[osg-users] DDS with DXT1 with and without alpha
robert.osfield at gmail.com
Thu Apr 14 02:49:59 PDT 2011
I have been investigating issues with handling of .dds image files
that contain DXT1 compressed RGB data, with some of these files being
picked out as being RGBA because they have a black pixel within them.
I've looked at what documentation on DXT1 I can find on the web and
have what looks to be a conflict/ambiguity between Microsfts online
docs on DXT1:
And the GL spec for the S3TC compressed texture extension:
To me it looks like the MS docs refer to what is effectively the
GL_COMPRESSED_RGBA_S3TC_DXT1_EXT pixel format, and
there is no equivilant to the GL_COMPRESSED_RGB_S3TC_DXT1_EXT. On the
GL side the only difference between the RGBA
and RGB versions of DXT1 is that RGBA interprets a alpha of 0 while
RGB interprets black for the same bit setting in the data format.
Problems arise because the dds format doesn't explictly distinguish
between the RGB and RGBA versions of DXT1 so you are left to guess
which is intended. Frustratingly the dds format does have bits in the
header for specifying alpha in the pixel format but the 3rd party
generated dds files I have the alpha bit is only looks to be properly
set when using uncompressed RGB vs RGBA. Our dds writer does actually
set the alpha bit when writing out GL_COMPRESSED_RGBA_S3TC_DXT1_EXT so
our dds reader has all the info it needs to reliably distinguish
between the two, but alas.. it's the 3rd party data that most users
will be dealing with.
Up till now the dds plugin has been addressing the ambuguity by
checking the presense of 0 alpha entries in the DXT1 pixel blocks,
however, this check is invalid if black has been encoded as part of a
GL_COMPRESSED_RGB_S3TC_DXT1_EXT compressed image. All these checks do
is assume that the format is GL_COMPRESSED_RGBA_S3TC_DXT1_EXT and
check for the presense of any 0 alpha entries, and if so set the
format to GL_COMPRESSED_RGBA_S3TC_DXT1_EXT otherwise set it to
GL_COMPRESSED_RGB_S3TC_DXT1_EXT. Given this checks are not robust, I
don't think we should be relying upon them, particularily in the
default implementation in plugin.
>From what I can work out MS's docs describe the
GL_COMPRESSED_RGBA_S3TC_DXT1_EXT format, so if one follows this onto
the dds format perhaps one should just default to
GL_COMPRESSED_RGBA_S3TC_DXT1_EXT. However, in general documentation
on DXT that I've seen on the web suggests using DXT1 for RGB data and
DXT3 or DXT5 for RGBA data, and only in special cases where 0 or 1
alpha is acceptable might you consided DXT1a (RGBA version of DXT1).
Given this perhaps we should be assuming
Another complication has that some applications and other other OSG
plugins use the pixel format information to tell whether a texture and
stateset associated with them should be classified as transparent so
should have blending and dropped into the transparent bin for depth
sorting. There is an osg::Image::isImageTranslucent() method that
helps this process, but it previously didn't handle the DXT formats at
all. Yesterday I added support for DXT1 into the isImageTranslucent()
method, and simplified the dds DXT1 RGBvsRGBA detection code to use
this, this provides a little more general functionality as well as
make the code in the dds DXT1 RGBvsRGBA detection code in the dds
However, the new DXT1 RGBvsRGBA detection code is no more robust than
original code - it still wrongly tags DXT1 RGB with black pixels as
being RGBA. There isn't any way to make this detection code robust -
the ambiguity is built into the format, so it's not a case of just
needing to fix a bug, but a case of deciding on what policy to take
when dealing with this ambuiguity - hence this email, giving the
community a chance to discuss the options and what the defaults should
be going forward.
The options I can see are:
1) Keep the current assumption of DXT1 RGBA encoding and use the
DXT1 RGBvsRGBA detection code to switch back to RGB when
no 0 alpha pixels are found. This does wrongly identify DXT1
RGB encoded images with black pixels as being RGBA.
2) Always assume DXT1 RGBA encoding for dds files. Let applications
reset to RGB if they know the image to RGB encoded.
3) Always assume DXT1 RGB encoding for dds files. Let applications
reset to RGBA if they know the image to RGBA encoded.
4) Use an osgDB::Option setting to set what on the above behaviour should be.
Now Option 4 is what I'm actually about to implement... but... it
doesn't resolve what the default setting should be, Option 1 would
keep the status quo as it is, which will work OK for some apps, but
fail for others. Options 2 and 3 won't be perfect for all apps
So what are end users experiences with DXT1 RGB and RGBA encoded
images? Do you use DXT1 for only RGB, only for RGBA, or both? What
3rd party tools do you use for generating your DXT1 dds files? What
issues have you found when using DXT1 in your apps? Of the above
options what default would you perfer?
I look forward to your thoughts.
More information about the osg-users