How to export result as SRGB encoded?

Update: The answer below is outdated; Texture Tools Exporter 2024.1.1 now allows you to force _SRGB or non-_SRGB formats! You can find the setting for this at the bottom of the settings pane, under “Export Transfer Function”. For more information, please see How to export a file with the format R8G8B8A8_UNORM_SRGB - #6 by nbickford!


Hi @jesse.r.meyer ! Thank you for the question.

I wanted to check on one thing quickly – when you mention a 32-bit-per-channel floating-point sRGB format in DDS, are you thinking of R32G32B32A32_FLOAT with the nonstandard DDPF_SRGB (0x40000000) flag set in the DDS pixel format’s dwFlags? I don’t think there’s a floating-point or 32-bpc DXGI format with the _UNORM flag – the Exporter’s “32x4f” format is written as R32G32B32A32_FLOAT.

To quickly answer the larger question, there isn’t a way to have the Exporter emit a _UNORM_SRGB instead of _UNORM texture as of 2023.3.1, but I’m hoping to add an option in the future!

There’s one quick workaround: we added “sRGB to Linear” and “Linear to sRGB” effects this year; adding one of those will get your data into the right color space, if that works! (Since it’s floating-point, there should be no loss in precision - these effects don’t clamp values below 0 or above 1 by default.)

At the moment, we’re mainly relying on the reader application knowing best whether it wants to interpret the DDS file’s values as-is (_UNORM) or with automatic sRGB-to-linear conversion (_UNORM_SRGB) – i.e. we’re relying on one of these happening:

  • The renderer changes _UNORM formats to _UNORM_SRGB if it wants sRGB-to-linear conversion to happen, or
  • An intermediate process modifies the DDS header (i.e. checks that bytes +0x54 - +0x57 are "DX10" and that byte +0x80 is between 70 and 77, 90 and 92, or 97 and 98, or equal to 28; if so, it adds 1 to the byte.)

The reasoning behind this is that DDS color space support is a bit of a mess. Most readers ignore color information or interpret _UNORM as “contains values that should be output directly to screen” and _UNORM_SRGB as “contains values that should be converted from sRGB to linear RGB and then output to the screen”. This means that writing sRGB data into an _SRGB format sometimes looks wrong. Some readers accept _UNORM formats, but refuse to read _UNORM_SRGB formats. On the writer side, things are also inconsistent.

(The KTX file format’s much more consistent about this because it has a “transfer function” field; any future sRGB or linear options will also apply to KTX.)

In the past, the Exporter’s usually tried to write data that works out-of-the-box across as many readers as possible, which means writing data to _UNORM instead of _UNORM_SRGB formats (and using the header without the DXT10 extension when possible). But now that NVTT’s been released, the Exporter’s moving to be more configurable (while still doing the most compatible thing by default).

Hope this helps, and let me know if you have any questions I can answer!

1 Like