Trouble Implementing Gradient Shadow Map

jbizzler

Newcomer
Now that I finally got DX10 to let me write to my shadow map after using it in a render pass, I need to eliminate the the surface acne. I have Shader X5, and it talks about Gradient Shadow Maps, but mostly refers to the chapter in Shader X4, which I do not have. Here's my pixel shader wihout any gradient:

Code:
float4 PS(PS_In input) : SV_TARGET
{	
	float amb = 0.4f;
	float diff = 0;
	float spec = 0;
	
	float2 sampleCoord = 0.5f * input.LightPos.xy / input.LightPos.w + float2(0.5, 0.5);
	sampleCoord.y = 1.0f - sampleCoord.y;
	
	if(input.LightPos.z < ShadowMap.Sample(Linear, sampleCoord).x + 0.00005f)
	{
		float3 N = normalize(input.Norm);
		float3 V = normalize(EyePos - input.wPos);
		float3 R = normalize(reflect(-L, N));
	
		diff = saturate(dot(N, L));
		spec = pow(saturate(dot(V, R)), 32);
	}
	
	float4 output;
	output.rgb = (float3)0.5f * (amb + diff + spec);
	output.a = 1;
	return output;
}
Which turns out as expected, but not good enough.

And then when I try and implement the gradient:

Code:
float4 PS(PS_In input) : SV_TARGET
{	
	float amb = 0.4f;
	float diff = 0;
	float spec = 0;
	
	float2 gradientVector = float2(input.LightPos.z / input.LightPos.x, input.LightPos.z / input.LightPos.y);
	float gradient = length(gradientVector);
	
	float2 sampleCoord = 0.5f * input.LightPos.xy / input.LightPos.w + float2(0.5, 0.5);
	sampleCoord.y = 1.0f - sampleCoord.y;
	
	float difference = ShadowMap.Sample(Linear, sampleCoord).x - input.LightPos.x;
	
	if(saturate(difference / gradient + 1))
	{
		float3 N = normalize(input.Norm);
		float3 V = normalize(EyePos - input.wPos);
		float3 R = normalize(reflect(-L, N));
	
		diff = saturate(dot(N, L));
		spec = pow(saturate(dot(V, R)), 32);
	}
	
	float4 output;
	output.rgb = (float3)0.5f * (amb + diff + spec);
	output.a = 1;
	return output;
}
Which turns out all with shadow in random places. What am I doing wrong?
 
I have no D3D10/SM4 experience and have not seen gradient shadow mapping, but could you explain this line?
Code:
if(saturate(difference / gradient + 1))
Whatever 'difference / gradient' turns out to be, adding 1 and saturating it will always yield 1, I would think. And you should probably be testing the result to be greater than or less than a certain value. I don't know what testing a float for true/false means.
 
Nor do I. This is just a SM4 implementation of the pseudocode in Shader X5, that they don't explain bust instead refer to Shader X4. I can't seem to find any documentation on it other than it.
 
Yeah, it's a bit late but it's better than never... The points is that you misinterpreted the formula with (dz/dx, dz/dy). These are partial derivatives, which can be computed taking finite differencing.

Here you have some nice slides: http://www.slideshare.net/ohyecloudy/42-eliminating-surface-acne-with-gradient-shadow-mapping

And code I've just written:
Code:
float SSM(float2 projTexCoord, float depth, float bias)
{
	float texelSize = 1.0f / shadowMapSize;

	float d1 = tex2D(shadowMapSampler_point, projTexCoord + float2(+texelSize, 0.0f));
	float d2 = tex2D(shadowMapSampler_point, projTexCoord + float2(-texelSize, 0.0f));
	float d3 = tex2D(shadowMapSampler_point, projTexCoord + float2(0.0f, +texelSize));
	float d4 = tex2D(shadowMapSampler_point, projTexCoord + float2(0.0f, -texelSize));

	float dx = abs(d1 - d2);
	float dy = abs(d3 - d4);

	float gradient = length(float2(dx, dy));

	float slopeScaleBias = 2.0f;

	return tex2D(shadowMapSampler_point, projTexCoord) > depth - slopeScaleBias*gradient;
}

Note that gradient can also be compute with gradient = max(dx, dy). Length just seems a bit more natural.
 
Back
Top