• Create Account

# NoMonkey89

Member Since 13 Feb 2013
Offline Last Active Mar 13 2013 07:19 AM

### Calculating viewspace coordinates from depth and texture coordinates

13 February 2013 - 12:15 PM

Hello,

I got my billboard quad particles and using a shader they look like spheres. I save the depth from those spheres in a texture.

At the next step I have to blur the depth.

Now I put this blurred texture on a screen filling quad and let the next shader run on it.

Now I have to create the normals at this point. To get the normals I have to calculate the view-space coordinates from the depth and texture coordinates (see slide 18).

My problem is the mysterious uvToEye-function.

I found some code to recalculate the coordinates here: http://mynameismjp.wordpress.com/2009/03/10/reconstructing-position-from-depth/ but it doesn't work (all I seem to get is (0,0,0) for every point).

This is my code: I skipped the blur-step since I figured there is no need to blur the depth before I cant calculate normals from it.

```struct VertexIn
{
float4 pos    	: POSITION;
float2 texco    : TEXCOORD0;
};

struct VertexOut
{
float4 	pos			: POSITION;
float2 	texco			: TEXCOORD0;
float3	eyeSpacePos		: TEXCOORD1;
};

struct PixelInput
{
float2	texco			: TEXCOORD0;
float3	eyeSpacePos		: TEXCOORD1;
};

struct PixelOutput
{
float4	color		: COLOR0;
};

VertexOut mainVS(	VertexIn	input,
uniform float4x4	worldViewProj_m,
uniform float4x4	worldView_m,
)
{
VertexOut output = (VertexOut)0;
input.pos.y += sphereRadius; //partikel nicht im Boden versinken lassen
output.pos = mul( worldViewProj_m, input.pos );
output.texco = input.texco;
output.eyeSpacePos = mul(worldView_m, input.pos).xyz;
return output;

}

PixelOutput mainPS(PixelInput input,
uniform float4x4 projMatrix,
)
{
PixelOutput output = (PixelOutput)0;
// calculate eye-space sphere normal from texture coordinates
float3 N;
N.xy = input.texco*2.0-1.0;
float r2 = dot(N.xy, N.xy);
if (r2 > 1.0) discard;   // kill pixels outside circle
N.z = sqrt(1.0 - r2);

// calculate depth
float4 pixelPos = float4(input.eyeSpacePos + N*sphereRadius, 1.0); //approximation of a sphere
float4 clipSpacePos = mul(projMatrix,pixelPos);
float fragDepth = clipSpacePos.z / clipSpacePos.w;
output.color.r = fragDepth;
return output;
}

```

And this is my shader for calculating the normals:

```struct VertexIn
{
float4 pos    	: POSITION;
float2 texco    : TEXCOORD0;
};

struct VertexOut
{
float4 	pos	: POSITION;
float2 	texco	: TEXCOORD0;
};

struct PixelInput
{
float2	texco	: TEXCOORD0;
};

struct PixelOutput
{
float4	color	: COLOR0;
};

VertexOut mainVS(VertexIn input,
uniform float4x4 worldViewProj_m)
{
VertexOut output = (VertexOut)0;
output.pos = mul( worldViewProj_m, input.pos );
output.texco = input.texco;
return output;
}

float3 uvToEye(float2 texCoord, float depth, float4x4 iP_m){
// Get x/w and y/w from the viewport position
float x = texCoord.x * 2.0 - 1.0;
float y = (1 - texCoord.y) * 2.0 - 1.0;
//float y = texCoord.y * 2.0 - 1.0;
float4 clipPos = float4(x , y, depth, 1.0f);
// Transform by the inverse projection matrix
//float4 viewPos = mul(clipPos, iP_m);
float4 viewPos = mul(iP_m , clipPos);
// Divide by w to get the view-space position
return viewPos.xyz / viewPos.w;
}

PixelOutput mainPS(PixelInput input,
uniform sampler	depthTex: register(s0),
uniform float4x4 invProj_m)
{
PixelOutput output = (PixelOutput)0;

// read eye-space depth from texture
float depth = tex2D(depthTex, input.texco).r;

// calculate eye-space position from depth
float texelSize = 0.0001; // correct value?

// calculate differences

float3 ddx1 = uvToEye(input.texco + float2(texelSize, 0), tex2D(depthTex, input.texco + float2(texelSize, 0)).r, invProj_m) - posEye;
float3 ddx2 = posEye - uvToEye(input.texco + float2(-texelSize, 0), tex2D(depthTex, input.texco + float2(-texelSize, 0)).r, invProj_m);
ddx1 = -ddx2 + ddx1;

if (abs(ddx1.z) > abs(ddx2.z)) {
ddx1 = ddx2;
}

float3 ddy1 = uvToEye(input.texco + float2(0, texelSize), tex2D(depthTex, input.texco + float2(0, texelSize)).r, invProj_m) - posEye;
float3 ddy2 = posEye - uvToEye(input.texco + float2(0, -texelSize), tex2D(depthTex, input.texco + float2(0, -texelSize)).r, invProj_m);
ddy1 = -ddy2 + ddy1;

if (abs(ddy2.z) < abs(ddy1.z)) {
ddy1 = ddy2;
}

// calculate normal
float3 n = cross(ddx1, ddy1);
n = normalize(n);

//output.color = float4(posEye, 1.0); // for testing, results in a black screen

output.color = float4(n,1);
return output;
}

```

I hope someone here can tell me what I'm doing wrong and what is the right way to do it.

Regards,

Kilian

PARTNERS