Dynamic soft shadows

A few days ago, i had an idea to display per-pixel soft shadows in real-time. I spent a few hours to code it, and here is a first result:


Granted, the scene is extremely simple but this implementation, which works as an extension to the shadow volumes algorithm, is only fill-rate limited. In addition, the fill-rate overhead for the soft shadows is independant of the geometry complexity, which means it should still run fast on pretty complex scenes.

You’ll also notice a few interesting effects; for example, the higher the distance to the light, the softer the shadow becomes; it’s still pretty sharp near the light, as in reality.

The technic doesn’t require any fancy stuff except simple pixel shaders. I’ve had it working on a Radeon 8500, and it could be implemented on a GF3/GF4. Possibly on a GF1/GF2 with the help of combiners, by accepting a lower quality and speed.

Now i’m gonna implement a more complex scene to see if there is no artifact or unaware problems with it… i’m pretty sure speed will be ok, but you never know… i’ll try to post a demo in a few days (maybe with some code) if i see it’s usable.


Why no explanation of the technique ?

Is it a combination of shadow volumes with a projected soft shadow texture ( as shown in an ATI demo ) ?

Looks great
Looking forward to see a deeper description of the technique.

Do you do it as I do in my engine. I add a number of shadow volumes and blend them. Each volume has a higher value of the stencil buffer and therefor you can add very fast soft blended quads over the entire screen using different stencil layers. Shadow further away gets their edger far away from each other wich gives a soft shadow far away and near the edges are almost the same wich gives sharp edges…
http://www.tooltech-software.com/images/umbra.jpg perhaps not a good picture but anyway…

No explanation because i want to make sure it works in a “real” scene before starting to explain it… 500 tris on screen is not very impressive, i’m sure you’ll agree.

Which ATI demo are you talking about ? It has nothing to do with softened shadow maps, if that’s what you mean…


ToolTech: i don’t think we do it the same way. I generate the shadow volume only once (which is why i said it’s not much dependant of the scene complexity), but i then do some image-based operations with some per-vertex parameters to control the sharpness (hint! hint!).


This is what I was thinking off,

combined with shadow volumes for self shadowing.

Does your method allow for soft self-shadowing ?

but i then do some image-based operations with some per-vertex parameters to control the sharpness (hint! hint!).

Ok, so what about NVIDIA’s soft shadow volume demo ( in their Cg browser ) ? Is that related ?

I use the same volume. And then I use the vertex weight method to add a skew matrix for the points at the far side. This way I can interpolate between the near sharp volume side and the far volume side using vertex wights 0-1.

but i then do some image-based operations with some per-vertex parameters to control the sharpness (hint! hint!).

Hmmmm. That is sounding kind of like a theory i have been working on to make stencil shadow volumes soft, with it being the softest at the ‘top’ of the shadow and sharper at the ‘bottom’ of the shadow. Just like in that screen. It would be kinda cool if we have both came up with the same technique. Of course, my theory needs some more work, it’s not quite at the same point as your method there…yet.


My tech demo in another thread shows the first stage of the shadow algo using only sharp shadows (self shadowing). Will hopefully get up a demo soon that shows the self shadowing soft shadow version. Wanted some feedback on the first demo until I rleased the second…

Very nice I think you should describe your technique even if it turns out not to work. Perhaps one of us would be able to help work around any shortcomings…

– Zeno

PH: no, that’s not it. I read it jitters / displaces the light many times to accumulate the shadow into the shadow map, which requires to draw the geometry many times. I don’t need that :slight_smile: And i think my method will work well with self-shadowing, because as i said, it’s an extension of shadow volumes, which are automatically handled. However, i haven’t tested it yet, which is why i want to try a more complex scene first… i have tested the NVidia’s soft shadow volume demo, but i can’t remember how they did it. I’ll look at it tomorrow…

ToolTech: i don’t think i understand well… it sounds like you accumulate the shadow volumes to determine the inner / outter borders of the shadow… am i completely off tracks ?

SirKnight: that sounds nice, if we all come up with a way to implement soft shadows, we might end up finding one usable in games, who knows? :slight_smile:

Zeno: i’ll be sure to describe it even if it doesn’t work :slight_smile:


