//-----------------------------------------------------------------------------
// Name: ogl_dot3_bump_mapping.cpp
// Author: Kevin Harris (kevin@codesampler.com)
// Last Modified: 03/30/05
// Description: This sample demonstrates how to perform Dot3 per-pixel bump
// mapping using a normal map and the GL_DOT3_RGB_EXT
// texture-blending operation. This technique is sometimes
// referred to as per-pixel lighting or per-pixel attenuation,
// but Dot3 per-pixel bump-mapping is what most programmers
// know it as.
//
// This sample also demonstrates how to create tangent,
// binormal, and normal vectors, for each vertex of our test
// geometry (a simple cube). These vectors are used during
// rendering to define an inverse tangent matrix for each
// vertex. This has to be done because a normal-map stores its
// normals in tangent-space. Therefore, we need an inverse
// tangent matrix so we can transform our scene's light vector
// from object-space into tangent-space. Once transformed, we
// then encode this new light vector as a RGB color and pass
// it into the texture blending stage as the vertex's Diffuse
// color.
//
// Additional Notes:
//
// The phrase "Dot3" comes form the mathematical operation that
// combines a light vector with a surface normal.
//
// The phrase "Per-pixel" comes from the fact that for every
// pixel in the base texture map, we store a unique surface
// normal to light it. These surface normals are passed into the
// texture blending stage via a normal-map. A normal-map is a
// texture where normals (x,y,z) have been encoded and stored
// as (r,g,b).
//
// Control Keys: d/D - Toggle Dot3 bump mapping
// l/L - Toggle the usage of regular lighting in addition
// to the per-pixel lighting effect of bump mapping.
// m/M - Toggle motion of point light
// Up Arrow - Move the test cube closer
// Down Arrow - Move the test cube away
//-----------------------------------------------------------------------------
#define STRICT
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <mmsystem.h>
// Do this to access M_PI, which is not officially part of the C/C++ standard.
#define _USE_MATH_DEFINES
#include <math.h>
#include <stdlib.h>
#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glaux.h>
#include "geometry.h"
#include "matrix4x4f.h"
#include "vector3f.h"
#include "resource.h"
//-----------------------------------------------------------------------------
// FUNCTION POINTERS FOR OPENGL EXTENSIONS
//-----------------------------------------------------------------------------
// For convenience, this project ships with its own "glext.h" extension header
// file. If you have trouble running this sample, it may be that this "glext.h"
// file is defining something that your hardware doesn�t actually support.
// Try recompiling the sample using your own local, vendor-specific "glext.h"
// header file.
#include "glext.h" // Sample's header file
//#include <GL/glext.h> // Your local header file
PFNGLACTIVETEXTUREPROC glActiveTexture = NULL;
PFNGLMULTITEXCOORD2FPROC glMultiTexCoord2f = NULL;
PFNGLCLIENTACTIVETEXTUREPROC glClientActiveTexture = NULL;
//-----------------------------------------------------------------------------
// GLOBALS
//-----------------------------------------------------------------------------
HDC g_hDC = NULL;
HGLRC g_hRC = NULL;
HWND g_hWnd = NULL;
GLuint g_textureID = -1;
GLuint g_normalmapTextureID = -1;
bool g_bDoDot3BumpMapping = true;
bool g_bMoveLightAbout = true;
bool g_bToggleRegularLighting = false;
GLfloat g_lightPosition[] = { 0.0f, 0.0f, 0.0f, 1.0f }; // Point Light's position
float g_fDistance = -5.0f;
float g_fSpinX = 0.0f;
float g_fSpinY = 0.0f;
float g_fElpasedTime;
double g_dCurTime;
double g_dLastTime;
struct Vertex
{
float tu, tv;
float r, g, b, a;
float nx, ny, nz;
float x, y, z;
};
const int NUM_VERTICES = 24;
Vertex g_cubeVertices[NUM_VERTICES] =
{
// tu tv r g b a nx ny nz x y z
// Front face
{ 0.0f,0.0f, 1.0f,1.0f,1.0f,1.0f, 0.0f, 0.0f, 1.0f, -1.0f,-1.0f, 1.0f },
{ 1.0f,0.0f, 1.0f,1.0f,1.0f,1.0f, 0.0f, 0.0f, 1.0f, 1.0f,-1.0f, 1.0f },
{ 1.0f,1.0f, 1.0f,1.0f,1.0f,1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f },
{ 0.0f,1.0f, 1.0f,1.0f,1.0f,1.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f, 1.0f },
// Back face
{ 1.0f,0.0f, 1.0f,1.0f,1.0f,1.0f, 0.0f, 0.0f,-1.0f, -1.0f,-1.0f,-1.0f },
{ 1.0f,1.0f, 1.0f,1.0f,1.0f,1.0f, 0.0f, 0.0f,-1.0f, -1.0f, 1.0f,-1.0f },
{ 0.0f,1.0f, 1.0f,1.0f,1.0f,1.0f, 0.0f, 0.0f,-1.0f, 1.0f, 1.0f,-1.0f },
{ 0.0f,0.0f, 1.0f,1.0f,1.0f,1.0f, 0.0f, 0.0f,-1.0f, 1.0f,-1.0f,-1.0f },
// Top face
{ 0.0f,1.0f, 1.0f,1.0f,1.0f,1.0f, 0.0f, 1.0f, 0.0f, -1.0f, 1.0f,-1.0f },
{ 0.0f,0.0f, 1.0f,1.0f,1.0f,1.0f, 0.0f, 1.0f, 0.0f, -1.0f, 1.0f, 1.0f },
{ 1.0f,0.0f, 1.0f,1.0f,1.0f,1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f },
{ 1.0f,1.0f, 1.0f,1.0f,1.0f,1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f,-1.0f },
// Bottom face
{ 1.0f,1.0f, 1.0f,1.0f,1.0f,1.0f, 0.0f,-1.0f, 0.0f, -1.0f,-1.0f,-1.0f },
{ 0.0f,1.0f, 1.0f,1.0f,1.0f,1.0f, 0.0f,-1.0f, 0.0f, 1.0f,-1.0f,-1.0f },
{ 0.0f,0.0f, 1.0f,1.0f,1.0f,1.0f, 0.0f,-1.0f, 0.0f, 1.0f,-1.0f, 1.0f },
{ 1.0f,0.0f, 1.0f,1.0f,1.0f,1.0f, 0.0f,-1.0f, 0.0f, -1.0f,-1.0f, 1.0f },
// Right face
{ 1.0f,0.0f, 1.0f,1.0f,1.0f,1.0f, 1.0f, 0.0f, 0.0f, 1.0f,-1.0f,-1.0f },
{ 1.0f,1.0f, 1.0f,1.0f,1.0f,1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f,-1.0f },
{ 0.0f,1.0f, 1.0f,1.0f,1.0f,1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f },
{ 0.0f,0.0f, 1.0f,1.0f,1.0f,1.0f, 1.0f, 0.0f, 0.0f, 1.0f,-1.0f, 1.0f },
// Left face
{ 0.0f,0.0f, 1.0f,1.0f,1.0f,1.0f, -1.0f, 0.0f, 0.0f, -1.0f,-1.0f,-1.0f },
{ 1.0f,0.0f, 1.0f,1.0f,1.0f,1.0f, -1.0f, 0.0f, 0.0f, -1.0f,-1.0f, 1.0f },
{ 1.0f,1.0f, 1.0f,1.0f,1.0f,1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 1.0f, 1.0f },
{ 0.0f,1.0f, 1.0f,1.0f,1.0f,1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 1.0f,-1.0f }
};
// For each vertex defined above, we'll need to create a Tangent, BiNormal, and
// Normal vector, which together define a tangent matrix for Dot3 bump mapping.
vector3f g_vTangents[NUM_VERTICES];
vector3f g_vBiNormals[NUM_VERTICES];
vector3f g_vNormals[NUM_VERTICES];
//-----------------------------------------------------------------------------
// PROTOTYPES
//-----------------------------------------------------------------------------
int WINAPI WinMain(HINSTANCE g_hInstance,HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow);
LRESULT CALLBACK WindowProc(HWND g_hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
void loadTexture(void);
void init(void);
void render(void);
void shutDown(void);
vector3f scaleAndBiasVectorAsRGBColor(vector3f* vVector);
void computeTangentsMatricesForEachVertex(void);
void createTangentSpaceVectors( vector3f *v1, vector3f *v2, vector3f *v3,
float v1u, float v1v, float v2u, float v2v, float v3u, float v3v,
vector3f *vTangent, vector3f *vBiNormal, vector3f *vNormal );
//-----------------------------------------------------------------------------
// Name: WinMain()
// Desc: The application's entry point
//----------------------------