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:
- A modelview transform to orient the projection in the scene.
- A projective transform (perspective or orthogonal).
- A scale and bias to map the near clipping plane to texture coordinates.
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