Search code examples
c++directxdirectx-11wicsrgb

Load texture as RGB not sRGB in DirectX11 using WIC


I'm loading textures using CreateWICTextureFromMemoryEx from DirectXTK. Everything I load is converted to sRGB. Is there any way to force WIC to create RGB surface instead?

Or maybe there is a way to convert an already loaded texture from sRGB to RGB? Back in D3DX there used to be D3DX11_FILTER_SRGB flag for that (from what I understand) but it's not deprecated.

Any help will be very appreciated, thanks!


Solution

  • The DirectX Tool Kit loader uses DXGI_FORMAT_*_SRGB when loading WIC images for a few reasons:

    • The WIC metadata for a PNG file contains the sRGB chunk (/sRGB/RenderingIntent is true)

    • The WIC metadata for a JPG indicates sRGB (/app1/ifd/exif/{ushort=40961} is 1)

    • The WIC metadata for a TIFF indicates sRGB (/ifd/exif/{ushort=40961} is 1)

    • If you pass 'true' as the forceSRGB parameter to the Ex version of the function

    So the image is in fact likely in sRGB colorspace. Therefore, the DXGI_FORMAT_*_SRGB indicates that reads from that texture should be subject to de-gamma to get them into a linear colorspace. I'm assuming you are not using gamma-correct rendering here?

    Gamma-correct rendering is achieved by using a DXGI_FORMAT_*_SRGB or HDR (10:10:10:2, 16:16:16:16) backbuffer format. You also need to use linear colors for Clear. See DeviceResources, Gamma-correct rendering, The Importance of Being Linear, and Linear-Space Lighting (i.e. Gamma) for details.

    A quick and easy workaround if you control the texture file would be to use texconv in the DirectXTex library to convert the source image to a DDS. You can use various switches like -srgbi or -srgbo to force the SRGB behavior you are after.

    Note that I'm also adding an option to let you ignore the sRGB metadata when using WICTextureLoader for a future release of DirectX Tool Kit. Linear rendering is best, but sometimes it's nice to have the option to avoid the DXGI_FORMAT_*_SRGB format being used.

    UPDATE: The more recent versions of WICTextureLoader in DirectX Tool Kit have the following options flags which help the loader determine the right choice for your scenario:

    • WIC_LOADER_FORCE_SRGB Will always return an *_SRGB format if one exists for the format.

    • WIC_LOADER_IGNORE_SRGB Will have the loader ignore the WIC colorspace metadata above if present.

    • Normally if there's no WIC metadata, the reader will assume it's linear (i.e. not sRGB). If you provide WIC_LOADER_SRGB_DEFAULT it assumes that lacking metadata means it should be *_SRGB instead.