Oblique plane clipping artifacts

Started by
3 comments, last by myers 18 years, 1 month ago
I've been playing around with Eric Lengyel's famous oblique plane clipping code, and I can't stop the z-buffer precision from being badly reduced. I keep getting these depth artifacts where fragments that should be occluded are showing through, even very close to the near clipping plane. These artifacts are so bad that I can't see how the technique is really useable for, say, reflections. So I was wondering: does anyone actually use the near plane for oblique clipping, or is it standard just to create extra clip planes?
Advertisement
hmmm, I've used it with no problems like that.. post some setup code so I can see what you are doing to get the various numbers..
Okay, er, I've tried to tidy up the code for human consumption, so I've probably inserted many new errors. But here goes.

This transforms the clip plane from world to camera space:

vector4D cameraspace_plane(){ vector4D plane; matrix4x4 modelview; float A, B, C; float pX, pY, pZ, pW; //transformed point float nX, nY, nZ, nW, inverse_normal_length; //transformed normal glGetFloatv(GL_MODELVIEW_MATRIX, modelview); A = 0; B = 0; C = 0; pX = A*modelview[0] +  B*modelview[4] +  C*modelview[8] +  modelview[12]; pY = A*modelview[1] +  B*modelview[5] +  C*modelview[9] +  modelview[13]; pZ = A*modelview[2] +  B*modelview[6] +  C*modelview[10] + modelview[14]; pW = 1; //transforming normal  A = 0; B = 1;  = 0;  nX = A*modelview[0] + B*modelview[4] + C*modelview[8]; 	nY = A*modelview[1] + B*modelview[5] + C*modelview[9]; Z = A*modelview[2] + B*modelview[6] + C*modelview[10]; 	nW = 0; //normalize inverse_normal_length = 1/ sqrtf( nX*nX + nY*nY + nZ*nZ ); nX *= inverse_normal_length; nY *= inverse_normal_length; nZ *= inverse_normal_length; //clip plane values plane.x = nX; plane.y = nY; plane.z = nZ; //dot between normal and point plane.w = -(pX*nX + pY*nY + pZ*nZ);  return plane;}


This returns the modelview matrix we want:

matrix4x4 set_modelview(){ matrix4x4 modelview; glMatrixMode(GL_MODELVIEW); glLoadIdentity(); //Rotate and transform if(camera.orientation.w<1 && camera.orientation.w>-1)  glRotatef(theta, camera.orientation.x, camera.orientation.y, camera.orientation.z); glTranslatef(-camera.position.x, -camera.position.y, -camera.position.z); glGetFloatv(GL_MODELVIEW_MATRIX,modelview); return modelview;}


And this sets the modelview and projection matrices, the latter of which has Eric Lengyel's transformations applied to it:

void set_camera(){ //Obtain modelview matrix matrix4x4 modelview=set_modelview(); //Transform the clip plane to camera space vector4D plane=cameraspace_plane(); //Set projection matrix glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(45.0f, 1.333f, 1.0f, 1024.0f); //Eric's routine ModifyProjectionMatrix(plane); //Set modelview matrix glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glLoadMatrixf(modelview); //Render etc.}


What's strange is that everything is fine apart from the z-buffer artifacts. The near plane seems to be set where I want it to be. I guess something must be amiss with the far plane?
Hi --

Famous, eh? The projection matrix technique does unavoidably reduce the z-buffer precision, but unless you're creating an extreme case specifically designed to break it, you shouldn't see a problem. I use the technique for a lot of things (water, mirrors, etc.) without problems.

What you're seeing probably means that the clipping plane isn't in the right place in camera space. Make sure that all of the following are true:

1) Your clipping plane normal points away from the camera position C. That is, the camera is on the negative side of the plane P. If the dot product (Px,Py,Pz,Pw) * (Cx,Cy,Cz,1) isn't negative, then negate all four components of your clipping plane.

2) You're transforming the clipping plane from the correct space into camera space. Is your clipping plane in world space or the local space of some object?

3) You're transforming the clipping plane into camera space with the right mathematical transform. A 4D vector P representing a plane is transformed by a 4x4 matrix M by computing P' = P * Inverse(M).

I noticed you're transforming the plane normal and a point on the plane separately, but it's much better to just transform a whole 4D plane vector at once. (Your calculation looks right, but it's more work.)

One other thing to note is that you don't have to renormalize the plane once it's been transformed. It gets normalized implicitly when the new projection matrix is calculated.
Quote:Original post by Eric Lengyel
Hi --

Famous, eh?


Well, it's mentioned in at least three GameDev threads. That probably makes you famous enough to go on Celebrity Big Brother. :)

Quote:What you're seeing probably means that the clipping plane isn't in the right place in camera space. Make sure that all of the following are true:

1) Your clipping plane normal points away from the camera position C. That is, the camera is on the negative side of the plane P. If the dot product (Px,Py,Pz,Pw) * (Cx,Cy,Cz,1) isn't negative, then negate all four components of your clipping plane.


The normal did point away from the camera (P.C<0), but since you mentioned it I thought I'd negate the plane components anyway just to see what happened. I expected this would just flip the plane - i.e. clip everything in front of it, rather than behind it. It did - but the z-artifacts were gone! So then it was just a matter of inverting the plane normal to get the clip space I wanted. It's fair to say I don't really understand why it's working now (maybe the sign of the plane's d component was wrong?). But oh well!

Incidentally, the artifacts return if I move the camera to a position co-planar with the clip plane. I guess that makes sense, though, and for reflections, at least, it doesn't matter.

Quote:I noticed you're transforming the plane normal and a point on the plane separately, but it's much better to just transform a whole 4D plane vector at once. (Your calculation looks right, but it's more work.)


D'oh. Yes, thanks.

Quote:One other thing to note is that you don't have to renormalize the plane once it's been transformed. It gets normalized implicitly when the new projection matrix is calculated.


Ah, righto.

Looks like your code's okay after all, then. You can sleep easy again!

This topic is closed to new replies.

Advertisement