فهرست منبع

Add scaled mip-chain for sdf textures

william7ba 7 سال پیش
والد
کامیت
a4d5eb104e
4فایلهای تغییر یافته به همراه91 افزوده شده و 10 حذف شده
  1. 2 0
      include/bimg/encode.h
  2. 1 1
      src/image.cpp
  3. 8 6
      src/image_encode.cpp
  4. 80 3
      tools/texturec/texturec.cpp

+ 2 - 0
include/bimg/encode.h

@@ -113,6 +113,7 @@ namespace bimg
 		, const void* _src
 		, float _alphaRef
 		, float _scale = 1.0f
+		, uint32_t _upscale = 1
 		);
 
 	///
@@ -124,6 +125,7 @@ namespace bimg
 		, void* _src
 		, float _coverage
 		, float _alphaRef
+		, uint32_t _upscale = 1
 		);
 
 	///

+ 1 - 1
src/image.cpp

@@ -1060,7 +1060,7 @@ namespace bimg
 		{ NULL,               NULL                 }, // ASTC10x5
 		{ NULL,               NULL                 }, // Unknown
 		{ NULL,               NULL                 }, // R1
-		{ bx::packR8,         bx::unpackR8         }, // A8
+		{ bx::packA8,         bx::unpackA8         }, // A8
 		{ bx::packR8,         bx::unpackR8         }, // R8
 		{ bx::packR8I,        bx::unpackR8I        }, // R8I
 		{ bx::packR8U,        bx::unpackR8U        }, // R8U

+ 8 - 6
src/image_encode.cpp

@@ -490,7 +490,7 @@ namespace bimg
 		return rgba[3];
 	}
 
