Page 1 of 1

Contact Hardening Shadows

Posted: Mon Nov 05, 2012 3:40 am
by lunkhound
Hi Ogre community!
I'd like to share some of the stuff I've been working on. I've been working alot on shadows with Ogre's terrain component. Lately I've been working on an effect known as "contact hardening shadows".

Here is a photo of the effect I'm aiming to reproduce:
Image
full size

Notice how the shadow has a hard edge at the base of the tree, and as the shadow gets further from the tree the shadow gets softer? That's known as "contact hardening" shadows.

And this is a screenshot of the effect in my Ogre based engine:
Image
full size

Here's the effect on a vehicle:
Image
full size

In this shot, you can see that the vehicle, being airborne and quite far above the ground, has quite a soft shadow:
Image
full size

As the vehicle comes in for a landing, the shadow edges become more distinct, giving the observer important visual cues about the vehicle's relationship to the ground:
Image
full size

If you'd like to take the demo for a spin, I've made it available here:

https://docs.google.com/open?id=0B3So90 ... zlDT0U4Vkk (23MB windows download)

The demo requires Windows with DirectX 9, and a GPU with pixelshader 3.0. I think it should run pretty decently on even a fairly old GPU (say 2 or 3 years old). I'm running it on an old GTX 260 and getting close to 60 fps.
If you do try it, I would love to hear what kind of framerate you are getting (and with what CPU/GPU). And if you have trouble downloading, installing or running it I would like to hear about that as well.

Thanks for reading!
Chris

[edit: images were too big to direct link, so created smaller thumbnails and added links to full size 1600x1200 images]

Re: Contact Hardening Shadows

Posted: Mon Nov 05, 2012 4:01 am
by saejox
i like executable demos :)

i got about 90fps, at 1080p maximum AA
with 2500k and gtx560

Re: Contact Hardening Shadows

Posted: Mon Nov 05, 2012 4:45 am
by Yati
Nice! It looks really good! Are you planning to share the source?

Re: Contact Hardening Shadows

Posted: Mon Nov 05, 2012 8:32 am
by lunkhound
Forgot to mention, shadow texture atlasing:

Image

In this shot, I've cranked up the number of cascades to 9. Each color band corresponds to a different shadow map cascade. All 9 shadow maps are kept in a single texture (inset).
In practice, I think 9 shadow maps is a bit much, and there is a definite framerate hit from it. I find 4 works nicely for shadow mapping out to about 1000m from the camera.
By default my demo is set to use 4, but you can adjust the number from 1 to 9 by pulling up the debug console ("`" key), and typing "shadow/cascadeCount=9".
There are numerous other settings. To display the shadow texture its: "shadow/toggleShadowMap"

I'm not planning to release my source, except for patches I've made to Ogre source. Shadow texture atlasing, for example required some changes to Ogre. I also have a number of bugfixes.
However, I'm happy to entertain questions about this stuff.

cheers,
Chris

Re: Contact Hardening Shadows

Posted: Mon Nov 05, 2012 11:02 am
by TheSHEEEP
If you don't plan to release the source, would you mind sharing how this works in general, probably with pseudocode or some kind of "manual", like:
1. do this.
2. do that.
3. combine output of 1. and 2. to do something else.
Speaking in deferred shading terms, I'd do something like this with the depth map (captain obvious here), but besides of that, I see a number of ways to implement it, but you seem to have it done with a good performance, too, so feel free to share as much as you want :D

Also, thanks for sharing the idea. This definitely looks awesome and whenever I can implement that, I guess I will :)

Re: Contact Hardening Shadows

Posted: Mon Nov 05, 2012 6:27 pm
by lunkhound
TheSHEEEP wrote:If you don't plan to release the source, would you mind sharing how this works in general, probably with pseudocode or some kind of "manual", like:
1. do this.
2. do that.
3. combine output of 1. and 2. to do something else.
Speaking in deferred shading terms, I'd do something like this with the depth map (captain obvious here), but besides of that, I see a number of ways to implement it, but you seem to have it done with a good performance, too, so feel free to share as much as you want :D

