Depth render target

Since we do not know before rendering what objects will and will not be visible, we will also not be able to know beforehand which objects will appear in front of others before rendering to the screen. However, if we were to purely render objects on the screen without considering depth, we would overwrite our objects in unexpected ways, having objects appear in front of other objects which are expected to be behind the object.

For this purpose, a depth buffer is often used in rendering. A depth buffer is used to store depth information for every pixel, allowing rendering of a pixel to be skipped when a pixel was rendered at a lower, higher or equal depth to prior renders. This is usually done to only accept pixels which are “closer” to the “camera” than the previous pixel in that location. In this way, all objects further to the back will be overwritten by objects closer, and not vice versa. This will render a far more correct image in a lot of circumstances.

In order to be able to create a depth buffer, we must create a 2D texture. In so doing, we must be sure to set the D3D11_BIND_DEPTH_STENCIL flag, and set the format to any depth-enabled format. In this case, we use DXGI_FORMAT_D32_FLOAT.

The D3D11_BIND_DEPTH_STENCIL flag specifies that the texture can be bound as a “depth stencil” buffer. This instructs the runtime to create the texture in such a way that we can use it to do depth and stencil operations to it by creating a “depth stencil view”.

In the creation of the depth stencil buffer, we use DXGI_FORMAT_D32_FLOAT. This means that the format is optimized for depth buffer operations using a 32-bit depth-optimized floating point format. This specific format does not contain any stencil information, denoted by “S[bits]".

It should be noted that a “stencil buffer” is closely tied to the depth buffer. A stencil buffer is similar to a depth buffer in that it is used to refuse certain pixels to be rendered in certain calls, but rather than being tied to depth, the stencil buffer can be filled with more arbitrary values. For instance, it can be used as a counter for the amount of times the pixel is rendered over or a state to either only allow pixels to be rendered in a certain area or refuse rendering in a certain area.

ID3D11Texture2D* dsTex;
result = renderer->device->lpVtbl->CreateTexture2D (
    renderer->device,
    &(D3D11_TEXTURE2D_DESC){
        .Width          = newWidth,
        .Height         = newHeight,
        .MipLevels      = 1,
        .ArraySize      = 1,
        .Format         = DXGI_FORMAT_D32_FLOAT,
        .Usage          = D3D11_USAGE_DEFAULT,
        .BindFlags      = D3D11_BIND_DEPTH_STENCIL,

        .SampleDesc.Count = 1,
    },
    NULL,
    &dsTex
);
if ( !SUCCEEDED ( result ) )
    RETURN_ERROR(-1, "CreateTexture2D failed (0x%08X)", result );

result = renderer->device->lpVtbl->CreateDepthStencilView (
    renderer->device,
    (ID3D11Resource*)dsTex,
    &(D3D11_DEPTH_STENCIL_VIEW_DESC){
        .Format = DXGI_FORMAT_D32_FLOAT,
        .ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D,
    },
    &renderer->dsv
);
if ( !SUCCEEDED ( result ) )
    RETURN_ERROR(-1, "CreateDepthStencilView failed (0x%08X)", result );
dsTex->lpVtbl->Release ( dsTex );

Note that we are calling the Release function on the depth stencil resource. All resource objects in DirectX 11 are using a reference counter in order to determine whether or not an object should be removed. When a resource is created, the reference count defaults to 1. Since the ID3D11DepthStencilView references the depth stencil resource, the reference counter is incremented by 1, becoming 2. If we are to call Release we decrease the counter by 1, becoming 1. If we are to remove the depth stencil view later, the reference counter will be reduced to 0, and the object will be deleted.

The depth stencil “view” should be seen as an interpretation of the resource rather than the resource itself. The format in the depth stencil view does not always have to match the resource's. While the resource itself cannot be used without the view, the view is mostly a way to use the resource rather than an exact match of the resource.