TomorrowPlusX
2005.05.10, 09:46 AM
My game uses GL_NV_DEPTH_CLAMP to allow me to use zfail shadows without the need for an infinite view frustum. Works *great* on NVIDIA cards.
Many moons ago, I asked what approaches I could take to emulate the depth clamp behavior on ATI cards, and Arrekusu kindly pointed out to me a fragment program from frustum.org which emulates depth clamping.
Here's the fragment shader.
!!ARBfp1.0
MOV_SAT result.depth, fragment.position.z;
END
Pretty simple, & makes sense. -- The trouble is, I can't get it to work.
So, I feel like I basically understand how to use it, but I figured I'd use frustum.org's Shader class for parsing and loading, since it's public domain anyway ( and since when I reach 1.0 I'll release my game with source, and proper attributions anyhow ).
Here are the Shader class files:
Shader.h (http://home.earthlink.net/~zakariya/files/Legion/Shader.h)
Shader.cpp (http://home.earthlink.net/~zakariya/files/Legion/Shader.cpp)
So, anyhow, in his sample code he brackets the drawing of the shadow volume as such:
... //various setup
if(have_nv3x) glEnable(GL_DEPTH_CLAMP_NV);
else {
depth_clamp_fp->enable();
depth_clamp_fp->bind();
}
... //draw extruded shadow volumes
if(have_nv3x) glDisable(GL_DEPTH_CLAMP_NV);
else depth_clamp_fp->disable();
... // cleanup
I've basically done the same thing in my code. But, nothing happens. Shadows don't draw *at all*.
Here's my code -- which is basically similar. This is just one path, I've got two-pass versions where two sided stencils aren't available, and I've also got subtractive shadowing for relatively slow machines ( like the PB I'm writing this game on :cry: )
void StencilShadow::singlePassModulative( vec4 lightPos )
{
if ( _depthClampAvailable )
{
glEnable( GL_DEPTH_CLAMP_NV );
}
else if ( _depthClampFP )
{
// I know the shader is valid
_depthClampFP->enable();
_depthClampFP->bind();
}
glDisable( GL_LIGHTING );
glDisable( GL_CULL_FACE );
glDepthFunc( GL_LESS );
glDepthMask( GL_FALSE );
glColorMask( GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE );
glEnable( GL_STENCIL_TEST );
glEnable( GL_STENCIL_TEST_TWO_SIDE_EXT );
glActiveStencilFaceEXT( GL_BACK );
glStencilOp( GL_KEEP, GL_INCR_WRAP_EXT, GL_KEEP );
glStencilMask( 0xFFFFFFFF );
glStencilFunc( GL_ALWAYS, 0, 0xFFFFFFFF );
glActiveStencilFaceEXT( GL_FRONT );
glStencilOp( GL_KEEP, GL_DECR_WRAP_EXT, GL_KEEP );
glStencilMask( 0xFFFFFFFF );
glStencilFunc( GL_ALWAYS, 0, 0xFFFFFFFF );
Entity::Vec &all = Entity::shadowCasters();
Entity::Vec::iterator it( all.begin() ), end( all.end() );
for (; it != end; ++it )
{
(*it)->generateShadowVolume( lightPos );
(*it)->drawShadowVolume();
}
if ( _depthClampFP )
{
_depthClampFP->disable();
}
else if ( _depthClampAvailable )
{
glDisable( GL_DEPTH_CLAMP_NV );
}
glStencilFunc( GL_EQUAL, 0, 0xFFFFFFFF );
glStencilOp( GL_KEEP, GL_KEEP, GL_KEEP );
glDepthMask( GL_TRUE );
glEnable( GL_CULL_FACE );
glColorMask( GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE );
/*
We're ready to draw lit scene. Let caller do it.
and then call modulativeZFailFinish
*/
}
Now, what I've done is set up a test situation where I tell my code that GL_NV_DEPTH_CLAMP isn't available and force it to fall back on depth_clamp.fp -- and my video card ( 5200 Fx GO ) *ought* to be able to run the fragment shader.
Also, I've massively checked for glErrors -- profiler says I'm clean, and my own code which is peppered with calls to glError says I'm clean.
So, the question is, why's nothing happening? Is there something I'm missing?
Many moons ago, I asked what approaches I could take to emulate the depth clamp behavior on ATI cards, and Arrekusu kindly pointed out to me a fragment program from frustum.org which emulates depth clamping.
Here's the fragment shader.
!!ARBfp1.0
MOV_SAT result.depth, fragment.position.z;
END
Pretty simple, & makes sense. -- The trouble is, I can't get it to work.
So, I feel like I basically understand how to use it, but I figured I'd use frustum.org's Shader class for parsing and loading, since it's public domain anyway ( and since when I reach 1.0 I'll release my game with source, and proper attributions anyhow ).
Here are the Shader class files:
Shader.h (http://home.earthlink.net/~zakariya/files/Legion/Shader.h)
Shader.cpp (http://home.earthlink.net/~zakariya/files/Legion/Shader.cpp)
So, anyhow, in his sample code he brackets the drawing of the shadow volume as such:
... //various setup
if(have_nv3x) glEnable(GL_DEPTH_CLAMP_NV);
else {
depth_clamp_fp->enable();
depth_clamp_fp->bind();
}
... //draw extruded shadow volumes
if(have_nv3x) glDisable(GL_DEPTH_CLAMP_NV);
else depth_clamp_fp->disable();
... // cleanup
I've basically done the same thing in my code. But, nothing happens. Shadows don't draw *at all*.
Here's my code -- which is basically similar. This is just one path, I've got two-pass versions where two sided stencils aren't available, and I've also got subtractive shadowing for relatively slow machines ( like the PB I'm writing this game on :cry: )
void StencilShadow::singlePassModulative( vec4 lightPos )
{
if ( _depthClampAvailable )
{
glEnable( GL_DEPTH_CLAMP_NV );
}
else if ( _depthClampFP )
{
// I know the shader is valid
_depthClampFP->enable();
_depthClampFP->bind();
}
glDisable( GL_LIGHTING );
glDisable( GL_CULL_FACE );
glDepthFunc( GL_LESS );
glDepthMask( GL_FALSE );
glColorMask( GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE );
glEnable( GL_STENCIL_TEST );
glEnable( GL_STENCIL_TEST_TWO_SIDE_EXT );
glActiveStencilFaceEXT( GL_BACK );
glStencilOp( GL_KEEP, GL_INCR_WRAP_EXT, GL_KEEP );
glStencilMask( 0xFFFFFFFF );
glStencilFunc( GL_ALWAYS, 0, 0xFFFFFFFF );
glActiveStencilFaceEXT( GL_FRONT );
glStencilOp( GL_KEEP, GL_DECR_WRAP_EXT, GL_KEEP );
glStencilMask( 0xFFFFFFFF );
glStencilFunc( GL_ALWAYS, 0, 0xFFFFFFFF );
Entity::Vec &all = Entity::shadowCasters();
Entity::Vec::iterator it( all.begin() ), end( all.end() );
for (; it != end; ++it )
{
(*it)->generateShadowVolume( lightPos );
(*it)->drawShadowVolume();
}
if ( _depthClampFP )
{
_depthClampFP->disable();
}
else if ( _depthClampAvailable )
{
glDisable( GL_DEPTH_CLAMP_NV );
}
glStencilFunc( GL_EQUAL, 0, 0xFFFFFFFF );
glStencilOp( GL_KEEP, GL_KEEP, GL_KEEP );
glDepthMask( GL_TRUE );
glEnable( GL_CULL_FACE );
glColorMask( GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE );
/*
We're ready to draw lit scene. Let caller do it.
and then call modulativeZFailFinish
*/
}
Now, what I've done is set up a test situation where I tell my code that GL_NV_DEPTH_CLAMP isn't available and force it to fall back on depth_clamp.fp -- and my video card ( 5200 Fx GO ) *ought* to be able to run the fragment shader.
Also, I've massively checked for glErrors -- profiler says I'm clean, and my own code which is peppered with calls to glError says I'm clean.
So, the question is, why's nothing happening? Is there something I'm missing?