I'm trying to read the values in a depth texture of type DXGI_FORMAT_D24_UNORM_S8_UINT.

I know this means "24 bits for depth, 8 bits for stencil" "A 32-bit z-buffer format that supports 24 bits for depth and 8 bits for stencil.", but how do you interpret those 24 bits?

It's clearly not going to be a 32-bit int, and it's not going to be a 32-bit float. If it is an integer value, how "far away" is a value of "1" in the depth texture?


It's an Unsigned NORMalized float, which is a floating-point value between 0.0 and 1.0.

EDIT: To clarify, the Depth component is accessed as a float, and the Stencil component is accessed as an unsigned integer.

  • \$\begingroup\$ _UINT indicates that it's quite clearly not a float. \$\endgroup\$ – Maximus Minimus Jul 2 '12 at 1:49
  • \$\begingroup\$ @mh01 Actually the D24 part is UNORM, and he's right \$\endgroup\$ – bobobobo Jul 2 '12 at 2:15
  • \$\begingroup\$ Check the DX SDK - UNORM - "Unsigned normalized integer; which is interpreted in a resource as an unsigned integer, and is interpreted in a shader as an unsigned normalized floating-point value in the range [0, 1]" - from the shader perspective he's right, from the resource perspective he's totally wrong. \$\endgroup\$ – Maximus Minimus Jul 2 '12 at 2:31
  • \$\begingroup\$ No, look carefully. I believe UNORM refers to a float datatype. \$\endgroup\$ – bobobobo Jul 2 '12 at 2:33
  • 1
    \$\begingroup\$ Sorry but that's a direct quote from the DX SDK page for DXGI_FORMAT - msdn.microsoft.com/en-us/library/windows/desktop/… - look at "Format Modifiers" towards the bottom. The data type is explicitly specified as unsigned integer by the documentation but it is interpreted as float in your shader - read it on the CPU and you'll get 24-bit uints, not 24-bit floats. \$\endgroup\$ – Maximus Minimus Jul 2 '12 at 13:48

Here is some demo code which shows how it works:

// create a temporary texture 
desc.Usage = D3D11_USAGE_STAGING; 
desc.BindFlags = 0; 
desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ; 
desc.MiscFlags = 0; 

ID3D11Texture2D* tmpTexture = nullptr; 
HRESULT hr = getDevice()->CreateTexture2D(&desc, nullptr, &tmpTexture); 

// Copy depth buffer
getImmediateContextD3D()->CopyResource(tmpTexture, depthStencilTexture); 

// access depth buffer
getImmediateContextD3D()->Map(tmpTexture, 0, D3D11_MAP_READ, 0, &mappedRes); 

unsigned int* color = (unsigned int*)mappedRes.pData;

// Extract 24 depth bits
float depth = static_cast<float>(color & 0x00FFFFFF); 
depth /= 16777216f; // divide bei 2^24

// compute a grayscale value [0;255]
unsigned char colorValue = static_cast<unsigned char>(depth * 255.0f);

Generally for your texture (or rather the SRV you'll create) you use a format in the same "type" family, in this case DXGI_FORMAT_R24G8_TYPELESS - then when you sample it in your shader you just use a .r swizzle to get the depth value out (in 0..1 range). You should not, of course, be reading it back to the CPU - how to interpret the data is going to be the least of your problems if you do.


I solved this problem by using DXGI_FORMAT_D32_FLOAT in my depth texture instead. It turned out that the z-buffer is all floats between 0.0f and 1.0f.


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.