views:

207

answers:

1

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) alt text

And then I realised yes, of course, it needs to be a projective transformation. According to these notes:

  1. A modelview transform to orient the projection in the scene.
  2. A projective transform (perspective or orthogonal).
  3. 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
+2  A: 

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.

Adrian Lopez
Thanks very much for all this, I am now trying to implement it.
CakeMaster
I'm not having much luck. My quad is textured with a single color - it looks like it might be extremely zoomed-in, so we're just seeing one pixel. I'll expand the question
CakeMaster
I notice in your code that you haven't specified the coefficients (via glTexGen) for any of the texture coordinate components. I also notice you haven't set the GL_TEXTURE matrix. You should set the glTexGen coefficients to something like (1.0, 0.0, 0.0, 0.0) for S, (0.0, 1.0, 0.0, 0.0) for T, etc. This will project your eye space coordinates directly into object space, and you can then apply your view and projection transforms to the GL_TEXTURE matrix to transform from object space into texture space.
Adrian Lopez
Also, for your particular purposes you want the GL_MODELVIEW matrix to remain the same before and after the call to glTexGen where you set the coefficients. To get the proper texture coordinates, apply your modelview and projection transforms to GL_TEXTURE like you did with GL_MODELVIEW/GL_PROJECTION and don't forget to scale and transform the s and t components by 0.5 as the final step so that the final texture coordinates lie inside the (0,1) range.
Adrian Lopez
Thank again. Yes, looks much more reasonable now, but the texture is tiled about 4 times (ie comes out too small), and the aspect ratio seems off. I will update details again, maybe there's one last things I've missed?
CakeMaster
I've edited my answer to fix various errors in my explanation and to provide a better answer to your original question.
Adrian Lopez