Soft Shadows - The Return

I was not happy with my last algorithm (remember the screenshots a few months ago?), because of the “shadow melting” artifacts, and also because the penumbra thickness was just a function of the distance to the camera and to the light source, not the occluder.

Well, i fixed these two problems. My previous technic was also using 3D textures which were not widely available; i got ride of them.

I implemented my new algorithm under DX9; not because i’m fond of it, but because since my last post i got a request to publish it into a book, and that book is specifically about DX9 vertex and pixel shaders. It could obviously still be implemented in OpenGL.

Here’s a screenshot, without melting artifacts, and correct to-occluder penumbras:

It’s running at 40-50 fps on my Radeon 8500; it requires ps_1_4 and vs_1_1. The demo will be released on the CD for the book.

Without saying too much, the new algorithm relies on determining the penumbra by using two stencil shadow passes, jittering the light for the second one, copying everything to a texture (output of stencil pass 1 in red component, output of stencil pass 2 in green component). It then applies a blurring filter to the pixels inside the penumbra with a pixel shader.

Comments welcome as usual :slight_smile:


Just to be clear, here’s a screenshot of the output of the stencil shadow passes:


Just the same ol’ comment : “where’s the demo?” =)

Is there a description of the algorithm anywhere, or are you unable to say because it’s going in a book?

Looks great, btw.


And the same ol’ comment: “on my hard drive” :slight_smile:

Seriously i don’t think i’m allowed to publish the demo yet; it was specifically done for the book.

As for the description of the algorithm, i can give a few more details if you want, but for the most it was described in my first post. It’s an extension of shadow volumes; It works like this:

  • prepare rendering to a NxN texture, fill Z Buffer
  • find silhouettes on CPU, prepare extrusion in a vertex shaders
  • extrude shadow volumes with a shader a first time
  • apply a full-screen quad to render to shadowed areas in green
  • prepare jittering the light, clear stencil buffer
  • extrude shadow volumes with a shader; this time jittering the light. The trick here is to move the light in the direction of the normal of the vertex, to simulate an area light.
  • apply a full-screen quad to render to shadowed areas in yellow.

At this step, you’ve got in the texture the output of my second post’s screenshot.

Now, all you need to do is to apply a fixed amount of passes on a full-screen quad using that texture to blur it. Nvidia has some good presentations about this so i won’t enter into the details. The trick here when you’re doing the blur is to only allow reading from areas with R > 0, and to only allow writing to areas with G > 0. In other words, to only blur inside the penumbra.

Finally you can evalulate your lighting equation normally and modulate it with the red component of the texture.

I guess it could be implemented on a Geforce 3, or even using multi-pass rendering, but it would require an insane amount of passes, making it no longer better than the standard “slow” technics…


I must say that you are really getting close to what I am doing now. I create the shadow outline by using vertex weights for the shadow volume and “scale” the volume towards is end cap. Beacuse my shadow volume length is proportional to the distance between light and occluder i get the bend effect proportional to the distance between occluder and shadow hit.

If I use two stencil passes I get one sharp edge and one “scaled” edge. However instead of blurring that area (the same area as you have) i repeat the scaling several times and therefor get a continious drop from the sharp edge to the blurred edge in e.g. 5 passes. Then I apply bluring to the various stencil values…

BTW. No shaders and no recalcs between several passes of static geom. Just scale the second weight matrix and apply the same shadow volume geometry…

Any comments on my comment ??

Yeah :slight_smile: Shadow volumes require some fillrate. A lot. Really, a lot of fillrate. So basically, jittering the light 5 times seem pretty slow to me, but i guess it also depends on the scene. The speed you’re loosing by doing shadow volumes 3 times more, maybe i’m loosing it by doing the blur through pixel shaders, i don’t know. I tried playing with the mipmap bias to get a free blur effect but it was so ugly…


ya the same technique i was implementing (in software tho)
but one prob still remains:
in which direction would you jitter a point omni light?
anyway congrats shots are looking good


>>specifically done for the book.

which book ??? tell me please…


DAAAMMMNNNNN that looks ****ing good !!!

perhaps we should hack ysaneya’s machine to get the source… rotflmao

Originally posted by DJSnow:

>>specifically done for the book.

which book ??? tell me please…[/b]

I’d guess ShaderX II

It looks like you’ve implemented a comb filter approach for the penumbra. You render a couple of volumes and then convolve the results in the framebuffer by tapping multiple locations of the resulting shadow.

I don’t see how this could work for omnidirectional lights since the multiple stencil passes I assume are generated by displacing the light source in a specific direction.

It’s also not clear how well this behaves when the shadow is visibly occluded, but I suppose depth of field demos have already shown the right kind of filtering to work around this, I wonder of they could be adapted.

[This message has been edited by dorbie (edited 02-20-2003).]

Originally posted by pocketmoon:
I’d guess ShaderX II

My guess too. If that’s the case you are actually allowed to publish the article and demo on your website too. I have specifically asked about that, cause I’m contributing to this book too, and was told I’m allowed to do that. My articles and demos are already available on my site .

dorbie: It sounds like he jitters the light a different direction for each vertex.


Coriolis, that sounds good, however does not work consistently in practice. A vertex would not know the right direction to jitter in since it’s the differential jitter that causes the soft shadow. Perhaps if you considered the object normal it would be possible and I’m wrong. You’d jitter along the normal vector of the vertex, it seems to me like this might be viable, I doubt much else would be.

[This message has been edited by dorbie (edited 02-21-2003).]

Yeah, it’s for ShaderX II. Humus, i knew i was allowed to publish the article, but didn’t know for the demo, that’s a good news. So you’ve finished your articles ? I’m still working on mines; had some problems with DX9 and 3D (volume) textures, which is the reason why i had to tweak my previous algorithm.

Dorbie: you’re right, it wouldn’t handle omni lights well if you had to use a per-object vector. I’m using a per-vertex displacement vector; it’s not exactly the normal but it’s close. Think about what you’re doing when you want to apply a glow to an object: you extrude the vertices in a direction to “scale” the whole model up. It’s a similar concept, except that, instead of using these vectors to displace the vertices, i use them to displace the light position.

I haven’t noticed any problem with omni lights yet, although i’m guessing it could happen if you have the light really close to the geometry. But in that case you can reduce the jittering distance.


Wow. I also submited my proposals about fake soft shadow volumes for ShaderX II. I got an answer, that somebody was already writing about that topic Now I know who!

My algorith requires one shadow volume pass and computes bluring factor using distances from light source and occluder (everything is computed using vertex/pixel shaders). I am currently workning on demo using my new Radeon 9700 Pro. I think, that I am able to avoid some artifacts related to the image-space nature of this algorithm…

Sorry for my english…

Sounds similar to my original algorithm, that i did a few months ago. Although i didn’t find a way to calculate the correct per-pixel to occluder distance, so i was working with the basic to-light distance. How are you computing it ?

But you’re right, most of the problems i had were image-space related. The main one was the “shadow melting” artifact, when you’re blurring shadowed pixels and non-shadowed pixels belonging to different objects (one shadowed, the other still lit). There was some kind of “light halo” around the edges. Fortunately i do not have it in the new technic:

…is a zoom on the head of the model in my first screenshot. As you see there’s no melting artifact.


About correct per-pixel to occluder distance…

I am not sure, if it works (I am still working on demo… I have a lot of different work - I am writing for ShaderX2 about something else: ))

But… I will try to explain it in english

I am doing extrusion in vertex shader using modified objects - every original edge has additional quad (well know technique).

Now… When quad is extruded, 2 points (A, B) are extruded from the position of the other 2 points (C, D). Because I know starting position of the translated vertexes (A, B) and I know “current” interpolated position (during rasterizing this quad), I can compute distances from the occluder casting this volume (quad).

I think, that most of the artifacts can be eliminated using informations stored in stencil buffer - clever bluring is applied only on pixels in shadow…