Sign in to follow this  
Lopez

Soft Shadow

Recommended Posts

Hi there, I'm currently working on soft shadow mapping. I have an idea of doing soft penumbra on the shadow map. I want to be able to blur the shadow based upon it's distance from the shadow caster. If I have the depth value of the shadow, stored in the depth map, how can I get the depth of the fragment from the lights point of view. I intend on subtracting the shdow depth from the fragment depth to get a blur offset which will then be used for blurring the shadow map. Can anyone point me in the right direction, and also about converting the depth from 0-1 range into world units.

Share this post


Link to post
Share on other sites
There is an example of this in Beginning OpenGL Game Programming that creates a soft shadow by using the accumulation buffer and jittering the light position back and forth to create a light source with volume. Instead of infinitely small light sources like in openGL. A shadow projection matrix is calculated using the new light position and then a cone is projected onto the floor plane and drawn as a black shadow. The results are accumulated with a factor based on the total number of samples.

Both the plane and the shadow are drawn every iteration, but the plane stays still while the shadow moves slightly due to the jittered light source. This results in the shadow having a dark center and lighter edges because the center pixels were rendered every time.

I haven't really dug too deeply into this sample, so if you have any more questions about it I can probably just post the function they use in the book to give you a better idea.

Share this post


Link to post
Share on other sites
I've got that working, using PCF, cheers.

What I need to know, is the distance between a shadow caster and receiver, so I can use this to compute a soft penumbra on the shadow. I'm presuming the best way to do this is by using depth values.

Share this post


Link to post
Share on other sites
I'm just shooting from the hip here, so this might not work out. If you split your geometry into shadow casters and shadow receivers such that no shadow caster is also a shadow receiver or vice versa (an assumption you might not be willing to make, as it rules out self shadowing), then you could render the depth of the occluders from the light into your standard shadow map, and then render the depth of the receivers from the light into a separate texture, then you could calculate the difference in a fragment shader. This wouldn't work for arbitrary scenes, but for a terrain, I think you could pull it off. Maybe if you played around with it a little, you could find a way to get around the no self shadowing assumption. I don't really know, I'm kindof just spilling out some rough thoughts here.

Share this post


Link to post
Share on other sites
Right.

I've come up with half a solution based upon blurring the depth map with a PCF kernel.

I can get the fragments distance from the light, by doing length(gl_Vertex-LightPos).

One thing I need to know is how to convert the scalar depth value into world units, so I can determine the distance the occluder is from the shadowed fragment.

If the near frustum is say at 1.0f, and the far frustum at 500.0f, I presume the the depth value is a log value between 1.0 and 500.0 right?

How do I convert this log depth value into a linear value between 1.0 and 500.0f?

Share this post


Link to post
Share on other sites
Cmon,

Someone out there must know how to get distances from a shadow caster to a fragment using a depth buffer for the shadow caster.

Share this post


Link to post
Share on other sites
I've found this formula that should convert from depth value to eye z coordinate:

a=-far/(far-near)
b=-far*near/(far-near)
Z=(a*z+b)/-z

I still have to try it, so I don't know if it works.
What you could try is the following:
-Get the depth value from the shadow map: you may need to use another texture unit bound to the shadow map, because otherwise you may not be able to read the depth value. Use the formula to transform the depth value first in light space and then in eye space.
-Get the fragment position and calculate the distance between the two points.

Let me know if that works, because I was interested too.

Share this post


Link to post
Share on other sites
Right,

I'm now mapping the linear distance from the light to the fragment (0.0-1.0) for the light frustum ( near = 1.0, far = 500.0).


vec4 l_pos = gl_LightSource[0].position;
vec4 f_pos = gl_ModelViewMatrix * vec4(cullvertex,1);
float far = 500.0;
float near = 1.0;
float dist = (1/far)*(abs(length(f_pos-l_pos))+near);





cullvertex is just gl_Vertex from the vert shader.

And this is what I get.

Free Image Hosting at www.ImageShack.us

Now I need the occluder's distance from the light, which is stored in the depth buffer. Ive tries using the depth texture with sampler2D and texture2DProj, but am having no luck.

If I can subtract the depth texture from the fragment depth, then it will solve the obvious problem with the shadow penumbra in the image below...

Free Image Hosting at www.ImageShack.us


Any ideas?

[Edited by - Lopez on May 24, 2006 1:20:00 PM]

Share this post


Link to post
Share on other sites
Well, if I got your problem right, you have your shadow map and want to get the distance of every single texel. To get this, I used the following formula:

float z = 100.0*0.1/(100.0-depth.x*(100.0-0.1));

where 100.0 is my far plane and 0.1 is my near plane. depth.x is the depth texture value got with texture2D(). Apparently, you cannot both read the depth value and use the shadow2d() function for comparation. To do that, you will need to bind the same depth texture to two samplers (using two units).

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this