Hi,
A while back I implemented projective texturing using texgen, but I always felt that perhaps that i’d misunderstood how it was meant to work. In addition ther appears to be a bug, where if the projected texture has mipmaps, I get parts of the texture outside the projection frustrum, even with clamping. From visual inspection it looks like it occurs at the point where the textured mesh passes across the near plane of the projection. In the sample jpg, the bug is the thick yellow band bottom right - this vanishes if i disable mipmapping. mipmap bug
So any advice on why mipmaps causes the visual artifact? Any way to fix it? I tried using Clamp_to_edge as I think that provided the correct behaviour I wanted.
Secondly i’m interested in comments on the texgen code. I’ve recently read through several similar questions in this forum, but they left me a bit more confused than when I started. One particular element was the repeated comment that you’d only have to update texgen if the modelview changed. But don’t you have to supply the texgen everytime you want to render the projected texture? Sure i['m missing something obvious there, perhaps just misunderstood what was meant. I feel I understand the process of projecting the textures, but not how to represent it in code (or rather using the correct code) i’ll admit I got this example working originally by simply testing out different approaches from code i’d seen online.
Anyway the code is as follows, but I should point out this is not from within an actual game engine, instead its run on the openGL stream (via GLtrace), because i’m adding this functionailty to an exsiting product. (sure not the best way, but it works). Because i’m relying solely on the openGL stream I can’t pass explicit data, so i have to use some creative means of obtaining data. Don’t worry about how I get this data, its not relevant, but i’ll quickly explain. Lets say then that in the 3Dworld I have a projector model, this projector, projects a texture onto whatever it faces. To get the projection matrix and model matrix of this projector model I create a dummy camera and a dummy model. The dummy model is placed at the world origin so that its modelview matrix represents the projector’s model actual position/orientation (inverse? - been a while since i came up with this). I flag this model and store the current projection matrix and modelview matrix for use later.
// Dump current projection matrix into LUT via glexIndex
glGetFloatv(GL_PROJECTION_MATRIX, glexProjectionMTX[glexIndex]);
// Dump current modelview into LUT
// The model must be at world origin, this means the modelview matrix
// represents the position and oreitnation of the projection source (camera/light whatever)
glGetFloatv(GL_MODELVIEW_MATRIX, glexModelMTX[glexIndex]);
The TexGen code is as follows.
Out of interest is there any specific order requirements to glEnable, glTexGeni, glTexGenfv? I’ve seen the order vary in almost everysample i’ve encountered.
Wether there is or not, is there any standard conversion for the order?
Just interested if i’m fundamentally misunderstanding what i’m meant to be doing, but it just happens to work
Perhaps the code can be simplified, although I realise that I can store the loadidentity matrix, scale and translate in precalucated matrix and save time there.
thanks
// TexGen props set elsewhere
GLfloat glexPS[4] = {1, 0, 0, 0};
GLfloat glexPT[4] = {0, 1, 0, 0};
GLfloat glexPR[4] = {0, 0, 1, 0};
GLfloat glexPQ[4] = {0, 0, 0, 1};
// Projective Texturing: World Space Based
glActiveTextureARB(GL_TEXTURE1_ARB);
glMatrixMode(GL_TEXTURE);
glPushMatrix(); // Later on I pop this back so openGL is in the same state the application thinks its in - just in case
glLoadIdentity();
glTranslatef(0.5f, 0.5f, 0.0f);
glScalef(0.5f, 0.5f, 1.0f);
glMultMatrixf(glexProjectionMTX[glexIndex]); // Get projection matrix from stored data
glMultMatrixf(glexModelMTX[glexIndex]);
glMatrixMode(GL_MODELVIEW);
glEnable(GL_TEXTURE_GEN_S);
glEnable(GL_TEXTURE_GEN_T);
glEnable(GL_TEXTURE_GEN_R);
glEnable(GL_TEXTURE_GEN_Q);
glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR); // GL_OBJECT_LINEAR 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, glexPS);
glTexGenfv(GL_T, GL_EYE_PLANE, glexPT);
glTexGenfv(GL_R, GL_EYE_PLANE, glexPR);
glTexGenfv(GL_Q, GL_EYE_PLANE, glexPQ);
// Fix clamping on ATI
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE);