Skip to content

Commit 673f30a

Browse files
authored
Merge pull request #23 from Capostrophic/bc4bc5
Support BC4- and BC5-compressed DDS images
2 parents 2ad03d6 + 6664a6c commit 673f30a

File tree

4 files changed

+182
-21
lines changed

4 files changed

+182
-21
lines changed

src/osg/Image.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1826,13 +1826,14 @@ void Image::flipVertical()
18261826
unsigned int rowStep = getRowStepInBytes();
18271827

18281828
const bool dxtc(dxtc_tool::isDXTC(_pixelFormat));
1829+
const bool rgtc(dxtc_tool::isRGTC(_pixelFormat));
18291830
if (_mipmapData.empty())
18301831
{
18311832
// no mipmaps,
18321833
// so we can safely handle 3d textures
18331834
for(int r=0;r<_r;++r)
18341835
{
1835-
if (dxtc)
1836+
if (dxtc || rgtc)
18361837
{
18371838
if (!dxtc_tool::VerticalFlip(_s,_t,_pixelFormat,data(0,0,r)))
18381839
{
@@ -1852,7 +1853,7 @@ void Image::flipVertical()
18521853
}
18531854
else if (_r==1)
18541855
{
1855-
if (dxtc)
1856+
if (dxtc || rgtc)
18561857
{
18571858
if (!dxtc_tool::VerticalFlip(_s,_t,_pixelFormat,_data))
18581859
{
@@ -1879,7 +1880,7 @@ void Image::flipVertical()
18791880
t >>= 1;
18801881
if (s==0) s=1;
18811882
if (t==0) t=1;
1882-
if (dxtc)
1883+
if (dxtc || rgtc)
18831884
{
18841885
if (!dxtc_tool::VerticalFlip(s,t,_pixelFormat,_data+_mipmapData[i]))
18851886
{

src/osg/dxtctool.cpp

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ namespace dxtc_tool {
1414
const size_t dxtc_pixels::BSIZE_DXT1 = 8;
1515
const size_t dxtc_pixels::BSIZE_DXT3 = 16;
1616
const size_t dxtc_pixels::BSIZE_DXT5 = 16;
17+
const size_t dxtc_pixels::BSIZE_RGTC1 = 8;
18+
const size_t dxtc_pixels::BSIZE_RGTC2 = 16;
1719
const size_t dxtc_pixels::BSIZE_ALPHA_DXT3 = 8;
1820
const size_t dxtc_pixels::BSIZE_ALPHA_DXT5 = 8;
1921

@@ -68,6 +70,10 @@ bool dxtc_pixels::VFlip() const
6870
VFlip_DXT3();
6971
else if (DXT5())
7072
VFlip_DXT5();
73+
else if (RGTC1())
74+
VFlip_RGTC1();
75+
else if (RGTC2())
76+
VFlip_RGTC2();
7177
else
7278
return false; // We should never get there
7379

@@ -155,6 +161,48 @@ void dxtc_pixels::VFlip_DXT5() const
155161
}
156162
}
157163

164+
void dxtc_pixels::VFlip_RGTC1() const
165+
{
166+
if (m_Height == 2)
167+
for (size_t j = 0; j < (m_Width + 3) / 4; ++j) {
168+
BVF_Alpha_DXT5_H2(((dxtc_int8 * ) m_pPixels) + (j * BSIZE_RGTC1));
169+
}
170+
171+
if (m_Height == 4)
172+
for (size_t j = 0; j < (m_Width + 3) / 4; ++j) {
173+
BVF_Alpha_DXT5_H4(((dxtc_int8 * ) m_pPixels) + (j * BSIZE_RGTC1));
174+
}
175+
176+
if (m_Height > 4)
177+
for (size_t i = 0; i < ((m_Height + 7) / 8); ++i)
178+
for (size_t j = 0; j < (m_Width + 3) / 4; ++j) {
179+
const size_t TargetRow = ((m_Height + 3) / 4) - (i + 1);
180+
BVF_Alpha_DXT5(GetBlock(i, j, BSIZE_RGTC1), GetBlock(TargetRow, j, BSIZE_RGTC1));
181+
}
182+
}
183+
184+
void dxtc_pixels::VFlip_RGTC2() const
185+
{
186+
if (m_Height == 2)
187+
for (size_t j = 0; j < (m_Width + 3) / 4; ++j) {
188+
BVF_Alpha_DXT5_H2(((dxtc_int8 * ) m_pPixels) + (j * BSIZE_RGTC2));
189+
BVF_Alpha_DXT5_H2(((dxtc_int8 * ) m_pPixels) + (j * BSIZE_RGTC2) + BSIZE_RGTC2 / 2);
190+
}
191+
192+
if (m_Height == 4)
193+
for (size_t j = 0; j < (m_Width + 3) / 4; ++j) {
194+
BVF_Alpha_DXT5_H4(((dxtc_int8 * ) m_pPixels) + (j * BSIZE_RGTC2));
195+
BVF_Alpha_DXT5_H4(((dxtc_int8 * ) m_pPixels) + (j * BSIZE_RGTC2) + BSIZE_RGTC2 / 2);
196+
}
197+
198+
if (m_Height > 4)
199+
for (size_t i = 0; i < ((m_Height + 7) / 8); ++i)
200+
for (size_t j = 0; j < (m_Width + 3) / 4; ++j) {
201+
const size_t TargetRow = ((m_Height + 3) / 4) - (i + 1);
202+
BVF_Color_RGTC2(GetBlock(i, j, BSIZE_RGTC2), GetBlock(TargetRow, j, BSIZE_RGTC2));
203+
}
204+
}
205+
158206
//
159207
// Structure of a DXT-1 compressed texture block
160208
// see page "Opaque and 1-Bit Alpha Textures (Direct3D 9)" on http://msdn.microsoft.com
@@ -184,6 +232,18 @@ struct DXT5TexelsBlock
184232
unsigned int texels4x4; // interpolated colors (2 bits per texel)
185233
};
186234

235+
struct RGTC1TexelsBlock
236+
{
237+
unsigned char color_0; // colors at their
238+
unsigned char color_1; // extreme
239+
unsigned char color3[6]; // color index values (3 bits per texel)
240+
};
241+
242+
struct RGTC2TexelsBlock
243+
{
244+
RGTC1TexelsBlock channels[2];
245+
};
246+
187247
bool isCompressedImageTranslucent(size_t width, size_t height, GLenum format, void * imageData)
188248
{
189249
// OSG_NOTICE<<"isCompressedImageTranslucent("<<width<<", "<<height<<", "<<format<<", "<<imageData<<")"<<std::endl;
@@ -475,6 +535,7 @@ bool CompressedImageGetColor(unsigned char color[4], unsigned int s, unsigned in
475535
}
476536
break;
477537
}
538+
// TODO: add RGTC support
478539
default:
479540
return false;
480541
}
@@ -579,6 +640,7 @@ void compressedBlockOrientationConversion(const GLenum format, const unsigned ch
579640
}
580641
break;
581642
}
643+
// TODO: add RGTC support
582644
default:
583645
return;
584646
}//switch

src/osg/dxtctool.h

Lines changed: 72 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
// Current version: 1.00 BETA 1 (27/08/2002)
3232
//
3333
// Comment: Only works with DXTC mode supported by OpenGL.
34-
// (currently: DXT1/DXT3/DXT5)
34+
// (currently: DXT1/DXT3/DXT5/RGTC1/RGTC2)
3535
//
3636
// History: -
3737
//
@@ -77,6 +77,8 @@ namespace dxtc_tool {
7777
// C-like function wrappers
7878
bool isDXTC(GLenum pixelFormat);
7979

80+
bool isRGTC(GLenum pixelFormat);
81+
8082
bool VerticalFlip(size_t Width, size_t Height, GLenum Format, void * pPixels);
8183

8284
bool isCompressedImageTranslucent(size_t Width, size_t Height, GLenum Format, void * pPixels);
@@ -108,13 +110,17 @@ class dxtc_pixels
108110
inline bool DXT1() const;
109111
inline bool DXT3() const;
110112
inline bool DXT5() const;
113+
inline bool RGTC1() const;
114+
inline bool RGTC2() const;
111115
inline bool OpenGLSize() const;
112116
inline bool SupportedFormat() const;
113117

114118
// Vertical flipping functions
115119
void VFlip_DXT1() const;
116120
void VFlip_DXT3() const;
117121
void VFlip_DXT5() const;
122+
void VFlip_RGTC1() const;
123+
void VFlip_RGTC2() const;
118124

119125
// Block vertical flipping functions
120126
inline void BVF_Color_H2(void * const pBlock) const; // V. flip one color block with its virtual height == 2
@@ -126,6 +132,7 @@ class dxtc_pixels
126132
inline void BVF_Alpha_DXT5_H2(void * const pBlock) const; // V. flip one alpha (DXT5) block with its virtual height == 2
127133
inline void BVF_Alpha_DXT5_H4(void * const pBlock) const; // V. flip one alpha (DXT5) block with its virtual height == 4
128134
inline void BVF_Alpha_DXT5(void * const pBlock1, void * const pBlock2) const; // V. flip and swap two alpha (DXT5) blocks, with their virtual height == 4
135+
inline void BVF_Color_RGTC2(void * const pBlock1, void * const pBlock2) const; // V. flip and swap two red-green (RGTC2) blocks, with their virtual height == 4
129136

130137
// Block localization functions
131138
inline void * GetBlock(size_t i, size_t j, size_t BlockSize) const;
@@ -134,6 +141,8 @@ class dxtc_pixels
134141
static const size_t BSIZE_DXT1;
135142
static const size_t BSIZE_DXT3;
136143
static const size_t BSIZE_DXT5;
144+
static const size_t BSIZE_RGTC1;
145+
static const size_t BSIZE_RGTC2;
137146
static const size_t BSIZE_ALPHA_DXT3;
138147
static const size_t BSIZE_ALPHA_DXT5;
139148

@@ -158,16 +167,30 @@ inline bool isDXTC(GLenum pixelFormat)
158167
case(GL_COMPRESSED_RGBA_S3TC_DXT1_EXT):
159168
case(GL_COMPRESSED_RGBA_S3TC_DXT3_EXT):
160169
case(GL_COMPRESSED_RGBA_S3TC_DXT5_EXT):
161-
case(GL_COMPRESSED_SRGB_S3TC_DXT1_EXT):
162-
case(GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT):
163-
case(GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT):
170+
case(GL_COMPRESSED_SRGB_S3TC_DXT1_EXT):
171+
case(GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT):
172+
case(GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT):
164173
case(GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT):
165174
return true;
166175
default:
167176
return false;
168177
}
169178
}
170179

180+
inline bool isRGTC(GLenum pixelFormat)
181+
{
182+
switch(pixelFormat)
183+
{
184+
case(GL_COMPRESSED_RED_RGTC1_EXT):
185+
case(GL_COMPRESSED_SIGNED_RED_RGTC1_EXT):
186+
case(GL_COMPRESSED_RED_GREEN_RGTC2_EXT):
187+
case(GL_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT):
188+
return true;
189+
default:
190+
return false;
191+
}
192+
}
193+
171194
inline bool VerticalFlip(size_t Width, size_t Height, GLenum Format, void * pPixels) {
172195
return (dxtc_pixels(Width, Height, Format, pPixels)).VFlip();
173196
}
@@ -182,24 +205,32 @@ inline dxtc_pixels::dxtc_pixels(size_t Width, size_t Height, GLenum Format, void
182205
m_Width(Width), m_Height(Height), m_Format(Format), m_pPixels(pPixels) { }
183206

184207

185-
inline bool dxtc_pixels::DXT1() const {
186-
return ((m_Format == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT) || (m_Format == GL_COMPRESSED_RGB_S3TC_DXT1_EXT)
187-
|| (m_Format == GL_COMPRESSED_SRGB_S3TC_DXT1_EXT) || (m_Format == GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT));
188-
}
189-
190-
191-
inline bool dxtc_pixels::DXT3() const {
192-
return ((m_Format == GL_COMPRESSED_RGBA_S3TC_DXT3_EXT) || (m_Format == GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT));
193-
}
194-
195-
196-
inline bool dxtc_pixels::DXT5() const {
197-
return ((m_Format == GL_COMPRESSED_RGBA_S3TC_DXT5_EXT) || (m_Format == GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT));
208+
inline bool dxtc_pixels::DXT1() const {
209+
return ((m_Format == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT) || (m_Format == GL_COMPRESSED_RGB_S3TC_DXT1_EXT)
210+
|| (m_Format == GL_COMPRESSED_SRGB_S3TC_DXT1_EXT) || (m_Format == GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT));
211+
}
212+
213+
214+
inline bool dxtc_pixels::DXT3() const {
215+
return ((m_Format == GL_COMPRESSED_RGBA_S3TC_DXT3_EXT) || (m_Format == GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT));
216+
}
217+
218+
219+
inline bool dxtc_pixels::DXT5() const {
220+
return ((m_Format == GL_COMPRESSED_RGBA_S3TC_DXT5_EXT) || (m_Format == GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT));
221+
}
222+
223+
inline bool dxtc_pixels::RGTC1() const {
224+
return ((m_Format == GL_COMPRESSED_RED_RGTC1_EXT) || (m_Format == GL_COMPRESSED_SIGNED_RED_RGTC1_EXT));
225+
}
226+
227+
inline bool dxtc_pixels::RGTC2() const {
228+
return ((m_Format == GL_COMPRESSED_RED_GREEN_RGTC2_EXT) || (m_Format == GL_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT));
198229
}
199230

200231

201232
inline bool dxtc_pixels::SupportedFormat() const {
202-
return (DXT1() || DXT3() || DXT5());
233+
return (DXT1() || DXT3() || DXT5() || RGTC1() || RGTC2());
203234
}
204235

205236

@@ -317,6 +348,29 @@ inline void dxtc_pixels::BVF_Alpha_DXT5(void * const pBlock1, void * const pBloc
317348
}
318349

319350

351+
inline void dxtc_pixels::BVF_Color_RGTC2(void * const pBlock1, void * const pBlock2) const {
352+
dxtc_int64 * pB1 = (dxtc_int64 * ) pBlock1;
353+
dxtc_int64 * pB2 = (dxtc_int64 * ) pBlock2;
354+
355+
for (int i = 0; i < 2; i++) {
356+
dxtc_int64 TmpQWord1 = (pB1[i] & HEX_0x000000000000FFFF);
357+
TmpQWord1 |= (pB1[i] & HEX_0x000000000FFF0000) << 36;
358+
TmpQWord1 |= (pB1[i] & HEX_0x000000FFF0000000) << 12;
359+
TmpQWord1 |= (pB1[i] & HEX_0x000FFF0000000000) >> 12;
360+
TmpQWord1 |= (pB1[i] & HEX_0xFFF0000000000000) >> 36;
361+
362+
dxtc_int64 TmpQWord2 = (pB2[i] & HEX_0x000000000000FFFF);
363+
TmpQWord2 |= (pB2[i] & HEX_0x000000000FFF0000) << 36;
364+
TmpQWord2 |= (pB2[i] & HEX_0x000000FFF0000000) << 12;
365+
TmpQWord2 |= (pB2[i] & HEX_0x000FFF0000000000) >> 12;
366+
TmpQWord2 |= (pB2[i] & HEX_0xFFF0000000000000) >> 36;
367+
368+
pB1[i] = TmpQWord2;
369+
pB2[i] = TmpQWord1;
370+
}
371+
}
372+
373+
320374
inline void * dxtc_pixels::GetBlock(size_t i, size_t j, size_t BlockSize) const {
321375
const dxtc_int8 * pPixels = (const dxtc_int8 *) m_pPixels;
322376

src/osgPlugins/dds/ReaderWriterDDS.cpp

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -258,7 +258,11 @@ struct DXT1TexelsBlock
258258
* FOURCC codes for 3dc compressed-texture pixel formats
259259
*/
260260
#define FOURCC_ATI1 (MAKEFOURCC('A','T','I','1'))
261+
#define FOURCC_BC4U (MAKEFOURCC('B','C','4','U'))
262+
#define FOURCC_BC4S (MAKEFOURCC('B','C','4','S'))
261263
#define FOURCC_ATI2 (MAKEFOURCC('A','T','I','2'))
264+
#define FOURCC_BC5U (MAKEFOURCC('B','C','5','U'))
265+
#define FOURCC_BC5S (MAKEFOURCC('B','C','5','S'))
262266

263267
/*
264268
* FOURCC codes for DX10 files
@@ -517,11 +521,31 @@ osg::Image* ReadDDSFile(std::istream& _istream, bool flipDDSRead)
517521
internalFormat = GL_COMPRESSED_RED_RGTC1_EXT;
518522
pixelFormat = GL_COMPRESSED_RED_RGTC1_EXT;
519523
break;
524+
case FOURCC_BC4U:
525+
OSG_INFO << "ReadDDSFile info : format = BC4U" << std::endl;
526+
internalFormat = GL_COMPRESSED_RED_RGTC1_EXT;
527+
pixelFormat = GL_COMPRESSED_RED_RGTC1_EXT;
528+
break;
529+
case FOURCC_BC4S:
530+
OSG_INFO << "ReadDDSFile info : format = BC4S" << std::endl;
531+
internalFormat = GL_COMPRESSED_SIGNED_RED_RGTC1_EXT;
532+
pixelFormat = GL_COMPRESSED_SIGNED_RED_RGTC1_EXT;
533+
break;
520534
case FOURCC_ATI2:
521535
OSG_INFO << "ReadDDSFile info : format = ATI2" << std::endl;
522536
internalFormat = GL_COMPRESSED_RED_GREEN_RGTC2_EXT;
523537
pixelFormat = GL_COMPRESSED_RED_GREEN_RGTC2_EXT;
524538
break;
539+
case FOURCC_BC5U:
540+
OSG_INFO << "ReadDDSFile info : format = BC5U" << std::endl;
541+
internalFormat = GL_COMPRESSED_RED_GREEN_RGTC2_EXT;
542+
pixelFormat = GL_COMPRESSED_RED_GREEN_RGTC2_EXT;
543+
break;
544+
case FOURCC_BC5S:
545+
OSG_INFO << "ReadDDSFile info : format = BC5S" << std::endl;
546+
internalFormat = GL_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT;
547+
pixelFormat = GL_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT;
548+
break;
525549
case 0x00000024: // A16B16G16R16
526550
OSG_INFO << "ReadDDSFile info : format = A16B16G16R16" << std::endl;
527551
internalFormat = GL_RGBA;
@@ -770,6 +794,26 @@ osg::Image* ReadDDSFile(std::istream& _istream, bool flipDDSRead)
770794
dataType = GL_SHORT;
771795
break;
772796

797+
case OSG_DXGI_FORMAT_BC4_UNORM:
798+
internalFormat = GL_COMPRESSED_RED_RGTC1_EXT;
799+
pixelFormat = GL_COMPRESSED_RED_RGTC1_EXT;
800+
break;
801+
802+
case OSG_DXGI_FORMAT_BC4_SNORM:
803+
internalFormat = GL_COMPRESSED_SIGNED_RED_RGTC1_EXT;
804+
pixelFormat = GL_COMPRESSED_SIGNED_RED_RGTC1_EXT;
805+
break;
806+
807+
case OSG_DXGI_FORMAT_BC5_UNORM:
808+
internalFormat = GL_COMPRESSED_RED_GREEN_RGTC2_EXT;
809+
pixelFormat = GL_COMPRESSED_RED_GREEN_RGTC2_EXT;
810+
break;
811+
812+
case OSG_DXGI_FORMAT_BC5_SNORM:
813+
internalFormat = GL_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT;
814+
pixelFormat = GL_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT;
815+
break;
816+
773817
default:
774818
OSG_WARN << "ReadDDSFile warning: unhandled DX10 pixel format 0x"
775819
<< std::hex << std::setw(8) << std::setfill('0')

0 commit comments

Comments
 (0)