I’ve been writing a game on my powerbook – which has an nVIDIA card – and for which all my shadow code is working.
recently I tested it on a machine with an ATI card, and my god was it awful. Z-fighting everywhere. So in the interest of robustness, I’ve isolated the shadow code and made a test app which I’m using to try to solve the problem robustly.
See the screenshots to see the z-fighting I’m talking about:
Now, this looks to me like the occluder geometry is z-fighting with the front-caps of my shadow volumes. ( for reference, I’m using z-fail ). On my nVIDIA, where I wrote this code initially, all it took was a call to glPolygonOffset to push the front caps away from the viewer.
Here’s the relevant code, displaying a pre-calculated volume.
void Geometry::drawShadowVolume( void )
{
/*
Volume needs to be pushed *backwards* in depth buffer so
as to eliminate z-fighting with occluder geometry
*/
glEnableClientState( GL_VERTEX_ARRAY );
glVertexPointer( 3, GL_FLOAT, 0, _shadowVolumePoints );
glDrawArrays( GL_QUADS, 0, _shadowVolumeTop );
glEnable( GL_POLYGON_OFFSET_FILL );
glPolygonOffset( 1.0, 1.0 );
glVertexPointer( 3, GL_FLOAT, 0, _shadowCapPoints );
glDrawArrays( GL_TRIANGLES, 0, _shadowCapTop );
glDisable( GL_POLYGON_OFFSET_FILL );
glDisableClientState( GL_VERTEX_ARRAY );
}
This works on nVIDIA, and not on ATI, as you can see from the screenshots. I’ve attempted several ranges of values for polygon offset but none seem to do the trick on the ATI. Am I missing something?
My second question also regards shadow volumes on ATI cards. I’m using GL_NV_DEPTH_CLAMP to allow me to not have to use an infinite projection matrix for my volume extrusion. Mainly this is because I’m lazy…
So, I googled around a bit and found a fragment program to simulate GL_NV_DEPTH_CLAMP on hardware which doesn’t have that extension.
!!ARBfp1.0
MOV result.color, 1.0;
MOV_SAT result.depth, fragment.position.z;
END
I had to add the MOV result.color, 1.0; line as without it nothing at all happened.
This shader, when run on my nVIDIA ( 5200 Fx Go ) works. It does exactly what GL_NV_DEPTH_CLAMP does, and I get nice robust shadows without far-plane capping artifacts.
But, on an ATI card which does support ARB_fragment_program, I get far-plane capping artifacts, as if nothing’s happening. And, to make things worse, I don’t get any errors.
Finally, this is on Mac OSX 10.3, 10.4, in case that makes any difference.
Thanks in advance, I hope somebody can help me.