Color conversion exceptions using nvtt export

Hi, I got a dds texture file for game modding, the format is :BC7_UNORM_SRGB. When I tried to convert it to DXT5 with nvtt_export tools, I got some results of color conversion exceptions. Since I don’t have more advanced knowledge, I assume that the problem is in the conversion between UNORM_SRGB and UNORM. I did a test with Microsoft texconv, using texconv to BC3_UNORM_SRGB, and got the same problematic results as NVTT, if I use texconv to BC3_UNORM, I get the same results as expected from the original file. Is there a way to get the same output as texconv by adjusting the settings? Picture 1 is the result of texconv outputting BC3_UNORM_SRGB and NVTT outputting BC3, Picture 2 is the result of the original file and tecconv outputting BC3_UNORM.

nvtt export ver :(ver:2021.2.0 ), the dds file is on TusFiles | Free File Storage

Hi lu_zero! I think what might be going on here is that the game might be expecting a DX10 DXGI format that ends in _SRGB, like DXGI_FORMAT_BC7_UNORM_SRGB (which Custom_Samurai_d_HI.dds uses) or DXGI_FORMAT_BC3_UNORM_SRGB, but nvtt_export is writing a file using the DXGI_FORMAT_BC3_UNORM DXGI format.

There’s two parts to this: the first is that nvtt_export doesn’t use the DXT10 DDS extension by default, and the second is specifying the _SRGB DXGI format.

To use the DXT10 DDS extension, set Format to BC3, then scroll to the bottom and check DDS: Use DXT10 Header:

image

What’s going on here is that DirectX 9-era DDS files specify their format using the DDS_PIXELFORMAT struct, which doesn’t have any information about whether the file should be read as linear or sRGB. The optional DXT10 header extension (from the mid-2000s) adds a DXGI format field which allows saying whether a file is BC3_UNORM or BC3_UNORM_SRGB – but some older DDS readers will crash if they see the DXT10 header, so nvtt_export doesn’t write it by default. My best guess is that the game might be loading the DX9 BC3 file as if it had the BC3_UNORM DXGI format, when it should load it with the BC3_UNORM_SRGB format.

The second part is that nvtt_export writes the BC3_UNORM enum without BC3_UNORM_SRGB by default (it might in the future though! I’ve written a bit more about this here). These contain the same data (the colors are sRGB in both files); the difference is that the GPU automatically performs sRGB-to-linear conversion on the fly for the latter.

Changing this is a bit trickier, and requires a hex editor at the moment (I often use HxD or ImHex; the design is that ideally the engine should do this format changing, but it looks like the engine doesn’t do that here). After writing the DDS file using nvtt_export.exe, load the DDS file into your hex editor. You should see something like this:

Click on the byte at offset 0x80 and change it from 4D (hexadecimal for 77, which is DXGI_FORMAT_BC3_UNORM) to 4E (hexadecimal for 78, which is DXGI_FORMAT_BC3_UNORM_SRGB):

image

Then save the file back out. If UNORM_SRGB vs. UNORM was the root cause, the texture should now load correctly!

Hope this helps, and let me know if this works!

–Neil

Thank you for your detailed explanation which gave me some knowledge. I follow the advice first check DDS: Use DXT10 Header,got another abnormal result, see below :

Then I Changed the byte at offset 0x80 from 4D to 4E and save(Coincidentally, I also chose the HxD and ImHex as my primary hex editor), but no change in game,It still shows a black(or dark)texture .

I am sorry that due to my memory error, there are some incorrect descriptions that may have misled you: Actually when I export the texture as _SRGB using DirectXTex , I got the same result as using NVTT with Use DXT10 Header
checked (the black texture).

If I use DirectXTex output texture with _UNORM then I woule get a file that is expected (brown)to be the same as the original . I’ll do some more tests…

I did some more tests, which I have now documented for reference.

First, the format of texture file I uploaded is: BC7_UNORM_SRGB(Identified by DirectXTex), in nvddsinfo shows it has DX10 header, however,it could be recognised and handled correctly(show as brown color ) by the game engine. Although, this file is not the official original game file.

Then I tried to convert it to BC7 with nvtt_export.exe, it seems pointless but for testing purposes only(by the way the conversion time is a little too long… ), the result is still the incorrect colour (without dx10 head checked shows white as picture 1, with dx10 header checked it shows black ). It seems more likely caused by the conversion process, just guess.

I found some other files to test, although not entirely certain, result can be found in some of the test files: the file which Identified as: UNORM_SRGB (by DirectXTex, cause nvddsinfo’s display results are a bit professionalism to me), wahtever BC3 or BC7, the results show abnormal colors. By th way, convert by texconvert.exe with parameter: -f BC7_UNORM_SRGB (or -f BC3_UNORM_SRGB), I got the same result as nvtt_export.exe with dx10 header checked (black color). The difference is that using parameter: -f BC7_UNORM (or BC3_xxx…) I could gout a normal working version of the file.

I hope these information will be of some help for you to help me. If you need more information and test let me know.

Have a great weekend!

Quickly reviving this topic (as it’s the most-viewed place where this was discussed) to mention that we’ve improved this in Texture Tools Exporter version 2024.1.0!

There’s a new “Export Transfer Function” option that allows you to force the Exporter to use an _SRGB format (automatic conversion from sRGB to linear in engine), or a linear (KTX) or untagged (DDS) format, instead of its default choice. This is particularly useful in cases like this, where an engine expects a file with a specific transfer function, and the engine can’t be changed.

Hope this helps!