dxgi

Convert DXGI_FORMAT_R32G32B32A32_FLOAT to DXGI_FORMAT_R8G8B8A8_UNORM


The data's on the cpu. I was hoping I could upload in DXGI_FORMAT_R32G32B32A32_FLOAT and CopyTextureRegion would do the conversion for me, but it only copies raw bits around.

So it seems like there are only two options, write a compute shader to do the conversion

RWTexture2D<unorm float4> RgbaTexture: register(u0);
...
RgbaTexture[uint2(..)] = float4(...);

(which I don't want to do) or do the conversion on the cpu. But I'm confused about the unorm format.


Solution

  • OpenGL has some good docs on UNORM.

    So it maps [0, MAX] to [0, 1.0] linearly, using the following simple equation: float = uint / UINT_MAX

    so you can just transform with the following kernel to convert to R8G8B8A8_UNORM

    uint8_t float32_to_unorm8(float in)
    {
        return std::clamp(in, 0.f, 1.f) * std::numeric_limits<uint8_t>::max();
    }
    
    std::array<uint8_t, 4> R32G32B32A32_FLOAT_TO_R8G8B8A8_UNORM(std::array<float, 4> in)
    {
        return { float32_to_unorm8(in[0]), float32_to_unorm8(in[1]), float32_to_unorm8(in[2]), float32_to_unorm8(in[3]) };
    }