Ha egy függvénynek nincs visszatérési értéke, akkor a visszatérési típust void-nak kell deklarálni. Ezen kívül még az üres paraméterlistát lehet vele jelölni függvényekben. Más deklarációkban nem szerepelhet.
A logikai típust a bool kulcsszó jelöli, amely csak a true és false értékeket képes tárolni. A C++-al ellentétben nem feleltethető meg az int típusnak.
Az egész típust az int vagy az uint kulcsszó jelöli. Az előbbi előjeles, az utóbbi előjel nélküli egész, amelyek pontosan 32 biten ábrázolódnak. Túlcsordulás és alulcsordulás esetén az alsó 32 bit marad meg. Egy egész literál alapértelmezetten egy int típusú literál, míg az u betű hozzáfűzésével uint típusú literált kapunk. Az egész literálokban a 0 előtag 8-as, a 0x vagy 0X előtag 16-os számrendszerben megadott számot jelöl. Ha nincs előtag, akkor 10-es számrendszerbeli a literál.
Egyszeres pontosságú típus a float, kétszeres pontosságú a double. Az IEEE-754 szabvány szerint kódoltak. A lebegőpontos literálok alapértelemezetten float típusúak lesznek, de az lf vagy LF utótag hozzáfűzésével double literált kapunk. A float literálhoz opcionálisan hozzáfűzhető az f vagy F utótag. Exponens rész is megadható. Például: 10e-2. Az előjel megadása esetén az előjel csak egy unáris operátornak számít, nem képezi részét a literálnak.
A nyelvben beépített típusok a 2, 3 vagy 4 komponenst tartalmazó vektorok, amelyek egész, lebegőpontos vagy logikai értékeket tárolhatnak. A lebegőpontos vektorok használhatók például színek, normálvektorok, pozíciók, textúrakoordináták tárolására, míg a logikai vektorok a numerikus vektorok koponensenkénti összehasonlítására használhatók. Néhány példa:
A nyelvben beépítetten a 2×2, 2×3, 2×4, 3×2, 3×3, 3×4, 4×2, 4×3 és 4×4 lebegőpontos komponens tárolására alkalmas mátrixok találhatóak. A mat szóval kezdődő típusok az egyszeres pontosságú, míg a dmat-al kezdődőek a dupla pontosságú lebegőpontos értékeket tároló mátrixokat jelölik. A mat vagy dmat után kell megadni NxM alakban a mátrix alakját, ahol az N az oszlopok számát, M pedig a sorok számát jelöli. Ha csak egy szám szerepel, akkor az egy NxN-es mátrix. Néhány példa:
Az átlátszatlan típusú változók nem olvashatók vagy írhatók közvetlen módon, ehelyett beépített függvényekkel férhetünk hozzájuk. Az ilyen típusú változók csak függvényparaméterek lehetnek vagy olyan változók, amelyek a uniform minősítővel vannak ellátva. Kifejezésekben nem szerepelhetnek operandusként, kiéve a zárójelezést, tömb indexelést és a struktúra adattag kiválasztást. Függvény paraméterben nem lehet out vagy inout minősítővel ellátni, viszont in minősítővel igen. Az OpenGL API inicializálja az ilyen változókat, így deklarációnál nem adathatunk meg inicializálást.
Három kategóriába sorolhatók az átlátszatlan típusok:
Felhasználó által definiált típust struktúrákkal lehet létrehozni, amelyeket a struct kulcsszóval kell megadni. Például:
A name az új típus neve, a variable1 és variable2 a name típusúnak deklarált új változók. A struktúrában legalább egy adattagnak lennie kell. A qualifier csak a deklarált variable1 és variable2-re vonatkozik nem magára a típusra. Az adattagok csak pontosságra vonatkozó minősítőt tartalmazhatnak deklarációjukban és típusuknak már definiáltnak kell lennie. Az adattagok deklarációja nem tartalmazhat inicializációt. Ha tömbnek deklarálunk egy adattagot, akkor annak meg kell adni a pontos méretét. A struktúrán belül nem lehetnek névtelen mezők és a struktúrák beágyazása sem támogatott.
Tömbökben egyforma típusú elemek tárolhatók, amelyek lehetnek alaptípusú vagy struktúra típusú elemek. A tömb mérete megadható egy egész típusú konstanssal, de ez nem kötelező. Ha nem adunk meg méretet deklarációnál, később ugyanazzal az azonosítóval újradeklarálhatunk egy ugyanilyen típusú tömböt egy megadott mérettel. Konstanssal való indexelésnél nem lehet negatív vagy a méretnél nagyobb-egyenlő indexet megadni, míg nem konsatans esetén ilyen esetben nem definiált működést eredményez a végrehajtás. Csak egydimenziós tömbök hozhatók létre és egymásba sem lehet őket ágyazni. Példák:
Tömb lehet függvény visszatérési értéke is és függvényparaméter is. A tömböket lehet inicializálni tömb konstruktorok segítségével:
Egy tömbnek értékül adhatunk egy olyan tömböt, amelynek a mérete adott:
A length() függvénnyel kérdezhető le egy tömb mérete, de csak akkor, ha a tömb konkrét elemszámmal lett deklarálva:
A length függvény egy int típusú értéket ad vissza.
A minősítőknek tetszőleges sorrendben a típus előtt kell szerepelniük. A layout minősítő az egyetlen, amely többször is szerepelhet. A memory minősítők közül többet felhasználhatunk a deklarációkban, de a többi minősítő típusból legfeljebb egy szerepelhet.
Változó deklarációnál legfeljebb egy tárolásra vonatkozó minősítő adható meg a típus neve előtt. A következő lehetőségek vannak:
Az in vagy out minősítővel ellátott változóknak megadható egy kiegészítő, tárolásra vonatkozó minősítő is: centroid, sample vagy patch.
Az attribute és varying minősítők kompatibilitási okokból még a nyelvben vannak. Az előbbi a vertex shaderben az in-nek, az utóbbi a vertex shaderben az out-nak és a fragment shaderben az in-nek felel meg.
Lokális változók a fentiek közül csak a const minősítőt használhatják. A függvény paraméterek az in, out és const-ot használhatják paraméter minősítőként a fentiek közül. Függvény visszatérési érték és struktúra adattagok nem használhatják egyik előbb felsorolt minősítőt sem.
Az in, out és uniform változók deklarációi interface blokkokba csoportosíthatók. Az interface deklarációk formája:
A layout minősítő és a példánynév opcionális. A példány nevével lehet a tagokra hivatkozni. Az interface minősítő in, out vagy uniform lehet. Az out minősítővel ellátott interface blokkok a csővezeték következő programozható szakaszának megfelelő in blokkjába másolódnak. Az uniform minősítővel ellátott interface blokkok a fő alkalmazás buffer objektumába másolódnak. Vertex shader-ben nem lehet in interface blokk, fragment shader-ben nem lehet out interface blokk. A blokkban lévő deklarációkban inicializációs lista, átlátszatlan típusok, struktúra definíciók nem szerepelhetnek. A tagoknak lehetnek további minősítői is: interpolation minősítő, kiegészítő storage minősítő és storage minősítő is. A tagok storage minősítője csak in lehet in minősítővel ellátott interface blokkban és ugyanígy out vagy uniform is lehet, ha out vagy uniform minősítőjű interface blokkban helyezkednek el.
A blokk neve arra való, hogy a szomszédos shader-ek interface blokkjainak illeszkedését megvalósítsuk, kivéve a uniform blokkot, ahol az alkalmazás a blokk nevével tud a blokkra hivatkozni. Egy shader out blokkjának és a következő shader in blokkjának deklarációjának meg kell egyeznie.
A példánynév megadása esetén a tagok a blokk hatókörébe kerülnek és a rájuk való hivatkozás a Példánynév.tag formában lehetséges, különben globális hatókörben deklaráltak és a tag nevével hivatkozhatunk rájuk. Az OpenGL API-ból való hivatkozás is hasonló, azzal a különbséggel, hogy ha megadunk egy példány nevet, akkor az API-ban nem a Példánynév.tag formában, hanem a Blokknév.tag formában hivatkozhatunk rájuk. Néhány példa:
Kidolgozásra vár.
Az input és output változók tovább minősíthetők legfeljebb egy interpolációs minősítővel. A flat minősítő esetén a változót nem interpolálja. A kiegészítő centroid és sample használható a flat mellett, de ez ugyanaz mintha csak a flat minősítőt adtuk volna meg. A smooth minősítő esetén perspektivikusan helyesen fogja interpolálni a kirajzolandó primitívet. A noperspective minősítő esetén lineárisan fogja interpolálni a változót a képernyő koordinátarendszerben.
A függvény paraméterek lehetséges minősítői. A részletes leírást a Függvények című fejezet tartalmazza.
A precision minősítők csak az OpenGL ES-el való kompatibilitás miatt vannak a nyelvben, de funkcionalitásuk és szemantikus jelentésük nincs, így a változók tárolásának pontosságára és a változókra alkalmazott műveletek pontosságára sincs hatással.
A fordítók gyakran optimalizálhatják a forráskódot lebegőpontos számításoknál, amelyek nagyobb teljesítményt érnek el, de csak hasonló eredményt adnak. Vannak olyan algoritmusok, amelyeknek a lebegőpontos számításokat abban a sorrendben kell elvégezniük, ahogyan a forráskódban meg lett adva és minden műveletet konzisztensen kell kezelniük. Például a result = (a*b) + (c*d) kifejezés optimalizálás esetén két művelet végrehajtásával számítódik ki, míg eredetileg 3-mal. Ezen kívül optimalizálásnál a két műveletet különböző pontossággal hajthatja végre.
A precise minősítőt egy változó neve előtt használva megtilthatjuk a fordítónak az optimalizálás lehetőségét azokban a műveletekben, amelyekben az adott változó értéke szerepel. Például:
Előfordulhat, hogy két külön shader programban pontosan ugyanaz a kifejezés különböző értékeket vehet fel. Például, ha van két vertex shader, amelyek két különböző programban vannak és vesszük a gl_Position változót, amelynek ugyanaz a kifejezés az értéke mindkét shader-ben, akkor előfordulhat, hogy nem pontosan ugyanazt az értéket tárolják. Ez problémát okozhat egyes algoritmusokban.
Alapértelmezésben minden változóra fenn áll az előbbi tulajdonság. Az invariant minősítő megadásával deklarált kimenő változók viszont mindig pontosan ugyanazt az értéket fogják tartalmazni, ha ugyanazt a kifejezést adjuk nekik értékül két különböző program shader-jében. Invariant csak out minősítővel ellátott globális hatókörben elhelyezkedő változó lehet. Például:
A következő preprocesszor utasítással (a fragment shader-eket leszámítva) a shader minden változóját invariant-tá lehet tenni, de ez csak debug-olási célokat szolgál, mivel az invariant használata teljesítmény csökkenést okozhat.
Konstans kifejezésekre mindig garantált az invariáns tulajdonság.
Csak az image típusú változókat lehet memory minősítővel ellátni.
Kidolgozásra vár.
Lehetőség van explicit típuskonverzióra skaláris típusok között, de nem típus konverziós operátorral, hanem konstruktorok használatával.
Nem skaláris típusú paraméter megadása esetén a paraméter első elemét veszi és azt konvertálja a megfelelő típusra.
Néhány esetben szükség lehet kifejezések implicit típuskonverziójára. A lehetséges implicit konverziókat tartalmazza a következő táblázat:
Ez a típus konvertálható | Erre a típusra |
int | uint |
int, uint | float |
int, uint, float | double |
ivec2 | uvec2 |
ivec3 | uvec3 |
ivec4 | uvec4 |
ivec2, uvec2 | vec2 |
ivec3, uvec3 | vec3 |
ivec4, uvec4 | vec4 |
ivec2, uvec2, vec2 | dvec2 |
ivec3, uvec3, vec3 | dvec3 |
ivec4, uvec4, vec4 | dvec4 |
mat2 | dmat2 |
mat3 | dmat3 |
mat4 | dmat4 |
mat2x3 | dmat2x3 |
mat2x4 | dmat2x4 |
mat3x2 | dmat3x2 |
mat3x4 | dmat3x4 |
mat4x2 | dmat4x2 |
mat4x3 | dmat4x3 |