Różnice między AGSL a GLSL

Składnia AGSL i GLSL jest bardzo podobna, dzięki czemu można przenieść wiele efektów cieniowania fragmentów GLSL na Androida przy minimalnych zmianach. Firma AGSL poprawia funkcję GLSL z zestawu GLSL ES 1.0 (język cieniowania używany przez OpenGL ES 2.0), aby zapewnić maksymalny zasięg urządzeń.

Program do cieniowania fragmentów GLSL kontroluje całe działanie GPU między rastrem a sprzętem do mieszania. Program do cieniowania wykonuje całą pracę związaną z obliczaniem koloru, a wygenerowany przez niego kolor jest przesyłany na etap mieszania potoku. Pisząc cieniowanie w AGSL, tworzysz etap potoku grafiki Androida. Wiele różnic językowych wynika z tego.

Uruchamianie funkcji Shader

Podobnie jak w przypadku programu do cieniowania GLSL, program do cieniowania AGSL zaczyna wykonywanie kodu od funkcji głównej. W przeciwieństwie do GLSL funkcja przyjmuje pozycję cieniowania we współrzędnych „lokalnych” jako parametr. Działa to podobnie do funkcji gl_FragCoord, ale raczej niż w przypadku współrzędnych bufora ramki, współrzędne mogły zostać przetłumaczone przed wywołaniem funkcji cieniowania. cieniowanie zwraca kolor piksela jako vec4 o średniej lub wysokiej dokładności (podobny do out vec4 color lub gl_FragColor w GLSL).

mediump vec4 main(in vec2 fragCoord)

Obszar współrzędnych

Przestrzenie współrzędnych GLSL i AGSL

Kod cieniowania rysowany przy użyciu GLSL a prawie identyczny cieniowanie rysowane przy użyciu AGSL

W AGSL i GLSL domyślnie używane są różne przestrzenie współrzędnych. W GLSL współrzędna fragmentu (fragCoord) jest względem lewego dolnego rogu. AGSL odpowiada układowi współrzędnych ekranu obiektu Canvas, co oznacza, że oś Y zaczyna się od lewego górnego rogu. W razie potrzeby możesz przekształcić te 2 przestrzenie, przekazując rozdzielczość jako jednolitą i używając resolution.y - fragCoord.y jako wartości osi Y. Możesz też zastosować do cieniowania lokalną macierz przekształceń.

// AGSL to GLSL coordinate space transformation matrix
val localMatrix = Matrix()
localMatrix.postScale(1.0f, -1.0f)
localMatrix.postTranslate(0.0f, viewHeight)
gridShader.setLocalMatrix(localMatrix)

Precyzja i typy

Obsługiwane są modyfikatory precyzji zgodne z GLSL, ale w AGSL wprowadzone są typy half i short, które również zapewniają średnią precyzję.

Typy wektorów można zadeklarować jako <typ podstawy><kolumny>. Możesz użyć właściwości float2 zamiast vec2 i bool4 zamiast właściwości bvec4. Typy macierzy można zadeklarować jako <typ podstawy><kolumny>x<wiersze>, więc zamiast mat3 można zastosować typ float3x3. AGSL zezwala też na deklaracje w stylu GLSL dla elementów mat i vec. Te typy są zmapowane na ich odpowiedniki zmiennoprzecinkowe.

Procesor wstępny

AGSL nie obsługuje dyrektyw w stylu GLSL preprocessor. Przekonwertuj instrukcje #define na zmienne stałe. Kompilator AGSL obsługuje zmienne stałe i eliminację rozgałęzień, dzięki czemu są one wydajne.

Przestrzenie kolorów

Aplikacje na Androida są zarządzane za pomocą kolorów. Przestrzeń kolorów obszaru roboczego określa roboczą przestrzeń kolorów dla rysowania. Treści źródłowe (takie jak cieniowanie, w tym BitmapShader) też zawierają przestrzenie kolorów.

W przypadku niektórych efektów, np. precyzyjnego oświetlenia, obliczenia matematyczne należy przeprowadzać w liniowej przestrzeni kolorów. Aby Ci to ułatwić, AGSL udostępnia te funkcje:

half3 toLinearSrgb(half3 color)
half3 fromLinearSrgb(half3 color)

Zmieniają one kolory między działającą przestrzenią kolorów a przestrzeń barw LINEAR_EXTENDED_SRGB Androida. Przestrzeń ta korzysta z kolorów podstawowych sRGB (gamut) i funkcji przenoszenia liniowego. Reprezentuje wartości spoza gamy sRGB za pomocą rozszerzonych wartości zakresu (poniżej 0,0 i większych niż 1,0).

Uniformy

Ponieważ AGSL nie wie, czy uniformy zawierają kolory, nie stosuje w nich automatycznie konwersji kolorów. half4/float4/vec4 możesz oznaczyć etykietą layout(color). Dzięki temu Android będzie wiedzieć, że strój będzie używany jako kolor. To pozwoli Androidowi zmienić jednolitą wartość na roboczą przestrzeń kolorów.

W AGSL deklaruj mundur w ten sposób:

layout(color) uniform half4 iColor;  // Input color
uniform float2 iResolution;          // Viewport resolution (pixels)

W kodzie Androida możesz ustawić mundur w ten sposób:

shader.setColorUniform("iColor", Color.GREEN)
shader.setFloatUniform("iResolution", canvas.width.toFloat(), canvas.height.toFloat())