1
\$\begingroup\$

I'm trying to render depth texture in XNA 4.0. I'm read few different tutorials several times and realy cannot understand what I'm doing wrong.

Depth shader:

float4x4 WVPMatrix;

struct VertexShaderOutput
{
    float4 Position : position0;
    float Depth : texcoord0;
};

VertexShaderOutput VertexShader1(float4 pPosition : position0)
{
    VertexShaderOutput output;
    output.Position = mul(pPosition, WVPMatrix);
    output.Depth.x = 1 - (output.Position.z / output.Position.w);
    return output;
}    

float4 PixelShader1(VertexShaderOutput pOutput) : color0
{
    return float4(pOutput.Depth.x, 0, 0, 1);
}    

technique Technique1
{
    pass Pass1
    {
        AlphaBlendEnable = false;
        ZEnable = true;
        ZWriteEnable = true;

        VertexShader = compile vs_2_0 VertexShader1();
        PixelShader = compile ps_2_0 PixelShader1();
    }
}

Drawing:

this.depthRenderTarget = new RenderTarget2D(
    this.graphicsDevice,
    this.graphicsDevice.PresentationParameters.BackBufferWidth,
    this.graphicsDevice.PresentationParameters.BackBufferHeight);

...

public void Draw(GameTime pGameTime, Camera pCamera, Effect pDepthEffect, Effect pOpaqueEffect, Effect pNotOpaqueEffect)
{
    this.graphicsDevice.SetRenderTarget(this.depthRenderTarget);
    this.graphicsDevice.Clear(Color.CornflowerBlue);
    this.DrawChunksDepth(pGameTime, pCamera, pDepthEffect);

    this.graphicsDevice.SetRenderTarget(null);
    this.spriteBatch.Begin(SpriteSortMode.Immediate, BlendState.Opaque, SamplerState.PointClamp, null, null);
    this.spriteBatch.Draw(this.depthRenderTarget, Vector2.Zero, Color.White);
    this.spriteBatch.End();
}

private void DrawChunksDepth(GameTime pGameTime, Camera pCamera, Effect pDepthEffect)
{
    // ...

    this.graphicsDevice.RasterizerState = RasterizerState.CullClockwise;
    this.graphicsDevice.DepthStencilState = DepthStencilState.Default;

    // draw mesh with pDepthEffect
}

Result: enter image description here

As I see output.Position.z always equals output.Position.w, but why?

\$\endgroup\$
1
\$\begingroup\$

If you work out your matrix math, you'll see that the resulting w component of a vector/matrix multiplication depends on what's in the 4th column of the matrix. If the last column is [0 0 0 1] (which it typically is for most translation/orientation matrices), then the w component will be whatever the w component of the vector was. However for a typical perspective projection matrix, the last column will be [0 0 1 0]. This means it will be equal to the z component of the vector, which in this case means that w will be the view-space z value of the vertex position.

This means that if you are using a typical projection matrix, position.z = position.w. Instead maybe you could try passing the maximum Draw Distance of the current camera to the shader and divide position.z by that. That way you'll get a smooth transition from closer to further depth.

\$\endgroup\$
1
  • \$\begingroup\$ Yeah, I thought so that just need to pass the distance. But could not figure why this process is described in all the examples, and why it does not work in this case? Anyway, thanks for the explanation. Matrix is not my forte. \$\endgroup\$
    – user62425
    Jul 25 '15 at 8:29

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy