Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

Version 1 (modified by janise, 16 years ago) (diff)

Shader

With this page I want to give some insights about shaders in Ogre in order to help anybody willing to implement some into orxonox. The Page does not really deal with writing shader programs but mainly with using them.

What are shaders?

Shaders are external code fragments that can be used to create graphical rendering effects. Famous examples are bump and normal mapping, water effects or HDR.

There are three major languages that are used to write shader programs:

  • HLSL (High Level Shader Language, can only be used with DirectX)
  • GLSL (OpenGL Shader Language, can only be used with OpenGL)
  • CG (by Nvidia, similar to GLSL, can be used for OpenGl and DirectX with an appropriate compiler: http://developer.nvidia.com/object/cg_toolkit.html

Two types of shader programs exist:

  • Vertex shader: Is run once for each vertex given to the graphics processor. The purpose is to transform each vertex's 3D position in virtual space to the 2D coordinate at which it appears on the screen. Vertex shaders can manipulate properties such as position, color, and texture coordinate.
  • Pixel shader (or fragment shader): Takes the output from the vertex shader and colorizes every individual pixel.

Implementing Shaders

For every shader we have to write a material file in Ogre where we need to define the shader programs we are going to need and their parameters. Then we can use those shader programs in the passes of the material file.

Basic Example: (taken from the Ogre wiki)
This Material simply applies a texture to an Object using shaders

PlainTexture.material

// CG Vertex shader definition
vertex_program PlainTexture_VS cg			
{
        // Look in this source file for shader code
	source GameObjStandard.cg
        // Use this function for the vertex shader			
	entry_point main_plain_texture_vp	
        // Compile the shader to vs_1_1 format	
	profiles vs_1_1					

	// This block saves us from manually setting parameters in code
        default_params					
	{
                // Ogre will put the worldviewproj into our 'worldViewProj' parameter for us.
		param_named_auto worldViewProj worldviewproj_matrix		
                // Note that 'worldViewProj' is a parameter in the cg code.
	}
}

// CG Pixel shader definition
fragment_program PlainTexture_PS cg			
{
        // Look in this source file for shader code
	source GameObjStandard.cg		
        // Use this function for the pixel shader	
	entry_point main_plain_texture_fp	
        // Compile to ps_1_1 format	
	profiles ps_1_1					
}

material PlainTexture
{
        // Material has one technique
	technique					
	{
                // This technique has one pass
		pass					
		{
                        // Make this pass use the vertex shader defined above
			vertex_program_ref PlainTexture_VS	
			{
			}
                        // Make this pass use the pixel shader defined above
			fragment_program_ref PlainTexture_PS	
			{
			}
			texture_unit
			{
                                // This pass will use this 2D texture as its input
				texture Ten.png 2d		
			}
		}
	}
}

GameObjStandard.cg

void main_plain_texture_vp(
		// Vertex Inputs
		float4 position		: POSITION,	// Vertex position in model space
		float2 texCoord0	: TEXCOORD0,	// Texture UV set 0

		// Outputs
		out float4 oPosition	: POSITION,	// Transformed vertex position
		out float2 uv0		: TEXCOORD0,	// UV0

		// Model Level Inputs
		uniform float4x4 worldViewProj)
{
	// Calculate output position
	oPosition = mul(worldViewProj, position);

	// Simply copy the input vertex UV to the output
	uv0 = texCoord0;
}

void main_plain_texture_fp(
		// Pixel Inputs
		float2 uv0		: TEXCOORD0,	// UV interpolated for current pixel
			 
		// Outputs
		out float4 color	: COLOR,	// Output color we want to write
			 
		// Model Level Inputs
		uniform sampler2D texture)		// Texture we're going to use
{
	// Just sample texture using supplied UV
	color = tex2D(texture, uv0);
}

The keyword uniform identifies the parameters you will have to supply in the material file.

  • Some parameters can be supplied by the Ogre Engine (param_named_auto), like a light position.
  • Some parameters can be supplied by your material file (param_named) like a texture map.
  • Some parameters can be supplied by your application (custom).

We can now apply this material file to an entity somewhere in our code:

    MyEntity->setMaterialName( "PlainTexture" );

Instead of just passing on the texture color to the output in the last line of the pixel shader you can imagine that we could do all kinds of funny things with it first. For instance changing the brightness of each pixel depending on a second normal map texture and the position of the viewer to create an illusion of a surface structure.