Projective texturing

Started by
4 comments, last by _the_phantom_ 19 years, 10 months ago
ok, this is slowly driving me crazy and I've reached the point where i've spent far too long trying to work out the problem, i'm starting to go blind due to lack of sleep and frustation is bring on a headache, mostly coz I have this horrible feeling its going to be a simple answer to my question [crying] Ok, having read the thread here about Water reflections between Yann and Mephs I thought i'd have a go at producing a reflection on a plane using a projected texture myself. So I went about modifiying a test app i've got and butchered some GLSL shadow mapping code to do the projective bit, cross referenced with the thread above, a book and google. First problem to hint, for some reason my RTT wasnt Rendering, but I thought i'll forgo that problem for now, instead deciding to concetrate on the issue of making sure my projectivive texture coordinates where in the right range, so at least i knew that bit was right, the outcome was this (the image is textured onto a quad which extends -5,-5 => 5,5 on the XZ plane where Y=0 to try to make my life easier). Now, unless i'm going crazy, if my texture matrix and GLSL programs were right, there should only be one ghost on the quad and it shouldnt be sheared like that. The image in question is a 128*128*32 texture, which is fine and perfectly alined on other objects which are normaly in scene. the texture is setup thusly

glBindTexture(GL_TEXTURE_2D, texture[1]);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D,GL_GENERATE_MIPMAP,GL_TRUE);
glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA8,psimage->getWidth(),psimage->getHeight(),0,GL_RGBA,GL_UNSIGNED_BYTE,(unsigned char *)psimage->getPixels());
I'm using the following code to setup the texture matrix to perform the projection

SetCamera();   // sets camera up so its 4 units up, 14 back and rotated 45 degrees downwards on the X axis
glActiveTextureARB(GL_TEXTURE0_ARB);	
glEnable(GL_TEXTURE_2D);	
// bind reflection texture to unit zero
ReflectionProg->useIt();
ReflectionProg->sendUniform("reflectTex", 0);	// tell the programs where to find the texture
glMatrixMode(GL_TEXTURE);
{
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
ReflectScene();
glGetFloatv(GL_MODELVIEW_MATRIX,viewMatrix);
glPopMatrix();

glMatrixMode(GL_PROJECTION);
glGetFloatv(GL_PROJECTION_MATRIX,ProjMatrix);
glMatrixMode(GL_TEXTURE);
glLoadMatrixf(viewMatrix);
glMultMatrixf(ProjMatrix);
glMultMatrixf(remapMatrix);									
}
glMatrixMode(GL_MODELVIEW);
glBindTexture(GL_TEXTURE_2D, texture[1]);
DrawReflectionSurface();
ReflectionProg->disableIt();
glMatrixMode(GL_TEXTURE);
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
ReflectionProg is an object which holds the vertex and fragment programs (GLSL) the various matrices are all glfloat var[16]. remapMatrix is defined thus:

GLfloat remapMatrix[] = {0.5,0.0,0.0,0.5,
                         0.0,0.5,0.0,0.5,
			 0.0,0.0,0.5,0.5,
			 0.0,0.0,0.0,1};
and the GLSL progs are as follows:

// Vertex
varying vec4 projCoord;

void main()
{
  projCoord = gl_TextureMatrix[0] * gl_Vertex;
  gl_FrontColor = vec4(1.0,1.0,1.0,1.0);
  gl_Position = ftransform();
}
// Fragment
uniform sampler2D reflectTex;

varying vec4 projCoord;
const vec4 ambient = vec4(0.13), boost = vec4(1.06);
void main()
{
  vec4 reflectionValue = texture2D(reflectTex, projCoord.xy);
  gl_FragColor = boost * gl_Color * reflectionValue + ambient;
}
All of which compile fine. As I said, i'm probably missing something simple but i'll be damned if I can see where and lack of code for showing how to construct this matrix isnt helpping (Nvidia have a paper which says the texmatrix = remap*proj*view*model, which is what i thought i was doing... [crying]) I'm going to get some sleep now, any help would be appricated [smile] [help]
Advertisement
ok, i've had a fiddle with things and the repeat rate of the texture is effected by the size of the thing i'm reflecting on, which while being intresting doesnt seem right to me.

Having reduced the plane to a 0.5,0.5 => -0.5,-0.5 plane, still on Y = 0, i've got it doing the texture once, but not in the right place and ofcourse this breaks as soon as the size of the quad increases.

