PDA

View Full Version : Efficient vertex program texture projection?



Kaldaien
09-21-2004, 01:35 PM
Right now I'm using the fixed-function pipeline to do my projective texturing (planar)...
I'm using the following to setup my texture matrix and it works well.


glMatrixMode (GL_TEXTURE);
/*
glLoadIdentity ();
glTranslatef (0.5f, 0.5f, 0.0f);
glScalef (0.5f, 0.5f, 1.0f);
*/
glLoadMatrixf (mEnvBase.m); /* Result of the above logic is a constant matrix... */
glMultMatrixf (mEnvProj.m);
glMultMatrixf (mEnvModel.m);
glMatrixMode (GL_MODELVIEW);My question is, what's the most efficient approach to doing the same thing
in a vertex program?

Should I just keep the code as it is and multiply the texture coordinates by
the appropriate texture matrix in the vertex program? I don't want to pass
the vertex program the projection*modelview matrix (see below) for performance
reasons.

Cg provides a special projective texture lookup intrinsic for fragment programs,
that as I understand it, divides the texture matrix by its last component (equiv.
to the glTranslate/glScale logic above?). I'm assuming there's some advantage to
doing it in a fragment program that I'm just too stupid to see? It seems to me
that all of the work could be done per-vertex and you'd save a few GPU cycles
per-fragment... Am I missing something here?

I also noticed (to my surprise) that pre-multiplying the Env Projection /
Modelview matrices on the CPU every time the projector's view changes (I have
a latency of 4+ frames, to keep the pixel buffer from eating too much fillrate)
is actually 10-15% slower than doing the projection and modelview mults EVERY
FRAME w/ glMultMatrixf.

The following, which logically seems like an optimization turns out slower than
the original code:


[Update Pixel Buffer (once every 4+ frames)]
--------------------------------------------
...
const l3dMatrix& mEnvProj = world.camera.projection ();
const l3dMatrix& mEnvModel = world.camera.modelview ();

mEnvProjView = mEnvProj * mEnvModel;
...


[Project Pixel Buffer's Texture (every frame)]
----------------------------------------------
...
glLoadMatrixf (mEnvBase.m);
glMultMatrixf (mEnvProjView.m);
glMatrixMode (GL_MODELVIEW);
...Lesson learned here:
+ Don't assume fewer operations per-frame/update are always "better" :p

(The driver can take advantage of SIMD/MMX instruction sets and other optimizations
that unless you have a REALLY nice math library, could prove orders of magnitude
faster than your own code...)

Figured I'd share that little bit since it *really* surprised me :)

-NiCo-
09-22-2004, 02:42 AM
You could try the following:

automatic texture coord generation code (only has to be set when mEnvProj changes, which should not be too often.


glMatrixMode(GL_MODELVIEW);
glLoadIdentity();

glActiveTextureARB(GL_TEXTURE0_ARB);

glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
glTexGeni(GL_Q, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);

mEnv=mEnvBase*mEnvProj;

glTexGenf(GL_S, GL_EYE_PLANE, mEnv.m[0], mEnv.m[4], mEnv.m[8], mEnv.m[12]);
glTexGenf(GL_T, GL_EYE_PLANE, mEnv.m[1], mEnv.m[5], mEnv.m[9], mEnv.m[13]);
glTexGenf(GL_R, GL_EYE_PLANE, mEnv.m[2], mEnv.m[6], mEnv.m[10], mEnv.m[14]);
glTexGenf(GL_Q, GL_EYE_PLANE, mEnv.m[3], mEnv.m[7], mEnv.m[11], mEnv.m[15]);

glEnable(GL_TEXTURE_GEN_S);
glEnable(GL_TEXTURE_GEN_T);
glEnable(GL_TEXTURE_GEN_R);
glEnable(GL_TEXTURE_GEN_Q);in vertex program add the line


MOV result.texcoord[0], vertex.texcoord[0];Greetz,

Nico

sqrt[-1]
09-22-2004, 03:18 PM
Uh, isn't tex gen mode disabled when using vertex programs?

dorbie
09-22-2004, 04:11 PM
In anycase you don't need it since you can assign the vertex values to the texcoords (after modelview transform for eye space texgen) which is a very efficient texgen for something like texture projection, then you can multiply the texture coordinate by your texture matrix.