Krótki przewodnik po AGSL

Narzędzie AGSL zostało zaprojektowane tak, aby było w dużej mierze zgodne z GLSL ES 1.0. Więcej informacji znajdziesz w opisie odpowiedniej funkcji w dokumentacji OpenGL ES Shading Language. Ta dokumentacja stara się w miarę możliwości wskazywać różnice między AGSL i GLSL.

Rodzaje

AGSL obsługuje typy GLSL ES 1.0 oraz dodatkowy sposób przedstawiania typów wektorów i macierzy. AGSL obsługuje dodatkowe typy short i half, co zapewnia średnią precyzję.

Rodzaje podstawowe

Typ Opis
void funkcja nie zwraca wartości lub pusta lista parametrów. W przeciwieństwie do GLSL funkcje bez typu zwróconego muszą zwracać wartość.
bool, bvec2, bvec3, bvec4
(bool2, bool3, bool4).
skalar/wektor logiczny
int, ivec2, ivec3, ivec4
(int2, int3, int4)
Liczba całkowita/wektor ze znakiem highp
float, vec2, vec3, vec4
(float2, float3, float4)
highp (pojedyncza precyzja) skalarnej/wektorowej zmiennoprzecinkowej liczby zmiennoprzecinkowej
short, short2, short3, short4 odpowiednik mediump int całkowitej ze znakiem/wektorem
half, half2, half3, half4 równoważny ze skalarem/wektorem mediump float
mat2, mat3, mat4
(float2x2, float3x3, float4x4)
Macierz 2 x 2, 3 x 3, 4 x 4 float
half2x2, half3x3, half4x4 Odpowiednik mediump float typu macierzy

Minimalne wartości precyzji i zakresu

To minimalna gwarantowana precyzja i zakres powiązane z każdym modyfikatorem na podstawie specyfikacji OpenGL ES 2.0. Większość urządzeń obsługuje ES 3.0, dlatego mają one bardziej gwarantowaną dokładność/zakres highp i int mediump. Modyfikatory precyzji można stosować do zmiennych i parametrów skalarnych, wektorowych i matrycowych. Gwarantowane są tylko wartości minimalne wymienione poniżej. Dokładność lowp nie musi być mniejsza niż precyzja działania mediump, a wskaźnik mediump niekoniecznie musi mieć mniejszą precyzję niż wartość highp. AGSL obecnie konwertuje lowp na mediump w ostatecznych danych wyjściowych.

Modyfikator zakres „zmiennoprzecinkowy” zakres wielkości „zmiennoprzecinkowej” precyzja „zmiennoprzecinkowa” zakres „int”
hazard \(\left\{-2^{62},2^{62}\right\}\) \(\left\{2^{-62},2^{62}\right\}\) Krewny: \(2^{-16}\) \(\left\{-2^{16},2^{16}\right\}\)
medium \(\left\{-2^{14},2^{14}\right\}\) \(\left\{2^{-14},2^{14}\right\}\) Krewny: \(2^{-10}\) \(\left\{-2^{10},2^{10}\right\}\)
niski poziom \(\left\{-2,2\right\}\) \(\left\{2^{-8},2\right\}\) Wartość bezwzględna: \(2^{-8}\) \(\left\{-2^{8},2^{8}\right\}\)

