Home | About Us | Media | Support | News | Contact Us
Copyright ACE Studios

In this tutorial we will cover:

using ATI's Render Monkey shaders
specular bump map effect via shaders
calculating the Binormal vector in the shader
using default shader parameters

Using shaders programs from external applications is an easy process, and when implemented in max as Ogre materials they can be added to the material library and used whenever you need them

NOTE: For this tutorial you need to download and install Render Monkey shader tool from ATI Developers web site

NOTE: A basic understanding of the Render Monkey shader tool is requiered, the reader is assumed to have some experience with this application and have worked with shader code before
Artist center
tutorial 1
tutorial 2
tutorial 3
tutorial 4
      tutorial 5
Example Scenes
1. Open Render Monkey application, by clicking on its icon or via the "Programs" menu
Open the "Illumination.rfx" workspace file from the "DX9" examples folder
Select the "Specular Bump" effect and "Set as Active Effect" with the F3 hotkey or via the context menu
2. Expand the "Single Pass" entry

Open the "Vertex Shader" entry by double cliking it
The vertex shader code for this pass will be displayed on the shader code editor

In the Shader editor window, bring the context menu (right click) and select "Save.."
Save the shader code with the name tutorial_BumpMap_vs.source

3. Open the "Pixel Shader" entry and repeat the process of the previous step, but save this shader with the name tutorial_BumpMap_ps.source
4. Because there are a few differences on how Ogre sets the meshes buffer streams, we will do some simple modifications to the vertex shader that we have saved to the file

NOTE: We can make this modifications in the Shader Editor of Render Monkey and then save the shader file, but to avoid any confusion if the display of Render Monkey changes after the modifications, in this tutorial we will do them on a separate text editor

If we look at the "Stream Mapping" entry used in the pass of this effect, we will see that it references to the main "PNTTB Stream Mapping", double click it to see the buffer stream contents (what data from the mesh is needed by the vertex shader)

The dialog shows that the data needed by the vertex shader is:

Positions data is streamed from the
Normals data is streamed from the
NORMALS buffer
UV data is streamed from the
TEXCOORD buffer 0
Tangents data is streamed from the
TANGENT buffer 0
Binormals data is streamed from the

In Ogre the Tangents are generated in a Texture coordenate buffer, so we will change the vertex shader to use the Texture Coordenate buffer 1 (the Texture Coordenate buffer 0 will be used by the diffuse channel texture)

The result will be Tangents data is streamed from the TEXCOORD buffer 1

For efficiency the Binormal of each vertex will be generated inside the vertex shader, doing this will save memory as we will not store this data in a vertex buffer with the mesh and will help the data streaming over the gpu

Remove the Binormal variable declaration

5. We will use this shader in CG (the shader currently is in HLSL) to support users of OpenGL and Direct3D9 at the same time

NOTE: They are similar languages and most of the time the code can be used with each other, but on some specific shaders the input parameters in CG should be used as arguments of the main function, while in HLSL can use as arguments or contructed as a Structure and passed to the main function

And we will add the Binormal generation code to the vertex shader

The Binormal of a vertex is the cross product of the Tangent and the Normal vectors

Add this code to the line 42 of

//** Calculate the Binormal vector

float3 binormal = cross(vsInStruct.tangent, vsInStruct.normal);
And replace all occurences of vsInStruct.binormal with binormal
Change it similar to this image
We have the shaders code ready to be used, now we will create the shader declaration
6. Create a new file in a text editor and add the shader declaration code
//CG Pixel Shader ps_2_0
fragment_program tutorial_BumpMap_ps cg
    source tutorial_BumpMap_ps.source
    profiles ps_2_0 arbfp1 fp20
    entry_point main

//CG Vertex Shader vs_2_0
vertex_program tutorial_BumpMap_vs cg
    source tutorial_BumpMap_vs.source
    profiles vs_2_0 arbvp1
    entry_point main
7. We will add Default Parameter Values to avoid setting them every time we use this shader in a material

Default parameters should be set when its value is most used in all situations or when their value dont need to be changed very often on materials

You can see what parameters are needed by the shader and their names in the shader code or with the oFusion shader parameter editor in max

Save this file as tutorial_BumpMap.program

If we copy this files (the .source and .program files) to the
oFusion/media/shaders folder of our max installation directory, the shader can be used in any material pass, but first we will add Default Parameters to the shader declaration
The vertex shader parameters names are:


And the pixel shader parameters names are:

