Shadow maps being cut off

Started by
17 comments, last by bjarnia 14 years ago
I'm trying to get my cascaded shadow maps implementation working and I'm facing a problem that I'm stuck on. This is the intended shadow for the car: http://www.steik.org/dump/Cosmopolis2010-04-1100-20-55-11.png This is however what I will see with a slightly different item-to-split population: http://www.steik.org/dump/Cosmopolis2010-04-1100-21-28-51.png During my debugging I came up with a dirty hack in the PCF function to at least make the wrong areas not black (shadowed) (see the first if statement)

    if (vTexCoord.z >= 0.999) 
    {
        ret = 1;
    }
    else
    {
        // 2x2 PCF Filtering    
        float fShadow[4];
        fShadow[0] = (vTexCoord.z - DepthBias[split] < tex2D(sam, vTexCoord + float2(0,         0)).r);
        fShadow[1] = (vTexCoord.z - DepthBias[split] < tex2D(sam, vTexCoord + float2(TexelSize, 0)).r);
        fShadow[2] = (vTexCoord.z - DepthBias[split] < tex2D(sam, vTexCoord + float2(0,         TexelSize)).r);
        fShadow[3] = (vTexCoord.z - DepthBias[split] < tex2D(sam, vTexCoord + float2(TexelSize, TexelSize)).r);
        
        float2 vLerpFactor = frac(ShadowMapSize * vTexCoord.xy);
        ret = lerp(lerp(fShadow[0], fShadow[1], vLerpFactor.x), lerp(fShadow[2], fShadow[3], vLerpFactor.x), vLerpFactor.y);
    }    
This is what happens with the hack: http://www.steik.org/dump/Cosmopolis2010-04-1100-20-51-76.png As you can see this is also a problem with the first split in all pictures. In all cases the geometry IS clearly being written in the depth map (see frames 1 and 2 on the top from the left), so I think it is just some stupid texture coordinate problem. I however have no idea pretty much why or how to fix this. I am basing my code on "Chapter 10: Parallel-Split Shadow Maps on Programmable GPUs" from GPU Gems 3. Clearly the LightViewProjection is correct since the depth maps are being drawn correctly, and the only thing I do extra when I sample it later is this: LightViewProjectionCropped * shadowMapTextureScale where the scaling matrix is a relatively standard matrix:
            
float shadowMapTexOffset = 0.5f + (0.5f / (float)shadowMapSize);

            return new Matrix(0.5f, 0.0f, 0.0f, 0.0f,
                              0.0f, -0.5f, 0.0f, 0.0f,
                              0.0f, 0.0f, 1.0f, 0.0f,
                              shadowMapTexOffset, shadowMapTexOffset, 0.0f, 1.0f);
      
So yeah.. This error doesn't really make sense to me since the depth maps are being drawn right. Any ideas?
____________________________Bjarni Arnasonbjarni.us
Advertisement
Hey, nice Lada 1200 model!

My guess is that you only apply the first (closest-to-light) shadowmap to the scene.
(BTW how did you get the working version?)

You have to sample from the other maps too.
I'm not in the shader stuff yet, and I don't know how the PSM works in that case, but I have a hunch that you should do something like this:
texture_unit = floor(vTexCoord.z); // will be 2 if vTexCoord.z = 2.3vTexCoord.z -= texture_unit; // will be 0.3 if vTexCoord.z = 2.3....//take sample from texture_unit
But it's just a wild guess.
Quote:Original post by szecs
Hey, nice Lada 1200 model!

My guess is that you only apply the first (closest-to-light) shadowmap to the scene.
(BTW how did you get the working version?)

You have to sample from the other maps too.
I'm not in the shader stuff yet, and I don't know how the CSM works in that case, but I have a hunch that you should do something like this:
texture_unit = floor(vTexCoord.z); // will be 2 if vTexCoord.z = 2.3vTexCoord.z -= texture_unit; // will be 0.3 if vTexCoord.z = 2.3....//take sample from texture_unit
But it's just a wild guess.


Working version of the GPU Gems Code? I can email it to you if you want.

I'm sampling from all of the maps, based on the coloring you see in the screenshot, thought that was kind of a given :) Red is closest, then green, blue and magenta.
That part works.

Edit: Also, that explanation would not fit since the part that is casting shadow is actually rendered on all of the depth maps.
____________________________Bjarni Arnasonbjarni.us
Then why don't I see it in the code?

Your code doesn't switch between textures, or you haven't posted the relevant code.

And the scene is just confusing. you should use simpler meshes for testing, cubes, for example. But the generated shadow maps seem fine.

I don't know, I guess I miss something, sorry.


BTW, your returned matrix seems very strange.
You only have to apply the offset (bias) in the 'z' direction:

