Refactor scene rendering to separate drawable actors

This commit is contained in:
Wojtek Figat
2022-10-27 18:27:12 +02:00
parent 4123e4cf69
commit e217d5e79b
22 changed files with 129 additions and 102 deletions

View File

@@ -63,7 +63,7 @@ BoundingBox Decal::GetEditorBox() const
void Decal::OnLayerChanged()
{
if (_sceneRenderingKey != -1)
GetSceneRendering()->UpdateActor(this, _sceneRenderingKey);
GetSceneRendering()->UpdateActor(this, _sceneRenderingKey, SceneRendering::PreRender);
}
void Decal::Draw(RenderContext& renderContext)
@@ -118,7 +118,7 @@ bool Decal::IntersectsItself(const Ray& ray, Real& distance, Vector3& normal)
void Decal::OnEnable()
{
GetSceneRendering()->AddActor(this, _sceneRenderingKey);
GetSceneRendering()->AddActor(this, _sceneRenderingKey, SceneRendering::PreRender);
#if USE_EDITOR
GetSceneRendering()->AddViewportIcon(this);
#endif
@@ -132,7 +132,7 @@ void Decal::OnDisable()
#if USE_EDITOR
GetSceneRendering()->RemoveViewportIcon(this);
#endif
GetSceneRendering()->RemoveActor(this, _sceneRenderingKey);
GetSceneRendering()->RemoveActor(this, _sceneRenderingKey, SceneRendering::PreRender);
// Base
Actor::OnDisable();
@@ -148,5 +148,5 @@ void Decal::OnTransformChanged()
BoundingSphere::FromBox(_box, _sphere);
if (_sceneRenderingKey != -1)
GetSceneRendering()->UpdateActor(this, _sceneRenderingKey);
GetSceneRendering()->UpdateActor(this, _sceneRenderingKey, SceneRendering::PreRender);
}

View File

