• Advertisement
Sign in to follow this  

DX12 [D3D12] Render wireframe on top of solid rendering

This topic is 737 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I would like to render a wireframe on top of the normal solid rendering in DirectX 12.

Right now I am using Microsoft's MiniEngine as a base to experiment with: https://github.com/Microsoft/DirectX-Graphics-Samples/tree/master/MiniEngine


I actually initially needed to draw the wireframe to debug my understanding of the structure of the MiniEngine's vertex and index buffers. So initially, I created a separate vertex and index buffer for the wireframe (I know this is not necessary). I constructed the index buffer to render a line list of all the edges of the model.

This technique gave me the result I was expecting, that can be seen below. In this image, the wireframe is correctly drawn on top of the solid rendering: 



Now I want to make a more optimized version that saves space by using the original vertex/index buffers and just renders the wireframe by changing the fill mode of the rasterizer:

CD3DX12_RASTERIZER_DESC l_cWireframeRasterizer(D3D12_DEFAULT);
l_cWireframeRasterizer.FillMode = D3D12_FILL_MODE_WIREFRAME;

The problem with this can be seen below. It seems to only render the wireframe on edges of objects, due to a depth test issue:



I'm not sure why I am having this problem, because I am using the same depth test function in both the index-buffer/line-list technique, as in the wireframe-fill-mode/triangle-list technique. Both techniques use the depth test function D3D12_COMPARISON_FUNC_GREATER_EQUAL.


Since this seems to be a depth fighting issue, I tried setting depth bias like:

l_cWireframeRasterizer.DepthBias = 10;

 The depth bias doesn't help and doesn't seem to have any impact. I tried values of 1, 10, 100, 1000, -1, -10. I think the correct value should be positive, but I was just trying stuff...?tongue.png


Does anyone know how to fix this issue? How to get the wireframe to render correctly on top of the solid rendering using the wireframe fill mode and the original vertex/index buffers?

Does the depth bias not work when you render with a wireframe fill mode?


To make it easier to see the difference between the two techniques, below are screenshots of the wireframe being rendered without the solid rendering first.

The expected result rendered with the line list and second index buffer:



The incorrect result rendered with the original vertex/index buffers and the fill mode set to wireframe:



Some additional information that might help:

In the MiniEngine the depth buffer is rendered in a separate pass. So the description of all the rendering passes is as follows:

Pass 1: Depth

Pass 2: Shadow

Pass 3: Color

Pass 4: Wireframe


Thanks in advance for any help.



Depth Buffer Rendering Example:



Share this post

Link to post
Share on other sites
The depth bias value is documented here. As it explains, the interpretation depends on the format of the depth buffer.

You mentioned that you're using GREATER_EQUAL for your depth testing...does this mean that you're using a reversed depth range, where your near and far clip planes are swapped?

Share this post

Link to post
Share on other sites
Just to be sure, did you check that you're not accidently clearing the backbuffer between the solid and wireframe rendering?

Share this post

Link to post
Share on other sites

I had the same problem, using DX11 though..


I got wireframes to appear correctly by using Bias=-1000, BiasClamp=0.0001f, SlopeScaledBias=0.01f :)

The values you input are dependant on your ZNear+ZFar I think, so try messing around some more with your Bias settings (including Clamp and Slope) and see if you can reach something that looks right?

Share this post

Link to post
Share on other sites
Thanks for your replies guys.
Thanks MJP, I'll have a look at the Depth Bias documentation more attentively. I just skimmed it before, because it was for DirectX 11, but I don't think there is a DirectX 12 version.
No, I don't think the near and far planes are swapped. Although this is set up by the MiniEngine, so I would have to find where it's done to make sure. But I think the depth function compares the values of the depth buffer. And in the depth buffer far away objects have a lower-value/darker/black, while closer objects have higher-value/lighter/white. Below I presented the depth buffer to the screen as an example. It's in black and red instead of black and white because I didn't change the shaders, but you can see that closer objects are lighter than far away objects:
Well, I can't seem to be able to upload images in a reply, so I added the image to the first post: Depth Buffer Rendering Example.
So D3D12_COMPARISON_FUNC_GREATER_EQUAL will draw something if it has a higher-value/is-closer than than what is previously in the depth buffer. That's my understanding anyway.
Thanks for your reply cozzie. No I don't think I am accidentally clearing the backbuffer (colorbuffer) between the solid rendering pass and the wireframe rendering pass. Just as a test I tried clearing the colorbuffer between the two passes and it gives me the same result as if I didn't do the solid pass at all. Like the image above with the wireframe on the black background.
Thanks for your reply vinterberg. I had high hopes that these values would fix the problem, but unfortunately they did not. I'll look into the documentation more closely and experiment with different values.


Edited by 0xfeedbacc

Share this post

Link to post
Share on other sites
With a "standard" projection, your depth buffer will have a value of 0.0 at the near clipping plane and 1.0 at the far clipping plane. Based on your description and the image that you posted, you're definitely using a "reversed" projection. This is fine, in fact it gives you better precision for floating point depth buffers. The reason I asked, is because it means that you'll want to use a *positive* depth bias instead of the normal negative bias.

