diff --git a/filament/include/filament/Texture.h b/filament/include/filament/Texture.h index 513b82792f..21b1da74a0 100644 --- a/filament/include/filament/Texture.h +++ b/filament/include/filament/Texture.h @@ -390,7 +390,8 @@ public: * * The reflections cubemap's dimension must be a power-of-two. * - * @warning This operation is computationally intensive, especially with large environments. + * @warning This operation is computationally intensive, especially with large environments and + * is currently synchronous. Expect about 1ms for a 16x16 cubemap. * * @param engine Reference to the filament::Engine to associate this IndirectLight with. * @param buffer Client-side buffer containing the images to set. diff --git a/libs/ibl/include/ibl/Cubemap.h b/libs/ibl/include/ibl/Cubemap.h index 48190fe8e8..ac66c62494 100644 --- a/libs/ibl/include/ibl/Cubemap.h +++ b/libs/ibl/include/ibl/Cubemap.h @@ -84,7 +84,7 @@ public: inline Image& getImageForFace(Face face); //! computes the center of a pixel at coordinate x, y - inline filament::math::float2 center(size_t x, size_t y) const; + static inline filament::math::float2 center(size_t x, size_t y); //! computes a direction vector from a face and a location of the center of pixel in an Image inline filament::math::float3 getDirectionFor(Face face, size_t x, size_t y) const; @@ -153,7 +153,7 @@ inline Image& Cubemap::getImageForFace(Face face) { return mFaces[int(face)]; } -inline filament::math::float2 Cubemap::center(size_t x, size_t y) const { +inline filament::math::float2 Cubemap::center(size_t x, size_t y) { return { x + 0.5f, y + 0.5f }; } diff --git a/libs/ibl/src/Cubemap.cpp b/libs/ibl/src/Cubemap.cpp index affa791137..8b9196f0a1 100644 --- a/libs/ibl/src/Cubemap.cpp +++ b/libs/ibl/src/Cubemap.cpp @@ -52,7 +52,7 @@ Cubemap::Address Cubemap::getAddressFor(const float3& r) { const float ry = std::abs(r.y); const float rz = std::abs(r.z); if (rx >= ry && rx >= rz) { - ma = rx; + ma = 1.0f / rx; if (r.x >= 0) { addr.face = Face::PX; sc = -r.z; @@ -63,7 +63,7 @@ Cubemap::Address Cubemap::getAddressFor(const float3& r) { tc = -r.y; } } else if (ry >= rx && ry >= rz) { - ma = ry; + ma = 1.0f / ry; if (r.y >= 0) { addr.face = Face::PY; sc = r.x; @@ -74,7 +74,7 @@ Cubemap::Address Cubemap::getAddressFor(const float3& r) { tc = -r.z; } } else { - ma = rz; + ma = 1.0f / rz; if (r.z >= 0) { addr.face = Face::PZ; sc = r.x; @@ -86,8 +86,8 @@ Cubemap::Address Cubemap::getAddressFor(const float3& r) { } } // ma is guaranteed to be >= sc and tc - addr.s = (sc / ma + 1) * 0.5f; - addr.t = (tc / ma + 1) * 0.5f; + addr.s = (sc * ma + 1.0f) * 0.5f; + addr.t = (tc * ma + 1.0f) * 0.5f; return addr; } @@ -205,15 +205,13 @@ Cubemap::Texel Cubemap::trilinearFilterAt(const Cubemap& l0, const Cubemap& l1, { Cubemap::Address addr(getAddressFor(L)); const Image& i0 = l0.getImageForFace(addr.face); + const Image& i1 = l1.getImageForFace(addr.face); float x0 = std::min(addr.s * l0.mDimensions, l0.mUpperBound); float y0 = std::min(addr.t * l0.mDimensions, l0.mUpperBound); - float3 c0(filterAt(i0, x0, y0)); - if (&l0 != &l1) { - const Image& i1 = l1.getImageForFace(addr.face); - float x1 = std::min(addr.s * l1.mDimensions, l1.mUpperBound); - float y1 = std::min(addr.t * l1.mDimensions, l1.mUpperBound); - c0 += lerp * (filterAt(i1, x1, y1) - c0); - } + float x1 = std::min(addr.s * l1.mDimensions, l1.mUpperBound); + float y1 = std::min(addr.t * l1.mDimensions, l1.mUpperBound); + float3 c0 = filterAt(i0, x0, y0); + c0 += lerp * (filterAt(i1, x1, y1) - c0); return c0; } diff --git a/libs/ibl/src/CubemapIBL.cpp b/libs/ibl/src/CubemapIBL.cpp index 9fa76c7f3c..3b5cde9408 100644 --- a/libs/ibl/src/CubemapIBL.cpp +++ b/libs/ibl/src/CubemapIBL.cpp @@ -300,13 +300,13 @@ void CubemapIBL::roughnessFilter(JobSystem& js, Cubemap& dst, const std::vector< if (linearRoughness == 0) { CubemapUtils::process(dst, js, [&] (CubemapUtils::EmptyState&, size_t y, Cubemap::Face f, Cubemap::Texel* data, size_t dim) { - if (updater) { + if (UTILS_UNLIKELY(updater)) { size_t p = progress.fetch_add(1, std::memory_order_relaxed) + 1; updater(0, (float)p / (dim * 6)); } const Cubemap& cm = levels[0]; for (size_t x = 0; x < dim; ++x, ++data) { - const float2 p(dst.center(x, y)); + const float2 p(Cubemap::center(x, y)); const float3 N(dst.getDirectionFor(f, p.x, p.y) * mirror); // FIXME: we should pick the proper LOD here and do trilinear filtering Cubemap::writeAt(data, cm.sampleAt(N)); @@ -356,9 +356,9 @@ void CubemapIBL::roughnessFilter(JobSystem& js, Cubemap& dst, const std::vector< #else const float NoV = 1; const float NoH = H.z; - const float NoH2 = H.z*H.z; - const float NoL = 2*NoH2 - 1; - const float3 L(2*NoH*H.x, 2*NoH*H.y, NoL); + const float NoH2 = H.z * H.z; + const float NoL = 2 * NoH2 - 1; + const float3 L(2 * NoH * H.x, 2 * NoH * H.y, NoL); #endif if (NoL > 0) { @@ -382,12 +382,12 @@ void CubemapIBL::roughnessFilter(JobSystem& js, Cubemap& dst, const std::vector< } } - std::for_each(cache.begin(), cache.end(), [weight](CacheEntry& entry){ - entry.brdf_NoL /= weight; - }); + for (auto& entry : cache) { + entry.brdf_NoL *= 1.0f / weight; + } // we can sample the cubemap in any order, sort by the weight, it could improve fp precision - std::sort(cache.begin(), cache.end(), [](CacheEntry const& lhs, CacheEntry const& rhs){ + std::sort(cache.begin(), cache.end(), [](CacheEntry const& lhs, CacheEntry const& rhs) { return lhs.brdf_NoL < rhs.brdf_NoL; }); @@ -395,7 +395,7 @@ void CubemapIBL::roughnessFilter(JobSystem& js, Cubemap& dst, const std::vector< [&](CubemapUtils::EmptyState&, size_t y, Cubemap::Face f, Cubemap::Texel* data, size_t dim) { - if (updater) { + if (UTILS_UNLIKELY(updater)) { size_t p = progress.fetch_add(1, std::memory_order_relaxed) + 1; updater(0, (float)p / (dim * 6)); } @@ -403,7 +403,7 @@ void CubemapIBL::roughnessFilter(JobSystem& js, Cubemap& dst, const std::vector< mat3 R; const size_t numSamples = cache.size(); for (size_t x = 0; x < dim; ++x, ++data) { - const float2 p(dst.center(x, y)); + const float2 p(Cubemap::center(x, y)); const float3 N(dst.getDirectionFor(f, p.x, p.y) * mirror); // center the cone around the normal (handle case of normal close to up) @@ -571,7 +571,7 @@ void CubemapIBL::diffuseIrradiance(JobSystem& js, Cubemap& dst, const std::vecto mat3 R; const size_t numSamples = cache.size(); for (size_t x = 0; x < dim; ++x, ++data) { - const float2 p(dst.center(x, y)); + const float2 p(Cubemap::center(x, y)); const float3 N(dst.getDirectionFor(f, p.x, p.y)); // center the cone around the normal (handle case of normal close to up) @@ -924,7 +924,7 @@ void CubemapIBL::brdf(utils::JobSystem& js, Cubemap& dst, float linearRoughness) [ & ](CubemapUtils::EmptyState&, size_t y, Cubemap::Face f, Cubemap::Texel* data, size_t dim) { for (size_t x=0 ; x