Inspired by this post
http://www.gamedev.net/blog/1323/entry-2254101-real-time-local-reflections/
I've written a GPU (depth) raytracer for screen space reflections on arbitrary surfaces that is surprisingly fast, even unoptimized (up to 1024fps on my 5870, depending on the amount of object shader pixels visible). However, I have a problem with the implementation that I cannot fix, the reflection image gets clinched when you decrease the distance to the surface:





The effect code:
Click to reveal..
Code:
float4x4 matWorldViewProj;
float4x4 matWorld;
float4x4 matViewProj;
float4x4 matView;
float4x4 matProj;
float4 vecViewPos;

texture bmp_camera_bmap;
texture bmp_depth_bmap;

sampler CameraSampler = sampler_state 
{ 
	Texture = <bmp_camera_bmap>; 
	AddressU  = Clamp; 
	AddressV  = Clamp; 
}; 

sampler DepthSampler = sampler_state 
{ 
	Texture = <bmp_depth_bmap>; 
	AddressU  = Clamp; 
	AddressV  = Clamp; 
}; 

// Vertex Shader: 
void ReflectVS( 
in float4 InPos: POSITION, 
in float3 InNormal: NORMAL, 
in float2 InTex: TEXCOORD0, 
out float4 OutPos: POSITION, 
out float2 OutTex: TEXCOORD0, 
out float3 OutNormal: TEXCOORD1,
out float4 ProjTex: TEXCOORD2,
out float4 OutPos2: TEXCOORD3) 
{ 
	OutPos = mul(InPos, matWorldViewProj);
	OutNormal = normalize(mul(InNormal, matWorld));
	OutTex = InTex; 
	ProjTex = OutPos;
	OutPos2 = mul(InPos, matWorld);
} 

// Pixel Shader: 
float4 ReflectPS( 
in float2 InTex: TEXCOORD0, 
in float3 InNormal: TEXCOORD1,
in float4 ProjTex: TEXCOORD2,
in float4 InPos: TEXCOORD3): COLOR 
{ 
	InNormal = normalize(InNormal);
	ProjTex.xy = ProjTex.xy/ProjTex.w;
	float3 projViewPos = ProjTex.xyz;
	ProjTex.xy = ProjTex.xy*0.5 + 0.5;
	ProjTex.y = 1-ProjTex.y;

	// calculate reflection vector in view space
	float3 viewpos = mul(InPos,matView).xyz;
	float3 dir = viewpos.xyz;
	dir = reflect(viewpos.xyz,mul(InNormal,matView));
	dir = normalize(dir);
	
	// transform from view to screen space
	float4 tPos = mul(float4(viewpos+dir,1), matProj);
	tPos.xy = tPos.xy/tPos.w;
	float3 screenDir = tPos.xyz-projViewPos;
	screenDir *= 0.05/length(screenDir.xy); // start with a rather big length and refine if necessary

	// transform from screen to texture coordinates
	float3 screenPos = projViewPos+screenDir;
	screenPos.xy = screenPos.xy*0.5 + 0.5;
	screenPos.y = 1-screenPos.y;
	screenDir.x *= 0.5;
	screenDir.y *= -0.5;

	float depth;
	int max_num = 30;
	int done = 0;
	float3 oldPos = ProjTex;
	for(int i = 0; i < max_num; i++)
	{
		depth = tex2D(DepthSampler, screenPos.xy).x;
		if(depth < screenPos.z) // refine search
		{
			screenPos = oldPos;
			screenDir *= 0.5;
			screenPos += screenDir;
			done++;
		}
		else
		{
			oldPos = screenPos.xyz;
			screenPos.xyz += screenDir;
		}
	}
	if(done < 1) return 0;
	return tex2D(CameraSampler, screenPos.xy);
} 

technique ReflectTechnique 
{ 
	pass P0 
	{ 
		VertexShader = compile vs_3_0 ReflectVS(); 
		PixelShader  = compile ps_3_0 ReflectPS(); 
	} 
}


Please help me and fix the code or tell me where the problem lies, I've tried everything (in return you get the source code for your own applications, of course).

Download the test scene from above: http://www.superku.de/reflect.zip
Thanks in advance for any help!


"Falls das Resultat nicht einfach nur dermassen gut aussieht, sollten Sie nochmal von vorn anfangen..." - Manual

Check out my new game: Pogostuck: Rage With Your Friends