GLSL ES 2.0 の仕様について
独立した名前空間
Vertex と Fragment は連携して一つの表現を実現しますが、GPU 上では独立したアプリケーションとして動作します。名前空間(Namespace)も共有ではなく独立しています。別々のアプリケーションなので、組み込み変数にも Vertex 固有・Fragment 固有の組み込みがそれぞれ有ります。
varying 修飾子を用いた場合のみ、Vertex と Fragment で共通した変数名を用いて Vertex から Fragment へ値を渡すことができます。
主プログラム( CPU 側)から各シェーダへ値を渡す場合、attribute もしくは uniform 修飾子を利用します。
実行順
Vertex と Fragment には動かすことのできない優先実行順位があり、Vertex は必ず Fragment より先に実行されます。
変数宣言と関数定義で成り立つ
Vertex と Fragment 各シェーダは変数宣言と関数定義で成り立っています。include で外部ファイルを読み込むような仕様はありません。※
※ 拡張機能としてならば include は GLSL ES にも実装があるけど、GM:S ユーザには関係無い
各シェーダにはスタートアップとして引数も戻り値も無い main 関数が一つ必要。各シェーダは組み込み関数以外に独自定義関数を宣言して利用することができます。
varying 修飾子
Vertex から Fragment へ値を渡したい場合には varying 修飾子を用います。
実行順の縛りがあるため Vertex シェーダから Fragment シェーダへ値を渡す、一方通行なやり取りのみが可能。Vertex と Fragment で共通した変数名を使い、その変数に対して共通して varying 修飾子を用いれば、Fragment 側の varying 変数へ自動的に値が渡される仕組みです。
attribute、uniform、varying にはグローバルスコープが必要
attribute、uniform、varying は GLSL に固有のストレージ修飾子です。※
※ attribute と varying は GLSL ES 3.0 以降廃止された、GM:S は ES2.0 対応だから利用可能
各ストレージ修飾子は変数スコープにグローバルが必要。値はシェーダ内における定数、つまり読み取り専用となる。
中間バイトコードを出力しない
GLSL ES の仕様として、プリコンパイル済み中間バイトコードは出力しません。
アプリケーション起動時にテキストファイル(文字列)から専用バイナリへ毎回コンパイルされる仕様なので、処理が複雑なシェーダはコンパイルに時間がかかる=アプリケーション起動に毎回時間を要する場合があります。
GLSL ES にはコンパイラが複数ある
マイクロソフトの HLSL とは異なり、OpenGL ES はコンパイラが無数に有ります。特にモバイルで Android 端末はシェーダ動作の互換性は完全検証が困難、テスト環境で問題が無かった場合でも別機種では問題が発生する可能性を孕んでいます。
Switch Case は使えるのか
使えません。switch 文を使えばコンパイルは失敗します。
OpenGL 3.0 (GLSL version 1.30) 以降から switch case が実装されました。
GM:S の GLSL ES 実装は GLSL Version 1.20 ベース、switch 文はサポートされていません。
if else を使ってください。
データ型
シェーダ記述言語では GML と異なったデータ型を多数利用しています。
vec2/vec3/vec4 など GML で普段あまり見ない宣言はベクトル型、2/3/4 という数字はベクトルの要素数を表す。ベクトル型(vec型)に格納される数値は単精度浮動小数値(float)です。整数ベクトルの場合は ivec 宣言を、ブールベクトルには bvec 宣言をそれぞれ利用します。
INT 型
GLSL ES では数値の int 型はプログラムの補助として存在しますが、メモリ管理や処理速度向上のために int 型を利用する必要はありません。型が不一致のままでは計算に利用することができないので、int 型と float 型を混在させた場合、どちらかの数値にキャストが必要と成ります。
ハードウェアが得意な計算分野
GPU の並列処理が利用できるため、スカラー値よりもベクトル(あるいは行列)を用いた計算の方が処理速度的な恩恵に預かれます。
一般的には GPU のシェーダ機能を使った描画の方が処理速度は高速になります。
[divpage]