From dd9563d491af9ee2334a4b1a9e11359c68fc8f3f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Branimir=20Karad=C5=BEi=C4=87?= Date: Mon, 25 Jun 2018 18:01:02 -0700 Subject: [PATCH] Fixed radiance encoding images. --- src/image_cubemap_filter.cpp | 64 +++++++++++++++++++++++++++++++++--- src/image_encode.cpp | 28 +++++++++------- tools/texturec/texturec.cpp | 8 +++++ 3 files changed, 84 insertions(+), 16 deletions(-) diff --git a/src/image_cubemap_filter.cpp b/src/image_cubemap_filter.cpp index 5c2a6d7..7370d9b 100644 --- a/src/image_cubemap_filter.cpp +++ b/src/image_cubemap_filter.cpp @@ -620,6 +620,35 @@ namespace bimg } } + void importanceSampleGGX(float* _result, const float* _xi, float _roughness, const float* _dir) + { + const float aa = bx::square(_roughness); + const float phi = bx::kPi2 * _xi[0]; + const float cosTheta = bx::sqrt( (1.0f - _xi[1]) / (1.0f + (bx::square(aa) - 1.0f) * _xi[1]) ); + const float sinTheta = bx::sqrt(1.0f - bx::square(cosTheta) ); + + float hh[3]; + hh[0] = sinTheta * bx::cos(phi); + hh[1] = sinTheta * bx::sin(phi); + hh[2] = cosTheta; + + float up[3] = { 0.0f, 0.0f, 0.0f }; + up[bx::abs(_dir[2]) < 0.999f ? 2 : 0] = 1.0f; + + float right[3]; + bx::vec3Cross(right, up, _dir); + + float tangentX[3]; + bx::vec3Norm(tangentX, right); + + float tangentY[3]; + bx::vec3Cross(tangentY, _dir, tangentX); + + _result[0] = tangentX[0] * hh[0] + tangentY[0] * hh[1] + _dir[0] * hh[2]; + _result[1] = tangentX[1] * hh[0] + tangentY[1] * hh[1] + _dir[1] * hh[2]; + _result[2] = tangentX[2] * hh[0] + tangentY[2] * hh[1] + _dir[2] * hh[2]; + } + void processFilterArea( float* _result , const ImageContainer& _image @@ -654,6 +683,7 @@ namespace bimg const uint32_t pitch = mip.m_width*bpp/8; const float widthMinusOne = float(mip.m_width-1); const float texelSize = 1.0f/float(mip.m_width); + BX_UNUSED(texelSize); const uint32_t minX = uint32_t(_aabb[side].m_min[0] * widthMinusOne); const uint32_t maxX = uint32_t(_aabb[side].m_max[0] * widthMinusOne); @@ -675,16 +705,31 @@ namespace bimg const float solidAngle = texelSolidAngle(uu, vv, texelSize); const float ndotl = bx::clamp(bx::vec3Dot(normal, _dir), 0.0f, 1.0f); -#else +#elif 1 const float* normal = (const float*)&nsaMip.m_data[(yy*nsaMip.m_width+xx)*(nsaMip.m_bpp/8)]; const float solidAngle = normal[3]; const float ndotl = bx::clamp(bx::vec3Dot(normal, _dir), 0.0f, 1.0f); +#else + const float uu = float(xx)*texelSize*2.0f - 1.0f; + const float vv = float(yy)*texelSize*2.0f - 1.0f; + float xi[2] = { uu, vv }; + + float hh[3]; + importanceSampleGGX(hh, xi, _specularPower, _dir); + + const float ddoth2 = 2.0f * bx::vec3Dot(_dir, hh); + + float ll[3]; + ll[0] = ddoth2 * hh[0] - _dir[0]; + ll[1] = ddoth2 * hh[1] - _dir[1]; + ll[2] = ddoth2 * hh[2] - _dir[2]; + + const float ndotl = bx::clamp(bx::vec3Dot(_dir, ll), 0.0f, 1.0f); #endif // 0 if (ndotl >= _specularAngle) { const float weight = solidAngle * bx::pow(ndotl, _specularPower); - float rgba[4]; unpack(rgba, row + xx*bpp/8); @@ -841,9 +886,20 @@ namespace bimg ImageContainer* output = imageAlloc(_allocator, TextureFormat::RGBA32F, uint16_t(input->m_width), uint16_t(input->m_width), 1, 1, true, true); - const uint32_t numMips = input->m_numMips; + for (uint8_t side = 0; side < 6; ++side) + { + ImageMip srcMip; + imageGetRawData(*input, side, 0, input->m_data, input->m_size, srcMip); - for (uint8_t lod = 0; lod < numMips; ++lod) + ImageMip dstMip; + imageGetRawData(*output, side, 0, output->m_data, output->m_size, dstMip); + + uint8_t* dstData = const_cast(dstMip.m_data); + + bx::memCopy(dstData, srcMip.m_data, srcMip.m_size); + } + + for (uint8_t lod = 1, numMips = input->m_numMips; lod < numMips; ++lod) { ImageContainer* nsa = imageCubemapNormalSolidAngle(_allocator, bx::max(_image.m_width>>lod, 1) ); diff --git a/src/image_encode.cpp b/src/image_encode.cpp index 3e29ef1..ec67ac8 100644 --- a/src/image_encode.cpp +++ b/src/image_encode.cpp @@ -228,7 +228,10 @@ namespace bimg break; default: - BX_ERROR_SET(_err, BIMG_ERROR, "Unable to convert between input/output formats!"); + if (!imageConvert(_allocator, _dst, _dstFormat, _src, _srcFormat, _width, _height, 1) ) + { + BX_ERROR_SET(_err, BIMG_ERROR, "Unable to convert between input/output formats!"); + } break; } } @@ -260,17 +263,18 @@ namespace bimg imageGetRawData(*output, side, lod, output->m_data, output->m_size, dstMip); uint8_t* dstData = const_cast(dstMip.m_data); - imageEncode(_allocator - , dstData - , mip.m_data - , mip.m_format - , mip.m_width - , mip.m_height - , mip.m_depth - , _dstFormat - , _quality - , &err - ); + imageEncode( + _allocator + , dstData + , mip.m_data + , mip.m_format + , mip.m_width + , mip.m_height + , mip.m_depth + , _dstFormat + , _quality + , &err + ); } } } diff --git a/tools/texturec/texturec.cpp b/tools/texturec/texturec.cpp index da300f8..fdabf7f 100644 --- a/tools/texturec/texturec.cpp +++ b/tools/texturec/texturec.cpp @@ -307,6 +307,14 @@ bimg::ImageContainer* convert(bx::AllocatorI* _allocator, const void* _inputData { output = bimg::imageCubemapRadianceFilter(_allocator, *input); + if (bimg::TextureFormat::RGBA32F != outputFormat) + { + bimg::ImageContainer* temp = bimg::imageEncode(_allocator, outputFormat, _options.quality, *output); + bimg::imageFree(output); + + output = temp; + } + bimg::imageFree(input); return output; }