Krótki przewodnik po AGSL

AGSL jest w dużej mierze zgodny z GLSL ES 1.0. Więcej informacji znajdziesz w odpowiedniej funkcji w dokumentacji języka opisu obrazu OpenGL ES. W miarę możliwości staramy się w tej dokumentacji wskazywać różnice między AGSL a GLSL.

Typy

AGSL obsługuje typy GLSL ES 1.0 oraz dodatkowy sposób reprezentacji typów wektorów i macierzy. AGSL obsługuje dodatkowe typy shorthalf, aby reprezentować średnią precyzję.

Typy podstawowe

Typ Opis
void Brak wartości zwracanej przez funkcję lub pusta lista parametrów. W przeciwieństwie do GLSL, funkcje bez typu zwracania void muszą zwracać wartość.
bool, bvec2, bvec3, bvec4
(bool2, bool3, bool4).
Wartość logiczna skalarna/wektory
int, ivec2, ivec3, ivec4
(int2, int3, int4)
highp podpisana liczba całkowita/wektory
float, vec2, vec3, vec4
(float2, float3, float4)
highp (pojedyncza precyzja) zmiennoprzecinkowa wektorowa/skalarna
short, short2, short3, short4 odpowiada mediump int podpisanemu całkowitemu/wektorowi
half, half2, half3, half4 jest tożsame co mediump float skalar/wektor
mat2, mat3, mat4
(float2x2, float3x3, float4x4)
Matryca 2 x 2, 3 x 3 lub 4 x 4 float
half2x2, half3x3, half4x4 Odpowiednik typów macierzy mediump float

Minimalna dokładność i zakres

Są to minimalna gwarantowana dokładność i zakres powiązane z każdym modyfikatorem zgodnie ze specyfikacją OpenGL ES 2.0. Większość urządzeń obsługuje ES 3.0, więc mają one większą gwarantowaną dokładność i zakres highp oraz zakres int mediump. Modyfikatory dokładności można stosować do parametrów i zmiennych skalarnych, wektorowych oraz macierzy. Gwarantowane są tylko minimalne wartości wymienione poniżej. lowp nie musi mieć niższej dokładności niż mediump, a mediump nie musi mieć niższej dokładności niż highp. Obecnie AGSL konwertuje lowp na mediump w końcowym wyjściu.

Modyfikator Zakres „float” Zakres wielkości „float” Dokładność „float” Zakres „int”
highp \(\left\{-2^{62},2^{62}\right\}\) \(\left\{2^{-62},2^{62}\right\}\) Względne: \(2^{-16}\) \(\left\{-2^{16},2^{16}\right\}\)
mediump \(\left\{-2^{14},2^{14}\right\}\) \(\left\{2^{-14},2^{14}\right\}\) Względne: \(2^{-10}\) \(\left\{-2^{10},2^{10}\right\}\)
lowp \(\left\{-2,2\right\}\) \(\left\{2^{-8},2\right\}\) Bezwzględne: \(2^{-8}\) \(\left\{-2^{8},2^{8}\right\}\)

Oprócz składni indeksu numerycznego tablicy, 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żywaj, gdy odczytuje się wektory, które reprezentują punkty lub normalne.

vect.rgba – używaj, gdy uzyskujesz dostęp do wektorów, które reprezentują kolory.

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

W AGSL wartości 0 i 1 mogą być używane do generowania stałych wartości 0 lub 1 na danym kanale. Przykład: vect.rgb1 == vec4(vect.rgb,1)

Struktury i tablice

Struktury są deklarowane za pomocą tej samej składni co w GLSL, ale AGSL obsługuje tylko struktury o zakresie globalnym.

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

Obsługiwane są tylko tablice jednowymiarowe z wyraźnym rozmiarem, zdefiniowanym za pomocą składni C lub GLSL:

<base type>[<array size>] nazwa zmiennej – np. half[10] x;

