8
\$\begingroup\$

I have some code to load DDS image files into OpenGL textures, and I'd like to extend it to support the BC6 and BC7 compressed formats introduced in D3D11. Since DirectX and OpenGL disagree about whether a texture's origin is in the upper-left or lower-left corner, my DDS loader flips each image's pixels along the Y axis before passing the pixels to OpenGL.

Flipping compressed textures presents an additional wrinkle: in addition to flipping each row of 4x4-pixel blocks, you also need to flip the pixels within each block. I found code here to flip BC1/BC2/BC3 blocks, and from the block diagrams on MSDN it was easy to adapt the BC3-flipping code to handle BC4 and BC5. The BC6 and BC7 formats look significantly more intimidating, though. Is there a similar bit-twiddling trick to flip these formats, or would I have to fully decompress and recompress each block?

UPDATE: It turns out the texture flip was only necessary because my texture coordinates were being incorrectly inverted at export time. Removing both flips made the code both simpler and faster (thanks Humus!). Flipping BC6/BC7 blocks may still be an interesting challenge, but it's no longer relevant to my original scenario.

\$\endgroup\$
2
  • 1
    \$\begingroup\$ Note that if you flip the texture coordinates instead of the texture images, you cannot use FBOs with the same meshes / shaders. \$\endgroup\$
    – msell
    Sep 5, 2012 at 4:28
  • \$\begingroup\$ That is true. Leaving DDS textures unflipped also causes them to appear upside down in tools like gDEBugger. Hrm. \$\endgroup\$ Sep 6, 2012 at 6:31

2 Answers 2

6
\$\begingroup\$

I suspect it is indeed possible to flip BC6-7 blocks with much less work than a full decompress and recompress, but it's still no picnic and is much more complex than flipping BC1-5 blocks.

First of all, BC6-7 have a variety of modes that can be selected per block. The modes have completely different binary layouts, so you'd pretty much have to write a different flip routine for each mode (there are ~20 of them altogether, IIRC).

Another difficulty is the partitioned modes, where the pixels in the block are partitioned into 2 or 3 subsets, each with its own RGB line segment. The partition must be chosen from a predefined set; the ones for BC6 can be seen here. The problem is that this partition set is not symmetric under vertical flips. However, I suspect it is symmetric under some combination of vertical flips and interchanging the two subsets. For example, looking at the partition #22 (6th row, 3rd column) at that link, there is no vertically flipped version of it in the table, but if you vertically flip and interchange 0s and 1s, you end up with the partition #9 (3rd row, 2nd column). I haven't verified that every partition can be flipped this way, nor have I checked the ones for BC7 (which also includes partitions with 3 subsets).

Even if that works, you're still not home free. In BC1-5, the order of the two endpoints of the RGB line segment was used to switch modes, but in BC6-7 the order of endpoints is chosen to fix one bit of the per-pixel indices in each partition subset. Therefore if you change the partition around you might also have to swap the order of endpoints.

And last but not least, in BC6-7 the endpoints are often delta-compressed (i.e. one endpoint is stored at full precision and the others are stored as lower-precision deltas from it). Swapping partition subsets and endpoint order will switch which endpoint is the high-precision one, so you'll have to shuffle the low-precision bits around and negate some deltas.

All in all, it doesn't seem like there's any fundamental showstopper (though I haven't actually written the code), but it sure would be a lot of work to flip or rotate these formats. If possible, I'd recommend flipping the images in your art pipeline before they get compressed.

(BTW, the fullest specification of BC6-7 I've found is the ARB_texture_compression_bptc spec; I also wrote a blog post about the BCn formats awhile back.)

\$\endgroup\$
1
  • \$\begingroup\$ Thanks; I am sufficiently terrified. I actually went searching for your blog post, but couldn't remember the link. It's an excellent resource on all things BCn; that alone is well worth an upvote! \$\endgroup\$ Sep 7, 2012 at 21:33
0
\$\begingroup\$

The flipping is only a matter of default on the two formats. You can go against the default.

This is probably better to do on the OpenGL side, because OpenGL is lower level, and thus less likely to lose optimization when doing things like this.

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .