Skip to main content
gamedev.net
🔒 Locked

Stencil shadow using depth pass problem

Started by Rizokuri 1 reply 700+ views
Original Post
Rizokuri
Rizokuri
Hi,
i'm trying to implement shadow volumes, and i've been stuck for a few days now. It works perfectly fine with simple models like cube, but if I use a complex model, it shows artifacts:



My first thought was that the volume wasn't properly generated, but after carefully inspecting the code, I can't find the error... Anyway, if someone could help, it would be great. Here is the code:

void findSilhouetteEdge( SubMesh* sm, Vector3d* lightPos, std::vector< Vertex* >& silhouette, std::vector< Face* >& facesInLight ){	int* faceInShadow = new int[ sm->getNumberOfFaces() ];;	for( int j=0; j<sm->getNumberOfFaces(); j++ )		faceInShadow[ j ] = -1;	for( int j=0; j<sm->getNumberOfFaces(); j++ )	{		Face* f = sm->getFace( j );		if( faceInShadow[ j ] == -1 )			faceInShadow[ j ] = ( GeometryUtil::dot( *lightPos, *f->normal ) <= 0 )?true:false;		if( !faceInShadow[ j ] )		{			facesInLight.push_back( sm->getFace( j ) );	 			for( std::map< std::pair<int,int>,Face* >::const_iterator faceIt = f->neighboors.begin(); faceIt != f->neighboors.end(); ++faceIt )			{				Face* neighboor = faceIt->second;								if( faceInShadow[ neighboor->indexInList ] == -1 )					faceInShadow[ neighboor->indexInList ] = ( GeometryUtil::dot( *lightPos, *(neighboor->normal) ) <= 0 )?true:false;								if( faceInShadow[ j ] != faceInShadow[ neighboor->indexInList ] )				{					// the common edge is part of the silhouette					for( int k=0; k<neighboor->getNbVertices(); k++ )					{						for( int l=0; l<f->getNbVertices(); l++ )						{							if( neighboor->getVertexInd(k) == f->getVertexInd(l) )								silhouette.push_back( sm->getVertex( neighboor->getVertexInd(k) ) );						}					}				}			}		}		if( f->neighboors.size() < f->getNbVertices() )		{			for( int l=0; l<f->getNbVertices(); l++ )			{				std::pair<int,int> edge1;				std::pair<int,int> edge2;				if( l != f->getNbVertices()-1 )				{					edge1 = std::pair<int,int>( f->getVertexInd(l), f->getVertexInd(l+1) );					edge2 = std::pair<int,int>( f->getVertexInd(l+1), f->getVertexInd(l) );				}				else				{					edge1 = std::pair<int,int>( f->getVertexInd(l), f->getVertexInd(0) );					edge2 = std::pair<int,int>( f->getVertexInd(0), f->getVertexInd(l) );				}				if( f->neighboors.find( edge1 ) == f->neighboors.end() && f->neighboors.find( edge2 ) == f->neighboors.end() )				{					silhouette.push_back( sm->getVertex( edge2.first ) );					silhouette.push_back( sm->getVertex( edge2.second ) );				}			}						}	}	delete faceInShadow;}


void drawSilhouetteShadowVolume( Vector3d* lightPos, std::vector< Vertex* > silhouette ){	for( int j=0; j<silhouette.size()-1; j+=2 )	{		Vertex* v1 = silhouette.at( j );		Vertex* v2 = silhouette.at( j+1 );		Vector3d v1proj( ( (v1->getCoordinates().x - lightPos->x) * M_INFINITY ) + lightPos->x,						 ( (v1->getCoordinates().y - lightPos->y) * M_INFINITY ) + lightPos->y,						 ( (v1->getCoordinates().z - lightPos->z) * M_INFINITY ) + lightPos->z );		Vector3d v2proj( ( (v2->getCoordinates().x - lightPos->x) * M_INFINITY ) + lightPos->x,						 ( (v2->getCoordinates().y - lightPos->y) * M_INFINITY ) + lightPos->y,						 ( (v2->getCoordinates().z - lightPos->z) * M_INFINITY ) + lightPos->z );		glBegin(GL_QUADS);		glVertex3f( v1->getCoordinates().x,v1->getCoordinates().y,v1->getCoordinates().z );		glVertex3f( v2->getCoordinates().x,v2->getCoordinates().y,v2->getCoordinates().z );		glVertex3f( v2proj.x,v2proj.y,v2proj.z );		glVertex3f( v1proj.x,v1proj.y,v1proj.z );		glEnd();	}}


void drawShadowVolume( Mesh* m, Vector3d* lightPos ){	for( int i=0; i < m->getNumSubMeshes(); i++ )	{		SubMesh* sm = m->getSubMesh( i );		std::vector< Vertex* > silhouette;		std::vector< Face* > facesInLight;		findSilhouetteEdge( sm, lightPos, silhouette, facesInLight );		if( silhouette.size() == 0 )			continue;		//depth-pass		glCullFace(GL_BACK);		glStencilFunc(GL_ALWAYS, 0x0, 0xff);		glStencilOp(GL_KEEP, GL_KEEP, GL_INCR);		drawSilhouetteShadowVolume( lightPos, silhouette );		glCullFace(GL_FRONT);		glStencilFunc(GL_ALWAYS, 0x0, 0xff);		glStencilOp(GL_KEEP, GL_KEEP, GL_DECR);		drawSilhouetteShadowVolume( lightPos, silhouette );	}	}


void Graphics::render(){      // render scene with only ambient light	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);	glEnable(GL_DEPTH_TEST);         glEnable(GL_CULL_FACE);         glCullFace(GL_BACK);           glDisable(GL_BLEND);   	glDepthFunc(GL_LESS);        glDepthMask(GL_TRUE);  	glEnable(GL_COLOR_MATERIAL);	glDisable(GL_LIGHT0);        drawScene();         glDisable(GL_LIGHTING);        glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);	glEnable(GL_CULL_FACE);	glDepthMask(GL_FALSE);	glEnable(GL_STENCIL_TEST);	glClear(GL_STENCIL_BUFFER_BIT);	glStencilFunc(GL_ALWAYS, 0, 0);	glEnable(GL_POLYGON_OFFSET_FILL);	glPolygonOffset(0.0f, 100.0f);         // here we draw the shadow volumes	if( shadowEnabled )	{		//for each light draw shadow volumes				std::map< int, Entity* > entities = sceneMgr->getEntities();		for( std::map< int, Entity* >::const_iterator it = entities.begin(); it != entities.end(); ++it )		{			if( it->second->castsShadow() )			{								glPushMatrix();				Mesh* m = it->second->getMesh();				drawShadowVolume( m, lightPos );					glPopMatrix();			}		}	}	// draw lit scene        glCullFace(GL_BACK);         glDepthFunc(GL_LEQUAL);         glEnable(GL_BLEND); 	glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);  	glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);	glEnable(GL_LIGHT0);	glStencilFunc(GL_EQUAL, 0, 0xff);	drawScene(); 	glDisable(GL_COLOR_MATERIAL);        glDepthMask(GL_TRUE);  }


Thanks !
Geometrian
Geometrian
Hi,

Without examining your code too closely, you might try a more complex, but still simple object.

You need to be certain that your objects have only one layer of polygons, (and that they have face normals, if your implementation doesn't take that into account).

-G
[size="1"]And a Unix user said rm -rf *.* and all was null and void...|There's no place like 127.0.0.1|The Application "Programmer" has unexpectedly quit. An error of type A.M. has occurred.
[size="2"]
Rizokuri
Rizokuri
Hey thanks ! I solved my problem. There was a bug in my silhouette generation function: in some cases the edge wasn't correctly oriented...

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.