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:
committed by
Mathias Agopian
parent
1eceab0040
commit
c212dd5bc7
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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]
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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{};
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()) {
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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,
|
||||
¤t.ssr.color, ¤t.ssr.desc);
|
||||
});
|
||||
|
||||
@@ -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
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user