From c212dd5bc70d52c0d4ccbdb37a22b6f36d695d0d Mon Sep 17 00:00:00 2001 From: Mathias Agopian Date: Fri, 15 Apr 2022 15:25:59 -0700 Subject: [PATCH] remove the CameraInfo state from FView this state only exists during Renderer::render(), having it outside of view is more flexible as it give us an opportunity to adjust camera parameter globally before drawing. Also greatly reduced the size of RenderPass (which is a Value object). --- filament/src/Froxelizer.cpp | 12 ++--- filament/src/Froxelizer.h | 4 +- filament/src/PerViewUniforms.cpp | 4 +- filament/src/PerViewUniforms.h | 2 +- filament/src/PostProcessManager.cpp | 19 +++---- filament/src/RenderPass.cpp | 11 +++-- filament/src/RenderPass.h | 5 +- filament/src/ShadowMap.cpp | 7 ++- filament/src/ShadowMap.h | 2 +- filament/src/ShadowMapManager.cpp | 38 +++++++------- filament/src/ShadowMapManager.h | 20 ++++---- filament/src/details/Camera.cpp | 2 +- filament/src/details/Camera.h | 3 +- filament/src/details/Renderer.cpp | 18 ++++--- filament/src/details/View.cpp | 77 +++++++++++++++-------------- filament/src/details/View.h | 22 +++++---- 16 files changed, 129 insertions(+), 117 deletions(-) diff --git a/filament/src/Froxelizer.cpp b/filament/src/Froxelizer.cpp index 3fab0f33cc..a4bc1e8280 100644 --- a/filament/src/Froxelizer.cpp +++ b/filament/src/Froxelizer.cpp @@ -513,10 +513,10 @@ void Froxelizer::commit(backend::DriverApi& driverApi) { } void Froxelizer::froxelizeLights(FEngine& engine, - CameraInfo const& UTILS_RESTRICT camera, + mat4f const& UTILS_RESTRICT viewMatrix, const FScene::LightSoa& UTILS_RESTRICT lightData) noexcept { // note: this is called asynchronously - froxelizeLoop(engine, camera, lightData); + froxelizeLoop(engine, viewMatrix, lightData); froxelizeAssignRecordsCompress(); #ifndef NDEBUG @@ -544,7 +544,7 @@ void Froxelizer::froxelizeLights(FEngine& engine, } void Froxelizer::froxelizeLoop(FEngine& engine, - const CameraInfo& UTILS_RESTRICT camera, + const mat4f& UTILS_RESTRICT viewMatrix, const FScene::LightSoa& UTILS_RESTRICT lightData) noexcept { SYSTRACE_CALL(); @@ -557,11 +557,11 @@ void Froxelizer::froxelizeLoop(FEngine& engine, auto const* UTILS_RESTRICT instances = lightData.data(); auto process = [ this, &froxelThreadData, - spheres, directions, instances, &camera, &lcm ] + spheres, directions, instances, &viewMatrix, &lcm ] (size_t count, size_t offset, size_t stride) { const mat4f& projection = mProjection; - const mat3f& vn = camera.view.upperLeft(); + const mat3f& vn = viewMatrix.upperLeft(); // We use minimum cone angle of 0.5 degrees because too small angles cause issues in the // sphere/cone intersection test, due to floating-point precision. @@ -572,7 +572,7 @@ void Froxelizer::froxelizeLoop(FEngine& engine, const size_t j = i + FScene::DIRECTIONAL_LIGHTS_COUNT; FLightManager::Instance li = instances[j]; LightParams light = { - .position = (camera.view * float4{ spheres[j].xyz, 1 }).xyz, // to view-space + .position = (viewMatrix * float4{ spheres[j].xyz, 1 }).xyz, // to view-space .cosSqr = std::min(maxCosSquared, lcm.getCosOuterSquared(li)), // spot only .axis = vn * directions[j], // spot only .invSin = lcm.getSinInverse(li), // spot only diff --git a/filament/src/Froxelizer.h b/filament/src/Froxelizer.h index 2fd0f8e1d9..e9c039a005 100644 --- a/filament/src/Froxelizer.h +++ b/filament/src/Froxelizer.h @@ -120,7 +120,7 @@ public: float getLightFar() const noexcept { return mZLightFar; } // update Records and Froxels texture with lights data. this is thread-safe. - void froxelizeLights(FEngine& engine, CameraInfo const& camera, + void froxelizeLights(FEngine& engine, math::mat4f const& viewMatrix, const FScene::LightSoa& lightData) noexcept; void updateUniforms(PerViewUib& s) { @@ -194,7 +194,7 @@ private: bool update() noexcept; void froxelizeLoop(FEngine& engine, - const CameraInfo& camera, const FScene::LightSoa& lightData) noexcept; + math::mat4f const& viewMatrix, const FScene::LightSoa& lightData) noexcept; void froxelizeAssignRecordsCompress() noexcept; diff --git a/filament/src/PerViewUniforms.cpp b/filament/src/PerViewUniforms.cpp index 71a0645d4f..450a3eabb5 100644 --- a/filament/src/PerViewUniforms.cpp +++ b/filament/src/PerViewUniforms.cpp @@ -127,7 +127,7 @@ void PerViewUniforms::prepareTemporalNoise(TemporalAntiAliasingOptions const& op s.temporalNoise = options.enabled ? temporalNoise : 0.0f; } -void PerViewUniforms::prepareFog(const CameraInfo& camera, FogOptions const& options) noexcept { +void PerViewUniforms::prepareFog(float3 const& cameraPosition, FogOptions const& options) noexcept { // this can't be too high because we need density / heightFalloff to produce something // close to fogOptions.density in the fragment shader which use 16-bits floats. constexpr float epsilon = 0.001f; @@ -135,7 +135,7 @@ void PerViewUniforms::prepareFog(const CameraInfo& camera, FogOptions const& opt // precalculate the constant part of density integral and correct for exp2() in the shader const float density = ((options.density / heightFalloff) * - std::exp(-heightFalloff * (camera.getPosition().y - options.height))) + std::exp(-heightFalloff * (cameraPosition.y - options.height))) * float(1.0f / F_LN2); auto& s = mUniforms.edit(); diff --git a/filament/src/PerViewUniforms.h b/filament/src/PerViewUniforms.h index 392a5a793f..8d82c1a16e 100644 --- a/filament/src/PerViewUniforms.h +++ b/filament/src/PerViewUniforms.h @@ -69,7 +69,7 @@ public: void prepareTime(math::float4 const& userTime) noexcept; void prepareTemporalNoise(TemporalAntiAliasingOptions const& options) noexcept; void prepareExposure(float ev100) noexcept; - void prepareFog(const CameraInfo& camera, FogOptions const& options) noexcept; + void prepareFog(math::float3 const& cameraPosition, FogOptions const& options) noexcept; void prepareStructure(TextureHandle structure) noexcept; void prepareSSAO(TextureHandle ssao, AmbientOcclusionOptions const& options) noexcept; void prepareBlending(bool needsAlphaChannel) noexcept; diff --git a/filament/src/PostProcessManager.cpp b/filament/src/PostProcessManager.cpp index 3aa6250943..a799c12639 100644 --- a/filament/src/PostProcessManager.cpp +++ b/filament/src/PostProcessManager.cpp @@ -531,22 +531,23 @@ FrameGraphId PostProcessManager::ssr(FrameGraph& fg, data.history = builder.sample(history); } }, - [=, &uniforms, renderPass = pass](FrameGraphResources const& resources, - auto const& data, DriverApi& driver) mutable { - + [this, projection = cameraInfo.projection, viewMatrix = cameraInfo.view, + worldOrigin = cameraInfo.worldOrigin, uvFromClipMatrix, historyProjection, + options, &uniforms, renderPass = pass] + (FrameGraphResources const& resources, auto const& data, DriverApi& driver) mutable { // set structure sampler uniforms.prepareStructure(data.structure ? resources.getTexture(data.structure) : getOneTexture()); // set screen-space reflections and screen-space refractions - mat4f uvFromViewMatrix = uvFromClipMatrix * cameraInfo.projection; - mat4f reprojection = uvFromClipMatrix * historyProjection - * inverse(cameraInfo.view * cameraInfo.worldOrigin); + mat4f uvFromViewMatrix = uvFromClipMatrix * projection; + mat4f reprojection = mat4f{ uvFromClipMatrix * historyProjection + * inverse(viewMatrix * worldOrigin) }; // the history sampler is a regular texture2D TextureHandle history = data.history ? resources.getTexture(data.history) : getZeroTexture(); - uniforms.prepareHistorySSR(history, reprojection, uvFromViewMatrix,options); + uniforms.prepareHistorySSR(history, reprojection, uvFromViewMatrix, options); uniforms.commit(driver); @@ -806,7 +807,7 @@ FrameGraphId PostProcessManager::screenSpaceAmbientOcclusion( // light direction in view space // (note: this is actually equivalent to using the camera view matrix -- before the // world matrix is accounted for) - auto m = cameraInfo.view * cameraInfo.worldOrigin; + const mat4f m{ cameraInfo.view * cameraInfo.worldOrigin }; const float3 l = normalize( mat3f::getTransformForNormals(m.upperLeft()) * options.ssct.lightDirection); @@ -2600,7 +2601,7 @@ void PostProcessManager::prepareTaa(FrameGraph& fg, filament::Viewport const& sv auto& current = frameHistory.getCurrent().*pTaa; // compute projection - current.projection = inoutCameraInfo->projection * (inoutCameraInfo->view * inoutCameraInfo->worldOrigin); + current.projection = mat4f{ inoutCameraInfo->projection * (inoutCameraInfo->view * inoutCameraInfo->worldOrigin) }; current.frameId = previous.frameId + 1; // sample position within a pixel [-0.5, 0.5] diff --git a/filament/src/RenderPass.cpp b/filament/src/RenderPass.cpp index e2abb13f4e..f04df5b6cc 100644 --- a/filament/src/RenderPass.cpp +++ b/filament/src/RenderPass.cpp @@ -74,6 +74,11 @@ void RenderPass::setGeometry(FScene::RenderableSoa const& soa, Range v mUboHandle = uboHandle; } +void RenderPass::setCamera(const CameraInfo& camera) noexcept { + mCameraPosition = camera.getPosition(); + mCameraForwardVector = camera.getForwardVector(); +} + void RenderPass::overridePolygonOffset(backend::PolygonOffset* polygonOffset) noexcept { if ((mPolygonOffsetOverride = (polygonOffset != nullptr))) { mPolygonOffset = *polygonOffset; @@ -97,7 +102,6 @@ void RenderPass::appendCommands(CommandTypeFlags const commandTypeFlags) noexcep const RenderFlags renderFlags = mFlags; const Variant variant = mVariant; const FScene::VisibleMaskType visibilityMask = mVisibilityMask; - CameraInfo const& camera = mCamera; // up-to-date summed primitive counts needed for generateCommands() FScene::RenderableSoa const& soa = *mRenderableSoa; @@ -112,9 +116,8 @@ void RenderPass::appendCommands(CommandTypeFlags const commandTypeFlags) noexcep commandCount += 1; // for the sentinel Command* const curr = append(commandCount); - // we extract camera position/forward outside of the loop, because these are not cheap. - const float3 cameraPosition(camera.getPosition()); - const float3 cameraForwardVector(camera.getForwardVector()); + const float3 cameraPosition(mCameraPosition); + const float3 cameraForwardVector(mCameraForwardVector); auto work = [commandTypeFlags, curr, &soa, variant, renderFlags, visibilityMask, cameraPosition, cameraForwardVector] (uint32_t startIndex, uint32_t indexCount) { diff --git a/filament/src/RenderPass.h b/filament/src/RenderPass.h index 264562468e..3d27637578 100644 --- a/filament/src/RenderPass.h +++ b/filament/src/RenderPass.h @@ -272,7 +272,7 @@ public: backend::Handle uboHandle) noexcept; // specifies camera information (e.g. used for sorting commands) - void setCamera(const CameraInfo& camera) noexcept { mCamera = camera; } + void setCamera(const CameraInfo& camera) noexcept; // flags controlling how commands are generated void setRenderFlags(RenderFlags flags) noexcept { mFlags = flags; } @@ -406,7 +406,8 @@ private: backend::Handle mUboHandle; // info about the camera - CameraInfo mCamera; + math::float3 mCameraPosition{}; + math::float3 mCameraForwardVector{}; // info about the scene features (e.g.: has shadows, lighting, etc...) RenderFlags mFlags{}; diff --git a/filament/src/ShadowMap.cpp b/filament/src/ShadowMap.cpp index 6631b50e45..c737564e05 100644 --- a/filament/src/ShadowMap.cpp +++ b/filament/src/ShadowMap.cpp @@ -72,7 +72,7 @@ ShadowMap::~ShadowMap() { void ShadowMap::render(FScene const& scene, utils::Range range, FScene::VisibleMaskType visibilityMask, filament::CameraInfo const& cameraInfo, RenderPass* const pass) noexcept { - pass->setCamera(cameraInfo); +// pass->setCamera(cameraInfo); pass->setVisibilityMask(visibilityMask); pass->setGeometry(scene.getRenderableData(), range, scene.getRenderableUBO()); pass->overridePolygonOffset(&mShadowMapInfo.polygonOffset); @@ -1048,13 +1048,12 @@ void ShadowMap::visitScene(const FScene& scene, uint32_t visibleLayers, } } -void ShadowMap::initSceneInfo(FScene const& scene, filament::CameraInfo const& camera, +void ShadowMap::initSceneInfo(FScene const& scene, mat4f const& viewMatrix, ShadowMap::SceneInfo& sceneInfo) { sceneInfo.vsNearFar = { std::numeric_limits::lowest(), std::numeric_limits::max() }; // We assume the light is at the origin to compute the SceneInfo. This is consumed later by // computeShadowCameraDirectional() which takes this into account. - const mat4f V = camera.view; // Compute scene bounds in world space, as well as the light-space and view-space near/far planes sceneInfo.wsShadowCastersVolume = {}; @@ -1071,7 +1070,7 @@ void ShadowMap::initSceneInfo(FScene const& scene, filament::CameraInfo const& c min(sceneInfo.wsShadowReceiversVolume.min, receiver.min); sceneInfo.wsShadowReceiversVolume.max = max(sceneInfo.wsShadowReceiversVolume.max, receiver.max); - float2 nf = ShadowMap::computeNearFar(V, receiver); + float2 nf = ShadowMap::computeNearFar(viewMatrix, receiver); sceneInfo.vsNearFar.x = std::max(sceneInfo.vsNearFar.x, nf.x); sceneInfo.vsNearFar.y = std::min(sceneInfo.vsNearFar.y, nf.y); } diff --git a/filament/src/ShadowMap.h b/filament/src/ShadowMap.h index b0d32f6c6a..76ed155ba4 100644 --- a/filament/src/ShadowMap.h +++ b/filament/src/ShadowMap.h @@ -129,7 +129,7 @@ public: // Call once per frame to populate the SceneInfo struct, then pass to update(). // This computes values constant across all shadow maps. - static void initSceneInfo(FScene const& scene, filament::CameraInfo const& camera, + static void initSceneInfo(FScene const& scene, math::mat4f const& viewMatrix, ShadowMap::SceneInfo& sceneInfo); // Update SceneInfo struct for a given light diff --git a/filament/src/ShadowMapManager.cpp b/filament/src/ShadowMapManager.cpp index f66973a0e4..6860b64bef 100644 --- a/filament/src/ShadowMapManager.cpp +++ b/filament/src/ShadowMapManager.cpp @@ -55,10 +55,9 @@ ShadowMapManager::~ShadowMapManager() { } } -ShadowMapManager::ShadowTechnique ShadowMapManager::update( - FEngine& engine, FView& view, - TypedUniformBuffer& shadowUb, FScene::RenderableSoa& renderableData, - FScene::LightSoa& lightData) noexcept { +ShadowMapManager::ShadowTechnique ShadowMapManager::update(FEngine& engine, FView& view, + CameraInfo const& cameraInfo, TypedUniformBuffer& shadowUb, + FScene::RenderableSoa& renderableData, FScene::LightSoa& lightData) noexcept { ShadowTechnique shadowTechnique = {}; calculateTextureRequirements(engine, view, lightData); @@ -66,15 +65,13 @@ ShadowMapManager::ShadowTechnique ShadowMapManager::update( ShadowMap::SceneInfo sceneInfo(view.getVisibleLayers()); // Compute scene-dependent values shared across all shadow maps - ShadowMap::initSceneInfo( - *view.getScene(), view.getCameraInfo(), - sceneInfo); + ShadowMap::initSceneInfo(*view.getScene(), cameraInfo.view, sceneInfo); shadowTechnique |= updateCascadeShadowMaps( - engine, view, renderableData, lightData, sceneInfo); + engine, view, cameraInfo, renderableData, lightData, sceneInfo); shadowTechnique |= updateSpotShadowMaps( - engine, view, renderableData, lightData, sceneInfo, shadowUb); + engine, view, cameraInfo, renderableData, lightData, sceneInfo, shadowUb); return shadowTechnique; } @@ -338,10 +335,9 @@ FrameGraphId ShadowMapManager::render(FrameGraph& fg, } ShadowMapManager::ShadowTechnique ShadowMapManager::updateCascadeShadowMaps(FEngine& engine, - FView& view, FScene::RenderableSoa& renderableData, FScene::LightSoa& lightData, - ShadowMap::SceneInfo& sceneInfo) noexcept { + FView& view, CameraInfo const& cameraInfo, FScene::RenderableSoa& renderableData, + FScene::LightSoa& lightData, ShadowMap::SceneInfo& sceneInfo) noexcept { FScene* scene = view.getScene(); - const CameraInfo& viewingCameraInfo = view.getCameraInfo(); auto& lcm = engine.getLightManager(); FLightManager::Instance directionalLight = lightData.elementAt(0); @@ -365,7 +361,7 @@ ShadowMapManager::ShadowTechnique ShadowMapManager::updateCascadeShadowMaps(FEng ShadowMapEntry& entry = mCascadeShadowMaps[0]; ShadowMap& shadowMap = entry.getShadowMap(); - shadowMap.updateDirectional(lightData, 0, viewingCameraInfo, shadowMapInfo, *scene, sceneInfo); + shadowMap.updateDirectional(lightData, 0, cameraInfo, shadowMapInfo, *scene, sceneInfo); Frustum const& frustum = shadowMap.getCamera().getCullingFrustum(); FView::cullRenderables(engine.getJobSystem(), renderableData, frustum, @@ -384,8 +380,8 @@ ShadowMapManager::ShadowTechnique ShadowMapManager::updateCascadeShadowMaps(FEng } // Adjust the near and far planes to tightly bound the scene. - float vsNear = -viewingCameraInfo.zn; - float vsFar = -viewingCameraInfo.zf; + float vsNear = -cameraInfo.zn; + float vsFar = -cameraInfo.zf; if (engine.debug.shadowmap.tightly_bound_scene) { vsNear = std::min(vsNear, sceneInfo.vsNearFar.x); vsFar = std::max(vsFar, sceneInfo.vsNearFar.y); @@ -402,7 +398,7 @@ ShadowMapManager::ShadowTechnique ShadowMapManager::updateCascadeShadowMaps(FEng } const CascadeSplits::Params p { - .proj = viewingCameraInfo.cullingProjection, + .proj = cameraInfo.cullingProjection, .near = vsNear, .far = vsFar, .cascadeCount = cascadeCount, @@ -440,7 +436,7 @@ ShadowMapManager::ShadowTechnique ShadowMapManager::updateCascadeShadowMaps(FEng sceneInfo.csNearFar = { csSplitPosition[i], csSplitPosition[i + 1] }; shadowMap.updateDirectional(lightData, 0, - viewingCameraInfo, shadowMapInfo, + cameraInfo, shadowMapInfo, *scene, sceneInfo); if (shadowMap.hasVisibleShadows()) { @@ -479,11 +475,11 @@ ShadowMapManager::ShadowTechnique ShadowMapManager::updateCascadeShadowMaps(FEng } ShadowMapManager::ShadowTechnique ShadowMapManager::updateSpotShadowMaps(FEngine& engine, - FView& view, FScene::RenderableSoa& renderableData, FScene::LightSoa& lightData, - ShadowMap::SceneInfo& sceneInfo, TypedUniformBuffer& shadowUb) noexcept { + FView& view, CameraInfo const& cameraInfo, FScene::RenderableSoa& renderableData, + FScene::LightSoa& lightData, ShadowMap::SceneInfo& sceneInfo, + TypedUniformBuffer& shadowUb) noexcept { auto& lcm = engine.getLightManager(); - const CameraInfo& viewingCameraInfo = view.getCameraInfo(); // shadow-map shadows for point/spotlights ShadowTechnique shadowTechnique{}; @@ -529,7 +525,7 @@ ShadowMapManager::ShadowTechnique ShadowMapManager::updateSpotShadowMaps(FEngine VISIBLE_SPOT_SHADOW_RENDERABLE_N_BIT(i)); shadowMap.updateSpot(lightData, lightIndex, - viewingCameraInfo, shadowMapInfo, + cameraInfo, shadowMapInfo, *view.getScene(), sceneInfo); if (shadowMap.hasVisibleShadows()) { diff --git a/filament/src/ShadowMapManager.h b/filament/src/ShadowMapManager.h index 0087ed6bda..00686859c8 100644 --- a/filament/src/ShadowMapManager.h +++ b/filament/src/ShadowMapManager.h @@ -82,8 +82,8 @@ public: // Updates all of the shadow maps and performs culling. // Returns true if any of the shadow maps have visible shadows. - ShadowTechnique update(FEngine& engine, FView& view, - TypedUniformBuffer& shadowUb, + ShadowMapManager::ShadowTechnique update(FEngine& engine, FView& view, + CameraInfo const& cameraInfo, TypedUniformBuffer& shadowUb, FScene::RenderableSoa& renderableData, FScene::LightSoa& lightData) noexcept; // Renders all the shadow maps. @@ -101,7 +101,8 @@ public: ShadowMap* getSpotShadowMap(size_t spot) noexcept { assert_invariant(spot < CONFIG_MAX_SHADOW_CASTING_SPOTS); - return std::launder(reinterpret_cast(&mShadowMapCache[CONFIG_MAX_SHADOW_CASCADES + spot])); + return std::launder(reinterpret_cast( + &mShadowMapCache[CONFIG_MAX_SHADOW_CASCADES + spot])); } ShadowMap const* getSpotShadowMap(size_t spot) const noexcept { @@ -114,13 +115,14 @@ public: } private: - ShadowTechnique updateCascadeShadowMaps(FEngine& engine, - FView& view, FScene::RenderableSoa& renderableData, FScene::LightSoa& lightData, - ShadowMap::SceneInfo& sceneInfo) noexcept; + ShadowMapManager::ShadowTechnique updateCascadeShadowMaps(FEngine& engine, + FView& view, CameraInfo const& cameraInfo, FScene::RenderableSoa& renderableData, + FScene::LightSoa& lightData, ShadowMap::SceneInfo& sceneInfo) noexcept; - ShadowTechnique updateSpotShadowMaps(FEngine& engine, - FView& view, FScene::RenderableSoa& renderableData, FScene::LightSoa& lightData, - ShadowMap::SceneInfo& sceneInfo, TypedUniformBuffer& shadowUb) noexcept; + ShadowMapManager::ShadowTechnique updateSpotShadowMaps(FEngine& engine, + FView& view, CameraInfo const& cameraInfo, FScene::RenderableSoa& renderableData, + FScene::LightSoa& lightData, ShadowMap::SceneInfo& sceneInfo, + TypedUniformBuffer& shadowUb) noexcept; void calculateTextureRequirements(FEngine& engine, FView& view, FScene::LightSoa& lightData) noexcept; diff --git a/filament/src/details/Camera.cpp b/filament/src/details/Camera.cpp index 01045825dc..23ddd7ad92 100644 --- a/filament/src/details/Camera.cpp +++ b/filament/src/details/Camera.cpp @@ -293,7 +293,7 @@ CameraInfo::CameraInfo(FCamera const& camera, const math::mat4& worldOriginCamer A = f / camera.getAperture(); d = std::max(zn, camera.getFocusDistance()); worldOffset = camera.getPosition(); - worldOrigin = mat4f{ worldOriginCamera }; + worldOrigin = worldOriginCamera; } } // namespace filament diff --git a/filament/src/details/Camera.h b/filament/src/details/Camera.h index f9ad29d934..83805425fa 100644 --- a/filament/src/details/Camera.h +++ b/filament/src/details/Camera.h @@ -217,11 +217,10 @@ struct CameraInfo { float A{}; // f-number or f / aperture diameter [m] float d{}; // focus distance [m] math::float3 worldOffset{}; // world offset, API-level camera position + math::mat4 worldOrigin; // this is already applied to model and view math::float3 const& getPosition() const noexcept { return model[3].xyz; } math::float3 getForwardVector() const noexcept { return normalize(-model[2].xyz); } - // for debugging: - math::mat4f worldOrigin; // this is already applied to model and view }; FILAMENT_UPCAST(Camera) diff --git a/filament/src/details/Renderer.cpp b/filament/src/details/Renderer.cpp index f68b4d1d03..9850d0c661 100644 --- a/filament/src/details/Renderer.cpp +++ b/filament/src/details/Renderer.cpp @@ -282,7 +282,10 @@ void FRenderer::renderJob(ArenaScope& arena, FView& view) { // If the swap-chain is transparent or if we blend into it, we need to allocate our intermediate // buffers with an alpha channel. const bool needsAlphaChannel = (mSwapChain && mSwapChain->isTransparent()) || blendModeTranslucent; - view.prepare(engine, driver, arena, svp, getShaderUserTime(), needsAlphaChannel); + + CameraInfo cameraInfo = view.computeCameraInfo(engine); + + view.prepare(engine, driver, arena, svp, cameraInfo, getShaderUserTime(), needsAlphaChannel); view.prepareUpscaler(scale); @@ -290,7 +293,8 @@ void FRenderer::renderJob(ArenaScope& arena, FView& view) { JobSystem::Job* jobFroxelize = nullptr; if (view.hasDynamicLighting()) { jobFroxelize = js.runAndRetain(js.createJob(nullptr, - [&engine, &view](JobSystem&, JobSystem::Job*) { view.froxelize(engine); })); + [&engine, &view, &viewMatrix = cameraInfo.view](JobSystem&, JobSystem::Job*) { + view.froxelize(engine, viewMatrix); })); } /* @@ -428,8 +432,6 @@ void FRenderer::renderJob(ArenaScope& arena, FView& view) { * Depth + Color passes */ - CameraInfo cameraInfo = view.getCameraInfo(); - // updatePrimitivesLod must be run before appendCommands and once for each set // of RenderPass::setCamera / RenderPass::setGeometry calls. view.updatePrimitivesLod(engine, cameraInfo, @@ -606,6 +608,9 @@ void FRenderer::renderJob(ArenaScope& arena, FView& view) { struct ExportSSRHistoryData { FrameGraphId history; }; + // FIXME: should we use the TAA-modified cameraInfo here or not? (we are). + auto projection = mat4f{ + cameraInfo.projection * (cameraInfo.view * cameraInfo.worldOrigin) }; fg.addPass("Export SSR history", [&](FrameGraph::Builder& builder, auto& data) { // We need to use sideEffect here to ensure this pass won't be culled. @@ -613,12 +618,11 @@ void FRenderer::renderJob(ArenaScope& arena, FView& view) { // an "import". builder.sideEffect(); data.history = builder.sample(colorPassOutput); // FIXME: an access must be declared for detach(), why? - }, [&view](FrameGraphResources const& resources, auto const& data, + }, [&view, projection](FrameGraphResources const& resources, auto const& data, backend::DriverApi&) { - const auto& cameraInfo = view.getCameraInfo(); auto& history = view.getFrameHistory(); auto& current = history.getCurrent(); - current.ssr.projection = cameraInfo.projection * (cameraInfo.view * cameraInfo.worldOrigin); + current.ssr.projection = projection; resources.detach(data.history, ¤t.ssr.color, ¤t.ssr.desc); }); diff --git a/filament/src/details/View.cpp b/filament/src/details/View.cpp index 031ca916f7..a9f178d998 100644 --- a/filament/src/details/View.cpp +++ b/filament/src/details/View.cpp @@ -283,7 +283,8 @@ bool FView::isSkyboxVisible() const noexcept { } void FView::prepareShadowing(FEngine& engine, DriverApi& driver, - FScene::RenderableSoa& renderableData, FScene::LightSoa& lightData) noexcept { + FScene::RenderableSoa& renderableData, FScene::LightSoa& lightData, + CameraInfo const& cameraInfo) noexcept { SYSTRACE_CALL(); mHasShadowing = false; @@ -338,7 +339,7 @@ void FView::prepareShadowing(FEngine& engine, DriverApi& driver, } } - auto shadowTechnique = mShadowMapManager.update(engine, *this, + auto shadowTechnique = mShadowMapManager.update(engine, *this, cameraInfo, mShadowUb, renderableData, lightData); mHasShadowing = any(shadowTechnique); @@ -346,10 +347,9 @@ void FView::prepareShadowing(FEngine& engine, DriverApi& driver, } void FView::prepareLighting(FEngine& engine, FEngine::DriverApi& driver, ArenaScope& arena, - filament::Viewport const& viewport) noexcept { + filament::Viewport const& viewport, CameraInfo const& cameraInfo) noexcept { SYSTRACE_CALL(); - const CameraInfo& camera = mViewingCameraInfo; FScene* const scene = mScene; auto const& lightData = scene->getLightData(); @@ -359,9 +359,10 @@ void FView::prepareLighting(FEngine& engine, FEngine::DriverApi& driver, ArenaSc mHasDynamicLighting = scene->getLightData().size() > FScene::DIRECTIONAL_LIGHTS_COUNT; if (mHasDynamicLighting) { - scene->prepareDynamicLights(camera, arena, mLightUbh); + scene->prepareDynamicLights(cameraInfo, arena, mLightUbh); Froxelizer& froxelizer = mFroxelizer; - if (froxelizer.prepare(driver, arena, viewport, camera.projection, camera.zn, camera.zf)) { + if (froxelizer.prepare(driver, arena, viewport, + cameraInfo.projection, cameraInfo.zn, cameraInfo.zf)) { // update our uniform buffer if needed mPerViewUniforms.prepareDynamicLights(mFroxelizer); } @@ -374,9 +375,9 @@ void FView::prepareLighting(FEngine& engine, FEngine::DriverApi& driver, ArenaSc * Exposure */ - const float exposure = Exposure::exposure(camera.ev100); + const float exposure = Exposure::exposure(cameraInfo.ev100); - mPerViewUniforms.prepareExposure(camera.ev100); + mPerViewUniforms.prepareExposure(cameraInfo.ev100); /* * Indirect light (IBL) @@ -406,15 +407,7 @@ void FView::prepareLighting(FEngine& engine, FEngine::DriverApi& driver, ArenaSc mHasDirectionalLight = directionalLight.isValid(); } -void FView::prepare(FEngine& engine, DriverApi& driver, ArenaScope& arena, - filament::Viewport const& viewport, float4 const& userTime, bool needsAlphaChannel) noexcept { - JobSystem& js = engine.getJobSystem(); - - /* - * Prepare the scene -- this is where we gather all the objects added to the scene, - * and in particular their world-space AABB. - */ - +CameraInfo FView::computeCameraInfo(FEngine& engine) noexcept { FScene* const scene = getScene(); /* @@ -444,20 +437,31 @@ void FView::prepare(FEngine& engine, DriverApi& driver, ArenaScope& arena, worldOriginScene[3].xyz -= camera->getPosition(); } - // Note: for debugging (i.e. visualize what the camera / objects are doing, using - // the viewing camera), we can set worldOriginScene to identity when mViewingCamera - // is set - mViewingCameraInfo = CameraInfo(*camera, worldOriginScene); + return { *camera, worldOriginScene }; +} + +void FView::prepare(FEngine& engine, DriverApi& driver, ArenaScope& arena, + filament::Viewport const& viewport, CameraInfo const& cameraInfo, + float4 const& userTime, bool needsAlphaChannel) noexcept { + + JobSystem& js = engine.getJobSystem(); + + /* + * Prepare the scene -- this is where we gather all the objects added to the scene, + * and in particular their world-space AABB. + */ + + FScene* const scene = getScene(); mCullingFrustum = Frustum(mat4f{ - mCullingCamera->getCullingProjectionMatrix() * - inverse(worldOriginScene * mCullingCamera->getModelMatrix()) }); + mCullingCamera->getCullingProjectionMatrix() * + inverse(cameraInfo.worldOrigin * mCullingCamera->getModelMatrix()) }); /* * Gather all information needed to render this scene. Apply the world origin to all * objects in the scene. */ - scene->prepare(worldOriginScene, hasVSM()); + scene->prepare(cameraInfo.worldOrigin, hasVSM()); /* * Light culling: runs in parallel with Renderable culling (below) @@ -466,9 +470,9 @@ void FView::prepare(FEngine& engine, DriverApi& driver, ArenaScope& arena, JobSystem::Job* prepareVisibleLightsJob = nullptr; if (scene->getLightData().size() > FScene::DIRECTIONAL_LIGHTS_COUNT) { prepareVisibleLightsJob = js.runAndRetain(js.createJob(nullptr, - [this, &engine, &arena, scene](JobSystem&, JobSystem::Job*) { + [this, &engine, &arena, &cameraInfo, scene](JobSystem&, JobSystem::Job*) { FView::prepareVisibleLights(engine.getLightManager(), arena, - mViewingCameraInfo, mCullingFrustum, scene->getLightData()); + cameraInfo.view, mCullingFrustum, scene->getLightData()); })); } @@ -497,7 +501,7 @@ void FView::prepare(FEngine& engine, DriverApi& driver, ArenaScope& arena, if (prepareVisibleLightsJob) { js.waitAndRelease(prepareVisibleLightsJob); } - prepareShadowing(engine, driver, renderableData, scene->getLightData()); + prepareShadowing(engine, driver, renderableData, scene->getLightData(), cameraInfo); /* * Partition the SoA so that renderables are partitioned w.r.t their visibility into the @@ -567,14 +571,14 @@ void FView::prepare(FEngine& engine, DriverApi& driver, ArenaScope& arena, * Relies on FScene::prepare() and prepareVisibleLights() */ - prepareLighting(engine, driver, arena, viewport); + prepareLighting(engine, driver, arena, viewport, cameraInfo); /* * Update driver state */ mPerViewUniforms.prepareTime(userTime); - mPerViewUniforms.prepareFog(mViewingCameraInfo, mFogOptions); + mPerViewUniforms.prepareFog(cameraInfo.getPosition(), mFogOptions); mPerViewUniforms.prepareTemporalNoise(mTemporalAntiAliasingOptions); mPerViewUniforms.prepareBlending(needsAlphaChannel); @@ -701,10 +705,10 @@ void FView::cleanupRenderPasses() const noexcept { mPerViewUniforms.unbindSamplers(); } -void FView::froxelize(FEngine& engine) const noexcept { +void FView::froxelize(FEngine& engine, mat4f const& viewMatrix) const noexcept { SYSTRACE_CALL(); assert_invariant(mHasDynamicLighting); - mFroxelizer.froxelizeLights(engine, mViewingCameraInfo, mScene->getLightData()); + mFroxelizer.froxelizeLights(engine, viewMatrix, mScene->getLightData()); } void FView::commitUniforms(DriverApi& driver) const noexcept { @@ -759,7 +763,8 @@ void FView::cullRenderables(JobSystem& js, } void FView::prepareVisibleLights(FLightManager const& lcm, ArenaScope& rootArena, - const CameraInfo& camera, Frustum const& frustum, FScene::LightSoa& lightData) noexcept { + mat4f const& viewMatrix, Frustum const& frustum, + FScene::LightSoa& lightData) noexcept { SYSTRACE_CALL(); assert_invariant(lightData.size() > FScene::DIRECTIONAL_LIGHTS_COUNT); @@ -837,7 +842,7 @@ void FView::prepareVisibleLights(FLightManager const& lcm, ArenaScope& rootArena // pre-compute the lights' distance to the camera, for sorting below // - we don't skip the directional light, because we don't care, it's ignored during sorting float4 const* const UTILS_RESTRICT spheres = lightData.data(); - computeLightCameraDistances(distances, camera, spheres, size); + computeLightCameraDistances(distances, viewMatrix, spheres, size); // skip directional light Zip2Iterator b = { lightData.begin(), distances }; @@ -855,15 +860,15 @@ void FView::prepareVisibleLights(FLightManager const& lcm, ArenaScope& rootArena UTILS_ALWAYS_INLINE inline void FView::computeLightCameraDistances( float* UTILS_RESTRICT const distances, - CameraInfo const& UTILS_RESTRICT camera, - float4 const* UTILS_RESTRICT const spheres, size_t count) noexcept { + mat4f const& UTILS_RESTRICT viewMatrix, + float4 const* UTILS_RESTRICT spheres, size_t count) noexcept { // without this, the vectorization is less efficient // we're guaranteed to have a multiple of 4 lights (at least) count = uint32_t(count + 3u) & ~3u; for (size_t i = 0 ; i < count; i++) { const float4 sphere = spheres[i]; - const float4 center = camera.view * sphere.xyz; // camera points towards the -z axis + const float4 center = viewMatrix * sphere.xyz; // camera points towards the -z axis distances[i] = length(center); } } diff --git a/filament/src/details/View.h b/filament/src/details/View.h index 92584d2445..f6a90cc926 100644 --- a/filament/src/details/View.h +++ b/filament/src/details/View.h @@ -51,6 +51,7 @@ #include #include +#include namespace utils { class JobSystem; @@ -118,8 +119,11 @@ public: void terminate(FEngine& engine); + CameraInfo computeCameraInfo(FEngine& engine) noexcept; + void prepare(FEngine& engine, backend::DriverApi& driver, ArenaScope& arena, - Viewport const& viewport, math::float4 const& userTime, bool needsAlphaChannel) noexcept; + filament::Viewport const& viewport, CameraInfo const& cameraInfo, + math::float4 const& userTime, bool needsAlphaChannel) noexcept; void setScene(FScene* scene) { mScene = scene; } FScene const* getScene() const noexcept { return mScene; } @@ -128,8 +132,6 @@ public: void setCullingCamera(FCamera* camera) noexcept { mCullingCamera = camera; } void setViewingCamera(FCamera* camera) noexcept { mViewingCamera = camera; } - CameraInfo const& getCameraInfo() const noexcept { return mViewingCameraInfo; } - void setViewport(Viewport const& viewport) noexcept; Viewport const& getViewport() const noexcept { return mViewport; @@ -166,9 +168,10 @@ public: void prepareCamera(const CameraInfo& camera) const noexcept; void prepareViewport(const Viewport& viewport) const noexcept; void prepareShadowing(FEngine& engine, backend::DriverApi& driver, - FScene::RenderableSoa& renderableData, FScene::LightSoa& lightData) noexcept; - void prepareLighting(FEngine& engine, FEngine::DriverApi& driver, - ArenaScope& arena, Viewport const& viewport) noexcept; + FScene::RenderableSoa& renderableData, FScene::LightSoa& lightData, + CameraInfo const& cameraInfo) noexcept; + void prepareLighting(FEngine& engine, FEngine::DriverApi& driver, ArenaScope& arena, + filament::Viewport const& viewport, CameraInfo const &cameraInfo) noexcept; void prepareSSAO(backend::Handle ssao) const noexcept; void prepareSSR(backend::Handle ssr, float refractionLodOffset, @@ -181,7 +184,7 @@ public: void prepareShadowMap() const noexcept; void cleanupRenderPasses() const noexcept; - void froxelize(FEngine& engine) const noexcept; + void froxelize(FEngine& engine, math::mat4f const& viewMatrix) const noexcept; void commitUniforms(backend::DriverApi& driver) const noexcept; void commitFroxels(backend::DriverApi& driverApi) const noexcept; @@ -461,11 +464,11 @@ private: Frustum const& frustum, FScene::RenderableSoa& renderableData) const noexcept; static void prepareVisibleLights(FLightManager const& lcm, ArenaScope& rootArena, - const CameraInfo& camera, Frustum const& frustum, + math::mat4f const& viewMatrix, Frustum const& frustum, FScene::LightSoa& lightData) noexcept; static inline void computeLightCameraDistances(float* distances, - const CameraInfo& camera, const math::float4* spheres, size_t count) noexcept; + math::mat4f const& viewMatrix, const math::float4* spheres, size_t count) noexcept; static void computeVisibilityMasks( uint8_t visibleLayers, uint8_t const* layers, @@ -500,7 +503,6 @@ private: FCamera* mCullingCamera = nullptr; FCamera* mViewingCamera = nullptr; - CameraInfo mViewingCameraInfo; Frustum mCullingFrustum{}; mutable Froxelizer mFroxelizer;