Soft Shadow

Started by
7 comments, last by cignox1 17 years, 11 months ago
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.
Advertisement
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.
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.
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.
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?

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

This topic is closed to new replies.

Advertisement