5
\$\begingroup\$

I'm relatively new to DirectX, and am currently converting some WPF 2D graphics code that displays geo-located sonar returns. I am using SharpDX, and rendering via a D3DImage.

I've got the basics working nicely, with very good performance, rendering segments of sonar as a set of quads textured via a texture array of chunks of sonar data.

I am now trying to modify the pixel shader so that it shows the highest "quality" signal return in the case where I have an overlap. Consider that the sonar return spreads from a central point, and (generally) gets worse the further away it is. When we have an overlap, a starting point to showing only the best data is to simply show the pixels that are nearest to the centre of the track, and a simple way I thought to do this would be to modify the depth values in the pixel shader so that the depth varies with the signal distance.

I have added a PS_OUT struct as so:

struct PS_OUT
{
    float4 Colour   : SV_Color;
    float Depth     : SV_Depth;
};

and a simplified version of the PixelShader:

    float quality = 1 - input.domain_uv.x;
    result.Colour = float4(quality, quality, quality, 1);
    result.Depth = quality;
    return result;

where the quality value varies from 0-1, and in this example I am also colouring the output with this quality value:

"depth" output

..which gives the expected colour output, but not the depth output. What I expect (want!) is that the higher quality (lighter coloured) output is preferred over the dark on a per-pixel basis.

I can confirm that depth testing is enabled, as I can vary the z coordinates of my quads and see the results. What seems to be my sticking point is that the depth value I calculate in the pixel shader is simply ignored, and my best guess is that I am missing something obvious - like I need to tell Directx to use it, and not its own calculated values. I can't find any documentation that suggests anything other than modifying the shader semantics is required.

The depth buffer/stencil is set up like this - this is taken from a WPF/SharpDX integration package:

 Set(ref m_depthStencil, DXUtils.CreateTexture2D(this.m_device, w, h,    BindFlags.DepthStencil, Format.D24_UNorm_S8_UInt));
  //Set(ref m_depthStencil, DXUtils.CreateTexture2D(this.m_device, w, h, BindFlags.DepthStencil, Format.D32_Float));
 Set(ref m_depthStencilView, new DepthStencilView(this.m_device, m_depthStencil));

 m_device.ImmediateContext.Rasterizer.SetViewports(new ViewportF[] { new ViewportF(0, 0, w, h, 0.0f, 1.0f) }, 1);
 m_device.ImmediateContext.OutputMerger.SetTargets(m_depthStencilView, m_renderTargetView);

I did try varying the texture format (see commented line), to no avail.

Subsequent to this, I also want to blend the very edges of the joins - but I'll leave that question for another day.

thanks, Matt

edit: I can simulate the final effect that I am after by adjusting the depths of my quad vertices such that the middle is lower than the outer. Depths are then "real" depths, and the correct pixels are drawn. I don't think, however, that this is going to work as a solution for me because I want to be able to implement a slightly more complicated "quality" metric in the pixel shader. SO the question remains: why are my depth values calculated in the PS being ignored?

Here's an image of overlapping tracks where the "closest" pixel is rendered at all times:

Closest pixel rendered

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

There is a chance that your depth value calculation is wrong. The way the GPU's are calculating the depth values is not that simple. For example if we take a point right in the middle between the near and far planes of the camera, the depth value is not 0.5 .

You can refer to this post by Steve Baker to see how you can calculate the depth value: http://www.sjbaker.org/steve/omniv/love_your_z_buffer.html

\$\endgroup\$

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.