<base type> nazwa zmiennej[<rozmiar tablicy>] – np. half x[10];

Tablic nie można zwracać z funkcji, kopiować, przypisywać ani porównywać. Ograniczenia tablic są rozpowszechniane na struktury zawierające tablice. Indeksowanie tablic jest możliwe tylko za pomocą stałej lub zmiennej pętli.

Eliminacje

Typ Opis
const Stałe wartościowe w czasie kompilacji lub parametry funkcji tylko do odczytu.
uniform Wartość nie zmienia się w przypadku przetwarzanego typu pierwotnego. Uniformy są przekazywane z Androida za pomocą metod RuntimeShader dla setColorUniform, setFloatUniform, setIntUniform, setInputBuffersetInputShader.
in Parametry funkcji przekazywane do funkcji. To jest ustawienie domyślne.
out Parametry funkcji z wynikiem. Musi mieć taką samą dokładność jak definicja funkcji.
inout Parametry, które są przekazywane do funkcji i z niej. Musi być używana z tą samą dokładnością co definicja funkcji.

Deklaracja zmiennej

Deklaracje muszą być w wyraźnym zakresie nawiasów. Deklaracja y w tym przykładzie jest niedozwolona:

if (condition)
    int y = 0;

Podstawy dotyczące macierzy, struktur i tablic

Przykłady konstruktora macierzy

Gdy macierz jest tworzona z jedną wartością, wszystkie wartości na przekątnej mają tę wartość, a pozostałe są równe 0. float2x2(1.0) utworzy więc macierz tożsamości 2 x 2.

Gdy tworzona jest matryca z wieloma wartościami, najpierw wypełniane są kolumny (kolejność kolumn).

Pamiętaj, że w odróżnieniu od GLSL konstruktory, które zmniejszają liczbę komponentów przekazywanego wektora, nie są obsługiwane, ale możesz użyć swizlowania, aby uzyskać ten sam efekt. Aby utworzyć vec3vec4 w AGSL z tym samym działaniem jak w GLSL, określ 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));

Elementy macierzy

Dostęp do elementów macierzy za pomocą składnika tablicowego.

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

Pola struktury

Wybierz pola struktury za pomocą operatora kropka .. Operatory:

Operator Opis
. selektor pól
==, != równość
= projekt

Elementy tablicy

Do elementów tablicy uzyskuje się dostęp za pomocą operatora indeksowania tablicy [ ]. Przykład:

diffuseColor += lightIntensity[3] * NdotL;

Operatorzy

Numerowane według kolejności ważności. Operatory relacji i równości > < <= >= == != zwracają wartość logiczną. Aby porównać wektory poszczególnymi składowymi, użyj funkcji takich jak lessThan(), equal() itp.

Operator Opis Związek
1 () grupowanie w nawiasach Nie dotyczy
2 [] () . ++ -- indeks tablicy, wywołanie funkcji i struktura konstruktora, selektor pola lub metody, zamiana, postfiks zwiększania i zmniejszania Od lewej do prawej
3 ++ -- + - ! prefiks zwiększania i zmniejszania unary Od prawej do lewej
4 * / mnożenie i dzielenie Od lewej do prawej
5 + - dodawanie i odejmowanie, Od lewej do prawej
7 < > <= >= relacyjny Od lewej do prawej
8 == != równość/nierówność Od lewej do prawej
12 && operator logiczny AND Od lewej do prawej
13 ^^ operator logiczny XOR Od lewej do prawej
14 || operator logiczny LUB Od lewej do prawej
15 ?\: selection (jeden cały operand) Od lewej do prawej
16 = += -= *= /= assignment arithmetic assignment arithmetic assignment Od lewej do prawej
17 , sequence Od lewej do prawej

Operacje na macierzach i wektorach

Po zastosowaniu do wartości skalarnych operatory arytmetyczne dają wynik skalarny. W przypadku operatorów innych niż modulo, jeśli jeden operand jest skalarem, a drugi wektorem lub macierzą, operacja jest wykonywana komponentowo i daje ten sam typ wektora lub macierzy. Jeśli obie operacje są wektorami o tym samym rozmiarze, operacja jest wykonywana komponentowo (i zwraca ten sam typ wektora).

Operacja Opis
m = f * m Mnożenie macierzy element po elemencie przez wartość skalarną
v = f * v Mnożenie wektora element po elemencie przez wartość skalarną
v = v * v Pomnażanie wektora element po elemencie przez wartość wektorową
m = m + m Dodawanie elementów macierzy
m = m - m Odejmowanie elementów macierzy
m = m * m Prosta mnożnia algebraiczna

Jeśli jeden operand jest wektorem pasującym do rozmiaru wiersza lub kolumny naszej macierzy, operator mnożenia może służyć do algebraicznego mnożenia wierszy i kolumn.

Operacja Opis
m = v * m Wektor wiersza * macierz liniowa algebraiczna mnożenie
m = m * v Macierz * wektor kolumnowy – mnożenie liniowo-algebraiczne

Użyj wbudowanych funkcji do iloczynu skalarnego, iloczynu wektorowego i iloczynu komponentowego:

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

Kontrola programu

Wywołanie funkcji Wywołanie funkcji z wartością zwracaną
Iteracja for (<init>;<test>;<next>)
{ break, continue }
Zaznaczenie if ( ) { }
if ( ) { } else { }
switch () { break, case }- domyślnie ostatnia litera
Przejdź break, continue, return
(odrzucenie nie jest dozwolone)
Wpis half4 main(float2 fragCoord)

Ograniczenia pętli for

Podobnie jak w GLSL ES 1.0, pętle „for” są dość ograniczone; kompilator musi mieć możliwość rozwinięcia pętli. Oznacza to, że inicjalizator, warunek testu i instrukcja next muszą używać stałych, aby wszystko można było obliczyć w czasie kompilacji. Oświadczenie next jest dodatkowo ograniczone do użycia ++, --, +=, or -=.

Wbudowane funkcje

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

Większość z nich działa na poziomie komponentu (funkcja jest stosowana osobno do każdego komponentu). W przeciwnym razie jest to zaznaczone.

Kąty i funkcje trygonometryczne

Parametry funkcji podane jako kąt są uznawane za kąt w radianach. Żadna z tych funkcji nie spowoduje błędu dzielenia przez 0. Jeśli dzielnik proporcji ma wartość 0, wyniki nie będą określone.

Funkcja Opis
GT radians(GT degrees) konwertuje stopnie na radiany,
GT degrees(GT radians) Przekształca radiany na stopnie
GT sin(GT angle) Standardowy sinus
GT cos(GT angle) Standardowy cosinus
GT tan(GT angle) Standardowa wartość dotykowa
GT asin(GT x) Zwraca kąt, którego sinus jest równy x w zakresie $ \left[-{\pi\over 2},{\pi\over 2}\right] $
GT acos(GT x) Zwraca kąt, którego cosinus jest równy x, w zakresie $ \left[0,\pi\right] $.
GT atan(GT y, GT x) Zwraca kąt, którego trójkątny arcus tangens jest równy $ \left[{y\over x}\right] $ w zakresie $ \left[-\pi,\pi\right] $
GT atan(GT y_over_x) Zwraca kąt, którego arctangens trygonometryczny jest równy 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 wartość 2^x $
GT log2(GT x) zwraca wartość $ log_2(x) $
GT sqrt(GT x) Zwraca $ \sqrt{x} $
GT inversesqrt(GT x) Zwraca wartość $ 1\over{\sqrt{x}} $

Funkcje wspólne

