Add shadow mapping (wip)

This commit is contained in:
SirLynix
2022-11-07 02:16:02 +01:00
committed by Jérôme Leclercq
parent be9fba3190
commit 4a10c1f8fe
23 changed files with 333 additions and 44 deletions

View File

@@ -89,6 +89,7 @@ namespace Nz
TextureUsageFlags usage;
unsigned int width;
unsigned int height;
bool hasFixedSize;
};
std::shared_ptr<CommandPool> m_commandPool;

View File

@@ -178,12 +178,21 @@ namespace Nz
inline void Camera::UpdateViewport(const Recti& viewport)
{
NazaraAssert(m_renderTarget, "no render target");
if (m_renderTarget)
{
// We compute the region necessary to make this view port with the actual size of the target
Vector2f invSize = 1.f / Vector2f(m_renderTarget->GetSize());
// We compute the region necessary to make this view port with the actual size of the target
Vector2f invSize = 1.f / Vector2f(m_renderTarget->GetSize());
UpdateTargetRegion(Rectf(invSize.x * viewport.x, invSize.y * viewport.y, invSize.x * viewport.width, invSize.y * viewport.height));
}
else
{
m_aspectRatio = float(viewport.width) / float(viewport.height);
m_viewport = viewport;
m_viewerInstance.UpdateTargetSize(Vector2f(viewport.GetLengths()));
UpdateTargetRegion(Rectf(invSize.x * viewport.x, invSize.y * viewport.y, invSize.x * viewport.width, invSize.y * viewport.height));
UpdateProjectionMatrix();
}
}
inline void Camera::UpdateSize(const Vector2f& size)

View File

@@ -21,6 +21,7 @@ namespace Nz
{
class AbstractViewer;
class FrameGraph;
class FramePass;
class FramePipeline;
class Material;
@@ -34,7 +35,7 @@ namespace Nz
void Prepare(RenderFrame& renderFrame);
void RegisterToFrameGraph(FrameGraph& frameGraph, std::size_t inputColorBufferIndex, std::size_t outputColorBufferIndex);
FramePass& RegisterToFrameGraph(FrameGraph& frameGraph, std::size_t inputColorBufferIndex, std::size_t outputColorBufferIndex);
DebugDrawPipelinePass& operator=(const DebugDrawPipelinePass&) = delete;
DebugDrawPipelinePass& operator=(DebugDrawPipelinePass&&) = delete;

View File

@@ -24,6 +24,7 @@ namespace Nz
class AbstractViewer;
class ElementRendererRegistry;
class FrameGraph;
class FramePass;
class FramePipeline;
class NAZARA_GRAPHICS_API DepthPipelinePass : public FramePipelinePass
@@ -40,7 +41,7 @@ namespace Nz
void Prepare(RenderFrame& renderFrame, const Frustumf& frustum, const std::vector<FramePipelinePass::VisibleRenderable>& visibleRenderables, std::size_t visibilityHash);
void RegisterMaterialInstance(const MaterialInstance& materialInstance);
void RegisterToFrameGraph(FrameGraph& frameGraph, std::size_t depthBufferIndex);
FramePass& RegisterToFrameGraph(FrameGraph& frameGraph, std::size_t depthBufferIndex);
void UnregisterMaterialInstance(const MaterialInstance& materialInstance);

View File

@@ -9,6 +9,7 @@
#include <Nazara/Prerequisites.hpp>
#include <Nazara/Graphics/BakedFrameGraph.hpp>
#include <Nazara/Graphics/Camera.hpp>
#include <Nazara/Graphics/Config.hpp>
#include <Nazara/Graphics/DebugDrawPipelinePass.hpp>
#include <Nazara/Graphics/DepthPipelinePass.hpp>
@@ -76,9 +77,13 @@ namespace Nz
struct LightData
{
std::shared_ptr<Light> light;
std::size_t shadowMapAttachmentIndex;
std::unique_ptr<Camera> camera;
std::unique_ptr<DepthPipelinePass> pass;
UInt32 renderMask;
NazaraSlot(Light, OnLightDataInvalided, onLightInvalidated);
NazaraSlot(Light, OnLightShadowCastingChanged, onLightShadowCastingChanged);
};
struct MaterialInstanceData
@@ -145,6 +150,7 @@ namespace Nz
std::vector<const Light*> m_visibleLights;
robin_hood::unordered_set<TransferInterface*> m_transferSet;
BakedFrameGraph m_bakedFrameGraph;
Bitset<UInt64> m_shadowCastingLights;
Bitset<UInt64> m_removedSkeletonInstances;
Bitset<UInt64> m_removedViewerInstances;
Bitset<UInt64> m_removedWorldInstances;

View File

@@ -26,6 +26,7 @@ namespace Nz
class AbstractViewer;
class ElementRendererRegistry;
class FrameGraph;
class FramePass;
class FramePipeline;
class Light;
@@ -43,7 +44,7 @@ namespace Nz
void Prepare(RenderFrame& renderFrame, const Frustumf& frustum, const std::vector<FramePipelinePass::VisibleRenderable>& visibleRenderables, const std::vector<const Light*>& visibleLights, std::size_t visibilityHash);
void RegisterMaterialInstance(const MaterialInstance& material);
void RegisterToFrameGraph(FrameGraph& frameGraph, std::size_t colorBufferIndex, std::size_t depthBufferIndex, bool hasDepthPrepass);
FramePass& RegisterToFrameGraph(FrameGraph& frameGraph, std::size_t colorBufferIndex, std::size_t depthBufferIndex, bool hasDepthPrepass);
void UnregisterMaterialInstance(const MaterialInstance& material);

View File

@@ -91,6 +91,7 @@ namespace Nz
TextureUsageFlags usage;
unsigned int width;
unsigned int height;
bool hasFixedSize;
};
struct WorkData

View File

@@ -20,6 +20,7 @@ namespace Nz
PixelFormat format;
unsigned int width = 100'000;
unsigned int height = 100'000;
bool hasFixedSize = false;
};
}

View File

@@ -12,6 +12,7 @@
#include <Nazara/Math/BoundingVolume.hpp>
#include <Nazara/Math/Quaternion.hpp>
#include <Nazara/Math/Vector3.hpp>
#include <Nazara/Utility/PixelFormat.hpp>
#include <Nazara/Utils/Signal.hpp>
#include <memory>
@@ -20,21 +21,32 @@ namespace Nz
class CommandBufferBuilder;
class RenderBuffer;
class RenderFrame;
class Texture;
class NAZARA_GRAPHICS_API Light
{
public:
inline Light(UInt8 lightType);
Light(UInt8 lightType);
Light(const Light&) = delete;
Light(Light&&) noexcept = default;
virtual ~Light();
virtual float ComputeContributionScore(const BoundingVolumef& boundingVolume) const = 0;
inline void EnableShadowCasting(bool castShadows);
virtual void FillLightData(void* data) const = 0;
inline const BoundingVolumef& GetBoundingVolume() const;
inline UInt8 GetLightType() const;
inline PixelFormat GetShadowMapFormat() const;
inline UInt32 GetShadowMapSize() const;
inline bool IsShadowCaster() const;
inline void UpdateShadowMapFormat(PixelFormat format);
inline void UpdateShadowMapSettings(UInt32 size, PixelFormat format);
inline void UpdateShadowMapSize(UInt32 size);
virtual void UpdateTransform(const Vector3f& position, const Quaternionf& rotation, const Vector3f& scale) = 0;
@@ -42,13 +54,18 @@ namespace Nz
Light& operator=(Light&&) noexcept = default;
NazaraSignal(OnLightDataInvalided, Light* /*emitter*/);
NazaraSignal(OnLightShadowCastingChanged, Light* /*light*/, bool /*isShadowCasting*/);
NazaraSignal(OnLightShadowMapSettingChange, Light* /*light*/, PixelFormat /*newPixelFormat*/, UInt32 /*newSize*/);
protected:
inline void UpdateBoundingVolume(const BoundingVolumef& boundingVolume);
private:
BoundingVolumef m_boundingVolume;
PixelFormat m_shadowMapFormat;
UInt8 m_lightType;
UInt32 m_shadowMapSize;
bool m_isShadowCaster;
};
}

View File

@@ -8,10 +8,13 @@
namespace Nz
{
inline Light::Light(UInt8 lightType) :
m_boundingVolume(BoundingVolumef::Null()),
m_lightType(lightType)
inline void Light::EnableShadowCasting(bool castShadows)
{
if (m_isShadowCaster != castShadows)
{
m_isShadowCaster = castShadows;
OnLightShadowCastingChanged(this, castShadows);
}
}
inline const BoundingVolumef& Light::GetBoundingVolume() const
@@ -24,6 +27,58 @@ namespace Nz
return m_lightType;
}
inline PixelFormat Light::GetShadowMapFormat() const
{
return m_shadowMapFormat;
}
inline UInt32 Light::GetShadowMapSize() const
{
return m_shadowMapSize;
}
inline bool Light::IsShadowCaster() const
{
return m_isShadowCaster;
}
inline void Light::UpdateShadowMapFormat(PixelFormat format)
{
if (m_shadowMapFormat != format)
{
PixelFormatContent content = PixelFormatInfo::GetContent(format);
NazaraAssert(content != PixelFormatContent::Depth && content != PixelFormatContent::DepthStencil, "invalid shadow map format (has no depth)");
OnLightShadowMapSettingChange(this, format, m_shadowMapSize);
m_shadowMapFormat = format;
}
}
inline void Light::UpdateShadowMapSettings(UInt32 size, PixelFormat format)
{
if (m_shadowMapFormat != format || m_shadowMapSize != size)
{
NazaraAssert(size > 0, "invalid shadow map size");
PixelFormatContent content = PixelFormatInfo::GetContent(format);
NazaraAssert(content != PixelFormatContent::Depth && content != PixelFormatContent::DepthStencil, "invalid shadow map format (has no depth)");
OnLightShadowMapSettingChange(this, format, size);
m_shadowMapFormat = format;
m_shadowMapSize = size;
}
}
inline void Light::UpdateShadowMapSize(UInt32 size)
{
if (m_shadowMapSize != size)
{
NazaraAssert(size > 0, "invalid shadow map size");
OnLightShadowMapSettingChange(this, m_shadowMapFormat, size);
m_shadowMapSize = size;
}
}
inline void Light::UpdateBoundingVolume(const BoundingVolumef& boundingVolume)
{
m_boundingVolume = boundingVolume;