diff --git a/Source/Engine/Audio/AudioSource.h b/Source/Engine/Audio/AudioSource.h
index 58903912c..07762be2f 100644
--- a/Source/Engine/Audio/AudioSource.h
+++ b/Source/Engine/Audio/AudioSource.h
@@ -207,16 +207,16 @@ public:
API_PROPERTY() void SetAttenuation(float value);
///
- /// Gets the doppler effect factor. Scale for source velocity. Default is 1.
+ /// Gets the doppler effect factor. Scale for source velocity. Default is 1. Used by spatial sources only. Cannot scale the effect up (only dim it).
///
- API_PROPERTY(Attributes="EditorOrder(75), DefaultValue(1.0f), Limit(0, float.MaxValue, 0.1f), EditorDisplay(\"Audio Source\")")
+ API_PROPERTY(Attributes="EditorOrder(75), DefaultValue(1.0f), Limit(0, 1.0f, 0.1f), EditorDisplay(\"Audio Source\")")
FORCE_INLINE float GetDopplerFactor() const
{
return _dopplerFactor;
}
///
- /// Sets the doppler effect factor. Scale for source velocity. Default is 1.
+ /// Sets the doppler effect factor. Scale for source velocity. Default is 1. Used by spatial sources only. Cannot scale the effect up (only dim it).
///
API_PROPERTY() void SetDopplerFactor(float value);
diff --git a/Source/Engine/Audio/OpenAL/AudioBackendOAL.cpp b/Source/Engine/Audio/OpenAL/AudioBackendOAL.cpp
index 715ede74f..8795cc6f9 100644
--- a/Source/Engine/Audio/OpenAL/AudioBackendOAL.cpp
+++ b/Source/Engine/Audio/OpenAL/AudioBackendOAL.cpp
@@ -829,7 +829,6 @@ bool AudioBackendOAL::Base_Init()
}
// Init
- Base_SetDopplerFactor(AudioSettings::Get()->DopplerFactor);
alDistanceModel(AL_INVERSE_DISTANCE_CLAMPED); // Default attenuation model
int32 clampedIndex = Math::Clamp(activeDeviceIndex, -1, Audio::Devices.Count() - 1);
if (clampedIndex == Audio::GetActiveDeviceIndex())
@@ -841,6 +840,7 @@ bool AudioBackendOAL::Base_Init()
if (ALC::IsExtensionSupported("AL_SOFT_source_spatialize"))
ALC::Features = EnumAddFlags(ALC::Features, FeatureFlags::SpatialMultiChannel);
#endif
+ Base_SetDopplerFactor(AudioSettings::Get()->DopplerFactor);
ALC::Inited = true;
// Log service info
diff --git a/Source/Engine/Foliage/Foliage.cpp b/Source/Engine/Foliage/Foliage.cpp
index 116866848..efe89bf5c 100644
--- a/Source/Engine/Foliage/Foliage.cpp
+++ b/Source/Engine/Foliage/Foliage.cpp
@@ -6,14 +6,13 @@
#include "Engine/Core/Log.h"
#include "Engine/Core/Random.h"
#include "Engine/Engine/Engine.h"
+#include "Engine/Graphics/Graphics.h"
#include "Engine/Graphics/RenderTask.h"
+#include "Engine/Graphics/RenderTools.h"
#include "Engine/Graphics/GPUDevice.h"
#include "Engine/Content/Deprecated.h"
#if !FOLIAGE_USE_SINGLE_QUAD_TREE
#include "Engine/Threading/JobSystem.h"
-#if FOLIAGE_USE_DRAW_CALLS_BATCHING
-#include "Engine/Graphics/RenderTools.h"
-#endif
#endif
#include "Engine/Level/SceneQuery.h"
#include "Engine/Profiler/ProfilerCPU.h"
@@ -125,7 +124,7 @@ void Foliage::AddToCluster(ChunkedArrayLODs.Get()[lod].Meshes;
for (int32 meshIndex = 0; meshIndex < meshes.Count(); meshIndex++)
@@ -141,7 +140,7 @@ void Foliage::DrawInstance(RenderContext& renderContext, FoliageInstance& instan
auto* e = result.TryGet(key);
if (!e)
{
- e = &result.Add(key, BatchedDrawCall(renderContext.List))->Value;
+ e = &result.Add(key, BatchedDrawCall(context.RenderContext.List))->Value;
ASSERT_LOW_LAYER(key.Mat);
e->DrawCall.Material = key.Mat;
e->DrawCall.Surface.Lightmap = EnumHasAnyFlags(_staticFlags, StaticFlags::Lightmap) && _scene ? _scene->LightmapsData.GetReadyLightmap(key.Lightmap) : nullptr;
@@ -152,21 +151,18 @@ void Foliage::DrawInstance(RenderContext& renderContext, FoliageInstance& instan
auto& instanceData = e->Instances.AddOne();
Matrix world;
const Transform transform = _transform.LocalToWorld(instance.Transform);
- const Float3 translation = transform.Translation - renderContext.View.Origin;
+ const Float3 translation = transform.Translation - context.ViewOrigin;
Matrix::Transformation(transform.Scale, transform.Orientation, translation, world);
constexpr float worldDeterminantSign = 1.0f;
instanceData.Store(world, world, instance.Lightmap.UVsArea, drawCall.Surface.GeometrySize, instance.Random, worldDeterminantSign, lodDitherFactor);
}
}
-void Foliage::DrawCluster(RenderContext& renderContext, FoliageCluster* cluster, const FoliageType& type, DrawCallsList* drawCallsLists, BatchedDrawCalls& result) const
+void Foliage::DrawCluster(DrawContext& context, FoliageCluster* cluster, DrawCallsList* drawCallsLists, BatchedDrawCalls& result) const
{
// Skip clusters that around too far from view
- const auto lodView = (renderContext.LodProxyView ? renderContext.LodProxyView : &renderContext.View);
- if (Float3::Distance(lodView->Position, cluster->TotalBoundsSphere.Center - lodView->Origin) - (float)cluster->TotalBoundsSphere.Radius > cluster->MaxCullDistance)
+ if (Float3::Distance(context.LodView.Position, cluster->TotalBoundsSphere.Center - context.LodView.Origin) - (float)cluster->TotalBoundsSphere.Radius > cluster->MaxCullDistance)
return;
- const Vector3 viewOrigin = renderContext.View.Origin;
-
//DebugDraw::DrawBox(cluster->Bounds, Color::Red);
// Draw visible children
@@ -178,10 +174,10 @@ void Foliage::DrawCluster(RenderContext& renderContext, FoliageCluster* cluster,
BoundingBox box;
#define DRAW_CLUSTER(idx) \
box = cluster->Children[idx]->TotalBounds; \
- box.Minimum -= viewOrigin; \
- box.Maximum -= viewOrigin; \
- if (renderContext.View.CullingFrustum.Intersects(box)) \
- DrawCluster(renderContext, cluster->Children[idx], type, drawCallsLists, result)
+ box.Minimum -= context.ViewOrigin; \
+ box.Maximum -= context.ViewOrigin; \
+ if (context.RenderContext.View.CullingFrustum.Intersects(box)) \
+ DrawCluster(context, cluster->Children[idx], drawCallsLists, result)
DRAW_CLUSTER(0);
DRAW_CLUSTER(1);
DRAW_CLUSTER(2);
@@ -192,21 +188,22 @@ void Foliage::DrawCluster(RenderContext& renderContext, FoliageCluster* cluster,
{
// Draw visible instances
const auto frame = Engine::FrameCount;
- const auto model = type.Model.Get();
- const auto transitionLOD = renderContext.View.Pass != DrawPass::Depth; // Let the main view pass update LOD transitions
+ const auto model = context.FoliageType.Model.Get();
+ const auto transitionLOD = context.RenderContext.View.Pass != DrawPass::Depth; // Let the main view pass update LOD transitions
// TODO: move DrawState to be stored per-view (so shadows can fade objects on their own)
for (int32 i = 0; i < cluster->Instances.Count(); i++)
{
auto& instance = *cluster->Instances.Get()[i];
BoundingSphere sphere = instance.Bounds;
- sphere.Center -= viewOrigin;
- if (Float3::Distance(lodView->Position, sphere.Center) - (float)sphere.Radius < instance.CullDistance &&
- renderContext.View.CullingFrustum.Intersects(sphere))
+ sphere.Center -= context.ViewOrigin;
+ if (Float3::Distance(context.LodView.Position, sphere.Center) - (float)sphere.Radius < instance.CullDistance &&
+ context.RenderContext.View.CullingFrustum.Intersects(sphere) &&
+ RenderTools::ComputeBoundsScreenRadiusSquared(sphere.Center, sphere.Radius, context.RenderContext.View) * context.ViewScreenSizeSq >= context.MinObjectPixelSizeSq)
{
const auto modelFrame = instance.DrawState.PrevFrame + 1;
// Select a proper LOD index (model may be culled)
- int32 lodIndex = RenderTools::ComputeModelLOD(model, sphere.Center, (float)sphere.Radius, renderContext);
+ int32 lodIndex = RenderTools::ComputeModelLOD(model, sphere.Center, (float)sphere.Radius, context.RenderContext);
if (lodIndex == -1)
{
// Handling model fade-out transition
@@ -231,20 +228,20 @@ void Foliage::DrawCluster(RenderContext& renderContext, FoliageCluster* cluster,
{
const auto prevLOD = model->ClampLODIndex(instance.DrawState.PrevLOD);
const float normalizedProgress = static_cast(instance.DrawState.LODTransition) * (1.0f / 255.0f);
- DrawInstance(renderContext, instance, type, model, prevLOD, normalizedProgress, drawCallsLists, result);
+ DrawInstance(context, instance, model, prevLOD, normalizedProgress, drawCallsLists, result);
}
}
else if (instance.DrawState.LODTransition < 255)
{
const auto prevLOD = model->ClampLODIndex(instance.DrawState.PrevLOD);
const float normalizedProgress = static_cast(instance.DrawState.LODTransition) * (1.0f / 255.0f);
- DrawInstance(renderContext, instance, type, model, prevLOD, normalizedProgress, drawCallsLists, result);
+ DrawInstance(context, instance, model, prevLOD, normalizedProgress, drawCallsLists, result);
}
}
instance.DrawState.PrevFrame = frame;
continue;
}
- lodIndex += renderContext.View.ModelLODBias;
+ lodIndex += context.RenderContext.View.ModelLODBias;
lodIndex = model->ClampLODIndex(lodIndex);
if (transitionLOD)
@@ -278,19 +275,19 @@ void Foliage::DrawCluster(RenderContext& renderContext, FoliageCluster* cluster,
// Draw
if (instance.DrawState.PrevLOD == lodIndex)
{
- DrawInstance(renderContext, instance, type, model, lodIndex, 0.0f, drawCallsLists, result);
+ DrawInstance(context, instance, model, lodIndex, 0.0f, drawCallsLists, result);
}
else if (instance.DrawState.PrevLOD == -1)
{
const float normalizedProgress = static_cast(instance.DrawState.LODTransition) * (1.0f / 255.0f);
- DrawInstance(renderContext, instance, type, model, lodIndex, 1.0f - normalizedProgress, drawCallsLists, result);
+ DrawInstance(context, instance, model, lodIndex, 1.0f - normalizedProgress, drawCallsLists, result);
}
else
{
const auto prevLOD = model->ClampLODIndex(instance.DrawState.PrevLOD);
const float normalizedProgress = static_cast(instance.DrawState.LODTransition) * (1.0f / 255.0f);
- DrawInstance(renderContext, instance, type, model, prevLOD, normalizedProgress, drawCallsLists, result);
- DrawInstance(renderContext, instance, type, model, lodIndex, normalizedProgress - 1.0f, drawCallsLists, result);
+ DrawInstance(context, instance, model, prevLOD, normalizedProgress, drawCallsLists, result);
+ DrawInstance(context, instance, model, lodIndex, normalizedProgress - 1.0f, drawCallsLists, result);
}
//DebugDraw::DrawSphere(instance.Bounds, Color::YellowGreen);
@@ -304,14 +301,11 @@ void Foliage::DrawCluster(RenderContext& renderContext, FoliageCluster* cluster,
#else
-void Foliage::DrawCluster(RenderContext& renderContext, FoliageCluster* cluster, Mesh::DrawInfo& draw)
+void Foliage::DrawCluster(DrawContext& context, FoliageCluster* cluster, Mesh::DrawInfo& draw)
{
// Skip clusters that around too far from view
- const auto lodView = (renderContext.LodProxyView ? renderContext.LodProxyView : &renderContext.View);
- if (Float3::Distance(lodView->Position, cluster->TotalBoundsSphere.Center - lodView->Origin) - (float)cluster->TotalBoundsSphere.Radius > cluster->MaxCullDistance)
+ if (Float3::Distance(context.LodView.Position, cluster->TotalBoundsSphere.Center - context.LodView.Origin) - (float)cluster->TotalBoundsSphere.Radius > cluster->MaxCullDistance)
return;
- const Vector3 viewOrigin = renderContext.View.Origin;
-
//DebugDraw::DrawBox(cluster->Bounds, Color::Red);
// Draw visible children
@@ -323,10 +317,10 @@ void Foliage::DrawCluster(RenderContext& renderContext, FoliageCluster* cluster,
BoundingBox box;
#define DRAW_CLUSTER(idx) \
box = cluster->Children[idx]->TotalBounds; \
- box.Minimum -= viewOrigin; \
- box.Maximum -= viewOrigin; \
- if (renderContext.View.CullingFrustum.Intersects(box)) \
- DrawCluster(renderContext, cluster->Children[idx], draw)
+ box.Minimum -= context.ViewOrigin; \
+ box.Maximum -= context.ViewOrigin; \
+ if (context.RenderContext.View.CullingFrustum.Intersects(box)) \
+ DrawCluster(context, cluster->Children[idx], draw)
DRAW_CLUSTER(0);
DRAW_CLUSTER(1);
DRAW_CLUSTER(2);
@@ -342,16 +336,17 @@ void Foliage::DrawCluster(RenderContext& renderContext, FoliageCluster* cluster,
auto& instance = *cluster->Instances[i];
auto& type = FoliageTypes[instance.Type];
BoundingSphere sphere = instance.Bounds;
- sphere.Center -= viewOrigin;
+ sphere.Center -= context.ViewOrigin;
// Check if can draw this instance
if (type._canDraw &&
- Float3::Distance(lodView->Position, sphere.Center) - (float)sphere.Radius < instance.CullDistance &&
- renderContext.View.CullingFrustum.Intersects(sphere))
+ Float3::Distance(context.LodView.Position, sphere.Center) - (float)sphere.Radius < instance.CullDistance &&
+ context.RenderContext.View.CullingFrustum.Intersects(sphere) &&
+ RenderTools::ComputeBoundsScreenRadiusSquared(sphere.Center, sphere.Radius, context.RenderContext.View) * context.ViewScreenSizeSq >= context.MinObjectPixelSizeSq)
{
Matrix world;
const Transform transform = _transform.LocalToWorld(instance.Transform);
- const Float3 translation = transform.Translation - renderContext.View.Origin;
+ const Float3 translation = transform.Translation - context.ViewOrigin;
Matrix::Transformation(transform.Scale, transform.Orientation, translation, world);
// Disable motion blur
@@ -367,7 +362,7 @@ void Foliage::DrawCluster(RenderContext& renderContext, FoliageCluster* cluster,
draw.PerInstanceRandom = instance.Random;
draw.DrawModes = type.DrawModes;
draw.SetStencilValue(_layer);
- type.Model->Draw(renderContext, draw);
+ type.Model->Draw(context.RenderContext, draw);
//DebugDraw::DrawSphere(instance.Bounds, Color::YellowGreen);
@@ -446,22 +441,50 @@ void Foliage::DrawFoliageJob(int32 i)
PROFILE_CPU();
PROFILE_MEM(Graphics);
const FoliageType& type = FoliageTypes[i];
- if (type.IsReady() && type.Model->CanBeRendered())
+ if (type._canDraw)
{
DrawCallsList drawCallsLists[MODEL_MAX_LODS];
for (RenderContext& renderContext : _renderContextBatch->Contexts)
+ {
+#if !FOLIAGE_USE_SINGLE_QUAD_TREE && FOLIAGE_USE_DRAW_CALLS_BATCHING
DrawType(renderContext, type, drawCallsLists);
+#else
+ Mesh::DrawInfo draw;
+ draw.Flags = GetStaticFlags();
+ draw.DrawModes = (DrawPass)(DrawPass::Default & renderContext.View.Pass);
+ draw.LODBias = 0;
+ draw.ForcedLOD = -1;
+ draw.VertexColors = nullptr;
+ draw.Deformation = nullptr;
+ DrawType(renderContext, type, draw);
+#endif
+ }
}
}
#endif
+#if !FOLIAGE_USE_SINGLE_QUAD_TREE && FOLIAGE_USE_DRAW_CALLS_BATCHING
void Foliage::DrawType(RenderContext& renderContext, const FoliageType& type, DrawCallsList* drawCallsLists)
+#else
+void Foliage::DrawType(RenderContext& renderContext, const FoliageType& type, Mesh::DrawInfo& draw)
+#endif
{
if (!type.Root || !FOLIAGE_CAN_DRAW(renderContext, type))
return;
const DrawPass typeDrawModes = FOLIAGE_GET_DRAW_MODES(renderContext, type);
PROFILE_CPU_ASSET(type.Model);
+ DrawContext context
+ {
+ renderContext,
+ renderContext.LodProxyView ? *renderContext.LodProxyView : renderContext.View,
+ type,
+ renderContext.View.Origin,
+ Math::Square(Graphics::Shadows::MinObjectPixelSize),
+ renderContext.View.ScreenSize.X * renderContext.View.ScreenSize.Y,
+ };
+ if (context.RenderContext.View.Pass != DrawPass::Depth)
+ context.MinObjectPixelSizeSq = 0.0f; // Don't use it in main view
#if FOLIAGE_USE_DRAW_CALLS_BATCHING
// Initialize draw calls for foliage type all LODs meshes
for (int32 lod = 0; lod < type.Model->LODs.Count(); lod++)
@@ -506,7 +529,7 @@ void Foliage::DrawType(RenderContext& renderContext, const FoliageType& type, Dr
// Draw instances of the foliage type
BatchedDrawCalls result(&renderContext.List->Memory);
- DrawCluster(renderContext, type.Root, type, drawCallsLists, result);
+ DrawCluster(context, type.Root, drawCallsLists, result);
// Submit draw calls with valid instances added
for (auto& e : result)
@@ -568,10 +591,22 @@ void Foliage::DrawType(RenderContext& renderContext, const FoliageType& type, Dr
}
}
#else
- DrawCluster(renderContext, type.Root, draw);
+ DrawCluster(context, type.Root, draw);
#endif
}
+void Foliage::InitType(const RenderView& view, FoliageType& type)
+{
+ const DrawPass drawModes = type.DrawModes & view.Pass & view.GetShadowsDrawPassMask(type.ShadowsMode);
+ type._canDraw = type.IsReady() && drawModes != DrawPass::None && type.Model && type.Model->CanBeRendered();
+ for (int32 j = 0; j < type.Entries.Count(); j++)
+ {
+ auto& e = type.Entries[j];
+ e.ReceiveDecals = type.ReceiveDecals != 0;
+ e.ShadowsMode = type.ShadowsMode;
+ }
+}
+
int32 Foliage::GetInstancesCount() const
{
return Instances.Count();
@@ -1131,12 +1166,7 @@ void Foliage::Draw(RenderContext& renderContext)
// Cache data per foliage instance type
for (auto& type : FoliageTypes)
{
- for (int32 j = 0; j < type.Entries.Count(); j++)
- {
- auto& e = type.Entries[j];
- e.ReceiveDecals = type.ReceiveDecals != 0;
- e.ShadowsMode = type.ShadowsMode;
- }
+ InitType(renderContext.View, type);
}
if (renderContext.View.Pass == DrawPass::GlobalSDF)
@@ -1202,12 +1232,7 @@ void Foliage::Draw(RenderContext& renderContext)
// Draw single foliage instance projection into Global Surface Atlas
auto& instance = *(FoliageInstance*)GlobalSurfaceAtlasPass::Instance()->GetCurrentActorObject();
auto& type = FoliageTypes[instance.Type];
- for (int32 i = 0; i < type.Entries.Count(); i++)
- {
- auto& e = type.Entries[i];
- e.ReceiveDecals = type.ReceiveDecals != 0;
- e.ShadowsMode = type.ShadowsMode;
- }
+ InitType(renderContext.View, type);
Matrix world;
const Transform transform = _transform.LocalToWorld(instance.Transform);
renderContext.View.GetWorldMatrix(transform, world);
@@ -1239,8 +1264,9 @@ void Foliage::Draw(RenderContext& renderContext)
draw.LODBias = 0;
draw.ForcedLOD = -1;
draw.VertexColors = nullptr;
+ draw.Deformation = nullptr;
#else
- DrawCallsList drawCallsLists[MODEL_MAX_LODS];
+ DrawCallsList draw[MODEL_MAX_LODS];
#endif
#if FOLIAGE_USE_SINGLE_QUAD_TREE
if (Root)
@@ -1248,7 +1274,7 @@ void Foliage::Draw(RenderContext& renderContext)
#else
for (auto& type : FoliageTypes)
{
- DrawType(renderContext, type, drawCallsLists);
+ DrawType(renderContext, type, draw);
}
#endif
}
@@ -1265,14 +1291,7 @@ void Foliage::Draw(RenderContextBatch& renderContextBatch)
{
// Cache data per foliage instance type
for (FoliageType& type : FoliageTypes)
- {
- for (int32 j = 0; j < type.Entries.Count(); j++)
- {
- auto& e = type.Entries[j];
- e.ReceiveDecals = type.ReceiveDecals != 0;
- e.ShadowsMode = type.ShadowsMode;
- }
- }
+ InitType(view, type);
// Run async job for each foliage type
_renderContextBatch = &renderContextBatch;
diff --git a/Source/Engine/Foliage/Foliage.h b/Source/Engine/Foliage/Foliage.h
index 6f8b36cf4..83ab6206c 100644
--- a/Source/Engine/Foliage/Foliage.h
+++ b/Source/Engine/Foliage/Foliage.h
@@ -158,6 +158,15 @@ public:
private:
void AddToCluster(ChunkedArray& clusters, FoliageCluster* cluster, FoliageInstance& instance);
+ struct DrawContext
+ {
+ RenderContext& RenderContext;
+ const RenderView& LodView;
+ const FoliageType& FoliageType;
+ Vector3 ViewOrigin;
+ float MinObjectPixelSizeSq;
+ float ViewScreenSizeSq;
+ };
#if !FOLIAGE_USE_SINGLE_QUAD_TREE && FOLIAGE_USE_DRAW_CALLS_BATCHING
struct DrawKey
{
@@ -181,10 +190,12 @@ private:
typedef Array> DrawCallsList;
typedef Dictionary BatchedDrawCalls;
- void DrawInstance(RenderContext& renderContext, FoliageInstance& instance, const FoliageType& type, Model* model, int32 lod, float lodDitherFactor, DrawCallsList* drawCallsLists, BatchedDrawCalls& result) const;
- void DrawCluster(RenderContext& renderContext, FoliageCluster* cluster, const FoliageType& type, DrawCallsList* drawCallsLists, BatchedDrawCalls& result) const;
+ void DrawInstance(DrawContext& context, FoliageInstance& instance, Model* model, int32 lod, float lodDitherFactor, DrawCallsList* drawCallsLists, BatchedDrawCalls& result) const;
+ void DrawCluster(DrawContext& context, FoliageCluster* cluster, DrawCallsList* drawCallsLists, BatchedDrawCalls& result) const;
+ void DrawType(RenderContext& renderContext, const FoliageType& type, DrawCallsList* drawCallsLists);
#else
- void DrawCluster(RenderContext& renderContext, FoliageCluster* cluster, Mesh::DrawInfo& draw);
+ void DrawCluster(DrawContext& context, FoliageCluster* cluster, Mesh::DrawInfo& draw);
+ void DrawType(RenderContext& renderContext, const FoliageType& type, Mesh::DrawInfo& draw);
#endif
#if !FOLIAGE_USE_SINGLE_QUAD_TREE
void DrawClusterGlobalSDF(class GlobalSignDistanceFieldPass* globalSDF, const BoundingBox& globalSDFBounds, FoliageCluster* cluster, const FoliageType& type);
@@ -192,7 +203,8 @@ private:
void DrawFoliageJob(int32 i);
RenderContextBatch* _renderContextBatch;
#endif
- void DrawType(RenderContext& renderContext, const FoliageType& type, DrawCallsList* drawCallsLists);
+
+ void InitType(const RenderView& view, FoliageType& type);
public:
///
diff --git a/Source/Engine/Foliage/FoliageType.h b/Source/Engine/Foliage/FoliageType.h
index bbe7e7739..224ed0bd8 100644
--- a/Source/Engine/Foliage/FoliageType.h
+++ b/Source/Engine/Foliage/FoliageType.h
@@ -47,6 +47,7 @@ API_CLASS(Sealed, NoSpawn) class FLAXENGINE_API FoliageType : public ScriptingOb
friend Foliage;
private:
uint8 _isReady : 1;
+ uint8 _canDraw : 1;
public:
///
diff --git a/Source/Engine/Graphics/Graphics.cpp b/Source/Engine/Graphics/Graphics.cpp
index dd3344f5d..97af4f089 100644
--- a/Source/Engine/Graphics/Graphics.cpp
+++ b/Source/Engine/Graphics/Graphics.cpp
@@ -28,6 +28,7 @@ Quality Graphics::GIQuality = Quality::High;
bool Graphics::GICascadesBlending = false;
PostProcessSettings Graphics::PostProcessSettings;
bool Graphics::SpreadWorkload = true;
+float Graphics::Shadows::MinObjectPixelSize = 2.0f;
bool Graphics::PostProcessing::ColorGradingVolumeLUT = true;
#if GRAPHICS_API_NULL
diff --git a/Source/Engine/Graphics/Graphics.h b/Source/Engine/Graphics/Graphics.h
index d328431b0..571a7f086 100644
--- a/Source/Engine/Graphics/Graphics.h
+++ b/Source/Engine/Graphics/Graphics.h
@@ -85,8 +85,17 @@ public:
API_FIELD() static bool SpreadWorkload;
public:
+ // Shadows rendering configuration.
+ API_CLASS(Static, Attributes="DebugCommand") class FLAXENGINE_API Shadows
+ {
+ DECLARE_SCRIPTING_TYPE_MINIMAL(Shadows);
+
+ // The minimum size in pixels of objects to cast shadows. Improves performance by skipping too small objects (eg. sub-pixel) from rendering into shadow maps.
+ API_FIELD() static float MinObjectPixelSize;
+ };
+
// Post Processing effects rendering configuration.
- API_CLASS(Static, Attributes = "DebugCommand") class FLAXENGINE_API PostProcessing
+ API_CLASS(Static, Attributes="DebugCommand") class FLAXENGINE_API PostProcessing
{
DECLARE_SCRIPTING_TYPE_MINIMAL(PostProcessing);
diff --git a/Source/Engine/Renderer/RenderList.cpp b/Source/Engine/Renderer/RenderList.cpp
index ac643b4e8..2bb206d6e 100644
--- a/Source/Engine/Renderer/RenderList.cpp
+++ b/Source/Engine/Renderer/RenderList.cpp
@@ -695,6 +695,7 @@ void RenderList::AddDrawCall(const RenderContextBatch& renderContextBatch, DrawP
DrawCallsLists[(int32)DrawCallsListType::MotionVectors].Indices.Add(index);
}
}
+ float minObjectPixelSizeSq = Math::Square(Graphics::Shadows::MinObjectPixelSize);
for (int32 i = 1; i < renderContextBatch.Contexts.Count(); i++)
{
const RenderContext& renderContext = renderContextBatch.Contexts.Get()[i];
@@ -702,7 +703,8 @@ void RenderList::AddDrawCall(const RenderContextBatch& renderContextBatch, DrawP
drawModes = modes & renderContext.View.Pass;
if (drawModes != DrawPass::None &&
(staticFlags & renderContext.View.StaticFlagsMask) == renderContext.View.StaticFlagsCompare &&
- renderContext.View.CullingFrustum.Intersects(bounds))
+ renderContext.View.CullingFrustum.Intersects(bounds) &&
+ RenderTools::ComputeBoundsScreenRadiusSquared(bounds.Center, bounds.Radius, renderContext.View) * (renderContext.View.ScreenSize.X * renderContext.View.ScreenSize.Y) >= minObjectPixelSizeSq)
{
renderContext.List->ShadowDepthDrawCallsList.Indices.Add(index);
}