PDA

View Full Version : Soft Shadows - The Return



Ysaneya
02-20-2003, 06:07 AM
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: http://www.fl-tw.com/opengl/SoftShadows/screenshot2.jpg

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 :)

Y.

Ysaneya
02-20-2003, 06:13 AM
Just to be clear, here's a screenshot of the output of the stencil shadow passes:
http://www.fl-tw.com/opengl/SoftShadows/screenshot3.jpg

Y.

tfpsly
02-20-2003, 06:39 AM
Just the same ol' comment : "where's the demo?" =)

Mezz
02-20-2003, 07:13 AM
Is there a description of the algorithm anywhere, or are you unable to say because it's going in a book?

Looks great, btw.

-Mezz

Ysaneya
02-20-2003, 07:29 AM
And the same ol' comment: "on my hard drive" :)

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..

Y.

ToolTech
02-20-2003, 08:24 AM
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 ??

Ysaneya
02-20-2003, 09:02 AM
Yeah :) 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..

Y.

tellaman
02-20-2003, 09:12 AM
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

DJSnow
02-20-2003, 09:33 AM
@Ysaneya:

>>specifically done for the book.

which book ????????? tell me please...

DJSnow
02-20-2003, 09:34 AM
@all:

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

perhaps we should hack ysaneya's machine to get the source.... http://www.opengl.org/discussion_boards/ubb/biggrin.gif *rotflmao*

pocketmoon
02-20-2003, 10:53 AM
Originally posted by DJSnow:
@Ysaneya:

>>specifically done for the book.

which book ????????? tell me please...

I'd guess ShaderX II

dorbie
02-20-2003, 01:57 PM
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).]

Humus
02-20-2003, 03:45 PM
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 (http://esprit.campus.luth.se/~humus/) .

Coriolis
02-20-2003, 05:13 PM
dorbie: It sounds like he jitters the light a different direction for each vertex.

knackered
02-20-2003, 10:42 PM
Interesting: http://www.gim.ktu.lt/nesnausk/nearaz/texts/revext.html

dorbie
02-20-2003, 11:35 PM
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).]

Ysaneya
02-21-2003, 02:23 AM
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.

Y.

arsil
02-21-2003, 03:39 AM
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 http://www.opengl.org/discussion_boards/ubb/frown.gif 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...

Ysaneya
02-21-2003, 03:55 AM
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:
http://www.fl-tw.com/opengl/SoftShadows/screenshot4.jpg

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

Y.

arsil
02-21-2003, 04:45 AM
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 http://www.opengl.org/discussion_boards/ubb/smile.gif

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...

Ysaneya
02-21-2003, 05:36 AM
That's damn funny, seems like it's a meeting of ShaderX II contributors :)

Arsil, i don't think your technic would work. For sure you know the current distance to the occluder for the interpolated position. But this position does not correspond to the one of the shadowed pixel.

Take a look at these figures: http://www.fl-tw.com/opengl/SoftShadows/screenshot5.jpg

In the perspective view, consider a pixel P that lies on the shadow of the occluder O.

By interpolating the distance to the occluder, you are actually computing the O-P1 distance (see second figure). But the real pixel, the one that lies on the surface plane, is not P1. It is P2. And the distance from P2 to the occluder is c-P2, which is actually much shorter than O-P1.

In conclusion: you'll calculate a wrong pixel-to-occluder distance (if that was your idea, that is).

Y.

arsil
02-21-2003, 06:05 AM
Unfortunately you might be right http://www.opengl.org/discussion_boards/ubb/smile.gif Computing correct distance to the occluder may be impossible at all....

But I am going to chcek, if I can render soft shadows based only on distance from the light source (maybe weighted with some estimated distance from the centre of the occluder) without artifacts using only one shadow volume pass.

Matt Halpin
02-21-2003, 07:07 AM
Looks very nice!

Is this equivalent to having a white texture, with black where your image is yellow. Then you do a blur, but only write to bits that have a green component in your original image? Then you modulate your lighting by this image.

Could you use the stencil from your outer shadow pass to mask out the rendering of the blur. Are you doing this, and is it quicker than colour modulating due to quicker reject from the stencil result?

So this means that the smoothness of the blur result is cut off by the masking, so you actually get hard transitions where the 2 shadow volumes are close together? (not that it looks bad at all http://www.opengl.org/discussion_boards/ubb/smile.gif

Also, do you vary the blur kernel radius based on screen-space depth, or not bother?

I look forward to your article http://www.opengl.org/discussion_boards/ubb/smile.gif

Matt Halpin

PS, I'm also writing a ShaderX II article, but it's on pre-ps.1.4 specular bump-mapping, so nothing too fancy http://www.opengl.org/discussion_boards/ubb/smile.gif

Ysaneya
02-21-2003, 07:48 AM
Is this equivalent to having a white texture, with black where your image is yellow. Then you do a blur, but only write to bits that have a green component in your original image? Then you modulate your lighting by this image.


Yes, exactly.



Could you use the stencil from your outer shadow pass to mask out the rendering of the blur.


I thought about doing that, but i does not directly work at the moment. The result of the second stencil pass is the yellow area. To do it, it'd have to be the green area, or all i'll get back is a hard shadows (since pixels in yellow areas remain black anyway). It should give a pretty nice performance boost, since blurring is fillrate intensive.



so you actually get hard transitions where the 2 shadow volumes are close together?


Yes, that's the idea. The shadow is sharper near the occluder.



Also, do you vary the blur kernel radius based on screen-space depth, or not bother?


Well, that's magic! A depth correction is not needed; given the same pixel and occluder, penumbras that are far away will end up being smaller, hence sharper (in pixel thickness), than penumbras that are closer to the viewer. It's due to the fact that the stencil passes output is naturally perspective correct.

I can't believe there's another one ShaderX II contributor. I thought this was an OpenGL board :)

Y.

pocketmoon
02-21-2003, 07:48 AM
Originally posted by Matt Halpin:
PS, I'm also writing a ShaderX II article, but it's on pre-ps.1.4 specular bump-mapping, so nothing too fancy http://www.opengl.org/discussion_boards/ubb/smile.gif

It's unusual these days if you are NOT writing an article for ShaderX II http://www.opengl.org/discussion_boards/ubb/smile.gif

Matt Halpin
02-21-2003, 09:03 AM
Originally posted by Ysaneya:
I thought about doing that, but i does not directly work at the moment. The result of the second stencil pass is the yellow area. To do it, it'd have to be the green area, or all i'll get back is a hard shadows (since pixels in yellow areas remain black anyway). It should give a pretty nice performance boost, since blurring is fillrate intensive..

Is there any particular reason why you couldn't re-order the passes?

Do inner stencil passes.
Copy to render-target.
Do outer stencil passes.
Do blur with stencil test on.


Yes, that's the idea. The shadow is sharper near the occluder.

Well, not quite. The gradient of the blur doesn't change, so you're actually cutting off a shallow gradient of blur, whereas you would actually want to adjust the blur to have a sharper gradient.


Well, that's magic! A depth correction is not needed; given the same pixel and occluder, penumbras that are far away will end up being smaller, hence sharper (in pixel thickness), than penumbras that are closer to the viewer. It's due to the fact that the stencil passes output is naturally perspective correct.

Again, you're truncating a shallow blur gradient, rather than creating a sharper blur. I think, unless I've missed something http://www.opengl.org/discussion_boards/ubb/smile.gif It still looks much nicer than having the shadows melt over other surfaces http://www.opengl.org/discussion_boards/ubb/smile.gif


I can't believe there's another one ShaderX II contributor. I thought this was an OpenGL board http://www.opengl.org/discussion_boards/ubb/smile.gif

lol, there do seem to be a lot around here http://www.opengl.org/discussion_boards/ubb/smile.gif

Matt Halpin

SirKnight
02-21-2003, 09:19 AM
Originally posted by pocketmoon:
It's unusual these days if you are NOT writing an article for ShaderX II http://www.opengl.org/discussion_boards/ubb/smile.gif



Well I'm not. http://www.opengl.org/discussion_boards/ubb/biggrin.gif I don't think I know of anything that I could do for the book anyway. Everything I know has already been done. http://www.opengl.org/discussion_boards/ubb/smile.gif I think so anyway.

-SirKnight

Ysaneya
02-21-2003, 10:52 AM
Is there any particular reason why you couldn't re-order the passes?


None at all, technically it should work. It just happened that i wrote the code in that order, so i'd just have to clean up the (current) mess and reorder it.



Well, not quite. The gradient of the blur doesn't change, so you're actually cutting off a shallow gradient of blur, whereas you would actually want to adjust the blur to have a sharper gradient.


Point taken. I'm definately not claiming to do perfect soft shadows. It's still a fake technic. But i consider that, as long as it looks half good and half fast, it's a success.

Although i must admit it's still a bit overkill to use in a complete game. 40 fps for one light is not too bad for soft shadows, but not good enough for a FPS for example, considering that nothing else is running. I suppose that it could become interesting in a few years (months?), when the Geforce FX / Radeon 9700 will be the standard :)



Everything I know has already been done.


Hehe, start looking into things you don't know, and you'll be welcome to contribute to Shader X III :)

Y.

Matt Halpin
02-21-2003, 10:56 AM
Originally posted by Ysaneya:
Point taken. I'm definately not claiming to do perfect soft shadows. It's still a fake technic. But i consider that, as long as it looks half good and half fast, it's a success.

