Graphics: Move shadow-mapping related code to LightShadow classes
This commit is contained in:
committed by
Jérôme Leclercq
parent
ec3bc45544
commit
1768f20365
@@ -18,7 +18,7 @@ namespace Nz
|
||||
return m_renderMask;
|
||||
}
|
||||
|
||||
const RenderTarget& Camera::GetRenderTarget()
|
||||
const RenderTarget& Camera::GetRenderTarget() const
|
||||
{
|
||||
if (!m_renderTarget)
|
||||
throw std::runtime_error("no rendertarget set");
|
||||
|
||||
@@ -129,10 +129,10 @@ namespace Nz
|
||||
it->second.usedCount++;
|
||||
}
|
||||
|
||||
FramePass& DepthPipelinePass::RegisterToFrameGraph(FrameGraph& frameGraph, std::size_t depthBufferIndex)
|
||||
FramePass& DepthPipelinePass::RegisterToFrameGraph(FrameGraph& frameGraph, std::size_t outputAttachment)
|
||||
{
|
||||
FramePass& depthPrepass = frameGraph.AddPass(m_passName);
|
||||
depthPrepass.SetDepthStencilOutput(depthBufferIndex);
|
||||
depthPrepass.SetDepthStencilOutput(outputAttachment);
|
||||
depthPrepass.SetDepthStencilClear(1.f, 0);
|
||||
|
||||
depthPrepass.SetExecutionCallback([&]()
|
||||
|
||||
@@ -30,6 +30,11 @@ namespace Nz
|
||||
AccessByOffset<Vector2f&>(data, lightOffset.lightMemberOffsets.shadowMapSize) = Vector2f(-1.f, -1.f);
|
||||
}
|
||||
|
||||
std::unique_ptr<LightShadowData> DirectionalLight::InstanciateShadowData(FramePipeline& pipeline, ElementRendererRegistry& elementRegistry) const
|
||||
{
|
||||
return nullptr; //< TODO
|
||||
}
|
||||
|
||||
void DirectionalLight::UpdateTransform(const Vector3f& /*position*/, const Quaternionf& rotation, const Vector3f& /*scale*/)
|
||||
{
|
||||
UpdateRotation(rotation);
|
||||
|
||||
@@ -44,11 +44,67 @@ namespace Nz
|
||||
m_viewerPool.Clear();
|
||||
}
|
||||
|
||||
std::size_t ForwardFramePipeline::RegisterLight(std::shared_ptr<Light> light, UInt32 renderMask)
|
||||
const std::vector<Nz::FramePipelinePass::VisibleRenderable>& ForwardFramePipeline::FrustumCull(const Frustumf& frustum, UInt32 mask, std::size_t& visibilityHash) const
|
||||
{
|
||||
auto CombineHash = [](std::size_t currentHash, std::size_t newHash)
|
||||
{
|
||||
return currentHash * 23 + newHash;
|
||||
};
|
||||
|
||||
m_visibleRenderables.clear();
|
||||
for (const RenderableData& renderableData : m_renderablePool)
|
||||
{
|
||||
if ((mask & renderableData.renderMask) == 0)
|
||||
continue;
|
||||
|
||||
const WorldInstancePtr& worldInstance = m_worldInstances.RetrieveFromIndex(renderableData.worldInstanceIndex)->worldInstance;
|
||||
|
||||
// Get global AABB
|
||||
BoundingVolumef boundingVolume(renderableData.renderable->GetAABB());
|
||||
boundingVolume.Update(worldInstance->GetWorldMatrix());
|
||||
|
||||
if (!frustum.Contains(boundingVolume))
|
||||
continue;
|
||||
|
||||
auto& visibleRenderable = m_visibleRenderables.emplace_back();
|
||||
visibleRenderable.instancedRenderable = renderableData.renderable;
|
||||
visibleRenderable.scissorBox = renderableData.scissorBox;
|
||||
visibleRenderable.worldInstance = worldInstance.get();
|
||||
|
||||
if (renderableData.skeletonInstanceIndex != NoSkeletonInstance)
|
||||
visibleRenderable.skeletonInstance = m_skeletonInstances.RetrieveFromIndex(renderableData.skeletonInstanceIndex)->skeleton.get();
|
||||
else
|
||||
visibleRenderable.skeletonInstance = nullptr;
|
||||
|
||||
visibilityHash = CombineHash(visibilityHash, std::hash<const void*>()(&renderableData));
|
||||
}
|
||||
|
||||
return m_visibleRenderables;
|
||||
}
|
||||
|
||||
void ForwardFramePipeline::ForEachRegisteredMaterialInstance(FunctionRef<void(const MaterialInstance& materialInstance)> callback)
|
||||
{
|
||||
for (RenderableData& renderable : m_renderablePool)
|
||||
{
|
||||
std::size_t matCount = renderable.renderable->GetMaterialCount();
|
||||
for (std::size_t j = 0; j < matCount; ++j)
|
||||
{
|
||||
if (MaterialInstance* mat = renderable.renderable->GetMaterial(j).get())
|
||||
callback(*mat);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ForwardFramePipeline::QueueTransfer(TransferInterface* transfer)
|
||||
{
|
||||
m_transferSet.insert(transfer);
|
||||
}
|
||||
|
||||
std::size_t ForwardFramePipeline::RegisterLight(const Light* light, UInt32 renderMask)
|
||||
{
|
||||
std::size_t lightIndex;
|
||||
LightData* lightData = m_lightPool.Allocate(lightIndex);
|
||||
lightData->light = std::move(light);
|
||||
lightData->light = light;
|
||||
lightData->renderMask = renderMask;
|
||||
lightData->onLightInvalidated.Connect(lightData->light->OnLightDataInvalided, [=](Light*)
|
||||
{
|
||||
@@ -65,11 +121,14 @@ namespace Nz
|
||||
lightData->onLightShadowCastingChanged.Connect(lightData->light->OnLightShadowCastingChanged, [=](Light* light, bool isCastingShadows)
|
||||
{
|
||||
if (isCastingShadows)
|
||||
{
|
||||
m_shadowCastingLights.UnboundedSet(lightIndex);
|
||||
lightData->shadowData = light->InstanciateShadowData(*this, m_elementRegistry);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_shadowCastingLights.Reset(lightIndex);
|
||||
lightData->pass.reset();
|
||||
lightData->shadowData.reset();
|
||||
}
|
||||
|
||||
m_rebuildFrameGraph = true;
|
||||
@@ -78,6 +137,7 @@ namespace Nz
|
||||
if (lightData->light->IsShadowCaster())
|
||||
{
|
||||
m_shadowCastingLights.UnboundedSet(lightIndex);
|
||||
lightData->shadowData = light->InstanciateShadowData(*this, m_elementRegistry);
|
||||
m_rebuildFrameGraph = true;
|
||||
}
|
||||
|
||||
@@ -215,7 +275,7 @@ namespace Nz
|
||||
|
||||
const Light* ForwardFramePipeline::RetrieveLight(std::size_t lightIndex) const
|
||||
{
|
||||
return m_lightPool.RetrieveFromIndex(lightIndex)->light.get();
|
||||
return m_lightPool.RetrieveFromIndex(lightIndex)->light;
|
||||
}
|
||||
|
||||
const Texture* ForwardFramePipeline::RetrieveLightShadowmap(std::size_t lightIndex) const
|
||||
@@ -223,8 +283,7 @@ namespace Nz
|
||||
if (!m_shadowCastingLights.UnboundedTest(lightIndex))
|
||||
return nullptr;
|
||||
|
||||
std::size_t shadowmapIndex = m_lightPool.RetrieveFromIndex(lightIndex)->shadowMapAttachmentIndex;
|
||||
return m_bakedFrameGraph.GetAttachmentTexture(shadowmapIndex).get();
|
||||
return m_lightPool.RetrieveFromIndex(lightIndex)->shadowData->RetrieveLightShadowmap(m_bakedFrameGraph);
|
||||
}
|
||||
|
||||
void ForwardFramePipeline::Render(RenderFrame& renderFrame)
|
||||
@@ -279,51 +338,11 @@ namespace Nz
|
||||
builder.EndDebugRegion();
|
||||
}, QueueType::Transfer);
|
||||
|
||||
auto CombineHash = [](std::size_t currentHash, std::size_t newHash)
|
||||
{
|
||||
return currentHash * 23 + newHash;
|
||||
};
|
||||
|
||||
// Shadow map handling
|
||||
for (std::size_t i = m_shadowCastingLights.FindFirst(); i != m_shadowCastingLights.npos; i = m_shadowCastingLights.FindNext(i))
|
||||
{
|
||||
LightData* lightData = m_lightPool.RetrieveFromIndex(i);
|
||||
|
||||
const Matrix4f& viewProjMatrix = lightData->camera->GetViewerInstance().GetViewProjMatrix();
|
||||
|
||||
Frustumf frustum = Frustumf::Extract(viewProjMatrix);
|
||||
|
||||
std::size_t visibilityHash = 5U;
|
||||
|
||||
m_visibleRenderables.clear();
|
||||
for (const RenderableData& renderableData : m_renderablePool)
|
||||
{
|
||||
if ((lightData->renderMask & renderableData.renderMask) == 0)
|
||||
continue;
|
||||
|
||||
WorldInstancePtr& worldInstance = m_worldInstances.RetrieveFromIndex(renderableData.worldInstanceIndex)->worldInstance;
|
||||
|
||||
// Get global AABB
|
||||
BoundingVolumef boundingVolume(renderableData.renderable->GetAABB());
|
||||
boundingVolume.Update(worldInstance->GetWorldMatrix());
|
||||
|
||||
if (!frustum.Contains(boundingVolume))
|
||||
continue;
|
||||
|
||||
auto& visibleRenderable = m_visibleRenderables.emplace_back();
|
||||
visibleRenderable.instancedRenderable = renderableData.renderable;
|
||||
visibleRenderable.scissorBox = renderableData.scissorBox;
|
||||
visibleRenderable.worldInstance = worldInstance.get();
|
||||
|
||||
if (renderableData.skeletonInstanceIndex != NoSkeletonInstance)
|
||||
visibleRenderable.skeletonInstance = m_skeletonInstances.RetrieveFromIndex(renderableData.skeletonInstanceIndex)->skeleton.get();
|
||||
else
|
||||
visibleRenderable.skeletonInstance = nullptr;
|
||||
|
||||
visibilityHash = CombineHash(visibilityHash, std::hash<const void*>()(&renderableData));
|
||||
}
|
||||
|
||||
lightData->pass->Prepare(renderFrame, frustum, m_visibleRenderables, visibilityHash);
|
||||
lightData->shadowData->PrepareRendering(renderFrame);
|
||||
}
|
||||
|
||||
// Render queues handling
|
||||
@@ -335,36 +354,8 @@ namespace Nz
|
||||
const Matrix4f& viewProjMatrix = viewerData.viewer->GetViewerInstance().GetViewProjMatrix();
|
||||
|
||||
Frustumf frustum = Frustumf::Extract(viewProjMatrix);
|
||||
|
||||
std::size_t visibilityHash = 5U;
|
||||
|
||||
m_visibleRenderables.clear();
|
||||
for (const RenderableData& renderableData : m_renderablePool)
|
||||
{
|
||||
if ((renderMask & renderableData.renderMask) == 0)
|
||||
continue;
|
||||
|
||||
WorldInstancePtr& worldInstance = m_worldInstances.RetrieveFromIndex(renderableData.worldInstanceIndex)->worldInstance;
|
||||
|
||||
// Get global AABB
|
||||
BoundingVolumef boundingVolume(renderableData.renderable->GetAABB());
|
||||
boundingVolume.Update(worldInstance->GetWorldMatrix());
|
||||
|
||||
if (!frustum.Contains(boundingVolume))
|
||||
continue;
|
||||
|
||||
auto& visibleRenderable = m_visibleRenderables.emplace_back();
|
||||
visibleRenderable.instancedRenderable = renderableData.renderable;
|
||||
visibleRenderable.scissorBox = renderableData.scissorBox;
|
||||
visibleRenderable.worldInstance = worldInstance.get();
|
||||
|
||||
if (renderableData.skeletonInstanceIndex != NoSkeletonInstance)
|
||||
visibleRenderable.skeletonInstance = m_skeletonInstances.RetrieveFromIndex(renderableData.skeletonInstanceIndex)->skeleton.get();
|
||||
else
|
||||
visibleRenderable.skeletonInstance = nullptr;
|
||||
|
||||
visibilityHash = CombineHash(visibilityHash, std::hash<const void*>()(&renderableData));
|
||||
}
|
||||
std::size_t visibilityHash = 5;
|
||||
const auto& visibleRenderables = FrustumCull(frustum, renderMask, visibilityHash);
|
||||
|
||||
// Lights update don't trigger a rebuild of the depth pre-pass
|
||||
std::size_t depthVisibilityHash = visibilityHash;
|
||||
@@ -381,14 +372,20 @@ namespace Nz
|
||||
if (renderMask & lightData.renderMask && frustum.Contains(boundingVolume))
|
||||
{
|
||||
m_visibleLights.push_back(lightIndex);
|
||||
visibilityHash = CombineHash(visibilityHash, std::hash<const void*>()(lightData.light.get()));
|
||||
|
||||
auto CombineHash = [](std::size_t currentHash, std::size_t newHash)
|
||||
{
|
||||
return currentHash * 23 + newHash;
|
||||
};
|
||||
|
||||
visibilityHash = CombineHash(visibilityHash, std::hash<const void*>()(lightData.light));
|
||||
}
|
||||
}
|
||||
|
||||
if (viewerData.depthPrepass)
|
||||
viewerData.depthPrepass->Prepare(renderFrame, frustum, m_visibleRenderables, depthVisibilityHash);
|
||||
viewerData.depthPrepass->Prepare(renderFrame, frustum, visibleRenderables, depthVisibilityHash);
|
||||
|
||||
viewerData.forwardPass->Prepare(renderFrame, frustum, m_visibleRenderables, m_visibleLights, visibilityHash);
|
||||
viewerData.forwardPass->Prepare(renderFrame, frustum, visibleRenderables, m_visibleLights, visibilityHash);
|
||||
|
||||
viewerData.debugDrawPass->Prepare(renderFrame);
|
||||
}
|
||||
@@ -571,60 +568,7 @@ namespace Nz
|
||||
for (std::size_t i = m_shadowCastingLights.FindFirst(); i != m_shadowCastingLights.npos; i = m_shadowCastingLights.FindNext(i))
|
||||
{
|
||||
LightData* lightData = m_lightPool.RetrieveFromIndex(i);
|
||||
|
||||
assert(lightData->light->GetLightType() == UnderlyingCast(BasicLightType::Spot));
|
||||
SpotLight& spotLight = SafeCast<SpotLight&>(*lightData->light);
|
||||
|
||||
PixelFormat shadowMapFormat = lightData->light->GetShadowMapFormat();
|
||||
UInt32 shadowMapSize = lightData->light->GetShadowMapSize();
|
||||
|
||||
lightData->shadowMapAttachmentIndex = frameGraph.AddAttachment({
|
||||
"Shadowmap",
|
||||
shadowMapFormat,
|
||||
FramePassAttachmentSize::Fixed,
|
||||
shadowMapSize, shadowMapSize,
|
||||
});
|
||||
|
||||
if (!lightData->camera)
|
||||
{
|
||||
lightData->camera = std::make_unique<Camera>(nullptr);
|
||||
ViewerInstance& viewerInstance = lightData->camera->GetViewerInstance();
|
||||
viewerInstance.OnTransferRequired.Connect([this](TransferInterface* transferInterface)
|
||||
{
|
||||
m_transferSet.insert(transferInterface);
|
||||
});
|
||||
|
||||
lightData->camera->UpdateFOV(spotLight.GetOuterAngle() * 2.f);
|
||||
lightData->camera->UpdateZNear(0.01f);
|
||||
lightData->camera->UpdateZFar(spotLight.GetRadius());
|
||||
lightData->camera->UpdateViewport(Recti(0, 0, SafeCast<int>(shadowMapSize), SafeCast<int>(shadowMapSize)));
|
||||
|
||||
lightData->onLightTransformInvalidated.Connect(lightData->light->OnLightTransformInvalided, [lightData](Light* light)
|
||||
{
|
||||
SpotLight& spotLight = SafeCast<SpotLight&>(*light);
|
||||
ViewerInstance& viewerInstance = lightData->camera->GetViewerInstance();
|
||||
viewerInstance.UpdateViewMatrix(Nz::Matrix4f::TransformInverse(spotLight.GetPosition(), spotLight.GetRotation()));
|
||||
});
|
||||
viewerInstance.UpdateViewMatrix(Nz::Matrix4f::TransformInverse(spotLight.GetPosition(), spotLight.GetRotation()));
|
||||
}
|
||||
|
||||
if (!lightData->pass)
|
||||
{
|
||||
std::size_t shadowPassIndex = Graphics::Instance()->GetMaterialPassRegistry().GetPassIndex("ShadowPass");
|
||||
|
||||
lightData->pass = std::make_unique<DepthPipelinePass>(*this, m_elementRegistry, lightData->camera.get(), shadowPassIndex, "Spot shadowmap");
|
||||
for (RenderableData& renderable : m_renderablePool)
|
||||
{
|
||||
std::size_t matCount = renderable.renderable->GetMaterialCount();
|
||||
for (std::size_t j = 0; j < matCount; ++j)
|
||||
{
|
||||
if (MaterialInstance* mat = renderable.renderable->GetMaterial(j).get())
|
||||
lightData->pass->RegisterMaterialInstance(*mat);
|
||||
}
|
||||
}
|
||||
|
||||
lightData->pass->RegisterToFrameGraph(frameGraph, lightData->shadowMapAttachmentIndex);
|
||||
}
|
||||
lightData->shadowData->RegisterToFrameGraph(frameGraph);
|
||||
}
|
||||
|
||||
for (auto& viewerData : m_viewerPool)
|
||||
@@ -648,7 +592,7 @@ namespace Nz
|
||||
for (std::size_t i = m_shadowCastingLights.FindFirst(); i != m_shadowCastingLights.npos; i = m_shadowCastingLights.FindNext(i))
|
||||
{
|
||||
LightData* lightData = m_lightPool.RetrieveFromIndex(i);
|
||||
forwardPass.AddInput(lightData->shadowMapAttachmentIndex);
|
||||
lightData->shadowData->RegisterPassInputs(forwardPass);
|
||||
}
|
||||
|
||||
viewerData.debugDrawPass->RegisterToFrameGraph(frameGraph, viewerData.forwardColorAttachment, viewerData.debugColorAttachment);
|
||||
|
||||
@@ -165,8 +165,8 @@ namespace Nz
|
||||
perElementData.lightCount = lightCount;
|
||||
perElementData.lightUniformBuffer = lightUboView;
|
||||
|
||||
for (std::size_t i = 0; i < lightCount; ++i)
|
||||
perElementData.shadowMaps[i] = m_pipeline.RetrieveLightShadowmap(m_renderableLights[i].lightIndex);
|
||||
for (std::size_t j = 0; j < lightCount; ++j)
|
||||
perElementData.shadowMaps[j] = m_pipeline.RetrieveLightShadowmap(m_renderableLights[j].lightIndex);
|
||||
|
||||
m_lightPerRenderElement.emplace(element, perElementData);
|
||||
}
|
||||
@@ -240,18 +240,18 @@ namespace Nz
|
||||
auto& renderStates = m_renderStates.emplace_back();
|
||||
renderStates.lightData = lightData.lightUniformBuffer;
|
||||
|
||||
for (std::size_t i = 0; i < lightData.lightCount; ++i)
|
||||
for (std::size_t j = 0; j < lightData.lightCount; ++j)
|
||||
{
|
||||
const Texture* texture = lightData.shadowMaps[i];
|
||||
const Texture* texture = lightData.shadowMaps[j];
|
||||
if (!texture)
|
||||
continue;
|
||||
|
||||
if (texture->GetType() == ImageType::E2D)
|
||||
renderStates.shadowMaps2D[i] = texture;
|
||||
renderStates.shadowMaps2D[j] = texture;
|
||||
else
|
||||
{
|
||||
assert(texture->GetType() == ImageType::Cubemap);
|
||||
renderStates.shadowMapsCube[i] = texture;
|
||||
renderStates.shadowMapsCube[j] = texture;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
11
src/Nazara/Graphics/LightShadowData.cpp
Normal file
11
src/Nazara/Graphics/LightShadowData.cpp
Normal file
@@ -0,0 +1,11 @@
|
||||
// Copyright (C) 2022 Jérôme "Lynix" Leclercq (lynix680@gmail.com)
|
||||
// This file is part of the "Nazara Engine - Graphics module"
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#include <Nazara/Graphics/LightShadowData.hpp>
|
||||
#include <Nazara/Graphics/Debug.hpp>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
LightShadowData::~LightShadowData() = default;
|
||||
}
|
||||
@@ -30,6 +30,11 @@ namespace Nz
|
||||
AccessByOffset<Vector2f&>(data, lightOffset.lightMemberOffsets.shadowMapSize) = Vector2f(-1.f, -1.f);
|
||||
}
|
||||
|
||||
std::unique_ptr<LightShadowData> PointLight::InstanciateShadowData(FramePipeline& pipeline, ElementRendererRegistry& elementRegistry) const
|
||||
{
|
||||
return nullptr; //< TODO
|
||||
}
|
||||
|
||||
void PointLight::UpdateTransform(const Vector3f& position, const Quaternionf& /*rotation*/, const Vector3f& /*scale*/)
|
||||
{
|
||||
UpdatePosition(position);
|
||||
|
||||
39
src/Nazara/Graphics/ShadowViewer.cpp
Normal file
39
src/Nazara/Graphics/ShadowViewer.cpp
Normal file
@@ -0,0 +1,39 @@
|
||||
// Copyright (C) 2022 Jérôme "Lynix" Leclercq (lynix680@gmail.com)
|
||||
// This file is part of the "Nazara Engine - Graphics module"
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#include <Nazara/Graphics/ShadowViewer.hpp>
|
||||
#include <Nazara/Graphics/Debug.hpp>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
const Color& ShadowViewer::GetClearColor() const
|
||||
{
|
||||
throw std::runtime_error("no clear color");
|
||||
}
|
||||
|
||||
UInt32 ShadowViewer::GetRenderMask() const
|
||||
{
|
||||
return m_renderMask;
|
||||
}
|
||||
|
||||
const RenderTarget& ShadowViewer::GetRenderTarget() const
|
||||
{
|
||||
throw std::runtime_error("no render target");
|
||||
}
|
||||
|
||||
ViewerInstance& ShadowViewer::GetViewerInstance()
|
||||
{
|
||||
return m_viewerInstance;
|
||||
}
|
||||
|
||||
const ViewerInstance& ShadowViewer::GetViewerInstance() const
|
||||
{
|
||||
return m_viewerInstance;
|
||||
}
|
||||
|
||||
const Recti& ShadowViewer::GetViewport() const
|
||||
{
|
||||
return m_viewport;
|
||||
}
|
||||
}
|
||||
@@ -6,6 +6,7 @@
|
||||
#include <Nazara/Graphics/Enums.hpp>
|
||||
#include <Nazara/Graphics/Graphics.hpp>
|
||||
#include <Nazara/Graphics/PredefinedShaderStructs.hpp>
|
||||
#include <Nazara/Graphics/SpotLightShadowData.hpp>
|
||||
#include <Nazara/Math/Vector2.hpp>
|
||||
#include <Nazara/Math/Vector3.hpp>
|
||||
#include <Nazara/Math/Vector4.hpp>
|
||||
@@ -33,6 +34,11 @@ namespace Nz
|
||||
AccessByOffset<Matrix4f&>(data, lightOffset.lightMemberOffsets.viewProjMatrix) = m_viewProjMatrix;
|
||||
}
|
||||
|
||||
std::unique_ptr<LightShadowData> SpotLight::InstanciateShadowData(FramePipeline& pipeline, ElementRendererRegistry& elementRegistry) const
|
||||
{
|
||||
return std::make_unique<SpotLightShadowData>(pipeline, elementRegistry, *this);
|
||||
}
|
||||
|
||||
void SpotLight::UpdateTransform(const Vector3f& position, const Quaternionf& rotation, const Vector3f& /*scale*/)
|
||||
{
|
||||
m_position = position; //< don't call UpdatePosition to prevent double update
|
||||
|
||||
99
src/Nazara/Graphics/SpotLightShadowData.cpp
Normal file
99
src/Nazara/Graphics/SpotLightShadowData.cpp
Normal file
@@ -0,0 +1,99 @@
|
||||
// Copyright (C) 2022 Jérôme "Lynix" Leclercq (lynix680@gmail.com)
|
||||
// This file is part of the "Nazara Engine - Graphics module"
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#include <Nazara/Graphics/SpotLightShadowData.hpp>
|
||||
#include <Nazara/Graphics/BakedFrameGraph.hpp>
|
||||
#include <Nazara/Graphics/FrameGraph.hpp>
|
||||
#include <Nazara/Graphics/FramePipeline.hpp>
|
||||
#include <Nazara/Graphics/Graphics.hpp>
|
||||
#include <Nazara/Graphics/SpotLight.hpp>
|
||||
#include <Nazara/Graphics/Debug.hpp>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
SpotLightShadowData::SpotLightShadowData(FramePipeline& pipeline, ElementRendererRegistry& elementRegistry, const SpotLight& light) :
|
||||
m_pipeline(pipeline),
|
||||
m_light(light),
|
||||
m_viewer(Recti(0, 0, 1, 1), 0xFFFFFFFF)
|
||||
{
|
||||
UInt32 shadowMapSize = light.GetShadowMapSize();
|
||||
m_viewer.UpdateViewport(Recti(0, 0, SafeCast<int>(shadowMapSize), SafeCast<int>(shadowMapSize)));
|
||||
|
||||
ViewerInstance& viewerInstance = m_viewer.GetViewerInstance();
|
||||
viewerInstance.UpdateProjectionMatrix(Matrix4f::Perspective(m_light.GetOuterAngle() * 2.f, 1.f, 0.01f, m_light.GetRadius()));
|
||||
|
||||
m_onLightShadowMapSettingChange.Connect(m_light.OnLightShadowMapSettingChange, [this](Light* /*light*/, PixelFormat /*newPixelFormat*/, UInt32 newSize)
|
||||
{
|
||||
m_viewer.UpdateViewport(Recti(0, 0, SafeCast<int>(newSize), SafeCast<int>(newSize)));
|
||||
});
|
||||
|
||||
m_onLightTransformInvalidated.Connect(m_light.OnLightTransformInvalided, [this]([[maybe_unused]] Light* light)
|
||||
{
|
||||
assert(&m_light == light);
|
||||
|
||||
ViewerInstance& viewerInstance = m_viewer.GetViewerInstance();
|
||||
viewerInstance.UpdateEyePosition(m_light.GetPosition());
|
||||
viewerInstance.UpdateViewMatrix(Nz::Matrix4f::TransformInverse(m_light.GetPosition(), m_light.GetRotation()));
|
||||
|
||||
m_pipeline.QueueTransfer(&viewerInstance);
|
||||
});
|
||||
viewerInstance.UpdateEyePosition(m_light.GetPosition());
|
||||
viewerInstance.UpdateViewMatrix(Nz::Matrix4f::TransformInverse(m_light.GetPosition(), m_light.GetRotation()));
|
||||
m_pipeline.QueueTransfer(&viewerInstance);
|
||||
|
||||
std::size_t shadowPassIndex = Graphics::Instance()->GetMaterialPassRegistry().GetPassIndex("ShadowPass");
|
||||
|
||||
m_depthPass.emplace(m_pipeline, elementRegistry, &m_viewer, shadowPassIndex, "Spotlight shadow mapping");
|
||||
m_pipeline.ForEachRegisteredMaterialInstance([this](const MaterialInstance& matInstance)
|
||||
{
|
||||
m_depthPass->RegisterMaterialInstance(matInstance);
|
||||
});
|
||||
}
|
||||
|
||||
void SpotLightShadowData::PrepareRendering(RenderFrame& renderFrame)
|
||||
{
|
||||
const Matrix4f& viewProjMatrix = m_viewer.GetViewerInstance().GetViewProjMatrix();
|
||||
|
||||
Frustumf frustum = Frustumf::Extract(viewProjMatrix);
|
||||
|
||||
std::size_t visibilityHash = 5U;
|
||||
const auto& visibleRenderables = m_pipeline.FrustumCull(frustum, 0xFFFFFFFF, visibilityHash);
|
||||
|
||||
m_depthPass->Prepare(renderFrame, frustum, visibleRenderables, visibilityHash);
|
||||
}
|
||||
|
||||
void SpotLightShadowData::RegisterMaterialInstance(const MaterialInstance& matInstance)
|
||||
{
|
||||
m_depthPass->RegisterMaterialInstance(matInstance);
|
||||
}
|
||||
|
||||
void SpotLightShadowData::RegisterPassInputs(FramePass& pass)
|
||||
{
|
||||
pass.AddInput(m_attachmentIndex);
|
||||
}
|
||||
|
||||
void SpotLightShadowData::RegisterToFrameGraph(FrameGraph& frameGraph)
|
||||
{
|
||||
UInt32 shadowMapSize = m_light.GetShadowMapSize();
|
||||
|
||||
m_attachmentIndex = frameGraph.AddAttachment({
|
||||
"Shadowmap",
|
||||
m_light.GetShadowMapFormat(),
|
||||
FramePassAttachmentSize::Fixed,
|
||||
shadowMapSize, shadowMapSize,
|
||||
});
|
||||
|
||||
m_depthPass->RegisterToFrameGraph(frameGraph, m_attachmentIndex);
|
||||
}
|
||||
|
||||
const Nz::Texture* SpotLightShadowData::RetrieveLightShadowmap(const BakedFrameGraph& bakedGraph) const
|
||||
{
|
||||
return bakedGraph.GetAttachmentTexture(m_attachmentIndex).get();
|
||||
}
|
||||
|
||||
void SpotLightShadowData::UnregisterMaterialInstance(const MaterialInstance& matInstance)
|
||||
{
|
||||
m_depthPass->UnregisterMaterialInstance(matInstance);
|
||||
}
|
||||
}
|
||||
@@ -378,7 +378,7 @@ namespace Nz
|
||||
return;
|
||||
|
||||
const auto& lightEntry = light->GetLightEntry(lightIndex);
|
||||
lightEntity->lightIndices[lightIndex] = m_pipeline->RegisterLight(lightEntry.light, lightEntry.renderMask);
|
||||
lightEntity->lightIndices[lightIndex] = m_pipeline->RegisterLight(lightEntry.light.get(), lightEntry.renderMask);
|
||||
});
|
||||
|
||||
lightEntity->onLightDetach.Connect(entityLight.OnLightDetach, [this, lightEntity](LightComponent* light, std::size_t lightIndex)
|
||||
@@ -413,7 +413,7 @@ namespace Nz
|
||||
if (!lightEntry.light)
|
||||
continue;
|
||||
|
||||
lightEntity->lightIndices[lightIndex] = m_pipeline->RegisterLight(lightEntry.light, lightEntry.renderMask);
|
||||
lightEntity->lightIndices[lightIndex] = m_pipeline->RegisterLight(lightEntry.light.get(), lightEntry.renderMask);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -515,7 +515,7 @@ namespace Nz
|
||||
if (!lightEntry.light)
|
||||
continue;
|
||||
|
||||
lightEntity->lightIndices[renderableIndex] = m_pipeline->RegisterLight(lightEntry.light, lightEntry.renderMask);
|
||||
lightEntity->lightIndices[renderableIndex] = m_pipeline->RegisterLight(lightEntry.light.get(), lightEntry.renderMask);
|
||||
}
|
||||
}
|
||||
m_newlyVisibleGfxEntities.clear();
|
||||
|
||||
Reference in New Issue
Block a user