Oprócz tablicy w indeksie dolnym np.: var[num], names of vector components for vectors of length 2 - 4 are denoted by a single letter. Components can be swizzled and replicated. ex:vect.yx,vect.yy`

vect.xyzw – użyj w przypadku uzyskiwania dostępu do wektorów reprezentujących punkty/normalne

vect.rgba – użyj w przypadku uzyskiwania dostępu do wektorów reprezentujących kolory

vect.LTRB – użyj, gdy wektor przedstawia prostokąt (nie w GLSL).

W AGSL wartości 0 i 1 mogą zostać użyte do uzyskania w tym kanale stałej wartości 0 lub 1. Np. vect.rgb1 == vec4(vect.rgb,1)

Struktury i tablice

Struktury są zadeklarowane z tą samą składnią co w GLSL, ale AGSL obsługuje tylko struktury w zakresie globalnym.

struct type-name {
 members
} struct-name; // optional variable declaration.

Tylko tablice jednowymiarowe są obsługiwane z jawnym rozmiarem tablicy przy użyciu składni stylu C lub GLSL:

<typ bazy>[<rozmiar tablicy>] nazwa zmiennej, np. half[10] x;

nazwa zmiennej <typ podstawy>[<rozmiar tablicy>], np. half x[10];

Tablic nie można zwracać z funkcji – nie można ich kopiować, przypisywać ani porównywać. Ograniczenia dotyczące tablic są rozpowszechniane na struktury zawierające tablice. Tablice mogą być indeksowane tylko za pomocą zmiennej stałej lub pętli.

Eliminacje

Typ Opis
const stałej czasowej lub parametru funkcji tylko do odczytu.
uniform Wartość nie zmienia się w trakcie przetwarzania elementu podstawowego. Mundury są przekazywane z Androida przy użyciu metody RuntimeShader w przypadku setColorUniform, setFloatUniform, setIntUniform, setInputBuffer i setInputShader.
in Służy do obsługi parametrów funkcji przekazywanych. Jest to wartość domyślna.
out Służy do obsługi parametrów funkcji przekazywanej. Musi mieć taką samą precyzję jak definicja funkcji.
inout Dotyczy parametrów przekazywanych zarówno do funkcji, jak i z niej. Musi mieć taką samą precyzję jak definicja funkcji.

Deklaracja zmiennej

Deklaracje muszą być w jawnie ograniczonym zakresie. Deklaracja y w tym przykładzie jest niedozwolona:

if (condition)
    int y = 0;

Podstawowe informacje o macierzy, strukturze i tablicach

Przykłady konstruktora macierzy

Jeśli macierz składa się z 1 wartości, otrzymuje ją wszystkie wartości wzdłuż przekątnej, a w pozostałych przypadkach – zerami. float2x2(1.0) utworzą więc macierz tożsamości 2 x 2.

Jeśli macierz składa się z wielu wartości, kolumny są wypełniane w pierwszej kolejności (kolejność kolumn w dużej kolejności).

Pamiętaj, że w przeciwieństwie do GLSL konstruktory, które zmniejszają liczbę komponentów wektora przekazywanego, nie są obsługiwane, ale ten sam efekt można uzyskać, korzystając z przewijania. Aby utworzyć element vec3 z elementu vec4 w AGSL w taki sam sposób jak w GLSL, wpisz vec3 nv = quadVec.xyz.

Przykład konstruktora struktury

struct light { float intensity; float3 pos; };
// literal integer constants auto-converted to floating point
light lightVar = light(3, float3(1, 2, 3.0));

Komponenty macierzy

Dostęp do komponentów macierzy za pomocą składni dolnej tablicy.

float4x4 m; // represents a matrix
m[1] = float4(2.0); // sets second column to all 2.0
m[0][0] = 1.0; // sets upper left element to 1.0
m[2][3] = 2.0; // sets 4th element of 3rd column to 2.0

Struktura pól

Wybierz pola struktury, używając operatora kropki .. Dostępne operatory:

Operator Opis
. selektor pól
==, != równość
= przypisanie udziału w konwersji

Elementy tablicy

Dostęp do elementów tablicy uzyskuje się przy użyciu operatora tablicy indeksu w dolnej części tablicy [ ]. Na przykład:

diffuseColor += lightIntensity[3] * NdotL;

Operatorzy

Mają numery w kolejności obowiązywania zasad. Operatory relacyjne i równości > < <= >= == != mają wartość logiczną. Aby porównać wektory pod kątem komponentów, użyj funkcji takich jak lessThan(), equal() itp.

Operator Opis Powiązania
1 () grupowanie w nawiasach Nie dotyczy
2 [] () . ++ -- indeks dolny z wywołaniem funkcji i strukturą konstruktora selektora pola lub metody Od lewej do prawej
3 ++ -- + - ! zwiększanie i zmniejszanie prefiksu jednowarunkowego Od prawej do lewej
4 * / mnożenie i dzielenie Od lewej do prawej
5 + - dodaj i odejmij Od lewej do prawej
7 < > <= >= relacyjne Od lewej do prawej
8 == != równość/nierówność Od lewej do prawej
12 && logiczna ORAZ Od lewej do prawej
13 ^^ logiczny XOR Od lewej do prawej
14 || logiczna LUB Od lewej do prawej
15 ?\: (jeden cały operand) Od lewej do prawej
16 = += -= *= /= przypisanie arytmetyczne przypisanie arytmetyczne Od lewej do prawej
17 , sequence Od lewej do prawej

Operacje na macierzy i wektorach

W przypadku wartości skalarnych operatory arytmetyczne dają skalar. W przypadku operatorów innych niż modulo: jeśli jeden operand jest skalarem, a drugi jest wektorem lub macierzą, operacja jest wykonywana w sposób komponentowy i otrzymuje ten sam typ wektora lub macierzy. Jeśli obie operacje są wektorami tego samego rozmiaru, są one wykonywane komponentowo (i zwracają ten sam typ wektora).

Operacja Opis
m = f * m Mnożenie macierzy według komponentów przez wartość skalarną
v = f * v Mnożenie wektorów według składowych przez wartość skalarną
v = v * v Mnożenie wektorów według składowych przez wartość wektora
m = m + m Dodawanie komponentów macierzy
m = m - m Odejmowanie składowe macierzy
m = m * m Algebraiczny mnożenie liniowy

Jeśli 1 operand jest wektorem pasującym do rozmiaru wiersza lub kolumny naszej macierzy, można użyć operatora mnożenia do algebraicznego mnożenia wierszy i kolumn.

Operacja Opis
m = v * m Wektor wiersza * mnożenie algebraiczne macierzy
m = m * v Macierz * mnożenie przez wektor liniowy kolumny

Użyj funkcji wbudowanych do iloczynu skalarnego, iloczynu wektorowego oraz mnożenia na podstawie komponentów:

Funkcja Opis
f = dot(v, v) Iloczyn skalarny wektorowy
v = cross(v, v) Iloczyn wektorowy wektorów
m = matrixCompMult(m, m) Mnożenie według komponentu

Kontrola programu

Wywołanie funkcji Połączenia według wartości zwrotu
Iteracja for (<init>;<test>;<next>)
{ break, continue }
Zaznaczenie if ( ) { }
if ( ) { } else { }
switch () { break, case } – ostatnie zgłoszenie domyślne
Skok break, continue, return
(odrzucenie jest niedozwolone)
Wpis half4 main(float2 fragCoord)

Ograniczenia pętli

Podobnie jak w GLSL ES 1.0, pętle „for” są dość ograniczone. Kompilator musi mieć możliwość uruchomienia pętli. Oznacza to, że inicjator, warunek testowy i instrukcja next muszą używać stałych, aby można było obliczyć wszystko w czasie kompilacji. Instrukcja next jest dodatkowo ograniczona do używania ++, --, +=, or -=.

Funkcje wbudowane

GT (typ ogólny) to float, float2, float3, float4 lub half, half2, half3, half4.

Większość z tych funkcji działa komponentowo (jest stosowana do poszczególnych komponentów). Jeśli nie jest to konieczne, będzie na niej podane.

Kąt i funkcje trygonometryczne

Przyjmujemy, że parametry funkcji określone jako kąt są podane w radianach. W żadnym przypadku żadna z tych funkcji nie spowoduje podziału przez zero. Jeśli dzielnik współczynnika ma wartość 0, wyniki będą nieokreślone.

Funkcja Opis
GT radians(GT degrees) Konwertuje stopnie na radiany
GT degrees(GT radians) Konwertuje radiany na stopnie
GT sin(GT angle) Sinus standardowy
GT cos(GT angle) Cosinus standardowy
GT tan(GT angle) Tangens standardowy
GT asin(GT x) Zwraca kąt, którego sinus jest x w zakresie $ \left[-{\pi\over 2},{\pi\over 2}\right] $
GT acos(GT x) Zwraca kąt, którego cosinus jest wartością x w zakresie $ \left[0,\pi\right] $
GT atan(GT y, GT x) Zwraca kąt, którego arcus trygonometryczny to $ \left[{y\over x}\right] $ w zakresie $ \left[-\pi,\pi\right] $.
GT atan(GT y_over_x) Zwraca kąt, którego arcus trygonometryczny ma wartość y_over_x w zakresie $ \left[-{\pi\over 2},{\pi\over 2}\right] $

Funkcje wykładnicze

Funkcja Opis
GT pow(GT x, GT y) Zwraca $ x^y $
GT exp(GT x) Zwraca $ e^x $
GT log(GT x) Zwraca $ ln(x) $
GT exp2(GT x) Zwraca 2^x $
GT log2(GT x) Zwraca $ log_2(x) $
GT sqrt(GT x) Zwraca $ \sqrt{x} $
GT inversesqrt(GT x) Zwraca $ 1\over{\sqrt{x}} $

Typowe funkcje

Funkcja Opis
GT abs(GT x) Wartość bezwzględna
GT sign(GT x) Zwraca na podstawie znaku x wartość -1,0, 0,0 lub 1.0
GT floor(GT x) Najbliższa liczba całkowita <= x
GT ceil(GT x) Najbliższa liczba całkowita >= x
GT fract(GT x) Zwraca część ułamkową liczby x
GT mod(GT x, GT y) Zwraca wartość x modulo y
GT mod(GT x, float y) Zwraca wartość x modulo y
GT min(GT x, GT y) Zwraca minimalną wartość x lub y
GT min(GT x, float y) Zwraca minimalną wartość x lub y
GT max(GT x, GT y) Zwraca maksymalną wartość zmiennej x lub y
GT max(GT x, float y) Zwraca maksymalną wartość zmiennej x lub y
GT clamp(GT x, GT minVal, GT maxVal) Zwraca wartość x ograniczoną między wartością minVal i maxVal.
GT clamp(GT x, float minVal, float maxVal) Zwraca wartość x ograniczoną między wartością minVal i maxVal
GT saturate(GT x) Zwraca wartość x ograniczoną z zakresu od 0,0 do 1,0
GT mix(GT x, GT y GT a) Zwraca połączenie liniowe
GT mix(GT x, GT y, float a) Zwraca połączenie liniowe
GT step(GT edge, GT x) Zwraca 0,0, jeśli x < krawędź, a w przeciwnym razie – 1,0
GT step(float edge, GT x) Zwraca 0,0, jeśli x < krawędź, a w przeciwnym razie – 1,0
GT smoothstep(GT edge0, GT edge1, GT x) Wykonuje interpolację Hermite między 0 a 1, gdy krawędź0 < x < krawędź1
GT smoothstep(float edge0, float edge1, GT x) Wykonuje interpolację Hermite między 0 a 1, gdy krawędź0 < x < krawędź1

Funkcje geometryczne

Funkcje te działają na wektorach jako wektorach, a nie na elementach składowych. GT to liczba zmiennoprzecinkowa/wektory w rozmiarach 2–4.

Funkcja Opis
float/half length (GT x) Zwraca długość wektora
float/half distance(GT p0, GT p1) Zwraca odległość między punktami
float/half dot(GT x, GT y) Zwraca iloczyn skalarny
float3/half3 cross(float3/half3 x, float3/half3 y) Zwraca iloczyn wektorowy
GT normalize(GT x) Normalizuj wektor do długości 1
GT faceforward(GT N, GT I, GT Nref) Zwraca N, jeśli kropka(Nref; I) < 0, w przeciwnym razie –N.
GT reflect(GT I, GT N) Kierunek odbicia I – 2 * kropka(N,I) * N.
GT refract(GT I, GT N, float/half eta) Zwraca wektor załamania

Funkcje macierzy

Argument mata oznacza dowolny typ macierzy kwadratowej.

Funkcja Opis
mat matrixCompMult(mat x, mat y) Pomnóż komponent x przez y
mat inverse(mat m) Zwraca odwrotność m

Wektorowe funkcje relacyjne

Porównaj komponenty x i y. Rozmiary wektorów wejściowych i powrotnych dla danego wywołania muszą być takie same. T to suma typów wektorów liczb całkowitych i zmiennoprzecinkowych. BV to wektor logiczny, który odpowiada rozmiarowi wektorów wejściowych.

Funkcja Opis
BV lessThan(T x, T y) x < y
BV lessThanEqual(T x, T y) x <= y
BV greaterThan(T x, T y) x > y
BV greaterThanEqual(T x, T y) x >= y
BV equal(T x, T y) x == y
BV equal(BV x, BV y) x == y
BV notEqual(T x, T y) x != y
BV notEqual(BV x, BV y) x != y
bool any(BV x) true, jeśli którykolwiek z komponentów x jest wartością true
bool all(BV x) true, jeśli wszystkie składniki x są true.
BV not(BV x) logiczne uzupełnienie x

Funkcje związane z kolorami

Funkcja Opis
vec4 unpremul(vec4 color) Konwertuje wartość koloru na nieoznaczoną wstępnie liczbę alfa
half3 toLinearSrgb(half3 color) Przekształcenie przestrzeni kolorów na liniowy SRGB
half3 fromLinearSrgb(half3 color) Przekształcenie przestrzeni kolorów

Próbkowanie cienia (ocena)

Typy próbników nie są obsługiwane, ale możesz oceniać inne. Jeśli chcesz próbkować teksturę, możesz utworzyć obiekt BitmapShader i dodać go jako jednolity. Możesz to zrobić w przypadku dowolnego programu do cieniowania, co oznacza, że możesz bezpośrednio ocenić każdy obiekt Shader w Androidzie, nie przekształcając go najpierw w Bitmapę, w tym także z innymi obiektami RuntimeShader. Zapewnia to olbrzymią elastyczność, ale testy złożone mogą być kosztowne, zwłaszcza w pętli.

uniform shader image;

image.eval(coord).a   // The alpha channel from the evaluated image shader

Próbkowanie nieprzetworzonego bufora

Choć większość obrazów zawiera kolory, które powinny być zarządzane, niektóre zawierają dane, które w rzeczywistości nie są kolorami, w tym obrazy z wartościami normalnymi, właściwościami materiałowymi (np. chropowatość), mapy wysokości lub inne dane czysto matematyczne przechowywane w obrazach. Jeśli używasz tego rodzaju obrazów w AGSL, możesz użyć BitmapShadera jako ogólnego bufora nieprzetworzonego za pomocą RuntimeShader#setInputBuffer. Pozwoli to uniknąć przekształcania przestrzeni kolorów i filtrowania.