Anatomy of a Programmable Realtime Shader

 
 
 

Programmable realtime shaders allow you to replace the fixed function pipeline with your own program to control shading at the vertex and pixel level. This allows you to create more complex effects, but it also requires that you re-implement code that the fixed-function pipeline executes automatically, like transforms and shading of vertices, texture coordinate generation and transforms, and texture modulation modes.

A programmable realtime shader consists of a vertex shader and a pixel shader. The data stream flows from the application to the vertex shader, then to the pixel shader, and finally to the frame buffer.

To write vertex and pixel shader code that supports OpenGL-based effects, you can use nVidia's Cg language or the OpenGL Shading Language (GLSL). For DirectX9-based effects, you can use Microsoft High Level Shading Language (HLSL).

Vertex Shaders

Vertex shaders are executed for every vertex of the shaded object. They take input parameters, process them, and generate output data to be sent to a pixel shader.

The input parameters of a vertex shader can be:

  • Vertex position in object space.

  • Vertex normal in object space.

  • Vertex colors.

  • Texture coordinates.

  • Uniform parameters, which are constants that can be used in the shader code.

The output of a vertex shader can be:

  • Vertex position in screen space.

  • Vertex colors.

  • Texture coordinates.

Pixel Shaders

Pixel shaders (also known as fragment shaders) are executed for every pixel generated of the object. They take input parameters, process them, and generate output data to be sent to the blending core of the GPU before going to the frame buffer. The input parameters come from vertex shaders and are interpolated inside of the triangle to which they belong.

The input parameters of a pixel shader can be:

  • Vertex position in screen space.

  • Vertex colors.

  • Texture coordinates.

  • Uniform parameters, which are constants that can be used in the shader code.

The output of a pixel shader can be composed of:

  • Pixel color.

  • Pixel depth.

Realtime Shader Structure

A realtime shader has a very simple structure: it has input parameters, output parameters, and code. The code is called for every vertex of every pixel.

There are two types of input parameters: uniform and varying. Uniform means that the parameter value is the same for all vertices or pixels. Varying means that the parameter value changes for every vertex and every pixel.

For example, this simple HLSL program transforms a vertex position into the position of eye coordinate space by modelview matrix.

struct a2v { 
	float4 Position : POSITION;
};
struct v2p {
	float4 Position : POSITION;
};
void main(in a2v IN, out v2p OUT,
	uniform float4x4 ModelViewMatrix)
{
	OUT.Position = mul(IN.Position, ModelViewMatrix);
}