Add Global SDF rendering for Foliage
This commit is contained in:
@@ -14,6 +14,7 @@
|
||||
#endif
|
||||
#include "Engine/Level/SceneQuery.h"
|
||||
#include "Engine/Profiler/ProfilerCPU.h"
|
||||
#include "Engine/Renderer/GlobalSignDistanceFieldPass.h"
|
||||
#include "Engine/Serialization/Serialization.h"
|
||||
#include "Engine/Utilities/Encryption.h"
|
||||
|
||||
@@ -318,6 +319,41 @@ void Foliage::DrawCluster(RenderContext& renderContext, FoliageCluster* cluster,
|
||||
|
||||
#endif
|
||||
|
||||
#if !FOLIAGE_USE_SINGLE_QUAD_TREE
|
||||
|
||||
void Foliage::DrawClusterGlobalSDF(class GlobalSignDistanceFieldPass* globalSDF, const BoundingBox& globalSDFBounds, FoliageCluster* cluster, FoliageType& type)
|
||||
{
|
||||
if (cluster->Children[0])
|
||||
{
|
||||
// Draw children recursive
|
||||
#define DRAW_CLUSTER(idx) \
|
||||
if (globalSDFBounds.Intersects(cluster->Children[idx]->TotalBounds)) \
|
||||
DrawClusterGlobalSDF(globalSDF, globalSDFBounds, cluster->Children[idx], type)
|
||||
DRAW_CLUSTER(0);
|
||||
DRAW_CLUSTER(1);
|
||||
DRAW_CLUSTER(2);
|
||||
DRAW_CLUSTER(3);
|
||||
#undef DRAW_CLUSTER
|
||||
}
|
||||
else
|
||||
{
|
||||
// Draw visible instances
|
||||
for (int32 i = 0; i < cluster->Instances.Count(); i++)
|
||||
{
|
||||
auto& instance = *cluster->Instances[i];
|
||||
if (CollisionsHelper::BoxIntersectsSphere(globalSDFBounds, instance.Bounds))
|
||||
{
|
||||
const Transform transform = _transform.LocalToWorld(instance.Transform);
|
||||
BoundingBox bounds;
|
||||
BoundingBox::FromSphere(instance.Bounds, bounds);
|
||||
globalSDF->RasterizeModelSDF(this, type.Model->SDF, transform, bounds);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
int32 Foliage::GetInstancesCount() const
|
||||
{
|
||||
return Instances.Count();
|
||||
@@ -856,15 +892,10 @@ bool Foliage::Intersects(const Ray& ray, Real& distance, Vector3& normal, int32&
|
||||
|
||||
void Foliage::Draw(RenderContext& renderContext)
|
||||
{
|
||||
if (renderContext.View.Pass == DrawPass::GlobalSDF)
|
||||
return; // TODO: Foliage rendering to Global SDF
|
||||
if (renderContext.View.Pass == DrawPass::GlobalSurfaceAtlas)
|
||||
return; // Not supported
|
||||
if (Instances.IsEmpty())
|
||||
return;
|
||||
auto& view = renderContext.View;
|
||||
|
||||
PROFILE_CPU();
|
||||
auto& view = renderContext.View;
|
||||
|
||||
// Cache data per foliage instance type
|
||||
for (auto& type : FoliageTypes)
|
||||
@@ -883,6 +914,37 @@ void Foliage::Draw(RenderContext& renderContext)
|
||||
}
|
||||
}
|
||||
|
||||
if (renderContext.View.Pass == DrawPass::GlobalSDF)
|
||||
{
|
||||
auto globalSDF = GlobalSignDistanceFieldPass::Instance();
|
||||
BoundingBox globalSDFBounds;
|
||||
globalSDF->GetCullingBounds(globalSDFBounds);
|
||||
//
|
||||
#if FOLIAGE_USE_SINGLE_QUAD_TREE
|
||||
for (auto i = Instances.Begin(); i.IsNotEnd(); ++i)
|
||||
{
|
||||
auto& instance = *i;
|
||||
auto& type = FoliageTypes[instance.Type];
|
||||
if (type._canDraw && CollisionsHelper::BoxIntersectsSphere(globalSDFBounds, instance.Bounds))
|
||||
{
|
||||
const Transform transform = _transform.LocalToWorld(instance.Transform);
|
||||
BoundingBox bounds;
|
||||
BoundingBox::FromSphere(instance.Bounds, bounds);
|
||||
globalSDF->RasterizeModelSDF(this, type.Model->SDF, transform, bounds);
|
||||
}
|
||||
}
|
||||
#else
|
||||
for (auto& type : FoliageTypes)
|
||||
{
|
||||
if (type._canDraw && type.Root)
|
||||
DrawClusterGlobalSDF(globalSDF, globalSDFBounds, type.Root, type);
|
||||
}
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
if (renderContext.View.Pass == DrawPass::GlobalSurfaceAtlas)
|
||||
return; // Not supported
|
||||
|
||||
// Draw visible clusters
|
||||
#if FOLIAGE_USE_SINGLE_QUAD_TREE || !FOLIAGE_USE_DRAW_CALLS_BATCHING
|
||||
Mesh::DrawInfo draw;
|
||||
|
||||
@@ -175,6 +175,9 @@ private:
|
||||
#else
|
||||
void DrawCluster(RenderContext& renderContext, FoliageCluster* cluster, Mesh::DrawInfo& draw);
|
||||
#endif
|
||||
#if !FOLIAGE_USE_SINGLE_QUAD_TREE
|
||||
void DrawClusterGlobalSDF(class GlobalSignDistanceFieldPass* globalSDF, const BoundingBox& globalSDFBounds, FoliageCluster* cluster, FoliageType& type);
|
||||
#endif
|
||||
|
||||
public:
|
||||
/// <summary>
|
||||
|
||||
@@ -537,9 +537,8 @@ bool GlobalSignDistanceFieldPass::Render(RenderContext& renderContext, GPUContex
|
||||
_sdfData = &sdfData;
|
||||
{
|
||||
PROFILE_CPU_NAMED("Draw");
|
||||
BoundingBox cascadeBoundsWorld = cascadeBounds;
|
||||
cascadeBoundsWorld.Minimum += sdfData.Origin;
|
||||
cascadeBoundsWorld.Maximum += sdfData.Origin;
|
||||
BoundingBox cascadeBoundsWorld = cascadeBounds.MakeOffsetted(sdfData.Origin);
|
||||
_cascadeCullingBounds = cascadeBoundsWorld;
|
||||
for (SceneRendering* scene : renderContext.List->Scenes)
|
||||
{
|
||||
for (const auto& e : scene->Actors)
|
||||
|
||||
@@ -47,6 +47,7 @@ private:
|
||||
int32 _cascadeIndex;
|
||||
float _voxelSize;
|
||||
BoundingBox _cascadeBounds;
|
||||
BoundingBox _cascadeCullingBounds;
|
||||
class GlobalSignDistanceFieldCustomBuffer* _sdfData;
|
||||
|
||||
public:
|
||||
@@ -75,6 +76,11 @@ public:
|
||||
/// <param name="output">The output buffer.</param>
|
||||
void RenderDebug(RenderContext& renderContext, GPUContext* context, GPUTexture* output);
|
||||
|
||||
void GetCullingBounds(BoundingBox& bounds) const
|
||||
{
|
||||
bounds = _cascadeCullingBounds;
|
||||
}
|
||||
|
||||
// Rasterize Model SDF into the Global SDF. Call it from actor Draw() method during DrawPass::GlobalSDF.
|
||||
void RasterizeModelSDF(Actor* actor, const ModelBase::SDFData& sdf, const Transform& localToWorld, const BoundingBox& objectBounds);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user