Přeskočit na obsah

OpenGL Shading Language

Z Wikipedie, otevřené encyklopedie

OpenGL Shading Language (zkráceně GLSL nebo také GLslang) je vyšší programovací jazyk pro psaní shaderů, který vychází ze syntaxe jazyka C pro všeobecné použití. Jazyk GLSL byl vytvořen konsorciem OpenGL ARB.

Popis

Jazyk vznikl v rámci procesu postupné transformace fixního vykreslovacího řetězce na řetězec programovatelný a stal se jednou z vyspělejších alternativ k tehdy používaným nižším programovacím jazykům pro psaní shaderů.

Nová funkcionalita je do GLSL často doplňována nejprve v podobě tzv. rozšíření (např. podpora geometry shaderu), které je třeba v kódu explicitně aktivovat a v pozdějších verzích se významná rozšíření stávají součástí funkcionality základní

Verze

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

Operátory

Jazyk GLSL poskytuje operátory známé z jazyka C. Výjimku tvoří operátory související s ukazateli, které nejsou v jazyce GLSL podporovány. V prvních verzích rovněž nebylo možné používat bitové operátory — jejich podpora byla zavedena ve verzi 1.30[2]. Oproti jazyku C je navíc k dispozici speciální operátor swizzle.

Datové typy

GLSL podporuje skalární datové typy jazyka C. Lze použít i datový typ void ovšem pouze jako typ návratové hodnoty funkcí. Podpora struktur poskytuje možnost vytvářet uživatelské datové typy.

Skalární typy

  • bool — pravdivostní datový typ (true/false)
  • int — 32-bit, celé číslo se znaménkem
  • uint — 32-bit, celé číslo bez znaménka
  • float — 32-bit, číslo s plovoucí desetinnou čárkou
  • double — 64-bit, číslo s plovoucí desetinnou čárkou a dvojnásobnou přesností

Vektorové typy

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á z prefixu části "vec" a sufixu. Prefix určuje datový typ složek vektoru[p 1] a sufix určuje jejich počet. Příklad použití (včetně inicializace):

vec4 color0 = 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].

Matice

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čen sufixem. 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ům pole v jazyce C[3]:

mat3 matrix;
matrix[1] = vec3(3.0, 3.0, 3.0);
matrix[2][0] = 16.0;

Řídící struktury a funkce

Jazyk GLSL využívá stejnou konstrukci řídících struktur (větvení, cyklů, skoků) a funkcí jako jazyk C.

Direktivy preprocesoru

Pro řízení předzpracování zdrojového kódu, je k dispozici sada preprocesorových direktiv známých z jazyka C. Navíc jsou k dispozici speciální direktivy #version a #extension [4].

Direktiva version

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 150

Direktiva extension

Chová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: chovani

Kde 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

Komentáře lze zapisovat ve stejném formátu jako v jazycích C, C++.

/* kratká verze */
// celořádková verze

Proces překladu

Ukázka vertex shaderu

Uvedený vertex shader realizuje stejnou transformaci vstupu jako fixní vykreslovací řetězec.

#version 120

void main(void)
{
    gl_Position = ftransform();
}

Použitá funkce ftransform() 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ě vykonat násobení vertexu projekční a modelview maticí.

#version 140

uniform Transformation
{
    mat4 projection_matrix;
    mat4 modelview_matrix;
};

in vec3 vertex;

void main()
{
    gl_Position = projection_matrix * modelview_matrix * vec4(vertex, 1.0);
}

Ukázka geometry shaderu

Následující kód realizuje jednoduchý průchozí geometry shader pro barvu a pozici vertexu.

#version 120
#extension GL_EXT_geometry_shader4 : enable

void main() {
  for(int i = 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 150

layout(triangles) in;
layout(triangle_strip, max_vertices = 3) out;

void main() {
  for(int i = 0; i < gl_in.length(); i++) {
    gl_Position = gl_in[i].gl_Position;
    EmitVertex();
  }
  EndPrimitive();
}

Ukázka fragment shaderu

Jednoduchý shader, jehož výstupem bude fragment červené barvy.

#version 120

void main(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 150

out vec4 MyFragColor;
void main(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, "FragColor");

kde:

  • Program - handler použitého shader programu
  • 0 - počet barvových bufferů
  • "FragColor" - uživatelsky definovaný název barvového bufferu


Ukázka Tessellation control shaderu

Příklad tessellation control shaderu pracujícího s trojúhelníky[5].

#version 400

layout(vertices = 3) out;
in vec3 vPosition[];
out vec3 tcPosition[];
uniform float TessLevelInner;
uniform float TessLevelOuter;

void main()
{
    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;
    }
}

Ukázka Tessellation evalution shaderu

Příklad tessellation evaluation shaderu pracujícího s trojúhelníky[5].

#version 400

layout(triangles, equal_spacing, cw) in;
in vec3 tcPosition[];
out vec3 tePosition;
out vec3 tePatchDistance;
uniform mat4 Projection;
uniform mat4 Modelview;

void main()
{
    vec3 p0 = gl_TessCoord.x * tcPosition[0];
    vec3 p1 = gl_TessCoord.y * tcPosition[1];
    vec3 p2 = gl_TessCoord.z * tcPosition[2];
    tePatchDistance = gl_TessCoord;
    tePosition = normalize(p0 + p1 + p2);
    gl_Position = Projection * Modelview * vec4(tePosition, 1);
}

Poznámky

  1. a b U názvů datových typů (vektorů a matic) jejichž složky jsou typu float, se prefix v neuvádí.

Příbuzné články

Ostatní jazyky pro psaní shaderů

Reference

V tomto článku byl použit překlad textu z článku GLSL na anglické Wikipedii.

Externí odkazy

IDE

Příklady a ukázky