Mathematics of glTexGen

From OpenGL Wiki
Revision as of 03:43, 26 October 2008 by V-man (talk | contribs)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search

When you enable one of the glTexGen modes, how are the texcoords computed?
If you will be using shaders, keep in mind that the vertex shader overrides this functionality, which means you have to do the work yourself.

Calculating for GL_OBJECT_LINEAR on the CPU

OpenGL takes the vertex and does a 4D dot product with the plane equation. Each component has its own plane equation.
GL_S has its own plane equation.
GL_R has its own plane equation.
GL_T has its own plane equation.
Your code would look something like this

 for(i=0; i<total; i++)
 {
   myTexCoord[i].s = dot4D(myVertex[i], myPlane_S);
   myTexCoord[i].t = dot4D(myVertex[i], myPlane_T);
 }

Calculating for GL_EYE_LINEAR on the CPU

In this case, you need to transform each vertex to eye space and then do the 4D dot product.
You need to transform the planes to eye space as well. Your code would look something like this

 myEyePlane_S = VectorTimesMatrix(myPlane_S, InverseModelviewMatrix);
 myEyePlane_T = VectorTimesMatrix(myPlane_T, InverseModelviewMatrix);
 //Now that we have myEyePlane_S and myEyePlane_T...
 for(i=0; i<total; i++)
 {
   myEyeVertex = MatrixTimesVector(ModelviewMatrix, myVertex[i]);
   myTexCoord[i].s = dot4D(myEyeVertex, myEyePlane_S);
   myTexCoord[i].t = dot4D(myEyeVertex, myEyePlane_T);
 }

Calculating for GL_SPHERE_MAP on the CPU

Used for sampling 2D textures.
In this one, we are basically calculating a reflection vector, then offsetting by 0.5 and using these as texcoords.

 for(i=0; i<total; i++)
 {
   myEyeVertex = MatrixTimesVector(ModelviewMatrix, myVertex[i]);
   myEyeVertex = Normalize(myEyeVertex);
   myEyeNormal = VectorTimesMatrix(myNormal[i], InverseModelviewMatrix);
   reflectionVector = myEyeVertex - myEyeNormal * 2.0 * dot3D(myEyeNormal, myEyeNormal);
   reflectionVector.z += 1.0;
   m = 1.0 / 2.0 * sqrt(dot3D(reflectionVector, reflectionVector));
   //I am emphasizing that we write to s and t. Used to sample a 2D texture.
   myTexCoord[i].s = reflectionVector.x * m + 0.5;
   myTexCoord[i].t = reflectionVector.y * m + 0.5;
 }

Calculating for GL_REFLECTION_MAP on the CPU

Used for sampling cubemaps.

 for(i=0; i<total; i++)
 {
   myEyeVertex = MatrixTimesVector(ModelviewMatrix, myVertex[i]);
   myEyeVertex = Normalize(myEyeVertex);
   myEyeNormal = VectorTimesMatrix(myNormal[i], InverseModelviewMatrix);
   dotResult = 2.0 * dot3D(myEyeNormal, myEyeNormal);
   //I am emphasizing that we write to s and t and r. Used to sample a cubemap.
   myTexCoord[i].s = myEyeVertex.x - myEyeNormal.x * dotResult;
   myTexCoord[i].t = myEyeVertex.y - myEyeNormal.y * dotResult;
   myTexCoord[i].r = myEyeVertex.z - myEyeNormal.z * dotResult;
 }