3D-Formats-Guidelines icon indicating copy to clipboard operation
3D-Formats-Guidelines copied to clipboard

ETC1S desktop decoding guidelines may be inefficient

Open zeux opened this issue 1 year ago • 3 comments

The guidelines for ETC1S format suggest that the applications should decode to BC7 (if available) with a fallback to BC1 (single-slice) and BC3 (dual-slice).

I'm curious, where does this recommendation come from? Intuitively, this seemed wrong to me because ETC1S is a comparatively weak format, and BC1 is usually able to match or slightly surpass its color encoding quality. Encoding a single-slice image into BC7 results in 8 bits per pixel; encoding into BC1 results in 4 bits per pixel (same as ETC1/2), which is more memory friendly.

I tried to gather a little bit of data to help validate this intuition; this is somewhat cumbersome since basisu no longer supports "-bench" command, but you can do this by encoding the texture into .basis file (basisu -basis file.png), unpacking it back (basisu -unpack file.basis), and using ImageMagick compare -metric psnr on the original .png and every unpacked image. I looked at the various diffuse textures for FlightHelmet asset (https://github.com/KhronosGroup/glTF-Sample-Assets/tree/main/Models/FlightHelmet/) and produced the following results:

Texture ETC2 PSNR ASTC PSNR BC1 PSNR BC7 PSNR
FlightHelmet_Materials_GlassPlasticMat_BaseColor.png 37.869 37.8623 37.695 37.7077
FlightHelmet_Materials_LeatherPartsMat_BaseColor.png 35.0998 35.1131 35.0543 35.0182
FlightHelmet_Materials_LensesMat_BaseColor.png 11.1624 11.1609 11.1557 11.1664
FlightHelmet_Materials_MetalPartsMat_BaseColor.png 36.1754 36.1807 36.0521 36.1625
FlightHelmet_Materials_RubberWoodMat_BaseColor.png 35.5046 35.521 35.3116 35.4136

BC7 here is occasionally a little better and occasionally a little worse vs BC1 (with delta up to ~0.1); this does not seem to be worth doubling the texture memory.

(I'm not really claiming that FlightHelmet base color textures are representative, but I'm not sure if there's more complete data that motivated the recommendation and what that data is)

For dual-slice source images, BC3 and BC7 have the same memory footprint, so in that case I don't have a problem with the current guidelines as I assume the quality delta will be minimal and the size delta is non-existent.

cc @donmccurdy as this came out of a discussion on three.js PR; three.js currently follows the guidelines and as such uses BC7 for decoding on desktop when that is supported. This results in 2x memory consumption for single-slice textures vs what is optimal, which affects memory consumption and the time to upload the compressed assets to GPU. I haven't measured the transcode time and assume it's close, but maybe that's not the case?

zeux avatar Oct 24 '24 17:10 zeux

For completeness also adding ORM and normal map for one material from the same asset (normal map encoded with -normal_map flag); the conclusion here is the same as above.

Texture ETC2 PSNR ASTC PSNR BC1 PSNR BC7 PSNR
FlightHelmet_Materials_MetalPartsMat_OcclusionRoughMetal.png 24.8572 24.8601 24.8328 24.8602
FlightHelmet_Materials_MetalPartsMat_Normal.png 32.8355 32.8311 32.7714 32.8121

zeux avatar Oct 24 '24 17:10 zeux

Please do not confuse dual-slice as RGB + A and dual-slice as Red-Green. BC5 is applicable only to the latter case. The former is handled with either BC7 or BC1/BC3.

The observed transcoding quality difference between BC1 and BC7 is a bit unexpected. I'll take a look.

lexaknyazev avatar Oct 24 '24 18:10 lexaknyazev

@lexaknyazev BC5 was a typo and I meant BC3 (aka DXT5) above. Edited to correct this.

zeux avatar Oct 24 '24 18:10 zeux