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:
// some declarations here
void main() { // main program here}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:
gl_Position = vec4(Position, 1.0);Accessing elements of a vector using attribute names:
vec4 a = vec4(1, 2, 3, 4);float x = a.x; // x = 1.0float y = a.y; // x = 2.0float z = a.z; // x = 3.0float 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:
vec4 a = vec4(1, 2, 3, 4);
vec3 b = a.xyz; // b = (1,2,3)vec2 c = a.qp; // c = (4,3)vec4 d = a.xxyy; // d = (1,1,2,2)vec2
vec2 a;a.x = 0.0;a.y = 1.0; // a = (0,1)
vec2 b;b.s = 10.0;b.t = 12.5; // b = (10,12.5)
vec2 c;c[0] = 9.0;c[1] = 8.0; // c= (9,8)vec3
vec3 a;a.x = 10.0; a.y = 20.0; a.z = 30.0; // a = (10, 20, 30)a.r = 0.1; a.g = 0.2; a.b = 0.3; // a = (0.1, 0.2, 0.3)a.s = 1.0; a.t = 2.0; a.p = 3.0; // a = (1, 2, 3)
vec3 b = vec3(4.0, 5.0, 6.0);
vec3 c = a + b; // c = (5, 7, 9)vec3 d = a - b; // d = (-3, -3, -3)vec3 e = a * b; // e = (4, 10, 18)vec3 f = a * 3; // e = (3, 6, 9)float g = dot(a, b); // g = 32vec3 h = cross(a,b); // h = (-5,6,-3)float i = length(a); // i = 3.742vec4
vec4 a;a.x = 10.0; a.y = 20.0; a.z = 30.0; a.w = 40.0; // a = (10, 20, 30, 40)a.r = 0.1; a.g = 0.2; a.b = 0.3; a.a = 0.4; // a = (0.1, 0.2, 0.3, 0.4)a.s = 1.0; a.t = 2.0; a.p = 3.0; a.q = 4.0; // a = (1, 2, 3, 4)
vec4 b = vec4(5, 6, 7, 8);
vec4 c = a + b; // c = (6, 8, 10, 12)vec4 d = a - b; // d = (-4, -4, -4, -4)vec4 e = a * b; // e = (5, 12, 21, 32)vec4 f = a * 3; // f = (3, 6, 9, 12)float g = length(a); // g = 5.477mat2
mat2 A = mat2(1.0,2.0,3.0,4.0); // in column-major order
vec2 x = vec2(1.0, 0.0);vec2 y = vec2(0.0, 1.0);
vec2 a = A * x; // a = (1,2)vec2 b = A * y; // b = (3,4)mat3
xxxxxxxxxxmat3 A = mat3(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0); // in column-major order
vec3 x = vec3(1.0, 0.0, 0.0);vec3 y = vec3(0.0, 1.0, 0.0);vec3 z = vec3(0.0, 0.0, 1.0);
vec3 a = A * x; // a = (1,2,3)vec3 b = A * y; // b = (4,5,6)vec3 c = A * z; // c = (6,7,8)mat4
xxxxxxxxxxmat4 A = mat4( 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0); // in column-major order
vec4 x = vec4(1.0, 0.0, 0.0, 0.0);vec4 y = vec4(0.0, 1.0, 0.0, 0.0);vec4 z = vec4(0.0, 0.0, 1.0, 0.0);vec4 w = vec4(0.0, 0.0, 0.0, 1.0);
vec4 a = A * x; // a = (1,2,3,4)vec4 b = A * y; // b = (5,6,7,8)vec4 c = A * z; // c = (9,10,11,12)vec4 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:
xxxxxxxxxxfloat A[4];A[0] = 5; A[3] = 10;
vec4 B[10];B[3] = vec4(1,2,3,4);B[8].y = 10.0;