AGSL と GLSL は構文が非常に似ているため、多くの GLSL フラグメント シェーダー効果を、最小限の変更で Android に移植できます。AGSL は、GLSL 機能セットを GLSL ES 1.0(OpenGL ES 2.0 で使用されるシェーディング言語)に修正し、デバイスのリーチを最大化します。
GLSL フラグメント シェーダーは、ラスタライザとブレンディング ハードウェアの間の GPU の動作全体を制御します。このシェーダーは、色を計算するためのすべての処理を行い、生成された色がパイプラインのブレンディング ステージにフィードされます。AGSL でシェーダーを記述することは、Android グラフィック パイプラインのステージをプログラミングすることに相当します。言語の違いの多くは、この点に起因しています。
シェーダーの実行
GLSL シェーダーと同様に、AGSL シェーダーは main 関数で実行を開始します。GLSL とは異なり、この関数は「ローカル」座標でのシェーダーの位置をパラメータとして受け取ります。これは gl_FragCoord
に似ていますが、フレームバッファの座標ではなく、シェーダーを呼び出す前にこれらの座標が変換されている可能性があります。その後、シェーダーはピクセル色を中精度または高精度の vec4
として返します(GLSL の out vec4 color
や gl_FragColor
と同様)。
mediump vec4 main(in vec2 fragCoord)
座標空間
GLSL を使用して描画されるシェーダーと、AGSL を使用して描画されるほぼ同一のシェーダー
AGSL と GLSL は、デフォルトでは異なる座標空間を使用します。GLSL では、フラグメントの座標(fragCoord)は左下を基準とします。AGSL は Canvas の画面座標系と一致します。つまり、Y 軸は左上隅から始まります。必要に応じて、解像度を unform として渡し、Y 軸の値として resolution.y - fragCoord.y
を使用することで、この 2 つの空間間の変換を行うことができます。また、ローカル変換行列をシェーダーに適用することもできます。
// AGSL to GLSL coordinate space transformation matrix
val localMatrix = Matrix()
localMatrix.postScale(1.0f, -1.0f)
localMatrix.postTranslate(0.0f, viewHeight)
gridShader.setLocalMatrix(localMatrix)
適合率と種類
GLSL 互換の精度修飾子がサポートされていますが、AGSL では、中程度の精度を表す half
型と short
型も導入されています。
ベクター型は <基本型><columns> という名前で宣言できます。vec2
の代わりに float2
を、bvec4
の代わりに bool4
を使用できます。行列型は <基本型><列>x<行> という名前で宣言できるため、mat3
ではなく float3x3
です。AGSL では、mat
と vec
の GLSL スタイルの宣言も許可されています。これらの型は対応する浮動小数点数にマッピングされます。
プリプロセッサ
AGSL は、GLSL スタイルのプリプロセッサ ディレクティブをサポートしていません。#define ステートメントを定数変数に変換します。AGSL のコンパイラは、定数変数の定数フォールディングと分岐除去をサポートしているため、これらが効率的です。
色空間
Android のアプリは色で管理されます。キャンバスの色空間は、描画の作業用色空間を決定します。ソース コンテンツ(BitmapShader などのシェーダーなど)にも色空間があります。
物理的に正確なライティングなどの特定の効果については、線形色空間で計算する必要があります。そのために、AGSL には次の組み込み関数が用意されています。
half3 toLinearSrgb(half3 color)
half3 fromLinearSrgb(half3 color)
これらは、作業色空間と Android の LINEAR_EXTENDED_SRGB
色空間の間で色を変換します。この空間では、sRGB 色域と線形伝達関数が使用されます。拡張範囲値(0.0 未満および 1.0 超)を使用して sRGB 色域外の値を表現します。
ユニフォーム
AGSL では、ユニフォームに色が含まれているかどうかわからないため、色変換が自動的に適用されません。half4
/float4
/vec4
に layout(color)
というラベルを付けます。これにより、制服が色に使用されることを Android が認識し、その均一な値を作業用の色空間に変換できます。
AGSL では、ユニフォームを次のように宣言します。
layout(color) uniform half4 iColor; // Input color
uniform float2 iResolution; // Viewport resolution (pixels)
Android のコードでは、次のようにユニフォームを設定できます。
shader.setColorUniform("iColor", Color.GREEN)
shader.setFloatUniform("iResolution", canvas.width.toFloat(), canvas.height.toFloat())