Beépített változók és konstansok
A shaderek-nek kommunikálnia kell az OpenGL csővezeték nem programozható részeivel és más shaderek-kel is. A nyelv beépítetten rengeteg változót kínál, amelyekkel bejövő adatokat lehet fogadni vagy kimenő adatokat lehet küldeni.
Minden shader típusban más beépített változók használhatóak. Néhány példa:
in int gl_VertexID;
in vec4 gl_FragCoord;
in vec4 gl_Color;
out gl_PerVertex {
vec4 gl_Position;
float gl_PointSize;
float gl_ClipDistance[];
};
A nyelv több beépített konstanst is tartalmaz, amelyek bármely shaderben használhatóak. A konstansok értékei implementáció függőek, de értékük legalább annyi, mint a meghatározott érték. Néhány példa:
const int gl_MaxVertexAttribs = 16;
const int gl_MaxVertexOutputComponents = 64;
const int gl_MaxViewports = 16;
További beépített változók és konstansok leírása a nyelv specifikációjában található: GLSL 4.2 specifikáció
Beépített függvények
A nyelvben számos beépített függvény szerepel különböző műveletekhez. Legtöbbjük több típusú shader-ben is használható, de vannak olyanok is, amelyek csak egy adott shader-ben használhatóak.
A beépített függvények három fő csoportba tartoznak:
- Valamilyen hardver funkcionalitást fejeznek ki. Például egy textúra elérése. Ezek nem írhatók meg shader-ben.
- Egyszerű műveletek, amelyeket a felhasználó is megírhatna, de nagyon gyakori használatuk és a hardver közvetlenül támogatja. Például: clamp(), mix().
- Olyan műveletek, amelyek végrehajtását a hardver bizonyos helyeken gyorsítani tudja. Például trigonometrikus függvények.
Az alkalmazásokban ajánlott használni a beépített függvényeket a saját függvények helyett, mivel optimalizáltak. A beépített függvények újradeklarálhatóak ugyanazzal a névvel és argumentumlistával. Néhány példa:
float radians (float degrees); // fokot radiánba vált
float sin (float angle); // egy szög sin-a
float pow (float x, float y); // x hatványozása az y kitevőre
float abs (float x); // x abszolútértékét adja vissza
vec3 normalize (vec3 x); // x normál vektorát adja vissza
mat2 inverse (mat2 m); // m inverzét adja vissza
Az alábbi függvények deklarációjában a genType float, vec2, vec3, vagy vec4 típusnak felel meg. genIType az egész értékű változatot, genUType az előjel nélkülit, genBType a bool, genDType pedig a double változatokat jelöli.s
Szög és trigonometriai függvények
Ahol a függvény egy szöget vár paramétereként azt radiánban kell megadni. Semmilyen esetben sem történik 0-val való osztás esetén hiba, ezesetben az eredmény nem definiált.
genType radians (genType degrees) // a megadott fokot radiánban adja vissza
genType degrees (genType radians) // a megadott radián értéket fokban adja vissza
genType sin (genType angle) // az általános szinusz függvény
genType cos (genType angle) // az általános koszinusz függvény
genType tan (genType angle) // az általános tangens függvény
genType asin (genType x) // az általános arkusz szinusz függvény
// visszadja azt a szöget amelynek a szinusza
// az eredmény nem definiált |x| > 1 esetén
genType acos (genType x) // az általános arkusz koszinusz függvény
// visszadja azt a szöget amelynek a koszinusza x
// az eredmény nem definiált |x| > 1 esetén
genType atan (genType y, genType x) // az általános arkusz tangens függvény
// visszadja azt a szöget amelynek a tangense x/y
// az eredmény nem definiált ha x és y is 0
genType atan (genType a) // visszadja azt a szöget amelynek a tangense a
genType sinh (genType x) // az általános hiperbolikus szinusz függvény
genType cosh (genType x) // az általános hiperbolikus koszinusz függvény
genType tanh (genType x) // az általános hiperbolikus tangens függvény
genType asinh (genType x) // a sinh inverze
genType acosh (genType x) // a cosh inverze, nem definiált x < 1-re
genType atanh (genType x) // a tanh inverze, nem definiált |x| > 1-re
Exponenciális függvények
genType pow (genType x, genType y) // visszadja x-nek az y-adik hatványát
// nem definiált x < 0 vagy x = 0 és y <= 0 esetekben
genType exp (genType x) // visszadja az e szám x-edik hatványát
genType log (genType x) // visszadja x természetes alapú logaritmusát,
// x <= 0 esetben nem definiált
genType exp2 (genType x) // 2 x-edik hatványat adja vissza
genType log2 (genType x) // x-nek a 2-es alapú logaritmusát adja vissza,
// x <= 0 esetben nem definiált
genType sqrt (genType x) // x négyzetgyökét adja vissza, x < 0 esetben nem definiált
genDType sqrt (genDType x)
genType inversesqrt (genType x) // x inverz négyzetgyökét adja vissza,
// x <= 0 esetben nem definiált
genDType inversesqrt (genDType x)
Általános függvények
// x abszolútértékét adja vissza
genType abs (genType x)
genIType abs (genIType x)
genDType abs (genDType x)
// x előjelét adja vissza, értéke 1.0, ha x pozitív,
// 0.0 ha x 0, -1.0 ha x negatív
genType sign (genType x)
genIType sign (genIType x)
genDType sign (genDType x)
// x-nek az egészértékét adja vissza
genType floor (genType x)
genDType floor (genDType x)
// x abszolútértékéhez tartozó legközelebbi egész szám abszolút értékét adja vissza
genType trunc (genType x)
genDType trunc (genDType x)
// x egeszre való kerekítését adja vissza
genType round (genType x)
genDType round (genDType x)
// x paráos egészre való kerekétését adja vissza
// pl. 3.5 és 4.5 bemenetre 4.0 lesz az eredmény
genType roundEven (genType x)
genDType roundEven (genDType x)
// a legközelebbi x-nél nagyobb egész számot adja vissza
genType ceil (genType x)
genDType ceil (genDType x)
// x – floor (x)
genType fract (genType x)
genDType fract (genDType x)
// modulus, x – y * floor (x/y)
genType mod (genType x, float y)
genType mod (genType x, genType y)
genDType mod (genDType x, double y)
genDType mod (genDType x, genDType y)
// mint a mod, csak i kimeneti paraméter a egész értékű osztás eredménye lesz
genType modf (genType x, out genType i)
genDType modf (genDType x, out genDType i)
// x és y közül a kisebb lesz az eredménye
genType min (genType x, genType y)
// x és y közül a nagyobb lesz az eredménye
genType max (genType x, genType y)
// min (max (x, minVal), maxVal)
genType clamp (genType x, genType minVal, genType maxVal)
// x*(1−a)+y*a
genType mix (genType x, genType y, genType a)
// 0.0, ha x < edge, különben 1.0
genType step (genType edge, genType x)
// 0.0, ha x <= edge0 és 1.0 ha x >= edge1
// edge0 < x < edge1 esetében pedig 0 és 1 közötti Hermite interpoláció
genType smoothstep (genType edge0, genType edge1, genType x)
genBType isnan (genType x) // igaz, ha x NaN
genBType isinf (genType x) // igaz, ha x végtelen
// olyan integerrel tér vissza amelynek értéke a megadott float változót tartalmazza
genIType floatBitsToInt (genType value)
genType intBitsToFloat (genIType value) // mint az előző, csak fordítva
genType fma (genType a, genType b, genType c) // a*b+c
// x=s*2^exp, s a visszatérési érték és [0.5, 1.0) intervallumba esik
genType frexp (genType x, out genIType exp)
genType ldexp (genType x, in genIType exp) // s*2^exp-el tér vissza
Lebegőpontos csomagoló és kicsomagoló műveletek
Az alábbi függvények a következőt csinálják:
Átkonvertálják minden komponensét v-nek 8 vagy 16 bites egészekre,
majd ezeket egy 32 bites előjel nélküli egészbe rakja össze.
uint packUnorm2x16 (vec2 v)
uint packSnorm2x16 (vec2 v)
uint packUnorm4x8 (vec4 v)
uint packSnorm4x8 (vec4 v)
A fentebbi műveletek fordítottját a következő függvények végzik:
vec2 unpackUnorm2x16 (uint p)
vec2 unpackSnorm2x16 (uint p)
vec4 unpackUnorm4x8 (uint p)
vec4 unpackSnorm4x8 (uint p)
Kétszeres pontosságú lebegőpontos szám előállítása egy 2 dimenziós vektorból valamint fordítva:
double packDouble2x32 (uvec2 v)
uvec2 unpackDouble2x32 (double v)
2 dimenziós lebegőpontos vektorból 32 bites előjel nélkül integer előállítása és fordítva:
uint packHalf2x16 (vec2 v)
vec2 unpackHalf2x16 (uint v)
Geometriai műveletek
// x vektor hossza: sqrt(x[0]^2 + x[1]^2...)
float length (genType x)
// p0 és p1 közötti távolság, length(p0-p1)
float distance (genType p0, genType p1)
float dot (genType x, genType y) // x és y skaláris szorzata
vec3 cross (vec3 x, vec3 y) // x és y 3D-s vektorok vektoriális szorzata
// x normalizáltjával tér vissza(ugyanolyan irányú mint x, csak 1 hosszúságú)
genType normalize (genType x)
// ha dit(Nref, I) < 0, akkor N-el, különben -N-el tér vissza
genType faceforward (genType N, genType I, genType Nref)
// I beesési vektor, és N felület orientációra a tülrüződést adjva vissza, I-2*dot(N,I)*N
genType reflect (genType I, genType N)
// mint ez előbbi, csak eta a fénytörési mutató
genType refract (genType I, genType N, float eta)
Mátrix műveletek
A következő mátrixműveletek mind egyszeres és kétszeres pontosságű lebegőpontos számokat tartalmaző mátrixokra valamint különböző méretű mátrixokra is értelmezve vannak.
mat matrixCompMult (mat x, mat y) // x és y elemeit komponensenként szorozza össze
mat2 outerProduct (vec2 c, vec2 r) // c mátrix elemeit egy oszlopnak véve,
// r mátrix elemeit pedig egy sornak véve elvégzi
// a lineáris algebrából ismert c * r mátrixszszorzást
mat2 transpose (mat2 m) // a bemeneti m mátrix transzponáltjával tér vissza
float determinant (mat2 m) // a bemeneti m mátrix determinánsával tér vissza
mat2 inverse (mat2 m) // a bemeneti m mátrix inverzével tér vissza
Vectorok relációs műveletei
Skaláris típusokra a relációs operátor mind értelmezve vannak.
Vektorok elemenkénti összehasonlítására az alábbi beépített függvényeket használhatjuk.
bvec lessThan (vec x, vec y) // x < y
bvec lessThanEqual (vec x, vec y) // x <= y
bvec greaterThan (vec x, vec y) // x > y
bvec greaterThanEqual (vec x, vec y) // x >= y
bvec equal (vec x, vec y) // x == y
bvec notEqual (vec x, vec y) // x != y
bool any (bvec x) // igaz, ha x legalabb egy eleme igaz
bool all (bvec x) // igaz, ha x minen eleme igaz
bool not (bvec x) // igaz, ha x minden eleme hamis
Egészekkel végezhető műveletei
// (x+y) mod 2^32, carry 1, ha az osszeg nagyobb 2^32-nél
genUType uaddCarry (genUType x, genUType y,out genUType carry)
// x-y, ha ez nem negatív, különben ehhez még hozzáad 2^32-t és borrow értéke 1 lesz
genUType usubBorrow (genUType x, genUType y, out genUType borrow)
// x és y 32 bites egészek szorzása, az eredmény alsó része lsb-be, míg a felső része msb-be kerül bele
void umulExtended (genUType x, genUType y, out genUType msb, out genUType lsb)
void imulExtended (genIType x, genIType y, out genIType msb, out genIType lsb)
// bitenkénti kivonás a következő módon: [offset, offset + bits - 1], az alsó bitekkel tér vissza
genIType bitfieldExtract (genIType value, int offset, int bits)
genUType bitfieldExtract (genUType value, int offset, int bits)
// insert-ből az alsó bits-et beleilleszi base-be
genIType bitfieldInsert (genIType base, genIType insert, int offset, int bits)
genUType bitfieldInsert (genUType base, genUType insert, int offset, int bits)
// visszatér a bitek megfordított sorrendjéból adódó értékkel
genIType bitfieldReverse (genIType value)
genUType bitfieldReverse (genUType value)
// 1 értékű biteg számával tér vissza
genIType bitCount (genIType value)
genIType bitCount (genUType value)
// 1 értékű bitek száma az alső részben
genIType findLSB (genIType value)
genIType findLSB (genUType value
// 1 értékű bitek száma a felső részben
genIType findMSB (genIType value)
genIType findMSB (genUType value)
Atomi számláló műveletek
A számlálót egy 32 bites előjel nélküli egész ábrázolja, ebből következendően az értéke a [0, 2^32-1] tartományba esik.
// megnoveli a c számláló értékét, majd visszatér növelés elötti értékkel
uint atomicCounterIncrement (atomic_uint c)
// csökkenti a c számláló értékét, majd visszatér az előző értékével
uint atomicCounterDecrement (atomic_uint c)
// visszatér c számláló értékével
uint atomicCounter (atomic_uint c)
Atomi memóriaműveletek
Az atomi memóriaműveletek atomi műveletet végeznek egy előjeles vagy előjel nélküli egészértéken, amely a buffer-objektumban vagy a megosztott tárolón van.
Minden ilyen művelet kiolvassa az értéket a memóriából, kiszámolja az új értékét, majd beleírja a memóriába, valamint a kiolvasott értékkel tér vissza.
// data értéket hozzáadja, a mem tartalmához
uint atomicAdd (inout uint mem, uint data)
int atomicAdd (inout int mem, int data)
// mem tartalma és a data értéke közül a kisebb lesz az új érték
uint atomicMin (inout uint mem, uint data)
int atomicMin (inout int mem, int data)
// mem tartalma és a data értéke közül a nagyobb lesz az új érték
uint atomicMax (inout uint mem, uint data)
int atomicMax (inout int mem, int data)
// mem tartalma és data értékén végzett bitenkénti ÉS művelet éesz az új érték
uint atomicAnd (inout uint mem, uint data)
int atomicAnd (inout int mem, int data)
// mem tartalma és data értékén végzett bitenkénti VAGY művelet éesz az új érték
uint atomicOr (inout uint mem, uint data)
int atomicOr (inout int mem, int data)
// mem tartalma és data értékén végzett bitenkénti KIZÁRÓ VAGY művelet éesz az új érték
uint atomicXor (inout uint mem, uint data)
int atomicXor (inout int mem, int data)
// data lesz az új érték
uint atomicExchange (inout uint mem, uint data)
int atomicExchange (inout int mem, int data)
// összehasonlítja compare értékét a mem tartalmával, ha egyenlőek data lesz az új érték
uint atomicCompSwap (inout uint mem, uint compare, uint data)
int atomicCompSwap (inout int mem, int compare, int data)
Fragment shader függvények
Ezeket a függvényeket csak a fragment shaderekben tudjuk használni.
Deriválás
Ezezek a függvények a valódi derivált közelítő értékét számolják ki, gyorsak, viszont nem teljesen pontosak.
// p argumentum x szerinti deriváltját számolja ki
genType dFdx (genType p)
// p argumentum y szerinti deriváltját számolja ki
genType dFdy (genType p)
// p argumentum x és y szerinti deriváltjainak összegét adja meg
genType fwidth (genType p)
Interpolációs műveletek
Interpolációs műveleteket a következő függvények segítségével végezhetjük el.
float interpolateAtCentroid (float interpolant)
float interpolateAtSample (float interpolant, int sample)
float interpolateAtOffset (float interpolant, vec2 offset)
Geometry shader függvények
Ezeket a függvényeket csak a geometry shaderekben tudjuk használni.
float interpolateAtCentroid (float interpolant)
float interpolateAtSample (float interpolant, int sample)
float interpolateAtOffset (float interpolant, vec2 offset)
// A kimenő változók aktuális értékét az megadott kimenő folyamra írja.
void EmitStreamVertex (int stream)
// Befejezi az aktuális primitívet és egy újat kezd.
void EndStreamPrimitive (int stream)
// A kimenő változók aktuális értékét az aktuális kimenő primitívbe írja.
void EmitVertex ()
// Befejezi az aktuális primitív számítását és újat kezd.
void EndPrimitive ()
További beépített függvények leírása a nyelv specifikációjában található: GLSL 4.2 specifikáció