If you can't get the depth bias to work, you could always do something custom in the pixel shader. For instance, you could output SV_DepthGreaterEqual from the pixel shader, and add a small bias directly in the shader. Or alternatively, you can do a "manual" depth test using alpha blending or discard. For each pixel you could read in the depth buffer value, compare against the depth of the pixel being shaded, and set alpha to 1 if the depth is close enough within some threshold (or set it to 0 otherwise).

Share this post

Link to post
Share on other sites

Alright I fixed it. When I added a quick and dirty depth bias in the vertex shader I realized the wireframe was being rendered for back-facing triangles only and not front-facing ones. To fix it all I had to do was fix the winding order the rasterizer uses by changing FrontCounterClockwise to true:

CD3DX12_RASTERIZER_DESC l_cWireframeRasterizer(D3D12_DEFAULT);
l_cWireframeRasterizer.FillMode = D3D12_FILL_MODE_WIREFRAME;
l_cWireframeRasterizer.FrontCounterClockwise = TRUE;

FrontCounterClockwise = TRUE is the same value the MiniEngine uses. But it is different than the default value for D3D12_DEFAULT.


Thanks for your help guys.

Share this post

Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
  • Advertisement
  • Popular Tags

  • Advertisement
  • Popular Now

  • Similar Content

    • By AxeGuywithanAxe
      I wanted to see how others are currently handling descriptor heap updates and management.
      I've read a few articles and there tends to be three major strategies :
      1 ) You split up descriptor heaps per shader stage ( i.e one for vertex shader , pixel , hull, etc)
      2) You have one descriptor heap for an entire pipeline
      3) You split up descriptor heaps for update each update frequency (i.e EResourceSet_PerInstance , EResourceSet_PerPass , EResourceSet_PerMaterial, etc)
      The benefits of the first two approaches is that it makes it easier to port current code, and descriptor / resource descriptor management and updating tends to be easier to manage, but it seems to be not as efficient.
      The benefits of the third approach seems to be that it's the most efficient because you only manage and update objects when they change.
    • By VietNN
      Hi all,
      I want to copy  just 1 mipmap level of a texture and I am doing like this:
      void CopyTextureRegion( &CD3DX12_TEXTURE_COPY_LOCATION(pDstData, mipmapIndex), 0, 0, 0, &CD3DX12_TEXTURE_COPY_LOCATION(pSrcData, pLayout), nullptr ); - pDstData : is DEFAULT_HEAP, pSrcData is UPLOAD_HEAP(buffer size was get by GetCopyableFootprints from pDstData with highest miplevel), pLayout is D3D12_PLACED_SUBRESOURCE_FOOTPRINT
      - I think the mipmapIndex will point the exact location data of Dest texture, but does it know where to get data location from Src texture because pLayout just contain info of this mipmap(Offset and Footprint).  (???)
      - pLayout has a member name Offset, and I try to modify it but it(Offset) need 512 Alignment but real offset in Src texture does not.
      So what I need to do to match the location of mip texture in Src Texture ?
      @SoldierOfLight @galop1n
    • By _void_
      I am wondering if there is a way to find out how many resources you could bind to the command list directly without putting them in a descriptor table.
      Specifically, I am referring to these guys:
      - SetGraphicsRoot32BitConstant
      - SetGraphicsRoot32BitConstants
      - SetGraphicsRootConstantBufferView
      - SetGraphicsRootShaderResourceView
      - SetGraphicsRootUnorderedAccessView
      I remember from early presentations on D3D12 that the count of allowed resources is hardware dependent and quite small. But I would like to learn some more concrete figures.
    • By lubbe75
      I am trying to set up my sampler correctly so that textures are filtered the way I want. I want to use linear filtering for both min and mag, and I don't want to use any mipmap at all.
      To make sure that mipmap is turned off I set the MipLevels to 1 for my textures.
      For the sampler filter I have tried all kind of combinations, but somehow the mag filter works fine while the min filter doesn't seem to work at all. As I zoom out there seems to be a nearest point filter.
      Is there a catch in Dx12 that makes my min filter not working?
      Do I need to filter manually in my shader? I don't think so since the mag filter works correctly.
      My pixel shader is just a simple texture lookup:
      textureMap.Sample(g_sampler, input.uv); My sampler setup looks like this (SharpDX):
      sampler = new StaticSamplerDescription() { Filter = Filter.MinMagLinearMipPoint, AddressU = TextureAddressMode.Wrap, AddressV = TextureAddressMode.Wrap, AddressW = TextureAddressMode.Wrap, ComparisonFunc = Comparison.Never, BorderColor = StaticBorderColor.TransparentBlack, ShaderRegister = 0, RegisterSpace = 0, ShaderVisibility = ShaderVisibility.Pixel, };  
    • By lubbe75
      Does anyone have a working example of how to implement MSAA in DX12? I have read short descriptions and I have seen code fragments on how to do it with DirectX Tool Kit.
      I get the idea, but with all the pipeline states, root descriptions etc I somehow get lost on the way.
      Could someone help me with a link pointing to a small implementation in DirectX 12 (or SharpDX with DX12)?
  • Advertisement