FIXED by setting near clipping plane to 1, rather than 0 (not sure why it was like that to start with). See the question for skeleton code, and Adrian's answer for how and why this works.
I have a few different camera positions, and my scene consists of a single quad.
The quad is such that it projects exactly onto the viewport/window in the first frame. I want to project a texture from this camera position onto the quad. The texture also covers the viewport exactly.
The first thing I did was
// GL_QUADS...
glTexCoord2f( /*one corner of s,t space*/);
glVertex3f(/* appropriate vertex */);;
and ended up with something like (picture not mine)
And then I realised yes, of course, it needs to be a projective transformation. According to these notes:
Now that it works, here's a rough implementation of the code:
// in init code
glEnable(GL_TEXTURE_2D);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
double ratio = width/height;
// set up FROM modelview matrix
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluPerspective(pcam._fov/ratio, ratio, 1, far_z);
gluLookAt(/* FROM camera's parameters */);
glTexGeni(GL_Q, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR); //S, T, R and Q
GLfloat Splane[] = {1.f, 0.f, 0.f, 0.f}; //S, T, R and Q, diagonal
glTexGenfv(GL_S,GL_EYE_PLANE,Splane); //S, T, R and Q
// -- load and bind texture --
glEnable(GL_TEXTURE_GEN_S); //S, T, R and Q
// scale and bias
glMatrixMode(GL_TEXTURE);
glPushMatrix();
glLoadIdentity();
glTranslatef(0.5,0.5,0.0);
glScalef(0.5,0.5,1);
gluPerspective(cam._fov/ratio, ratio, 1, far_z);
gluLookAt(/* TO camera's parameters */);
glBegin(GL_QUADS);
glVertex3f(/* for each vertex */);
glEnd();
glDisable(GL_TEXTURE_GEN_S); //S, T, R and Q
Take a look at the documentation for glTexGen (in your case, you want to use GL_EYE_LINEAR
along with an appropriate set of coefficients as described below) and glEnable(GL_TEXTURE_GEN_*
). When you enable the texgen feature for particular texture coordinate components (S, T, R and/or Q), the values you specify for those components (via glTexCoord
) are ignored and texture coordinates are instead generated according to the specified glTexGen
mode.
When computing texture coordinates via GL_EYE_LINEAR
, vertex coordinates are first transformed into eye space by the current GL_MODELVIEW
matrix. Once in eye space, for each enabled component (S, T, R, Q), the vertex coordinates are transformed by the inverse of the GL_MODELVIEW
matrix as defined at the time of the call to glTexGen
, and the dot product between the resulting coordinates and the coefficients sent to glTexGen
is then obtained. For each enabled component, the resulting scalar values become the corresponding components (S, T, R and/or Q) of the texture coordinates, which are finally transformed by the GL_TEXTURE
matrix to produce the final texture coordinates.
For each texture component, the coefficients (a, b, c, d) sent to glTexGen
define a plane ax + by + cz + d = 0. Assuming (a, b, c) is a vector of unit length, the result of the dot product operation described above represents the distance between this plane and the vertex being processed. If GL_EYE_LINEAR
is enabled for all four texture components and the plane equations for S, T, R and Q are defined respectively as (1.0, 0.0, 0.0, 0.0), (0.0, 1.0, 0.0, 0.0), (0.0, 0.0, 1.0, 0.0), and (0.0, 0.0, 0.0, 1.0), the texture coordinates produced for each texture component are then exactly the same as the original object-space vertex coordinates. Thus, the GL_TEXTURE
matrix should contain whatever operations are needed to transform these coordinates from object space to texture space: modeling, viewing and projection transforms to convert from object coordinates to normalized device coordinates, plus scale and bias transforms to convert from normalized device coordinates to texture space.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With