AGSL dan GLSL sangat mirip dalam sintaksis, memungkinkan banyak efek shader fragmen GLSL dibawa ke Android dengan perubahan minimal. AGSL memperbaiki kumpulan fitur GLSL-nya pada GLSL ES 1.0 (bahasa shading yang digunakan oleh OpenGL ES 2.0) untuk menyediakan jangkauan perangkat maksimum.
Shader fragmen GLSL mengontrol seluruh perilaku GPU antara rasterizer dan hardware pencampuran. Shader tersebut melakukan semua tugas untuk menghitung warna, dan warna yang dihasilkannya akan diberikan ke tahap pencampuran pipeline. Saat menulis shader di AGSL, Anda memprogram tahap pipeline grafis Android. Terdapat banyak perbedaan bahasa yang disebabkan oleh hal ini.
Eksekusi shader
Sama seperti di shader GLSL, shader AGSL memulai eksekusi dalam fungsi utama.
Tidak seperti GLSL, fungsi ini menggunakan posisi shader dalam koordinat "lokal" sebagai
parameter. Ini mirip dengan gl_FragCoord
, tetapi bukan koordinat framebuffer, koordinat ini mungkin telah diterjemahkan sebelum memanggil shader Anda. Shader Anda kemudian menampilkan warna piksel sebagai vec4
dalam presisi sedang atau tinggi (mirip dengan out vec4 color
atau gl_FragColor
di GLSL).
mediump vec4 main(in vec2 fragCoord)
Ruang koordinat
Shader digambar menggunakan GLSL vs Shader identik dekat yang digambar menggunakan AGSL
AGSL dan GLSL menggunakan ruang koordinat yang berbeda secara default. Dalam GLSL, koordinat
fragmen (fragCoord) relatif terhadap kiri bawah. AGSL cocok dengan sistem koordinat
layar Canvas,
yang berarti sumbu Y dimulai dari sudut kiri atas. Jika perlu, Anda
dapat melakukan konversi antara dua ruang ini dengan meneruskan resolusi sebagai seragam
dan menggunakan resolution.y - fragCoord.y
untuk nilai sumbu Y. Atau, Anda
dapat menerapkan matriks transformasi lokal ke shader.
// AGSL to GLSL coordinate space transformation matrix
val localMatrix = Matrix()
localMatrix.postScale(1.0f, -1.0f)
localMatrix.postTranslate(0.0f, viewHeight)
gridShader.setLocalMatrix(localMatrix)
Presisi dan jenis
Pengubah presisi yang kompatibel dengan GLSL didukung, tetapi AGSL memperkenalkan
jenis half
dan short
yang juga mewakili presisi sedang.
Jenis vektor dapat dideklarasikan sebagai bernama <base type><columns>. Anda dapat menggunakan
float2
, bukan vec2
dan bool4
, bukan bvec4
.
Jenis matriks dapat dideklarasikan sebagai bernama <base type><columns>x<rows>, sehingga float3x3
, bukan mat3
. AGSL juga mengizinkan deklarasi gaya GLSL untuk mat
dan vec
, dan jenis ini dipetakan ke float yang setara.
Praprosesor
AGSL tidak mendukung perintah preprocessor gaya GLSL. Mengonversi pernyataan #define menjadi variabel konstanta. Compiler AGSL mendukung folding konstan dan eliminasi cabang untuk variabel const, sehingga ini akan efisien.
Ruang warna
Aplikasi Android dikelola oleh warna. Ruang warna {i>Canvas<i} menentukan ruang warna kerja untuk menggambar. Konten sumber (seperti shader, termasuk BitmapShader) juga memiliki ruang warna.
Untuk efek tertentu, seperti pencahayaan yang akurat secara fisik, matematika harus dilakukan dalam ruang warna linear. Untuk membantu melakukan hal ini, AGSL menyediakan fungsi intrinsik berikut:
half3 toLinearSrgb(half3 color)
half3 fromLinearSrgb(half3 color)
Keduanya mengonversi warna antara ruang warna yang berfungsi dan ruang warna
LINEAR_EXTENDED_SRGB
Android. Ruang tersebut menggunakan warna primer (gamut) sRGB dan fungsi transfer linear. Parameter ini mewakili nilai di luar gamut sRGB menggunakan nilai rentang yang diperluas (di bawah 0.0 dan di atas 1.0).
Seragam
Karena AGSL tidak tahu apakah seragam berisi warna, seragam tersebut tidak akan otomatis menerapkan
konversi warna. Anda dapat melabeli half4
/float4
/vec4
dengan
layout(color)
, yang memungkinkan Android mengetahui bahwa seragam akan digunakan sebagai
warna, yang memungkinkan Android mengubah nilai seragam ke ruang warna
yang berfungsi.
Di AGSL, deklarasikan seragam seperti ini:
layout(color) uniform half4 iColor; // Input color
uniform float2 iResolution; // Viewport resolution (pixels)
Dalam kode Android, Anda kemudian dapat menyetel seragam seperti ini:
shader.setColorUniform("iColor", Color.GREEN)
shader.setFloatUniform("iResolution", canvas.width.toFloat(), canvas.height.toFloat())