Original Post
I want to implement shadow mapping, but in order to do this I would like to understand (and implement) projective textures. So far, I've got a lot of docs (from nVidia, Ati, and many others) and a couple of topics here on gd, but I wasn't able to figure them out. I there somewhere a very good and easy tutorial with opengl code that explains how to project a texture onto a mesh? What I understood so far is that I have to build some matrices that would tell opengl texture coordinates routines how to calculate the texture coordinates. Not very much, that is. I've found a small class that should be able to enable a texture projection, but I dont' know how to use it (when I try, I get a black screen. Making it work could be a starting point for me to understand the theory behind: I use it in the following way:
// Date: 25/07/2004
// By: Lukas Heise
// ###############################################################################
// Usage Instructions
// ==================
// ProjectiveTexture myProjTexture;
// myProjTexture.SetupTexture(myTexture);
// myProjTexture.SetupMatrix(position,rotation,fov);
//
// in the main loop...
//
// RenderScene(RENDER_NORMALY);
// myProjTexture.BeginRender();
// RenderScene(DONT_BIND_TEXTURES);
// myProjTexture.EndRender();
// ###############################################################################
#ifndef __PROJTEXTURE_H
#define __PROJTEXTURE_H
#include <gl/gl.h>
class ProjectiveTexture
{
private:
UINT textureID;
float matrix[16];
double clipPlane[4];
public:
ProjectiveTexture()
{
}
virtual ~ProjectiveTexture()
{
glDeleteTextures(1,&textureID);
}
void SetupTexture(UINT id)
{
textureID = id;
glBindTexture(GL_TEXTURE_2D,id);
glTexEnvi(GL_TEXTURE_2D,GL_TEXTURE_ENV_MODE,GL_ADD); // add the colors from this texture to the scene
glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
}
void SetupMatrix(float* Position, float* Rotation, float FOV)
{
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
static float biasMatrix[16] = { 0.5f, 0.0f, 0.0f, 0.0f,
0.0f, 0.5f, 0.0f, 0.0f,
0.0f, 0.0f, 0.5f, 0.0f,
0.5f, 0.5f, 0.5f, 1.0f };
// construct the projection matrix (to make things easy let's use the math that OpenGL provides us with)
glLoadMatrixf(biasMatrix);
gluPerspective(FOV,1.0f,1.0f,2.0f);
glRotatef(Rotation[0],1,0,0);
glRotatef(Rotation[1],0,1,0);
glRotatef(Rotation[2],0,0,1);
glTranslatef(Position[0],Position[1],Position[2]);
glGetFloatv(GL_MODELVIEW_MATRIX,matrix);
// to eliminate reverse projection we need to construct a clipping plane
clipPlane[0] = (double)matrix[3];
clipPlane[1] = (double)matrix[7];
clipPlane[2] = (double)matrix[11];
clipPlane[3] = (double)matrix[15];
glPopMatrix();
}
void BeginRender()
{
static float planeS[4] = { 1.0f, 0.0f, 0.0f, 0.0f };
static float planeT[4] = { 0.0f, 1.0f, 0.0f, 0.0f };
static float planeR[4] = { 0.0f, 0.0f, 1.0f, 0.0f };
static float planeQ[4] = { 0.0f, 0.0f, 0.0f, 1.0f };
glPushAttrib(GL_ENABLE_BIT);
glBindTexture(GL_TEXTURE_2D,textureID);
glTexGeni(GL_S,GL_TEXTURE_GEN_MODE,GL_EYE_LINEAR);
glTexGeni(GL_T,GL_TEXTURE_GEN_MODE,GL_EYE_LINEAR);
glTexGeni(GL_R,GL_TEXTURE_GEN_MODE,GL_EYE_LINEAR);
glTexGeni(GL_Q,GL_TEXTURE_GEN_MODE,GL_EYE_LINEAR);
glTexGenfv(GL_S,GL_EYE_PLANE,planeS);
glTexGenfv(GL_T,GL_EYE_PLANE,planeT);
glTexGenfv(GL_R,GL_EYE_PLANE,planeR);
glTexGenfv(GL_Q,GL_EYE_PLANE,planeQ);
glEnable(GL_TEXTURE_GEN_S);
glEnable(GL_TEXTURE_GEN_T);
glEnable(GL_TEXTURE_GEN_R);
glEnable(GL_TEXTURE_GEN_Q);
glDepthMask(GL_FALSE);
glEnable(GL_BLEND);
glEnable(GL_ALPHA_TEST);
glEnable(GL_CLIP_PLANE0);
glAlphaFunc(GL_GREATER,0.0f); // we decide not to render the transparent areas of our texture (alpha value is less or equal 0.05)
glBlendFunc(GL_DST_COLOR,GL_SRC_COLOR); // this blending effect looks good but do experiment with others!
glClipPlane(GL_CLIP_PLANE0,clipPlane);
glMatrixMode(GL_TEXTURE);
glPushMatrix();
glLoadMatrixf(matrix); // load our projection matrix
}
void EndRender()
{
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
glDisable(GL_CLIP_PLANE0);
glDisable(GL_ALPHA_TEST);
glDisable(GL_BLEND);
glDepthMask(GL_TRUE);
glDisable(GL_TEXTURE_GEN_S);
glDisable(GL_TEXTURE_GEN_T);
glDisable(GL_TEXTURE_GEN_R);
glDisable(GL_TEXTURE_GEN_Q);
glPopAttrib();
}
};
#endif
ProjectiveTexture myProjTexture;
myProjTexture.SetupTexture(1);
float pos[] = {1.0,1.0,-1.0,1.0};
float r[] = {0.0,0.0,1.0,1.0};
myProjTexture.SetupMatrix(pos,r,45.0);
.
.
.
//Render the frame
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
Render();
myProjTexture.BeginRender();
Render();
myProjTexture.EndRender();
SDL_GL_SwapBuffers();