I think you are storing linear depth, but I'm unsure. I don't do it in that way, I do it like this. Obviously ignore the RGB output, the A is linear depth and fFar is the far plane value.
float4x4 wvp : WORLDVIEWPROJECTION;
float4x4 wv : WORLDVIEW;
float4x4 w : WORLD;
float fFar;
texture b: TEXTURE1;
sampler2D bs = sampler_state {
Texture = (b);
MIPFILTER = LINEAR;
MINFILTER = LINEAR;
MAGFILTER = LINEAR;
};
struct a2v {
float4 p : POSITION0;
float3 t : TANGENT;
float3 b : BINORMAL;
float3 n : NORMAL;
float2 uv: TEXCOORD0;
};
struct v2f {
float4 p : POSITION0;
float2 uv: TEXCOORD0;
float3 t : TEXCOORD1;
float3 b : TEXCOORD2;
float3 n : TEXCOORD3;
float z : TEXCOORD4;
};
v2f vp(in a2v _in) {
v2f _out;
_out.p = mul(_in.p, wvp);
_out.uv = _in.uv;
_out.t = _in.t;
_out.b = _in.b;
_out.n = _in.n;
_out.z = mul(_in.p, wv).z;
return _out;
}
float4 fp(in v2f _in): COLOR0 {
float3x3 tbn = float3x3(_in.t, _in.b, _in.n);
float3x3 ttw = mul(tbn, (float4x3)w);
float3 n = 2 * tex2D(bs, _in.uv) - 1;
return float4(mul(n, ttw), _in.z / fFar);
}
technique render {
pass p0 {
VertexShader = compile vs_2_0 vp();
PixelShader = compile ps_2_0 fp();
}
}