-	float imageAlphaTestCoverage(TextureFormat::Enum _format, uint32_t _width, uint32_t _height, uint32_t _srcPitch, const void* _src, float _alphaRef, float _scale)
+	float imageAlphaTestCoverage(TextureFormat::Enum _format, uint32_t _width, uint32_t _height, uint32_t _srcPitch, const void* _src, float _alphaRef, float _scale, uint32_t _upscale)
 	{
 		UnpackFn unpack = getUnpack(_format);
 		if (NULL == unpack)
@@ -501,7 +501,8 @@ namespace bimg
 		float coverage = 0.0f;
 		const uint8_t* src = (const uint8_t*)_src;
 		const uint32_t xstep = getBitsPerPixel(_format) / 8;
-		const float numSamples = 8.0f;
+		const uint32_t numSamples = _upscale;
+		const float sampleStep = 1.0f / numSamples;
 
 		for (uint32_t yy = 0, ystep = _srcPitch; yy < _height-1; ++yy, src += ystep)
 		{
@@ -513,9 +514,9 @@ namespace bimg
 				float alpha01 = _scale * getAlpha(unpack, data+ystep);
 				float alpha11 = _scale * getAlpha(unpack, data+ystep+xstep);
 
-				for (float fy = 0.5f/numSamples; fy < 1.0f; fy += 1.0f)
+				for (float fy = 0.0f; fy < 1.0f; fy += sampleStep)
 				{
-					for (float fx = 0.5f/numSamples; fx < 1.0f; fx += 1.0f)
+					for (float fx = 0.0f; fx < 1.0f; fx += sampleStep)
 					{
 						float alpha = 0.0f
 							+ alpha00 * (1.0f - fx) * (1.0f - fy)
@@ -536,7 +537,7 @@ namespace bimg
 		return coverage / float(_width*_height*numSamples*numSamples);
 	}
 
-	void imageScaleAlphaToCoverage(TextureFormat::Enum _format, uint32_t _width, uint32_t _height, uint32_t _srcPitch, void* _src, float _desiredCoverage, float _alphaRef)
+	void imageScaleAlphaToCoverage(TextureFormat::Enum _format, uint32_t _width, uint32_t _height, uint32_t _srcPitch, void* _src, float _desiredCoverage, float _alphaRef, uint32_t _upscale)
 	{
 		PackFn   pack   = getPack(_format);
 		UnpackFn unpack = getUnpack(_format);
@@ -550,7 +551,7 @@ namespace bimg
 		float max   = 4.0f;
 		float scale = 1.0f;
 
-		for (uint32_t ii = 0; ii < 8; ++ii)
+		for (uint32_t ii = 0; ii < 10; ++ii)
 		{
 			float coverage = imageAlphaTestCoverage(
 				  _format
@@ -560,6 +561,7 @@ namespace bimg
 				, _src
 				, _alphaRef
 				, scale
+				, _upscale
 				);
 
 			if (coverage < _desiredCoverage)

+ 80 - 3
tools/texturec/texturec.cpp

@@ -620,10 +620,10 @@ bimg::ImageContainer* convert(bx::AllocatorI* _allocator, const void* _inputData
 						, bimg::TextureFormat::R8
 						);
 					temp = BX_ALLOC(_allocator, size);
-					uint8_t* rgba = (uint8_t*)temp;
+					uint8_t* r8 = (uint8_t*)temp;
 
 					bimg::imageDecodeToR8(_allocator
-						, rgba
+						, r8
 						, mip.m_data
 						, mip.m_width
 						, mip.m_height
@@ -640,8 +640,85 @@ bimg::ImageContainer* convert(bx::AllocatorI* _allocator, const void* _inputData
 						, mip.m_width
 						, mip.m_height
 						, mip.m_width
-						, rgba
+						, r8
+						);
+
+					if (_options.mips) {
+						const float alphaRef = 0.5f;
+						float coverage = bimg::imageAlphaTestCoverage(bimg::TextureFormat::A8
+							, mip.m_width
+							, mip.m_height
+							, mip.m_width
+							, r8
+							, alphaRef
+						);
+
+						size = bimg::imageGetSize(
+							NULL
+							, uint16_t(dstMip.m_width)
+							, uint16_t(dstMip.m_height)
+							, uint16_t(dstMip.m_depth)
+							, false
+							, false
+							, 1
+							, bimg::TextureFormat::RGBA8
 						);
+						void* rgbaTemp = BX_ALLOC(_allocator, size);
+						uint8_t* rgba = (uint8_t*)rgbaTemp;
+
+						bimg::imageDecodeToRgba8(
+							_allocator
+							, rgba
+							, dstMip.m_data
+							, dstMip.m_width
+							, dstMip.m_height
+							, dstMip.m_width * 4
+							, bimg::TextureFormat::A8
+						);
+
+						for (uint8_t lod = 1; lod < numMips && _err->isOk(); ++lod) {
+							bimg::imageRgba8Downsample2x2(rgba
+								, dstMip.m_width
+								, dstMip.m_height
+								, dstMip.m_depth
+								, dstMip.m_width * 4
+								, bx::strideAlign(dstMip.m_width / 2, blockWidth) * 4
+								, rgba
+							);
+
+							// For each mip, upscale to original size,
+							// scale image alpha to get same coverage as mip0
+							uint32_t upsample   = 1 << lod;
+							uint32_t destWidth  = dstMip.m_width / 2;
+							uint32_t destHeight = dstMip.m_height / 2;
+							bimg::imageScaleAlphaToCoverage(bimg::TextureFormat::RGBA8
+								, destWidth
+								, destHeight
+								, destWidth * 4
+								, rgba
+								, coverage
+								, alphaRef
+								, upsample
+							);
+
+							bimg::imageGetRawData(*output, side, lod, output->m_data, output->m_size, dstMip);
+							dstData = const_cast<uint8_t*>(dstMip.m_data);
+
+							bimg::imageEncodeFromRgba8(
+								_allocator
+								, dstData
+								, rgba
+								, dstMip.m_width
+								, dstMip.m_height
+								, dstMip.m_depth
+								, bimg::TextureFormat::A8
+								, _options.quality
+								, _err
+							);
+						}
+
+						BX_FREE(_allocator, rgbaTemp);
+					}
 				}
 				// RGBA8
 				else