OpenGL Shading Language (zkráceněGLSL nebo takéGLslang) jevyšší programovacíjazyk pro psaní shaderů, který vychází ze syntaxejazyka C provšeobecné použití. Jazyk GLSL byl vytvořen konsorciemOpenGL ARB.
Jazyk vznikl v rámci procesu postupné transformacefixního vykreslovacího řetězce nařetězec programovatelný a stal se jednou z vyspělejších alternativ k tehdy používanýmnižším programovacím jazykům pro psaní shaderů.
Nová funkcionalita (nebo funkcionalita specifická pro určitého výrobce čihardware) je do GLSL často doplňována nejprve v podobě tzv. rozšíření (např. podpora geometry shaderu), které je třeba vkóduexplicitně aktivovat a v pozdějších verzích se významná rozšíření stávají součástí funkcionality základní.
Tabulka shrnující jednotlivé verze OpenGL a příslušné verze GLSL, které byly v rámci dané specifikace představeny:[1]
| Verze GLSL | Verze OpenGL |
|---|---|
| 1.10.59 | 2.0 |
| 1.20.8 | 2.1 |
| 1.30.10 | 3.0 |
| 1.40.08 | 3.1 |
| 1.50.11 | 3.2 |
| 3.30.6 | 3.3 |
| 4.00.9 | 4.0 |
| 4.10.6 | 4.1 |
| 4.20.6 | 4.2 |
Jazyk GLSL poskytuje operátory známé zjazyka C. Výjimku tvoří operátory související sukazateli, které nejsou v jazyce GLSL podporovány. V prvních verzích rovněž nebylo možné používatbitové operátory — jejich podpora byla zavedena ve verzi 1.30.[2] Oproti jazyku C je navíc k dispozici speciální operátorswizzle.
GLSL podporujeskalárnídatové typy jazyka C. Lze použít i datový typvoid ovšem pouze jako typ návratové hodnotyfunkcí. Podporastruktur apolí umožňuje tvorbuuživatelských datových typů.
bool — pravdivostní datový typ (true/false)int — 32bit,celé číslo se znaménkemuint — 32bit, celé číslo bez znaménkafloat — 32bit, číslo s plovoucí desetinnou čárkoudouble — 64bit, číslo s plovoucí desetinnou čárkou a dvojnásobnou přesnostíVektor je homogenní datový typ. GLSL má vestavěnou podporu pro jedno- až čtyř-složkové vektory. Název vektorového datového typu (např.dvec4) se skládá zprefixu části "vec" asufixu. Prefix určuje datový typ složek vektoru[p 1] a sufix určuje jejich počet. Příklad použití (včetně inicializace):
vec4color0=vec4(1.0,0.0,0.0,0.0);
K jednotlivým složkám vektoru lze pak přistupovat pomocí definovaných složek x, y, z a w (např.color0.x = 0.5;).[3]
GLSL poskytuje podporu pro práci s maticemi o rozměrech 2x2 až 4x4, přičemž matice nemusí být pouze čtvercová (k dispozici jsou všechny kombinace uvedených rozměrů). Názvy maticových datových typů jsou tvořeny obdobně jako u vektorů — název začínáprefixem následuje část "mat" a je ukončensufixem. Prefix určuje datový typ prvků matice[p 1] a sufix určuje rozměr matice (např. mat3x4; u čtvercových matic je použit zkrácený zápis např. mat3 pro matici o rozměrech 3x3). Příklad použití (včetně inicializace):
K jednotlivým prvkům matice přistupujeme obdobně jako k prvkůmpole v jazyce C:[3]
mat3matrix;matrix[1]=vec3(3.0,3.0,3.0);matrix[2][0]=16.0;
GLSL nabízí i tzv.opaque (česky někdy též "transparentní")datové typy. Opaque datový typ je ve skutečnosti pouzehandler (handle) na nějaký jiný objekt. Přístup k takovému objektu probíhá přes sadu vestavěnýchfunkcí (přímé čtení či zápis hodnotyproměnné takového typu není možné). Při deklaraci jednoho opaque datového typu jsou ve skutečnosti deklarovány objekty dva, handler samotný i vnitřní objekt ke kterému handler přistupuje. Deklarace těchto typů je možná pouze na některých místech kódu — typicky bývají deklarovány např. jako parametry funkcí.[4]
Do kategorie opaque datových typů spadají v GLSL tzv.Samplery (např.sampler2D) a jedná se o handler k jedno-, dvou- či tří-rozměrnétextuře, hloubkové textuře, cube-mapě apod.
Image je další třídou opaque datových typů (např.image1D,image2D,image2DMS a další). jedná se o handler k jedno-, dvou- či tří-rozměrnému obrázku (image), které se používají pro načítání či ukládánísouborů obsahujících statický obraz (případně pro další atomické operace).
Jazyk GLSL využívá stejnou konstrukciřídících struktur (větvení, cyklů, skoků) afunkcí jako jazyk C. Kromě podpory uživatelských funkcí disponuje GLSL i sadou funkcí vestavěných. Některé z nich jsou podobné funkcím jazyka C (zejména matematickým) — např. funkce exp() nebo abs(), zatímco jiné jsou určeny speciálně pro práci s grafikou — např. smoothstep() nebo texture2D().
Pro řízení předzpracovánízdrojového kódu, je k dispozici sadapreprocesorových direktiv známých zjazyka C. Navíc jsou k dispozici speciální direktivy#version a#extension.[4]
Direktiva#version se musí nacházet na začátku každého zdrojového souboru a určuje verzi GLSL, která bude při překladu použita.
#version 150Chování GLSL lze dále ovlivnit pomocí tzv.rozšíření OpenGL (OpenGL extensions). Tato rozšíření lze řídit právě pomocí direktivy#extension:
#extension jmeno_rozsireni: chovaniKde položka "jmeno_rozsireni" definuje název konkrétního rozšíření nebo nabývá hodnoty "all" chceme-li pracovat se všemi rozšířeními. Dané rozšíření lze v části "chovani" povolit nebo zakázat a dále pak definovat chování v případě, kdy rozšíření není dostupné.
Komentáře lze zapisovat ve stejném formátu jako v jazycích C,C++.
/* krátká verze */// celořádková verze
Kód shaderu může být umístěn v samostatnémsouboru nebo jakotextový řetězec v rámci hlavního programu. Vlastnípřeklad probíhá až za běhu aplikace. Nejprve je třeba vytvořitshader objekt a definovat jeho typ (např. GL_VERTEX_SHADER) voláním OpenGL funkceglCreateShader(). Vlastní překlad je vyvolán funkcíglCompileShader() (jako parametr je předán řetězec s kódem shaderu). Dalším krokem jesestavení přeložených shaderů ve výsledný program. Opět je nejprve nutné vytvořit speciálníobjekt program funkcíglCreateProgram(). Následuje připojení přeložených shader objektů —glAttachShader() a potom již vlastní proces linkování —glLinkProgram(), v rámci kterého dochází rovněž k mapování proměnných hlavního programu a proměnných GLSL shaderů.[5]
Uvedený vertex shader realizuje stejnou transformaci vstupu jakofixní vykreslovací řetězec.
#version 120voidmain(void){gl_Position=ftransform();}
Použitá funkceftransform() není od verze GLSL 1.40 dostupná. Při použití novější specifikace GLSL musíprogramátor místo použití této funkce explicitně vykonatnásobení vertexuprojekční amodelviewmaticí.
#version 140uniformTransformation{mat4projection_matrix;mat4modelview_matrix;};invec3vertex;voidmain(){gl_Position=projection_matrix*modelview_matrix*vec4(vertex,1.0);}
Následujícíkód realizuje jednoduchý průchozí geometry shader pro barvu a pozici vertexu.
#version 120#extension GL_EXT_geometry_shader4 : enablevoidmain(){for(inti=0;i<gl_VerticesIn;++i){gl_FrontColor=gl_FrontColorIn[i];gl_Position=gl_PositionIn[i];EmitVertex();}}
Od verze GLSL 1.50 nejsou již geometry shadery rozšířením, ale staly se součástí základní funkcionality GLSL. V souvislosti s tím došlo i k mírné změněsyntaxe.
#version 150layout(triangles)in;layout(triangle_strip,max_vertices=3)out;voidmain(){for(inti=0;i<gl_in.length();i++){gl_Position=gl_in[i].gl_Position;EmitVertex();}EndPrimitive();}
Jednoduchý shader, jehož výstupem bude fragment červené barvy.
#version 120voidmain(void){gl_FragColor=vec4(1.0,0.0,0.0,1.0);}
Při použití specifikace GLSL 1.30 nebo pozdější je třeba shader upravit.
#version 150outvec4MyFragColor;voidmain(void){MyFragColor=vec4(1.0,0.0,0.0,1.0);}
V hlavním programu je potřeba provést navázání proměnné:
glBindFragDataLocation(Program,0,"MyFragColor");
kde:
Program — handler použitého shader programu0 — index barvového bufferu"MyFragColor" — uživatelsky definovaný název barvového bufferuPříklad tessellation control shaderu pracujícího strojúhelníky.[6]
#version 400layout(vertices=3)out;invec3vPosition[];outvec3tcPosition[];uniformfloatTessLevelInner;uniformfloatTessLevelOuter;voidmain(){tcPosition[gl_InvocationID]=vPosition[gl_InvocationID];if(gl_InvocationID==0){gl_TessLevelInner[0]=TessLevelInner;gl_TessLevelOuter[0]=TessLevelOuter;gl_TessLevelOuter[1]=TessLevelOuter;gl_TessLevelOuter[2]=TessLevelOuter;}}
Příklad tessellation evaluation shaderu pracujícího s trojúhelníky.[6]
#version 400layout(triangles,equal_spacing,cw)in;invec3tcPosition[];outvec3tePosition;outvec3tePatchDistance;uniformmat4Projection;uniformmat4Modelview;voidmain(){vec3p0=gl_TessCoord.x*tcPosition[0];vec3p1=gl_TessCoord.y*tcPosition[1];vec3p2=gl_TessCoord.z*tcPosition[2];tePatchDistance=gl_TessCoord;tePosition=normalize(p0+p1+p2);gl_Position=Projection*Modelview*vec4(tePosition,1);}
V tomto článku byl použitpřeklad textu z článkuGLSL na anglické Wikipedii.