Graphics: Move shadow-mapping related code to LightShadow classes

This commit is contained in:
SirLynix
2022-11-26 18:33:12 +01:00
committed by Jérôme Leclercq
parent ec3bc45544
commit 1768f20365
27 changed files with 496 additions and 160 deletions

View File

@@ -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);