dhpoware logo
home products source demos contact us
navbar navbar
box top left corner box top right corner
OpenGL 2.0 Shading Language Normal Mapping Demo.

This Windows demo implements tangent space normal mapping using a series of OpenGL Shading Language (GLSL) shader programs. Separate normal mapping shader programs are provided for each of the three OpenGL 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 quads.

Tangent space normal mapping involves evaluating the lighting equations per fragment 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.

To learn how to normal map an arbitrary 3D model check out the OpenGL OBJ Viewer demo.

1. This is an OpenGL 2.0 demo. This demo will not run on OpenGL 1.x hardware.
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.

1 April 2008.
gl_font.cpp: Fixed bug in drawTextEnd() method where the vertex buffer was not being unmapped when there's no text to draw. Thanks goes to Ari Ohvo for spotting this bug.

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

11 January 2008.
The demo has been updated to include the light attenuation calculations from the OpenGL 2.0 Shading Language Attenuation Demo.

main.cpp: Added LIGHT_RADIUS constant. Updated RenderFrame() function to set the lightRadius uniform variable in the point and spot lighting shaders.

normal_mapping_point.glsl: Replaced attenuation calculations with one based on a light radius. Added a lightRadius uniform variable.

normal_mapping_spot.glsl: Replaced attenuation calculations with one based on a light radius. Added a lightRadius uniform variable.

7 January 2008.
This is a minor update to include proper text rendering.

main.cpp: Removed user instruction in file header comments. Changed defined constants to global constant variables. Changed g_maxAnisotrophy from a float to an integer. Added g_displayHelp and g_font global variables. Removed ExtensionSupported() function. Added overloaded LoadTexture() function. Renamed DrawCube() function to RenderCube(). Renamed DrawFrame() function to RenderFrame(). Added RenderText() function. Removed support for wire frame display mode. No longer updates the window caption.

5 November 2007.
main.cpp: Updated the tangent member of the Vertex structure to include a 'w' component that stores the handedness of the local tangent space coordinate system at that vertex. The CalcTangentVector() function has been updated to calculate the handedness.

All of the shaders have been updated to use the handedness stored in the tangent vertex attribute.

Please note that these shaders have been written to use normal maps with the y-axis oriented bottom to top (as per OpenGL conventions). When generating normal maps for use with these shaders please ensure that you invert the y-axis before generating the normal maps in your content creation applications.

23 October 2007.
main.cpp: Fixed a bug in CalcTangentVector() where the inverse of the determinant should have been used to calculate the tangent vector instead of the determinant.

21 October 2007.
This is a major rewrite of the OpenGL 2.0 Shading Language Bump Mapping demo. The demo has now been renamed to OpenGL 2.0 Shading Language 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 demo is now Vista friendly.

Fixed a bug in all three shaders where the tbnMatrix rotation matrix was being incorrectly calculated. This was causing the normal mapped surface to be incorrectly lit.

8 December 2006.
main.cpp: Removed the cube's silver material. The cube is now rendered using OpenGL's default material properties. The clear color was changed to CornflowerBlue.

18 November 2006.
Fixed a bug in all three shaders where the light direction, and view direction vectors were being incorrectly normalized in the vertex shader. This was causing the interpolated direction of these vectors to be incorrect. Also fixed a bug in the point and spot light shaders where the attenuation was incorrectly calculated using the normalized light direction from the vertex shader.

main.cpp: The UpdateLighting() function was not being called when the camera was being dollied. This was causing the spot light's cone to remain fixed in size as the camera was being dollied.

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