Simple lens shader that uses object's normals to distort the background. Render texture without this object, use it as "ScreenMapSampler" and then render all scene including this object in final frame. Not best implementation, but it works.
struct PS_OUTPUT{float4 Color : COLOR0;};
struct VS_Lens
{
float4 Position: POSITION;
float4 ScreenMapSamplingPos: TEXCOORD0;
float3 Normal: TEXCOORD1;
float4 RefractionPosition: TEXCOORD2;
float Depth : TEXCOORD3;
};
VS_Lens vs_Lens( float4 inPos : POSITION, float3 vNormal: NORMAL)
{
VS_Lens Output = (VS_Lens)0;
float4x4 preViewProjection = mul (matView, matProjection);
float4x4 preWorldViewProjection = mul (matWorld, preViewProjection);
matrix viewProjectWorld = mul(matView, matProjection);
viewProjectWorld = mul(matWorld, viewProjectWorld);
float4x4 worldViewProj = mul(matWorld, matView);
worldViewProj = mul(worldViewProj, matProjection);
Output.RefractionPosition = mul(inPos, worldViewProj);
Output.ScreenMapSamplingPos = mul(inPos, preWorldViewProjection);
Output.Position = mul(inPos, preWorldViewProjection);
Output.Normal = vNormal;
Output.Depth = Output.Position.z;
return Output;
}
PS_OUTPUT ps_Lens(VS_Lens In)
{
PS_OUTPUT Output = (PS_OUTPUT)0;
float4 TextureCoords = In.RefractionPosition;
TextureCoords.xyz /= TextureCoords.w;
TextureCoords.x = 0.5f*TextureCoords.x + 0.5f;
TextureCoords.y = -0.5f*TextureCoords.y + 0.5f;
TextureCoords.z = .1f / TextureCoords.z;
Output.Color = tex2D(ScreenMapSampler, TextureCoords.xy - TextureCoords.z * In.Normal.xz);
return Output;
}
technique Lens
{
pass Pass0
{
VertexShader = compile vs_3_0 vs_Lens();
PixelShader = compile ps_3_0 ps_Lens();
}
}