Stencil Shadows - please help me..

Started by
14 comments, last by genesys 17 years, 4 months ago
Hi! i implemented stencil shadows in my little engine and they're finaly working... now i have two problems: 1.) it's slooooooooow! :( my process is the following: on startup, i store for every edge of a triangle its neighbour triangles on runtime, i do in every frame (since the light source is moving): -step1: loop through all faces and calculate, wether they are lit by the lightsource -step2: loop through all lit faces { loop through all three edges of the current lit face { if there is no neighbourface or the neighbourface isn't lit{ take the two vertices of the edge and calculate two more vertices by adding the lightvector to these two points; store all four points as quad in a list;}}} -step3: loop throug all quads and draw them to the stencil buffer (incr) using glBegin(GL_QUADS) and cull_face set to GL_BACK -step4: loop again through all quads and draw them to the stencil buffer (decr) using glBegin(GL_QUADS) and cull_face set to GL_FRONT -step5: draw a big black quad to the screen using the stencilbuffer as mask ... this i do in every frame . . . it's really slow - i'm already using shadow LOD (each shadow LOD model has between 30 and 50 triangles) is there anything i can improve or do differently to improve the performance?? result: http://neo.cycovery.com/stencil_problem1.gif 2.) the shadow shape is visible at this place, where the shadow volumes end: http://neo.cycovery.com/stencil_problem2.gif i understand why this effect appears, but i don't really know, what i could do against it (without decreasing the performance even more...) If somebody could help me on that or give me some hints, i'd really appreciate it! thanks a lot! [Edited by - genesys on November 27, 2006 12:46:47 PM]
Advertisement
i'm not sure if this is the answer your looking for but you could cap your shadow volume to get rid of those floating artifacts below the whole city.
Quote:2.)
the shadow shape is visible at this place, where the shadow volumes end:
http://neo.cycovery.com/stencil_problem2.gif
i understand why this effect appears, but i don't really know, what i could do against it (without decreasing the performance even more...)


Just a shot in the dark here, but couldn't you just clip the shadow ends out down there? It looks like they're being rendered far below your map...
Without order nothing can exist - without chaos nothing can evolve.
by caping you mean to trace for every quad the distance to the next object in lightvector direction and use this distance to calculate the length of the quad?

i'm afraid that this decreases my performance even more . . .
Quote:
by caping you mean to trace for every quad the distance to the next object in lightvector direction and use this distance to calculate the length of the quad?


whooooa, that sentence just blew my mind....

take a look at this page:
http://www.codesampler.com/oglsrc/oglsrc_8.htm#ogl_shadow_volume

maybe youve already been there, maybe not, itll probably give you some insight anyways
thanks for the link - but this sample is way too basic . . . my stencil shadows work - they'r just terribly slow :(

would it maybe make sense to use Vertex Arrays for the shadow volume? the vertices have to be calculated in every frame again and the count of vertices can change from frame to frame, that's why i think vertex arrays won't help me here. the same thing for display lists... since the shadow volume changes in every frame i'd have to compile the display list once per frame - i don't think this would increase the performance although i have to draw the shadowvolume twice per frame and could call the compiled displaylist when drawing it the secound time . . . or do you think a display list would help me?
maybe the answer is actually in your question...

it's slow.....why could it be slow?

judging by your second image the lightsource appears to be the sun.
you say "the light source is moving".....but shadows that the sun casts dont typically move noticeably all the time. Maybe you should do all these "COMPLEX" calculations once every 1000 frames or maybe 10,000 frames.

...

Another possible solution would be to consider another method besides shadow volumes to create shadows for buildings and other static objects. I doubt that commercial games with big citys employ a method like the one your using to shadow TONS of buildings in a city.



not trying to bash your idea or anything because i actually think the images you posted look pretty good. i would like to hear your thoughts on my feedback too.

good luck
Hi paulshady

The sun is moving verry fast.. 1 minute = 1 day.

You are right, that an image based shadow approach will create faster results and maybe is more clever for a big city...

But i'm writing an engine and this city is only one application for it - i want to make it able to serve for different needs, so i want to implement stencil shadows as performant as possible. That's why i'm asking...

at the moment it's running at 15 frames... i think one big problem is, that i have to send single GL_QUADS calls to openGL... maybe an idea how i could achieve it with less calls?
Quote:i think one big problem is, that i have to send single GL_QUADS calls to openGL... maybe an idea how i could achieve it with less calls?


You're not using immediate rendering are you? That would be pure evil.

Either way, you might find it faster to batch up your geometry into a single buffer, and then push that buffer as a quad vertex-array in a single shot when its full, or when you are finished. This way you wont be sending individual quads, but instead a single stream of data which the GPU will be able to consume much quicker.
ive done something like this before:

struct VERTEX_BUFFER
{
VECTOR3 position; //VECTOR3 is 3 floats
} * VertexBuffer;

For shadow volumes i think youll probably only need the position, otherwise you can fill up your struct with whatever else you want (UV Coords, Normals, etc...)

Anyways, put your entire list of shadow volume data in the VERTEX_BUFFER thingy.

Once you do that OGL allows this:

glInterleavedArrays( GL_V3F, 0, myMesh.VertexBuffer );
glDrawElements( GL_TRIANGLES, listSize, GL_UNSIGNED_INT, &VertexBuffer );


I definitely prefer these calls over the GlBegin() glEnd() stuff.
Let me know if youve used them before. also please don't correct my OGL syntax, i realize it might not be entirely accurate because i mainly use DirectX.


This topic is closed to new replies.

Advertisement