Selaa lähdekoodia

texturec: Added BC4/5 compression.

Branimir Karadžić 10 vuotta sitten
vanhempi
sitoutus
c82d3e86d9
5 muutettua tiedostoa jossa 124 lisäystä ja 67 poistoa
  1. 2 0
      3rdparty/.editorconfig
  2. 38 8
      3rdparty/libsquish/squish.cpp
  3. 15 9
      3rdparty/libsquish/squish.h
  4. 10 8
      src/image.cpp
  5. 59 42
      tools/texturec/texturec.cpp

+ 2 - 0
3rdparty/.editorconfig

@@ -11,3 +11,5 @@ indent_size  = 4
 [remotery/*]
 indent_style = space
 indent_size  = 4
+
+[libsquish/*]

+ 38 - 8
3rdparty/libsquish/squish.cpp

@@ -37,13 +37,18 @@ namespace squish {
 static int FixFlags( int flags )
 {
 	// grab the flag bits
-	int method = flags & ( kDxt1 | kDxt3 | kDxt5 );
+	int method = flags & ( kDxt1 | kDxt3 | kDxt5 | kBc4 | kBc5 );
 	int fit = flags & ( kColourIterativeClusterFit | kColourClusterFit | kColourRangeFit );
 	int extra = flags & kWeightColourByAlpha;
 	
 	// set defaults
-	if( method != kDxt3 && method != kDxt5 )
+	if ( method != kDxt3
+	&&   method != kDxt5
+	&&   method != kBc4
+	&&   method != kBc5 )
+	{
 		method = kDxt1;
+	}
 	if( fit != kColourRangeFit && fit != kColourIterativeClusterFit )
 		fit = kColourClusterFit;
 		
@@ -56,9 +61,34 @@ void CompressMasked( u8 const* rgba, int mask, void* block, int flags, float* me
 	// fix any bad flags
 	flags = FixFlags( flags );
 
+	if ( ( flags & ( kBc4 | kBc5 ) ) != 0 )
+	{
+		u8 alpha[16*4];
+		for( int i = 0; i < 16; ++i )
+		{
+			alpha[i*4 + 3] = rgba[i*4 + 0]; // copy R to A
+		}
+
+		u8* rBlock = reinterpret_cast< u8* >( block );
+		CompressAlphaDxt5( alpha, mask, rBlock );
+
+		if ( ( flags & ( kBc5 ) ) != 0 )
+		{
+			for( int i = 0; i < 16; ++i )
+			{
+				alpha[i*4 + 3] = rgba[i*4 + 1]; // copy G to A
+			}
+
+			u8* gBlock = reinterpret_cast< u8* >( block ) + 8;
+			CompressAlphaDxt5( alpha, mask, gBlock );
+		}
+
+		return;
+	}
+
 	// get the block locations
 	void* colourBlock = block;
-	void* alphaBock = block;
+	void* alphaBlock = block;
 	if( ( flags & ( kDxt3 | kDxt5 ) ) != 0 )
 		colourBlock = reinterpret_cast< u8* >( block ) + 8;
 
@@ -87,9 +117,9 @@ void CompressMasked( u8 const* rgba, int mask, void* block, int flags, float* me
 	
 	// compress alpha separately if necessary
 	if( ( flags & kDxt3 ) != 0 )
-		CompressAlphaDxt3( rgba, mask, alphaBock );
+		CompressAlphaDxt3( rgba, mask, alphaBlock );
 	else if( ( flags & kDxt5 ) != 0 )
-		CompressAlphaDxt5( rgba, mask, alphaBock );
+		CompressAlphaDxt5( rgba, mask, alphaBlock );
 }
 
 void Decompress( u8* rgba, void const* block, int flags )
@@ -120,7 +150,7 @@ int GetStorageRequirements( int width, int height, int flags )
 	
 	// compute the storage requirements
 	int blockcount = ( ( width + 3 )/4 ) * ( ( height + 3 )/4 );
-	int blocksize = ( ( flags & kDxt1 ) != 0 ) ? 8 : 16;
+	int blocksize = ( ( flags & ( kDxt1 | kBc4 ) ) != 0 ) ? 8 : 16;
 	return blockcount*blocksize;	
 }
 
@@ -131,7 +161,7 @@ void CompressImage( u8 const* rgba, int width, int height, void* blocks, int fla
 
 	// initialise the block output
 	u8* targetBlock = reinterpret_cast< u8* >( blocks );
-	int bytesPerBlock = ( ( flags & kDxt1 ) != 0 ) ? 8 : 16;
+	int bytesPerBlock = ( ( flags & ( kDxt1 | kBc4 ) ) != 0 ) ? 8 : 16;
 
 	// loop over blocks
 	for( int y = 0; y < height; y += 4 )
@@ -185,7 +215,7 @@ void DecompressImage( u8* rgba, int width, int height, void const* blocks, int f
 
 	// initialise the block input
 	u8 const* sourceBlock = reinterpret_cast< u8 const* >( blocks );
-	int bytesPerBlock = ( ( flags & kDxt1 ) != 0 ) ? 8 : 16;
+	int bytesPerBlock = ( ( flags & ( kDxt1 | kBc4 ) ) != 0 ) ? 8 : 16;
 
 	// loop over blocks
 	for( int y = 0; y < height; y += 4 )

+ 15 - 9
3rdparty/libsquish/squish.h

@@ -39,23 +39,29 @@ typedef unsigned char u8;
 enum
 {
 	//! Use DXT1 compression.
-	kDxt1 = ( 1 << 0 ), 
-	
+	kDxt1 = ( 1 << 0 ),
+
 	//! Use DXT3 compression.
-	kDxt3 = ( 1 << 1 ), 
-	
+	kDxt3 = ( 1 << 1 ),
+
 	//! Use DXT5 compression.
-	kDxt5 = ( 1 << 2 ), 
-	
+	kDxt5 = ( 1 << 2 ),
+
+	//! Use BC4 compression.
+	kBc4 = ( 1 << 3 ),
+
+	//! Use BC5 compression.
+	kBc5 = ( 1 << 4 ),
+
 	//! Use a very slow but very high quality colour compressor.
 	kColourIterativeClusterFit = ( 1 << 8 ),	
-	
+
 	//! Use a slow but high quality colour compressor (the default).
 	kColourClusterFit = ( 1 << 3 ),	
-	
+
 	//! Use a fast but low quality colour compressor.
 	kColourRangeFit	= ( 1 << 4 ),
-	
+
 	//! Weight the colour by alpha during cluster fit (disabled by default).
 	kWeightColourByAlpha = ( 1 << 7 )
 };

+ 10 - 8
src/image.cpp

@@ -1609,18 +1609,19 @@ namespace bgfx
 			}
 		}
 
-		_imageContainer.m_data = NULL;
-		_imageContainer.m_size = 0;
-		_imageContainer.m_offset = (uint32_t)bx::seek(_reader);
-		_imageContainer.m_width  = width;
-		_imageContainer.m_height = height;
-		_imageContainer.m_depth  = depth;
+		_imageContainer.m_data     = NULL;
+		_imageContainer.m_size     = 0;
+		_imageContainer.m_offset   = (uint32_t)bx::seek(_reader);
+		_imageContainer.m_width    = width;
+		_imageContainer.m_height   = height;
+		_imageContainer.m_depth    = depth;
 		_imageContainer.m_format   = uint8_t(format);
 		_imageContainer.m_numMips  = uint8_t( (caps[0] & DDSCAPS_MIPMAP) ? mips : 1);
 		_imageContainer.m_hasAlpha = hasAlpha;
 		_imageContainer.m_cubeMap  = cubeMap;
-		_imageContainer.m_ktx = false;
-		_imageContainer.m_srgb = srgb;
+		_imageContainer.m_ktx      = false;
+		_imageContainer.m_ktxLE    = false;
+		_imageContainer.m_srgb     = srgb;
 
 		return TextureFormat::Unknown != format;
 	}
@@ -1896,6 +1897,7 @@ namespace bgfx
 		_imageContainer.m_cubeMap  = numFaces > 1;
 		_imageContainer.m_ktx      = true;
 		_imageContainer.m_ktxLE    = fromLittleEndian;
+		_imageContainer.m_srgb     = false;
 
 		return TextureFormat::Unknown != format;
 	}

+ 59 - 42
tools/texturec/texturec.cpp

@@ -40,6 +40,54 @@ namespace bgfx
 		::free(mem);
 	}
 
+	void imageEncodeFromRgba8(uint8_t* _dst, const uint8_t* _src, uint32_t _width, uint32_t _height, uint8_t _format)
+	{
+		TextureFormat::Enum format = TextureFormat::Enum(_format);
+
+		switch (format)
+		{
+		case TextureFormat::BC1:
+		case TextureFormat::BC2:
+		case TextureFormat::BC3:
+		case TextureFormat::BC4:
+		case TextureFormat::BC5:
+			squish::CompressImage(_src, _width, _height, _dst
+				, format == TextureFormat::BC1 ? squish::kDxt1
+				: format == TextureFormat::BC2 ? squish::kDxt3
+				: format == TextureFormat::BC3 ? squish::kDxt5
+				: format == TextureFormat::BC4 ? squish::kBc4
+				:                                squish::kBc5
+				);
+			break;
+
+		case TextureFormat::BC6H:
+			nvtt::compressBC6H(_src, _width, _height, 4, _dst);
+			break;
+
+		case TextureFormat::BC7:
+			nvtt::compressBC7(_src, _width, _height, 4, _dst);
+			break;
+
+		case TextureFormat::ETC1:
+			etc1_encode_image(_src, _width, _height, 4, _width*4, _dst);
+			break;
+
+		case TextureFormat::ETC2:
+		case TextureFormat::ETC2A:
+		case TextureFormat::ETC2A1:
+		case TextureFormat::PTC12:
+		case TextureFormat::PTC14:
+		case TextureFormat::PTC12A:
+		case TextureFormat::PTC14A:
+		case TextureFormat::PTC22:
+		case TextureFormat::PTC24:
+			break;
+
+		default:
+			break;
+		}
+	}
+
 } // namespace bgfx
 
 void help(const char* _error = NULL)
@@ -110,6 +158,14 @@ int main(int _argc, const char* _argv[])
 		{
 			format = TextureFormat::BC3;
 		}
+		else if (0 == bx::stricmp(type, "bc4") )
+		{
+			format = TextureFormat::BC4;
+		}
+		else if (0 == bx::stricmp(type, "bc5") )
+		{
+			format = TextureFormat::BC5;
+		}
 		else if (0 == bx::stricmp(type, "etc1") )
 		{
 			format = TextureFormat::ETC1;
@@ -134,6 +190,7 @@ int main(int _argc, const char* _argv[])
 	bool loaded = imageParse(imageContainer, mem->data, mem->size);
 	if (!loaded)
 	{
+
 	}
 
 	BX_UNUSED(mips);
@@ -151,48 +208,8 @@ int main(int _argc, const char* _argv[])
 
 			output = (uint8_t*)BX_ALLOC(&allocator, imageGetSize(format, mip.m_width, mip.m_height) );
 
-			switch (format)
-			{
-			case TextureFormat::BC1:
-			case TextureFormat::BC2:
-			case TextureFormat::BC3:
-				squish::CompressImage(rgba, mip.m_width, mip.m_height, output
-					, format == TextureFormat::BC1 ? squish::kDxt1
-					: format == TextureFormat::BC2 ? squish::kDxt3
-					:                                squish::kDxt5
-					);
-				break;
-
-			case TextureFormat::BC4:
-			case TextureFormat::BC5:
-				break;
-
-			case TextureFormat::BC6H:
-				nvtt::compressBC6H(rgba, mip.m_width, mip.m_height, 4, output);
-				break;
-
-			case TextureFormat::BC7:
-				nvtt::compressBC7(rgba, mip.m_width, mip.m_height, 4, output);
-				break;
-
-			case TextureFormat::ETC1:
-				etc1_encode_image(rgba, mip.m_width, mip.m_height, 4, mip.m_width*4, output);
-				break;
-
-			case TextureFormat::ETC2:
-			case TextureFormat::ETC2A:
-			case TextureFormat::ETC2A1:
-			case TextureFormat::PTC12:
-			case TextureFormat::PTC14:
-			case TextureFormat::PTC12A:
-			case TextureFormat::PTC14A:
-			case TextureFormat::PTC22:
-			case TextureFormat::PTC24:
-				break;
-
-			default:
-				break;
-			}
+			imageContainer.m_format = format;
+			imageEncodeFromRgba8(output, rgba, mip.m_width, mip.m_height, format);
 
 			BX_FREE(&allocator, rgba);
 		}