Original Post
So I have been trying out this new method (new to me) to generate shadow maps, by giving each object their own shadow map rendered to a texture atlas and then projecting each portion of the map to the scene. The shadows look right, in that they are where they are supposed to be for each object, but a lot of them have dark boxes that take over part or all of the shadow's shape. This is something that I haven't encountered before in other methods I've used in shadow mapping. I have a feeling that the depth comparison is not sitting in well with the way I render each individual object.
For each shadow caster that is lit by a directional light, I create a tightly fitting bounding frustum that encloses the bounding box for that object. Long or skinny objects have the dark box problem the worst, their shadow shapes are covered more by it.
I noticed that scaling up the size of the bounding frustum remedies the problem somewhat, but it's not a consistent solution for all shadow casters. Plus, scaling up makes the object render smaller in the shadow map, and the shadows more low-res quality which goes against the purpose of using this shadow mapping technique.
Here is a video showing the problem, this time with just one object as a shadow caster (I cut back from texture atlases to isolate the problem). The light is rotating and with it the dark box stretches and rotates with it. The shadows *are* supposed to be off the pillars, since the pillars are ignored as shadow casters.
This is what my shader code for projecting shadow maps looks like. I'm sampling from depth G-Buffer to compare depths, not the depth from actual geometry.
[source lang="cpp"]
float depthVal = tex2D(depthSampler, input.TexCoord).r;
// Convert position to world space
float4 position;
position.xy = input.TexCoord.x * 2.0f - 1.0f;
position.y = -(input.TexCoord.y * 2.0f - 1.0f);
position.z = depthVal;
position.w = 1.0f;
position = mul(position, invertViewProj);
position /= position.w;
// Get shadow map position projected in light view
float4 shadowMapPos = mul(position, lightViewProj);
// Find the position in the shadow map for this pixel
float2 shadowTexCoord = shadowMapPos.xy / shadowMapPos.w / 2.0f + float2(0.5, 0.5);
shadowTexCoord.y = 1 - shadowTexCoord.y;
float shadowdepth = 0;
float3 shadow = 1;
// Calculate the current pixel depth
float ourdepth = (shadowMapPos.z / shadowMapPos.w) - DepthBias;
if ((shadowTexCoord.x <= 1 && shadowTexCoord.y <= 1) &&
(shadowTexCoord.x >= 0 && shadowTexCoord.y >= 0))
{
shadowdepth = tex2D(shadowMapSampler, shadowTexCoord).r;
shadow = shadowdepth > ourdepth;
}[/source]
For each shadow caster that is lit by a directional light, I create a tightly fitting bounding frustum that encloses the bounding box for that object. Long or skinny objects have the dark box problem the worst, their shadow shapes are covered more by it.
I noticed that scaling up the size of the bounding frustum remedies the problem somewhat, but it's not a consistent solution for all shadow casters. Plus, scaling up makes the object render smaller in the shadow map, and the shadows more low-res quality which goes against the purpose of using this shadow mapping technique.
Here is a video showing the problem, this time with just one object as a shadow caster (I cut back from texture atlases to isolate the problem). The light is rotating and with it the dark box stretches and rotates with it. The shadows *are* supposed to be off the pillars, since the pillars are ignored as shadow casters.
This is what my shader code for projecting shadow maps looks like. I'm sampling from depth G-Buffer to compare depths, not the depth from actual geometry.
[source lang="cpp"]
float depthVal = tex2D(depthSampler, input.TexCoord).r;
// Convert position to world space
float4 position;
position.xy = input.TexCoord.x * 2.0f - 1.0f;
position.y = -(input.TexCoord.y * 2.0f - 1.0f);
position.z = depthVal;
position.w = 1.0f;
position = mul(position, invertViewProj);
position /= position.w;
// Get shadow map position projected in light view
float4 shadowMapPos = mul(position, lightViewProj);
// Find the position in the shadow map for this pixel
float2 shadowTexCoord = shadowMapPos.xy / shadowMapPos.w / 2.0f + float2(0.5, 0.5);
shadowTexCoord.y = 1 - shadowTexCoord.y;
float shadowdepth = 0;
float3 shadow = 1;
// Calculate the current pixel depth
float ourdepth = (shadowMapPos.z / shadowMapPos.w) - DepthBias;
if ((shadowTexCoord.x <= 1 && shadowTexCoord.y <= 1) &&
(shadowTexCoord.x >= 0 && shadowTexCoord.y >= 0))
{
shadowdepth = tex2D(shadowMapSampler, shadowTexCoord).r;
shadow = shadowdepth > ourdepth;
}[/source]