aye, it's one of the best examples of soft shadows I've seen so far, so no problem with that. http://www.opengl.org/discussion_boards/ubb/smile.gif

Matt Halpin

V-man
02-22-2003, 08:43 AM
Ysaneya,

you are doing a single jitter with the single light source right? That would be a problem for some objects in the wrong places.

Throw in some more lights. I don't think the FPS will be cut in half if you add a second light. Maybe 6/10th, but not half.

It looks quite good and is excellent from a games point of view.

Ysaneya
02-23-2003, 07:19 AM
you are doing a single jitter with the single light source right? That would be a problem for some objects in the wrong places.


Yeah, i'm doing a single jitter. But i don't see how it could be a problem with some objects (except when they're in the jittering radius of the light).



Throw in some more lights.


Ok, i spent a few hours modifying the code to support more lights. Here's a shot with 2 lights; With a 512x512 map (highest quality) it's running at 18 fps:
http://www.fl-tw.com/opengl/SoftShadows/screenshot6.jpg

And here's the same one with a 256x256 map, running at 28 fps:
http://www.fl-tw.com/opengl/SoftShadows/screenshot7.jpg

Using a 256x256 map instead of 512x512 improves quite a lot the performance; but, although you don't see it well in the 2 shots, there's some aliasing on the shadows when you start moving, which is the primary reason i'm sticking to 512x512 at the moment :)

I also tested the stencil trick idea. Doesn't work well; actually it slows down things a bit. The reason is, although the stencil tests saves some pixel-shading fill rate, the maps have to be cleared between each blurring step. With 2 lights that means 6 clears of a 512x512 map.

Y.

PixelDuck
02-24-2003, 10:57 PM
I don't know for sure, but you could get the two volumes with just to volume passes into the stencil buffer, but you'd get minor problems with the volume "cutting through" the corners of the model, by scaling the end cap of the colume, that is scaling the volume "pyramid" base. I had a similar idea, but it's a bit different, since it needs floating point textures ( =), two stencil passes and a blur filter.

Cheers!

Ysaneya
02-25-2003, 12:43 AM
Huh? I don't really see your idea. The basic shadow volumes algorithm requires 2 stencil passes (w/o stencil 2 sides) already. How can you calculate the penumbra without 2 additionnal passes ? I fail to see how just scaling the end cap would be working; you'd just get a different shadow, but no penumbra..?

Y.

ToolTech
02-25-2003, 06:48 AM
What he suggests is the same thing I am doing but only two passes. I guess he means two passes with both front/back stencil per pass.

I do the same but with 5 times to get 5 levels of stencil values. You can use just two values to get a uniform blurred umbra.

I use vertex weights to "bend" the volume each pass....

Gives very good result and no requiremnet for shaders...

Future enhancements could be using shaders to do a better "bend"

PixelDuck
02-25-2003, 09:55 PM
Yeah, basically I mean front and back, but you can do it with two sided stencil operations, can't you? Anyways, I won't tell more before I've tested it :]

But, ToolTech, I would actually get a uniformly blended volume (or not using more stencil passes and "blending concatonation") but it might/should get a bit more accurate one, that actually changes a bit more correctly over distance than what Ysaneya explained. But it's just speculation, I haven't tested it, hate beeing confined by school http://www.opengl.org/discussion_boards/ubb/wink.gif

Cheers!

[This message has been edited by PixelDuck (edited 02-25-2003).]

Ysaneya
02-26-2003, 12:30 AM
Huh again ? That's exactly what i'm doing ? I'm getting the penumbra in two front-and-back stencil passes.. or i'm not getting your idea..

*confused*

Y.

Gordon_Freem@n
11-03-2003, 02:00 PM
Sorry. How can i blur result texture?

hyvelbank
11-20-2003, 10:53 PM
Volumetric soft shadows from area/volume light sources: http://borgenstam.com/noname/index.php?view=projects&filter=softshadow

It is an OpenGL implementation of the algorithm presented by Assarsson et al.

As good as it gets.

JustHanging
11-23-2003, 07:28 AM
Yeah, that's a promising technicue, but last time I checked it couldn't really deal with multiple lights as it stores intermediate results in color buffer. Still, even if you have to accumulate lighting through textures it might beat multiple volumes.

-Ilkka

hyvelbank
11-23-2003, 10:34 PM
Originally posted by JustHanging:
Yeah, that's a promising technicue, but last time I checked it couldn't really deal with multiple lights as it stores intermediate results in color buffer. Still, even if you have to accumulate lighting through textures it might beat multiple volumes.

-Ilkka
It is not a problem. You only have to render to the same v-buffer for every lightsource. There is no difference really between this algorithm and std. shadow volume algorithm, except that a v-buffer is used instead of a stencilbuffer.