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).
This commit is contained in:
Mathias Agopian
2022-04-18 12:04:18 -07:00
committed by Mathias Agopian
parent 1eceab0040
commit c212dd5bc7
16 changed files with 129 additions and 117 deletions
+6 -6
View File
@@ -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<FScene::LIGHT_INSTANCE>();
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
+2 -2
View File
@@ -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;
+2 -2
View File
@@ -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();
+1 -1
View File
@@ -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;
+10 -9
View File
@@ -531,22 +531,23 @@ FrameGraphId<FrameGraphTexture> 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<FrameGraphTexture> 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]
+7 -4
View File
@@ -74,6 +74,11 @@ void RenderPass::setGeometry(FScene::RenderableSoa const& soa, Range<uint32_t> 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) {
+3 -2
View File
@@ -272,7 +272,7 @@ public:
backend::Handle<backend::HwBufferObject> 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<backend::HwBufferObject> 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{};
+3 -4
View File
@@ -72,7 +72,7 @@ ShadowMap::~ShadowMap() {
void ShadowMap::render(FScene const& scene, utils::Range<uint32_t> 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<float>::lowest(), std::numeric_limits<float>::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);
}
+1 -1
View File
@@ -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
+17 -21
View File
@@ -55,10 +55,9 @@ ShadowMapManager::~ShadowMapManager() {
}
}
ShadowMapManager::ShadowTechnique ShadowMapManager::update(
FEngine& engine, FView& view,
TypedUniformBuffer<ShadowUib>& shadowUb, FScene::RenderableSoa& renderableData,
FScene::LightSoa& lightData) noexcept {
ShadowMapManager::ShadowTechnique ShadowMapManager::update(FEngine& engine, FView& view,
CameraInfo const& cameraInfo, TypedUniformBuffer<ShadowUib>& 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<FrameGraphTexture> 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<FScene::LIGHT_INSTANCE>(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<ShadowUib>& shadowUb) noexcept {
FView& view, CameraInfo const& cameraInfo, FScene::RenderableSoa& renderableData,
FScene::LightSoa& lightData, ShadowMap::SceneInfo& sceneInfo,
TypedUniformBuffer<ShadowUib>& 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()) {
+11 -9
View File
@@ -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<ShadowUib>& shadowUb,
ShadowMapManager::ShadowTechnique update(FEngine& engine, FView& view,
CameraInfo const& cameraInfo, TypedUniformBuffer<ShadowUib>& 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<ShadowMap*>(&mShadowMapCache[CONFIG_MAX_SHADOW_CASCADES + spot]));
return std::launder(reinterpret_cast<ShadowMap*>(
&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<ShadowUib>& shadowUb) noexcept;
ShadowMapManager::ShadowTechnique updateSpotShadowMaps(FEngine& engine,
FView& view, CameraInfo const& cameraInfo, FScene::RenderableSoa& renderableData,
FScene::LightSoa& lightData, ShadowMap::SceneInfo& sceneInfo,
TypedUniformBuffer<ShadowUib>& shadowUb) noexcept;
void calculateTextureRequirements(FEngine& engine, FView& view, FScene::LightSoa& lightData) noexcept;
+1 -1
View File
@@ -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
+1 -2
View File
@@ -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)
+11 -7
View File
@@ -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<FrameGraphTexture> 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<ExportSSRHistoryData>("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,
&current.ssr.color, &current.ssr.desc);
});
+41 -36
View File
@@ -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<FScene::POSITION_RADIUS>();
computeLightCameraDistances(distances, camera, spheres, size);
computeLightCameraDistances(distances, viewMatrix, spheres, size);
// skip directional light
Zip2Iterator<FScene::LightSoa::iterator, float*> 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);
}
}
+12 -10
View File
@@ -51,6 +51,7 @@
#include <utils/Slice.h>
#include <math/scalar.h>
#include <math/mat4.h>
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<backend::HwTexture> ssao) const noexcept;
void prepareSSR(backend::Handle<backend::HwTexture> 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;