Part of the Khronos Group
OpenGL.org

The Industry's Foundation for High Performance Graphics

from games to virtual reality, mobile phones to supercomputers

Page 1 of 2 12 LastLast
Results 1 to 10 of 17

Thread: some (advanced) shadow volumes questions

  1. #1
    Member Regular Contributor
    Join Date
    Jul 2005
    Location
    Germany
    Posts
    311

    some (advanced) shadow volumes questions

    i read Eric Lengyel's article on stencil shadow volumes on gamasutra and adapted his improvements to my existing code, works great i still have some questions though:

    - he suggests to use an infinite projection matrix. should i use this projection all the time or just when i extrude my shadow volumes?

    - how can i perform frustum and occlusion culling for meshes that can potentially cast shadows? i cannot cull an object just because it's outside the frustum, as it could still cast a shadow into the frustum.. how do you do it instead?

    - i thought about faking soft shadows by rendering the stencil mask to a texture, blurring it and use the result in a shader, similar to a shadow map. does that make sense or is it a silly idea?

    -what can i do to prevent those "popping" self-shadows?

    thanks!

  2. #2
    Senior Member OpenGL Guru Humus's Avatar
    Join Date
    Mar 2000
    Location
    Stockholm, Sweden
    Posts
    2,444

    Re: some (advanced) shadow volumes questions

    The soft shadows idea isn't that bad, I did something similar with shadow mapping here:
    http://www.humus.ca/index.php?page=3D&ID=54

    The only think you need to keep in mind is weight samples in your blur according to depth difference to avoid light and shadow bleeding across from the background or foreground.

  3. #3
    Senior Member OpenGL Pro cass's Avatar
    Join Date
    Feb 2000
    Location
    Austin, TX, USA
    Posts
    1,058

    Re: some (advanced) shadow volumes questions

    Hi Vexator,

    I'll answer the first two questions since they're easier.

    1. If you use the infinite projection matrix, you need to use it all the time.

    2. You need to check if the shadow volume is in the intersection of the light volume and the view frustum. This isn't too hard if you use basic bounding volumes.

    I'll hand wave on the other two.

    3. Humus's idea may be good. There's also the penumbra wedges approach that Thomas Moller came up with. I haven't studied the problem much.

    4. There are a number of tricks, and I've even written some ideas about it, but nothing that could be called truly robust.

    Hope this helps some.

    Cass
    Cass Everitt -- cass@xyzw.us

  4. #4
    Junior Member Regular Contributor
    Join Date
    Jul 2000
    Location
    Roseville, CA
    Posts
    162

    Re: some (advanced) shadow volumes questions

    Originally posted by Vexator:

    - how can i perform frustum and occlusion culling for meshes that can potentially cast shadows? i cannot cull an object just because it's outside the frustum, as it could still cast a shadow into the frustum.. how do you do it instead?
    Hi --

    You need to cast shadows for objects that intersect the convex hull formed by the view frustum and the light source. There are a bunch more details in the GDC presentations linked on the front page of terathon.com.

    -- Eric Lengyel

  5. #5
    Member Regular Contributor
    Join Date
    Jul 2005
    Location
    Germany
    Posts
    311

    Re: some (advanced) shadow volumes questions

    wow thanks for the helpful replies i'll read through your presentation, eric, thanks. regarding popping self-shadows: i took a look at the shadow volumes demo in the nvidia sdk and they are dividing the geometry of the shadow caster into polygons that face the the light and polygons that do not.. for the ones that do not face it, they call this:

    glStencilFunc(GL_GEQUAL, 129, ~0); // don't shadow polys that backface the light and are only in one shadow volume

    why? and how can i implement this if i'm using vbo's, where i do not have access to single vertices? @cass: what are those tricks you have? would you share them with me?

    thanks

  6. #6
    Senior Member OpenGL Pro cass's Avatar
    Join Date
    Feb 2000
    Location
    Austin, TX, USA
    Posts
    1,058

    Re: some (advanced) shadow volumes questions

    The trick in the NVIDIA demo is mine.

    Assuming you have to know which way each face of the model points when generating the shadow volume, you can use that to generate two separate index lists for rendering the faces that face toward then the faces that face away from the light.

    You don't need a new VBO for vertex positions, but you do need new index lists.
    Cass Everitt -- cass@xyzw.us

  7. #7
    Senior Member OpenGL Pro cass's Avatar
    Join Date
    Feb 2000
    Location
    Austin, TX, USA
    Posts
    1,058

    Re: some (advanced) shadow volumes questions

    Oh, and the reason it's not really robust is that you're relying on shading to darken the face, not the shadowing calculation.

    Shading isn't guaranteed to do the right thing, but it usually does. And the artifacts are less objectionable because they don't tend to pop.
    Cass Everitt -- cass@xyzw.us

  8. #8
    Member Regular Contributor
    Join Date
    Jul 2005
    Location
    Germany
    Posts
    311

    Re: some (advanced) shadow volumes questions

    ok i'll give it a try. it's ok if it works in most cases, still better than those popping artefacts

    btw another question - so far i was using immediate mode to draw my shadow silhouette, like this (yes i know, i do not have to recompute the silhouette every frame and i do not need the caps in all cases, still have to fix this):

    Code :
    void Group::ExtrudeSilhouette( const Vector3D translation )
    {
    	// for all polygons..
        for( unsigned int i = 0; i < m_vpkPolygons.size(); i++ )
    	{
    		// get polygon
    		Polygon *pkPolygon = m_vpkPolygons[i];
     
    		// check if it's visible
            if( !pkPolygon->m_bIsVisible )
    			continue;
     
    		// construct volume's caps
            glBegin( GL_TRIANGLES );
    		glVertex3fv( m_vpkVertices[(i*3)] );
    		glVertex3fv( m_vpkVertices[(i*3)+1] );
    		glVertex3fv(m_vpkVertices[(i*3)+2] );
    		glVertex3fv( m_vpkVertices[(i*3)]+(m_vpkVertices[(i*3)]-translation)*100.0f );
    		glVertex3fv( m_vpkVertices[(i*3)+2]+(m_vpkVertices[(i*3)+2]-translation)*100.0f );
    		glVertex3fv( m_vpkVertices[(i*3)+1]+(m_vpkVertices[(i*3)+1]-translation)*100.0f );
            glEnd();
     
    		// for every vertex..
            for( unsigned int j = 0; j < 3; j++ )
    		{
    			// get neighbor
    			int k = pkPolygon->m_aiNeighbors[j];
     
    			// if there's no neighbour or the neighbour isn't visible..
    			if( (!k) &amp;#0124;&amp;#0124; (!m_vpkPolygons[k-1]->m_bIsVisible) )
                {
    				// get the edges..
    				Vector3D &amp;kVertex1 = m_vpkVertices[(i*3)+j];
    				Vector3D &amp;kVertex2 = m_vpkVertices[(i*3)+(j+1)%3];
     
    				// extrude them..
                    Vector3D kVertex3 = kVertex1+(kVertex1-translation)*100.0f;
                    Vector3D kVertex4 = kVertex2+(kVertex2-translation)*100.0f;
     
    				// and construct volume
                    glBegin( GL_TRIANGLE_STRIP );
    				glVertex3fv( kVertex1 );
    				glVertex3fv( kVertex3 );
    				glVertex3fv( kVertex2 );
    				glVertex3fv( kVertex4 );
                    glEnd();
    			}
    		}
    	}
    }
    now i thought it's probably faster to use a vertex array, like this:

    Code :
    void Group::ExtrudeSilhouette( const Vector3D translation )
    {
    	vector<Vector3D> m_vpkSilhouetteVertices;
     
    	// for all polygons..
        for( unsigned int i = 0; i < m_vpkPolygons.size(); i++ )
    	{
    		// get polygon
    		Polygon *pkPolygon = m_vpkPolygons[i];
     
    		// check if it's visible
            if( !pkPolygon->m_bIsVisible )
    			continue;
     
    		// construct volume's caps
    		m_vpkSilhouetteVertices.push_back( m_vpkVertices[(i*3)] );
    		m_vpkSilhouetteVertices.push_back( m_vpkVertices[(i*3)+1] );
    		m_vpkSilhouetteVertices.push_back( m_vpkVertices[(i*3)+2] );
    		m_vpkSilhouetteVertices.push_back( m_vpkVertices[(i*3)]+(m_vpkVertices[(i*3)]-translation)*100.0f );
    		m_vpkSilhouetteVertices.push_back( m_vpkVertices[(i*3)+2]+(m_vpkVertices[(i*3)+2]-translation)*100.0f );
    		m_vpkSilhouetteVertices.push_back( m_vpkVertices[(i*3)+1]+(m_vpkVertices[(i*3)+1]-translation)*100.0f );
     
    		// for every vertex..
            for( unsigned int j = 0; j < 3; j++ )
    		{
    			// get neighbor
    			int k = pkPolygon->m_aiNeighbors[j];
     
    			// if there's no neighbour or the neighbour isn't visible..
    			if( (!k) &amp;#0124;&amp;#0124; (!m_vpkPolygons[k-1]->m_bIsVisible) )
                {
    				// get the edges..
    				Vector3D &amp;kVertex1 = m_vpkVertices[(i*3)+j];
    				Vector3D &amp;kVertex2 = m_vpkVertices[(i*3)+(j+1)%3];
     
    				// extrude them..
                    Vector3D kVertex3 = kVertex1+(kVertex1-translation)*100.0f;
                    Vector3D kVertex4 = kVertex2+(kVertex2-translation)*100.0f;
     
    				// and construct volume
    				m_vpkSilhouetteVertices.push_back( kVertex1 );
    				m_vpkSilhouetteVertices.push_back( kVertex3 );
    				m_vpkSilhouetteVertices.push_back( kVertex2 );
    				m_vpkSilhouetteVertices.push_back( kVertex2 );
    				m_vpkSilhouetteVertices.push_back( kVertex3 );
    				m_vpkSilhouetteVertices.push_back( kVertex4 );
    			}
    		}
    	}
     
    	glEnableClientState( GL_VERTEX_ARRAY );
    	glVertexPointer( 3, GL_FLOAT, 0, &amp;(m_vpkSilhouetteVertices[0]) );
    	glDrawArrays( GL_TRIANGLES, 0, m_vpkSilhouetteVertices.size() );
    	glDisableClientState( GL_VERTEX_ARRAY );
    }
    however, this is much slower, 25fps compared to 35fps - wtf?

  9. #9
    Intern Contributor
    Join Date
    Apr 2005
    Location
    Prague, Czech Republic
    Posts
    89

    Re: some (advanced) shadow volumes questions

    well drawing your geometry with vertex arrays should never be slower then immediate mode ( but they are often not much faster ). So I think that your problem is probably with generating the array for VAs.

    The problem may be connected with your usage of vector<Vector3D> m_vpkSilhouetteVertices;

    I'm not sure how the vector class is implemented but I think that each time you call push_back() on it the whole array is reallocated and it can slow down the whole process ( and you call this method really often ). You can try to pre-allocate it with reserve() method ( just compute how much memory you will need, it doesnt have to be accurate so you can just compute max possible memory you will need ). Maybe the problem is elsewhere but you can give it a try.

  10. #10
    Member Regular Contributor Jackis's Avatar
    Join Date
    Sep 2005
    Location
    Saint-Petersburg, Russia
    Posts
    279

    Re: some (advanced) shadow volumes questions

    BTW, push_back() in standard vector, based on array allocator, is fast enough. If capacity is not enough, it doubles it, so, I hope, push_back isn't a bottleneck.

    But, just for the case, it's a good idea to reserve needed capacity.
    Also, your vertex array is in system memory, this is awfully bad, try using VBOs instead.

    If your vertex light position changes rarely (less, then once per frame) - you shouldn't do vertex-array filling every time you draw your extruded silhouette.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •