Add scaled mip-chain for sdf textures

This commit is contained in:
william7ba
2018-12-17 16:38:54 -08:00
parent 756a62fc02
commit a4d5eb104e
4 changed files with 91 additions and 10 deletions

View File

@@ -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
);
///

View File

@@ -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

View File

@@ -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)

View File

@@ -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