diff --git a/include/bimg/encode.h b/include/bimg/encode.h index 326728d..29ecf1d 100644 --- a/include/bimg/encode.h +++ b/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 ); /// diff --git a/src/image.cpp b/src/image.cpp index 6bf0d52..7c6f789 100644 --- a/src/image.cpp +++ b/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 diff --git a/src/image_encode.cpp b/src/image_encode.cpp index 09586fe..034349e 100644 --- a/src/image_encode.cpp +++ b/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) diff --git a/tools/texturec/texturec.cpp b/tools/texturec/texturec.cpp index 848e136..ab96cd1 100644 --- a/tools/texturec/texturec.cpp +++ b/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(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