PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Was ist an meinem Shadow Volume falsch?


Simon
2004-06-15, 12:39:07
Hallo,

ich hab versucht, Stencil Shadow Volumes zu implementieren. Klappt soweit auch gut, das Volume wird richtig erstellt. Nur wenn ich jetzt ein großes Quad über den Viewport zeichne, um den Bildschirm abzudunkeln, dann wird alles abgedunkelt und nicht nur der Bereich des Volumes :(
Hier mein Code:

void C3DObject::DrawShadowVolumeToStencil(vector vLightPosition)
{
/* Get modelview matrix */
Matrix44 mModelView, mInvModelView;

glGetFloatv(GL_MODELVIEW_MATRIX, (GLfloat*) mModelView);
/* and invert it */
InvertMatrix(mModelView, mInvModelView);

/* calculate object space light position */
vector vOSLightPosition;
vOSLightPosition.x = vLightPosition.x * mInvModelView[ 0 + 4 * 0 ] +
vLightPosition.y * mInvModelView[ 0 + 4 * 1 ] +
vLightPosition.z * mInvModelView[ 0 + 4 * 2 ] + mInvModelView[ 0 + 4 * 3 ];
vOSLightPosition.y = vLightPosition.x * mInvModelView[ 1 + 4 * 0 ] +
vLightPosition.y * mInvModelView[ 1 + 4 * 1 ] +
vLightPosition.z * mInvModelView[ 1 + 4 * 2 ] + mInvModelView[ 1 + 4 * 3 ];
vOSLightPosition.z = vLightPosition.x * mInvModelView[ 2 + 4 * 0 ] +
vLightPosition.y * mInvModelView[ 2 + 4 * 1 ] +
vLightPosition.z * mInvModelView[ 2 + 4 * 2 ] + mInvModelView[ 2 + 4 * 3 ];

//vOSLightPosition = vLightPosition;

for(uint f=0; f < m_uiNumOfFaces; f++)
{
Face* pFace = &m_pFaces[f];

float F = pFace->m_vNormal.x * vOSLightPosition.x +
pFace->m_vNormal.y * vOSLightPosition.y +
pFace->m_vNormal.z * vOSLightPosition.z;
if(F + pFace->m_fDistanceToOrigin > 0.0f)
pFace->m_bFacesLight = true;
else
pFace->m_bFacesLight = false;
}
glEnable(GL_CULL_FACE);
glFrontFace(GL_CCW);

// Vorbereiten von Stencil Buffer zeichnen
glDisable( GL_LIGHTING );
glDepthFunc( GL_LEQUAL );
glDepthMask( GL_FALSE );

glEnable( GL_STENCIL_TEST );
glColorMask( 0, 0, 0, 0 );
glStencilFunc( GL_ALWAYS, 1, 0xffffffff );

// 1. Pass: Zeichnen der Frontfacing Polygone des Shadow Volumes, Stencil Buffer inkrementieren
glFrontFace( GL_CCW );
glStencilOp( GL_KEEP, GL_KEEP, GL_INCR );

glDepthFunc(GL_LEQUAL);
glDepthMask(0);

glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

glColor4f(0,0,1,.4);

for(uint f=0; f < m_uiNumOfFaces; f++)
{
Face* pFace = &m_pFaces[f];

if(pFace->m_bFacesLight)
{
Face* k;
for(uint j=0; j < 3; j++)
{
if ( ( k = pFace->m_pAdjacentFaces[j] ) != NULL && !k->m_bFacesLight )
{
// Ja, es gibt eins und es ist vom Licht abgewandt
// => Polygon bilden und in den Stencil Buffer zeichnen

vector *e1 = &m_pVertices[ pFace->p[j] ];
vector *e2 = &m_pVertices[ pFace->p[(j+1)%3] ];
vector e3, e4;
e3 = *e1 + ( *e1 - vOSLightPosition ) * m_fExtrusionLength;
e4 = *e2 + ( *e2 - vOSLightPosition ) * m_fExtrusionLength;

glBegin( GL_TRIANGLE_STRIP );
glVertex3fv( (GLfloat*)e1 );
glVertex3fv( (GLfloat*)&e3 );
glVertex3fv( (GLfloat*)e2 );
glVertex3fv( (GLfloat*)&e4 );
glEnd();
}
}
}
}
// 2. Pass: Zeichnen der Backfacing Polygone des Shadow Volumes, Stencil Buffer dekrementieren
glFrontFace( GL_CW );
glStencilOp( GL_KEEP, GL_KEEP, GL_DECR );
glColor4f(1,1,0,.4);


for(uint f=0; f < m_uiNumOfFaces; f++)
{
Face* pFace = &m_pFaces[f];

if(pFace->m_bFacesLight)
{
Face* k;
for(uint j=0; j < 3; j++)
{
if ( ( k = pFace->m_pAdjacentFaces[j] ) != NULL && !k->m_bFacesLight )
{
// Ja, es gibt eins und es ist vom Licht abgewandt
// => Polygon bilden und in den Stencil Buffer zeichnen

vector *e1 = &m_pVertices[ pFace->p[j] ];
vector *e2 = &m_pVertices[ pFace->p[(j+1)%3] ];
vector e3, e4;
e3 = *e1 + ( *e1 - vOSLightPosition ) * m_fExtrusionLength;
e4 = *e2 + ( *e2 - vOSLightPosition ) * m_fExtrusionLength;

glBegin( GL_TRIANGLE_STRIP );
glVertex3fv( (GLfloat*)e1 );
glVertex3fv( (GLfloat*)&e3 );
glVertex3fv( (GLfloat*)e2 );
glVertex3fv( (GLfloat*)&e4 );
glEnd();
}
}
}
}

glFrontFace( GL_CCW );
glColorMask( 1, 1, 1, 1 );

glDepthFunc( GL_LEQUAL );
glDepthMask( GL_TRUE );
glEnable( GL_LIGHTING );
glDisable( GL_STENCIL_TEST );

glDisable(GL_BLEND);
}

void C3DObject::FinishShadow()
{
glDisable( GL_LIGHTING );
glDepthFunc( GL_LEQUAL );
glDepthMask( GL_FALSE );
glEnable( GL_STENCIL_TEST );

glColor4ub( 0, 0, 0, 128 );

glEnable( GL_BLEND );
glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );

glStencilFunc( GL_NOTEQUAL, 0, 0xffffffff );
glStencilOp( GL_KEEP, GL_KEEP, GL_KEEP );

glMatrixMode( GL_MODELVIEW );
glPushMatrix();
glLoadIdentity();

glMatrixMode( GL_PROJECTION );
glPushMatrix();
glLoadIdentity();

glDisable( GL_DEPTH_TEST );
glBegin( GL_TRIANGLE_STRIP );
glVertex2i( -1, 1 );
glVertex2i( -1, -1 );
glVertex2i( 1, 1 );
glVertex2i( 1, -1 );
glEnd();
glEnable( GL_DEPTH_TEST );

glPopMatrix();
glMatrixMode( GL_MODELVIEW );
glPopMatrix();

glDisable( GL_BLEND );

glDepthFunc( GL_LEQUAL );
glDepthMask( GL_TRUE );
glEnable( GL_LIGHTING );
glDisable( GL_STENCIL_TEST );
}

Also, erst wird für alle Occluder C3DObject::DrawShadowVolumeToStencil(vector vLightPosition) aufgerufen und ganz zuletzt dann einmal void C3DObject::FinishShadow().
Leider seh ich den Fehler nicht :(
Hat jemand einen Tip für mich?

Danke und bye, Enrico

Simon
2004-06-15, 13:45:36
nach ein bischen Abstand hatte ich den Fehler: Muss natürlich glStencilFunc( GL_NOTEQUAL, 0, 0x1); sein. Nur ist jetzt die Erstellung meines Volumes falsch....