Also, thanks for sharing the idea. This definitely looks awesome and whenever I can implement that, I guess I will :)
Its pretty straightforward. I'm using variance shadow mapping (VSM) wherein instead of just storing a depth value in the shadow map, one also stores depth-squared. So its a 2 channel shadow map. Here is a 2006 paper by Andrew Lauritzen describing it. VSM has its shortcomings, in addition to doubling the memory for shadow maps, there are light bleeding artifacts that occur.

However, the big advantage of VSM is that you can apply a blur filter directly to the shadow map, and it will soften the shadows. All I'm doing is applying a variable blur compositor to each of my shadow maps.

Psueodocode:

Code: Select all

For each shadow map,
  render the scene from the shadow camera, storing (depth, depth*depth) at each pixel (ala standard VSM)
  apply 4-pass variable blur compositor,
    pass 1: into a temporary 1-channel texture (lets call it the blur-map) render the results of edge detection on the shadow map, that is,
       for each shadow map texel,
          compare the depth to the 4 neighboring texels and write out a value proportional to the maximum absolute difference in depths.  This value determines how much blurring we need in this part of the shadow map.
    pass 2: blur map flood-fill pass.  Output a second blur map using the first blur map as input.
       for each texel in the blur map,
          search in each of the 4 cardinal directions for the maximum blur value that would be in blur-range of the output pixel
       The idea here is to smear out the results of the first blur map so that neighboring pixels of heavily blurred areas are also blurred.
    pass 3: using the blur map and the shadow map, apply the first part of a separable blur filter.  So blur in the horizonal first, applying the amount of blur specified by the blur map.
    pass 4: second part of separable blur filter applied to the output of previous pass and again using the blur map as input.  Blur in the vertical direction.
My separable blur isn't a gaussian, its just a box filter for simplicity and maximum blurriness. It doesn't seem to produce any boxy-ness in the output that I've noticed.

This is what light bleeding looks like:
Image

You can see that the blurriness of the tree shadow "bleeds" through to the vehicle's shadow underneath. I'm still working on this part.

cheers,
Chris

Re: Contact Hardening Shadows

Posted: Tue Dec 11, 2012 2:33 pm
by nickG
Do you can post demo-source?

Re: Contact Hardening Shadows

Posted: Tue Dec 11, 2012 5:08 pm
by Nauk
Awesome work and very usefull! Thanks for sharing the algorithm behind it :) Most realistic shadows I have seen on Ogre so far.

Re: Contact Hardening Shadows

Posted: Tue Dec 11, 2012 6:24 pm
by scrawl
Add me to the list - looks awesome and I'd like to see the source as well :)

Re: Contact Hardening Shadows

Posted: Tue Dec 11, 2012 8:12 pm
by lunkhound
Nauk wrote:Awesome work and very usefull! Thanks for sharing the algorithm behind it :) Most realistic shadows I have seen on Ogre so far.
Thanks for the kind words!
Also thanks for ArtifexTerra, it was very helpful in making my terrain.

@nickG: At present, I'm not planning to release the source. I'm currently trying to make this into an actual game for (hopefully) profit.
Besides that, I don't think the source would be all that useful to people. It won't even compile without modifications to Ogre, so it would be a real hassle to set up. You'd need to get a certain mercurial revision of OGRE, then apply a bunch of patches to it and so forth.
Secondly, I don't have the rights to redistribute most of the assets in plain form. By license I can only distribute them in some obfuscated format. So even if someone were to get it to compile, they still wouldn't be able to run it without plugging in all of the artwork.
I think I would be spending alot of time trying to explain how to get it working!

All that said, there are parts that I wouldn't mind sharing. I've already posted a number of patches on the OGRE patch-tracker (all bugfixes). I have a few other patches to OGRE that may be worth sharing. I'm mainly thinking of the shadow texture atlas support. That's a pretty handy feature for saving texture samplers in the terrain pixel shader. I haven't submitted it to the patch tracker because it's quite minimal interface-wise, to the point of being obscure and unintuitive. I'm just afraid that in its current form it would just add some extra complexity to OGRE's already complicated shadowing code without seeing much use. Still if anyone is interested, I'd be glad to put that patch up somewhere.