Shadow Volume SceneProcessor

Hi,

I’ve been working on a new and improved Shadow Volume SceneProcessor based on the JME2 one, with a few improvements.


  • New: More/better Caching (caching some stuff per Mesh, and others per Geometry

  • New: Support for inefficient shapes (i.e. ones with edges that share coordinates but do not share indexes)

  • New: Works in JME3 (80% of the old code has been modified, rewritten, or is new)

  • New: Trivial to use (just 2 lines of code to add the scene processor)

  • New: Surface bias to make it look better

  • New: No issues with being inside of the shadow (modified z-fail)

  • Trivial to use (rootNode.setShadowMode(ShadowMode.CastAndReceive);)

  • No aliasing

  • Requires my StencilBuffer addition to RenderState
  • Coming soon: optimized shadow volumes for spheres



Note: The two existing shadow methods (Basic and PSSM) are likely better for most game applications: high poly count, high numbers of lights, anything with moving lights, or large numbers of moving objects, and anything with partially transparent shadow casters, but worse for other applications: distant shadow casters, large static scenes, surface-self shadowing (at least until biasing is properly used in them- the demos don't seem to use it), and other specific cases.

In my case I want to do space scenes with relatively few objects, at relatively large distances, so shadow volumes work well and look good.

Screenshots:
Based on the PSSM Test:
http://i.imgur.com/TG5db.jpg
http://i.imgur.com/VH679.jpghttp://i.imgur.com/MtfVc.jpg
(Note, framerates are lower than they could be because I have moving objects in the scene)

Here is the code for the ShadowVolumeRenderer:
https://bitbucket.org/josephduchesne/shadowvolumes-for-jmonkeyengine3/src/175f1ebcb576/src/mygame/

main.java is the test file.

If you have any comments, questions, or concerns let me know :)

A note on the usage of z-fail: The patent specifically requires incrementing the stencil on back face depth fail, and decrementing on the front face. My code does the opposite: it decrement-wraps on back face fail, and increment-wraps on front face fail. Additionally this is done in one step using new two sided stencil buffer functionality in OpenGL 2.0. To my knowledge this implementation is non-infringing, however it's trivial to modify it to z-pass, although that reintroduces camera placement issues.
7 Likes

Good job! By the way, does it handle multiple lights? How about point lights?

The primary issue with Basic and PSSM shadows is that they only support a single directional light, this makes it very difficult to use them for indoor terrains.

Multiple lights should work just fine, update speed is linear with the number of lights based on the code… let me actually test that :stuck_out_tongue:



My tests:



Two directional lights:

http://i.imgur.com/4g8m3.png

As you can see, I’m only doing one stencil pass for all shadow volumes, so shadows are not additive. I should probably make it an option to do multiple passes (boolean), because I can think of times when you’d want one or the other.



A point light (not quite working yet)

http://i.imgur.com/mpP4f.png

This demonstrates a directional light. The code I had up in the repo this morning didn’t support point lights, but only because I had some debugging stuff forcing all lights to be directional. I’ve changed the 2-3 lines and pushed the changeset to bitbucket, but as the screenshot kindof shows, something’s screwing up with point lights, although it’s very clearly nearly functioning. To be honest I had intended to support them, but entirely forgot about it, so the fact that it works at all is nice. I suspect that I’m miscalculating something to do with them that will be fairly easy to discover.

Great work, thanks for sharing :slight_smile:

Out of intrest, how are multiple static shadow volumes are handled? Are the batched into one larger ? As the only problem I see is the possibility of havig to mcuh objects.



However since I’m working on a space game too I’m really intrested in this.

(Shadowvolumes for static objects and ppsm or dynamic might be a fast solution, at least I hope)

This is AWESOME!!! :smiley: :smiley: :smiley:

Waiting to get my hand on it :smiley:

Shadow volumes are handled like this:

  • Edge/face geometry created the first time a Mesh is used and then reused every time a model using that mesh is created by ShadowVolumeRenderer. (This is the most expensive part of creating the shadow volumes).
  • GeometryShadows caches Geometry and Light transforms on a per geometry basis, and caches the shadow volumes for each shadow of the geometry (via the ShadowEdge ShadowTriangle and ShadowVolume classes). These are updated whenever something moves basically. If a light moves then all of the shadow volumes created by that light are updated, while if an object moves, just that object’s SV is updated. There is code from the JME2 version for throttling updates but I don’t think it works quite yet.



    Having a large number of static objects and static lights shouldn’t be a problem, but if you had more than about 20 high poly count objects (most space ships probably don’t count) things might get slow.



    As for running both shadow renderers, it’s possible with minor changes but JME3 doesn’t really have a way of choosing one technique over the other on a per model basis at the moment. It wouldn’t be hard to implement though.

hey nice work!

That’s good to have an alternative to shadow mapping or pssm.

Thank you for sharing this, we definitely gonna add it to the core.

nehon said:
hey nice work!
That's good to have an alternative to shadow mapping or pssm.
Thank you for sharing this, we definitely gonna add it to the core.


Glad to hear it. I'm just going to see if I can get point lighting to work. The project that I needed Shadow Volumes for has been put on hold so I figured that I might as well just try to get my work out there so that it doesn't go to waste. Once I'm happy with it (eta one week most likely) I'll create a post in the contributions forum for it :)
1 Like

