HLSL         Using HLSL in OGRE

HLSL - High Level Shader Language. This is a shader language developed by Microsoft for use with {LEX()}DirectX{LEX} and is very similar to {LEX()}Cg{LEX}.

{WIKIPEDIA()/}

Using HLSL in OGRE

HLSL shaders are used inside Ogre much like the other shading languages as Cg and {LEX()}GLSL{LEX}, but there are some little differences that I will try to explain here.
First, the material definition will be much like this:

material Test13/RockWall
{
    technique
    {
        pass
        {
            vertex_program_ref Deferred_nm_vs
            {
            }
            fragment_program_ref Deferred_nm_ps
            {
            }

            texture_unit
            {
                // sampler s0
                                // ...
            }
            texture_unit
            {
                // sampler s1
                                // ...
            }        
                }
    }
}

vertex_program_ref refers to a vertex program definition and fragment_program_ref refers to a fragment program definition. Those can be defined in .program scripts or inside the .material script itself. These define the name of the program text file, the destination profile (vs/ps version) and default parameters.

vertex_program Deferred_vs hlsl
{
    source Deferred_vs.hlsl
    target vs_1_1
    entry_point main
    
    default_params
    {
        param_named_auto worldView worldview_matrix
        param_named_auto worldViewProj worldviewproj_matrix
    }
}
fragment_program Deferred_ps hlsl
{
    source Deferred_ps.hlsl
    target ps_2_0
    entry_point main
    default_params
    {
        param_named specularity float 0.0
    }
}

  • source defines the program source code name.
  • entry_point is the name of the shader function that is called for each vertex/fragment. This is usually main.
  • target signifies the Vertex Shaders or Pixel Shaders version to compile for. For fragment_program this can be ps_1_1, ps_1_4, ps_2_0, ps_2_x, ps_3_0 or ps_3_x (for more information have a look at Declaring Vertex and Fragment Programs. For vertex_program it can be vs_1_1, vs_2_0, vs_2_x or vs_3_0. Always try to use the lowest version that can do what you need, as this is usually faster and supports more cards.
  • default_params define default parameters for this shader. These can be overidden in the vertex_program_ref and fragment_program_ref blocks.

Parameters

Named parameters can be defined at global scope in the HLSL program:

float4x4 worldViewProj;
float4x4 world;
float4x4 worldView;

Ogre will make sure these parameters will contain the values assigned to them via param_named or param_named_auto in the program or material script.

Samplers and texture units

Inside .hlsl fragment programs, you can define samplers using a special syntax, so that Ogre knows which texture unit the sampler refers to:

sampler Tex0: register(s0);
sampler Tex1: register(s1);

register(s0) refers to the first texture_unit block, register(s1) to the second one and so on.

Vertex shaders

A minimal vertex shader that receives the POSITION, NORMAL and TEXCOORD0 vertex attributes and outputs POSITION and TEXCOORD0 to the fragment shader would look like this:

struct VS_OUTPUT {
   float4 pos: POSITION;
   float2 texCoord0: TEXCOORD0;
};

float4x4 worldViewProj;

VS_OUTPUT main(
    float4 Pos: POSITION, 
    float3 normal: NORMAL,
    float2 texCoord0: TEXCOORD0
){
   VS_OUTPUT Out;
   
   Out.pos = mul(worldViewProj, Pos);
   Out.texCoord0 = texCoord0;

   return Out;
}

Fragment shaders

A minimal fragment shader that samples a texture at the incoming texture coordinate and outputs the sampled COLOR:

sampler Tex0: register(s0);

float4 main(float4 texCoord0: TEXCOORD0): COLOR0
{
    return tex2D(Tex0, texCoord0);
}

Tangent vectors

If you need tangent vectors in your HLSL shaders, you can ask OGRE to provide them. However, you will have to use the semantic TEXCOORD for that. So the input structure for your vertex shader may look like this:

struct a2v
{
     float4 position : POSITION0;
     float3 normal : NORMAL;
     float2 tex : TEXCOORD0;
     float3 tangent : TEXCOORD1;
};


To make sure OGRE can give you these tangents, either tell the exporter you use for your models to generate them, or tell OGRE to generate them by using the following code:

unsigned short src, dest; 
if (!pMesh->suggestTangentVectorBuildParams(Ogre::VES_TANGENT, src, dest)) 
{ 
    pMesh->buildTangentVectors(Ogre::VES_TANGENT, src, dest); 
}


Note:

  • Since OGRE 1.6.0 this is done automatically.
  • OGRE does not generate any binormals. If you need them, you can calculate them yourself by simply taking the cross product of the tangent and the normal in the vertex shader.


OGRE manual: Declaring Vertex and Fragment programs

Microsoft HLSL reference