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.