Any more recent news on this? I’d love to have access to a shadowing technique that doesn’t result in all-parallel shadows and can handle multiple light sources. I was more than a little shocked / disappointed when I discovered that JME3 didn’t support something like that already.



Does this technique work correctly with transparent / translucent objects?

DemonWasp said:
I was more than a little shocked / disappointed when I discovered that JME3 didn't support something like that already.

Must have been soooo hard for you, we are so sorry.....
Well you can contribute your own shadow renderer we'll be glad to add it to the core...

Woah, sorry, wasn’t meaning to be derogatory. I was meaning “JME is so great I was surprised this feature wasn’t already there”. It just seems like one of the first things to be done.

Well I’m sorry too, never mind :wink:



In fact directional shadow mapping works fine for wide area and I think it’s the most used shadow technique. That’s why once it was implemented we relied on it.

But shadow mapping for point lights is definitely planned too.



Also this shadow Volume renderer will be added to the core pretty soon, I don’t know if it works for transparent materials though.

Hmm…as another question, is it possible to combine shadowing techniques? Say for example you have a character carrying a torch (point light) at dusk. You’d probably want to use a directional light + PSSM for the sunlight, but you’d also want to use point light + shadow volumes for the torch. Would the two play nicely together?



I ask because I actually have very little background in how 3D rendering works, so despite reading the papers on PSSM I have no idea how it works.

It should, but honestly, it has to be tested.

One thing to know though is that dynamic shadows are expensive, if you have this kind of scene, with dark corridors, consider using light maps (pre baked shadow maps) for the scene and dynamic shadows for the point light.

Combining the rendering methods will run into some slight architectural issues if my memory serves me:



Both methods use the same shadow caster flag to determine which objects should cast shadows. This is a problem as it requires that all shadow processing techniques can only act on the same objects. A solution may be to either use a more general purpose flag to determine which objects should cast shadows (for example user object user data). I considered this initially but then decided that I’d rather integrate with the existing code instead of breaking the standard that exists. There is no technical reason why we can’t use both for different light sources, it’s trivial code to fix, but it requires architectural changes that I would rather not get into at the moment.



One problem with using shadow volumes for a torch is that you would be recalculating all nearby objects’ shadow every frame. While you could likely do this for a dozen high poly objects and a few dozen low poly objects, anything past that will bring any computer to its knees. Luckily, once this shadow volume stuff is more functional you’ll be able to easily test a moving point light source.



I’m afraid I haven’t been able to devout much time to getting point sources working (the project that I was going to use JME3 on has been postponed for a fairly long time), but I have recently been added as a comitter to the JME3 project, so you should be able to test this out soon (and maybe give me a hand if you can :stuck_out_tongue: ) if you have an SVN version of JME3 handy. I do plan on getting shadow volumes fully functional for both point light and directional light sources, and integrated into the engine if I can.

1 Like

I really appreciate the effort you, and everyone else on the project, is putting into this.



I have a mediocre background in math (I’m halfway through a CS degree at UWaterloo), but I have almost no experience in working with 3D rendering software, or even real-time systems. I’d be more than happy to help, but I have essentially no idea how to get started. Is there a tutorial for would-be contributors, or a book I should be reading? I’m not against spending some money to learn about these things. At the moment JME is sort of a magical black box that I feed a scene into to produce an image.



The question that keeps coming up in my mind is: how do the professional games do it? If you look at a game like Thief 3 (not even all that graphically impressive, to be honest), it manages to have dozens of point light sources in any given scene (torches) casting real-time shadows of moving objects (animated guard models) onto curved surfaces (barrels, sidewalks, etc). How do they do it?

Hello!


DemonWasp said:
The question that keeps coming up in my mind is: how do the professional games do it? If you look at a game like Thief 3 (not even all that graphically impressive, to be honest), it manages to have dozens of point light sources in any given scene (torches) casting real-time shadows of moving objects (animated guard models) onto curved surfaces (barrels, sidewalks, etc). How do they do it?


Well, there's a lot of trickery you could employ. Having only moving entities flagged for shadow casting could be one. Maybe the shadows are actually acting on a lower resolution model that you can't see (but the engine knows about it). Maybe everything that could cast a shadow knows whether or not it can be moved, and thus simplifying the calculation. Really, the idea is to simplify it enough so that the computer can handle the calculations at a decent rate. Pointlight shadows are pretty tricky, so you'd probably have to baby it a bit to get acceptable performance. If walls are involved, it may do a one time calculation for those shadows, or it might skip that altogether and use shadow maps.

In the end, professionals use every trick at their disposal to pull off these effects. They very rarely are afforded the opportunity to throw a catch all at something and expect it to work in every situation. And also, to remember when "good enough" really is "good enough."

Cheers!
~FlaH

Finally got the time to try this out :wink:



Can it be that it currently even work’s without any stencil stuff? Just downloaded it from the repository and hit start and it worked right away :wink:

Woot :stuck_out_tongue:



I committed the changes about a month ago, but I wasn’t sure that it had made it into a mainline version. I’ve been working on other stuff mostly. I’m glad that it works :slight_smile: