cubemap reflection not perspective correct

From the posts I saw on this forum, I’ve implemented my own reflection texture-mappping using the GL_TEXTURE_CUBE_MAP_ARB extension. It’s working great for me except for one thing: The reflection does not get rendered perspective-correct (regular texture mapping modes are working fine). Is this a limitation of the technique or is there something extra I must do when using a cubemap to render reflections?

I’ve looked at Nutty’s demo and source code where he’s doing the same thing, and I see his reflections have the same problem, which leads me to believe it’s just a limitation I have to live with. (Thanks Nutty for your demos)

See these images for clarification, which are just simple cubes with 2 tris/face:

Correctly rendered cube with a simple checkerboard pattern http://home.columbus.rr.com/bpainte/cube3.jpg

Incorrectly rendered cube with reflection mapping (nevermind that the reflection does not include the ground in the scene, I’m not dynamically updating the cubemap texture) http://home.columbus.rr.com/bpainte/cube1.jpg

Of course, I’ll post code if people feel it will help.

(Edited to add extra info.)
Oh yes, hw is Geforce4 Ti 4200, with 30.72 drivers.

[This message has been edited by painterb (edited 11-27-2002).]

That doesn’t look like a perspective correction problem; it looks like a cube map image problem. If you use those same images as a sky box, does it look seamless or does it show the same discontinuities at the seams?

When used as a skybox, the textures look fine together.

Just to be sure we’re looking at the same thing, here’s one more image … the flawed areas are highlighted in yellow (it’s where the 2 tris of one face meet). This type of distortion doesn’t occur on my skybox. http://home.columbus.rr.com/bpainte/cube2.jpg

And, here’s a link to Nutty’s demo exhibiting the same flaw. (Look for the demo “Dynamic Cubemap Demo”) http://romka.demonews.com/opengl/demos/texture_eng.htm

tesselate it higher…

you do per vertex generate reflection coords, but per triangle, you will map planar onto the surface… it looks like you have smooth normals, on wich you reflect at?

at least, its a texcoord problem. nothing else…

How are you computing the texture coordinates to use for the cube mapping? I had this problem once when creating the reflection vectors in a vertex program since I was normalizong them per vertex. Interpolating normalized vectors does not give the correct results.
If you are using REFLECTION_MAP however, it should not be doing this normalisation. Just make sure you have unit normals on your cube.

Originally posted by davepermen:
tesselate it higher…

I realize this would help. But the problem would still exist, just at a level where it won’t be terribly noticable.

And I’m surprised, is this really the only way to solve? Because when applying a texture normally (GL_TEXTURE_2D mode, not CUBE_MAP) say in decal mode, this flaw is not present.

Sorry I left out some useful data … I am using glTexGen to generate the tex coords:
glTexGeni(GL_S,GL_TEXTURE_GEN_MODE,GL_REFLECTION_MAP_ARB);
glTexGeni(GL_T,GL_TEXTURE_GEN_MODE,GL_REFLECTION_MAP_ARB);
glTexGeni(GL_R,GL_TEXTURE_GEN_MODE,GL_REFLECTION_MAP_ARB);

bakery2k, ok, I will double check to make sure my normals are of unit length.

I admit, I have trouble with the more complex texture-mapping methods, so you guys no doubt are smarter than me, but from what I’ve read it certainly looks like a perspective-correction issue. I will see if I can put together an executable for you to run.

Thanks all.

One thing that will help debug this for you is to try outputting those texture coords as colors. This can show you if the coordintes are showing a discontinuity there. I imagine the problem you are having is with the texture matrix.

-Evan

BTW, Go Bucks!

Does this help:

glTexGeni(GL_Q,GL_TEXTURE_GEN_MODE,GL_REFLECTION_MAP_ARB);

Just a guess really.

Okay, I’m also convinced it’s a triangle edge issue now.

I’d bet a donut that Dorbies suggestion is on the right track.

Quote from the OpenGL 1.4 specs:

“Calling TexGen with a coord of Q when pname indicates REFLECTION_MAP generates the error INVALID_ENUM”

That’s not it…

Originally posted by ehart:
BTW, Go Bucks!

… yeah, I about had a heart attack watching that game! Woohoo!

bakery2k’s right … I already tried that and promptly generated an Opengl error.

Well, I’ll keep trying and let you know if I find the solution … Nutty if you’re here, I’d be curious if you noticed this with your demo and what you found. Also, I’m still trying to put an exe together.

This is normal behaviour. The texture coords are linearly interpolated, which isn’t the most optimal or most correct way to interpolate reflection vectors.
From the “issues” section in GL_ARB_texture_cube_map:

The spec just linearly interpolates the reflection vectors computed
per-vertex across polygons.  Is there a problem interpolating
reflection vectors in this way?
  Probably.  The better approach would be to interpolate the eye
  vector and normal vector over the polygon and perform the reflection
  vector computation on a per-fragment basis.  Not doing so is likely
  to lead to artifacts because angular changes in the normal vector
  result in twice as large a change in the reflection vector as normal
  vector changes.  The effect is likely to be reflections that become
  glancing reflections too fast over the surface of the polygon.
  Note that this is an issue for REFLECTION_MAP_ARB, but not
  NORMAL_MAP_ARB.

[This message has been edited by Humus (edited 11-27-2002).]

its the same “bug” we know from environmental mapping… its a nonlinear generated mapping coord, but you only generate it at the edges and linear interpolate between.
nuttys demo uses a sphere…

how to solve it? move to a flatshaded quad. then it should look less ugly (if it is yet flat shaded, i’m sorry… it really is ugly )

the only real solution is calculating the reflection per pixel and then look up. possible on a gf3+, radeon8500+…

you can only correctly map something wich is based on a linear equation. GL_NORMAL_ARB (or whats it called again?), normal texture mapping, projective, eye space coord mapping, object space coord mapping, etc… but reflections are not linear, like envmaps are not linear.

so interpolate the linear components per vertex, and set up texture_shaders/fragment_shader/ARB_fragment_program to take those inputs and generate a perpixelreflection to look up into the cubemap…

thats the only way.

for hw that can’t do this: tesselate… (think of the sphere of nutty… )

Originally posted by davepermen:
for hw that can’t do this: tesselate… (think of the sphere of nutty… )

Nutty’s demo has two reflecting cubes which orbit the sphere. It is those two cubes which I was referring to having the error. They pass across the scene quickly, but the error is visible (especially if you get the source and slow them down!)

OK, looks like the easy thing for me to do is to go ahead and add polygons, or just forget it.

I’ll have to mull over what you said (Humus and davepermen) for a bit. Each side of the cube is flatshaded however (I only submit one normal (perp to the face) to render the 2 tris composing each face).

Thanks to all.

(Thanks Nutty for your demos)

No problemo.

And, here’s a link to Nutty’s demo exhibiting the same flaw. (Look for the demo “Dynamic Cubemap Demo”) edit

Man I wish he would just link to my site, than hosting them directly…

Nutty if you’re here, I’d be curious if you noticed this with your demo and what you found. Also, I’m still trying to put an exe together.

Yeah, Humus and Dave seem to be right. You can either tesselate the faces, which doesn’t remove the problem, just makes it alot less visible, or calculate the reflection vector correctly per fragment.

I never noticed it before, cos I always use stuff with pretty good tesselation.

Nutty

Nutty’s demo has two reflecting cubes which orbit the sphere. It is those two cubes which I was referring to having the error. They pass across the scene quickly, but the error is visible (especially if you get the source and slow them down!)

The cube are just sphere-mapped

Nutty

I may be wrong about this, but if I’m not mistaken, while your normals should be normalized, your eye vector ( ie. texcoords ) should not. Leave them at vertex-to-eye length.

It works for me when I’m using the dot_product_reflect_cube_map_eye_from_qs texture shader. I had the same artifact when the eye vectors were normalized. It might not be the case for the non-texture-shader version though.

Edit: fixed UBB code

[This message has been edited by Dakeyras (edited 11-27-2002).]

Originally posted by Nutty:
You can either tesselate the faces, which doesn’t remove the problem, just makes it alot less visible, or calculate the reflection vector correctly per fragment.

What about a normal map? Would that work?

painterb: you can’t do anything about the “perspective-correction-like” problem because OpenGL does work linearly. A possible solution would be to work with Q coordinate, but in that case I’m not even sure the Q coordinate would be interpolated either. I’m afraid the only solution is tesselation again and again…

rgpc: of course you can, since normal maps lead to per-fragment computations. But not all hardware can perform it today.

No, this is not a fundamental problem with cube mapping. The reflection vector is interpolated, but this reflection vector is referencing a spherical lookup table, essentially, so you shouldn’t be getting these artifacts.
The only thing I would ask is will you please draw your normal vectors, and print out another screenshot for us…I’ll bet your cube has 8 shared vertices, and therefore 8 shared normals - this may explain why it looks messed up, because with a cube you should duplicate the shared vertices because the normals should be drastically different for each face sharing the vertex.
BTW, make sure you load the inverse upperleft 3x3 of the modelview matrix into the texture matrix before rendering.

[This message has been edited by knackered (edited 11-28-2002).]