Ok. I will try to explain in details.

  1. Create a shadow volume out of the object. The volume is a true volume. Not just a siluette.

  2. Set the vertex weights for the front cap to 0 and for the back cap to 1. This way I am able to control the slope for each side.

  3. Create a secondary matrix that takes its local coordinate system in the z axis aligned from the light source to the center of the occluding object. create a scale in the x,y plane with scale factors 1, 0.9, 0.8 etc. depending on how many iterations to be used ( i use about 5 ). If the lamp source has a big radius then the gap beteen each scale factor is larger. if the light source is small the value gap is small like 1, 0.99,0.98,0.97 etc.

  4. Multiply the current transform with this scale matrix and set the secondary weight matrix to the result.

  5. for each iteration draw the shadow volume and increase the stencil values each time. for each iteration you should also update the second weight matrix with decreasing scale factor.

  6. the result is a combination of mutiple shadow volumes that at the occluding objects boundary are aligned but at the far side they are warped into a smaller scale.

  7. Apply for each stencil value a blend and a darkening so that the result of all iterations shall become the fully shadowed color and at the edges where the stencil values are low only a small darkening effect occurs.

Remember to tun of all specular but keep a dimmed diffuse component.

This way I can create umbra/penumbra for small sharp lamps or larger diffuse lamps. All shadows are self shadowing…

Now I got a report that the techdemo on an Athlon 1800 + GForce 4 runs at 250 Hz so I am aiming at 60 hz for good looking soft shadows within a complex environment.

Hmmm, this isn’t very different than the ATI demo. You iterate many times and displace a little the light source, to get a penumbra effect. What confused me is that you said you used the same shadow volume, while you actually render it many times (5!). You also need to apply a full-screen quad for each iteration. I do not need all of this. I draw the shadow volume only once. At the end of the process, i apply only one full-screen quad. On the other hand, my method suffers from small artifacts (which i’ll call shadow melting), but i’m trying to minimize them so that they’re almost invisible.


I dunno if this as already been addressed, but to be perfectly pendantic… Shadow softness is not based on distance from the light, it is based on distance from the shadow caster.

To demonstrate, make a shadow on the wall with your hand, if you move it very close the shadow gets sharp, if you move it away it gets fuzzy. The distance from the light to the shadow never changes.

This may be what your method does, but you just mistated it.

Moving the light away from the shadow caster makes shadows sharper because the light source becomes more and more like a point light.

This look perfect : please, describe your method.

Sincerly tours,


PS : it look like a hoax.

This looks damn good!
Can U do the test you where talking about and explain more in deep the tecnique ??

The most interesting part is that the shadows doesn’t look like hardly changing direction on the front facing plane of the green “thing” receiving the shadow.

I used volume jittering and proj shadows but in both the shadow borders where exactly following the receiving surface inclination.

Do you draw into the color buffer (alpha) while setting the stencil buffer? If you do your method might be similar to the one I made up…

Assign alpha values to vertices of the shadow volume… like 0 at the vertices closer to the light and 1 to the farther ones.

Draw into dest alpha while setting the stencil buffer.Now the alpha value at any shadow point in the color buffer is almost directly proportional to the distance of the point to the corresponding point on the occluder.

If this linear(almost?) alpha values can be converted to some non linear space then we can have alpha intensity that correspond to the darkness of the shadow at the point.

Something like (0.0 … 0.5 …0.9…1.0) -> (0.0 … 0.01…0.3…1.0)

If some transformation like that can be done using the pixel shader(i dunno much about shaders) then we should be able to have soft shadows by drawing a screen aligned black quad with an appropriate blend mode (unless i goofed up somewhere).

[This message has been edited by tarantula (edited 09-05-2002).]


Your method does not make much sense to me. The alpha values in the shadow will be from the polygons that make up the sides of the shadow volume. This may bear no resemblance whatsoever to the distance from the surface to the occluder silluoette unless you are using an orthogonal projection and the view is perpendicular to the direction of the lightsource.

EDIT: In addition, it is not just distance from the occluder silluoette, it is the distance from the edge of the shadow. Any surface for which the light is completely occluded will be completely in shadow no matter how far away from the occluder it is.

[This message has been edited by Nakoruru (edited 09-05-2002).]