Stencil shadow drawing?

BlitzMax Forums/OpenGL Module/Stencil shadow drawing?

JoshK(Posted 2006) [#1]
Does anyone have any example code to setup the stencil buffer, and draw stencil shadows correctly? I have got the stencil volumes created, and just need to render them now to look like shadows, instead of big solid volumes.




Tom(Posted 2006) [#2]
Is your shadow color pure black?

If I recall correctly, in my old B3D stencil demo, the final step was to black quad over the screen and render with alpha blending on, the amount of alpha controlled how dark the stencil shadow was.

You're using GL b.t.w, right?


JoshK(Posted 2006) [#3]
Trying to render them now, but nothing appears. This is the code from the NeHe tutorial. If I just render them without stencils, it appears as it does in the image at the top of this page.

I also set the stencil bits to 8 in the setpixelformat code. I made no other changes:

gldisable GL_LIGHTING
										glcolor3f 0,0,0

										glPushAttrib(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_ENABLE_BIT|GL_POLYGON_BIT|GL_STENCIL_BUFFER_BIT)
										glDisable( GL_LIGHTING )'									Turn Off Lighting
										glDepthMask( GL_FALSE )'									Turn Off Writing To The Depth-Buffer
										glDepthFunc( GL_LEQUAL )'
										glEnable( GL_STENCIL_TEST )'								Turn On Stencil Buffer Testing
										glColorMask( GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE )'		Don't Draw Into The Colour Buffer
										glStencilFunc( GL_ALWAYS, 1, HexToInt("0xFFFFFFFFL"))

										'First Pass. Increase Stencil Value In The Shadow
										glFrontFace(GL_CCW)
										glStencilOp(GL_KEEP,GL_KEEP,GL_INCR)
										lightlink.shadowvolume.draw()
										
										'Second Pass. Decrease Stencil Value In The Shadow
										glFrontFace(GL_CW)
										glStencilOp(GL_KEEP,GL_KEEP,GL_DECR)
										lightlink.shadowvolume.draw()

										glFrontFace( GL_CCW );
										glColorMask( GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE )' 			Enable Rendering To Colour Buffer For All Components
									
										'Draw A Shadowing Rectangle Covering The Entire Screen
										glColor4f(0.0,0.0,0.0,0.4 )
										glEnable(GL_BLEND)
										glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA)
										glStencilFunc(GL_NOTEQUAL,0,HexToInt("0xFFFFFFFFL"))
										glStencilOp(GL_KEEP,GL_KEEP,GL_KEEP)
										glPushMatrix()
										glLoadIdentity()
										gldisable GL_CULL_FACE
										glBegin(GL_QUADS);
											tformpoint 10,10,10,0,camera
											glvertex3f tformedx(),tformedy(),tformedz()
											tformpoint -10,10,10,0,camera
											glvertex3f tformedx(),tformedy(),tformedz()
											tformpoint -10,-10,10,0,camera
											glvertex3f tformedx(),tformedy(),tformedz()
											tformpoint 10,-10,10,0,camera
											glvertex3f tformedx(),tformedy(),tformedz()																														
										glEnd()
										glPopMatrix()
										glPopAttrib()

										glcolor3f 1,1,1
										glenable GL_LIGHTING
										glenable GL_CULL_FACE
										gldisable GL_BLEND



JoshK(Posted 2006) [#4]
I'm a little closer now.

Should I draw one textured quad across the screen at the end of the rendering routine, or should I draw one for each shadow?


Dreamora(Posted 2006) [#5]
Would go for "per entity" for 2 reasons:

1. Normally not the whole screen is filled with shadows (at least outside Doom3), so this will save some bandwidth

2. It allows per entity shadow rendering passes. Usefull if there are situations where some shadows change but others don't and the like ...


JoshK(Posted 2006) [#6]
I found that by doing a per-entity shadow pass, I could fade the shadow with distance...as the light gets further away, and the area darkens, the shadow lightens...it's a pretty good way to blend shadows in and out.


JoshK(Posted 2006) [#7]
Here is the current state. The boxes appear correctly, but the oildrums clearly have some bad mistakes. Can anyone tell what is going on here?




Dreamora(Posted 2006) [#8]
Would say that the function that calculates the outline breaks on the concave top / bottom.
The reason I think so is the shadow part in the middle, right, where you see the bottom shadow stretch out. But you see as well, that a part is missing of it although the outline of the barrel is not "inexistant" there. It looks like the concave part was just cut out on shadow calculation.


JoshK(Posted 2006) [#9]
Edges appear to be calculating correctly:







AramusM(Posted 2006) [#10]
It looks like parts that are self shadowing only are projecting out of the object onto the wall behind as well.


Dreamora(Posted 2006) [#11]
And that they even substract from the original shadow (see the bright spot within the upper part of the barrel shadow or the backside of the barel, where the selfshadowing is broken)


AramusM(Posted 2006) [#12]
Hmm, or is it the lit part of the concave lid thats projecting a shadow through and causing the problem, yet i cant see an outline displayed for that volume.


JoshK(Posted 2006) [#13]
Do you have to eliminate edges that are within the bounds of other edges? I found the edges between triangle that face towards and away from the light, but I did not do any elimination of edges that fall within the outline of the object silhouette.


AramusM(Posted 2006) [#14]
When creating the closed volume to project the shadow it looks like the common edge of top of the can and of the back of the can have made 1 linked volume? and to make this a closed loop to project the edge of the volume has had to go into itself.

Lets see if i can do some ascii art to represent it. :)

xxxxxxxxxxx
x00000xx00x
x00000xux0x
x0000xuux0x
x000xuuux0x
x000xxxxx0x
x000000000x
xxxxxxxxxxx

the section where the '0' are would be the volume projected by the back of the can,

the section where the 'u' are would be the volume projected but the lit section on top of the can.

the 'x' are the outline.

because these have a common edge have these volumes linked to become one volume, thus when the outline is generated it has to follow the 'x' round. The 'u' area then is outside the shadow volume.

I havent tried shadows myself yet and what i've just typed is general stuff i've just picked up from articles on gamedev.net and nvidia developer section so please correct me if im talking nonsense:)


JoshK(Posted 2006) [#15]
So what do I do about it?


AramusM(Posted 2006) [#16]
To be honest i havent really looked into this much before and im just googling for answers for you.

there is a fair bit of information out there on self intersection of silhouette loops and how this can cause the problem you are seeing.

http://graphics.cs.lth.se/theses/projects/shadows/so_thesis_lq.pdf

is someones thesis i found detailing some info on shadow volumes that may be of some use.

There are some idea's i've seen while googling around about projecting your volume onto a 2d plane that faces the light sorce, then using faster 2d techniques to check for self intersections of the loop. But alot of the maths involed on those pages were beyond me and i got bored fast and moved onto other pages.

Sorry I couldnt be more help but im just googling around and understanding little(im more into creating 2d platformers etc, i havent reached the 3d age yet)


JoshK(Posted 2006) [#17]
Aw crap.

To decide which way the quads projected from the edges face, I calculated the normal of the quad (based on the first three vertex positions) and compared that to an average of the normal of the two triangles the quad's edge lies between. If the dotproduct was more than zero, I flipped the quad face. So all my volume edges are pointing on the same direction that the edge's triangles are pointing, and not in the opposite direction.

This works great for a convex outline. The outside of my shadow volume is perfect. However, it doesn't work with the smaller volume made out of the inside of the lip at the top. Although the edges form a complete loop, the sides of the volume point inward, and the bottom points up.

Is this indeed the problem?

How do I possibly figure out which direction to make the quads point? The only way I know how to is to make a list of all vertices for the loop, order them, calculate the angle change between each vertex, and add the changes up...or something like that. It sounds horribly complicated.


JoshK(Posted 2006) [#18]
HA!

The problem was which way the quads were facing.

To determine this, you take another vertex from one of the triangles, a vertex which does not form part of the edge. That point needs to lie behind the quad. Do a plane distance test with the plane equation you get from the first three vertices of the projected quad. If the distance is less than zero, reverse the order of the quad vertices.

Thanks to all that contributed.




ImaginaryHuman(Posted 2006) [#19]
Looks pretty nice. What about antialiasing and soft shadows?


JoshK(Posted 2006) [#20]
AA is already in, I just haven't been running it. The command accepts a parameter for the aa level, like 2, 4, 8 etc., and returns a value to tell if the mode was set successfully.


bytecode77(Posted 2006) [#21]
hey, great wok, i must say :) ... could you give me the code for the shadow volumes, please?

edit: oh shit this is bmx, not bb, sorry. forget this post


Drey(Posted 2006) [#22]
what type of FPS are you gettin on what computer specs?


DareDevil(Posted 2006) [#23]
what have resolved, position camera in to cone shadow?