Add shadow mapping (wip)
This commit is contained in:
committed by
Jérôme Leclercq
parent
be9fba3190
commit
4a10c1f8fe
@@ -131,8 +131,8 @@ namespace Nz
|
||||
|
||||
bool BakedFrameGraph::Resize(RenderFrame& renderFrame)
|
||||
{
|
||||
auto [width, height] = renderFrame.GetSize();
|
||||
if (m_width == width && m_height == height)
|
||||
auto [frameWidth, frameHeight] = renderFrame.GetSize();
|
||||
if (m_width == frameWidth && m_height == frameHeight)
|
||||
return false;
|
||||
|
||||
const std::shared_ptr<RenderDevice>& renderDevice = Graphics::Instance()->GetRenderDevice();
|
||||
@@ -151,10 +151,18 @@ namespace Nz
|
||||
{
|
||||
TextureInfo textureCreationParams;
|
||||
textureCreationParams.type = ImageType::E2D;
|
||||
textureCreationParams.width = textureData.width * width / 100'000;
|
||||
textureCreationParams.height = textureData.height * height / 100'000;
|
||||
textureCreationParams.usageFlags = textureData.usage;
|
||||
textureCreationParams.pixelFormat = textureData.format;
|
||||
if (textureData.hasFixedSize)
|
||||
{
|
||||
textureCreationParams.width = textureData.width;
|
||||
textureCreationParams.height = textureData.height;
|
||||
}
|
||||
else
|
||||
{
|
||||
textureCreationParams.width = textureData.width * frameWidth / 100'000;
|
||||
textureCreationParams.height = textureData.height * frameHeight / 100'000;
|
||||
}
|
||||
|
||||
textureData.texture = renderDevice->InstantiateTexture(textureCreationParams);
|
||||
if (!textureData.name.empty())
|
||||
@@ -173,12 +181,22 @@ namespace Nz
|
||||
auto& textureData = m_textures[textureId];
|
||||
textures.push_back(textureData.texture);
|
||||
|
||||
framebufferWidth = std::min(framebufferWidth, textureData.width);
|
||||
framebufferHeight = std::min(framebufferHeight, textureData.height);
|
||||
}
|
||||
unsigned int width;
|
||||
unsigned int height;
|
||||
if (textureData.hasFixedSize)
|
||||
{
|
||||
width = textureData.width;
|
||||
height = textureData.height;
|
||||
}
|
||||
else
|
||||
{
|
||||
width = frameWidth * textureData.width / 100'000;
|
||||
height = frameHeight * textureData.height / 100'000;
|
||||
}
|
||||
|
||||
framebufferWidth = framebufferWidth * width / 100'000;
|
||||
framebufferHeight = framebufferHeight * height / 100'000;
|
||||
framebufferWidth = std::min(framebufferWidth, width);
|
||||
framebufferHeight = std::min(framebufferHeight, height);
|
||||
}
|
||||
|
||||
passData.renderRect.Set(0, 0, int(framebufferWidth), int(framebufferHeight));
|
||||
|
||||
@@ -189,8 +207,8 @@ namespace Nz
|
||||
passData.forceCommandBufferRegeneration = true;
|
||||
}
|
||||
|
||||
m_width = width;
|
||||
m_height = height;
|
||||
m_width = frameWidth;
|
||||
m_height = frameHeight;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ namespace Nz
|
||||
debugDrawer.Prepare(renderFrame);
|
||||
}
|
||||
|
||||
void DebugDrawPipelinePass::RegisterToFrameGraph(FrameGraph& frameGraph, std::size_t inputColorBufferIndex, std::size_t outputColorBufferIndex)
|
||||
FramePass& DebugDrawPipelinePass::RegisterToFrameGraph(FrameGraph& frameGraph, std::size_t inputColorBufferIndex, std::size_t outputColorBufferIndex)
|
||||
{
|
||||
FramePass& debugDrawPass = frameGraph.AddPass("Debug draw pass");
|
||||
debugDrawPass.AddInput(inputColorBufferIndex);
|
||||
@@ -47,5 +47,7 @@ namespace Nz
|
||||
DebugDrawer& debugDrawer = m_pipeline.GetDebugDrawer();
|
||||
debugDrawer.Draw(builder);
|
||||
});
|
||||
|
||||
return debugDrawPass;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -129,7 +129,7 @@ namespace Nz
|
||||
it->second.usedCount++;
|
||||
}
|
||||
|
||||
void DepthPipelinePass::RegisterToFrameGraph(FrameGraph& frameGraph, std::size_t depthBufferIndex)
|
||||
FramePass& DepthPipelinePass::RegisterToFrameGraph(FrameGraph& frameGraph, std::size_t depthBufferIndex)
|
||||
{
|
||||
FramePass& depthPrepass = frameGraph.AddPass("Depth pre-pass");
|
||||
depthPrepass.SetDepthStencilOutput(depthBufferIndex);
|
||||
@@ -157,6 +157,8 @@ namespace Nz
|
||||
|
||||
m_rebuildCommandBuffer = false;
|
||||
});
|
||||
|
||||
return depthPrepass;
|
||||
}
|
||||
|
||||
void DepthPipelinePass::UnregisterMaterialInstance(const MaterialInstance& materialInstance)
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
#include <Nazara/Graphics/DirectionalLight.hpp>
|
||||
#include <Nazara/Graphics/Enums.hpp>
|
||||
#include <Nazara/Graphics/Graphics.hpp>
|
||||
#include <Nazara/Graphics/PredefinedShaderStructs.hpp>
|
||||
#include <Nazara/Math/Vector2.hpp>
|
||||
#include <Nazara/Math/Vector3.hpp>
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include <Nazara/Graphics/PointLight.hpp>
|
||||
#include <Nazara/Graphics/PredefinedShaderStructs.hpp>
|
||||
#include <Nazara/Graphics/RenderElement.hpp>
|
||||
#include <Nazara/Graphics/SpotLight.hpp>
|
||||
#include <Nazara/Graphics/ViewerInstance.hpp>
|
||||
#include <Nazara/Graphics/WorldInstance.hpp>
|
||||
#include <Nazara/Math/Angle.hpp>
|
||||
@@ -61,6 +62,25 @@ namespace Nz
|
||||
}
|
||||
});
|
||||
|
||||
lightData->onLightShadowCastingChanged.Connect(lightData->light->OnLightShadowCastingChanged, [=](Light* light, bool isCastingShadows)
|
||||
{
|
||||
if (isCastingShadows)
|
||||
m_shadowCastingLights.UnboundedSet(lightIndex);
|
||||
else
|
||||
{
|
||||
m_shadowCastingLights.Reset(lightIndex);
|
||||
lightData->pass.reset();
|
||||
}
|
||||
|
||||
m_rebuildFrameGraph = true;
|
||||
});
|
||||
|
||||
if (lightData->light->IsShadowCaster())
|
||||
{
|
||||
m_shadowCastingLights.UnboundedSet(lightIndex);
|
||||
m_rebuildFrameGraph = true;
|
||||
}
|
||||
|
||||
return lightIndex;
|
||||
}
|
||||
|
||||
@@ -248,6 +268,48 @@ namespace Nz
|
||||
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);
|
||||
}
|
||||
|
||||
// Render queues handling
|
||||
for (auto& viewerData : m_viewerPool)
|
||||
{
|
||||
@@ -398,6 +460,7 @@ namespace Nz
|
||||
void ForwardFramePipeline::UnregisterLight(std::size_t lightIndex)
|
||||
{
|
||||
m_lightPool.Free(lightIndex);
|
||||
m_shadowCastingLights.UnboundedReset(lightIndex);
|
||||
}
|
||||
|
||||
void ForwardFramePipeline::UnregisterRenderable(std::size_t renderableIndex)
|
||||
@@ -486,6 +549,56 @@ namespace Nz
|
||||
{
|
||||
FrameGraph frameGraph;
|
||||
|
||||
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,
|
||||
shadowMapSize, shadowMapSize,
|
||||
true // fixed size
|
||||
});
|
||||
|
||||
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());
|
||||
lightData->camera->UpdateZFar(spotLight.GetRadius());
|
||||
lightData->camera->UpdateViewport(Recti(0, 0, SafeCast<int>(shadowMapSize), SafeCast<int>(shadowMapSize)));
|
||||
|
||||
viewerInstance.UpdateViewMatrix(Nz::Matrix4f::TransformInverse(spotLight.GetPosition(), spotLight.GetRotation()));
|
||||
}
|
||||
|
||||
if (!lightData->pass)
|
||||
{
|
||||
lightData->pass = std::make_unique<DepthPipelinePass>(*this, m_elementRegistry, lightData->camera.get());
|
||||
for (RenderableData& renderable : m_renderablePool)
|
||||
{
|
||||
std::size_t matCount = renderable.renderable->GetMaterialCount();
|
||||
for (std::size_t i = 0; i < matCount; ++i)
|
||||
{
|
||||
if (MaterialInstance* mat = renderable.renderable->GetMaterial(i).get())
|
||||
lightData->pass->RegisterMaterialInstance(*mat);
|
||||
}
|
||||
}
|
||||
|
||||
lightData->pass->RegisterToFrameGraph(frameGraph, lightData->shadowMapAttachmentIndex);
|
||||
}
|
||||
}
|
||||
|
||||
for (auto& viewerData : m_viewerPool)
|
||||
{
|
||||
viewerData.forwardColorAttachment = frameGraph.AddAttachment({
|
||||
@@ -503,7 +616,12 @@ namespace Nz
|
||||
if (viewerData.depthPrepass)
|
||||
viewerData.depthPrepass->RegisterToFrameGraph(frameGraph, viewerData.depthStencilAttachment);
|
||||
|
||||
viewerData.forwardPass->RegisterToFrameGraph(frameGraph, viewerData.forwardColorAttachment, viewerData.depthStencilAttachment, viewerData.depthPrepass != nullptr);
|
||||
FramePass& forwardPass = viewerData.forwardPass->RegisterToFrameGraph(frameGraph, viewerData.forwardColorAttachment, viewerData.depthStencilAttachment, viewerData.depthPrepass != nullptr);
|
||||
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);
|
||||
}
|
||||
|
||||
viewerData.debugDrawPass->RegisterToFrameGraph(frameGraph, viewerData.forwardColorAttachment, viewerData.debugColorAttachment);
|
||||
}
|
||||
@@ -548,7 +666,7 @@ namespace Nz
|
||||
mergePass.AddOutput(renderTargetData.finalAttachment);
|
||||
mergePass.SetClearColor(0, Color::Black);
|
||||
|
||||
mergePass.SetCommandCallback([&targetViewers](CommandBufferBuilder& builder, const Nz::FramePassEnvironment& env)
|
||||
mergePass.SetCommandCallback([&targetViewers](CommandBufferBuilder& builder, const FramePassEnvironment& env)
|
||||
{
|
||||
builder.SetScissor(env.renderRect);
|
||||
builder.SetViewport(env.renderRect);
|
||||
|
||||
@@ -265,7 +265,7 @@ namespace Nz
|
||||
it->second.usedCount++;
|
||||
}
|
||||
|
||||
void ForwardPipelinePass::RegisterToFrameGraph(FrameGraph& frameGraph, std::size_t colorBufferIndex, std::size_t depthBufferIndex, bool hasDepthPrepass)
|
||||
FramePass& ForwardPipelinePass::RegisterToFrameGraph(FrameGraph& frameGraph, std::size_t colorBufferIndex, std::size_t depthBufferIndex, bool hasDepthPrepass)
|
||||
{
|
||||
FramePass& forwardPass = frameGraph.AddPass("Forward pass");
|
||||
forwardPass.AddOutput(colorBufferIndex);
|
||||
@@ -299,6 +299,8 @@ namespace Nz
|
||||
|
||||
m_rebuildCommandBuffer = false;
|
||||
});
|
||||
|
||||
return forwardPass;
|
||||
}
|
||||
|
||||
void ForwardPipelinePass::UnregisterMaterialInstance(const MaterialInstance& materialInstance)
|
||||
|
||||
@@ -115,6 +115,7 @@ namespace Nz
|
||||
auto& bakedTexture = bakedTextures.emplace_back();
|
||||
bakedTexture.name = std::move(texture.name);
|
||||
bakedTexture.format = texture.format;
|
||||
bakedTexture.hasFixedSize = texture.hasFixedSize;
|
||||
bakedTexture.height = texture.height;
|
||||
bakedTexture.usage = texture.usage;
|
||||
bakedTexture.width = texture.width;
|
||||
@@ -952,7 +953,8 @@ namespace Nz
|
||||
TextureData& data = m_pending.textures[textureId];
|
||||
if (data.format != attachmentData.format ||
|
||||
data.width != attachmentData.width ||
|
||||
data.height != attachmentData.height)
|
||||
data.height != attachmentData.height ||
|
||||
data.hasFixedSize != attachmentData.hasFixedSize)
|
||||
continue;
|
||||
|
||||
m_pending.texturePool.erase(it);
|
||||
@@ -972,6 +974,7 @@ namespace Nz
|
||||
data.format = attachmentData.format;
|
||||
data.width = attachmentData.width;
|
||||
data.height = attachmentData.height;
|
||||
data.hasFixedSize = attachmentData.hasFixedSize;
|
||||
|
||||
return textureId;
|
||||
}
|
||||
|
||||
@@ -81,6 +81,7 @@ namespace Nz
|
||||
*/
|
||||
Graphics::Graphics(Config config) :
|
||||
ModuleBase("Graphics", this),
|
||||
m_preferredDepthFormat(PixelFormat::Undefined),
|
||||
m_preferredDepthStencilFormat(PixelFormat::Undefined)
|
||||
{
|
||||
Renderer* renderer = Renderer::Instance();
|
||||
@@ -213,6 +214,7 @@ namespace Nz
|
||||
void Graphics::BuildDefaultMaterials()
|
||||
{
|
||||
std::size_t depthPassIndex = m_materialPassRegistry.GetPassIndex("DepthPass");
|
||||
std::size_t shadowPassIndex = m_materialPassRegistry.GetPassIndex("ShadowPass");
|
||||
std::size_t forwardPassIndex = m_materialPassRegistry.GetPassIndex("ForwardPass");
|
||||
|
||||
// BasicMaterial
|
||||
@@ -228,6 +230,7 @@ namespace Nz
|
||||
MaterialPass depthPass = forwardPass;
|
||||
depthPass.options[CRC32("DepthPass")] = true;
|
||||
settings.AddPass(depthPassIndex, depthPass);
|
||||
settings.AddPass(shadowPassIndex, depthPass);
|
||||
|
||||
m_defaultMaterials.basicMaterial = std::make_shared<Material>(std::move(settings), "BasicMaterial");
|
||||
}
|
||||
@@ -246,6 +249,7 @@ namespace Nz
|
||||
MaterialPass depthPass = forwardPass;
|
||||
depthPass.options[CRC32("DepthPass")] = true;
|
||||
settings.AddPass(depthPassIndex, depthPass);
|
||||
settings.AddPass(shadowPassIndex, depthPass);
|
||||
|
||||
m_defaultMaterials.pbrMaterial = std::make_shared<Material>(std::move(settings), "PhysicallyBasedMaterial");
|
||||
}
|
||||
@@ -264,6 +268,7 @@ namespace Nz
|
||||
MaterialPass depthPass = forwardPass;
|
||||
depthPass.options[CRC32("DepthPass")] = true;
|
||||
settings.AddPass(depthPassIndex, depthPass);
|
||||
settings.AddPass(shadowPassIndex, depthPass);
|
||||
|
||||
m_defaultMaterials.phongMaterial = std::make_shared<Material>(std::move(settings), "PhongMaterial");
|
||||
}
|
||||
@@ -272,6 +277,7 @@ namespace Nz
|
||||
|
||||
m_defaultMaterials.basicNoDepth = m_defaultMaterials.basicMaterial->Instantiate();
|
||||
m_defaultMaterials.basicNoDepth->DisablePass(depthPassIndex);
|
||||
m_defaultMaterials.basicNoDepth->DisablePass(shadowPassIndex);
|
||||
m_defaultMaterials.basicNoDepth->UpdatePassStates(forwardPassIndex, [](RenderStates& states)
|
||||
{
|
||||
states.depthBuffer = false;
|
||||
@@ -279,6 +285,7 @@ namespace Nz
|
||||
|
||||
m_defaultMaterials.basicTransparent = m_defaultMaterials.basicMaterial->Instantiate();
|
||||
m_defaultMaterials.basicTransparent->DisablePass(depthPassIndex);
|
||||
m_defaultMaterials.basicTransparent->DisablePass(shadowPassIndex);
|
||||
m_defaultMaterials.basicTransparent->UpdatePassStates(forwardPassIndex, [](RenderStates& renderStates)
|
||||
{
|
||||
renderStates.depthWrite = false;
|
||||
@@ -316,6 +323,7 @@ namespace Nz
|
||||
{
|
||||
m_materialPassRegistry.RegisterPass("ForwardPass");
|
||||
m_materialPassRegistry.RegisterPass("DepthPass");
|
||||
m_materialPassRegistry.RegisterPass("ShadowPass");
|
||||
}
|
||||
|
||||
void Graphics::RegisterShaderModules()
|
||||
|
||||
@@ -3,9 +3,19 @@
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#include <Nazara/Graphics/Light.hpp>
|
||||
#include <Nazara/Graphics/Graphics.hpp>
|
||||
#include <Nazara/Graphics/Debug.hpp>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
Light::Light(UInt8 lightType) :
|
||||
m_boundingVolume(BoundingVolumef::Null()),
|
||||
m_shadowMapFormat(Graphics::Instance()->GetPreferredDepthFormat()),
|
||||
m_shadowMapSize(512),
|
||||
m_lightType(lightType),
|
||||
m_isShadowCaster(false)
|
||||
{
|
||||
}
|
||||
|
||||
Light::~Light() = default;
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
#include <Nazara/Graphics/PointLight.hpp>
|
||||
#include <Nazara/Graphics/Enums.hpp>
|
||||
#include <Nazara/Graphics/Graphics.hpp>
|
||||
#include <Nazara/Graphics/PredefinedShaderStructs.hpp>
|
||||
#include <Nazara/Math/Vector2.hpp>
|
||||
#include <Nazara/Math/Vector3.hpp>
|
||||
|
||||
@@ -38,6 +38,8 @@ option VertexUvLoc: i32 = -1;
|
||||
option VertexJointIndicesLoc: i32 = -1;
|
||||
option VertexJointWeightsLoc: i32 = -1;
|
||||
|
||||
option MaxLightCount: u32 = u32(3); //< FIXME: Fix integral value types
|
||||
|
||||
const HasNormal = (VertexNormalLoc >= 0);
|
||||
const HasVertexColor = (VertexColorLoc >= 0);
|
||||
const HasColor = (HasVertexColor || Billboard);
|
||||
@@ -93,7 +95,9 @@ external
|
||||
[tag("InstanceData")] instanceData: uniform[InstanceData],
|
||||
[tag("ViewerData")] viewerData: uniform[ViewerData],
|
||||
[tag("SkeletalData")] skeletalData: uniform[SkeletalData],
|
||||
[tag("LightData")] lightData: uniform[LightData]
|
||||
[tag("LightData")] lightData: uniform[LightData],
|
||||
[tag("ShadowMaps2D")] shadowMaps2D: array[sampler2D[f32], MaxLightCount],
|
||||
[tag("ShadowMapsCube")] shadowMapsCube: array[samplerCube[f32], MaxLightCount]
|
||||
}
|
||||
|
||||
struct VertToFrag
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
#include <Nazara/Graphics/SpotLight.hpp>
|
||||
#include <Nazara/Graphics/Enums.hpp>
|
||||
#include <Nazara/Graphics/Graphics.hpp>
|
||||
#include <Nazara/Graphics/PredefinedShaderStructs.hpp>
|
||||
#include <Nazara/Math/Vector2.hpp>
|
||||
#include <Nazara/Math/Vector3.hpp>
|
||||
|
||||
Reference in New Issue
Block a user