Add Global SDF rendering for Foliage

This commit is contained in:
Wojciech Figat
2022-08-10 14:27:08 +02:00
parent 6a1378ebdb
commit 6c9b1f6be0
4 changed files with 79 additions and 9 deletions

View File

@@ -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;

View File

@@ -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>

View File

@@ -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)

View File

@@ -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);