Search code examples
c++directxdirectx-10

DirectX 10 HUD in C++


I'm attempting to make a custom HUD system in DirectX 10. My current method of attack is to simply use a tree of meshes to represent different levels of the menu.

I believe that by disabling the Depth Test I can make a mesh which is pasted up above the rest of my 3d world in the background. To achieve this I've attempted to use a D3D10_DEPTH_STENCIL_DESC whereby I set DepthEnable option to false. I then bind this D3D10_DEPTH_STENCIL_DESC to a stencil state which I then activate just before I draw my mesh. This thus far has left me with a missing mesh.

My question really boils down to : Am I on the right track with this, Or do I need to re-think this altogether? Additionally if this is a good plan of attack on this problem, is there anything that I am forgetting to take into consideration?

Below are the bits of code where I attempt to get this HUD

Creating the D3D10_DEPTH_STENCIL_DESC:

    //HUD Elements
D3D10_DEPTH_STENCIL_DESC dsDesc;
//Depth Settings 
dsDesc.DepthEnable      = false;
dsDesc.DepthWriteMask   = D3D10_DEPTH_WRITE_MASK_ALL;
dsDesc.DepthFunc        = D3D10_COMPARISON_LESS;
//Stencil settings
dsDesc.StencilEnable    = true;
dsDesc.StencilReadMask  = 0xff;
dsDesc.StencilWriteMask = 0xff;
//Always pass the stencil test, and replace the current stencil value with 
// the stencil reference value 1
dsDesc.FrontFace.StencilFailOp      = D3D10_STENCIL_OP_KEEP;
dsDesc.FrontFace.StencilDepthFailOp = D3D10_STENCIL_OP_KEEP;
dsDesc.FrontFace.StencilPassOp      = D3D10_STENCIL_OP_REPLACE;
dsDesc.FrontFace.StencilFunc        = D3D10_COMPARISON_ALWAYS;
// We are not rendering backfacing polygons, so these settings do not matter.
dsDesc.BackFace.StencilFailOp       = D3D10_STENCIL_OP_KEEP;
dsDesc.BackFace.StencilDepthFailOp  = D3D10_STENCIL_OP_KEEP;
dsDesc.BackFace.StencilPassOp       = D3D10_STENCIL_OP_REPLACE;
dsDesc.BackFace.StencilFunc         = D3D10_COMPARISON_ALWAYS;
//Bind HUD to a stencil
HR(md3dDevice->CreateDepthStencilState(&dsDesc,&hud));

To Draw I simply do:

    md3dDevice->OMSetDepthStencilState(hud, 1);
menu.draw(mVP);

Solution

  • Yeah you are barking up the right tree. Something to bear in mind though is that if your menu system is layered then you HAVE to draw back to front as the Z-buffer can't help you. This will mean quite a bit of overdraw.

    Another solution allows you to limit the amount of overdraw by using a Z-Buffer (and especially using the early Z rejects the hardware supports) and drawing front to back. However you then have the problem of it interacting with your scene. This can easily be fixed by simply clearing the Z-Buffer before rendering your menu.

    TBH though you'd be best off using the Z-Buffer clearing method as it means you can batch together draw calls far more efficiently. ie Constantly mapping and filling an ID3D10Buffer will be slower than doing it once and then continually re-drawing it. Sure when the state changes you may need to edit the buffer but you can limit how much of the buffer you edit AND when there is no state change you aren't chewing through the CPU unnecessarily.