Part of the problem seems to have been my remap matrix being wrong, moving the 0.5 from 31,32,33 to 13,23,33 (col,row) gives it the same appearance as doing a gltranslate(0.5f,0.5f,0.5f) & glscale(0.5f,0.5f,0.5f) in that order, which gives a slightly more correct image (orignal and current) but is still wrong (and currently reflected, but again i'll worry about that later) [sad]

i'll keep on fiddling but in the mean time if anyone can point out why this might have happened please do, it coud save my hair [smile]
ok, so it turns out i was partly being crazy :)
having fiddled around a bit i've worked out that the projective texturing is work, just now how i expected it to as its ofcourse constrained to clip space (-w < X < w), not the object its being projected on, so the images I'm getting are correct for projecting over a whole plane.

Since thats been corrected it turns out RTT was working as now i can render the object to a texture and project it onto the Y=0 plane.

However, i've still got problems [smile]

Currently i'm doing thus :
- positioning the camera at x = 0, y = -4, z = -14
- then applying a reflect matrix by multiplying the current modelview matrix by a reflection matrix of
GLfloat ReflectionMatrix[] = {1.0f,0.0f,0.0f,0.0f,                              0.0f,-1.0f,0.0f,0.0f,                              0.0f,0.0f,1.0f,0.0f,                              0.0f,0.0f,0.0f,1.0f};

as the reflection plane is on Y=0 and i'm reflecting about Y (I'll worry about a general term later).
- draw my spinning cubes into the texture
- repostioning the camera as before (does a load Identity first)
- switch to texture matrix mode
- switch to modelview matrix mode (i know, wastefull but this is fiddling code)
- push the matrix to perserve the camear position
- apply reflection matrix as before
- extract modelview matrix to an array
- pop matrix
- switch back to texture matrix mode
- Load identity matrix
- translate by (0.5,0.5,0)
- scale by (0.5,0.5,1) (numbers extracted from a projection mapping program by Cass of NV)
- multiply by the projection matrix (extracted earlier in program after OGL setup)
- multiply by viewmatrix
- switch to modelview matrix mode
- draw plane with texture projected on it

1 changes to my fragment shader, i'm now doing a projective lookup with the texture coord rather than a standard lookup.
Everything else now remains the same.
After all that my reflection looks like this : Clicky
However, given that my objects are here that doesnt look remotely right at all.

I'm still gonna keep poking, but as before if anyone can point out where i've gone wrong it would be great [smile]
You seem to be quite lonely in this thread ;)

What you're doing is a little bit confusing, but let's take it apart.

This:
Quote:
- switch back to texture matrix mode
- Load identity matrix
- translate by (0.5,0.5,0)
- scale by (0.5,0.5,1) (numbers extracted from a projection mapping program by Cass of NV)
- multiply by the projection matrix (extracted earlier in program after OGL setup)
- multiply by viewmatrix

is OK, and should give you a correct projection matrix. BUT: what is "viewmatrix", where did you get it from ? If it comes from here:
Quote:
- switch to modelview matrix mode (i know, wastefull but this is fiddling code)
- push the matrix to perserve the camear position
- apply reflection matrix as before
- extract modelview matrix to an array
- pop matrix

then there is a mistake: you have to apply the reflection matrix only when rendering the reflected scene into the RTT, but not when projecting it back on screen. In the projection step, you should use the same non-reflected modelview matrix as you use to render the geometry the texture will be projected onto: for example the water plane. Without any reflection, as the reflection is already encoded in the projected RTT !

In short: just remove the lines I marked in bold above.
Quote:Original post by Yann L
You seem to be quite lonely in this thread ;)


hehe, i'm used to talking to myself most of the time anyways, this thread just became an extension of my mad ramblings [wink]

Anyways, cheers for taking a look, i've removed the lines you said.
You were quite correct about where i was getting the modelview matrix from (or viewmatrix as i refered to it later), I must have misunderstood what you were refering to in the other thread in the Graphics theory forum [smile]

A quick recompile later and it appears things havent changed, the full scene still looks like this : clicky [oh]
(I've moved the cameara back slightly so that i could see the plane properly i'm projecting onto)
yey!
I've found the problem and it WAS a stupid mistake on my part [smile]
I decided to add a quad showing my reflection texture to my main scene so I could see what was going on, the outcome was this [grin]
a quick shift in perspective and a translate shows things are a touch distorted however - clicky probably the result of me rendering a 1024*768 scene into a 1024*1024 texture [oh]

Simple problem and now its fixed, next job adding a clipping plane/volume via the code Yann posted a link to in the thread which started all this [smile]

thanks Yann for correcting my minor matrix mistake as well [smile]

edit: distortion fixed, just a case of aspect ratio being wrong on the pbuffer [smile]

[Edited by - _the_phantom_ on July 2, 2004 5:22:48 PM]

This topic is closed to new replies.

Advertisement