Sign in to follow this  
zhugel_007

calculate depth value in vertex shader

Recommended Posts

zhugel_007    126
Hi, I am currently working on the volumetric fog. I need to render the scene depth into a texture so that i could use it to calculate the thickness of the fog. I've got some problem of render the depth value into the texture. Here are the vertex&pixel shaders : float4x4 matViewProjection; struct VS_INPUT { float4 Position : POSITION0; }; struct VS_OUTPUT { float4 Position : POSITION0; float Depth : TEXCOORD0; }; VS_OUTPUT vs_main( VS_INPUT Input ) { VS_OUTPUT Output; Output.Position = mul( Input.Position, matViewProjection ); Output.Depth = (Output.Position.z/Output.Position.w); return( Output ); } float4 ps_main(float Depth: TEXCOORD0) : COLOR0 { return Depth; } But when i check the texture, it is almost purely white. :( I was thinking the depth value should be in the range [0,1] so that at least the texture shouldn't be that white... Did i do anything wrong? Can someone give me a hint? Thanks in advance. :)

Share this post


Link to post
Share on other sites
MJP    19788
You have to do the perspective divide after interpolation. In other words...do this:

struct VS_INPUT
{
float4 Position : POSITION0;
};

struct VS_OUTPUT
{
float4 Position : POSITION0;
float2 Depth : TEXCOORD0;
};

VS_OUTPUT vs_main( VS_INPUT Input )
{
VS_OUTPUT Output;

Output.Position = mul( Input.Position, matViewProjection );
Output.Depth = Output.Position.zw;

return( Output );
}

float4 ps_main(float2 Depth: TEXCOORD0) : COLOR0
{
return Depth.x/Depth.y;
}

Share this post


Link to post
Share on other sites
MJP is correct, but even with your approach you might have seen some change of color. The reason you are not seeing any differences of color may be because either vertices in front of the camera are too close so they do not have much difference in depth or may be the far plane is too large.

Share this post


Link to post
Share on other sites
zhugel_007    126
Thanks MJP and akm_masuduzzaman for your quick reply! :)

I've tried your shader, it seems still has the same problem. :(

I was wondering why should i do the perspective divide after interpolation? Could you please explain more?

and i am a bit confused. if the object is close to the camera, the z value should be almost 0 so that the color in the depth texture should be almost black, right?

Thanks!

Share this post


Link to post
Share on other sites
MJP    19788
"close to the camera" is relative to your projection parameters. If your pixel is at z = 1.8 and the near clipping plane is at 1.0, the pixel is still not very close if the far plane is at z = 2.0. What sort of parameters are you using for creating your perspective projection?

Share this post


Link to post
Share on other sites
Jason Z    6436
I think what you actually want is the linear distance to each object in the scene, not the projection space distance. If you calculate the view space position of the vertex and pass it to the pixel shader, then you can directly use the position to calculate the distance to the vertex. Here's how I have done it in the past:

//--------------------------------------------------------------------------------
// view_space_depth.fx
//
// This effect is used to transform the input geometry to clip space and output
// the vertices to the rasterizer. The additional vertex attribute that is sent
// out with the position is the view space depth (or z value). To find this value
// the geometry is transformed with the world/view matrices.
//
// Copyright (C) 2007 Jason Zink
//--------------------------------------------------------------------------------
float4x4 WV : WorldViewMatrix;
float4x4 WVP : WorldViewProjMatrix;
//-----------------------------------------------------------------------------
struct vertex
{
float3 position : POSITION;
};
//-----------------------------------------------------------------------------
struct fragment
{
float4 position : POSITION;
float viewdepth : TEXCOORD0;
};
//-----------------------------------------------------------------------------
struct pixel
{
float4 color : COLOR;
};
//-----------------------------------------------------------------------------

//-----------------------------------------------------------------------------
// Vertex Shader
//-----------------------------------------------------------------------------
fragment VS( vertex IN )
{
fragment OUT;

OUT.position = mul( float4(IN.position, 1), WVP );

float3 viewpos = mul( float4( IN.position, 1 ), WV ).xyz;

OUT.viewdepth = length( viewpos );

// Alternatively use the view space z value...
//OUT.viewdepth = viewpos.z;

return OUT;
}
//-----------------------------------------------------------------------------
pixel PS( fragment IN )
{
pixel OUT;

float normDepth = IN.viewdepth / 200.0f; //(1000.0f - 0.1f);

OUT.color = float4( normDepth, normDepth, normDepth, normDepth );

return OUT;
}
//-----------------------------------------------------------------------------
technique depth_pass
{
pass P0
{
VertexShader = compile vs_2_0 VS();
PixelShader = compile ps_2_0 PS();
}
}
//-----------------------------------------------------------------------------


As shown in there, you can also use the view space z position as a rough approximation to reduce the instruction count (not critical in the vertex shader though...). Also remember to divide the view depth in the pixel shader by the maximum distance in the scene - if using the length method above then it's the distance from the camera to the far corners of the view frustum, and if using the z value it would be the distance to the center of the far clip plane.

Try this out - you should get a much better distribution of depth values than using the projected coordinates.

Share this post


Link to post
Share on other sites
zhugel_007    126
Thanks for all your replies. Jason is right, i need the linear distance.

i've done the shader in a different way and it seems works correctly.

float4x4 matViewProjection;
float near;
float far;

struct VS_INPUT
{
float4 Position : POSITION0;
};

struct VS_OUTPUT
{
float4 Position : POSITION0;
float Depth : TEXCOORD0;
};

VS_OUTPUT vs_main( VS_INPUT Input )
{
VS_OUTPUT Output;

Output.Position = mul( Input.Position, matViewProjection );

// render the depth value into a texture.
// the w value is the real z after the projection.
// here is to adjust the z value into range [0,1]
Output.Depth = (Output.Position.w-near)/(far-near);

return( Output );

}

float4 ps_main(float Depth: TEXCOORD0) : COLOR0
{
return Depth;
}


Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this