dhpoware logo
home products source demos contact us
navbar navbar
box top left corner box top right corner
Direct3D 9 Normal Mapping Demo.

This Windows demo implements tangent space normal mapping using a series of Direct3D 9 High Level Shading Language (HLSL) shaders. A single D3DX Effect file (.fx) is provided with three techniques that implements normal mapping for each of the three Direct3D light types: directional, point, and spot lights.

The demo consists of a single cube centered at the world origin. The cube consists of only 6 faces with each face composed of 2 triangles.

Tangent space normal mapping involves evaluating the lighting equations per pixel in the surface local coordinate space of the normal map texture. Rather than using the cube's interpolated vertex normals tangent space normal mapping uses the normals from the normal map texture instead. Doing this allows additional surface detail to be applied to each face of the cube without requiring extra geometry to be added to each face.

The lighting vectors (light, view, and half-angle vectors) are transformed into the normal map texture's tangent space using a rotation matrix. This rotation matrix must be calculated for each face of the cube. Each face has its own rotation matrix because each face is uniquely texture mapped to the normal map texture and the rotation matrix must take this into consideration. The rotation matrix is constructed using each face's tangent, bitangent, and normal vectors.

This demo was built using the June 2010 update of the Microsoft DirectX SDK. The required end-user runtimes can be downloaded here.

1. This demo requires shader model 2.0 or higher support.
2. This demo requires the Visual C++ 2010 Library Runtimes. Download instructions can be found here


zip file Download executable, source, and Visual C++ 2010 solution files.

Change History:

10 July 2010.
Added missing .vcxproj.filters file to the project.

13 June 2010.
Updated solution to Microsoft Visual Studio 2010.

25 March 2008.
Fixed memory leak in CreateNullTexture() function where 'pSurface' was not being released.

2 February 2008.
Updated solution to Microsoft Visual Studio 2008.

4 January 2008.
main.cpp: Added mouse wheel support. Updated DOLLY_MIN and DOLLY_MAX values. Renamed MOUSE_ORBIT_SPEED to MOUSE_ROTATE_SPEED. Added MOUSE_WHEEL_DOLLY_SPEED constant. Added g_cubePos global variable. Removed UpdateLighting() function. In ProcessMouseInput() function renamed CameraMode enum to MouseMode. Renamed enum constants accordingly. The ProcessMouseInput() function no longer updates g_cameraPos. It now updates g_cubePos. The camera is now fixed in space. Only the cube moves now. Updated RenderText() function to display mouse wheel help message. In UpdateEffect() function the calculated world matrix now includes a translation transformation to position the cube in the scene.

normal_mapping.fx: Changed all vector outputs from the vertex shaders to float3. Added diffuse and specular outputs for the vertex shaders. Fixed bug in the vertex shaders where the worldInverseTransposeMatrix was not being cast to a float3x3. Updated pixel shaders to use the float3 vector outputs from the vertex shaders. Updated pixel shaders to use the diffuse and specular outputs from the vertex shaders.

2 January 2008.
Updated normal_map.jpg texture.

normal_mapping.fx: Fixed bug where all 4 components of the normal map normal was being normalized instead of just the rgb components. Removed use of the lit() intrinsic function. Removed separate specular support.

main.cpp: Changed the material shininess.

26 December 2007.
normal_mapping.fx: Replaced the point and spot lighting attenuation model with a simpler model based on a light radius. Fixed a bug in the directional lighting vertex shader where the half angle vector was being incorrectly calculated.

main.cpp: Updated Light structure to use the new attenuation model in the normal_mapping.fx shader. Improved font rendering to support ClearType quality when available. Changed the output text on the screen. Renamed DrawFrame(), DrawText(), and DrawCube() to RenderFrame(), RenderText(), and RenderCube().

5 November 2007.
This is a major rewrite of the Direct3D 9 HLSL Bump Mapping demo. This demo has now been renamed Direct3D 9 Normal Mapping demo to more accurately describe the shader technique that it implements. This new demo contains many critical bug fixes.

main.cpp: The cube model no longer contains a bitangent vertex attribute. The bitangent is now calculated in the vertex shader. Only the tangent vector is calculated and stored in the cube now. The CalcTangentVector() function now calculates the handedness of the local tangent space coordinate system at each vertex and stores it in the tangent vector's 'w' component.

normal_mapping.fx: The bitangent vector is now calculated in the vertex shader. Fixed a bug where the transpose of the tbnMatrix was being used.

15 January 2007.
bump_mapping.fx: Added 3 new debugging techniques to disable the color map texture. Removed all semantics except for those used by the vertex and pixel shader input and output structures. Renamed the texture 'decalMapTexture' to 'colorMapTexture'. Renamed the sampler 'decalMap' to 'colorMap'. Updated the pixel shaders to normalize the normal fetched from the normal map. This gives a slight improvement to the visual quality. Refactored all pixel shaders to use the lit() HLSL function. Optimized the calculation of the spotlight effect in the PS_SpotLighting() pixel shader.

main.cpp: Much of the code has been updated to more closely match the Direct3D 9 HLSL Parallax Bump Mapping demo. Added the ability to enable and disable the color map texture. This hooks into the new debug techniques in the bump_mapping.fx effect file. Added the ability to view the tangent space basis vectors for each face of the cube. Updated all references to the 'decalMap' HLSL sampler variable to 'colorMap'. Renamed 'g_pDecalMap' to 'g_pColorMap'. Refactored the cube model creation into the function GenerateCube().

2 January 2007.
main.cpp: Fixed a possible resource leak in LoadShader() function where the ID3DXBuffer pointer was not being released. The executable has been rebuilt using Visual C++ 2005 with Visual Studio 2005 Service Pack 1 applied.

1 January 2007.
bump_mapping.fx: Fixed a bug in all 3 vertex shaders where the viewDir and lightDir vectors were being incorrectly transformed using the transposed tbnMatrix. HLSL matrices are column major by default.

main.cpp: Added event handler for the WM_SIZE message. Fixes an issue with the aspect ratio being incorrect after a full screen toggle.

box bottom left corner content box box bottom right corner
logo logo