Help end child hunger

Hello World in GLSL

 
Prev: Shader Examples Next: Color Shader
 

This is kind of a Hello World for GLSL. A minimal shader that performs the most basic tasks: transform the vertices and render the primitives in a single color. In here these shaders, vertex and fragment, are presented.

Vertex Shader

As mentioned before, a vertex shader is responsible for transforming the vertices. In here it will be shown how to transform the vertices following the equations for the fixed functionality.

The fixed functionality states that a vertex is to be transformed by the modelview and projection matrices using the following equation:

	vTrans = projection * modelview * incomingVertex

In order to write such a statement in GLSL it is necessary to access the OpenGL state to retrieve both matrices. As mentioned before, part of the OpenGL state is accessible in GLSL, namely the above mentioned matrices. The matrices are provided through predefined uniform variables declared as:

	uniform mat4 gl_ModelViewMatrix;
	uniform mat4 gl_ProjectionMatrix;

One more thing is needed: to access the incoming vertex. These vertices are suplied, one by one, to the vertex shader through a predefined attribute variable:

	attribute vec4 gl_Vertex;

In order to output the transformed vertex, the shader must write to the also predefined variable gl_Position, declared as a vec4.

Given the above, it is now possible to write a vertex shader that will do nothing more than transform vertices. Note that all other functionality will be lost, meaning, for instance, that lighting computations will not be performed.

The vertex shader has to have a main function. The following code does the trick:

void main()
{
	gl_Position = gl_ProjectionMatrix * gl_ModelViewMatrix * gl_Vertex;
}

In the above code, the projection matrix is multiplied by the modelview matrix for every vertex, which is a clear waste of time since these matrices do not change per vertex. The matrices are uniform variables.

GLSL provides some derived matrices, namely the gl_ModelViewProjectionMatrix that is the result of multiplying the above matrices. So the vertex shader could be written as:

void main()
{
	gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
}

The end result is of course the same. Does this guarantee the same transformation as in the fixed functionality? Well in theory yes, but in practice the process of transforming the vertices may not follow the same order of operations as in this case. This is normally a highly optimized task in a graphic card, and a special function is provided to take advantage of that optimization. Another reason for this function is due to the limit in the precision of the float data type. When calculus is done in different orders, different results may be obtained due to this limited precision. Hence the GLSL provides a function that guarantees that not only the best performance is obtained but also that the result is always the same as when using the fixed functionality. This magical function is:

	vec4 ftransform(void);

This function returns the transformed incoming vertex, following the same steps as the fixed functionality does. The shader could then be rewritten as:

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

Fragment Shader

The fragment shader also has a predefined variable to write the color of the fragment: gl_FragColor. As in the case of vertex shaders, fragment shaders must also have a main function. The following code is for a fragment shader that draws all fragments in a bluish color:

void main()
{
	gl_FragColor = vec4(0.4,0.4,0.8,1.0);
}

The source code for this example can be obtained in here: ARB extensions syntax or OpenGL 2.0 syntax.

 

 

Prev: Shader Examples Next: Color Shader
 

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.

%d bloggers like this: