Add frustum culling (WIP)
This commit is contained in:
@@ -54,6 +54,12 @@ namespace Nz
|
||||
void ProcessRenderQueue(CommandBufferBuilder& builder, const RenderQueue<RenderElement*>& renderQueue);
|
||||
void UnregisterMaterialPass(MaterialPass* material);
|
||||
|
||||
struct ElementAABB
|
||||
{
|
||||
Boxf aabb;
|
||||
std::size_t count;
|
||||
};
|
||||
|
||||
struct MaterialData
|
||||
{
|
||||
std::size_t usedCount = 0;
|
||||
@@ -70,7 +76,19 @@ namespace Nz
|
||||
{
|
||||
std::size_t colorAttachment;
|
||||
std::size_t depthStencilAttachment;
|
||||
std::size_t depthPrepassVisibilityHash = 0;
|
||||
std::size_t forwardVisibilityHash = 0;
|
||||
std::vector<ElementAABB> depthPrepassAABB;
|
||||
std::vector<ElementAABB> forwardAABB;
|
||||
std::vector<std::unique_ptr<RenderElement>> depthPrepassRenderElements;
|
||||
std::vector<std::unique_ptr<RenderElement>> forwardRenderElements;
|
||||
RenderQueueRegistry depthPrepassRegistry;
|
||||
RenderQueueRegistry forwardRegistry;
|
||||
RenderQueue<RenderElement*> depthPrepassRenderQueue;
|
||||
RenderQueue<RenderElement*> forwardRenderQueue;
|
||||
ShaderBindingPtr blitShaderBinding;
|
||||
bool rebuildDepthPrepass = true;
|
||||
bool rebuildForwardPass = true;
|
||||
};
|
||||
|
||||
std::size_t m_depthPassIndex;
|
||||
@@ -82,17 +100,9 @@ namespace Nz
|
||||
std::unordered_set<MaterialPass*> m_invalidatedMaterials;
|
||||
std::unordered_set<WorldInstance*> m_invalidatedWorldInstances;
|
||||
std::unordered_set<WorldInstancePtr> m_removedWorldInstances;
|
||||
std::vector<std::unique_ptr<RenderElement>> m_depthPrepassRenderElements;
|
||||
std::vector<std::unique_ptr<RenderElement>> m_forwardRenderElements;
|
||||
std::vector<std::unique_ptr<ElementRenderer>> m_elementRenderers;
|
||||
BakedFrameGraph m_bakedFrameGraph;
|
||||
RenderQueueRegistry m_depthPrepassRegistry;
|
||||
RenderQueueRegistry m_forwardRegistry;
|
||||
RenderQueue<RenderElement*> m_depthPrepassRenderQueue;
|
||||
RenderQueue<RenderElement*> m_forwardRenderQueue;
|
||||
bool m_rebuildDepthPrepass;
|
||||
bool m_rebuildFrameGraph;
|
||||
bool m_rebuildForwardPass;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include <Nazara/Prerequisites.hpp>
|
||||
#include <Nazara/Core/Signal.hpp>
|
||||
#include <Nazara/Graphics/Config.hpp>
|
||||
#include <Nazara/Math/Box.hpp>
|
||||
#include <memory>
|
||||
|
||||
namespace Nz
|
||||
@@ -22,13 +23,14 @@ namespace Nz
|
||||
class NAZARA_GRAPHICS_API InstancedRenderable
|
||||
{
|
||||
public:
|
||||
InstancedRenderable() = default;
|
||||
inline InstancedRenderable(const Boxf& aabb);
|
||||
InstancedRenderable(const InstancedRenderable&) = delete;
|
||||
InstancedRenderable(InstancedRenderable&&) noexcept = default;
|
||||
~InstancedRenderable();
|
||||
|
||||
virtual void BuildElement(std::size_t passIndex, WorldInstance& worldInstance, std::vector<std::unique_ptr<RenderElement>>& elements) const = 0;
|
||||
|
||||
inline const Boxf& GetAABB() const;
|
||||
virtual const std::shared_ptr<Material>& GetMaterial(std::size_t i) const = 0;
|
||||
virtual std::size_t GetMaterialCount() const = 0;
|
||||
|
||||
@@ -36,6 +38,9 @@ namespace Nz
|
||||
InstancedRenderable& operator=(InstancedRenderable&&) noexcept = default;
|
||||
|
||||
NazaraSignal(OnMaterialInvalidated, InstancedRenderable* /*instancedRenderable*/, std::size_t /*materialIndex*/, const std::shared_ptr<Material>& /*newMaterial*/);
|
||||
|
||||
private:
|
||||
Boxf m_aabb;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -7,6 +7,15 @@
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
inline InstancedRenderable::InstancedRenderable(const Boxf& aabb) :
|
||||
m_aabb(aabb)
|
||||
{
|
||||
}
|
||||
|
||||
inline const Boxf& InstancedRenderable::GetAABB() const
|
||||
{
|
||||
return m_aabb;
|
||||
}
|
||||
}
|
||||
|
||||
#include <Nazara/Graphics/DebugOff.hpp>
|
||||
|
||||
@@ -23,7 +23,7 @@ namespace Nz
|
||||
class NAZARA_GRAPHICS_API Model : public InstancedRenderable
|
||||
{
|
||||
public:
|
||||
Model(std::shared_ptr<GraphicalMesh> graphicalMesh);
|
||||
Model(std::shared_ptr<GraphicalMesh> graphicalMesh, const Boxf& aabb);
|
||||
Model(const Model&) = delete;
|
||||
Model(Model&&) noexcept = default;
|
||||
~Model() = default;
|
||||
|
||||
@@ -28,6 +28,12 @@ namespace Nz
|
||||
ViewerInstance(ViewerInstance&&) noexcept = default;
|
||||
~ViewerInstance() = default;
|
||||
|
||||
inline const Matrix4f& GetInvProjectionMatrix() const;
|
||||
inline const Matrix4f& GetInvViewMatrix() const;
|
||||
inline const Matrix4f& GetInvViewProjMatrix() const;
|
||||
inline const Matrix4f& GetProjectionMatrix() const;
|
||||
inline const Matrix4f& GetViewMatrix() const;
|
||||
inline const Matrix4f& GetViewProjMatrix() const;
|
||||
inline std::shared_ptr<AbstractBuffer>& GetInstanceBuffer();
|
||||
inline const std::shared_ptr<AbstractBuffer>& GetInstanceBuffer() const;
|
||||
inline ShaderBinding& GetShaderBinding();
|
||||
|
||||
@@ -8,6 +8,36 @@
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
inline const Matrix4f& ViewerInstance::GetInvProjectionMatrix() const
|
||||
{
|
||||
return m_invProjectionMatrix;
|
||||
}
|
||||
|
||||
inline const Matrix4f& ViewerInstance::GetInvViewMatrix() const
|
||||
{
|
||||
return m_invViewMatrix;
|
||||
}
|
||||
|
||||
inline const Matrix4f& ViewerInstance::GetInvViewProjMatrix() const
|
||||
{
|
||||
return m_invViewProjMatrix;
|
||||
}
|
||||
|
||||
inline const Matrix4f& ViewerInstance::GetProjectionMatrix() const
|
||||
{
|
||||
return m_projectionMatrix;
|
||||
}
|
||||
|
||||
inline const Matrix4f& ViewerInstance::GetViewMatrix() const
|
||||
{
|
||||
return m_viewMatrix;
|
||||
}
|
||||
|
||||
inline const Matrix4f& ViewerInstance::GetViewProjMatrix() const
|
||||
{
|
||||
return m_viewProjMatrix;
|
||||
}
|
||||
|
||||
inline std::shared_ptr<AbstractBuffer>& ViewerInstance::GetInstanceBuffer()
|
||||
{
|
||||
return m_viewerDataBuffer;
|
||||
|
||||
@@ -33,8 +33,10 @@ namespace Nz
|
||||
|
||||
inline std::shared_ptr<AbstractBuffer>& GetInstanceBuffer();
|
||||
inline const std::shared_ptr<AbstractBuffer>& GetInstanceBuffer() const;
|
||||
inline const Matrix4f& GetInvWorldMatrix() const;
|
||||
inline ShaderBinding& GetShaderBinding();
|
||||
inline const ShaderBinding& GetShaderBinding() const;
|
||||
inline const Matrix4f& GetWorldMatrix() const;
|
||||
|
||||
void UpdateBuffers(UploadPool& uploadPool, CommandBufferBuilder& builder);
|
||||
inline void UpdateWorldMatrix(const Matrix4f& worldMatrix);
|
||||
|
||||
@@ -18,6 +18,11 @@ namespace Nz
|
||||
return m_instanceDataBuffer;
|
||||
}
|
||||
|
||||
inline const Matrix4f& WorldInstance::GetInvWorldMatrix() const
|
||||
{
|
||||
return m_invWorldMatrix;
|
||||
}
|
||||
|
||||
inline ShaderBinding& WorldInstance::GetShaderBinding()
|
||||
{
|
||||
return *m_shaderBinding;
|
||||
@@ -28,6 +33,11 @@ namespace Nz
|
||||
return *m_shaderBinding;
|
||||
}
|
||||
|
||||
inline const Matrix4f& WorldInstance::GetWorldMatrix() const
|
||||
{
|
||||
return m_worldMatrix;
|
||||
}
|
||||
|
||||
inline void WorldInstance::UpdateWorldMatrix(const Matrix4f& worldMatrix)
|
||||
{
|
||||
m_worldMatrix = worldMatrix;
|
||||
|
||||
@@ -264,7 +264,7 @@ namespace Nz
|
||||
plane[2] *= invLength;
|
||||
plane[3] *= -invLength;
|
||||
|
||||
m_planes[FrustumPlane::Right].Set(plane);
|
||||
m_planes[UnderlyingCast(FrustumPlane::Right)].Set(plane);
|
||||
|
||||
// Extract the numbers for the LEFT plane
|
||||
plane[0] = clipMatrix[ 3] + clipMatrix[ 0];
|
||||
@@ -279,7 +279,7 @@ namespace Nz
|
||||
plane[2] *= invLength;
|
||||
plane[3] *= -invLength;
|
||||
|
||||
m_planes[FrustumPlane::Left].Set(plane);
|
||||
m_planes[UnderlyingCast(FrustumPlane::Left)].Set(plane);
|
||||
|
||||
// Extract the BOTTOM plane
|
||||
plane[0] = clipMatrix[ 3] + clipMatrix[ 1];
|
||||
@@ -294,7 +294,7 @@ namespace Nz
|
||||
plane[2] *= invLength;
|
||||
plane[3] *= -invLength;
|
||||
|
||||
m_planes[FrustumPlane::Bottom].Set(plane);
|
||||
m_planes[UnderlyingCast(FrustumPlane::Bottom)].Set(plane);
|
||||
|
||||
// Extract the TOP plane
|
||||
plane[0] = clipMatrix[ 3] - clipMatrix[ 1];
|
||||
@@ -309,7 +309,7 @@ namespace Nz
|
||||
plane[2] *= invLength;
|
||||
plane[3] *= -invLength;
|
||||
|
||||
m_planes[FrustumPlane::Top].Set(plane);
|
||||
m_planes[UnderlyingCast(FrustumPlane::Top)].Set(plane);
|
||||
|
||||
// Extract the FAR plane
|
||||
plane[0] = clipMatrix[ 3] - clipMatrix[ 2];
|
||||
@@ -324,7 +324,7 @@ namespace Nz
|
||||
plane[2] *= invLength;
|
||||
plane[3] *= -invLength;
|
||||
|
||||
m_planes[FrustumPlane::Far].Set(plane);
|
||||
m_planes[UnderlyingCast(FrustumPlane::Far)].Set(plane);
|
||||
|
||||
// Extract the NEAR plane
|
||||
plane[0] = clipMatrix[ 3] + clipMatrix[ 2];
|
||||
@@ -339,7 +339,7 @@ namespace Nz
|
||||
plane[2] *= invLength;
|
||||
plane[3] *= -invLength;
|
||||
|
||||
m_planes[FrustumPlane::Near].Set(plane);
|
||||
m_planes[UnderlyingCast(FrustumPlane::Near)].Set(plane);
|
||||
|
||||
// Once planes have been extracted, we must extract points of the frustum
|
||||
// Based on: http://www.gamedev.net/topic/393309-calculating-the-view-frustums-vertices/
|
||||
@@ -354,56 +354,56 @@ namespace Nz
|
||||
corner = invClipMatrix.Transform(corner);
|
||||
corner.Normalize();
|
||||
|
||||
m_corners[BoxCorner::FarLeftBottom] = Vector3<T>(corner.x, corner.y, corner.z);
|
||||
m_corners[UnderlyingCast(BoxCorner::FarLeftBottom)] = Vector3<T>(corner.x, corner.y, corner.z);
|
||||
|
||||
// FarLeftTop
|
||||
corner.Set(T(-1.0), T(1.0), T(1.0));
|
||||
corner = invClipMatrix.Transform(corner);
|
||||
corner.Normalize();
|
||||
|
||||
m_corners[BoxCorner::FarLeftTop] = Vector3<T>(corner.x, corner.y, corner.z);
|
||||
m_corners[UnderlyingCast(BoxCorner::FarLeftTop)] = Vector3<T>(corner.x, corner.y, corner.z);
|
||||
|
||||
// FarRightBottom
|
||||
corner.Set(T(1.0), T(-1.0), T(1.0));
|
||||
corner = invClipMatrix.Transform(corner);
|
||||
corner.Normalize();
|
||||
|
||||
m_corners[BoxCorner::FarRightBottom] = Vector3<T>(corner.x, corner.y, corner.z);
|
||||
m_corners[UnderlyingCast(BoxCorner::FarRightBottom)] = Vector3<T>(corner.x, corner.y, corner.z);
|
||||
|
||||
// FarRightTop
|
||||
corner.Set(T(1.0), T(1.0), T(1.0));
|
||||
corner = invClipMatrix.Transform(corner);
|
||||
corner.Normalize();
|
||||
|
||||
m_corners[BoxCorner::FarRightTop] = Vector3<T>(corner.x, corner.y, corner.z);
|
||||
m_corners[UnderlyingCast(BoxCorner::FarRightTop)] = Vector3<T>(corner.x, corner.y, corner.z);
|
||||
|
||||
// NearLeftBottom
|
||||
corner.Set(T(-1.0), T(-1.0), T(0.0));
|
||||
corner = invClipMatrix.Transform(corner);
|
||||
corner.Normalize();
|
||||
|
||||
m_corners[BoxCorner::NearLeftBottom] = Vector3<T>(corner.x, corner.y, corner.z);
|
||||
m_corners[UnderlyingCast(BoxCorner::NearLeftBottom)] = Vector3<T>(corner.x, corner.y, corner.z);
|
||||
|
||||
// NearLeftTop
|
||||
corner.Set(T(-1.0), T(1.0), T(0.0));
|
||||
corner = invClipMatrix.Transform(corner);
|
||||
corner.Normalize();
|
||||
|
||||
m_corners[BoxCorner::NearLeftTop] = Vector3<T>(corner.x, corner.y, corner.z);
|
||||
m_corners[UnderlyingCast(BoxCorner::NearLeftTop)] = Vector3<T>(corner.x, corner.y, corner.z);
|
||||
|
||||
// NearRightBottom
|
||||
corner.Set(T(1.0), T(-1.0), T(0.0));
|
||||
corner = invClipMatrix.Transform(corner);
|
||||
corner.Normalize();
|
||||
|
||||
m_corners[BoxCorner::NearRightBottom] = Vector3<T>(corner.x, corner.y, corner.z);
|
||||
m_corners[UnderlyingCast(BoxCorner::NearRightBottom)] = Vector3<T>(corner.x, corner.y, corner.z);
|
||||
|
||||
// NearRightTop
|
||||
corner.Set(T(1.0), T(1.0), T(0.0));
|
||||
corner = invClipMatrix.Transform(corner);
|
||||
corner.Normalize();
|
||||
|
||||
m_corners[BoxCorner::NearRightTop] = Vector3<T>(corner.x, corner.y, corner.z);
|
||||
m_corners[UnderlyingCast(BoxCorner::NearRightTop)] = Vector3<T>(corner.x, corner.y, corner.z);
|
||||
}
|
||||
else
|
||||
NazaraWarning("Clip matrix is not invertible, failed to compute frustum corners");
|
||||
@@ -440,9 +440,9 @@ namespace Nz
|
||||
const Vector3<T>& Frustum<T>::GetCorner(BoxCorner corner) const
|
||||
{
|
||||
#ifdef NAZARA_DEBUG
|
||||
if (corner > BoxCornerCount)
|
||||
if (UnderlyingCast(corner) > BoxCornerCount)
|
||||
{
|
||||
NazaraError("Corner not handled (0x" + NumberToString(corner, 16) + ')');
|
||||
NazaraError("Corner not handled (0x" + NumberToString(UnderlyingCast(corner), 16) + ')');
|
||||
|
||||
static Vector3<T> dummy;
|
||||
return dummy;
|
||||
@@ -465,9 +465,9 @@ namespace Nz
|
||||
const Plane<T>& Frustum<T>::GetPlane(FrustumPlane plane) const
|
||||
{
|
||||
#ifdef NAZARA_DEBUG
|
||||
if (plane > FrustumPlane::Max)
|
||||
if (UnderlyingCast(plane) > FrustumPlaneCount)
|
||||
{
|
||||
NazaraError("Frustum plane not handled (0x" + NumberToString(plane, 16) + ')');
|
||||
NazaraError("Frustum plane not handled (0x" + NumberToString(UnderlyingCast(plane), 16) + ')');
|
||||
|
||||
static Plane<T> dummy;
|
||||
return dummy;
|
||||
|
||||
@@ -89,9 +89,9 @@ namespace Nz
|
||||
const Vector3<T>& OrientedBox<T>::GetCorner(BoxCorner corner) const
|
||||
{
|
||||
#ifdef NAZARA_DEBUG
|
||||
if (corner > BoxCornerCount)
|
||||
if (UnderlyingCast(corner) > BoxCornerCount)
|
||||
{
|
||||
NazaraError("Corner not handled (0x" + NumberToString(corner, 16) + ')');
|
||||
NazaraError("Corner not handled (0x" + NumberToString(UnderlyingCast(corner), 16) + ')');
|
||||
|
||||
static Vector3<T> dummy;
|
||||
return dummy;
|
||||
|
||||
Reference in New Issue
Block a user