(0.5f, 0.0f, 0.0f, 0.0f,
0.0f, -0.5f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f, 0.0f,
0.0f, 0.0f, shadowMapTexOffset, 1.0f); //or maybe -shadowMapTexOffset

Or I totally misunderstand something.
I'm confused by your shadow maps, are you sure they're not inverted? Assuming your sun position is supposed to be behind your viewer's right shoulder, shouldn't the 1st shadowmap have the front of the car on the left of the image rather than the right?

Edit: plus I totally agree with szecs that getting shadow mapping working with simple geometry is far easier. I'd stick a few different sized cubes in instead of the lada and try again.
Quote:Original post by szecs
Then why don't I see it in the code?

Your code doesn't switch between textures, or you haven't posted the relevant code.

And the scene is just confusing. you should use simpler meshes for testing, cubes, for example. But the generated shadow maps seem fine.

I don't know, I guess I miss something, sorry.


I refrained from posting the entire code as that that would likely be in the range of some hundred lines and resulting in a big wall of text.

The code I posted is just my SamplePCF function:
float SamplePCF(sampler2D sam, float4 vTexCoord, int split)

It is called as follows in the pixel shader:

    if(fDistance < SplitDistances[0])    {        fLightingFactor = SamplePCF(ShadowMapSampler[0], input.vTexCoord[0], 0);		output.Color = float4(1, 0, 0, 1);    }    else if(fDistance < SplitDistances[1])    {        fLightingFactor = SamplePCF(ShadowMapSampler[1], input.vTexCoord[1], 1);		output.Color = float4(0, 1, 0, 1);    }    else if(fDistance < SplitDistances[2])    {        fLightingFactor = SamplePCF(ShadowMapSampler[2], input.vTexCoord[2], 2);		output.Color = float4(0, 0, 1, 1);    }    else if(fDistance < SplitDistances[3])    {        fLightingFactor = SamplePCF(ShadowMapSampler[3], input.vTexCoord[3], 3);		output.Color = float4(1, 0, 1, 1);    }


the output.Color assignments are for the debugging of split positions.

As for the scene setup, I would normally agree, but with real objects I feel like I have a better view of what the shadow should actually be. But maybe I'm just weird :)

Quote:



BTW, your returned matrix seems very strange.
You only have to apply the offset (bias) in the 'z' direction:

(0.5f, 0.0f, 0.0f, 0.0f,
0.0f, -0.5f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f, 0.0f,
0.0f, 0.0f, shadowMapTexOffset, 1.0f); //or maybe -shadowMapTexOffset

Or I totally misunderstand something.



Hmm.. thanks, I'll take a look.
____________________________Bjarni Arnasonbjarni.us
Quote:Original post by RobMaddison
I'm confused by your shadow maps, are you sure they're not inverted? Assuming your sun position is supposed to be behind your viewer's right shoulder, shouldn't the 1st shadowmap have the front of the car on the left of the image rather than the right?

Edit: plus I totally agree with szecs that getting shadow mapping working with simple geometry is far easier. I'd stick a few different sized cubes in instead of the lada and try again.


Interesting, I had not noticed that before. Thanks!

Ps. If I wouldn't have had the lada and had a cube instead, you would not have noticed this error :)
____________________________Bjarni Arnasonbjarni.us
Wait a bit!

I use this:
#define SHADOW_BIAS		0.4995f...float scale_x = 0.5*SCRN_WDTH/2048.0;//SM-size: 2048 x 2048, but I only use the srceen size portionfloat scale_y = 0.5*SCRN_HGHT/2048.0;//you have '-' here, because the mirrored imagefloat biasMatrix[16] = {scale_x, 0.0f, 0.0f, 0.0f,			0.0f, scale_y, 0.0f, 0.0f,			0.0f, 0.0f, 0.5f, 0.0f,			scale_x, scale_y, SHADOW_BIAS, 1.0f};
Try to work it out from this [rolleyes]

EDIT: okay I get it:
float biasMatrix[16] = {0.5, 0.0f, 0.0f, 0.0f,			0.0f, 0.5, 0.0f, 0.0f,			0.0f, 0.0f, 0.5f, 0.0f,			0.5, 0.5, SHADOW_BIAS, 1.0f};
Quote:Ps. If I wouldn't have had the lada and had a cube instead, you would not have noticed this error :)


Ah, but that's why you use different sized cubes! :)
I'm sure now that the problem is with your returned matrix.
And cubes are better: it's easier to spot self-shadowing artifacts than in your complex scene.

It would have been easier to spot the real problem: the shadows are not cut off, but they are wrongly offseted and wrongly scaled in the light direction.

But I'm not totally sure yet.

This topic is closed to new replies.

Advertisement