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:
..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: