Weirdness with glClipPlane
I've used glClipPlane before and it always did what it's supposed to do. It made a clipping plane in the modelview space which was static relative to the scene.
But, for some baffling reason I'm seeing a dynamic clip plane which slides around relative to the camera position! It's driving me batty, and I'm hoping some kind soul here can give some suggestions to help me out.
First, a video of what I'm talking about. I'm doing simple reflections, and in the video you'll see a scene of a bunch of textured boxes reflected in a textured plane. I'm rendering world flipped across the plane and using a glClipPlane to clip the scene by that reflection plane.
http://shamyl.zakariya.net/etc/ClippingPlaneWoes.mov
The relevant code is below. It's a little ugly right now since I'm experimenting. That being said, the reflected rendering and reflected frustum culling work great. The issue at hand is that the clipping plane slides around as the camera moves and looks around. I have no idea why this would happen!
But, for some baffling reason I'm seeing a dynamic clip plane which slides around relative to the camera position! It's driving me batty, and I'm hoping some kind soul here can give some suggestions to help me out.
First, a video of what I'm talking about. I'm doing simple reflections, and in the video you'll see a scene of a bunch of textured boxes reflected in a textured plane. I'm rendering world flipped across the plane and using a glClipPlane to clip the scene by that reflection plane.
http://shamyl.zakariya.net/etc/ClippingPlaneWoes.mov
The relevant code is below. It's a little ugly right now since I'm experimenting. That being said, the reflected rendering and reflected frustum culling work great. The issue at hand is that the clipping plane slides around as the camera moves and looks around. I have no idea why this would happen!
Code:
void World::renderReflectionsForCamera( const CameraRef &camera, bool shadows )
{
_renderingReflection = true;
for ( EntityCameraReflectionMap::const_iterator it( _reflectionCameras.begin() ), end( _reflectionCameras.end() );
it != end; ++it )
{
_renderingReflectionForEntity = it->first;
for ( std::map< CameraRef, ReflectionRTTCameraRef >::const_iterator cIt( it->second.begin() ), cEnd( it->second.end() );
cIt != cEnd; ++cIt )
{
CameraRef camera = cIt->first;
//
// Don't bother rendering the reflection if this camera can't see the reflecting entity
//
if ( camera->frustum().intersects( it->first->aabb() ))
{
glError();
_activeReflectionCamera = cIt->second;
_activeReflectionCamera->begin();
displayForCamera( camera, shadows );
_activeReflectionCamera->end();
glError();
}
}
}
_renderingReflectionForEntity.reset();
_activeReflectionCamera.reset();
_renderingReflection = false;
}
void World::displayForCamera( const CameraRef &camera, bool shadows )
{
LightRef noLight;
glError();
Frustum frustum = camera->frustum();
if ( _renderingReflection )
{
_activeReflectionCamera->setFarPlane( _farPlane );
_activeReflectionCamera->set();
plane reflectionPlane = _activeReflectionCamera->reflectionPlane();
mat4 householderTransform = _activeReflectionCamera->householderTransform();
vec3 refPoint = vec3( reflectionPlane.a, reflectionPlane.b, reflectionPlane.c ) * reflectionPlane.d;
glError();
GLdouble clipPlane[4] = { reflectionPlane.a,reflectionPlane.b,reflectionPlane.c,reflectionPlane.d };
glEnable( GL_CLIP_PLANE0 );
glClipPlane( GL_CLIP_PLANE0, clipPlane );
glPushMatrix();
glTranslatef( refPoint.x, refPoint.y, refPoint.z );
glMultMatrixf( householderTransform );
glTranslatef( -refPoint.x, -refPoint.y, -refPoint.z );
frustum = _activeReflectionCamera->reflectedFrustum();
}
else
{
camera->setFarPlane( _farPlane );
camera->set();
}
//
// Prepare visibility set, then run visibility determination
// against each graph to populate it. Then, finish it so we can render.
//
_visibilitySet->begin();
for ( GraphRefMap::iterator it( _graphs.begin() ), end( _graphs.end() );
it != end; ++it )
{
it->second->determineVisibility( _visibilitySet, frustum );
}
_visibilitySet->done();
glError();
glEnable( GL_DEPTH_TEST );
glDepthFunc( GL_LEQUAL );
glEnable( GL_CULL_FACE );
glCullFace( GL_BACK );
glFrontFace( GL_CCW );
glDisable( GL_BLEND );
glError();
// render opaque lighting
displayLighting( true, shadows );
// render transparent lighting, grabbing depth & color tex if necessary
if ( _visibilitySet->transparentRenderPassNeeded() )
{
if ( _visibilitySet->transparentRenderPassNeedsDepthTexture() )
{
grabDepthTexture();
}
if ( _visibilitySet->transparentRenderPassNeedsColorTexture() )
{
grabColorTexture();
}
displayLighting( false, shadows );
}
glError();
displayPass( RenderPass::FinalPass, noLight, false );
if ( _debugGraphs )
{
glDisable( GL_FOG );
glDisable( GL_LIGHTING );
glEnable( GL_COLOR_MATERIAL );
glEnable( GL_BLEND );
glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
for ( GraphRefMap::iterator it( _graphs.begin() ), end( _graphs.end() );
it != end; ++it )
{
it->second->debugRender();
}
}
glDisable( GL_ALPHA_TEST );
if ( _renderingReflection )
{
glDisable( GL_CLIP_PLANE0 );
glPopMatrix();
}
}
This has happened to me before. I haven't looked at your code in detail but I'm looking at p. 140 of the red book, 3rd ed. which says (italics are mine):
Quote:All points with eye coordinates (xe, ye, ze, we) that satisfy (A B C D) M^-1 (xe ye ze we)^T >= 0 lie in the half-space defined by the plane, where M is the current modelview matrix at the time glClipPlane() is called.The last time I had this problem, it was because I defined a clip plane before I had placed my camera where I wanted it (essentially putting the clip plane and the camera in different coordinate systems).
Interesting. I didn't realize glClipPlane was relative to a particular modelview. I just assumed it was magic, I guess. I'm going to have to do some more experimentation.
SOLVED!
What I didn't know is that if you're using vertex shaders, you have to calculate the clip vertex. Probably something I read in the orange book and then forgot immediately.
So, if you have this problem, it's a one-liner. Add this to your vertex shader:
Obviously, the above is valid only if what you want is clipping planes defined in modelview space.
What I didn't know is that if you're using vertex shaders, you have to calculate the clip vertex. Probably something I read in the orange book and then forgot immediately.
So, if you have this problem, it's a one-liner. Add this to your vertex shader:
Code:
gl_ClipVertex = gl_ModelViewMatrix*gl_Vertex;Obviously, the above is valid only if what you want is clipping planes defined in modelview space.
Glad I didn't have the misfortune to mess with clip planes and vertex shaders at the same time!
Also I guess I should pick up an orange book -- seems like there's some non-intuitive things happening in there...
Also I guess I should pick up an orange book -- seems like there's some non-intuitive things happening in there...
UH-OH!
It seems that writing to gl_ClipVertex forces software vertex execution ( on the x1600 at least ). What a shame. I pretty much have to give up on rendering reflections if it's going to cause horrible slowdowns.
It seems that writing to gl_ClipVertex forces software vertex execution ( on the x1600 at least ). What a shame. I pretty much have to give up on rendering reflections if it's going to cause horrible slowdowns.
You could always implement the clip plane yourself by discarding pixels on the wrong side of the plane in your fragment shader.
I've considered that, but the trouble is I'm rendering the entire "world" reflected across the plane, which means all my shaders would have to have the discard code, which wouldn't be used 99.99% of the time.
Seems like a waste.
Seems like a waste.
If you only need one clip plane you can do that weird changing-the-shape-of-the-view-frustum trick. That seems to be the "done thing" these days.
Now, now that's interesting. OSC, to the rescue.
Thanks, chief.
Thanks, chief.
neat idea.
It works! Thanks for the link!
Possibly Related Threads...
| Thread: | Author | Replies: | Views: | Last Post | |
| Alpha blending weirdness on GMA 950 | akb825 | 15 | 8,237 |
Sep 1, 2009 06:22 PM Last Post: arekkusu |
|
| OpenGL weirdness | DoG | 9 | 3,662 |
Oct 31, 2006 04:49 AM Last Post: DoG |
|

