From c3a55957f264f33f91f6aeb42ad77415955bc1b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Branimir=20Karad=C5=BEi=C4=87?= Date: Thu, 21 Jun 2018 19:10:14 -0700 Subject: [PATCH] CMFT WIP. --- include/bimg/bimg.h | 10 +++ src/image.cpp | 132 ++++++++++++++++++++++++++++++++++- src/image_cubemap_filter.cpp | 132 ++++++++++++++++++++++++++++------- tools/texturec/texturec.cpp | 2 +- 4 files changed, 248 insertions(+), 28 deletions(-) diff --git a/include/bimg/bimg.h b/include/bimg/bimg.h index 7866a11..9893e94 100644 --- a/include/bimg/bimg.h +++ b/include/bimg/bimg.h @@ -334,6 +334,16 @@ namespace bimg , const void* _src ); + /// + void imageRgba32fDownsample2x2( + void* _dst + , uint32_t _width + , uint32_t _height + , uint32_t _depth + , uint32_t _srcPitch + , const void* _src + ); + /// void imageRgba32fDownsample2x2NormalMap( void* _dst diff --git a/src/image.cpp b/src/image.cpp index 1d3db08..192369f 100644 --- a/src/image.cpp +++ b/src/image.cpp @@ -709,6 +709,136 @@ namespace bimg imageRgba32fLinearDownsample2x2Ref(_dst, _width, _height, _depth, _srcPitch, _src); } + void imageRgba32fDownsample2x2Ref(void* _dst, uint32_t _width, uint32_t _height, uint32_t _depth, uint32_t _srcPitch, const void* _src) + { + const uint32_t dstWidth = _width/2; + const uint32_t dstHeight = _height/2; + const uint32_t dstDepth = _depth/2; + + if (0 == dstWidth + || 0 == dstHeight) + { + return; + } + + const uint8_t* src = (const uint8_t*)_src; + uint8_t* dst = (uint8_t*)_dst; + + if (0 == dstDepth) + { + for (uint32_t yy = 0, ystep = _srcPitch*2; yy < dstHeight; ++yy, src += ystep) + { + const float* rgba0 = (const float*)&src[0]; + const float* rgba1 = (const float*)&src[_srcPitch]; + for (uint32_t xx = 0; xx < dstWidth; ++xx, rgba0 += 8, rgba1 += 8, dst += 16) + { + float xyz[4]; + + xyz[0] = bx::toLinear(rgba0[0]); + xyz[1] = bx::toLinear(rgba0[1]); + xyz[2] = bx::toLinear(rgba0[2]); + xyz[3] = rgba0[3]; + + xyz[0] += bx::toLinear(rgba0[4]); + xyz[1] += bx::toLinear(rgba0[5]); + xyz[2] += bx::toLinear(rgba0[6]); + xyz[3] += rgba0[7]; + + xyz[0] += bx::toLinear(rgba1[0]); + xyz[1] += bx::toLinear(rgba1[1]); + xyz[2] += bx::toLinear(rgba1[2]); + xyz[3] += rgba1[3]; + + xyz[0] += bx::toLinear(rgba1[4]); + xyz[1] += bx::toLinear(rgba1[5]); + xyz[2] += bx::toLinear(rgba1[6]); + xyz[3] += rgba1[7]; + + xyz[0] = bx::toGamma(xyz[0]/4.0f); + xyz[1] = bx::toGamma(xyz[1]/4.0f); + xyz[2] = bx::toGamma(xyz[2]/4.0f); + xyz[3] = xyz[3]/4.0f; + + bx::packRgba32F(dst, xyz); + } + } + } + else + { + const uint32_t slicePitch = _srcPitch*_height; + + for (uint32_t zz = 0; zz < dstDepth; ++zz, src += slicePitch) + { + for (uint32_t yy = 0, ystep = _srcPitch*2; yy < dstHeight; ++yy, src += ystep) + { + const float* rgba0 = (const float*)&src[0]; + const float* rgba1 = (const float*)&src[_srcPitch]; + const float* rgba2 = (const float*)&src[slicePitch]; + const float* rgba3 = (const float*)&src[slicePitch+_srcPitch]; + for (uint32_t xx = 0 + ; xx < dstWidth + ; ++xx, rgba0 += 8, rgba1 += 8, rgba2 += 8, rgba3 += 8, dst += 16 + ) + { + float xyz[4]; + + xyz[0] = bx::toLinear(rgba0[0]); + xyz[1] = bx::toLinear(rgba0[1]); + xyz[2] = bx::toLinear(rgba0[2]); + xyz[3] = rgba0[3]; + + xyz[0] += bx::toLinear(rgba0[4]); + xyz[1] += bx::toLinear(rgba0[5]); + xyz[2] += bx::toLinear(rgba0[6]); + xyz[3] += rgba0[7]; + + xyz[0] += bx::toLinear(rgba1[0]); + xyz[1] += bx::toLinear(rgba1[1]); + xyz[2] += bx::toLinear(rgba1[2]); + xyz[3] += rgba1[3]; + + xyz[0] += bx::toLinear(rgba1[4]); + xyz[1] += bx::toLinear(rgba1[5]); + xyz[2] += bx::toLinear(rgba1[6]); + xyz[3] += rgba1[7]; + + xyz[0] += bx::toLinear(rgba2[0]); + xyz[1] += bx::toLinear(rgba2[1]); + xyz[2] += bx::toLinear(rgba2[2]); + xyz[3] += rgba2[3]; + + xyz[0] += bx::toLinear(rgba2[4]); + xyz[1] += bx::toLinear(rgba2[5]); + xyz[2] += bx::toLinear(rgba2[6]); + xyz[3] += rgba2[7]; + + xyz[0] += bx::toLinear(rgba3[0]); + xyz[1] += bx::toLinear(rgba3[1]); + xyz[2] += bx::toLinear(rgba3[2]); + xyz[3] += rgba3[3]; + + xyz[0] += bx::toLinear(rgba3[4]); + xyz[1] += bx::toLinear(rgba3[5]); + xyz[2] += bx::toLinear(rgba3[6]); + xyz[3] += rgba3[7]; + + xyz[0] = bx::toGamma(xyz[0]/8.0f); + xyz[1] = bx::toGamma(xyz[1]/8.0f); + xyz[2] = bx::toGamma(xyz[2]/8.0f); + xyz[3] = xyz[3]/8.0f; + + bx::packRgba32F(dst, xyz); + } + } + } + } + } + + void imageRgba32fDownsample2x2(void* _dst, uint32_t _width, uint32_t _height, uint32_t _depth, uint32_t _srcPitch, const void* _src) + { + imageRgba32fDownsample2x2Ref(_dst, _width, _height, _depth, _srcPitch, _src); + } + void imageRgba32fDownsample2x2NormalMapRef(void* _dst, uint32_t _width, uint32_t _height, uint32_t _srcPitch, uint32_t _dstPitch, const void* _src) { const uint32_t dstWidth = _width/2; @@ -1037,7 +1167,7 @@ namespace bimg if (_dstFormat == _srcFormat) { - bx::memCopy(_dst, _src, _width*_height*_depth*srcBpp/8); + bx::memCopy(_dst, _src, _width*_height*_depth*(srcBpp/8) ); return true; } diff --git a/src/image_cubemap_filter.cpp b/src/image_cubemap_filter.cpp index c366e45..58f5588 100644 --- a/src/image_cubemap_filter.cpp +++ b/src/image_cubemap_filter.cpp @@ -623,6 +623,7 @@ namespace bimg void processFilterArea( float* _result , const ImageContainer& _image + , uint8_t _lod , const Aabb* _aabb , const float* _dir , float _specularPower @@ -633,9 +634,6 @@ namespace bimg float totalWeight = 0.0f; const uint32_t bpp = getBitsPerPixel(_image.m_format); - const uint32_t pitch = _image.m_width*bpp/8; - const float widthMinusOne = float(_image.m_width-1); - const float invWidth = 1.0f/float(_image.m_width); UnpackFn unpack = getUnpack(_image.m_format); @@ -646,14 +644,18 @@ namespace bimg continue; } - const uint32_t minX = uint32_t(_aabb[side].m_min[0] * widthMinusOne); - const uint32_t maxX = uint32_t(_aabb[side].m_max[0] * widthMinusOne); - const uint32_t minY = uint32_t(_aabb[side].m_min[1] * widthMinusOne); - const uint32_t maxY = uint32_t(_aabb[side].m_max[1] * widthMinusOne); - ImageMip mip; - if (imageGetRawData(_image, side, 0, _image.m_data, _image.m_size, mip) ) + if (imageGetRawData(_image, side, _lod, _image.m_data, _image.m_size, mip) ) { + const uint32_t pitch = mip.m_width*bpp/8; + const float widthMinusOne = float(mip.m_width-1); + const float invWidth = 1.0f/float(mip.m_width); + + const uint32_t minX = uint32_t(_aabb[side].m_min[0] * widthMinusOne); + const uint32_t maxX = uint32_t(_aabb[side].m_max[0] * widthMinusOne); + const uint32_t minY = uint32_t(_aabb[side].m_min[1] * widthMinusOne); + const uint32_t maxY = uint32_t(_aabb[side].m_max[1] * widthMinusOne); + for (uint32_t yy = minY; yy <= maxY; ++yy) { const uint8_t* row = mip.m_data + yy*pitch; @@ -713,35 +715,113 @@ namespace bimg } } + ImageContainer* imageGenerateMips(bx::AllocatorI* _allocator, const ImageContainer& _image) + { + if (_image.m_format != TextureFormat::RGBA8 + && _image.m_format != TextureFormat::RGBA32F) + { + return NULL; + } + + ImageContainer* output = imageAlloc(_allocator, _image.m_format, uint16_t(_image.m_width), uint16_t(_image.m_height), uint16_t(_image.m_depth), _image.m_numLayers, _image.m_cubeMap, true); + + const uint32_t numMips = output->m_numMips; + const uint32_t numLayers = output->m_numLayers; + const uint32_t numSides = output->m_cubeMap ? 6 : 1; + + for (uint32_t layer = 0; layer < numLayers; ++layer) + { + for (uint8_t side = 0; side < numSides; ++side) + { + ImageMip mip; + if (imageGetRawData(_image, uint16_t(layer*numSides + side), 0, _image.m_data, _image.m_size, mip) ) + { + for (uint8_t lod = 0; lod < numMips; ++lod) + { + ImageMip srcMip; + imageGetRawData(*output, uint16_t(layer*numSides + side), lod == 0 ? 0 : lod-1, output->m_data, output->m_size, srcMip); + + ImageMip dstMip; + imageGetRawData(*output, uint16_t(layer*numSides + side), lod, output->m_data, output->m_size, dstMip); + + uint8_t* dstData = const_cast(dstMip.m_data); + + if (0 == lod) + { + bx::memCopy(dstData, mip.m_data, mip.m_size); + } + else if (output->m_format == TextureFormat::RGBA8) + { + imageRgba8Downsample2x2( + dstData + , srcMip.m_width + , srcMip.m_height + , srcMip.m_depth + , srcMip.m_width*4 + , dstMip.m_width*4 + , srcMip.m_data + ); + } + else if (output->m_format == TextureFormat::RGBA32F) + { + imageRgba32fDownsample2x2( + dstData + , srcMip.m_width + , srcMip.m_height + , srcMip.m_depth + , srcMip.m_width*16 + , srcMip.m_data + ); + } + } + } + } + } + + return output; + } + ImageContainer* imageCubemapRadianceFilter(bx::AllocatorI* _allocator, const ImageContainer& _image, float _filterSize) { - const uint32_t dstWidth = _image.m_width; - const uint32_t dstPitch = dstWidth*16; - const float invDstWidth = 1.0f / float(dstWidth); + ImageContainer* output = imageConvert(_allocator, TextureFormat::RGBA32F, _image, true); - ImageContainer* output = imageAlloc(_allocator, TextureFormat::RGBA32F, uint16_t(dstWidth), uint16_t(dstWidth), 1, 1, true, true); + if (1 >= output->m_numMips) + { + ImageContainer* temp = imageGenerateMips(_allocator, *output); + imageFree(output); + output = temp; + } + + const uint32_t numMips = output->m_numMips; for (uint8_t side = 0; side < 6; ++side) { - ImageMip mip; - imageGetRawData(*output, side, 0, output->m_data, output->m_size, mip); - - for (uint32_t yy = 0; yy < dstWidth; ++yy) + for (uint8_t lod = 0; lod < numMips; ++lod) { - for (uint32_t xx = 0; xx < dstWidth; ++xx) + ImageMip mip; + imageGetRawData(*output, side, lod, output->m_data, output->m_size, mip); + + const uint32_t dstWidth = mip.m_width; + const uint32_t dstPitch = dstWidth*16; + const float invDstWidth = 1.0f / float(dstWidth); + + for (uint32_t yy = 0; yy < dstWidth; ++yy) { - float* dstData = (float*)&mip. m_data[yy*dstPitch+xx*16]; + for (uint32_t xx = 0; xx < dstWidth; ++xx) + { + float* dstData = (float*)&mip.m_data[yy*dstPitch+xx*16]; - const float uu = float(xx)*invDstWidth*2.0f - 1.0f; - const float vv = float(yy)*invDstWidth*2.0f - 1.0f; + const float uu = float(xx)*invDstWidth*2.0f - 1.0f; + const float vv = float(yy)*invDstWidth*2.0f - 1.0f; - float dir[3]; - texelUvToDir(dir, side, uu, vv); + float dir[3]; + texelUvToDir(dir, side, uu, vv); - Aabb aabb[6]; - calcFilterArea(aabb, dir, _filterSize); + Aabb aabb[6]; + calcFilterArea(aabb, dir, _filterSize); - processFilterArea(dstData, _image, aabb, dir, 10.0f, 0.2f); + processFilterArea(dstData, *output, lod, aabb, dir, 10.0f, 0.2f); + } } } } diff --git a/tools/texturec/texturec.cpp b/tools/texturec/texturec.cpp index a2032d4..59a2030 100644 --- a/tools/texturec/texturec.cpp +++ b/tools/texturec/texturec.cpp @@ -1069,7 +1069,7 @@ int main(int _argc, const char* _argv[]) bimg::imageWriteHdr(&writer , mip.m_width , mip.m_height - , mip.m_width*8 + , mip.m_width*getBitsPerPixel(mip.m_format)/8 , mip.m_data , output->m_format , false