Vertex and Fragment shaders are written in GLSL, a domain-specific mini-language for writing shaders. The syntax is C/C++-like, and basic shaders tend to look like very simple C programs, such as:
x1// some declarations here23void main() {4 // main program here5}The vertex shader's job is to:
gl_Position, which is a vec4 that contains the vertex's position.varying parameters needed for the Fragment shaderThe fragment shader's job is to:
gl_FragColor, which is a vec4 containing the fragment's color.Here are some things about GLSL that are not C-like:
vec2, vec3, vec4, mat2, mat3, mat4 are built-in vector and matrix types; their values are floats.Multiplication involving these types is matrix/vector multiplication
Colors are 4 channels. The first 3 are RGB, and the 4th is transparency; 0 is fully transparent, 1 is fully opaque.
varyings are declared in both the Vertex shader and in the Fragment shader. By convention, their names are usually chosen to begin with v, such as vColor or vNormal.
Vector types support some neat shorthand. For example:
In the following line Position is a vec3, and its entries become the first three entries of the vec4 being set to gl_Position:
xxxxxxxxxx11gl_Position = vec4(Position, 1.0);Accessing elements of a vector using attribute names:
xxxxxxxxxx51vec4 a = vec4(1, 2, 3, 4);2float x = a.x; // x = 1.03float y = a.y; // x = 2.04float z = a.z; // x = 3.05float w = a.w; // x = 4.0This works for shorter vectors too, within bounds; you can also use r,g,b,a, and s,t,p,q as alternative accessors.
Swizzling allows you to easily construct one vector from elements of another:
xxxxxxxxxx51vec4 a = vec4(1, 2, 3, 4);23vec3 b = a.xyz; // b = (1,2,3)4vec2 c = a.qp; // c = (4,3)5vec4 d = a.xxyy; // d = (1,1,2,2)vec2
xxxxxxxxxx111vec2 a;2a.x = 0.0;3a.y = 1.0; // a = (0,1)45vec2 b;6b.s = 10.0;7b.t = 12.5; // b = (10,12.5)89vec2 c;10c[0] = 9.0;11c[1] = 8.0; // c= (9,8)vec3
xxxxxxxxxx141vec3 a;2a.x = 10.0; a.y = 20.0; a.z = 30.0; // a = (10, 20, 30)3a.r = 0.1; a.g = 0.2; a.b = 0.3; // a = (0.1, 0.2, 0.3)4a.s = 1.0; a.t = 2.0; a.p = 3.0; // a = (1, 2, 3)56vec3 b = vec3(4.0, 5.0, 6.0);78vec3 c = a + b; // c = (5, 7, 9)9vec3 d = a - b; // d = (-3, -3, -3)10vec3 e = a * b; // e = (4, 10, 18)11vec3 f = a * 3; // e = (3, 6, 9)12float g = dot(a, b); // g = 3213vec3 h = cross(a,b); // h = (-5,6,-3)14float i = length(a); // i = 3.742vec4
xxxxxxxxxx121vec4 a;2a.x = 10.0; a.y = 20.0; a.z = 30.0; a.w = 40.0; // a = (10, 20, 30, 40)3a.r = 0.1; a.g = 0.2; a.b = 0.3; a.a = 0.4; // a = (0.1, 0.2, 0.3, 0.4)4a.s = 1.0; a.t = 2.0; a.p = 3.0; a.q = 4.0; // a = (1, 2, 3, 4)56vec4 b = vec4(5, 6, 7, 8);78vec4 c = a + b; // c = (6, 8, 10, 12)9vec4 d = a - b; // d = (-4, -4, -4, -4)10vec4 e = a * b; // e = (5, 12, 21, 32)11vec4 f = a * 3; // f = (3, 6, 9, 12)12float g = length(a); // g = 5.477mat2
xxxxxxxxxx71mat2 A = mat2(1.0,2.0,3.0,4.0); // in column-major order23vec2 x = vec2(1.0, 0.0);4vec2 y = vec2(0.0, 1.0);56vec2 a = A * x; // a = (1,2)7vec2 b = A * y; // b = (3,4)mat3
xxxxxxxxxx91mat3 A = mat3(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0); // in column-major order23vec3 x = vec3(1.0, 0.0, 0.0);4vec3 y = vec3(0.0, 1.0, 0.0);5vec3 z = vec3(0.0, 0.0, 1.0);67vec3 a = A * x; // a = (1,2,3)8vec3 b = A * y; // b = (4,5,6)9vec3 c = A * z; // c = (6,7,8)mat4
xxxxxxxxxx151mat4 A = mat4(2 1.0, 2.0, 3.0, 4.0,3 5.0, 6.0, 7.0, 8.0,4 9.0, 10.0, 11.0, 12.0,5 13.0, 14.0, 15.0, 16.0); // in column-major order67vec4 x = vec4(1.0, 0.0, 0.0, 0.0);8vec4 y = vec4(0.0, 1.0, 0.0, 0.0);9vec4 z = vec4(0.0, 0.0, 1.0, 0.0);10vec4 w = vec4(0.0, 0.0, 0.0, 1.0);1112vec4 a = A * x; // a = (1,2,3,4)13vec4 b = A * y; // b = (5,6,7,8)14vec4 c = A * z; // c = (9,10,11,12)15vec4 d = A * w; // d = (13,14,15,16)There are also integer vectors (ivec2, ivec3, ivec4) and boolean vectors (bvec2, bvec3, bvec4).
You can declare fixed-size arrays whose sizes are known at compile time:
xxxxxxxxxx61float A[4];2A[0] = 5; A[3] = 10;34vec4 B[10];5B[3] = vec4(1,2,3,4);6B[8].y = 10.0;