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();
}
}