diff --git a/filament/src/PerViewUniforms.cpp b/filament/src/PerViewUniforms.cpp index eabf34aef3..a7fad027be 100644 --- a/filament/src/PerViewUniforms.cpp +++ b/filament/src/PerViewUniforms.cpp @@ -91,14 +91,9 @@ void PerViewUniforms::prepareCamera(const CameraInfo& camera) noexcept { s.clipControl = mClipControl; } -void PerViewUniforms::prepareUpscaler(math::float2 scale, - DynamicResolutionOptions const& options) noexcept { +void PerViewUniforms::prepareLodBias(float bias) noexcept { auto& s = mUniforms.edit(); - if (options.quality >= QualityLevel::HIGH) { - s.lodBias = std::log2(std::min(scale.x, scale.y)); - } else { - s.lodBias = 0.0f; - } + s.lodBias = bias; } void PerViewUniforms::prepareExposure(float ev100) noexcept { diff --git a/filament/src/PerViewUniforms.h b/filament/src/PerViewUniforms.h index 11b0d20f71..bf08812fd9 100644 --- a/filament/src/PerViewUniforms.h +++ b/filament/src/PerViewUniforms.h @@ -64,7 +64,7 @@ public: void terminate(backend::DriverApi& driver); void prepareCamera(const CameraInfo& camera) noexcept; - void prepareUpscaler(math::float2 scale, DynamicResolutionOptions const& options) noexcept; + void prepareLodBias(float bias) noexcept; /* * @param viewport viewport (should be same as RenderPassParams::viewport) diff --git a/filament/src/RendererUtils.cpp b/filament/src/RendererUtils.cpp index e13023cb50..b27956baf8 100644 --- a/filament/src/RendererUtils.cpp +++ b/filament/src/RendererUtils.cpp @@ -173,7 +173,7 @@ FrameGraphId RendererUtils::colorPass( view.prepareSSAO(data.ssao ? resources.getTexture(data.ssao) : engine.getOneTextureArray()); - view.prepareShadowMap(view.getVsmShadowOptions().highPrecision); + view.prepareShadowMapping(view.getVsmShadowOptions().highPrecision); // set shadow sampler view.prepareShadow(data.shadows ? @@ -200,6 +200,7 @@ FrameGraphId RendererUtils::colorPass( view.prepareViewport(static_cast(out.params.viewport), config.xoffset, config.yoffset); + view.commitUniforms(driver); out.params.clearColor = data.clearColor; diff --git a/filament/src/ShadowMap.cpp b/filament/src/ShadowMap.cpp index 724a09a02d..f818fbfa74 100644 --- a/filament/src/ShadowMap.cpp +++ b/filament/src/ShadowMap.cpp @@ -41,8 +41,10 @@ using namespace backend; static constexpr bool USE_DEPTH_CLAMP = false; ShadowMap::ShadowMap(FEngine& engine) noexcept - : mShadowType(ShadowType::DIRECTIONAL), - mHasVisibleShadows(false) { + : mPerViewUniforms(engine), + mShadowType(ShadowType::DIRECTIONAL), + mHasVisibleShadows(false), + mFace(0) { Entity entities[2]; engine.getEntityManager().create(2, entities); mCamera = engine.createCamera(entities[0]); @@ -64,12 +66,14 @@ void ShadowMap::terminate(FEngine& engine) { ShadowMap::~ShadowMap() = default; -void ShadowMap::initialize(size_t lightIndex, ShadowType shadowType, uint16_t shadowIndex, +void ShadowMap::initialize(size_t lightIndex, ShadowType shadowType, + uint16_t shadowIndex, uint8_t face, LightManager::ShadowOptions const* options) { mLightIndex = lightIndex; mShadowIndex = shadowIndex; mOptions = options; mShadowType = shadowType; + mFace = face; } mat4f ShadowMap::getDirectionalLightViewMatrix(float3 direction, float3 position) noexcept { @@ -1238,4 +1242,56 @@ void ShadowMap::updateSceneInfoSpot(mat4f const& Mv, FScene const& scene, ); } +filament::Viewport ShadowMap::getViewport() const noexcept { + // We set a viewport with a 1-texel border for when we index outside the + // texture. + // DON'T CHANGE this unless ShadowMap::getTextureCoordsMapping() is updated too. + // see: ShadowMap::getTextureCoordsMapping() + // + // For floating-point depth textures, the 1-texel border could be set to + // FLOAT_MAX to avoid clamping in the shadow shader (see sampleDepth inside + // shadowing.fs). Unfortunately, the APIs don't seem let us clear depth + // attachments to anything greater than 1.0, so we'd need a way to do this other + // than clearing. + const uint32_t dim = mOptions->mapSize; + if (isPointShadow()) { + // for point-light we don't have a border + return { 0, 0, dim, dim }; + } else { + return { 1, 1, dim - 2, dim - 2 }; + } +} + +// ------------------------------------------------------------------------------------------------ + +void ShadowMap::prepareCamera(const CameraInfo& cameraInfo) noexcept { + mPerViewUniforms.prepareCamera(cameraInfo); + mPerViewUniforms.prepareLodBias(0.0f); +} + +void ShadowMap::prepareViewport(const filament::Viewport& viewport) noexcept { + mPerViewUniforms.prepareViewport(viewport, 0, 0); +} + +void ShadowMap::prepareTime(math::float4 const& userTime) noexcept { + mPerViewUniforms.prepareTime(userTime); +} + +void ShadowMap::prepareDirectionalLight(math::float3 const& sceneSpaceDirection, + LightManager::Instance instance) noexcept { + mPerViewUniforms.prepareDirectionalLight(1.0f, sceneSpaceDirection, instance); +} + +void ShadowMap::prepareShadowMapping(bool highPrecision) noexcept { + mPerViewUniforms.prepareShadowMapping(highPrecision); +} + +void ShadowMap::commitUniforms(backend::DriverApi& driver) const noexcept { + mPerViewUniforms.commit(driver); +} + +void ShadowMap::bindPerViewUniformsAndSamplers(backend::DriverApi& driver) const noexcept { + mPerViewUniforms.bind(driver); +} + } // namespace filament diff --git a/filament/src/ShadowMap.h b/filament/src/ShadowMap.h index c6ff7d745f..28ccb4e6fb 100644 --- a/filament/src/ShadowMap.h +++ b/filament/src/ShadowMap.h @@ -19,12 +19,14 @@ #include "components/LightManager.h" +#include "PerViewUniforms.h" + #include "details/Camera.h" #include "details/Scene.h" -#include "backend/DriverApiForward.h" -#include "private/backend/SamplerGroup.h" -#include "math/mat4.h" +#include "private/backend/DriverApi.h" + +#include #include #include @@ -122,7 +124,7 @@ public: static math::mat4f getPointLightViewMatrix(backend::TextureCubemapFace face, math::float3 position) noexcept; - void initialize(size_t lightIndex, ShadowType shadowType, uint16_t shadowIndex, + void initialize(size_t lightIndex, ShadowType shadowType, uint16_t shadowIndex, uint8_t face, LightManager::ShadowOptions const* options); struct ShaderParameters { @@ -172,6 +174,8 @@ public: static void updateSceneInfoSpot(const math::mat4f& Mv, FScene const& scene, SceneInfo& sceneInfo); + filament::Viewport getViewport() const noexcept; + LightManager::ShadowOptions const* getShadowOptions() const noexcept { return mOptions; } size_t getLightIndex() const { return mLightIndex; } uint16_t getShadowIndex() const { return mShadowIndex; } @@ -181,6 +185,16 @@ public: bool isSpotShadow() const noexcept { return mShadowType == ShadowType::SPOT; } bool isPointShadow() const noexcept { return mShadowType == ShadowType::POINT; } ShadowType getShadowType() const noexcept { return mShadowType; } + uint8_t getFace() const noexcept { return mFace; } + + void prepareCamera(const CameraInfo& cameraInfo) noexcept; + void prepareViewport(const filament::Viewport& viewport) noexcept; + void prepareTime(math::float4 const& userTime) noexcept; + void prepareDirectionalLight(math::float3 const& sceneSpaceDirection, + LightManager::Instance instance) noexcept; + void prepareShadowMapping(bool highPrecision) noexcept; + void commitUniforms(backend::DriverApi& driver) const noexcept; + void bindPerViewUniformsAndSamplers(backend::DriverApi& driver) const noexcept; private: struct Segment { @@ -278,6 +292,8 @@ private: { 2, 6, 7, 3 }, // top }; + mutable PerViewUniforms mPerViewUniforms; // 64 + 2048 + FCamera* mCamera = nullptr; // 8 FCamera* mDebugCamera = nullptr; // 8 @@ -287,10 +303,13 @@ private: uint32_t mLightIndex = 0; // which light are we shadowing // 4 uint16_t mShadowIndex = 0; // our index in the shadowMap vector // 2 uint8_t mLayer = 0; // our layer in the shadowMap texture // 1 - ShadowType mShadowType : 2; - bool mHasVisibleShadows : 2; + ShadowType mShadowType : 2; // :2 + bool mHasVisibleShadows : 2; // :2 + uint8_t mFace : 3; // :3 }; +static_assert(sizeof(ShadowMap) == 32 + 2048 + 64); + } // namespace filament #endif // TNT_FILAMENT_DETAILS_SHADOWMAP_H diff --git a/filament/src/ShadowMapManager.cpp b/filament/src/ShadowMapManager.cpp index 4128bc3970..227a89db6c 100644 --- a/filament/src/ShadowMapManager.cpp +++ b/filament/src/ShadowMapManager.cpp @@ -98,22 +98,34 @@ void ShadowMapManager::setDirectionalShadowMap(size_t lightIndex, assert_invariant(options->shadowCascades <= CONFIG_MAX_SHADOW_CASCADES); for (size_t c = 0; c < options->shadowCascades; c++) { auto* pShadowMap = getCascadeShadowMap(c); - pShadowMap->initialize(lightIndex, ShadowType::DIRECTIONAL, c, options); + pShadowMap->initialize(lightIndex, ShadowType::DIRECTIONAL, c, 0, options); mCascadeShadowMaps.push_back(pShadowMap); } } void ShadowMapManager::addShadowMap(size_t lightIndex, bool spotlight, LightManager::ShadowOptions const* options) noexcept { - const size_t c = mSpotShadowMaps.size(); - assert_invariant(c < CONFIG_MAX_SHADOWMAP_PUNCTUAL); - auto* pShadowMap = getPointOrSpotShadowMap(c); - pShadowMap->initialize(lightIndex, spotlight ? ShadowType::SPOT : ShadowType::POINT, c, options); - mSpotShadowMaps.push_back(pShadowMap); + if (spotlight) { + const size_t c = mSpotShadowMaps.size(); + assert_invariant(c < CONFIG_MAX_SHADOWMAP_PUNCTUAL); + auto* pShadowMap = getPointOrSpotShadowMap(c); + pShadowMap->initialize(lightIndex, ShadowType::SPOT, c, 0, options); + mSpotShadowMaps.push_back(pShadowMap); + } else { + // point-light + for (size_t face = 0; face < 6; face++) { + const size_t c = mSpotShadowMaps.size(); + assert_invariant(c < CONFIG_MAX_SHADOWMAP_PUNCTUAL); + auto* pShadowMap = getPointOrSpotShadowMap(c); + pShadowMap->initialize(lightIndex, ShadowType::POINT, c, face, options); + mSpotShadowMaps.push_back(pShadowMap); + } + } } -FrameGraphId ShadowMapManager::render(FrameGraph& fg, FEngine& engine, - RenderPass const& pass, FView& view, CameraInfo const& mainCameraInfo) noexcept { +FrameGraphId ShadowMapManager::render(FEngine& engine, FrameGraph& fg, + RenderPass const& pass, FView& view, CameraInfo const& mainCameraInfo, + float4 const& userTime) noexcept { const float moment2 = std::numeric_limits::max(); const float moment1 = std::sqrt(moment2); @@ -133,11 +145,9 @@ FrameGraphId ShadowMapManager::render(FrameGraph& fg, FEngine struct PrepareShadowPassData { struct ShadowPass { mutable RenderPass::Executor executor; - mutable CameraInfo cameraInfo; ShadowMap* shadowMap; utils::Range range; FScene::VisibleMaskType visibilityMask; - uint8_t face = 0; }; // the actual shadow map atlas (currently a 2D texture array) FrameGraphId shadows; @@ -166,7 +176,7 @@ FrameGraphId ShadowMapManager::render(FrameGraph& fg, FEngine // for the directional light, we already know if it has visible shadows. if (pShadowMap->hasVisibleShadows()) { passList.push_back({ - {}, {}, pShadowMap, directionalShadowCastersRange, + {}, pShadowMap, directionalShadowCastersRange, VISIBLE_DIR_SHADOW_RENDERABLE }); } } @@ -178,16 +188,8 @@ FrameGraphId ShadowMapManager::render(FrameGraph& fg, FEngine for (auto* pShadowMap : mSpotShadowMaps) { assert_invariant(!pShadowMap->isDirectionalShadow()); passList.push_back({ - {}, {}, pShadowMap, spotShadowCastersRange, + {}, pShadowMap, spotShadowCastersRange, VISIBLE_DYN_SHADOW_RENDERABLE }); - if (pShadowMap->isPointShadow()) { - // add the 5 extra faces - for (uint8_t face = 1; face < 6; face++) { - passList.push_back({ - {}, {}, pShadowMap, spotShadowCastersRange, - VISIBLE_DYN_SHADOW_RENDERABLE, face }); - } - } } } @@ -197,10 +199,8 @@ FrameGraphId ShadowMapManager::render(FrameGraph& fg, FEngine // "read" from one of its resource (only writes), so the FrameGraph culls it. builder.sideEffect(); }, - [this, &engine, &view, scene, &mainCameraInfo, &passTemplate = pass]( + [this, &engine, &view, scene, mainCameraInfo, userTime, passTemplate = pass]( FrameGraphResources const& resources, auto const& data, DriverApi& driver) { - // set uniforms needed to render this ShadowMap - view.prepareShadowMap(view.getVsmShadowOptions().highPrecision); // Note: we could almost parallel_for the loop below, the problem currently is // that updatePrimitivesLod() updates temporary global state. @@ -215,7 +215,9 @@ FrameGraphId ShadowMapManager::render(FrameGraph& fg, FEngine // for spot shadow map, we need to do the culling switch (shadowMap.getShadowType()) { case ShadowType::DIRECTIONAL: - // nothing to do, it's been done already + shadowMap.prepareDirectionalLight( + scene->getLightData().elementAt(0), + scene->getLightData().elementAt(0)); break; case ShadowType::SPOT: prepareSpotShadowMap(shadowMap, engine, view, mainCameraInfo, @@ -225,7 +227,7 @@ FrameGraphId ShadowMapManager::render(FrameGraph& fg, FEngine case ShadowType::POINT: preparePointShadowMap(shadowMap, engine, view, mainCameraInfo, scene->getRenderableData(), entry.range, - scene->getLightData(), entry.face, mSceneInfo); + scene->getLightData(), mSceneInfo); break; } @@ -243,6 +245,12 @@ FrameGraphId ShadowMapManager::render(FrameGraph& fg, FEngine // cameraInfo only valid after calling update const CameraInfo cameraInfo{ shadowMap.getCamera() }; + shadowMap.prepareCamera(cameraInfo); + shadowMap.prepareViewport(shadowMap.getViewport()); + shadowMap.prepareTime(userTime); + shadowMap.prepareShadowMapping(view.getVsmShadowOptions().highPrecision); + shadowMap.commitUniforms(driver); + // updatePrimitivesLod must be run before RenderPass::appendCommands. view.updatePrimitivesLod(engine, cameraInfo, scene->getRenderableData(), entry.range); @@ -256,7 +264,24 @@ FrameGraphId ShadowMapManager::render(FrameGraph& fg, FEngine pass.sortCommands(engine); entry.executor = pass.getExecutor(); - entry.cameraInfo = cameraInfo; + + if (!view.hasVSM()) { + auto li = scene->getLightData().elementAt( + entry.shadowMap->getLightIndex()); + + auto const& params = engine.getLightManager().getShadowParams(li); + + const PolygonOffset polygonOffset = { // handle reversed Z + .slope = -params.options.polygonOffsetSlope, + .constant = -params.options.polygonOffsetConstant + }; + entry.executor.overridePolygonOffset(&polygonOffset); + } + + constexpr const backend::Viewport disabledScissor{ 0, 0, + (uint32_t)std::numeric_limits::max(), + (uint32_t)std::numeric_limits::max() }; + entry.executor.overrideScissor(&disabledScissor); } } @@ -274,8 +299,7 @@ FrameGraphId ShadowMapManager::render(FrameGraph& fg, FEngine struct ShadowPassData { FrameGraphId tempBlurSrc{}; // temporary shadowmap when blurring FrameGraphId output; - uint32_t blurRt{}; - uint32_t shadowRt{}; + uint32_t rt{}; }; auto const& passList = prepareShadowPass.getData().passList; @@ -284,7 +308,7 @@ FrameGraphId ShadowMapManager::render(FrameGraph& fg, FEngine continue; } - const uint8_t layer = entry.shadowMap->getLayer() + entry.face; + const uint8_t layer = entry.shadowMap->getLayer(); const auto* options = entry.shadowMap->getShadowOptions(); auto& shadowPass = fg.addPass("Shadow Pass", @@ -333,7 +357,7 @@ FrameGraphId ShadowMapManager::render(FrameGraph& fg, FEngine data.tempBlurSrc = builder.write(data.tempBlurSrc, FrameGraphTexture::Usage::COLOR_ATTACHMENT); - data.blurRt = builder.declareRenderPass("Temp Shadow RT", { + data.rt = builder.declareRenderPass("Temp Shadow RT", { .attachments = { .color = { data.tempBlurSrc }, .depth = depth }, @@ -352,9 +376,13 @@ FrameGraphId ShadowMapManager::render(FrameGraph& fg, FEngine } // finally, create the shadowmap render target -- one per layer. - data.shadowRt = builder.declareRenderPass("Shadow RT", renderTargetDesc); + auto rt = builder.declareRenderPass("Shadow RT", renderTargetDesc); + + // render either directly into the shadowmap, or to the temporary texture for + // blurring. + data.rt = blur ? data.rt : rt; }, - [=, &engine, &entry, &view](FrameGraphResources const& resources, + [=, &engine, &entry](FrameGraphResources const& resources, auto const& data, DriverApi& driver) { // Note: we capture entry by reference here. That's actually okay because @@ -364,62 +392,14 @@ FrameGraphId ShadowMapManager::render(FrameGraph& fg, FEngine // It wouldn't work to capture by copy because entry.pass wouldn't be // initialized, as this happens in an `execute` block. - auto& executor = entry.executor; - CameraInfo const& cameraInfo = entry.cameraInfo; + entry.shadowMap->bindPerViewUniformsAndSamplers(driver); - const bool blur = view.hasVSM() && options->vsm.blurWidth > 0.0f; - - // set uniforms relative to the camera - view.prepareCamera(cameraInfo); - - // We set a viewport with a 1-texel border for when we index outside the - // texture. - // DON'T CHANGE this unless ShadowMap::getTextureCoordsMapping() is updated too. - // see: ShadowMap::getTextureCoordsMapping() - // - // For floating-point depth textures, the 1-texel border could be set to - // FLOAT_MAX to avoid clamping in the shadow shader (see sampleDepth inside - // shadowing.fs). Unfortunately, the APIs don't seem let us clear depth - // attachments to anything greater than 1.0, so we'd need a way to do this other - // than clearing. - const uint32_t dim = options->mapSize; - filament::Viewport viewport{ 1, 1, dim - 2, dim - 2 }; - if (entry.shadowMap->isPointShadow()) { - // for point-light we don't have a border - viewport = { 0, 0, dim, dim }; - } - - view.prepareViewport(viewport, 0, 0); - - view.commitUniforms(driver); - - // render either directly into the shadowmap, or to the temporary texture for - // blurring. - auto rt = resources.getRenderPassInfo(blur ? data.blurRt : data.shadowRt); - rt.params.viewport = viewport; - - constexpr const backend::Viewport disabledScissor{ 0, 0, - (uint32_t)std::numeric_limits::max(), - (uint32_t)std::numeric_limits::max() }; - - if (!view.hasVSM()) { - auto li = scene->getLightData().elementAt( - entry.shadowMap->getLightIndex()); - - auto const& params = engine.getLightManager().getShadowParams(li); - - const PolygonOffset polygonOffset = { // handle reversed Z - .slope = -params.options.polygonOffsetSlope, - .constant = -params.options.polygonOffsetConstant - }; - executor.overridePolygonOffset(&polygonOffset); - } - - executor.overrideScissor(&disabledScissor); + auto rt = resources.getRenderPassInfo(data.rt); + rt.params.viewport = entry.shadowMap->getViewport(); engine.flush(); driver.beginRenderPass(rt.target, rt.params); - executor.execute(engine, "Shadow Pass"); + entry.executor.execute(engine, "Shadow Pass"); driver.endRenderPass(); }); @@ -710,9 +690,10 @@ void ShadowMapManager::prepareSpotShadowMap(ShadowMap& shadowMap, void ShadowMapManager::preparePointShadowMap(ShadowMap& shadowMap, FEngine& engine, FView& view, CameraInfo const& mainCameraInfo, FScene::RenderableSoa& renderableData, utils::Range range, - FScene::LightSoa& lightData, uint8_t face, + FScene::LightSoa& lightData, ShadowMap::SceneInfo const& sceneInfo) noexcept { + const uint8_t face = shadowMap.getFace(); const size_t lightIndex = shadowMap.getLightIndex(); FLightManager::ShadowOptions const* const options = shadowMap.getShadowOptions(); @@ -803,9 +784,15 @@ ShadowMapManager::ShadowTechnique ShadowMapManager::updateSpotShadowMaps(FEngine shadowTechnique |= ShadowTechnique::SHADOW_MAP; for (auto const* pShadowMap : mSpotShadowMaps) { const size_t lightIndex = pShadowMap->getLightIndex(); - shadowInfo[lightIndex].castsShadows = true; // FIXME: is that set correctly? - shadowInfo[lightIndex].index = pShadowMap->getShadowIndex(); - shadowInfo[lightIndex].layer = pShadowMap->getLayer(); + + // FIXME: currently we have one slot per shadowmap in the UBO, but we now have up to + // 6 shadowmap per light. So for now, we only write the data of the face 0, + // and the shader will figure out where to find the other face (layer+face) + if (pShadowMap->getFace() == 0) { + shadowInfo[lightIndex].castsShadows = true; // FIXME: is that set correctly? + shadowInfo[lightIndex].index = pShadowMap->getShadowIndex(); + shadowInfo[lightIndex].layer = pShadowMap->getLayer(); + } } } @@ -846,10 +833,6 @@ void ShadowMapManager::calculateTextureRequirements(FEngine& engine, FView& view maxDimension = std::max(maxDimension, options->mapSize); elvsm = elvsm || options->vsm.elvsm; pShadowMap->setLayer(layer++); - if (pShadowMap->isPointShadow()) { - // FIXME: we need to make sure we don't exceed 256 - layer += 5; - } } const uint8_t layersNeeded = layer; diff --git a/filament/src/ShadowMapManager.h b/filament/src/ShadowMapManager.h index 52e0acf5c1..5f95314423 100644 --- a/filament/src/ShadowMapManager.h +++ b/filament/src/ShadowMapManager.h @@ -90,8 +90,8 @@ public: FScene::RenderableSoa& renderableData, FScene::LightSoa& lightData) noexcept; // Renders all the shadow maps. - FrameGraphId render(FrameGraph& fg, FEngine& engine, - RenderPass const& pass, FView& view, CameraInfo const& mainCameraInfo) noexcept; + FrameGraphId render(FEngine& engine, FrameGraph& fg, RenderPass const& pass, + FView& view, CameraInfo const& mainCameraInfo, math::float4 const& userTime) noexcept; ShadowMap* getCascadeShadowMap(size_t cascade) noexcept { assert_invariant(cascade < CONFIG_MAX_SHADOW_CASCADES); @@ -140,7 +140,7 @@ private: void preparePointShadowMap(ShadowMap& map, FEngine& engine, FView& view, CameraInfo const& mainCameraInfo, FScene::RenderableSoa& renderableData, utils::Range range, - FScene::LightSoa& lightData, uint8_t face, + FScene::LightSoa& lightData, ShadowMap::SceneInfo const& sceneInfo) noexcept; static void updateSpotVisibilityMasks( diff --git a/filament/src/details/Renderer.cpp b/filament/src/details/Renderer.cpp index e38b98a3a5..446a4337bc 100644 --- a/filament/src/details/Renderer.cpp +++ b/filament/src/details/Renderer.cpp @@ -656,7 +656,7 @@ void FRenderer::renderJob(ArenaScope& arena, FView& view) { RenderPass shadowPass(pass); shadowPass.setVariant(shadowVariant); - auto shadows = view.renderShadowMaps(fg, engine, cameraInfo, shadowPass); + auto shadows = view.renderShadowMaps(engine, fg, cameraInfo, mShaderUserTime, shadowPass); blackboard["shadows"] = shadows; } @@ -740,8 +740,8 @@ void FRenderer::renderJob(ArenaScope& arena, FView& view) { // view set-ups that need to happen before rendering fg.addTrivialSideEffectPass("Prepare View Uniforms", - [=, &uniforms = view.getPerViewUniforms()](DriverApi& driver) { - uniforms.prepareCamera(cameraInfo); + [=, &view](DriverApi& driver) { + view.prepareCamera(cameraInfo); // The code here is a little fragile. In theory, we need to call prepareViewport() // for each render pass, because the viewport parameters depend on the resolution. @@ -761,11 +761,14 @@ void FRenderer::renderJob(ArenaScope& arena, FView& view) { // The reason why this bug is acceptable is that the viewport parameters are // currently only used for generating noise, so it's not too bad. - uniforms.prepareViewport(svp, + view.prepareViewport(svp, xvp.left * aoOptions.resolution, xvp.bottom * aoOptions.resolution); - uniforms.commit(driver); + view.commitUniforms(driver); + + // set uniforms and samplers for the color passes + view.bindPerViewUniformsAndSamplers(driver); }); // -------------------------------------------------------------------------------------------- diff --git a/filament/src/details/View.cpp b/filament/src/details/View.cpp index 80fed63e84..c5f066bf9f 100644 --- a/filament/src/details/View.cpp +++ b/filament/src/details/View.cpp @@ -606,9 +606,19 @@ void FView::prepare(FEngine& engine, DriverApi& driver, ArenaScope& arena, mPerViewUniforms.prepareFog(cameraInfo.getPosition(), mFogOptions); mPerViewUniforms.prepareTemporalNoise(mTemporalAntiAliasingOptions); mPerViewUniforms.prepareBlending(needsAlphaChannel); +} - // set uniforms and samplers - bindPerViewUniformsAndSamplers(driver); +void FView::bindPerViewUniformsAndSamplers(FEngine::DriverApi& driver) const noexcept { + mPerViewUniforms.bind(driver); + + driver.bindUniformBuffer(+UniformBindingPoints::LIGHTS, + mLightUbh); + + driver.bindUniformBuffer(+UniformBindingPoints::SHADOW, + mShadowMapManager.getShadowUniformsHandle()); + + driver.bindUniformBuffer(+UniformBindingPoints::FROXEL_RECORDS, + mFroxelizer.getRecordBuffer()); } void FView::computeVisibilityMasks( @@ -656,7 +666,9 @@ UTILS_NOINLINE void FView::prepareUpscaler(float2 scale) const noexcept { SYSTRACE_CALL(); - mPerViewUniforms.prepareUpscaler(scale, mDynamicResolution); + const float bias = (mDynamicResolution.quality >= QualityLevel::HIGH) ? + std::log2(std::min(scale.x, scale.y)) : 0.0f; + mPerViewUniforms.prepareLodBias(bias); } void FView::prepareCamera(const CameraInfo& cameraInfo) const noexcept { @@ -711,7 +723,7 @@ void FView::prepareShadow(Handle texture) const noexcept { } } -void FView::prepareShadowMap(bool highPrecision) const noexcept { +void FView::prepareShadowMapping(bool highPrecision) const noexcept { mPerViewUniforms.prepareShadowMapping(highPrecision); } @@ -894,9 +906,9 @@ void FView::updatePrimitivesLod(FEngine& engine, const CameraInfo&, } } -FrameGraphId FView::renderShadowMaps(FrameGraph& fg, FEngine& engine, - CameraInfo const& cameraInfo, RenderPass const& pass) noexcept { - return mShadowMapManager.render(fg, engine, pass, *this, cameraInfo); +FrameGraphId FView::renderShadowMaps(FEngine& engine, FrameGraph& fg, + CameraInfo const& cameraInfo, float4 const& userTime, RenderPass const& pass) noexcept { + return mShadowMapManager.render(engine, fg, pass, *this, cameraInfo, userTime); } void FView::commitFrameHistory(FEngine& engine) noexcept { diff --git a/filament/src/details/View.h b/filament/src/details/View.h index 4a23bc235c..8267ae8446 100644 --- a/filament/src/details/View.h +++ b/filament/src/details/View.h @@ -92,6 +92,8 @@ public: filament::Viewport const& viewport, CameraInfo const& cameraInfo, math::float4 const& userTime, bool needsAlphaChannel) noexcept; + void bindPerViewUniformsAndSamplers(FEngine::DriverApi& driver) const noexcept; + void setScene(FScene* scene) { mScene = scene; } FScene const* getScene() const noexcept { return mScene; } FScene* getScene() noexcept { return mScene; } @@ -148,7 +150,7 @@ public: ScreenSpaceReflectionsOptions const& ssrOptions) const noexcept; void prepareStructure(backend::Handle structure) const noexcept; void prepareShadow(backend::Handle structure) const noexcept; - void prepareShadowMap(bool highPrecision) const noexcept; + void prepareShadowMapping(bool highPrecision) const noexcept; void cleanupRenderPasses() const noexcept; void froxelize(FEngine& engine, math::mat4f const& viewMatrix) const noexcept; @@ -165,8 +167,9 @@ public: bool hasPCSS() const noexcept { return mShadowType == ShadowType::PCSS; } bool hasPicking() const noexcept { return mActivePickingQueriesList != nullptr; } - FrameGraphId renderShadowMaps(FrameGraph& fg, FEngine& engine, - CameraInfo const& cameraInfo, RenderPass const& pass) noexcept; + FrameGraphId renderShadowMaps(FEngine& engine, FrameGraph& fg, + CameraInfo const& cameraInfo, math::float4 const& userTime, + RenderPass const& pass) noexcept; void updatePrimitivesLod( FEngine& engine, const CameraInfo& camera, @@ -451,13 +454,6 @@ private: Culler::result_type* visibleMask, size_t count); - void bindPerViewUniformsAndSamplers(FEngine::DriverApi& driver) const noexcept { - mPerViewUniforms.bind(driver); - driver.bindUniformBuffer(+UniformBindingPoints::LIGHTS, mLightUbh); - driver.bindUniformBuffer(+UniformBindingPoints::SHADOW, mShadowMapManager.getShadowUniformsHandle()); - driver.bindUniformBuffer(+UniformBindingPoints::FROXEL_RECORDS, mFroxelizer.getRecordBuffer()); - } - // Clean-up the whole history, free all resources. This is typically called when the View is // being terminated. void drainFrameHistory(FEngine& engine) noexcept;