@@ -73,7 +73,7 @@ bool DirectionalLight::IntersectsItself(const Ray& ray, Real& distance, Vector3&
void DirectionalLight::OnEnable()
{
GetSceneRendering()->AddActor(this, _sceneRenderingKey);
GetSceneRendering()->AddActor(this, _sceneRenderingKey, SceneRendering::PreRender);
#if USE_EDITOR
GetSceneRendering()->AddViewportIcon(this);
#endif
@@ -87,7 +87,7 @@ void DirectionalLight::OnDisable()
#if USE_EDITOR
GetSceneRendering()->RemoveViewportIcon(this);
#endif
GetSceneRendering()->RemoveActor(this, _sceneRenderingKey);
GetSceneRendering()->RemoveActor(this, _sceneRenderingKey, SceneRendering::PreRender);
// Base
LightWithShadow::OnDisable();

View File

@@ -170,7 +170,7 @@ void EnvironmentProbe::UpdateBounds()
_sphere = BoundingSphere(GetPosition(), GetScaledRadius());
BoundingBox::FromSphere(_sphere, _box);
if (_sceneRenderingKey != -1)
GetSceneRendering()->UpdateActor(this, _sceneRenderingKey);
GetSceneRendering()->UpdateActor(this, _sceneRenderingKey, SceneRendering::PreRender);
}
void EnvironmentProbe::Draw(RenderContext& renderContext)
@@ -206,7 +206,7 @@ void EnvironmentProbe::OnDebugDrawSelected()
void EnvironmentProbe::OnLayerChanged()
{
if (_sceneRenderingKey != -1)
GetSceneRendering()->UpdateActor(this, _sceneRenderingKey);
GetSceneRendering()->UpdateActor(this, _sceneRenderingKey, SceneRendering::PreRender);
}
void EnvironmentProbe::Serialize(SerializeStream& stream, const void* otherObj)
@@ -259,7 +259,7 @@ bool EnvironmentProbe::IntersectsItself(const Ray& ray, Real& distance, Vector3&
void EnvironmentProbe::OnEnable()
{
GetSceneRendering()->AddActor(this, _sceneRenderingKey);
GetSceneRendering()->AddActor(this, _sceneRenderingKey, SceneRendering::PreRender);
#if USE_EDITOR
GetSceneRendering()->AddViewportIcon(this);
#endif
@@ -273,7 +273,7 @@ void EnvironmentProbe::OnDisable()
#if USE_EDITOR
GetSceneRendering()->RemoveViewportIcon(this);
#endif
GetSceneRendering()->RemoveActor(this, _sceneRenderingKey);
GetSceneRendering()->RemoveActor(this, _sceneRenderingKey, SceneRendering::PreRender);
// Base
Actor::OnDisable();

View File

@@ -209,7 +209,7 @@ void ExponentialHeightFog::DrawFog(GPUContext* context, RenderContext& renderCon
void ExponentialHeightFog::OnEnable()
{
GetSceneRendering()->AddActor(this, _sceneRenderingKey);
GetSceneRendering()->AddActor(this, _sceneRenderingKey, SceneRendering::PreRender);
#if USE_EDITOR
GetSceneRendering()->AddViewportIcon(this);
#endif
@@ -223,7 +223,7 @@ void ExponentialHeightFog::OnDisable()
#if USE_EDITOR
GetSceneRendering()->RemoveViewportIcon(this);
#endif
GetSceneRendering()->RemoveActor(this, _sceneRenderingKey);
GetSceneRendering()->RemoveActor(this, _sceneRenderingKey, SceneRendering::PreRender);
// Base
Actor::OnDisable();

View File

@@ -66,12 +66,12 @@ void PointLight::UpdateBounds()
BoundingBox::FromSphere(_sphere, _box);
if (_sceneRenderingKey != -1)
GetSceneRendering()->UpdateActor(this, _sceneRenderingKey);
GetSceneRendering()->UpdateActor(this, _sceneRenderingKey, SceneRendering::PreRender);
}
void PointLight::OnEnable()
{
GetSceneRendering()->AddActor(this, _sceneRenderingKey);
GetSceneRendering()->AddActor(this, _sceneRenderingKey, SceneRendering::PreRender);
#if USE_EDITOR
GetSceneRendering()->AddViewportIcon(this);
#endif
@@ -85,7 +85,7 @@ void PointLight::OnDisable()
#if USE_EDITOR
GetSceneRendering()->RemoveViewportIcon(this);
#endif
GetSceneRendering()->RemoveActor(this, _sceneRenderingKey);
GetSceneRendering()->RemoveActor(this, _sceneRenderingKey, SceneRendering::PreRender);
// Base
LightWithShadow::OnDisable();
@@ -170,7 +170,7 @@ void PointLight::OnDebugDrawSelected()
void PointLight::OnLayerChanged()
{
if (_sceneRenderingKey != -1)
GetSceneRendering()->UpdateActor(this, _sceneRenderingKey);
GetSceneRendering()->UpdateActor(this, _sceneRenderingKey, SceneRendering::PreRender);
}
void PointLight::Serialize(SerializeStream& stream, const void* otherObj)

View File

@@ -248,7 +248,7 @@ void Sky::EndPlay()
void Sky::OnEnable()
{
GetSceneRendering()->AddActor(this, _sceneRenderingKey);
GetSceneRendering()->AddActor(this, _sceneRenderingKey, SceneRendering::PreRender);
#if USE_EDITOR
GetSceneRendering()->AddViewportIcon(this);
#endif
@@ -262,7 +262,7 @@ void Sky::OnDisable()
#if USE_EDITOR
GetSceneRendering()->RemoveViewportIcon(this);
#endif
GetSceneRendering()->RemoveActor(this, _sceneRenderingKey);
GetSceneRendering()->RemoveActor(this, _sceneRenderingKey, SceneRendering::PreRender);
// Base
Actor::OnDisable();

View File

@@ -181,7 +181,7 @@ bool SkyLight::HasContentLoaded() const
void SkyLight::OnEnable()
{
GetSceneRendering()->AddActor(this, _sceneRenderingKey);
GetSceneRendering()->AddActor(this, _sceneRenderingKey, SceneRendering::PreRender);
#if USE_EDITOR
GetSceneRendering()->AddViewportIcon(this);
#endif
@@ -195,7 +195,7 @@ void SkyLight::OnDisable()
#if USE_EDITOR
GetSceneRendering()->RemoveViewportIcon(this);
#endif
GetSceneRendering()->RemoveActor(this, _sceneRenderingKey);
GetSceneRendering()->RemoveActor(this, _sceneRenderingKey, SceneRendering::PreRender);
// Base
Light::OnDisable();

View File

@@ -127,7 +127,7 @@ void Skybox::ApplySky(GPUContext* context, RenderContext& renderContext, const M
void Skybox::OnEnable()
{
GetSceneRendering()->AddActor(this, _sceneRenderingKey);
GetSceneRendering()->AddActor(this, _sceneRenderingKey, SceneRendering::PreRender);
#if USE_EDITOR
GetSceneRendering()->AddViewportIcon(this);
#endif
@@ -141,7 +141,7 @@ void Skybox::OnDisable()
#if USE_EDITOR
GetSceneRendering()->RemoveViewportIcon(this);
#endif
GetSceneRendering()->RemoveActor(this, _sceneRenderingKey);
GetSceneRendering()->RemoveActor(this, _sceneRenderingKey, SceneRendering::PreRender);
// Base
Actor::OnDisable();

View File

@@ -114,12 +114,12 @@ void SpotLight::UpdateBounds()
BoundingBox::FromSphere(_sphere, _box);
if (_sceneRenderingKey != -1)
GetSceneRendering()->UpdateActor(this, _sceneRenderingKey);
GetSceneRendering()->UpdateActor(this, _sceneRenderingKey, SceneRendering::PreRender);
}
void SpotLight::OnEnable()
{
GetSceneRendering()->AddActor(this, _sceneRenderingKey);
GetSceneRendering()->AddActor(this, _sceneRenderingKey, SceneRendering::PreRender);
#if USE_EDITOR
GetSceneRendering()->AddViewportIcon(this);
#endif
@@ -133,7 +133,7 @@ void SpotLight::OnDisable()
#if USE_EDITOR
GetSceneRendering()->RemoveViewportIcon(this);
#endif
GetSceneRendering()->RemoveActor(this, _sceneRenderingKey);
GetSceneRendering()->RemoveActor(this, _sceneRenderingKey, SceneRendering::PreRender);
// Base
LightWithShadow::OnDisable();

View File

@@ -389,7 +389,7 @@ void Level::CallBeginPlay(Actor* obj)
}
}
void Level::DrawActors(RenderContext& renderContext)
void Level::DrawActors(RenderContext& renderContext, byte category)
{
PROFILE_CPU();
@@ -398,7 +398,7 @@ void Level::DrawActors(RenderContext& renderContext)
for (Scene* scene : Scenes)
{
if (scene->IsActiveInHierarchy())
scene->Rendering.Draw(renderContext);
scene->Rendering.Draw(renderContext, (SceneRendering::DrawCategory)category);
}
}

View File

@@ -164,7 +164,8 @@ public:
/// Draws all the actors.
/// </summary>
/// <param name="renderContext">The rendering context.</param>
static void DrawActors(RenderContext& renderContext);
/// <param name="category">The actors category to draw (see SceneRendering::DrawCategory).</param>
static void DrawActors(RenderContext& renderContext, byte category = 0);
/// <summary>
/// Collects all the post fx volumes.

View File

@@ -28,20 +28,21 @@ void ISceneRenderingListener::ListenSceneRendering(SceneRendering* scene)
}
}
void SceneRendering::Draw(RenderContext& renderContext)
void SceneRendering::Draw(RenderContext& renderContext, DrawCategory category)
{
ScopeLock lock(Locker);
auto& view = renderContext.View;
const BoundingFrustum frustum = view.CullingFrustum;
const Vector3 origin = view.Origin;
renderContext.List->Scenes.Add(this);
auto& list = Actors[(int32)category];
// Draw all visual components
if (view.IsOfflinePass)
{
for (int32 i = 0; i < Actors.Count(); i++)
for (int32 i = 0; i < list.Count(); i++)
{
auto e = Actors.Get()[i];
auto e = list.Get()[i];
e.Bounds.Center -= origin;
if (view.RenderLayersMask.Mask & e.LayerMask && (e.NoCulling || frustum.Intersects(e.Bounds)) && e.Actor->GetStaticFlags() & view.StaticFlagsMask)
{
@@ -54,9 +55,9 @@ void SceneRendering::Draw(RenderContext& renderContext)
}
else if (origin.IsZero())
{
for (int32 i = 0; i < Actors.Count(); i++)
for (int32 i = 0; i < list.Count(); i++)
{
auto e = Actors.Get()[i];
auto e = list.Get()[i];
if (view.RenderLayersMask.Mask & e.LayerMask && (e.NoCulling || frustum.Intersects(e.Bounds)))
{
#if SCENE_RENDERING_USE_PROFILER
@@ -68,9 +69,9 @@ void SceneRendering::Draw(RenderContext& renderContext)
}
else
{
for (int32 i = 0; i < Actors.Count(); i++)
for (int32 i = 0; i < list.Count(); i++)
{
auto e = Actors.Get()[i];
auto e = list.Get()[i];
e.Bounds.Center -= origin;
if (view.RenderLayersMask.Mask & e.LayerMask && (e.NoCulling || frustum.Intersects(e.Bounds)))
{
@@ -82,7 +83,7 @@ void SceneRendering::Draw(RenderContext& renderContext)
}
}
#if USE_EDITOR
if (view.Pass & DrawPass::GBuffer)
if (view.Pass & DrawPass::GBuffer && category == SceneDraw)
{
// Draw physics shapes
if (view.Flags & ViewFlags::PhysicsDebug || view.Mode == ViewMode::PhysicsColliders)
@@ -116,42 +117,44 @@ void SceneRendering::Clear()
listener->_scenes.Remove(this);
}
_listeners.Clear();
Actors.Clear();
for (auto& e : Actors)
e.Clear();
#if USE_EDITOR
PhysicsDebug.Clear();
#endif
}
void SceneRendering::AddActor(Actor* a, int32& key)
void SceneRendering::AddActor(Actor* a, int32& key, DrawCategory category)
{
if (key != -1)
return;
ScopeLock lock(Locker);
if (key == -1)
auto& list = Actors[(int32)category];
// TODO: track removedCount and skip searching for free entry if there is none
key = 0;
for (; key < list.Count(); key++)
{
// TODO: track removedCount and skip searching for free entry if there is none
key = 0;
for (; key < Actors.Count(); key++)
{
if (Actors[key].Actor == nullptr)
break;
}
if (key == Actors.Count())
Actors.AddOne();
auto& e = Actors[key];
e.Actor = a;
e.LayerMask = a->GetLayerMask();
e.Bounds = a->GetSphere();
e.NoCulling = a->_drawNoCulling;
for (auto* listener : _listeners)
listener->OnSceneRenderingAddActor(a);
if (list[key].Actor == nullptr)
break;
}
if (key == list.Count())
list.AddOne();
auto& e = list[key];
e.Actor = a;
e.LayerMask = a->GetLayerMask();
e.Bounds = a->GetSphere();
e.NoCulling = a->_drawNoCulling;
for (auto* listener : _listeners)
listener->OnSceneRenderingAddActor(a);
}
void SceneRendering::UpdateActor(Actor* a, int32 key)
void SceneRendering::UpdateActor(Actor* a, int32 key, DrawCategory category)
{
ScopeLock lock(Locker);
if (Actors.IsEmpty())
auto& list = Actors[(int32)category];
if (list.IsEmpty())
return;
auto& e = Actors[key];
auto& e = list[key];
ASSERT_LOW_LAYER(a == e.Actor);
for (auto* listener : _listeners)
listener->OnSceneRenderingUpdateActor(a, e.Bounds);
@@ -159,12 +162,13 @@ void SceneRendering::UpdateActor(Actor* a, int32 key)
e.Bounds = a->GetSphere();
}
void SceneRendering::RemoveActor(Actor* a, int32& key)
void SceneRendering::RemoveActor(Actor* a, int32& key, DrawCategory category)
{
ScopeLock lock(Locker);
if (Actors.HasItems())
auto& list = Actors[(int32)category];
if (list.HasItems())
{
auto& e = Actors[key];
auto& e = list[key];
ASSERT_LOW_LAYER(a == e.Actor);
for (auto* listener : _listeners)
listener->OnSceneRenderingRemoveActor(a);

View File

@@ -74,7 +74,18 @@ public:
BoundingSphere Bounds;
};
Array<DrawActor> Actors;
/// <summary>
/// Drawing categories for separate draw stages.
/// </summary>
enum DrawCategory
{
SceneDraw = 0,
PreRender,
PostRender,
MAX
};
Array<DrawActor> Actors[MAX];
Array<IPostFxSettingsProvider*> PostFxProviders;
CriticalSection Locker;
@@ -93,7 +104,8 @@ public:
/// Draws the scene. Performs the optimized actors culling and draw calls submission for the current render pass (defined by the render view).
/// </summary>
/// <param name="renderContext">The rendering context.</param>
void Draw(RenderContext& renderContext);
/// <param name="category">The actors category to draw.</param>
void Draw(RenderContext& renderContext, DrawCategory category = DrawCategory::SceneDraw);
/// <summary>
/// Collects the post fx volumes for the given rendering view.
@@ -107,9 +119,9 @@ public:
void Clear();
public:
void AddActor(Actor* a, int32& key);
void UpdateActor(Actor* a, int32 key);
void RemoveActor(Actor* a, int32& key);
void AddActor(Actor* a, int32& key, DrawCategory category = SceneDraw);
void UpdateActor(Actor* a, int32 key, DrawCategory category = SceneDraw);
void RemoveActor(Actor* a, int32& key, DrawCategory category = SceneDraw);
FORCE_INLINE void AddPostFxProvider(IPostFxSettingsProvider* obj)
{