diff --git a/Source/Engine/Content/Assets/Model.h b/Source/Engine/Content/Assets/Model.h
index f63bc9749..c561ad2e2 100644
--- a/Source/Engine/Content/Assets/Model.h
+++ b/Source/Engine/Content/Assets/Model.h
@@ -89,6 +89,24 @@ public:
Meshes.Get()[i].Draw(renderContext, material, world, flags, receiveDecals, drawModes, perInstanceRandom, sortOrder);
}
+ ///
+ /// Draws the meshes from the model LOD.
+ ///
+ /// The rendering context batch.
+ /// The material to use for rendering.
+ /// The world transformation of the model.
+ /// The object static flags.
+ /// True if rendered geometry can receive decals, otherwise false.
+ /// The draw passes to use for rendering this object.
+ /// The random per-instance value (normalized to range 0-1).
+ /// Object sorting key.
+ /// The object shadows casting mode.
+ void Draw(API_PARAM(Ref) const RenderContextBatch& renderContextBatch, MaterialBase* material, API_PARAM(Ref) const Matrix& world, StaticFlags flags = StaticFlags::None, bool receiveDecals = true, DrawPass drawModes = DrawPass::Default, float perInstanceRandom = 0.0f, int8 sortOrder = 0, ShadowsCastingMode shadowsMode = ShadowsCastingMode::All) const
+ {
+ for (int32 i = 0; i < Meshes.Count(); i++)
+ Meshes.Get()[i].Draw(renderContextBatch, material, world, flags, receiveDecals, drawModes, perInstanceRandom, sortOrder, 0, shadowsMode);
+ }
+
///
/// Draws all the meshes from the model LOD.
///
diff --git a/Source/Engine/Foliage/Foliage.cpp b/Source/Engine/Foliage/Foliage.cpp
index bf9b94b50..e797d77db 100644
--- a/Source/Engine/Foliage/Foliage.cpp
+++ b/Source/Engine/Foliage/Foliage.cpp
@@ -1205,16 +1205,16 @@ bool Foliage::Intersects(const Ray& ray, Real& distance, Vector3& normal, int32&
return false;
}
-void Foliage::Draw(RenderContext& renderContext)
+void Foliage::Draw(RenderContextBatch& renderContextBatch)
{
if (Instances.IsEmpty())
return;
- PROFILE_CPU();
+ const RenderContext& renderContext = renderContextBatch.GetMainContext();
const RenderView& view = renderContext.View;
- PreDraw(view);
if (renderContext.View.Pass == DrawPass::GlobalSDF)
{
+ // Draw into Global SDF
auto globalSDF = GlobalSignDistanceFieldPass::Instance();
BoundingBox globalSDFBounds;
globalSDF->GetCullingData(globalSDFBounds);
@@ -1240,7 +1240,6 @@ void Foliage::Draw(RenderContext& renderContext)
#endif
return;
}
-
if (renderContext.View.Pass == DrawPass::GlobalSurfaceAtlas)
{
// Draw foliage instances into Global Surface Atlas
@@ -1294,34 +1293,8 @@ void Foliage::Draw(RenderContext& renderContext)
return;
}
- // Draw visible clusters
-#if FOLIAGE_USE_SINGLE_QUAD_TREE || !FOLIAGE_USE_DRAW_CALLS_BATCHING
- Mesh::DrawInfo draw;
- draw.Flags = GetStaticFlags();
- draw.DrawModes = (DrawPass)(DrawPass::Default & view.Pass);
-#endif
-#if FOLIAGE_USE_SINGLE_QUAD_TREE
- if (Root)
- DrawCluster(renderContext, Root, draw);
-#else
- for (auto& type : FoliageTypes)
- {
-#if !FOLIAGE_USE_SINGLE_QUAD_TREE && FOLIAGE_USE_DRAW_CALLS_BATCHING
- DrawCallsList draw[MODEL_MAX_LODS];
-#endif
- DrawType(renderContext, type, draw);
- }
-#endif
-}
-
-void Foliage::Draw(RenderContextBatch& renderContextBatch)
-{
- if (Instances.IsEmpty())
- return;
-
#if !FOLIAGE_USE_SINGLE_QUAD_TREE
// Run async job for each foliage type
- const RenderView& view = renderContextBatch.GetMainContext().View;
if (EnumHasAnyFlags(view.Pass, DrawPass::GBuffer) && !(view.Pass & (DrawPass::GlobalSDF | DrawPass::GlobalSurfaceAtlas)) && renderContextBatch.EnableAsync)
{
PreDraw(view);
@@ -1336,8 +1309,28 @@ void Foliage::Draw(RenderContextBatch& renderContextBatch)
}
#endif
- // Fallback to default rendering
- Actor::Draw(renderContextBatch);
+ // Draw visible clusters
+#if FOLIAGE_USE_SINGLE_QUAD_TREE || !FOLIAGE_USE_DRAW_CALLS_BATCHING
+ Mesh::DrawInfo draw;
+ draw.Flags = GetStaticFlags();
+ draw.DrawModes = (DrawPass)(DrawPass::Default & view.Pass);
+#endif
+#if FOLIAGE_USE_SINGLE_QUAD_TREE
+ if (Root)
+ {
+ for (RenderContext& c : renderContextBatch.Contexts)
+ DrawCluster(c, Root, draw);
+ }
+#else
+ for (auto& type : FoliageTypes)
+ {
+#if !FOLIAGE_USE_SINGLE_QUAD_TREE && FOLIAGE_USE_DRAW_CALLS_BATCHING
+ DrawCallsList draw[MODEL_MAX_LODS];
+#endif
+ for (RenderContext& c : renderContextBatch.Contexts)
+ DrawType(c, type, draw);
+ }
+#endif
}
bool Foliage::IntersectsItself(const Ray& ray, Real& distance, Vector3& normal)
diff --git a/Source/Engine/Foliage/Foliage.h b/Source/Engine/Foliage/Foliage.h
index b428ad356..801e51198 100644
--- a/Source/Engine/Foliage/Foliage.h
+++ b/Source/Engine/Foliage/Foliage.h
@@ -239,7 +239,6 @@ private:
public:
// [Actor]
- void Draw(RenderContext& renderContext) override;
void Draw(RenderContextBatch& renderContextBatch) override;
bool IntersectsItself(const Ray& ray, Real& distance, Vector3& normal) override;
void Serialize(SerializeStream& stream, const void* otherObj) override;
diff --git a/Source/Engine/Graphics/Models/Mesh.cpp b/Source/Engine/Graphics/Models/Mesh.cpp
index 423c7f118..27959b727 100644
--- a/Source/Engine/Graphics/Models/Mesh.cpp
+++ b/Source/Engine/Graphics/Models/Mesh.cpp
@@ -251,6 +251,42 @@ void Mesh::Draw(const RenderContext& renderContext, MaterialBase* material, cons
renderContext.List->AddDrawCall(renderContext, drawModes, flags, drawCall, receiveDecals, sortOrder);
}
+void Mesh::Draw(const RenderContextBatch& renderContextBatch, MaterialBase* material, const Matrix& world, StaticFlags flags, bool receiveDecals, DrawPass drawModes, float perInstanceRandom, int8 sortOrder, uint8 stencilValue, ShadowsCastingMode shadowsMode) const
+{
+ if (!material || !material->IsSurface() || !IsInitialized())
+ return;
+ drawModes &= material->GetDrawModes();
+ if (drawModes == DrawPass::None)
+ return;
+
+ // Setup draw call
+ DrawCall drawCall;
+ drawCall.Geometry.IndexBuffer = _indexBuffer;
+ drawCall.Geometry.VertexBuffers[0] = _vertexBuffers[0];
+ drawCall.Geometry.VertexBuffers[1] = _vertexBuffers[1];
+ drawCall.Geometry.VertexBuffers[2] = _vertexBuffers[2];
+ drawCall.Draw.IndicesCount = _triangles * 3;
+ drawCall.InstanceCount = 1;
+ drawCall.Material = material;
+ drawCall.World = world;
+ drawCall.ObjectPosition = drawCall.World.GetTranslation();
+ drawCall.ObjectRadius = (float)_sphere.Radius * drawCall.World.GetScaleVector().GetAbsolute().MaxValue();
+ drawCall.Surface.GeometrySize = _box.GetSize();
+ drawCall.Surface.PrevWorld = world;
+ drawCall.PerInstanceRandom = perInstanceRandom;
+ drawCall.StencilValue = stencilValue;
+ const RenderContext& renderContext = renderContextBatch.GetMainContext();
+#if GPU_ENABLE_DEVELOPMENT
+ const ViewMode viewMode = renderContext.View.Mode;
+ if (viewMode == ViewMode::LightmapUVsDensity || viewMode == ViewMode::LODPreview)
+ GBufferPass::AddIndexBufferToModelLOD(_indexBuffer, &((Model*)_model)->LODs[_lodIndex]);
+#endif
+
+ // Push draw call to the render list
+ BoundingSphere bounds(drawCall.ObjectPosition, drawCall.ObjectRadius);
+ renderContext.List->AddDrawCall(renderContextBatch, drawModes, flags, shadowsMode, bounds, drawCall, receiveDecals, sortOrder);
+}
+
void Mesh::Draw(const RenderContext& renderContext, const DrawInfo& info, float lodDitherFactor) const
{
const auto& entry = info.Buffer->At(_materialSlotIndex);
diff --git a/Source/Engine/Graphics/Models/Mesh.h b/Source/Engine/Graphics/Models/Mesh.h
index 7a23e4d3c..6848096e8 100644
--- a/Source/Engine/Graphics/Models/Mesh.h
+++ b/Source/Engine/Graphics/Models/Mesh.h
@@ -142,6 +142,21 @@ public:
/// Object stencil value.
API_FUNCTION() void Draw(API_PARAM(Ref) const RenderContext& renderContext, MaterialBase* material, API_PARAM(Ref) const Matrix& world, StaticFlags flags = StaticFlags::None, bool receiveDecals = true, DrawPass drawModes = DrawPass::Default, float perInstanceRandom = 0.0f, int8 sortOrder = 0, uint8 stencilValue = 0) const;
+ ///
+ /// Draws the mesh.
+ ///
+ /// The rendering context batch.
+ /// The material to use for rendering.
+ /// The world transformation of the model.
+ /// The object static flags.
+ /// True if rendered geometry can receive decals, otherwise false.
+ /// The draw passes to use for rendering this object.
+ /// The random per-instance value (normalized to range 0-1).
+ /// Object sorting key.
+ /// Object stencil value.
+ /// The object shadows casting mode.
+ void Draw(API_PARAM(Ref) const RenderContextBatch& renderContextBatch, MaterialBase* material, API_PARAM(Ref) const Matrix& world, StaticFlags flags = StaticFlags::None, bool receiveDecals = true, DrawPass drawModes = DrawPass::Default, float perInstanceRandom = 0.0f, int8 sortOrder = 0, uint8 stencilValue = 0, ShadowsCastingMode shadowsMode = ShadowsCastingMode::All) const;
+
///
/// Draws the mesh.
///
diff --git a/Source/Engine/Level/Actor.cpp b/Source/Engine/Level/Actor.cpp
index d22a10f99..e20defb43 100644
--- a/Source/Engine/Level/Actor.cpp
+++ b/Source/Engine/Level/Actor.cpp
@@ -19,7 +19,6 @@
#include "Engine/Core/Collections/CollectionPoolCache.h"
#include "Engine/Core/Math/Double4x4.h"
#include "Engine/Debug/Exceptions/JsonParseException.h"
-#include "Engine/Graphics/RenderContext.h"
#include "Engine/Physics/Physics.h"
#include "Engine/Profiler/ProfilerCPU.h"
#include "Engine/Profiler/ProfilerMemory.h"
@@ -1485,15 +1484,8 @@ void Actor::InitializeHierarchy()
Children[i]->InitializeHierarchy();
}
-void Actor::Draw(RenderContext& renderContext)
-{
-}
-
void Actor::Draw(RenderContextBatch& renderContextBatch)
{
- // Default impl calls single-context
- for (RenderContext& renderContext : renderContextBatch.Contexts)
- Draw(renderContext);
}
#if USE_EDITOR
diff --git a/Source/Engine/Level/Actor.h b/Source/Engine/Level/Actor.h
index 79944fb51..4d2e930d2 100644
--- a/Source/Engine/Level/Actor.h
+++ b/Source/Engine/Level/Actor.h
@@ -738,13 +738,7 @@ public:
public:
///
- /// Draws this actor. Called by Scene Rendering service. This call is more optimized than generic Draw (eg. geometry is rendered during all pass types but other actors are drawn only during GBufferFill pass).
- ///
- /// The rendering context.
- virtual void Draw(RenderContext& renderContext);
-
- ///
- /// Draws this actor. Called by Scene Rendering service. This call is more optimized than generic Draw (eg. geometry is rendered during all pass types but other actors are drawn only during GBufferFill pass).
+ /// Draws this actor. Called by Scene Rendering to collect draw calls from objects.
///
/// The rendering context batch (eg, main view and shadow projections).
virtual void Draw(RenderContextBatch& renderContextBatch);
diff --git a/Source/Engine/Level/Actors/AnimatedModel.cpp b/Source/Engine/Level/Actors/AnimatedModel.cpp
index b07ed19e2..4f45504b8 100644
--- a/Source/Engine/Level/Actors/AnimatedModel.cpp
+++ b/Source/Engine/Level/Actors/AnimatedModel.cpp
@@ -1250,64 +1250,14 @@ void AnimatedModel::Update()
_lastMinDstSqr = MAX_Real;
}
-void AnimatedModel::Draw(RenderContext& renderContext)
-{
- if (!SkinnedModel || !SkinnedModel->IsLoaded())
- return;
- if (renderContext.View.Pass == DrawPass::GlobalSDF)
- return;
- if (renderContext.View.Pass == DrawPass::GlobalSurfaceAtlas)
- return; // Not supported
- auto drawState = renderContext.Buffers->GetGeometryDrawState(&GetScene()->Rendering, _sceneRenderingKey, this);
- ACTOR_GET_WORLD_MATRIX(this, view, world);
- GEOMETRY_DRAW_STATE_EVENT_BEGIN(drawState, world);
-
- _lastMinDstSqr = Math::Min(_lastMinDstSqr, Vector3::DistanceSquared(_transform.Translation, renderContext.View.WorldPosition));
- if (_bones.IsAllocated)
- {
- // Flush skinning data with GPU
- if (_bones.IsDirty)
- _bones.Flush();
-
- SkinnedMesh::DrawInfo draw;
- draw.Buffer = &Entries;
- draw.SkinningBones = RenderListExtension.GlobalBuffer;
- draw.SkinningBonesOffset = _bones.GlobalBufferOffset / sizeof(Matrix3x4);
- draw.WithPrevBones = _bones.HasPrevBones && _bones.IsPrevFlushed;
- if (draw.WithPrevBones)
- {
- draw.PrevBonesOffset = _bones.BonesCount;
- if (_bones.IsPrevBones)
- {
- draw.SkinningBonesOffset += draw.PrevBonesOffset;
- draw.PrevBonesOffset = -draw.PrevBonesOffset;
- }
- }
- draw.World = &world;
- draw.DrawState = drawState;
- draw.Deformation = _deformation;
- PRAGMA_DISABLE_DEPRECATION_WARNINGS
- draw.DrawModes = DrawModes & renderContext.View.GetShadowsDrawPassMask(ShadowsMode);
- PRAGMA_ENABLE_DEPRECATION_WARNINGS
- draw.Bounds = _sphere;
- draw.Bounds.Center -= renderContext.View.Origin;
- draw.PerInstanceRandom = GetPerInstanceRandom();
- draw.LODBias = LODBias;
- draw.ForcedLOD = ForcedLOD;
- draw.SortOrder = SortOrder;
- draw.SetStencilValue(_layer);
-
- SkinnedModel->Draw(renderContext, draw);
- }
-
- GEOMETRY_DRAW_STATE_EVENT_END(drawState, world);
-}
-
void AnimatedModel::Draw(RenderContextBatch& renderContextBatch)
{
- if (!SkinnedModel || !SkinnedModel->IsLoaded())
+ auto model = SkinnedModel.Get();
+ if (!model || !model->IsLoaded())
return;
const RenderContext& renderContext = renderContextBatch.GetMainContext();
+ if (renderContext.View.Pass == DrawPass::GlobalSDF || renderContext.View.Pass == DrawPass::GlobalSurfaceAtlas)
+ return; // Not supported
Matrix world;
const Float3 translation = _transform.Translation - renderContext.View.Origin;
Matrix::Transformation(_transform.Scale, _transform.Orientation, translation, world);
@@ -1331,6 +1281,7 @@ void AnimatedModel::Draw(RenderContextBatch& renderContextBatch)
draw.PrevBonesOffset = _bones.BonesCount;
if (_bones.IsPrevBones)
{
+ // Swap bone buffer chunks
draw.SkinningBonesOffset += draw.PrevBonesOffset;
draw.PrevBonesOffset = -draw.PrevBonesOffset;
}
@@ -1347,7 +1298,7 @@ void AnimatedModel::Draw(RenderContextBatch& renderContextBatch)
draw.SortOrder = SortOrder;
draw.SetStencilValue(_layer);
- PRAGMA_DISABLE_DEPRECATION_WARNINGS
+PRAGMA_DISABLE_DEPRECATION_WARNINGS
if (ShadowsMode != ShadowsCastingMode::All)
{
// To handle old ShadowsMode option for all meshes we need to call per-context drawing (no batching opportunity)
@@ -1355,14 +1306,14 @@ void AnimatedModel::Draw(RenderContextBatch& renderContextBatch)
for (auto& e : renderContextBatch.Contexts)
{
draw.DrawModes = DrawModes & e.View.GetShadowsDrawPassMask(ShadowsMode);
- SkinnedModel->Draw(e, draw);
+ model->Draw(e, draw);
}
}
else
{
- SkinnedModel->Draw(renderContextBatch, draw);
+ model->Draw(renderContextBatch, draw);
}
- PRAGMA_ENABLE_DEPRECATION_WARNINGS
+PRAGMA_ENABLE_DEPRECATION_WARNINGS
}
GEOMETRY_DRAW_STATE_EVENT_END(drawState, world);
diff --git a/Source/Engine/Level/Actors/AnimatedModel.h b/Source/Engine/Level/Actors/AnimatedModel.h
index 97cebde7c..f18bde120 100644
--- a/Source/Engine/Level/Actors/AnimatedModel.h
+++ b/Source/Engine/Level/Actors/AnimatedModel.h
@@ -494,7 +494,6 @@ private:
public:
// [ModelInstanceActor]
bool HasContentLoaded() const override;
- void Draw(RenderContext& renderContext) override;
void Draw(RenderContextBatch& renderContextBatch) override;
#if USE_EDITOR
void OnDebugDrawSelected() override;
diff --git a/Source/Engine/Level/Actors/Camera.cpp b/Source/Engine/Level/Actors/Camera.cpp
index e6a08cba7..a43f17232 100644
--- a/Source/Engine/Level/Actors/Camera.cpp
+++ b/Source/Engine/Level/Actors/Camera.cpp
@@ -355,8 +355,9 @@ bool Camera::HasContentLoaded() const
return _previewModel == nullptr || _previewModel->IsLoaded();
}
-void Camera::Draw(RenderContext& renderContext)
+void Camera::Draw(RenderContextBatch& renderContextBatch)
{
+ const RenderContext& renderContext = renderContextBatch.GetMainContext();
if (EnumHasAnyFlags(renderContext.View.Flags, ViewFlags::EditorSprites)
&& renderContext.View.CullingFrustum.Intersects(_previewModelBox)
&& _previewModel
diff --git a/Source/Engine/Level/Actors/Camera.h b/Source/Engine/Level/Actors/Camera.h
index db728f97d..56abe6599 100644
--- a/Source/Engine/Level/Actors/Camera.h
+++ b/Source/Engine/Level/Actors/Camera.h
@@ -266,7 +266,7 @@ public:
#if USE_EDITOR
BoundingBox GetEditorBox() const override;
bool HasContentLoaded() const override;
- void Draw(RenderContext& renderContext) override;
+ void Draw(RenderContextBatch& renderContextBatch) override;
void OnDebugDrawSelected() override;
#endif
void Serialize(SerializeStream& stream, const void* otherObj) override;
diff --git a/Source/Engine/Level/Actors/Decal.cpp b/Source/Engine/Level/Actors/Decal.cpp
index 1a9e94fb6..a07ad4ac6 100644
--- a/Source/Engine/Level/Actors/Decal.cpp
+++ b/Source/Engine/Level/Actors/Decal.cpp
@@ -67,8 +67,9 @@ void Decal::OnLayerChanged()
GetSceneRendering()->UpdateActor(this, _sceneRenderingKey, ISceneRenderingListener::Layer);
}
-void Decal::Draw(RenderContext& renderContext)
+void Decal::Draw(RenderContextBatch& renderContextBatch)
{
+ const RenderContext& renderContext = renderContextBatch.GetMainContext();
MaterialBase* material = Material;
if (EnumHasAnyFlags(renderContext.View.Flags, ViewFlags::Decals) &&
EnumHasAnyFlags(renderContext.View.Pass, DrawPass::GBuffer) &&
diff --git a/Source/Engine/Level/Actors/Decal.h b/Source/Engine/Level/Actors/Decal.h
index 068a4447e..7ec096f01 100644
--- a/Source/Engine/Level/Actors/Decal.h
+++ b/Source/Engine/Level/Actors/Decal.h
@@ -74,7 +74,7 @@ public:
BoundingBox GetEditorBox() const override;
#endif
void OnLayerChanged() override;
- void Draw(RenderContext& renderContext) override;
+ void Draw(RenderContextBatch& renderContextBatch) override;
void Serialize(SerializeStream& stream, const void* otherObj) override;
void Deserialize(DeserializeStream& stream, ISerializeModifier* modifier) override;
bool IntersectsItself(const Ray& ray, Real& distance, Vector3& normal) override;
diff --git a/Source/Engine/Level/Actors/DirectionalLight.cpp b/Source/Engine/Level/Actors/DirectionalLight.cpp
index e80182d5d..61625087e 100644
--- a/Source/Engine/Level/Actors/DirectionalLight.cpp
+++ b/Source/Engine/Level/Actors/DirectionalLight.cpp
@@ -17,8 +17,9 @@ DirectionalLight::DirectionalLight(const SpawnParams& params)
Brightness = 8.0f;
}
-void DirectionalLight::Draw(RenderContext& renderContext)
+void DirectionalLight::Draw(RenderContextBatch& renderContextBatch)
{
+ const RenderContext& renderContext = renderContextBatch.GetMainContext();
float brightness = Brightness;
AdjustBrightness(renderContext.View, brightness);
Float3 color = Color.ToFloat3() * (Color.A * brightness);
diff --git a/Source/Engine/Level/Actors/DirectionalLight.h b/Source/Engine/Level/Actors/DirectionalLight.h
index fc00a31a1..6a5c9941d 100644
--- a/Source/Engine/Level/Actors/DirectionalLight.h
+++ b/Source/Engine/Level/Actors/DirectionalLight.h
@@ -62,7 +62,7 @@ public:
public:
// [LightWithShadow]
- void Draw(RenderContext& renderContext) override;
+ void Draw(RenderContextBatch& renderContextBatch) override;
void Serialize(SerializeStream& stream, const void* otherObj) override;
void Deserialize(DeserializeStream& stream, ISerializeModifier* modifier) override;
bool IntersectsItself(const Ray& ray, Real& distance, Vector3& normal) override;
diff --git a/Source/Engine/Level/Actors/EnvironmentProbe.cpp b/Source/Engine/Level/Actors/EnvironmentProbe.cpp
index 53a16caeb..899cb886f 100644
--- a/Source/Engine/Level/Actors/EnvironmentProbe.cpp
+++ b/Source/Engine/Level/Actors/EnvironmentProbe.cpp
@@ -181,8 +181,9 @@ void EnvironmentProbe::UpdateBounds()
GetSceneRendering()->UpdateActor(this, _sceneRenderingKey, ISceneRenderingListener::Bounds);
}
-void EnvironmentProbe::Draw(RenderContext& renderContext)
+void EnvironmentProbe::Draw(RenderContextBatch& renderContextBatch)
{
+ const RenderContext& renderContext = renderContextBatch.GetMainContext();
if (Brightness > ZeroTolerance &&
EnumHasAnyFlags(renderContext.View.Flags, ViewFlags::Reflections) &&
EnumHasAnyFlags(renderContext.View.Pass, DrawPass::GBuffer))
diff --git a/Source/Engine/Level/Actors/EnvironmentProbe.h b/Source/Engine/Level/Actors/EnvironmentProbe.h
index bf65222ee..0da01d13b 100644
--- a/Source/Engine/Level/Actors/EnvironmentProbe.h
+++ b/Source/Engine/Level/Actors/EnvironmentProbe.h
@@ -158,7 +158,7 @@ public:
return BoundingBox(_transform.Translation - size, _transform.Translation + size);
}
#endif
- void Draw(RenderContext& renderContext) override;
+ void Draw(RenderContextBatch& renderContextBatch) override;
#if USE_EDITOR
void OnDebugDrawSelected() override;
#endif
diff --git a/Source/Engine/Level/Actors/ExponentialHeightFog.cpp b/Source/Engine/Level/Actors/ExponentialHeightFog.cpp
index b8dff5f67..f10819b38 100644
--- a/Source/Engine/Level/Actors/ExponentialHeightFog.cpp
+++ b/Source/Engine/Level/Actors/ExponentialHeightFog.cpp
@@ -31,10 +31,9 @@ ExponentialHeightFog::ExponentialHeightFog(const SpawnParams& params)
#endif
}
-void ExponentialHeightFog::Draw(RenderContext& renderContext)
+void ExponentialHeightFog::Draw(RenderContextBatch& renderContextBatch)
{
- // Render only when shader is valid and fog can be rendered
- // Do not render exponential fog in orthographic views
+ const RenderContext& renderContext = renderContextBatch.GetMainContext();
if (EnumHasAnyFlags(renderContext.View.Flags, ViewFlags::Fog)
&& EnumHasAnyFlags(renderContext.View.Pass, DrawPass::GBuffer)
&& _shader
diff --git a/Source/Engine/Level/Actors/ExponentialHeightFog.h b/Source/Engine/Level/Actors/ExponentialHeightFog.h
index c0e5407d2..cd1fed743 100644
--- a/Source/Engine/Level/Actors/ExponentialHeightFog.h
+++ b/Source/Engine/Level/Actors/ExponentialHeightFog.h
@@ -147,7 +147,7 @@ public:
return BoundingBox(_transform.Translation - size, _transform.Translation + size);
}
#endif
- void Draw(RenderContext& renderContext) override;
+ void Draw(RenderContextBatch& renderContextBatch) override;
void Serialize(SerializeStream& stream, const void* otherObj) override;
void Deserialize(DeserializeStream& stream, ISerializeModifier* modifier) override;
bool HasContentLoaded() const override;
diff --git a/Source/Engine/Level/Actors/PointLight.cpp b/Source/Engine/Level/Actors/PointLight.cpp
index fd18ed700..89ab2763b 100644
--- a/Source/Engine/Level/Actors/PointLight.cpp
+++ b/Source/Engine/Level/Actors/PointLight.cpp
@@ -81,8 +81,9 @@ void PointLight::OnTransformChanged()
UpdateBounds();
}
-void PointLight::Draw(RenderContext& renderContext)
+void PointLight::Draw(RenderContextBatch& renderContextBatch)
{
+ const RenderContext& renderContext = renderContextBatch.GetMainContext();
float brightness = ComputeBrightness();
AdjustBrightness(renderContext.View, brightness);
Float3 position;
diff --git a/Source/Engine/Level/Actors/PointLight.h b/Source/Engine/Level/Actors/PointLight.h
index 9ea4d6b64..6e54dbe82 100644
--- a/Source/Engine/Level/Actors/PointLight.h
+++ b/Source/Engine/Level/Actors/PointLight.h
@@ -91,7 +91,7 @@ private:
public:
// [LightWithShadow]
- void Draw(RenderContext& renderContext) override;
+ void Draw(RenderContextBatch& renderContextBatch) override;
#if USE_EDITOR
void OnDebugDraw() override;
void OnDebugDrawSelected() override;
diff --git a/Source/Engine/Level/Actors/Sky.cpp b/Source/Engine/Level/Actors/Sky.cpp
index 7b7e1f57b..773546b76 100644
--- a/Source/Engine/Level/Actors/Sky.cpp
+++ b/Source/Engine/Level/Actors/Sky.cpp
@@ -83,8 +83,9 @@ void Sky::InitConfig(ShaderAtmosphericFogData& config) const
}
}
-void Sky::Draw(RenderContext& renderContext)
+void Sky::Draw(RenderContextBatch& renderContextBatch)
{
+ const RenderContext& renderContext = renderContextBatch.GetMainContext();
if (HasContentLoaded() && EnumHasAnyFlags(renderContext.View.Flags, ViewFlags::Sky))
{
// Ensure to have pipeline state cache created
diff --git a/Source/Engine/Level/Actors/Sky.h b/Source/Engine/Level/Actors/Sky.h
index 61bb048ef..8da1236e8 100644
--- a/Source/Engine/Level/Actors/Sky.h
+++ b/Source/Engine/Level/Actors/Sky.h
@@ -69,7 +69,7 @@ public:
return BoundingBox(_transform.Translation - size, _transform.Translation + size);
}
#endif
- void Draw(RenderContext& renderContext) override;
+ void Draw(RenderContextBatch& renderContextBatch) override;
void Serialize(SerializeStream& stream, const void* otherObj) override;
void Deserialize(DeserializeStream& stream, ISerializeModifier* modifier) override;
bool HasContentLoaded() const override;
diff --git a/Source/Engine/Level/Actors/SkyLight.cpp b/Source/Engine/Level/Actors/SkyLight.cpp
index 697a58cfa..7f4e588c9 100644
--- a/Source/Engine/Level/Actors/SkyLight.cpp
+++ b/Source/Engine/Level/Actors/SkyLight.cpp
@@ -108,8 +108,9 @@ void SkyLight::UpdateBounds()
GetSceneRendering()->UpdateActor(this, _sceneRenderingKey, ISceneRenderingListener::Bounds);
}
-void SkyLight::Draw(RenderContext& renderContext)
+void SkyLight::Draw(RenderContextBatch& renderContextBatch)
{
+ RenderContext& renderContext = renderContextBatch.GetMainContext();
float brightness = Brightness;
AdjustBrightness(renderContext.View, brightness);
const Float3 position = GetPosition() - renderContext.View.Origin;
diff --git a/Source/Engine/Level/Actors/SkyLight.h b/Source/Engine/Level/Actors/SkyLight.h
index f23199cba..96feea9fe 100644
--- a/Source/Engine/Level/Actors/SkyLight.h
+++ b/Source/Engine/Level/Actors/SkyLight.h
@@ -107,7 +107,7 @@ private:
public:
// [Light]
- void Draw(RenderContext& renderContext) override;
+ void Draw(RenderContextBatch& renderContextBatch) override;
#if USE_EDITOR
void OnDebugDrawSelected() override;
#endif
diff --git a/Source/Engine/Level/Actors/Skybox.cpp b/Source/Engine/Level/Actors/Skybox.cpp
index 24e3fd2f6..be05265cd 100644
--- a/Source/Engine/Level/Actors/Skybox.cpp
+++ b/Source/Engine/Level/Actors/Skybox.cpp
@@ -29,7 +29,7 @@ void Skybox::setupProxy()
}
}
-void Skybox::Draw(RenderContext& renderContext)
+void Skybox::Draw(RenderContextBatch& renderContextBatch)
{
bool isReady;
if (CustomMaterial)
@@ -41,6 +41,7 @@ void Skybox::Draw(RenderContext& renderContext)
setupProxy();
isReady = _proxyMaterial && _proxyMaterial->IsReady();
}
+ const RenderContext& renderContext = renderContextBatch.GetMainContext();
if (isReady && EnumHasAnyFlags(renderContext.View.Flags, ViewFlags::Sky))
{
renderContext.List->Sky = this;
diff --git a/Source/Engine/Level/Actors/Skybox.h b/Source/Engine/Level/Actors/Skybox.h
index fb831df44..9112ad51f 100644
--- a/Source/Engine/Level/Actors/Skybox.h
+++ b/Source/Engine/Level/Actors/Skybox.h
@@ -63,7 +63,7 @@ public:
return BoundingBox(_transform.Translation - size, _transform.Translation + size);
}
#endif
- void Draw(RenderContext& renderContext) override;
+ void Draw(RenderContextBatch& renderContextBatch) override;
void Serialize(SerializeStream& stream, const void* otherObj) override;
void Deserialize(DeserializeStream& stream, ISerializeModifier* modifier) override;
bool HasContentLoaded() const override;
diff --git a/Source/Engine/Level/Actors/SplineModel.cpp b/Source/Engine/Level/Actors/SplineModel.cpp
index 2e7e8d4fa..1f702d59e 100644
--- a/Source/Engine/Level/Actors/SplineModel.cpp
+++ b/Source/Engine/Level/Actors/SplineModel.cpp
@@ -382,12 +382,12 @@ bool SplineModel::HasContentLoaded() const
return (Model == nullptr || Model->IsLoaded()) && Entries.HasContentLoaded();
}
-void SplineModel::Draw(RenderContext& renderContext)
+void SplineModel::Draw(RenderContextBatch& renderContextBatch)
{
- const DrawPass actorDrawModes = DrawModes & renderContext.View.Pass;
- if (!_spline || !Model || !Model->IsLoaded() || !Model->CanBeRendered() || actorDrawModes == DrawPass::None)
- return;
auto model = Model.Get();
+ if (!_spline || !model || !model->IsLoaded() || !model->CanBeRendered())
+ return;
+ const RenderContext& renderContext = renderContextBatch.GetMainContext();
if (renderContext.View.Pass == DrawPass::GlobalSDF)
return; // TODO: Spline Model rendering to Global SDF
if (renderContext.View.Pass == DrawPass::GlobalSurfaceAtlas)
@@ -466,14 +466,14 @@ void SplineModel::Draw(RenderContext& renderContext)
// Check if skip rendering
const auto shadowsMode = entry.ShadowsMode & slot.ShadowsMode;
- const auto drawModes = actorDrawModes & renderContext.View.GetShadowsDrawPassMask(shadowsMode) & material->GetDrawModes();
+ const auto drawModes = DrawModes & material->GetDrawModes();
if (drawModes == DrawPass::None)
continue;
// Submit draw call
mesh->GetDrawCallGeometry(drawCall);
drawCall.Material = material;
- renderContext.List->AddDrawCall(renderContext, drawModes, _staticFlags, drawCall, entry.ReceiveDecals);
+ renderContext.List->AddDrawCall(renderContextBatch, drawModes, _staticFlags, shadowsMode, instanceSphere, drawCall, entry.ReceiveDecals);
}
}
}
diff --git a/Source/Engine/Level/Actors/SplineModel.h b/Source/Engine/Level/Actors/SplineModel.h
index a9b105a8e..c9bf6893a 100644
--- a/Source/Engine/Level/Actors/SplineModel.h
+++ b/Source/Engine/Level/Actors/SplineModel.h
@@ -110,7 +110,7 @@ private:
public:
// [ModelInstanceActor]
bool HasContentLoaded() const override;
- void Draw(RenderContext& renderContext) override;
+ void Draw(RenderContextBatch& renderContextBatch) override;
bool IntersectsItself(const Ray& ray, Real& distance, Vector3& normal) override;
void Serialize(SerializeStream& stream, const void* otherObj) override;
void Deserialize(DeserializeStream& stream, ISerializeModifier* modifier) override;
diff --git a/Source/Engine/Level/Actors/SpotLight.cpp b/Source/Engine/Level/Actors/SpotLight.cpp
index 4617c5a76..164b5680d 100644
--- a/Source/Engine/Level/Actors/SpotLight.cpp
+++ b/Source/Engine/Level/Actors/SpotLight.cpp
@@ -128,8 +128,9 @@ void SpotLight::OnTransformChanged()
UpdateBounds();
}
-void SpotLight::Draw(RenderContext& renderContext)
+void SpotLight::Draw(RenderContextBatch& renderContextBatch)
{
+ const RenderContext& renderContext = renderContextBatch.GetMainContext();
float brightness = ComputeBrightness();
AdjustBrightness(renderContext.View, brightness);
Float3 position;
diff --git a/Source/Engine/Level/Actors/SpotLight.h b/Source/Engine/Level/Actors/SpotLight.h
index fa9e5dc47..f58130ec1 100644
--- a/Source/Engine/Level/Actors/SpotLight.h
+++ b/Source/Engine/Level/Actors/SpotLight.h
@@ -117,7 +117,7 @@ private:
public:
// [LightWithShadow]
- void Draw(RenderContext& renderContext) override;
+ void Draw(RenderContextBatch& renderContextBatch) override;
#if USE_EDITOR
void OnDebugDraw() override;
void OnDebugDrawSelected() override;
diff --git a/Source/Engine/Level/Actors/StaticModel.cpp b/Source/Engine/Level/Actors/StaticModel.cpp
index 48f08544c..5d9370d86 100644
--- a/Source/Engine/Level/Actors/StaticModel.cpp
+++ b/Source/Engine/Level/Actors/StaticModel.cpp
@@ -366,20 +366,22 @@ bool StaticModel::HasContentLoaded() const
return (Model == nullptr || Model->IsLoaded()) && Entries.HasContentLoaded();
}
-void StaticModel::Draw(RenderContext& renderContext)
+void StaticModel::Draw(RenderContextBatch& renderContextBatch)
{
- if (!Model || !Model->IsLoaded() || !Model->CanBeRendered())
+ auto model = Model.Get();
+ if (!model || !model->IsLoaded())
return;
+ const RenderContext& renderContext = renderContextBatch.GetMainContext();
if (renderContext.View.Pass == DrawPass::GlobalSDF)
{
- if (EnumHasAnyFlags(_drawModes, DrawPass::GlobalSDF) && Model->SDF.Texture)
- GlobalSignDistanceFieldPass::Instance()->RasterizeModelSDF(this, Model->SDF, _transform, _box);
+ if (EnumHasAnyFlags(_drawModes, DrawPass::GlobalSDF) && model->SDF.Texture)
+ GlobalSignDistanceFieldPass::Instance()->RasterizeModelSDF(this, model->SDF, _transform, _box);
return;
}
if (renderContext.View.Pass == DrawPass::GlobalSurfaceAtlas)
{
- if (EnumHasAnyFlags(_drawModes, DrawPass::GlobalSurfaceAtlas) && Model->SDF.Texture)
- GlobalSurfaceAtlasPass::Instance()->RasterizeActor(this, this, _sphere, _transform, Model->LODs.Last().GetBox());
+ if (EnumHasAnyFlags(_drawModes, DrawPass::GlobalSurfaceAtlas) && model->SDF.Texture)
+ GlobalSurfaceAtlasPass::Instance()->RasterizeActor(this, this, _sphere, _transform, model->LODs.Last().GetBox());
return;
}
auto drawState = renderContext.Buffers->GetGeometryDrawState(&GetScene()->Rendering, _sceneRenderingKey, this);
@@ -410,45 +412,7 @@ void StaticModel::Draw(RenderContext& renderContext)
draw.LightmapScale = _scaleInLightmap;
#endif
- Model->Draw(renderContext, draw);
-
- GEOMETRY_DRAW_STATE_EVENT_END(drawState, world);
-}
-
-void StaticModel::Draw(RenderContextBatch& renderContextBatch)
-{
- if (!Model || !Model->IsLoaded())
- return;
- const RenderContext& renderContext = renderContextBatch.GetMainContext();
- auto drawState = renderContext.Buffers->GetGeometryDrawState(&GetScene()->Rendering, _sceneRenderingKey, this);
- ACTOR_GET_WORLD_MATRIX(this, view, world);
- GEOMETRY_DRAW_STATE_EVENT_BEGIN(drawState, world);
- if (_vertexColorsDirty)
- FlushVertexColors();
-
- Mesh::DrawInfo draw;
- draw.Buffer = &Entries;
- draw.World = &world;
- draw.DrawState = drawState;
- draw.Deformation = _deformation;
- draw.Lightmap = _scene && Lightmap.TextureIndex != -1 ? _scene->LightmapsData.GetReadyLightmap(Lightmap.TextureIndex) : nullptr;
- draw.LightmapUVs = &Lightmap.UVsArea;
- draw.Flags = _staticFlags;
- draw.DrawModes = _drawModes;
- draw.Bounds = _sphere;
- draw.Bounds.Center -= renderContext.View.Origin;
- draw.PerInstanceRandom = GetPerInstanceRandom();
- draw.LODBias = _lodBias;
- draw.ForcedLOD = _forcedLod;
- draw.SortOrder = _sortOrder;
- draw.VertexColors = _vertexColorsCount ? _vertexColorsBuffer : nullptr;
- draw.SetStencilValue(_layer);
-#if GPU_ENABLE_DEVELOPMENT
- if (HasStaticFlag(StaticFlags::Lightmap))
- draw.LightmapScale = _scaleInLightmap;
-#endif
-
- Model->Draw(renderContextBatch, draw);
+ model->Draw(renderContextBatch, draw);
GEOMETRY_DRAW_STATE_EVENT_END(drawState, world);
}
diff --git a/Source/Engine/Level/Actors/StaticModel.h b/Source/Engine/Level/Actors/StaticModel.h
index d7e63144b..f2fdd7f0e 100644
--- a/Source/Engine/Level/Actors/StaticModel.h
+++ b/Source/Engine/Level/Actors/StaticModel.h
@@ -169,7 +169,6 @@ private:
public:
// [ModelInstanceActor]
bool HasContentLoaded() const override;
- void Draw(RenderContext& renderContext) override;
void Draw(RenderContextBatch& renderContextBatch) override;
bool IntersectsItself(const Ray& ray, Real& distance, Vector3& normal) override;
void Serialize(SerializeStream& stream, const void* otherObj) override;
diff --git a/Source/Engine/Level/Scene/SceneRendering.cpp b/Source/Engine/Level/Scene/SceneRendering.cpp
index 2a58155ba..b9dbcfbe5 100644
--- a/Source/Engine/Level/Scene/SceneRendering.cpp
+++ b/Source/Engine/Level/Scene/SceneRendering.cpp
@@ -276,7 +276,7 @@ void SceneRendering::DrawActorsJob(int32 i)
FOR_EACH_BATCH_ACTOR
if (CHECK_ACTOR_SINGLE_FRUSTUM)
{
- DRAW_ACTOR(mainContext);
+ DRAW_ACTOR(*_drawBatch);
}
}
}
diff --git a/Source/Engine/Particles/ParticleEffect.cpp b/Source/Engine/Particles/ParticleEffect.cpp
index f0c235284..d703e3c26 100644
--- a/Source/Engine/Particles/ParticleEffect.cpp
+++ b/Source/Engine/Particles/ParticleEffect.cpp
@@ -605,21 +605,13 @@ bool ParticleEffect::HasContentLoaded() const
return true;
}
-void ParticleEffect::Draw(RenderContext& renderContext)
-{
- if (renderContext.View.Pass == DrawPass::GlobalSDF ||
- renderContext.View.Pass == DrawPass::GlobalSurfaceAtlas ||
- EnumHasNoneFlags(renderContext.View.Flags, ViewFlags::Particles))
- return;
- _lastMinDstSqr = Math::Min(_lastMinDstSqr, Vector3::DistanceSquared(GetPosition(), renderContext.View.WorldPosition));
- RenderContextBatch renderContextBatch(renderContext);
- Particles::DrawParticles(renderContextBatch, this);
-}
-
void ParticleEffect::Draw(RenderContextBatch& renderContextBatch)
{
- const RenderView& mainView = renderContextBatch.GetMainContext().View;
- if (EnumHasNoneFlags(mainView.Flags, ViewFlags::Particles))
+ const RenderContext& renderContext = renderContextBatch.GetMainContext();
+ const RenderView& mainView = renderContext.View;
+ if (mainView.Pass == DrawPass::GlobalSDF ||
+ mainView.Pass == DrawPass::GlobalSurfaceAtlas ||
+ EnumHasNoneFlags(mainView.Flags, ViewFlags::Particles))
return;
Particles::DrawParticles(renderContextBatch, this);
diff --git a/Source/Engine/Particles/ParticleEffect.h b/Source/Engine/Particles/ParticleEffect.h
index 5ae56603a..4317cd41e 100644
--- a/Source/Engine/Particles/ParticleEffect.h
+++ b/Source/Engine/Particles/ParticleEffect.h
@@ -414,7 +414,6 @@ private:
public:
// [Actor]
bool HasContentLoaded() const override;
- void Draw(RenderContext& renderContext) override;
void Draw(RenderContextBatch& renderContextBatch) override;
#if USE_EDITOR
void OnDebugDrawSelected() override;
diff --git a/Source/Engine/Physics/Actors/Cloth.cpp b/Source/Engine/Physics/Actors/Cloth.cpp
index b60fe38f7..8e4fc4184 100644
--- a/Source/Engine/Physics/Actors/Cloth.cpp
+++ b/Source/Engine/Physics/Actors/Cloth.cpp
@@ -908,12 +908,6 @@ void Cloth::OnPostUpdate()
}
}
-void Cloth::Draw(RenderContext& renderContext)
-{
- // Update min draw distance for the next simulation tick
- _lastMinDstSqr = Math::Min(_lastMinDstSqr, Vector3::DistanceSquared(_transform.Translation, renderContext.View.WorldPosition));
-}
-
void Cloth::Draw(RenderContextBatch& renderContextBatch)
{
// Update min draw distance for the next simulation tick
diff --git a/Source/Engine/Physics/Actors/Cloth.h b/Source/Engine/Physics/Actors/Cloth.h
index 8d6f13370..d2637a7dc 100644
--- a/Source/Engine/Physics/Actors/Cloth.h
+++ b/Source/Engine/Physics/Actors/Cloth.h
@@ -347,7 +347,6 @@ private:
public:
// [Actor]
- void Draw(RenderContext& renderContext) override;
void Draw(RenderContextBatch& renderContextBatch) override;
bool IntersectsItself(const Ray& ray, Real& distance, Vector3& normal) override;
void Serialize(SerializeStream& stream, const void* otherObj) override;
diff --git a/Source/Engine/Renderer/GI/GlobalSurfaceAtlasPass.cpp b/Source/Engine/Renderer/GI/GlobalSurfaceAtlasPass.cpp
index 9b44b9cc7..b8bc5d6ae 100644
--- a/Source/Engine/Renderer/GI/GlobalSurfaceAtlasPass.cpp
+++ b/Source/Engine/Renderer/GI/GlobalSurfaceAtlasPass.cpp
@@ -17,7 +17,6 @@
#include "Engine/Graphics/GPUDevice.h"
#include "Engine/Graphics/GPUPass.h"
#include "Engine/Graphics/Graphics.h"
-#include "Engine/Graphics/RenderTask.h"
#include "Engine/Graphics/RenderContext.h"
#include "Engine/Graphics/RenderBuffers.h"
#include "Engine/Graphics/RenderTargetPool.h"
@@ -219,7 +218,7 @@ public:
Array FailedObjects;
Array PrevFrameFailedObjects;
Array AsyncScenesDrawCounters[2];
- RenderContext AsyncRenderContext;
+ RenderContextBatch AsyncRenderContextBatch;
GlobalSurfaceAtlasCustomBuffer()
: ObjectsBuffer(256 * (GLOBAL_SURFACE_ATLAS_OBJECT_DATA_STRIDE + GLOBAL_SURFACE_ATLAS_TILE_DATA_STRIDE * 3 / 4), PixelFormat::R32G32B32A32_Float, false, TEXT("GlobalSurfaceAtlas.ObjectsBuffer"))
@@ -280,9 +279,10 @@ public:
auto drawCategory = index >= 0 ? SceneRendering::SceneDrawAsync : SceneRendering::SceneDraw;
const Vector3 cullingPos(CullingPosDistance);
const Real cullingDistance = CullingPosDistance.W;
- const uint32 viewMask = AsyncRenderContext.View.RenderLayersMask;
+ const RenderContext& renderContext = AsyncRenderContextBatch.GetMainContext();
+ const uint32 viewMask = renderContext.View.RenderLayersMask;
const float minObjectRadius = MinObjectRadius;
- auto& scenes = AsyncRenderContext.List->Scenes;
+ auto& scenes = renderContext.List->Scenes;
auto& drawCounters = AsyncScenesDrawCounters[index >= 0 ? 1 : 0];
// Draw all scenes and all actors (cooperative with other jobs)
@@ -297,7 +297,7 @@ public:
if (e.Bounds.Radius >= minObjectRadius && viewMask & e.LayerMask && Vector3::Distance(e.Bounds.Center, cullingPos) - e.Bounds.Radius < cullingDistance)
{
//PROFILE_CPU_ACTOR(e.Actor);
- e.Actor->Draw(AsyncRenderContext);
+ e.Actor->Draw(AsyncRenderContextBatch);
}
}
}
@@ -373,8 +373,8 @@ public:
// TODO: add DetailsScale param to adjust quality of scene details in Global Surface Atlas
MinObjectRadius = METERS_TO_UNITS(0.2f); // Skip too small objects
CullingPosDistance = Vector4(renderContext.View.Position, distance);
- AsyncRenderContext = renderContext;
- AsyncRenderContext.View.Pass = DrawPass::GlobalSurfaceAtlas;
+ AsyncRenderContextBatch = RenderContext(renderContext);
+ AsyncRenderContextBatch.GetMainContext().View.Pass = DrawPass::GlobalSurfaceAtlas;
// Each scene uses own atomic counter to draw all actors
AsyncScenesDrawCounters[0].Resize(renderContext.List->Scenes.Count());
@@ -1135,7 +1135,8 @@ bool GlobalSurfaceAtlasPass::Render(RenderContext& renderContext, GPUContext* co
PROFILE_GPU_CPU_NAMED("Rasterize Tiles");
// Init rendering context
- RenderContext renderContextTiles = renderContext;
+ RenderContextBatch renderContextBatchTiles(renderContext);
+ RenderContext& renderContextTiles = renderContextBatchTiles.GetMainContext();
renderContextTiles.List = RenderList::GetFromPool();
renderContextTiles.View.Pass = DrawPass::GBuffer | DrawPass::GlobalSurfaceAtlas;
renderContextTiles.View.Mode = ViewMode::Default;
@@ -1218,7 +1219,7 @@ bool GlobalSurfaceAtlasPass::Render(RenderContext& renderContext, GPUContext* co
// Collect draw calls for the object
_currentActorObject = actorObject;
- object.Actor->Draw(renderContextTiles);
+ object.Actor->Draw(renderContextBatchTiles);
// Render all tiles into the atlas
#if GLOBAL_SURFACE_ATLAS_DEBUG_DRAW_OBJECTS
diff --git a/Source/Engine/Renderer/GlobalSignDistanceFieldPass.cpp b/Source/Engine/Renderer/GlobalSignDistanceFieldPass.cpp
index 52bde969b..5537c4caf 100644
--- a/Source/Engine/Renderer/GlobalSignDistanceFieldPass.cpp
+++ b/Source/Engine/Renderer/GlobalSignDistanceFieldPass.cpp
@@ -251,7 +251,7 @@ public:
// Async objects drawing cache
Array> AsyncDrawWaitLabels;
- RenderContext AsyncRenderContext;
+ RenderContextBatch AsyncRenderContextBatch;
~GlobalSignDistanceFieldCustomBuffer()
{
@@ -351,8 +351,8 @@ public:
// Setup data for rendering
if (FrameIndex++ > 128)
FrameIndex = 0;
- AsyncRenderContext = renderContext;
- AsyncRenderContext.View.Pass = DrawPass::GlobalSDF;
+ AsyncRenderContextBatch = RenderContextBatch(renderContext);
+ AsyncRenderContextBatch.GetMainContext().View.Pass = DrawPass::GlobalSDF;
DebugOverdraw = renderContext.View.Mode == ViewMode::GlobalSDFOverdraw;
const bool useCache = !reset && !GLOBAL_SDF_DEBUG_FORCE_REDRAW;
static_assert(GLOBAL_SDF_RASTERIZE_CHUNK_SIZE % GLOBAL_SDF_RASTERIZE_GROUP_SIZE == 0, "Invalid chunk size for Global SDF rasterization group size.");
@@ -511,12 +511,13 @@ void GlobalSignDistanceFieldCustomBuffer::DrawCascadeActors(const CascadeData& c
{
PROFILE_CPU();
const BoundingBox cullingBounds = cascade.CullingBounds;
- const uint32 viewMask = AsyncRenderContext.View.RenderLayersMask;
+ auto& renderContext = AsyncRenderContextBatch.GetMainContext();
+ const uint32 viewMask = renderContext.View.RenderLayersMask;
// TODO: add scene detail scale factor to PostFx settings (eg. to increase or decrease scene details and quality)
const float minObjectRadius = Math::Max(20.0f, cascade.VoxelSize * 2.0f); // Skip too small objects for this cascade
int32 actorsDrawn = 0;
SceneRendering::DrawCategory drawCategories[] = { SceneRendering::SceneDraw, SceneRendering::SceneDrawAsync };
- for (auto* scene : AsyncRenderContext.List->Scenes)
+ for (auto* scene : renderContext.List->Scenes)
{
for (SceneRendering::DrawCategory drawCategory : drawCategories)
{
@@ -526,7 +527,7 @@ void GlobalSignDistanceFieldCustomBuffer::DrawCascadeActors(const CascadeData& c
if (e.Bounds.Radius >= minObjectRadius && viewMask & e.LayerMask && CollisionsHelper::BoxIntersectsSphere(cullingBounds, e.Bounds))
{
//PROFILE_CPU_ACTOR(e.Actor);
- e.Actor->Draw(AsyncRenderContext);
+ e.Actor->Draw(AsyncRenderContextBatch);
#if COMPILE_WITH_PROFILER
actorsDrawn++;
#endif
diff --git a/Source/Engine/Renderer/RenderList.cpp b/Source/Engine/Renderer/RenderList.cpp
index 4b68a8662..2ffb606fe 100644
--- a/Source/Engine/Renderer/RenderList.cpp
+++ b/Source/Engine/Renderer/RenderList.cpp
@@ -749,7 +749,7 @@ void RenderList::AddDrawCall(const RenderContextBatch& renderContextBatch, DrawP
// Add draw call to proper draw lists
DrawPass modes = drawModes & mainRenderContext.View.GetShadowsDrawPassMask(shadowsMode);
drawModes = modes & mainRenderContext.View.Pass;
- if (drawModes != DrawPass::None && mainRenderContext.View.CullingFrustum.Intersects(bounds))
+ if (drawModes != DrawPass::None && (mainRenderContext.View.IsCullingDisabled || mainRenderContext.View.CullingFrustum.Intersects(bounds)))
{
if ((drawModes & DrawPass::Depth) != DrawPass::None)
{
diff --git a/Source/Engine/Renderer/Renderer.cpp b/Source/Engine/Renderer/Renderer.cpp
index fce1d09d3..5b359b8f3 100644
--- a/Source/Engine/Renderer/Renderer.cpp
+++ b/Source/Engine/Renderer/Renderer.cpp
@@ -341,6 +341,12 @@ void Renderer::DrawPostFxMaterial(GPUContext* context, const RenderContext& rend
}
void Renderer::DrawActors(RenderContext& renderContext, const Array& customActors)
+{
+ RenderContextBatch renderContextBatch(renderContext);
+ DrawActors(renderContextBatch, customActors);
+}
+
+void Renderer::DrawActors(RenderContextBatch& renderContextBatch, const Array& customActors)
{
if (customActors.HasItems())
{
@@ -348,13 +354,12 @@ void Renderer::DrawActors(RenderContext& renderContext, const Array& cus
for (Actor* actor : customActors)
{
if (actor && actor->GetIsActive())
- actor->Draw(renderContext);
+ actor->Draw(renderContextBatch);
}
}
else
{
// Draw scene actors
- RenderContextBatch renderContextBatch(renderContext);
JobSystem::SetJobStartingOnDispatch(false);
Level::DrawActors(renderContextBatch, SceneRendering::DrawCategory::SceneDraw);
Level::DrawActors(renderContextBatch, SceneRendering::DrawCategory::SceneDrawAsync);
diff --git a/Source/Engine/Renderer/Renderer.h b/Source/Engine/Renderer/Renderer.h
index 5f0a90be1..80ad0d3b8 100644
--- a/Source/Engine/Renderer/Renderer.h
+++ b/Source/Engine/Renderer/Renderer.h
@@ -8,6 +8,7 @@ class GPUContext;
class GPUTexture;
class GPUTextureView;
struct RenderContext;
+struct RenderContextBatch;
class RenderTask;
class SceneRenderTask;
class MaterialBase;
@@ -56,4 +57,11 @@ public:
/// The rendering context.
/// The custom set of actors to render. If empty, the loaded scenes will be rendered.
API_FUNCTION() static void DrawActors(API_PARAM(Ref) RenderContext& renderContext, API_PARAM(DefaultValue=null) const Array& customActors);
+
+ ///
+ /// Invoked drawing of the scene objects (collects draw calls into RenderList for all contexts in a batch).
+ ///
+ /// The rendering context batch.
+ /// The custom set of actors to render. If empty, the loaded scenes will be rendered.
+ API_FUNCTION() static void DrawActors(API_PARAM(Ref) RenderContextBatch& renderContextBatch, API_PARAM(DefaultValue=null) const Array& customActors);
};
diff --git a/Source/Engine/Terrain/Terrain.cpp b/Source/Engine/Terrain/Terrain.cpp
index 911037e33..d4eea1616 100644
--- a/Source/Engine/Terrain/Terrain.cpp
+++ b/Source/Engine/Terrain/Terrain.cpp
@@ -541,18 +541,6 @@ void Terrain::Draw(RenderContextBatch& renderContextBatch)
}
}
-void Terrain::Draw(RenderContext& renderContext)
-{
- const DrawPass drawModes = DrawModes & renderContext.View.Pass;
- if (drawModes == DrawPass::None)
- return;
- PROFILE_CPU();
- if (DrawSetup(renderContext))
- return;
- HashSet drawnChunks;
- DrawImpl(renderContext, drawnChunks);
-}
-
bool Terrain::DrawSetup(RenderContext& renderContext)
{
// Special drawing modes
diff --git a/Source/Engine/Terrain/Terrain.h b/Source/Engine/Terrain/Terrain.h
index 984f3d388..9c041b961 100644
--- a/Source/Engine/Terrain/Terrain.h
+++ b/Source/Engine/Terrain/Terrain.h
@@ -462,7 +462,6 @@ private:
public:
// [PhysicsColliderActor]
void Draw(RenderContextBatch& renderContextBatch) override;
- void Draw(RenderContext& renderContext) override;
#if USE_EDITOR
void OnDebugDrawSelected() override;
#endif
diff --git a/Source/Engine/UI/SpriteRender.cpp b/Source/Engine/UI/SpriteRender.cpp
index 398337d80..9d0461238 100644
--- a/Source/Engine/UI/SpriteRender.cpp
+++ b/Source/Engine/UI/SpriteRender.cpp
@@ -119,8 +119,9 @@ bool SpriteRender::HasContentLoaded() const
return (Material == nullptr || Material->IsLoaded()) && (Image == nullptr || Image->IsLoaded());
}
-void SpriteRender::Draw(RenderContext& renderContext)
+void SpriteRender::Draw(RenderContextBatch& renderContextBatch)
{
+ RenderContext& renderContext = renderContextBatch.GetMainContext();
if (renderContext.View.Pass == DrawPass::GlobalSDF || renderContext.View.Pass == DrawPass::GlobalSurfaceAtlas)
return;
if (!Material || !Material->IsLoaded() || !_quadModel || !_quadModel->IsLoaded())
@@ -145,7 +146,7 @@ void SpriteRender::Draw(RenderContext& renderContext)
view.GetWorldMatrix(_transform, m2);
Matrix::Multiply(m1, m2, world);
}
- model->LODs[0].Draw(renderContext, _materialInstance, world, GetStaticFlags(), false, DrawModes, GetPerInstanceRandom(), SortOrder);
+ model->LODs[0].Draw(renderContextBatch, _materialInstance, world, GetStaticFlags(), false, DrawModes, GetPerInstanceRandom(), SortOrder);
}
void SpriteRender::Serialize(SerializeStream& stream, const void* otherObj)
diff --git a/Source/Engine/UI/SpriteRender.h b/Source/Engine/UI/SpriteRender.h
index 3b7d130f4..593982e48 100644
--- a/Source/Engine/UI/SpriteRender.h
+++ b/Source/Engine/UI/SpriteRender.h
@@ -98,7 +98,7 @@ private:
public:
// [Actor]
bool HasContentLoaded() const override;
- void Draw(RenderContext& renderContext) override;
+ void Draw(RenderContextBatch& renderContextBatch) override;
void Serialize(SerializeStream& stream, const void* otherObj) override;
void Deserialize(DeserializeStream& stream, ISerializeModifier* modifier) override;
void OnLayerChanged() override;
diff --git a/Source/Engine/UI/TextRender.cpp b/Source/Engine/UI/TextRender.cpp
index fb4b3c814..b88a7806d 100644
--- a/Source/Engine/UI/TextRender.cpp
+++ b/Source/Engine/UI/TextRender.cpp
@@ -362,54 +362,54 @@ bool TextRender::HasContentLoaded() const
return (Material == nullptr || Material->IsLoaded()) && (Font == nullptr || Font->IsLoaded());
}
-void TextRender::Draw(RenderContext& renderContext)
+void TextRender::Draw(RenderContextBatch& renderContextBatch)
{
+ const RenderContext& renderContext = renderContextBatch.GetMainContext();
if (renderContext.View.Pass == DrawPass::GlobalSDF)
return; // TODO: Text rendering to Global SDF
if (renderContext.View.Pass == DrawPass::GlobalSurfaceAtlas)
return; // TODO: Text rendering to Global Surface Atlas
if (_isDirty)
UpdateLayout();
+ if (_vb.Data.IsEmpty())
+ return;
Matrix world;
renderContext.View.GetWorldMatrix(_transform, world);
auto drawState = renderContext.Buffers->GetGeometryDrawState(&GetScene()->Rendering, _sceneRenderingKey, this);
GEOMETRY_DRAW_STATE_EVENT_BEGIN(drawState, world);
- const DrawPass drawModes = DrawModes & renderContext.View.Pass & renderContext.View.GetShadowsDrawPassMask(ShadowsMode);
- if (_vb.Data.Count() > 0 && drawModes != DrawPass::None)
+ // Flush buffers
+ if (_buffersDirty)
{
- // Flush buffers
- if (_buffersDirty)
- {
- _buffersDirty = false;
- _ib.Flush();
- _vb.Flush();
- }
+ _buffersDirty = false;
+ _ib.Flush();
+ _vb.Flush();
+ }
- // Setup draw call
- DrawCall drawCall;
- drawCall.World = world;
- drawCall.ObjectPosition = drawCall.World.GetTranslation();
- drawCall.ObjectRadius = (float)_sphere.Radius;
- drawCall.Surface.GeometrySize = _localBox.GetSize();
- drawCall.Surface.PrevWorld = drawState ? drawState->PrevWorld : world;
- drawCall.PerInstanceRandom = GetPerInstanceRandom();
- drawCall.SetStencilValue(_layer);
- drawCall.Geometry.IndexBuffer = _ib.GetBuffer();
- drawCall.Geometry.VertexBuffers[0] = _vb.GetBuffer();
- drawCall.InstanceCount = 1;
+ // Setup draw call
+ DrawCall drawCall;
+ drawCall.World = world;
+ drawCall.ObjectPosition = drawCall.World.GetTranslation();
+ drawCall.ObjectRadius = (float)_sphere.Radius;
+ drawCall.Surface.GeometrySize = _localBox.GetSize();
+ drawCall.Surface.PrevWorld = drawState ? drawState->PrevWorld : world;
+ drawCall.PerInstanceRandom = GetPerInstanceRandom();
+ drawCall.SetStencilValue(_layer);
+ drawCall.Geometry.IndexBuffer = _ib.GetBuffer();
+ drawCall.Geometry.VertexBuffers[0] = _vb.GetBuffer();
+ drawCall.InstanceCount = 1;
- // Submit draw calls
- for (const auto& e : _drawChunks)
- {
- const DrawPass chunkDrawModes = drawModes & e.Material->GetDrawModes();
- if (chunkDrawModes == DrawPass::None)
- continue;
- drawCall.Draw.IndicesCount = e.IndicesCount;
- drawCall.Draw.StartIndex = e.StartIndex;
- drawCall.Material = e.Material;
- renderContext.List->AddDrawCall(renderContext, chunkDrawModes, GetStaticFlags(), drawCall, true, SortOrder);
- }
+ // Submit draw calls
+ const DrawPass drawModes = DrawModes & renderContext.View.GetShadowsDrawPassMask(ShadowsMode);
+ for (const auto& e : _drawChunks)
+ {
+ const DrawPass chunkDrawModes = drawModes & e.Material->GetDrawModes();
+ if (chunkDrawModes == DrawPass::None)
+ continue;
+ drawCall.Draw.IndicesCount = e.IndicesCount;
+ drawCall.Draw.StartIndex = e.StartIndex;
+ drawCall.Material = e.Material;
+ renderContext.List->AddDrawCall(renderContextBatch, chunkDrawModes, GetStaticFlags(), ShadowsMode, _sphere, drawCall, true, SortOrder);
}
GEOMETRY_DRAW_STATE_EVENT_END(drawState, world);
diff --git a/Source/Engine/UI/TextRender.h b/Source/Engine/UI/TextRender.h
index 1f599f98d..b095eb874 100644
--- a/Source/Engine/UI/TextRender.h
+++ b/Source/Engine/UI/TextRender.h
@@ -160,7 +160,7 @@ private:
public:
// [Actor]
bool HasContentLoaded() const override;
- void Draw(RenderContext& renderContext) override;
+ void Draw(RenderContextBatch& renderContextBatch) override;
#if USE_EDITOR
void OnDebugDrawSelected() override;
#endif