Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Projecting a texture in OpenGL

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
like image 962
CakeMaster Avatar asked Sep 03 '10 01:09

CakeMaster


1 Answers

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.

like image 160
Adrian Lopez Avatar answered Nov 08 '22 02:11

Adrian Lopez