Funkcja Opis
GT abs(GT x) Wartość bezwzględna
GT sign(GT x) Zwraca -1.0, 0.0 lub 1.0 w zależności od znaku x.
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ść x lub y
GT max(GT x, float y) Zwraca maksymalną wartość x lub y
GT clamp(GT x, GT minVal, GT maxVal) Zwraca wartość x ograniczoną do zakresu od minVal do maxVal.
GT clamp(GT x, float minVal, float maxVal) Zwraca wartość x ściśnioną między minVal i maxVal
GT saturate(GT x) Zwraca wartość x ściśniętą w zakresie od 0,0 do 1,0
GT mix(GT x, GT y, GT a) Zwraca mieszankę liniową x i y.
GT mix(GT x, GT y, float a) Zwraca mieszankę liniową x i y.
GT step(GT edge, GT x) Zwraca 0,0, jeśli x < edge, w przeciwnym razie zwraca 1,0.
GT step(float edge, GT x) Zwraca 0,0, jeśli x < edge, w przeciwnym razie 1,0.
GT smoothstep(GT edge0, GT edge1, GT x) Przeprowadza interpolację Hermite'a w zakresie od 0 do 1, gdy edge0 < x < edge1
GT smoothstep(float edge0, float edge1, GT x) Przeprowadza interpolację Hermite'a w zakresie od 0 do 1, gdy edge0 < x < edge1

Funkcje geometryczne

Te funkcje działają na wektorach jako wektory, a nie na ich komponentach. GT to wektory typu float/half o 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) Normalizacja wektora do długości 1
GT faceforward(GT N, GT I, GT Nref) Zwraca N, jeśli dot(Nref, I) < 0, w przeciwnym razie zwraca –N.
GT reflect(GT I, GT N) Kierunek odbicia I = 2 * dot(N,I) * N.
GT refract(GT I, GT N, float/half eta) Zwraca wektor załamania promieniowania.

Funkcje macierzy

Typ mat to dowolny kwadratowy typ macierzy.

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

Funkcje wektorowe

Porównaj komponenty x i y. Rozmiary wektora wejściowego i zwrotnego w przypadku danego wywołania muszą być takie same. T jest iloczykiem wektorów typu liczba całkowita i liczba zmiennoprzecinkowa. BV to wektor logiczny o rozmiarze odpowiadającym wektorom wejściowym.

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 dowolny składnik x jest true
bool all(BV x) true, jeśli wszystkie składniki x są true.
BV not(BV x) uzupełnienie logiczne x

Funkcje kolorów

Funkcja Opis
vec4 unpremul(vec4 color) Konwertuje wartość koloru na nieskalibrowaną wartość alfa.
half3 toLinearSrgb(half3 color) Przekształcenie przestrzeni kolorów na liniową sRGB
half3 fromLinearSrgb(half3 color) Przekształcanie przestrzeni kolorów

Próbkowanie shaderów (ocena)

Typy próbkowania nie są obsługiwane, ale możesz oceniać inne shadery. Jeśli chcesz pobrać próbkę tekstury, możesz utworzyć obiekt BitmapShader i dodać go jako uniform. Możesz to zrobić w przypadku dowolnego shadera, co oznacza, że możesz bezpośrednio ocenić dowolny shader Androida bez wcześniejszego przekształcania go w Bitmap, w tym inne obiekty RuntimeShader. Daje to ogromną elastyczność, ale złożone shadery mogą być kosztowne w przetwarzaniu, zwłaszcza w pętli.

uniform shader image;

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

Próbkowanie bufora surowego

Chociaż większość obrazów zawiera kolory, które powinny być poddane zarządzaniu kolorami, niektóre obrazy zawierają dane, które nie są kolorami, w tym obrazy przechowujące normalne, właściwości materiału (np. chropowatość), mapy wysokości lub inne dane czysto matematyczne, które są przechowywane w obrazie. Gdy używasz tego typu obrazów w AGSL, możesz użyć BitmapShader jako ogólnego bufora nieprzetworzonego, używając RuntimeShader#setInputBuffer. Dzięki temu unikniesz przekształcania i filtrowania przestrzeni barw.