Hi,
I’m working with 32bit per channel floating point textures whose values are intended to be encoded as sRGB (the values are defined wrt the sRGB primaries but this terminology has always been confused). But Texture Tools insist on exporting the .dds file as some class of UNORM (the actual header field value). I’ve hit this problem with other types of images too.
How do I override Texture Tools into treating the values as sRGB ‘compressed’ and to set the .dds header field accordingly?
I’m aware of the ‘Linear to sRGB’ and ‘gamma correction’ options, but those don’t appear to address the problem.
Thanks!
Jesse
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!
–Neil
1 Like
Thanks Nick!
So the input image is .EXR, but I’ve tried with JPEG as well. So, while it would be nice to ingest sRGB .dds files, that’s not my case… yet. ;)
I think in the mean time I will add ‘_srgb’ to the file name and add custom handling to our engine’s .dds loader. The values themselves already are encoded correctly (and I think the gamma correction option is important here).
The zoo of incompatible dds reader and writers were partially why I had mentioned an ‘override’ so that the user has to make an explicit choice that they must live with the outcome. I think the default as-is is reasonable!