Autor: Mihkel Tsäko
Ettekanne aines
"Programmeerimiskeeled".
20080527
GLSL = OpenGl Shading Language
Sissejuhatus
Taust
-
Misasi on OpenGl?
OpenGL (Open Graphics Library) is a standard specification defining a cross-language cross-platform API for writing applications that produce 2D and 3D computer graphics. The interface consists of over 250 different function calls which can be used to draw complex three-dimensional scenes from simple primitives. OpenGL was developed by Silicon Graphics Inc. (SGI) in 1992[1] and is widely used in CAD, virtual reality, scientific visualization, information visualization, and flight simulation.
OpenGl spetsifikatsioonid.
- Core - API baasversioon (hetkel viimane on 2.1)
ARB - Architecture Review Board - standardsed laiendused
EXT - mitme vendori ühine laiendus
tootja (NV, ATI, etc) - tootja spetsiifiline laiendus
XXX - eksperimentaalne laiendus
- GLSL on kasutusel kolme liiki programmide jaoks: Vertex, Fragment ja Geometry programm
- OpenGl pipeline:
NB! Vertex ja Fragment shader on core alates 2.0 ja Geometry shader on EXT alates 2.0.
Saamislugu
- Texture combiners (väljatoodud ainult ARB lahendused):
* Kombineerime tekstuure (REPLACE, MODULATE, ADD ...)
ARB_multitexture (9/15/1998 Core 1.2.1)
ARB_texture_env_add
ARB_texture_env_combine
ARB_texture_env_crossbar
ARB_texture_env_dot3 (bump mapping)
...
- Register combiners:
* Esimene samm assembleri suunas
NV_register_combiners (1999 lõpp)
NV_register_combiners2
NV_texture_shader
NV_texture_shader2
NV_texture_shader3
ATI_fragment_shader
EXT_vertex_shader
...
glEnable(REGISTER_COMBINERS_NV);
glCombinerParameteriNV(NUM_GENERAL_COMBINERS_NV, 1);
glCombinerParameteriNV(COLOR_SUM_CLAMP_NV, GL_TRUE);
glFinalCombinerInputNV(VARIABLE_A_NV, GL_ZERO, UNSIGNED_IDENTITY_NV, GL_RGB);
glFinalCombinerInputNV(VARIABLE_B_NV, GL_ZERO, UNSIGNED_IDENTITY_NV, GL_RGB);
glFinalCombinerInputNV(VARIABLE_C_NV, GL_ZERO, UNSIGNED_IDENTITY_NV, GL_RGB);
glFinalCombinerInputNV(VARIABLE_D_NV, TEXTURE0_ARB, UNSIGNED_IDENTITY_NV, GL_RGB);
glFinalCombinerInputNV(VARIABLE_G_NV, TEXTURE3_ARB, UNSIGNED_IDENTITY_NV, GL_ALPHA);
// oh hell ...
- Assembler:
* Esimesed assembleri põhised lahendused
NV_vertex_program
NV_vertex_program1_1
NV_fragment_program
...
ja lõpuks ka ARB
ARB_vertex_program (June, 2002)
ARB_fragment_program (September, 2002)
Järgnesid igasugused täiendused
ARB_fragment_program_shadow
...
!!ARBfp1.0
# Simple program to show how to code up the default texture environment
ATTRIB tex = fragment.texcoord; #first set of texture coordinates
ATTRIB col = fragment.color.primary; #diffuse interpolated color
OUTPUT outColor = result.color;
TEMP tmp;
TXP tmp, tex, texture, 2D; #sample the texture
MUL outColor, tmp, col; #perform the modulation
END
- GlSl
ARB_shading_language_100, ARB_shader_objects, ARB_vertex_shader, ARB_fragment_shader (June 2003)
=> GlSl 1.00 (core alates 2.0)
täiendused
GL_EXT_geometry_shader4
#version 120
#extension GL_EXT_geometry_shader4 : enable
void main() {
for(int i = 0; i < gl_VerticesIn; ++i) {
gl_FrontColor = gl_FrontColorIn[i]; // copy color
gl_Position = gl_PositionIn[i]; // copy position
EmitVertex(); // done with the vertex
}
}
GLSL
Üldist
- Keele süntaks on peaaegu sama mis C
* kommentaarid kas // järel või /* ja */ vahel
* puudub automaatne tüübiteisendus (1.00 hilisemates versioonides lubatakse int->float)
* puuduvad stringid
* puudub switch konstruktsioon
ning teised pisemad ja suuremad erinevused.
- Süntaks ühine kõigi kolme (Vertex, Fragment, Geometry) programmi jaoks
- Igal programmil erinevad kasutatavad eeldefineeritud funktsioonid ja muutujad
- Võtmesõnad: attribute const uniform varying centroid break continue do for while if else in out inout float int void bool true false invariant discard return mat2 mat3 mat4 mat2x2 mat2x3 mat2x4 mat3x2 mat3x3 mat3x4 mat4x2 mat4x3 mat4x4 vec2 vec3 vec4 ivec2 ivec3 ivec4 bvec2 bvec3 bvec4 sampler1D sampler2D sampler3D samplerCube sampler1DShadow sampler2DShadow struct
- Tuleviku tarbeks reserveeritud võtmesõnad: asm class union enum typedef template this packed goto switch default inline noinline volatile public static extern external interface long short double half fixed unsigned lowp mediump highp precision input output hvec2 hvec3 hvec4 dvec2 dvec3 dvec4 fvec2 fvec3 fvec4 sampler2DRect sampler3DRect sampler2DRectShadow sizeof cast namespace using
NB! reserveeritud on ka kõik võtmesõnad mis algavad __ga.
- Keelest on hetkeseisuga kolm versiooni 1.00, 1.10 ja 1.20 (uusim hetkel on 1.20.8)
- Charset - ASCII alamosa: tühikud* a-z, A-Z 0-9 ning _.+-/*%<>[](){}^|&~=!:;,? ja # preprotsessorile
- Identifikaatorid (gl_ algavad on reserveeritud): _ a-z A-Z 0-9*
- swizzling ja vektori komponendid
{x,y,z,w} - punktid ja normaalid, {r,g,b,a} - värvid, {s,t,p,q} - textuuri kordinaadid
vec4 a,b,c;
a.rgba = b.rrra;
b.xy = vec2(10.0);
c = vec4(a.st, b.zy);
// a.rr = ... VIGA!
// a.ry ... VIGA!
- Programme kirjutades peab arvestama suurte riistvara piirangutega
- GLSL spetsifikatsioon
Preprotsessori direktiivid
- #define, #undef - sama mis C++ ka makrod (eeldefineeritud makrod:__LINE__, __FILE__, __VERSION__)
- #if, #ifdef, #ifndef, #else, #elif, #endif
- #error
- #pragma (STDGL*, optimize, debug)
- #extension (defineeri laiendus "#extension {nimi|all} : {require|enable|warn|disable}")
- #version (kasutatava glsl versiooni number ex: 120)
- #line
- operaatorid: defined, (, ), + ... jne
Andmetüübid
- void
- bool, int, float
- vec[234], bvec[234], ivec[234]
vec3 foo = vec3(vec2(1.1, 2.2) ,3.3)
- mat[234]
mat3 foo = mat3(1.0); // diagonaalis 1.0 ülejäänud nullid
mat2x2 bar = mat2(vec2(1.0), vec2(0.0));
bar[1][2] = 1.7;
// jne...
- sampler[123]D, samplerCube, sampler[12]Dshadow
- ühemõõtmelised massiivid - seejuures suurus on kompileerimisaegne konstant ja piire ei kontrollita
const int len = 2;
float foo[]; // massiivi foo definitsioon
// float[len * 3] // massiivi tüüp
// float[3](1.1,0.0,7.7) // konstructor
// Samas massiivide massiivi defineerida ei või (float[3] a[3])
- Kasutaja saab ka ise defineerida andmetüüpe agregeerides juba defineeritud tüüpe struct võtmesõnaga
struct light {
float intensity;
vec3 position;
} barlight;
Muutujate ja parameetrite kvalifikaatorid
- const - konstant
- varying - vertex -> fragment
- uniform - globaalne ja seega ainult loetav
- attribute - globaalne ja ainult loetav - per vertex
- parameetri kvalifikaatorid: in (vaikimisi), out, inout
- invariant - sama sisendi korral eeldad sama väljundit
invariant gl_Position; // make existing gl_Position be invariant
varying vec3 Color;
invariant Color; // make existing Color be invariant
invariant varying vec3 Normal;
#pragma STDGL invariant(all)
Operaatorid
Kõik C ja C++ operaatorid va bitioperaatorid ja pointerid. Samas bitioperaatorid on tasapisi lisandumas laiendustena.
Tüübi "castimise" operaator puudub, selle asemel on kasutusel konstruktorid.
Precedence | Operator Class | Operators | Associativity |
1 | parenthetical grouping | ( ) | NA |
2 | array subscript function call and constructor structure field or method selector, swizzler post fix increment and decrement | [ ] ( ) . ++ -- | Left to Right |
3 | prefix increment and decrement unary (tilde is reserved) | ++ -- + - ~ ! | Right to Left |
4 | multiplicative (modulus reserved) | * / % | Left to Right |
5 | additive | + - | Left to Right |
6 | bit-wise shift (reserved) | << >> | Left to Right |
7 | relational | < > <= >= | Left to Right |
8 | equality | == != | Left to Right |
9 | bit-wise and (reserved) | & | Left to Right |
10 | bit-wise exclusive or (reserved) | ^ | Left to Right |
11 | bit-wise inclusive or (reserved) | | | Left to Right |
12 | logical and | && | Left to Right |
13 | logical exclusive or | ^^ | Left to Right |
14 | logical inclusive or | || | Left to Right |
15 | selection | ? : | Right to Left |
16 | Assignment arithmetic assignments (modulus, shift, and bit-wise are reserved) | =+ = -= *= /= %= <<= >>= &= ^= |= | Right to Left |
17 | sequence | , | Left to Right |
Voo kontrollimise struktuurid
- selection (if-else)
- iteration (for, while, do-while)
- jumps (discard ainult fragmendi korral, return, break, continue)
- funktsioonid / protseduurid
- puudub switch konstruktsioon
- erindid puuduvad
Sisseehitatud funktsioonid
- trigonomeetria (radians, degrees, sin, asin ...)
- exponent (pow, exp, log, log2, inversesqrt ...)
- matrix (matrixCompMult, outerProduct, transpose ...)
- vector (lessThan, any ...)
- texture lookup (texture1D, texture1DProjLod ...) ei pruugi olla toetatud vertex shaderis
- müra (noise1, noise2 ...) tavakasutaja kaartides realiseerimata
- Fragment only: (dFdy, dFdx, fwidth) ei pruugi olla toetatud
- ftransform (invariant gl_ProjectionMatrix * gl_ModelViewMatrix * gl_Vertex)
- muu (abs, sign, floor, min, clamp, smoothstep, length, dot, reflect, refract ...)
Vertex program
GLSL vertex shader asendab järgmised fixed-function operatsioonid
- Vertex transformations
- Normal transformations
- Normal normalization
- Handling of per-vertex lighting
- Handling of texture coordinates
Ei asenda järgmisi operatsioone
- Frustum clipping
- Homogenous division
- Viewport mapping
- Backface culling
- Polygon mode
- Polygon offset
Mõned enimkasutatavad sisseehitatud muutujad
- vec4 gl_Vertex
- vec3 gl_Normal
- vec4 gl_Color
- vec4 gl_MultiTexCoordi (i=0, 1, 2, ...)
- mat4 gl_ModelViewMatrix
- mat4 gl_ProjectionMatrix
- mat4 gl_ModelViewProjectionMatrix
- mat4 gl_NormalMatrix
Programmi sisend ja väljund
- IN: standardsed OGL atribuudid: gl_color, gl_normal ...
- IN: üldised(generic) atribuudid: 0, 1, 2 ...
- IN: sisseehitatud unifrom: gl_FogColor, gl_ModelViewMatrix ...
- IN: kasutaja defineeritud uniform
- IN: tekstuurid
- OUT: standardsed varying: gl_FrontColor, gl_BackColor ...
- OUT: erimuutujad: gl_Position, gl_ClipVertex, gl_PointSize
- OUT: kasutaja defineeritud varying
Fragment program
GLSL fragment shader asendab järgmised fixed-function operatsioonid
- Color computation
- Texturing
- Color arithmetic
- Handling of per-pixel lighting
- Fog
- Blending
- Discarding fragments
Ei asenda järgmisi operatsioone:
- Stencil test
- Z-buffer test
- Stippling (aka dithering)
Mõned enimkasutatavad sisseehitatud muutujad
- vec4 gl_FragColor
- float gl_FragDepth
Programmi sisend ja väljund
- IN: standardsed varying: gl_Color, gl_SecondaryColor ...
- IN: erimuutujad: gl_FragCoord, gl_FrontFacing
- IN: sisseehitatud uniform: gl_FogColor, gl_ModelViewMatrix ...
- IN: kasutaja defineeritud varying
- IN: kasutaja defineeritud uniform
- IN: tekstuurid
- OUT: gl_FragColor, gl_FragDepth, gl_FragData[n]
Geometry program
GLSL geometry shader asendab järgmised fixed-function operatsioonid
- Ei asendagi midagi! Varasem CPU töö kolib võimalusel osaliselt GPU peale.
Mõned enimkasutatavad sisseehitatud muutujad / funktsioonid
- int gl_VerticesIn
- vec4 gl_PositionIn[]
- vec4 gl_TexCoordIn[]
- EmitVertex()
- EndPrimitive()
Programmi sisend ja väljund
- IN: suuresti sama mis Vertex shader aga terve primitiivina massiivi kujul
- IN: gl_VerticesIn
- OUT: x primitiivi
Näidisprogramm
#version 120
#extension GL_EXT_geometry_shader4 : enable
void main(void) {
int i;
for(i=0; i<gl_VerticesIn; i++){
gl_Position = gl_PositionIn[i];
EmitVertex();
}
EndPrimitive();
//Uus primitiiv !
for(i=0; i<gl_VerticesIn; i++){
gl_Position = gl_PositionIn[i];
gl_Position.xy = gl_Position.yx;
EmitVertex();
}
EndPrimitive();
}
Näiteid
Julia faktoriaal
Rendermonkey skript.
Artisti vaates on muudetav:
* iter - iteratsioonide arv
* zoom - suurenduse faktor (suurendatakse zoom*zoom korda)
* c - on koht Mandelbroti seti pinnal kust Julia set võetakse. Punktid värvitakse iteratsiooni numbri järgi kust vastus saadi
* posd - on nihe (et saaks uurida mõnda teist kohta peale pildi keskpunkti)
Mudeliks on kasutatud ekraaniga paralleelset ruutu - aga minupärast kasutage midaiganes (elevant?) kui suudate järgitava koha ekraanil hoida ;) .
Värvimiseks on võetud vikerkaarevärvide tekstuur.
-
Vertex program:
varying vec2 tc;
uniform float zoom;
uniform vec2 posd;
void main(void) {
tc = gl_MultiTexCoord0.xy;
float zf = zoom * zoom;
vec4 xyzw = ftransform(); // ~ gl_ProjectionMatrix * gl_ModelViewMatrix * gl_Vertex
xyzw.x+=posd.x; xyzw.y+=posd.y;
xyzw.x*=zf; xyzw.y*=zf;
gl_Position = xyzw;
}
- Fragment program:
uniform sampler2D tex;
uniform vec2 c;
uniform int iter;
varying vec2 tc;
void main() {
// c = vec2(-0.4,0.6);
// c = vec2(0.285,0.0);
// c = vec2(0.285,0.01);
// c = vec2(0.45,0.1428);
// c = vec2(-0.70176,-0.3842);
// c = vec2(-0.8,0.156); // nice!
vec2 z;
z.x = 3.0 * (tc.x - 0.5);
z.y = 2.0 * (tc.y - 0.5);
int i;
for(i=0; i<iter; i++) {
float x = (z.x * z.x - z.y * z.y) + c.x;
float y = (z.y * z.x + z.x * z.y) + c.y;
if((x * x + y * y) > 4.0) break;
z.x = x;
z.y = y;
}
gl_FragColor =
texture2D(tex,
vec2(float(i == iter ? 0 : i) / float(iter),0.0));
}
Pretty pictures - ehk näiteid programmi tulemitest
Milline see Julia fraktaal siis välja võiks näha?
12 pilti ühest kohast erineva suurendusega (1-10000 * ekraaniresolutsioon)
Veel üks kena pildike :)