AGSL 和 GLSL 在語法中非常類似,可讓許多 GLSL 片段著色器影響,僅須進行極少的變更即可提供給 Android。AGSL 修正了 GLSL ES 1.0 (OpenGL ES 2.0 使用的陰影語言) 的 GLSL 功能集,盡可能擴大裝置觸及範圍。
GLSL 片段著色器可控制 GPU 在光柵器和混合硬體之間的整體行為。這個著色器會執行所有工作來計算顏色,而產生的顏色正好提供給管道的混合階段。當您在 AGSL 中編寫著色器時,您會編寫 Android 圖形管道的階段。這也有許多語言差異來自這點。
著色器執行作業
就像 GLSL 著色器一樣,AGSL 著色器會在主要函式中開始執行。
與 GLSL 不同,函式會使用「本機」座標中的著色器位置做為參數。這與 gl_FragCoord
類似,但而不是 framebuffer 座標,這些座標在呼叫著色器之前可能已轉譯。接著,著色器會以中等或高精確度的 vec4
的形式傳回像素顏色 (與 GLSL 中的 out vec4 color
或 gl_FragColor
)。
mediump vec4 main(in vec2 fragCoord)
座標空間
使用 GLSL 繪製著色器和使用 AGSL 繪製的相似著色器
根據預設,AGSL 和 GLSL 使用不同的座標空間。在 GLSL 中,片段座標 (fragCoord) 是相對於左下方的值。AGSL 與 Canvas 的螢幕座標系統相符,也就是說,Y 軸從左上角開始。如有需要,您可以藉由以統一的形式傳入解析度,並針對 Y 軸值使用 resolution.y - fragCoord.y
,藉此在這兩個空間之間轉換。或者,您也可以將本機轉換矩陣套用至著色器。
// 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
類型,同樣代表中精確度。
向量類型可以宣告為名為 <base type><columns>。您可以使用 float2
取代 vec2
和 bool4
,而不使用 bvec4
。矩陣類型可宣告為已命名的 <base type><columns>x<rows>,因此 float3x3
而非 mat3
。AGSL 也允許 mat
和 vec
的 GLSL 樣式宣告,這些類型會對應至相應的浮點等項目。
預先處理器
AGSL 不支援 GLSL 樣式的預先處理器指令。將 #define 陳述式轉換為 Const 變數。AGSL 的編譯器支援常數變數的常數折疊和分支消除作業,因此能夠提高效率。
色域
Android 應用程式會以顏色管理。Canvas 的色域會決定繪圖的工作色空間。來源內容 (例如著色器,包括 BitmapShader) 也具有色域。
對於特定效果 (例如實際亮度) 而言,數學應在線性色域中完成。為協助解決這個問題,AGSL 提供下列內建函式:
half3 toLinearSrgb(half3 color)
half3 fromLinearSrgb(half3 color)
這些顏色會轉換工作色域和 Android 的 LINEAR_EXTENDED_SRGB
色域。該空間使用 sRGB 原色 (色調) 和線性傳輸函式。這會使用延伸範圍值 (低於 0.0 和 1.0 以上) 表示 sRGB 色域以外的值。
制服
由於 AGSL 不知道製服是否包含顏色,因此不會自動為它們套用顏色轉換。您可以使用 layout(color)
為 half4
/float4
/vec4
加上標籤,讓 Android 瞭解系統會將統一值當做顏色使用,以便 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())