Incorrect PCF on Ati hardware?

51mon

Newcomer
Hi
I have implemented hardware PCF for a demo application. On Nvidia GPU's the approach is pretty straight forward. I use the z-buffer as a texture and sample it with tex2Dproj, then the PCF is carried out automatically. On Ati hardware the case was a little bit trickier. I had to use the fetch4 functionality and emulate bilinear interpolation between the four samples in the shader. My code look like this:

Code:
	// Application code
	V( pd3dDevice->CreateTexture( SHADOW_BUFFER_WIDTH, SHADOW_BUFFER_HEIGHT, 1, D3DUSAGE_DEPTHSTENCIL, (D3DFORMAT)(MAKEFOURCC('D','F','2','4')), 
		D3DPOOL_DEFAULT, &g_pShadowTexture, NULL));

	V( pd3dDevice->SetSamplerState( 0, D3DSAMP_MIPMAPLODBIAS, MAKEFOURCC('G','E','T','4')));
	V( pd3dDevice->SetSamplerState( 0, D3DSAMP_MINFILTER, D3DTEXF_POINT));
	V( pd3dDevice->SetSamplerState( 0, D3DSAMP_MAGFILTER, D3DTEXF_POINT));


	// Shader code
	float4 vecNormCoord = In.LightSpacePos.xyzw / In.LightSpacePos.wwww;
    	float4 vecShadowBufferComparision = tex2D( ShadowBufferSampler, vecNormCoord);
    	float4 vecComparison = (vecShadowBufferComparision.rgba > vecNormCoord.zzzz);
    
    	float4 vecFrac;
    	vecFrac.xy = frac( vecNormCoord.xy * float2( SHADOW_BUFFER_WIDTH, SHADOW_BUFFER_HEIGHT));
    	vecFrac.zw = float2( 1.0f, 1.0f) - vecFrac.xy;		
	float4 vecBilinearWeights = vecFrac.xzxz * vecFrac.wyyw;
	float shadow = dot( vecComparision, vecBilinearWeights);

The problem is that the visual result is not the same on both vendors. Even though the artefacts on Ati is not too severe, Nvidia looks much better. See the comparison pictures bellow.

test1_comparison.jpg


As you can see the shadows is not identical and Ati hardware got black and white stripes running through the penumbra of the shadows.

test2_ati.jpg


I don't know the reason for this problem or if it can be fixed. I found the order in which the four samples from fetch4 operation is interpolated by trial&error. Am I doing it right? Also I tried to add a small bias to float2( SHADOW_BUFFER_WIDTH, SHADOW_BUFFER_HEIGHT) and the the artefacts became severer. Which indicate that there might be some numerical instability bug somehow? I don't know. If someone could explain what's going wrong I would be really happy.

Thanks
 
First of all, don't do a vendor check for PCF because all ATI DX10 cards support the DX9 PCF backdoor too.

As for the problem, it's because the texture unit may not switch to the next texel at the exact time as your frac(texcoord * size) snaps over. The solution is the snap the texture coordinates to the center of the texel. Since you're already computing the fraction it should be straightforward.
 
First of all, don't do a vendor check for PCF because all ATI DX10 cards support the DX9 PCF backdoor too.

The implementation is in DX9. So I do a vendor check to tell which shader to use. Do you mean that there is a uniform way to do it?

As for the problem, it's because the texture unit may not switch to the next texel at the exact time as your frac(texcoord * size) snaps over. The solution is the snap the texture coordinates to the center of the texel. Since you're already computing the fraction it should be straightforward.

I put a constant offset to the equation, frac(texcoord * size + offset). I found that offset = 0.0078 gave a good result. The number don't really make any sense to me but I guess it's related to the hardware. One question remains though. Why do the shadows look differently on Ati vs Nvidia? In my first post I included a comparison image (the light source got the same position in both).
 
Back
Top