PDA

View Full Version : spherical environment reflections



09-17-2005, 06:17 AM
Hi,

in my MacOS X application, I'm using spherical environment mapping to simulate reflections on water and to create a chrome effect. So far, it seemed to work well, but some user who uses a GeForce FX 5200 graphics card reproted that the water reflections wouldn't work while the chrome effect seems to be ok.
Somehow the texture coordinates for the water aren't generated and openGL uses the ones supplied with the vertex data instead.

Is there any difference in the way ATI and Nvidia cards handle spherical mapping?

There isn't any major difference between the code for the chrome effect, that always works, and the code for the water reflection. Both use single triangles.
Is there any common mistake I could have made that would cause spherical environment mapping to only work on certain cards?

Thanks in advance

Here's the code I use to render the water:

glDisable(GL_LIGHTING);
glBindTexture(GL_TEXTURE_2D, g.envTexID);
glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
glEnable(GL_TEXTURE_GEN_S);
glEnable(GL_TEXTURE_GEN_T);
glBegin(GL_TRIANGLES);

for(x1 = xstart; x1 < xend; x1 += xStep){
x2 = x1 + xStep;
for(z1 = zstart; z1 < zend; z1 += zStep){
z2 = z1 + zStep;
/* draw the triangles */
glNormal3f(0.0f, 1.0f, 0.0f);
glTexCoord2f(0.0f, 0.0f);
glVertex3f(x1, 0, z1);

glNormal3f(0.0f, 1.0f, 0.0f);
glTexCoord2f(0.0f, 1.0f);
glVertex3f(x1, 0, z2);

glNormal3f(0.0f, 1.0f, 0.0f);
glTexCoord2f(1.0f, 1.0f);
glVertex3f(x2, 0, z2);

/* 2nd tri */
glNormal3f(0.0f, 1.0f, 0.0f);
glTexCoord2f(0.0f, 0.0f);
glVertex3f(x1, 0, z1);

glNormal3f(0.0f, 1.0f, 0.0f);
glTexCoord2f(1.0f, 1.0f);
glVertex3f(x2, 0, z2);

glNormal3f(0.0f, 1.0f, 0.0f); /* 4th vertex */
glTexCoord2f(1.0f, 0.0f);
glVertex3f(x2, 0, z1);
}
}
glEnd();

glDisable(GL_TEXTURE_GEN_S);
glDisable(GL_TEXTURE_GEN_T);
glEnable(GL_LIGHTING);

Hlz
09-17-2005, 10:02 AM
The code you posted looks OK (look at triangle strips for your water). Can you post/link a simple test case that reproduces the problem? I'd be happy to try it.

09-17-2005, 11:02 AM
Just embeded the water code into a glut environment, but I got to send it to the one with the FX 5200 card to make sure the problem is still in it.

09-18-2005, 01:24 PM
Hi,

I were finally able to test my glut version and it seems to reproduce the problem.
As far as I can tell, it's caused by the way I render a "base texture" for the water:

my app first renders a plane build of triangles with a normal texture that is used as some base color / texture for the water.
after that, it renders the reflection effect using another plane that is slightly above the first one.

If I don't render the plane with the base texture, the spherical mapping is applied, if I do, it doesn't work.

The test app can be downloaded from http://www.falkoa.de/up/envmap.zip ( http://www.falkoa.de/up/envmap.zip) .
I added some controls to help testing:
e : turn environment mapping on/off (0/1)
b : draw "background" plane not/first/last (0/1/2)
a : toggle alpha value of the planes (doesn't seem to have any effect on the env. mapping problem)

The app starts up in the configuration that is used in my main app which causes the problems.

The source code includes a Xcode project file (mac os) but main.c should compile on any platform using glut.

Thanks for your help!

Hlz
09-18-2005, 04:38 PM
Well, for starters, it works, or at least I think it's doing what you would expect, but I don't have basis to go on (GeForce FX 5900, FW 77.72).

A few observations:

1. Your zNear and zFar choices can lead to trouble with depth testing. The greater the disparity in these values, the worse it gets. Try something like zNear=1, zFar=8000, or so. Also try a depthfunc of GL_LEQUAL. I think that technically the spec says that there can be differences in the rasterization of identical primitives if certain render states are different (blending, for example), but my experience tells me that you should be able to render these 2 surfaces with the same "water depth" without any trouble (worked for me).

2. Look at your scaling in general. It's a tad on the large side, which can lead to problems. For testing, take the step size down to 64, and set the mesh radius from 50,000 to something like 1024, or so.

3. Change your tex object types to GLuint (were GLint).

4. A light position with w=0 is a direction. Again, there's no need to use such large numbers here, especially in the case where opengl is expecting a normalized vector.

4. You're calling stencil functions, but you forgot to specify a stencil buffer (GLUT_STENCIL).

5. Things I missed and/or forgot.

Anyways, just a few things to tinker with. I assume the problem machine is running with the latest official drivers properly installed.

P.S. Maybe you could widdle this down a bit more and post it here :-)

09-19-2005, 02:09 AM
I chose the scale as that is what my game uses and I wanted to copy the situatuion as good as possible (same with stencil).
I'd have to glScale the whole scene down if I used other values for zNear / Far
I also tried a larger "water depth" value (-60) to make sure that there is no z-buffer fighting, but it didn't make a difference.
The driver version used is the one that came with MacOS X 10.4.2 and there don't seem to be any other drivers available for mac on the nvidia site.
Also, someone with a GeForce2 card didn't have any problems running the code either.

I'll try to clean the glut code up a bit and remove the stuff that is not needed to reproduce the problem.

09-19-2005, 12:04 PM
I cleaned the code up a bit and reduced the scale, but the problem remains. As soon as the "background layer" for the water is drawn, the spherical mapping isn't applied anymore.
It's available from http://www.falkoa.de/up/envmap-2.zip .

Disabling the spherical mapping with the e-key reproduces how the app always looks like on the comp with the FX 5200.

Here's an excerpt of my code:

glBindTexture(GL_TEXTURE_2D, imgTex);
glColor4f(0.2f, 0.2f, 1.0f, 0.8f);

/* draw plane at y = -10 */
/* if this isn't drawn, the spherical mapping works */
/* independant of alpha values */
DoDrawPlane(-10);


/*
* Draw the environment reflection
*/
glColor4f(0.4f, 0.4f, 1.0f, 0.4f);

/* bind the environment texture */
glBindTexture(GL_TEXTURE_2D, envTex);
if(useEnv){ /* set env mode stuff */
glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
glEnable(GL_TEXTURE_GEN_S);
glEnable(GL_TEXTURE_GEN_T);
}

DoDrawPlane(0);

if(useEnv){ /* set env mode stuff */
glDisable(GL_TEXTURE_GEN_S);
glDisable(GL_TEXTURE_GEN_T);
}