3
votes

I have an issue with shadows cast by object really far away from the light source. I am using the depth map approach for rendering shadows in my Solar System simulation. The sun is a point light source and I would like to observe the shadow of the moon on the earth. But since the moon is a really tiny object relative to the distance between it and the sun and since the depth map resolution is limited, the presence of the moon and earth are ignored when rendering the depth cube map texture.

Solar System Depth Map:

enter image description here

You can see that even with the size of the moon exaggerated, it only leaves a small footprint on the depth cube map. With this big of a moon, the eclipses do work but once i shrink the moon to its actual size it is no longer rendered in the depth map and because of that, no longer taken into account for shadow calculations. I am using a 4096 X 4096 texture. Is there a way to solve this problem or is my approach doomed to fail? Any help would be much appreciated.

1
Are you sure that depth maps are a good approach for shadows in such a scene? Since you have a tiny number of tiny objects, shadow volumes may suit you better.lisyarus
I am not sure its the best approach. That's why I am asking. Shadow Mapping is the only approach I know.Grupa

1 Answers

4
votes

There is a crucial observation to make: when you look up close at earth you, probably, don't care about shadows on mars. Therefore, instead of using a cube-map to shadow map the entire solar system, use a planar shadow map to cover only the near-earth region.

With a 4096x4096 depth map and distance to moon of 384000 km, you get a resolution of ~100km per texel and the moon will take up a disk of ~20 texels in radius on the shadow map.

There is, however, a better approach. Since planets and moons are approximately spherical and there are just a handful of them, you can simply do ray-sphere intersections per fragment to calculate the shadows. It's possible to calculate the angular area of the intersection between the moon and the sun disks in order to get real-time umbra/penumbra rendering. Here is a function that approximates the shadow factor in the shader:

float soft_shadow(vec3 light, float light_radius,
    vec3 occluder, float occluder_radius, vec3 fragment)
{
    vec3 v0 = light - fragment;
    vec3 v1 = occluder - fragment;

    float R0 = length(v0);
    float R1 = length(v1);

    float a0 = light_radius/R0;
    float a1 = occluder_radius/R1;

    float a = length(cross(v0, v1))/(R0*R1);
    a = smoothstep(a0 - a1, a0 + a1, a);
    return 1 - (1 - a)*pow(a1/a0, 2);
}

Here 0.0 means full shadow, 1.0 means no shadow at all. The light, occluder and fragment are the locations of the sun, moon and the fragment in the non-projective space, whereas light_radius and occluder_radius are the radii of the sun and the moon.

For realistic dimensions this code gives me these images:

If I decrease the size of the sun by half, I get these: