Graphics: Move shadow-mapping related code to LightShadow classes
This commit is contained in:
parent
ec3bc45544
commit
1768f20365
|
|
@ -25,7 +25,7 @@ namespace Nz
|
||||||
|
|
||||||
virtual const Color& GetClearColor() const = 0;
|
virtual const Color& GetClearColor() const = 0;
|
||||||
virtual UInt32 GetRenderMask() const = 0;
|
virtual UInt32 GetRenderMask() const = 0;
|
||||||
virtual const RenderTarget& GetRenderTarget() = 0;
|
virtual const RenderTarget& GetRenderTarget() const = 0;
|
||||||
virtual ViewerInstance& GetViewerInstance() = 0;
|
virtual ViewerInstance& GetViewerInstance() = 0;
|
||||||
virtual const ViewerInstance& GetViewerInstance() const = 0;
|
virtual const ViewerInstance& GetViewerInstance() const = 0;
|
||||||
virtual const Recti& GetViewport() const = 0;
|
virtual const Recti& GetViewport() const = 0;
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,7 @@ namespace Nz
|
||||||
inline DegreeAnglef GetFOV() const;
|
inline DegreeAnglef GetFOV() const;
|
||||||
UInt32 GetRenderMask() const override;
|
UInt32 GetRenderMask() const override;
|
||||||
inline Int32 GetRenderOrder() const;
|
inline Int32 GetRenderOrder() const;
|
||||||
const RenderTarget& GetRenderTarget() override;
|
const RenderTarget& GetRenderTarget() const;
|
||||||
inline const Vector2f& GetSize() const;
|
inline const Vector2f& GetSize() const;
|
||||||
inline const Rectf& GetTargetRegion() const;
|
inline const Rectf& GetTargetRegion() const;
|
||||||
ViewerInstance& GetViewerInstance() override;
|
ViewerInstance& GetViewerInstance() override;
|
||||||
|
|
|
||||||
|
|
@ -41,7 +41,7 @@ namespace Nz
|
||||||
void Prepare(RenderFrame& renderFrame, const Frustumf& frustum, const std::vector<FramePipelinePass::VisibleRenderable>& visibleRenderables, std::size_t visibilityHash);
|
void Prepare(RenderFrame& renderFrame, const Frustumf& frustum, const std::vector<FramePipelinePass::VisibleRenderable>& visibleRenderables, std::size_t visibilityHash);
|
||||||
|
|
||||||
void RegisterMaterialInstance(const MaterialInstance& materialInstance);
|
void RegisterMaterialInstance(const MaterialInstance& materialInstance);
|
||||||
FramePass& RegisterToFrameGraph(FrameGraph& frameGraph, std::size_t depthBufferIndex);
|
FramePass& RegisterToFrameGraph(FrameGraph& frameGraph, std::size_t outputAttachment);
|
||||||
|
|
||||||
void UnregisterMaterialInstance(const MaterialInstance& materialInstance);
|
void UnregisterMaterialInstance(const MaterialInstance& materialInstance);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,8 @@ namespace Nz
|
||||||
|
|
||||||
void FillLightData(void* data) const override;
|
void FillLightData(void* data) const override;
|
||||||
|
|
||||||
|
std::unique_ptr<LightShadowData> InstanciateShadowData(FramePipeline& pipeline, ElementRendererRegistry& elementRegistry) const override;
|
||||||
|
|
||||||
inline float GetAmbientFactor() const;
|
inline float GetAmbientFactor() const;
|
||||||
inline float GetDiffuseFactor() const;
|
inline float GetDiffuseFactor() const;
|
||||||
inline Color GetColor() const;
|
inline Color GetColor() const;
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@
|
||||||
#include <Nazara/Graphics/FramePipeline.hpp>
|
#include <Nazara/Graphics/FramePipeline.hpp>
|
||||||
#include <Nazara/Graphics/InstancedRenderable.hpp>
|
#include <Nazara/Graphics/InstancedRenderable.hpp>
|
||||||
#include <Nazara/Graphics/Light.hpp>
|
#include <Nazara/Graphics/Light.hpp>
|
||||||
|
#include <Nazara/Graphics/LightShadowData.hpp>
|
||||||
#include <Nazara/Graphics/MaterialPass.hpp>
|
#include <Nazara/Graphics/MaterialPass.hpp>
|
||||||
#include <Nazara/Graphics/RenderElement.hpp>
|
#include <Nazara/Graphics/RenderElement.hpp>
|
||||||
#include <Nazara/Graphics/RenderQueue.hpp>
|
#include <Nazara/Graphics/RenderQueue.hpp>
|
||||||
|
|
@ -44,7 +45,13 @@ namespace Nz
|
||||||
ForwardFramePipeline(ForwardFramePipeline&&) = delete;
|
ForwardFramePipeline(ForwardFramePipeline&&) = delete;
|
||||||
~ForwardFramePipeline();
|
~ForwardFramePipeline();
|
||||||
|
|
||||||
std::size_t RegisterLight(std::shared_ptr<Light> light, UInt32 renderMask) override;
|
const std::vector<FramePipelinePass::VisibleRenderable>& FrustumCull(const Frustumf& frustum, UInt32 mask, std::size_t& visibilityHash) const override;
|
||||||
|
|
||||||
|
void ForEachRegisteredMaterialInstance(FunctionRef<void(const MaterialInstance& materialInstance)> callback) override;
|
||||||
|
|
||||||
|
void QueueTransfer(TransferInterface* transfer) override;
|
||||||
|
|
||||||
|
std::size_t RegisterLight(const Light* light, UInt32 renderMask) override;
|
||||||
std::size_t RegisterRenderable(std::size_t worldInstanceIndex, std::size_t skeletonInstanceIndex, const InstancedRenderable* instancedRenderable, UInt32 renderMask, const Recti& scissorBox) override;
|
std::size_t RegisterRenderable(std::size_t worldInstanceIndex, std::size_t skeletonInstanceIndex, const InstancedRenderable* instancedRenderable, UInt32 renderMask, const Recti& scissorBox) override;
|
||||||
std::size_t RegisterSkeleton(SkeletonInstancePtr skeletonInstance) override;
|
std::size_t RegisterSkeleton(SkeletonInstancePtr skeletonInstance) override;
|
||||||
std::size_t RegisterViewer(AbstractViewer* viewerInstance, Int32 renderOrder) override;
|
std::size_t RegisterViewer(AbstractViewer* viewerInstance, Int32 renderOrder) override;
|
||||||
|
|
@ -79,14 +86,11 @@ namespace Nz
|
||||||
|
|
||||||
struct LightData
|
struct LightData
|
||||||
{
|
{
|
||||||
std::shared_ptr<Light> light;
|
std::unique_ptr<LightShadowData> shadowData;
|
||||||
std::size_t shadowMapAttachmentIndex;
|
const Light* light;
|
||||||
std::unique_ptr<Camera> camera;
|
|
||||||
std::unique_ptr<DepthPipelinePass> pass;
|
|
||||||
UInt32 renderMask;
|
UInt32 renderMask;
|
||||||
|
|
||||||
NazaraSlot(Light, OnLightDataInvalided, onLightInvalidated);
|
NazaraSlot(Light, OnLightDataInvalided, onLightInvalidated);
|
||||||
NazaraSlot(Light, OnLightTransformInvalided, onLightTransformInvalidated);
|
|
||||||
NazaraSlot(Light, OnLightShadowCastingChanged, onLightShadowCastingChanged);
|
NazaraSlot(Light, OnLightShadowCastingChanged, onLightShadowCastingChanged);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -150,7 +154,7 @@ namespace Nz
|
||||||
std::unordered_map<const RenderTarget*, RenderTargetData> m_renderTargets;
|
std::unordered_map<const RenderTarget*, RenderTargetData> m_renderTargets;
|
||||||
std::unordered_map<MaterialInstance*, MaterialInstanceData> m_materialInstances;
|
std::unordered_map<MaterialInstance*, MaterialInstanceData> m_materialInstances;
|
||||||
std::vector<ElementRenderer::RenderStates> m_renderStates;
|
std::vector<ElementRenderer::RenderStates> m_renderStates;
|
||||||
std::vector<FramePipelinePass::VisibleRenderable> m_visibleRenderables;
|
mutable std::vector<FramePipelinePass::VisibleRenderable> m_visibleRenderables;
|
||||||
std::vector<std::size_t> m_visibleLights;
|
std::vector<std::size_t> m_visibleLights;
|
||||||
robin_hood::unordered_set<TransferInterface*> m_transferSet;
|
robin_hood::unordered_set<TransferInterface*> m_transferSet;
|
||||||
BakedFrameGraph m_bakedFrameGraph;
|
BakedFrameGraph m_bakedFrameGraph;
|
||||||
|
|
@ -159,7 +163,7 @@ namespace Nz
|
||||||
Bitset<UInt64> m_removedViewerInstances;
|
Bitset<UInt64> m_removedViewerInstances;
|
||||||
Bitset<UInt64> m_removedWorldInstances;
|
Bitset<UInt64> m_removedWorldInstances;
|
||||||
ElementRendererRegistry& m_elementRegistry;
|
ElementRendererRegistry& m_elementRegistry;
|
||||||
MemoryPool<RenderableData> m_renderablePool;
|
mutable MemoryPool<RenderableData> m_renderablePool; //< FIXME: has to be mutable because MemoryPool has no const_iterator
|
||||||
MemoryPool<LightData> m_lightPool;
|
MemoryPool<LightData> m_lightPool;
|
||||||
MemoryPool<SkeletonInstanceData> m_skeletonInstances;
|
MemoryPool<SkeletonInstanceData> m_skeletonInstances;
|
||||||
MemoryPool<ViewerData> m_viewerPool;
|
MemoryPool<ViewerData> m_viewerPool;
|
||||||
|
|
|
||||||
|
|
@ -9,10 +9,12 @@
|
||||||
|
|
||||||
#include <Nazara/Prerequisites.hpp>
|
#include <Nazara/Prerequisites.hpp>
|
||||||
#include <Nazara/Graphics/Config.hpp>
|
#include <Nazara/Graphics/Config.hpp>
|
||||||
|
#include <Nazara/Graphics/FramePipelinePass.hpp>
|
||||||
#include <Nazara/Graphics/RenderElement.hpp>
|
#include <Nazara/Graphics/RenderElement.hpp>
|
||||||
#include <Nazara/Graphics/SkeletonInstance.hpp>
|
#include <Nazara/Graphics/SkeletonInstance.hpp>
|
||||||
#include <Nazara/Graphics/WorldInstance.hpp>
|
#include <Nazara/Graphics/WorldInstance.hpp>
|
||||||
#include <Nazara/Renderer/DebugDrawer.hpp>
|
#include <Nazara/Renderer/DebugDrawer.hpp>
|
||||||
|
#include <Nazara/Utils/FunctionRef.hpp>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
|
@ -21,6 +23,7 @@ namespace Nz
|
||||||
class AbstractViewer;
|
class AbstractViewer;
|
||||||
class InstancedRenderable;
|
class InstancedRenderable;
|
||||||
class Light;
|
class Light;
|
||||||
|
class MaterialInstance;
|
||||||
class RenderFrame;
|
class RenderFrame;
|
||||||
|
|
||||||
class NAZARA_GRAPHICS_API FramePipeline
|
class NAZARA_GRAPHICS_API FramePipeline
|
||||||
|
|
@ -31,9 +34,16 @@ namespace Nz
|
||||||
FramePipeline(FramePipeline&&) noexcept = default;
|
FramePipeline(FramePipeline&&) noexcept = default;
|
||||||
virtual ~FramePipeline();
|
virtual ~FramePipeline();
|
||||||
|
|
||||||
|
// TODO: Move RenderQueue handling to proper classes (allowing to reuse them)
|
||||||
|
virtual const std::vector<FramePipelinePass::VisibleRenderable>& FrustumCull(const Frustumf& frustum, UInt32 mask, std::size_t& visibilityHash) const = 0;
|
||||||
|
|
||||||
|
virtual void ForEachRegisteredMaterialInstance(FunctionRef<void(const MaterialInstance& materialInstance)> callback) = 0;
|
||||||
|
|
||||||
inline DebugDrawer& GetDebugDrawer();
|
inline DebugDrawer& GetDebugDrawer();
|
||||||
|
|
||||||
virtual std::size_t RegisterLight(std::shared_ptr<Light> light, UInt32 renderMask) = 0;
|
virtual void QueueTransfer(TransferInterface* transfer) = 0;
|
||||||
|
|
||||||
|
virtual std::size_t RegisterLight(const Light* light, UInt32 renderMask) = 0;
|
||||||
virtual std::size_t RegisterRenderable(std::size_t worldInstanceIndex, std::size_t skeletonInstanceIndex, const InstancedRenderable* instancedRenderable, UInt32 renderMask, const Recti& scissorBox) = 0;
|
virtual std::size_t RegisterRenderable(std::size_t worldInstanceIndex, std::size_t skeletonInstanceIndex, const InstancedRenderable* instancedRenderable, UInt32 renderMask, const Recti& scissorBox) = 0;
|
||||||
virtual std::size_t RegisterSkeleton(SkeletonInstancePtr skeletonInstance) = 0;
|
virtual std::size_t RegisterSkeleton(SkeletonInstancePtr skeletonInstance) = 0;
|
||||||
virtual std::size_t RegisterViewer(AbstractViewer* viewerInstance, Int32 renderOrder) = 0;
|
virtual std::size_t RegisterViewer(AbstractViewer* viewerInstance, Int32 renderOrder) = 0;
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@
|
||||||
|
|
||||||
#include <Nazara/Prerequisites.hpp>
|
#include <Nazara/Prerequisites.hpp>
|
||||||
#include <Nazara/Graphics/Config.hpp>
|
#include <Nazara/Graphics/Config.hpp>
|
||||||
|
#include <Nazara/Graphics/LightShadowData.hpp>
|
||||||
#include <Nazara/Math/BoundingVolume.hpp>
|
#include <Nazara/Math/BoundingVolume.hpp>
|
||||||
#include <Nazara/Math/Quaternion.hpp>
|
#include <Nazara/Math/Quaternion.hpp>
|
||||||
#include <Nazara/Math/Vector3.hpp>
|
#include <Nazara/Math/Vector3.hpp>
|
||||||
|
|
@ -19,6 +20,8 @@
|
||||||
namespace Nz
|
namespace Nz
|
||||||
{
|
{
|
||||||
class CommandBufferBuilder;
|
class CommandBufferBuilder;
|
||||||
|
class ElementRendererRegistry;
|
||||||
|
class FramePipeline;
|
||||||
class RenderBuffer;
|
class RenderBuffer;
|
||||||
class RenderFrame;
|
class RenderFrame;
|
||||||
class Texture;
|
class Texture;
|
||||||
|
|
@ -42,6 +45,8 @@ namespace Nz
|
||||||
inline PixelFormat GetShadowMapFormat() const;
|
inline PixelFormat GetShadowMapFormat() const;
|
||||||
inline UInt32 GetShadowMapSize() const;
|
inline UInt32 GetShadowMapSize() const;
|
||||||
|
|
||||||
|
virtual std::unique_ptr<LightShadowData> InstanciateShadowData(FramePipeline& pipeline, ElementRendererRegistry& elementRegistry) const = 0;
|
||||||
|
|
||||||
inline bool IsShadowCaster() const;
|
inline bool IsShadowCaster() const;
|
||||||
|
|
||||||
inline void UpdateShadowMapFormat(PixelFormat format);
|
inline void UpdateShadowMapFormat(PixelFormat format);
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,49 @@
|
||||||
|
// 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
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifndef NAZARA_GRAPHICS_LIGHTSHADOWDATA_HPP
|
||||||
|
#define NAZARA_GRAPHICS_LIGHTSHADOWDATA_HPP
|
||||||
|
|
||||||
|
#include <Nazara/Prerequisites.hpp>
|
||||||
|
#include <Nazara/Graphics/Config.hpp>
|
||||||
|
|
||||||
|
namespace Nz
|
||||||
|
{
|
||||||
|
class BakedFrameGraph;
|
||||||
|
class FrameGraph;
|
||||||
|
class FramePass;
|
||||||
|
class MaterialInstance;
|
||||||
|
class RenderFrame;
|
||||||
|
class Texture;
|
||||||
|
|
||||||
|
class NAZARA_GRAPHICS_API LightShadowData
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
LightShadowData() = default;
|
||||||
|
LightShadowData(const LightShadowData&) = delete;
|
||||||
|
LightShadowData(LightShadowData&&) = delete;
|
||||||
|
virtual ~LightShadowData();
|
||||||
|
|
||||||
|
virtual void PrepareRendering(RenderFrame& renderFrame) = 0;
|
||||||
|
|
||||||
|
virtual void RegisterMaterialInstance(const MaterialInstance& matInstance) = 0;
|
||||||
|
virtual void RegisterPassInputs(FramePass& pass) = 0;
|
||||||
|
virtual void RegisterToFrameGraph(FrameGraph& frameGraph) = 0;
|
||||||
|
|
||||||
|
virtual const Texture* RetrieveLightShadowmap(const BakedFrameGraph& bakedGraph) const = 0;
|
||||||
|
|
||||||
|
virtual void UnregisterMaterialInstance(const MaterialInstance& matInstance) = 0;
|
||||||
|
|
||||||
|
LightShadowData& operator=(const LightShadowData&) = delete;
|
||||||
|
LightShadowData& operator=(LightShadowData&&) = delete;
|
||||||
|
|
||||||
|
private:
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#include <Nazara/Graphics/LightShadowData.inl>
|
||||||
|
|
||||||
|
#endif // NAZARA_GRAPHICS_LIGHTSHADOWDATA_HPP
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
// 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
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
#include <Nazara/Graphics/DebugOff.hpp>
|
||||||
|
|
@ -54,7 +54,6 @@ namespace Nz
|
||||||
|
|
||||||
std::shared_ptr<GraphicalMesh> m_graphicalMesh;
|
std::shared_ptr<GraphicalMesh> m_graphicalMesh;
|
||||||
std::vector<SubMeshData> m_submeshes;
|
std::vector<SubMeshData> m_submeshes;
|
||||||
Recti m_scissorBox;
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,8 @@ namespace Nz
|
||||||
|
|
||||||
void FillLightData(void* data) const override;
|
void FillLightData(void* data) const override;
|
||||||
|
|
||||||
|
std::unique_ptr<LightShadowData> InstanciateShadowData(FramePipeline& pipeline, ElementRendererRegistry& elementRegistry) const override;
|
||||||
|
|
||||||
inline float GetAmbientFactor() const;
|
inline float GetAmbientFactor() const;
|
||||||
inline float GetDiffuseFactor() const;
|
inline float GetDiffuseFactor() const;
|
||||||
inline Color GetColor() const;
|
inline Color GetColor() const;
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,46 @@
|
||||||
|
// 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
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifndef NAZARA_GRAPHICS_SHADOWVIEWER_HPP
|
||||||
|
#define NAZARA_GRAPHICS_SHADOWVIEWER_HPP
|
||||||
|
|
||||||
|
#include <Nazara/Prerequisites.hpp>
|
||||||
|
#include <Nazara/Graphics/AbstractViewer.hpp>
|
||||||
|
#include <Nazara/Graphics/ViewerInstance.hpp>
|
||||||
|
|
||||||
|
namespace Nz
|
||||||
|
{
|
||||||
|
class NAZARA_GRAPHICS_API ShadowViewer : public AbstractViewer
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
inline ShadowViewer(const Recti& viewport, UInt32 renderMask);
|
||||||
|
ShadowViewer(const ShadowViewer&) = delete;
|
||||||
|
ShadowViewer(ShadowViewer&&) = delete;
|
||||||
|
~ShadowViewer() = default;
|
||||||
|
|
||||||
|
const Color& GetClearColor() const override;
|
||||||
|
UInt32 GetRenderMask() const override;
|
||||||
|
const RenderTarget& GetRenderTarget() const override;
|
||||||
|
ViewerInstance& GetViewerInstance() override;
|
||||||
|
const ViewerInstance& GetViewerInstance() const override;
|
||||||
|
const Recti& GetViewport() const override;
|
||||||
|
|
||||||
|
inline void UpdateRenderMask(UInt32 renderMask);
|
||||||
|
inline void UpdateViewport(const Recti& viewport);
|
||||||
|
|
||||||
|
ShadowViewer& operator=(const ShadowViewer&) = delete;
|
||||||
|
ShadowViewer& operator=(ShadowViewer&&) = delete;
|
||||||
|
|
||||||
|
private:
|
||||||
|
Recti m_viewport;
|
||||||
|
ViewerInstance m_viewerInstance;
|
||||||
|
UInt32 m_renderMask;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#include <Nazara/Graphics/ShadowViewer.inl>
|
||||||
|
|
||||||
|
#endif // NAZARA_GRAPHICS_SHADOWVIEWER_HPP
|
||||||
|
|
@ -0,0 +1,28 @@
|
||||||
|
// 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
|
||||||
|
{
|
||||||
|
inline ShadowViewer::ShadowViewer(const Recti& viewport, UInt32 renderMask) :
|
||||||
|
m_renderMask(renderMask)
|
||||||
|
{
|
||||||
|
UpdateViewport(viewport);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void ShadowViewer::UpdateRenderMask(UInt32 renderMask)
|
||||||
|
{
|
||||||
|
m_renderMask = renderMask;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void ShadowViewer::UpdateViewport(const Recti& viewport)
|
||||||
|
{
|
||||||
|
m_viewport = viewport;
|
||||||
|
m_viewerInstance.UpdateTargetSize({ float(m_viewport.width), float(m_viewport.height) });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#include <Nazara/Graphics/DebugOff.hpp>
|
||||||
|
|
@ -38,6 +38,8 @@ namespace Nz
|
||||||
inline const Quaternionf& GetRotation() const;
|
inline const Quaternionf& GetRotation() const;
|
||||||
inline float GetRadius() const;
|
inline float GetRadius() const;
|
||||||
|
|
||||||
|
std::unique_ptr<LightShadowData> InstanciateShadowData(FramePipeline& pipeline, ElementRendererRegistry& elementRegistry) const override;
|
||||||
|
|
||||||
inline void UpdateAmbientFactor(float factor);
|
inline void UpdateAmbientFactor(float factor);
|
||||||
inline void UpdateColor(Color color);
|
inline void UpdateColor(Color color);
|
||||||
inline void UpdateDiffuseFactor(float factor);
|
inline void UpdateDiffuseFactor(float factor);
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,56 @@
|
||||||
|
// 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
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifndef NAZARA_GRAPHICS_SPOTLIGHTSHADOWDATA_HPP
|
||||||
|
#define NAZARA_GRAPHICS_SPOTLIGHTSHADOWDATA_HPP
|
||||||
|
|
||||||
|
#include <Nazara/Prerequisites.hpp>
|
||||||
|
#include <Nazara/Graphics/DepthPipelinePass.hpp>
|
||||||
|
#include <Nazara/Graphics/Light.hpp>
|
||||||
|
#include <Nazara/Graphics/LightShadowData.hpp>
|
||||||
|
#include <Nazara/Graphics/ShadowViewer.hpp>
|
||||||
|
|
||||||
|
namespace Nz
|
||||||
|
{
|
||||||
|
class FramePipeline;
|
||||||
|
class SpotLight;
|
||||||
|
|
||||||
|
class NAZARA_GRAPHICS_API SpotLightShadowData : public LightShadowData
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
SpotLightShadowData(FramePipeline& pipeline, ElementRendererRegistry& elementRegistry, const SpotLight& light);
|
||||||
|
SpotLightShadowData(const SpotLightShadowData&) = delete;
|
||||||
|
SpotLightShadowData(SpotLightShadowData&&) = delete;
|
||||||
|
~SpotLightShadowData() = default;
|
||||||
|
|
||||||
|
void PrepareRendering(RenderFrame& renderFrame) override;
|
||||||
|
|
||||||
|
void RegisterMaterialInstance(const MaterialInstance& matInstance) override;
|
||||||
|
void RegisterPassInputs(FramePass& pass) override;
|
||||||
|
void RegisterToFrameGraph(FrameGraph& frameGraph) override;
|
||||||
|
|
||||||
|
const Texture* RetrieveLightShadowmap(const BakedFrameGraph& bakedGraph) const override;
|
||||||
|
|
||||||
|
void UnregisterMaterialInstance(const MaterialInstance& matInstance) override;
|
||||||
|
|
||||||
|
SpotLightShadowData& operator=(const SpotLightShadowData&) = delete;
|
||||||
|
SpotLightShadowData& operator=(SpotLightShadowData&&) = delete;
|
||||||
|
|
||||||
|
private:
|
||||||
|
NazaraSlot(Light, OnLightShadowMapSettingChange, m_onLightShadowMapSettingChange);
|
||||||
|
NazaraSlot(Light, OnLightTransformInvalided, m_onLightTransformInvalidated);
|
||||||
|
|
||||||
|
std::optional<DepthPipelinePass> m_depthPass;
|
||||||
|
std::size_t m_attachmentIndex;
|
||||||
|
FramePipeline& m_pipeline;
|
||||||
|
const SpotLight& m_light;
|
||||||
|
ShadowViewer m_viewer;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#include <Nazara/Graphics/SpotLightShadowData.inl>
|
||||||
|
|
||||||
|
#endif // NAZARA_GRAPHICS_SPOTLIGHTSHADOWDATA_HPP
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
// 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/Debug.hpp>
|
||||||
|
|
||||||
|
namespace Nz
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
#include <Nazara/Graphics/DebugOff.hpp>
|
||||||
|
|
@ -18,7 +18,7 @@ namespace Nz
|
||||||
return m_renderMask;
|
return m_renderMask;
|
||||||
}
|
}
|
||||||
|
|
||||||
const RenderTarget& Camera::GetRenderTarget()
|
const RenderTarget& Camera::GetRenderTarget() const
|
||||||
{
|
{
|
||||||
if (!m_renderTarget)
|
if (!m_renderTarget)
|
||||||
throw std::runtime_error("no rendertarget set");
|
throw std::runtime_error("no rendertarget set");
|
||||||
|
|
|
||||||
|
|
@ -129,10 +129,10 @@ namespace Nz
|
||||||
it->second.usedCount++;
|
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);
|
FramePass& depthPrepass = frameGraph.AddPass(m_passName);
|
||||||
depthPrepass.SetDepthStencilOutput(depthBufferIndex);
|
depthPrepass.SetDepthStencilOutput(outputAttachment);
|
||||||
depthPrepass.SetDepthStencilClear(1.f, 0);
|
depthPrepass.SetDepthStencilClear(1.f, 0);
|
||||||
|
|
||||||
depthPrepass.SetExecutionCallback([&]()
|
depthPrepass.SetExecutionCallback([&]()
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,11 @@ namespace Nz
|
||||||
AccessByOffset<Vector2f&>(data, lightOffset.lightMemberOffsets.shadowMapSize) = Vector2f(-1.f, -1.f);
|
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*/)
|
void DirectionalLight::UpdateTransform(const Vector3f& /*position*/, const Quaternionf& rotation, const Vector3f& /*scale*/)
|
||||||
{
|
{
|
||||||
UpdateRotation(rotation);
|
UpdateRotation(rotation);
|
||||||
|
|
|
||||||
|
|
@ -44,11 +44,67 @@ namespace Nz
|
||||||
m_viewerPool.Clear();
|
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;
|
std::size_t lightIndex;
|
||||||
LightData* lightData = m_lightPool.Allocate(lightIndex);
|
LightData* lightData = m_lightPool.Allocate(lightIndex);
|
||||||
lightData->light = std::move(light);
|
lightData->light = light;
|
||||||
lightData->renderMask = renderMask;
|
lightData->renderMask = renderMask;
|
||||||
lightData->onLightInvalidated.Connect(lightData->light->OnLightDataInvalided, [=](Light*)
|
lightData->onLightInvalidated.Connect(lightData->light->OnLightDataInvalided, [=](Light*)
|
||||||
{
|
{
|
||||||
|
|
@ -65,11 +121,14 @@ namespace Nz
|
||||||
lightData->onLightShadowCastingChanged.Connect(lightData->light->OnLightShadowCastingChanged, [=](Light* light, bool isCastingShadows)
|
lightData->onLightShadowCastingChanged.Connect(lightData->light->OnLightShadowCastingChanged, [=](Light* light, bool isCastingShadows)
|
||||||
{
|
{
|
||||||
if (isCastingShadows)
|
if (isCastingShadows)
|
||||||
|
{
|
||||||
m_shadowCastingLights.UnboundedSet(lightIndex);
|
m_shadowCastingLights.UnboundedSet(lightIndex);
|
||||||
|
lightData->shadowData = light->InstanciateShadowData(*this, m_elementRegistry);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_shadowCastingLights.Reset(lightIndex);
|
m_shadowCastingLights.Reset(lightIndex);
|
||||||
lightData->pass.reset();
|
lightData->shadowData.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
m_rebuildFrameGraph = true;
|
m_rebuildFrameGraph = true;
|
||||||
|
|
@ -78,6 +137,7 @@ namespace Nz
|
||||||
if (lightData->light->IsShadowCaster())
|
if (lightData->light->IsShadowCaster())
|
||||||
{
|
{
|
||||||
m_shadowCastingLights.UnboundedSet(lightIndex);
|
m_shadowCastingLights.UnboundedSet(lightIndex);
|
||||||
|
lightData->shadowData = light->InstanciateShadowData(*this, m_elementRegistry);
|
||||||
m_rebuildFrameGraph = true;
|
m_rebuildFrameGraph = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -215,7 +275,7 @@ namespace Nz
|
||||||
|
|
||||||
const Light* ForwardFramePipeline::RetrieveLight(std::size_t lightIndex) const
|
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
|
const Texture* ForwardFramePipeline::RetrieveLightShadowmap(std::size_t lightIndex) const
|
||||||
|
|
@ -223,8 +283,7 @@ namespace Nz
|
||||||
if (!m_shadowCastingLights.UnboundedTest(lightIndex))
|
if (!m_shadowCastingLights.UnboundedTest(lightIndex))
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
std::size_t shadowmapIndex = m_lightPool.RetrieveFromIndex(lightIndex)->shadowMapAttachmentIndex;
|
return m_lightPool.RetrieveFromIndex(lightIndex)->shadowData->RetrieveLightShadowmap(m_bakedFrameGraph);
|
||||||
return m_bakedFrameGraph.GetAttachmentTexture(shadowmapIndex).get();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ForwardFramePipeline::Render(RenderFrame& renderFrame)
|
void ForwardFramePipeline::Render(RenderFrame& renderFrame)
|
||||||
|
|
@ -279,51 +338,11 @@ namespace Nz
|
||||||
builder.EndDebugRegion();
|
builder.EndDebugRegion();
|
||||||
}, QueueType::Transfer);
|
}, QueueType::Transfer);
|
||||||
|
|
||||||
auto CombineHash = [](std::size_t currentHash, std::size_t newHash)
|
|
||||||
{
|
|
||||||
return currentHash * 23 + newHash;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Shadow map handling
|
// Shadow map handling
|
||||||
for (std::size_t i = m_shadowCastingLights.FindFirst(); i != m_shadowCastingLights.npos; i = m_shadowCastingLights.FindNext(i))
|
for (std::size_t i = m_shadowCastingLights.FindFirst(); i != m_shadowCastingLights.npos; i = m_shadowCastingLights.FindNext(i))
|
||||||
{
|
{
|
||||||
LightData* lightData = m_lightPool.RetrieveFromIndex(i);
|
LightData* lightData = m_lightPool.RetrieveFromIndex(i);
|
||||||
|
lightData->shadowData->PrepareRendering(renderFrame);
|
||||||
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
|
// Render queues handling
|
||||||
|
|
@ -335,36 +354,8 @@ namespace Nz
|
||||||
const Matrix4f& viewProjMatrix = viewerData.viewer->GetViewerInstance().GetViewProjMatrix();
|
const Matrix4f& viewProjMatrix = viewerData.viewer->GetViewerInstance().GetViewProjMatrix();
|
||||||
|
|
||||||
Frustumf frustum = Frustumf::Extract(viewProjMatrix);
|
Frustumf frustum = Frustumf::Extract(viewProjMatrix);
|
||||||
|
std::size_t visibilityHash = 5;
|
||||||
std::size_t visibilityHash = 5U;
|
const auto& visibleRenderables = FrustumCull(frustum, renderMask, visibilityHash);
|
||||||
|
|
||||||
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));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Lights update don't trigger a rebuild of the depth pre-pass
|
// Lights update don't trigger a rebuild of the depth pre-pass
|
||||||
std::size_t depthVisibilityHash = visibilityHash;
|
std::size_t depthVisibilityHash = visibilityHash;
|
||||||
|
|
@ -381,14 +372,20 @@ namespace Nz
|
||||||
if (renderMask & lightData.renderMask && frustum.Contains(boundingVolume))
|
if (renderMask & lightData.renderMask && frustum.Contains(boundingVolume))
|
||||||
{
|
{
|
||||||
m_visibleLights.push_back(lightIndex);
|
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)
|
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);
|
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))
|
for (std::size_t i = m_shadowCastingLights.FindFirst(); i != m_shadowCastingLights.npos; i = m_shadowCastingLights.FindNext(i))
|
||||||
{
|
{
|
||||||
LightData* lightData = m_lightPool.RetrieveFromIndex(i);
|
LightData* lightData = m_lightPool.RetrieveFromIndex(i);
|
||||||
|
lightData->shadowData->RegisterToFrameGraph(frameGraph);
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto& viewerData : m_viewerPool)
|
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))
|
for (std::size_t i = m_shadowCastingLights.FindFirst(); i != m_shadowCastingLights.npos; i = m_shadowCastingLights.FindNext(i))
|
||||||
{
|
{
|
||||||
LightData* lightData = m_lightPool.RetrieveFromIndex(i);
|
LightData* lightData = m_lightPool.RetrieveFromIndex(i);
|
||||||
forwardPass.AddInput(lightData->shadowMapAttachmentIndex);
|
lightData->shadowData->RegisterPassInputs(forwardPass);
|
||||||
}
|
}
|
||||||
|
|
||||||
viewerData.debugDrawPass->RegisterToFrameGraph(frameGraph, viewerData.forwardColorAttachment, viewerData.debugColorAttachment);
|
viewerData.debugDrawPass->RegisterToFrameGraph(frameGraph, viewerData.forwardColorAttachment, viewerData.debugColorAttachment);
|
||||||
|
|
|
||||||
|
|
@ -165,8 +165,8 @@ namespace Nz
|
||||||
perElementData.lightCount = lightCount;
|
perElementData.lightCount = lightCount;
|
||||||
perElementData.lightUniformBuffer = lightUboView;
|
perElementData.lightUniformBuffer = lightUboView;
|
||||||
|
|
||||||
for (std::size_t i = 0; i < lightCount; ++i)
|
for (std::size_t j = 0; j < lightCount; ++j)
|
||||||
perElementData.shadowMaps[i] = m_pipeline.RetrieveLightShadowmap(m_renderableLights[i].lightIndex);
|
perElementData.shadowMaps[j] = m_pipeline.RetrieveLightShadowmap(m_renderableLights[j].lightIndex);
|
||||||
|
|
||||||
m_lightPerRenderElement.emplace(element, perElementData);
|
m_lightPerRenderElement.emplace(element, perElementData);
|
||||||
}
|
}
|
||||||
|
|
@ -240,18 +240,18 @@ namespace Nz
|
||||||
auto& renderStates = m_renderStates.emplace_back();
|
auto& renderStates = m_renderStates.emplace_back();
|
||||||
renderStates.lightData = lightData.lightUniformBuffer;
|
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)
|
if (!texture)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (texture->GetType() == ImageType::E2D)
|
if (texture->GetType() == ImageType::E2D)
|
||||||
renderStates.shadowMaps2D[i] = texture;
|
renderStates.shadowMaps2D[j] = texture;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
assert(texture->GetType() == ImageType::Cubemap);
|
assert(texture->GetType() == ImageType::Cubemap);
|
||||||
renderStates.shadowMapsCube[i] = texture;
|
renderStates.shadowMapsCube[j] = texture;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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);
|
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*/)
|
void PointLight::UpdateTransform(const Vector3f& position, const Quaternionf& /*rotation*/, const Vector3f& /*scale*/)
|
||||||
{
|
{
|
||||||
UpdatePosition(position);
|
UpdatePosition(position);
|
||||||
|
|
|
||||||
|
|
@ -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/Enums.hpp>
|
||||||
#include <Nazara/Graphics/Graphics.hpp>
|
#include <Nazara/Graphics/Graphics.hpp>
|
||||||
#include <Nazara/Graphics/PredefinedShaderStructs.hpp>
|
#include <Nazara/Graphics/PredefinedShaderStructs.hpp>
|
||||||
|
#include <Nazara/Graphics/SpotLightShadowData.hpp>
|
||||||
#include <Nazara/Math/Vector2.hpp>
|
#include <Nazara/Math/Vector2.hpp>
|
||||||
#include <Nazara/Math/Vector3.hpp>
|
#include <Nazara/Math/Vector3.hpp>
|
||||||
#include <Nazara/Math/Vector4.hpp>
|
#include <Nazara/Math/Vector4.hpp>
|
||||||
|
|
@ -33,6 +34,11 @@ namespace Nz
|
||||||
AccessByOffset<Matrix4f&>(data, lightOffset.lightMemberOffsets.viewProjMatrix) = m_viewProjMatrix;
|
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*/)
|
void SpotLight::UpdateTransform(const Vector3f& position, const Quaternionf& rotation, const Vector3f& /*scale*/)
|
||||||
{
|
{
|
||||||
m_position = position; //< don't call UpdatePosition to prevent double update
|
m_position = position; //< don't call UpdatePosition to prevent double update
|
||||||
|
|
|
||||||
|
|
@ -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;
|
return;
|
||||||
|
|
||||||
const auto& lightEntry = light->GetLightEntry(lightIndex);
|
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)
|
lightEntity->onLightDetach.Connect(entityLight.OnLightDetach, [this, lightEntity](LightComponent* light, std::size_t lightIndex)
|
||||||
|
|
@ -413,7 +413,7 @@ namespace Nz
|
||||||
if (!lightEntry.light)
|
if (!lightEntry.light)
|
||||||
continue;
|
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)
|
if (!lightEntry.light)
|
||||||
continue;
|
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();
|
m_newlyVisibleGfxEntities.clear();
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue