diff --git a/android/filament-android/src/main/java/com/google/android/filament/LightManager.java b/android/filament-android/src/main/java/com/google/android/filament/LightManager.java index 4330397653..4409345ce2 100644 --- a/android/filament-android/src/main/java/com/google/android/filament/LightManager.java +++ b/android/filament-android/src/main/java/com/google/android/filament/LightManager.java @@ -188,7 +188,7 @@ public class LightManager { * Control the quality / performance of the shadow map associated to this light */ public static class ShadowOptions { - /** Size of the shadow map in texels. Must be a power-of-two. */ + /** Size of the shadow map in texels. Must be a power-of-two and larger or equal to 8. */ public int mapSize = 1024; /** diff --git a/filament/include/filament/LightManager.h b/filament/include/filament/LightManager.h index b7535154cf..83d1da3c2e 100644 --- a/filament/include/filament/LightManager.h +++ b/filament/include/filament/LightManager.h @@ -189,7 +189,7 @@ public: * Control the quality / performance of the shadow map associated to this light */ struct ShadowOptions { - /** Size of the shadow map in texels. Must be a power-of-two. */ + /** Size of the shadow map in texels. Must be a power-of-two and larger or equal to 8. */ uint32_t mapSize = 1024; /** diff --git a/filament/src/PostProcessManager.cpp b/filament/src/PostProcessManager.cpp index 1580b3c299..8cc2b03771 100644 --- a/filament/src/PostProcessManager.cpp +++ b/filament/src/PostProcessManager.cpp @@ -757,7 +757,8 @@ FrameGraphId PostProcessManager::gaussianBlurPass(FrameGraph& data.temp = builder.sample(data.temp); data.temp = builder.declareRenderPass(data.temp); - data.out = builder.createSubresource(output, "Blurred texture mip",{ .level = dstLevel, .layer = layer }); + data.out = builder.createSubresource(output, "Blurred texture mip", + { .level = dstLevel, .layer = layer }); data.out = builder.declareRenderPass(data.out); }, [=](FrameGraphResources const& resources, @@ -2320,7 +2321,8 @@ FrameGraphId PostProcessManager::resolve(FrameGraph& fg, } FrameGraphId PostProcessManager::vsmMipmapPass(FrameGraph& fg, - FrameGraphId input, uint8_t layer, size_t level, bool finalize) noexcept { + FrameGraphId input, uint8_t layer, size_t level, + math::float4 clearColor, bool finalize) noexcept { struct VsmMipData { FrameGraphId in; @@ -2337,7 +2339,7 @@ FrameGraphId PostProcessManager::vsmMipmapPass(FrameGraph& fg out = builder.write(out, FrameGraphTexture::Usage::COLOR_ATTACHMENT); builder.declareRenderPass(name, { .attachments = { .color = { out }}, - .clearColor = { 1.0f, 1.0f, 1.0f, 1.0f }, + .clearColor = clearColor, .clearFlags = TargetBufferFlags::COLOR }); }, @@ -2355,6 +2357,12 @@ FrameGraphId PostProcessManager::vsmMipmapPass(FrameGraph& fg driver.setMinMaxLevels(in, level, level); auto& material = getPostProcessMaterial("vsmMipmap"); + + // When generating shadow map mip levels, we want to preserve the 1 texel border. + // (note clearing never respects the scissor in filament) + PipelineState pipeline(material.getPipelineState()); + pipeline.scissor = { 1u, 1u, dim - 2u, dim - 2u }; + FMaterialInstance* const mi = material.getMaterialInstance(); mi->setParameter("color", in, { .filterMag = SamplerMagFilter::LINEAR, @@ -2363,12 +2371,12 @@ FrameGraphId PostProcessManager::vsmMipmapPass(FrameGraph& fg mi->setParameter("level", uint32_t(level)); mi->setParameter("layer", uint32_t(layer)); mi->setParameter("uvscale", 1.0f / dim); + mi->commit(driver); + mi->use(driver); - // When generating shadow map mip levels, we want to preserve the 1 texel border. - auto vpWidth = (uint32_t) std::max(0, dim - 2); - out.params.viewport = { 1, 1, vpWidth, vpWidth }; - - commitAndRender(out, material, driver); + driver.beginRenderPass(out.target, out.params); + driver.draw(pipeline, mEngine.getFullScreenRenderPrimitive()); + driver.endRenderPass(); if (finalize) { driver.setMinMaxLevels(in, 0, level); diff --git a/filament/src/PostProcessManager.h b/filament/src/PostProcessManager.h index 8a1b45b2cb..aec322df5c 100644 --- a/filament/src/PostProcessManager.h +++ b/filament/src/PostProcessManager.h @@ -131,7 +131,8 @@ public: // VSM shadow mipmap pass FrameGraphId vsmMipmapPass(FrameGraph& fg, - FrameGraphId input, uint8_t layer, size_t level, bool finalize) noexcept; + FrameGraphId input, uint8_t layer, size_t level, + math::float4 clearColor, bool finalize) noexcept; FrameGraphId gaussianBlurPass(FrameGraph& fg, FrameGraphId input, uint8_t srcLevel, diff --git a/filament/src/ShadowMapManager.cpp b/filament/src/ShadowMapManager.cpp index 7db30254f1..a1b788f9a4 100644 --- a/filament/src/ShadowMapManager.cpp +++ b/filament/src/ShadowMapManager.cpp @@ -120,6 +120,10 @@ void ShadowMapManager::render(FrameGraph& fg, FEngine& engine, FView& view, passes.emplace_back(&map, pass); } + const float vsmMoment2 = std::numeric_limits::max(); + const float vsmMoment1 = std::sqrt(vsmMoment2); + const float4 vsmClearColor{ vsmMoment1, vsmMoment2, 0.0f, 0.0f }; + assert_invariant(passes.size() <= textureRequirements.layers); // ------------------------------------------------------------------------------------------- @@ -202,7 +206,7 @@ void ShadowMapManager::render(FrameGraph& fg, FEngine& engine, FView& view, renderTargetDesc.clearFlags = TargetBufferFlags::COLOR | TargetBufferFlags::DEPTH; // we need to clear the shadow map with the max EVSM moments - renderTargetDesc.clearColor = { 256.0f, 65536.f, 0.0f, 0.0f }; + renderTargetDesc.clearColor = vsmClearColor; renderTargetDesc.samples = options->vsm.msaaSamples; if (blur) { @@ -213,7 +217,7 @@ void ShadowMapManager::render(FrameGraph& fg, FEngine& engine, FView& view, .attachments = { .color = { data.tempBlurSrc }, .depth = depth }, - .clearColor = { 256.0f, 65536.f, 256.0f, 65536.f }, + .clearColor = vsmClearColor, .samples = options->vsm.msaaSamples, .clearFlags = TargetBufferFlags::COLOR | TargetBufferFlags::DEPTH @@ -294,8 +298,9 @@ void ShadowMapManager::render(FrameGraph& fg, FEngine& engine, FView& view, // So generate the mipmaps for each layer if (textureRequirements.levels > 1) { for (size_t level = 0; level < textureRequirements.levels - 1; level++) { - const bool finalize = textureRequirements.levels - 2; - shadows = ppm.vsmMipmapPass(fg, shadows, layer, level, finalize); + const bool finalize = level == textureRequirements.levels - 2; + shadows = ppm.vsmMipmapPass(fg, shadows, layer, level, + vsmClearColor, finalize); } } } diff --git a/filament/src/View.cpp b/filament/src/View.cpp index 924f6fb6fd..00d34d527c 100644 --- a/filament/src/View.cpp +++ b/filament/src/View.cpp @@ -708,7 +708,7 @@ void FView::prepareShadow(backend::Handle texture) const noe texture, { .filterMag = SamplerMagFilter::LINEAR, .filterMin = filterMin, - .anisotropyLog2 = anisotropy, + .anisotropyLog2 = anisotropy, // ignored for PCF .compareMode = SamplerCompareMode::COMPARE_TO_TEXTURE, // ignored for VSM .compareFunc = SamplerCompareFunc::GE // ignored for VSM }}); diff --git a/filament/src/components/LightManager.cpp b/filament/src/components/LightManager.cpp index 8f49d9764e..5972eb2a64 100644 --- a/filament/src/components/LightManager.cpp +++ b/filament/src/components/LightManager.cpp @@ -171,27 +171,8 @@ void FLightManager::create(const FLightManager::Builder& builder, utils::Entity lightType.shadowCaster = builder->mCastShadows; lightType.lightCaster = builder->mCastLight; - ShadowParams& shadowParams = manager[i].shadowParams; - shadowParams.options = builder->mShadowOptions; - - // validate all shadow options - shadowParams.options.mapSize = clamp(shadowParams.options.mapSize, 0u, 2048u); - shadowParams.options.shadowCascades = clamp(shadowParams.options.shadowCascades, 1, CONFIG_MAX_SHADOW_CASCADES); - shadowParams.options.constantBias = clamp(shadowParams.options.constantBias, 0.0f, 2.0f); - shadowParams.options.normalBias = clamp(shadowParams.options.normalBias, 0.0f, 3.0f); - shadowParams.options.shadowFar = std::max(shadowParams.options.shadowFar, 0.0f); - shadowParams.options.shadowNearHint = std::max(shadowParams.options.shadowNearHint, 0.0f); - shadowParams.options.shadowFarHint = std::max(shadowParams.options.shadowFarHint, 0.0f); - shadowParams.options.stable = shadowParams.options.stable; - shadowParams.options.polygonOffsetConstant = shadowParams.options.polygonOffsetConstant; - shadowParams.options.polygonOffsetSlope = shadowParams.options.polygonOffsetSlope; - shadowParams.options.screenSpaceContactShadows = shadowParams.options.screenSpaceContactShadows; - shadowParams.options.stepCount = shadowParams.options.stepCount; - shadowParams.options.maxShadowDistance = shadowParams.options.maxShadowDistance; - shadowParams.options.vsm.msaaSamples = std::max(uint8_t(0), shadowParams.options.vsm.msaaSamples); - shadowParams.options.vsm.blurWidth = std::max(0.0f, shadowParams.options.vsm.blurWidth); - // set default values by calling the setters + setShadowOptions(i, builder->mShadowOptions); setLocalPosition(i, builder->mPosition); setLocalDirection(i, builder->mDirection); setColor(i, builder->mColor); @@ -232,6 +213,20 @@ void FLightManager::terminate() noexcept { } } +void FLightManager::setShadowOptions(Instance i, ShadowOptions const& options) noexcept { + ShadowParams& params = mManager[i].shadowParams; + params.options = options; + params.options.mapSize = clamp(options.mapSize, 8u, 2048u); + params.options.shadowCascades = clamp(options.shadowCascades, 1, CONFIG_MAX_SHADOW_CASCADES); + params.options.constantBias = clamp(options.constantBias, 0.0f, 2.0f); + params.options.normalBias = clamp(options.normalBias, 0.0f, 3.0f); + params.options.shadowFar = std::max(options.shadowFar, 0.0f); + params.options.shadowNearHint = std::max(options.shadowNearHint, 0.0f); + params.options.shadowFarHint = std::max(options.shadowFarHint, 0.0f); + params.options.vsm.msaaSamples = std::max(uint8_t(0), options.vsm.msaaSamples); + params.options.vsm.blurWidth = std::max(0.0f, options.vsm.blurWidth); +} + void FLightManager::setLocalPosition(Instance i, const float3& position) noexcept { assert_invariant(i); auto& manager = mManager; diff --git a/filament/src/components/LightManager.h b/filament/src/components/LightManager.h index 110591fadc..9fb4b1b4f6 100644 --- a/filament/src/components/LightManager.h +++ b/filament/src/components/LightManager.h @@ -221,10 +221,7 @@ public: return getShadowParams(i).options; } - void setShadowOptions(Instance i, ShadowOptions const& options) noexcept { - ShadowParams& params = mManager[i].shadowParams; - params.options = options; - } + void setShadowOptions(Instance i, ShadowOptions const& options) noexcept; private: friend class FScene;