base_map (sampler, read only, will use the first texture unit)
(sampler, read only, will use the next texture unit)

The default vertex shader parameter will be declared as:

param_named_auto view_proj_matrix worldViewProj_matrix
param_named_auto inv_view_matrix inverse_worldView_matrix
param_named_auto light_position light_position_object_space 0
param_named_auto eye_position camera_position_object_space

The default pixel shader parameter will be declared as (we map the values with the corresponding values used in Render Monkey):
param_named Ka float 0.30
Kd float 1.0
Ks float 1.0
ambient ambient_light_colour
diffuse light_diffuse_colour 0
specular light_specular_colour 0
bumpiness float 1.0
specular_power float 64.0
With this addition, the shader declaration file will contain this code:
//CG Pixel Shader ps_2_0
fragment_program tutorial_BumpMap_ps cg
    source tutorial_BumpMap_ps.source
    profiles ps_2_0 arbfp1 fp20
    entry_point main

        param_named Ka float 0.30
        param_named Kd float 1.0
        param_named Ks float 1.0
        param_named_auto ambient ambient_light_colour
        param_named_auto diffuse light_diffuse_colour 0
        param_named_auto specular light_specular_colour 0
        param_named bumpiness float 1.0
        param_named specular_power float 64.0

//CG Vertex Shader vs_2_0
vertex_program tutorial_BumpMap_vs cg
    source tutorial_BumpMap_vs.source
    profiles vs_2_0 arbvp1
    entry_point main

        param_named_auto view_proj_matrix worldViewProj_matrix
        param_named_auto inv_view_matrix inverse_worldView_matrix
        param_named_auto light_position light_position_object_space 0
        param_named_auto eye_position camera_position_object_space
Save the tutorial_BumpMap.program file with the new default parameter additions

Copy this file and the .source (the shader code) files to the
oFusion/media/shaders folder of your max installation directory

The new shaders are ready to be used in oFusion, and will be displayed in the Shader list of the pass materials

Using the newly created shader

Create a torus on the viewport

Activate the "Generate Mapping Coords." option to create texture coordinates for the mesh
Open the Object Properties panel and activate the "Generate Tangent Vectors" option for the torus mesh

As this object has only a single texture channel (used for the diffuse texture, Texture Coordenate buffer 0) the Tangents will be generated in the Texture Coordenate buffer 1

NOTE: The shader was modified to use the TEXCOORD1 buffer for the Tangents, when generating vertex tangents the next emtpy texture coord buffer will be used by the tangent generator, if your object has multiple coordenate sets you must modify the vertex shader to use the texture coord buffer assigend for the tangents
Create an omni light to illuminate the scene
Activate the oFusion viewport
Create an Ogre Material with a Technique and a Pass, assign this material to the created object

In the
Vertex Shader (Program) list control of the Pass material, select tutorial_BumpMap_vs and click on Active

In the
Pixel Shader (Program) list control of the Pass material, select tutorial_BumpMap_ps and click on Active
We know the the pixel shader needs a diffuse image map and a bump image map (we can open the shader parameter editor for the pixel shader program and see the order of the textures needed)

In Render Monkey they are the TextureStage parameters, and in the example the
Fieldstone.tga is used for the diffuse map and the FieldstoneBumpDOT3.tga is used for the bump map
Add a TextureUnit texmap in the Pass material with the Fieldstone.tga image from the "Examples\Media\Textures\" folder of ATI Render Monkey installation

Add a new TextureUnit texmap with the
FieldstoneBumpDOT3.tga image from the same folder of ATI Render Monkey installation
As we defined default parameter values, the specular bumpmap effect is inmediatly visible, and we can modify or fine tune the parameters if needed

The effect can be applied to any object as long as the texture sets are the requiered by the pixel shader
The pixel shader can report an ambiguity while compiling it, so we will fix this by changing the lines 73 and 74 (or 83 and 84 if you didnt removed and just commented out the global parameters), declaring the first parameter of the max function as float

In the
tutorial_BumpMap_ps.source file, the code looks similar to this image
The global shader parameters will be moved to the main function declaration

In the
vertex shader file, remove or comment the global parameters (the 4 initial lines)
And move them to the main function argument list (for each parameter add the "uniform" keyword and remove the "register" assign)
Apply the same process to the pixel shader file, comment or remove the global parameters
And move them to the main function argument lis
The complete scene, with the pixel and vertex shaders, can be downloaded in the Scenes section