Odd float precision problem ( I think )
# Odd float precision problem ( I think )

**Subject**: **Odd float precision problem ( I think )**
- From: Shamyl Zakariya <email@hidden>
- Date: Fri, 20 Apr 2007 09:28:05 -0400
- Delivered-to: email@hidden
- Delivered-to: email@hidden

Hi,

`I'm seeing a minor but annoying precision problem in my z-fail shadow
volume extrusion -- or at least I assume it's a precision problem,
perhaps somebody here can help me.`
`First, here's 3 screenshots that show what I'm seeing. If you look at
them, you'll see that the shadows show weird "cracks" for lack of a
better word to describe them.`
http://zakariya.net/shamyl/Screenshots/Crack1.png
http://zakariya.net/shamyl/Screenshots/Crack2.png
http://zakariya.net/shamyl/Screenshots/Crack3.png

`What I assume here is that since I'm using z-fail shadows, I'm
projecting the end-caps of the volume as well as the back-facing
edges of the silhouette perimeter to "infinity" and perhaps they're
not quite water tight. That's the best explanation I can come up with.`
`Now, what's odd to me is that I've done z-fail implementations before
( on my old powerbook with an nvidia 5200 ) and I never saw this --
but having moved my code over to my fancy MacBook Pro with an ati
x1600 I'm seeing this for the first time. But, since I'm using ODE
( which I can't figure out how to make universal ) I can't test this
on my powerbook to see if it's causing the same problem there. So
perhaps this is an ati issue, or perhaps it's something bone-headed
in my code.`
`I'm using four implementations of shadow volume extrusion -- two on
the CPU ( directional & positional for static volumes ) and two on
the GPU ( again for directional and positional lighting ) for moving
lights or moving entities. CPU and GPU implement z-fail but
differently ( since GPU extrusion is a different can of worms ) --
but all four exhibit the same cracking I'm describing above.`
`So, I'm posting below the code for my positional light CPU shadow
volume extrusion since it makes a little more sense out of context.
Any help would be appreciated!`

class ShadowCaster
{
public:

...snip: lots of stuff...

` /**`

Generate and cache the shadow volume geometry for a

positional light @a lightPos

*/

void generateShadowVolumePositional( const sgf::vec4
&lightPos );
` /**`

Render the shadow volume generated

in generateShadowVolumePositional or
generateShadowVolumeDirectional
@note Implementation is in MeshData_Shadows.cpp
*/
void drawShadowVolume( void );

protected:

typedef std::vector< sgf::vec4 > vec4vec;

GeometryRef _geometry;
sgf::vec4 _localLight;
vec4vec _shadowVolumePoints, _shadowCapPoints;
int _shadowVolumeTop, _shadowCapTop;
bool _shadowWasDirectional;
};

`void ShadowCaster::generateShadowVolumePositional( const vec4
&lightPosition )`

{

if ( lightPosition.distance2( _localLight ) < ( 0.0001f )) return;

_localLight = lightPosition;
` vec3 lp( lightPosition.xyz() ), a, b;`

Triangle *triangles = _geometry->triangles(), *lastTriangle =
triangles + _geometry->numTriangles(), *tri = NULL;

Edge *edges = _geometry->edges(), *lastEdge = edges + _geometry-
>numEdges(), *edge = NULL;

plane *e = NULL;
vec3 *points = _geometry->vertices();
vec4 *shadowVolumePoints = &(_shadowVolumePoints.front()),
*shadowCapPoints = &(_shadowCapPoints.front());

/*
mark that shadow was not directional, so extrusion will be
in the form of quads, with both front and end caps
*/
_shadowWasDirectional = false;

` /*`

Determine triangle visibility relative to lightsource

*/

for ( tri = triangles; tri != lastTriangle; tri++ )

{

e = &tri->planeEq;

tri->lit = (e->a * lightPosition.x) + (e->b *
lightPosition.y) + (e->c * lightPosition.z) + (e->d *
lightPosition.w) > 0;

}
int shadowVolumeTop = 0;
for ( edge = edges; edge != lastEdge; edge++ )
{
bool aLit = triangles[ edge->triangleIndexA ].lit,
bLit = triangles[ edge->triangleIndexB ].lit;

/*
If both are lit, or both aren't lit, we can skip
*/
if ( aLit == bLit ) continue;

/*
Different winding depending on which triangle was lit
*/
if ( aLit && !bLit )
{
a = points[ edge->indexB ];
b = points[ edge->indexA ];

` shadowVolumePoints[ shadowVolumeTop++ ] = a;`

shadowVolumePoints[ shadowVolumeTop++ ] = vec4( ( a -
lp ), 0.0f );

shadowVolumePoints[ shadowVolumeTop++ ] = vec4( ( b -
lp ), 0.0f );

shadowVolumePoints[ shadowVolumeTop++ ] = b;

}

else

{

a = points[ edge->indexA ];

b = points[ edge->indexB ];
` shadowVolumePoints[ shadowVolumeTop++ ] = a;`

shadowVolumePoints[ shadowVolumeTop++ ] = vec4( ( a -
lp ), 0.0f );

shadowVolumePoints[ shadowVolumeTop++ ] = vec4( ( b -
lp ), 0.0f );

shadowVolumePoints[ shadowVolumeTop++ ] = b;

}
}
_shadowVolumeTop = shadowVolumeTop;

/*
Now, create the caps
*/

int shadowCapTop = 0;
for ( tri = triangles; tri != lastTriangle; tri++ )
{
if (tri->lit)
{
/*
Front cap, don't project
*/

vec4 a( points[ tri->indices[0] ] ),
b( points[ tri->indices[1] ] ),
c( points[ tri->indices[2] ] );

shadowCapPoints[ shadowCapTop++ ] = c;
shadowCapPoints[ shadowCapTop++ ] = b;
shadowCapPoints[ shadowCapTop++ ] = a;

/*
Back cap, project front triangle to
infinity but wind in reverse.
Note we don't need to normalize direction,
since we're going to infinity anyway.
*/

vec4 aInfinity( ( a - lp ), 0.0f ),
bInfinity( ( b - lp ), 0.0f ),
cInfinity( ( c - lp ), 0.0f );

shadowCapPoints[ shadowCapTop++ ] = aInfinity;
shadowCapPoints[ shadowCapTop++ ] = bInfinity;
shadowCapPoints[ shadowCapTop++ ] = cInfinity;
}
}

_shadowCapTop = shadowCapTop;
}

void ShadowCaster::drawShadowVolume( void )
{
glBindBuffer( GL_ARRAY_BUFFER, 0 );

/*
Volume needs to be pushed *backwards* in depth buffer so
as to eliminate z-fighting with occluder geometry
*/
PolygonOffset::push( 1.0f, 2.0f );

` glEnableClientState( GL_VERTEX_ARRAY );`

glVertexPointer( 4, GL_FLOAT, 0, &(_shadowVolumePoints.front()) );

glDrawArrays( _shadowWasDirectional ? GL_TRIANGLES : GL_QUADS,
0, _shadowVolumeTop );

glVertexPointer( 4, GL_FLOAT, 0, &(_shadowCapPoints.front()));
glDrawArrays( GL_TRIANGLES, 0, _shadowCapTop );

PolygonOffset::pop();
glDisableClientState( GL_VERTEX_ARRAY );
}

email@hidden
"shaking fist at indifferent cosmos"

_______________________________________________
Do not post admin requests to the list. They will be ignored.
Mac-opengl mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
`This email sent to email@hidden
`