diff --git a/Source/Editor/Utilities/ViewportIconsRenderer.cpp b/Source/Editor/Utilities/ViewportIconsRenderer.cpp index 72690f8a4..b967cad9b 100644 --- a/Source/Editor/Utilities/ViewportIconsRenderer.cpp +++ b/Source/Editor/Utilities/ViewportIconsRenderer.cpp @@ -51,74 +51,14 @@ public: { } + static void DrawIcons(RenderContext& renderContext, Scene* scene, Mesh::DrawInfo& draw); + static void DrawIcons(RenderContext& renderContext, Actor* actor, Mesh::DrawInfo& draw); bool Init() override; void Dispose() override; }; ViewportIconsRendererService ViewportIconsRendererServiceInstance; -namespace -{ - void DrawIcons(RenderContext& renderContext, Scene* scene, Mesh::DrawInfo& draw) - { - auto& view = renderContext.View; - const BoundingFrustum frustum = view.Frustum; - auto& icons = scene->GetSceneRendering()->ViewportIcons; - Matrix m1, m2, world; - for (Actor* icon : icons) - { - BoundingSphere sphere(icon->GetPosition(), ICON_RADIUS); - IconTypes iconType; - if (frustum.Intersects(sphere) && ActorTypeToIconType.TryGet(icon->GetTypeHandle(), iconType)) - { - // Create world matrix - Matrix::Scaling(ICON_RADIUS * 2.0f, m2); - Matrix::RotationY(PI, world); - Matrix::Multiply(m2, world, m1); - Matrix::Billboard(sphere.Center, view.Position, Vector3::Up, view.Direction, m2); - Matrix::Multiply(m1, m2, world); - - // Draw icon - GeometryDrawStateData drawState; - draw.DrawState = &drawState; - draw.Buffer = &InstanceBuffers[static_cast(iconType)]; - draw.World = &world; - draw.Bounds = sphere; - QuadModel->Draw(renderContext, draw); - } - } - } - - void DrawIcons(RenderContext& renderContext, Actor* actor, Mesh::DrawInfo& draw) - { - auto& view = renderContext.View; - const BoundingFrustum frustum = view.Frustum; - Matrix m1, m2, world; - BoundingSphere sphere(actor->GetPosition(), ICON_RADIUS); - IconTypes iconType; - if (frustum.Intersects(sphere) && ActorTypeToIconType.TryGet(actor->GetTypeHandle(), iconType)) - { - // Create world matrix - Matrix::Scaling(ICON_RADIUS * 2.0f, m2); - Matrix::RotationY(PI, world); - Matrix::Multiply(m2, world, m1); - Matrix::Billboard(sphere.Center, view.Position, Vector3::Up, view.Direction, m2); - Matrix::Multiply(m1, m2, world); - - // Draw icon - GeometryDrawStateData drawState; - draw.DrawState = &drawState; - draw.Buffer = &InstanceBuffers[static_cast(iconType)]; - draw.World = &world; - draw.Bounds = sphere; - QuadModel->Draw(renderContext, draw); - } - - for (auto child : actor->Children) - DrawIcons(renderContext, child, draw); - } -} - void ViewportIconsRenderer::DrawIcons(RenderContext& renderContext, Actor* actor) { auto& view = renderContext.View; @@ -137,14 +77,73 @@ void ViewportIconsRenderer::DrawIcons(RenderContext& renderContext, Actor* actor if (const auto scene = SceneObject::Cast(actor)) { - ::DrawIcons(renderContext, scene, draw); + ViewportIconsRendererService::DrawIcons(renderContext, scene, draw); } else { - ::DrawIcons(renderContext, actor, draw); + ViewportIconsRendererService::DrawIcons(renderContext, actor, draw); } } +void ViewportIconsRendererService::DrawIcons(RenderContext& renderContext, Scene* scene, Mesh::DrawInfo& draw) +{ + auto& view = renderContext.View; + const BoundingFrustum frustum = view.Frustum; + auto& icons = scene->GetSceneRendering()->ViewportIcons; + Matrix m1, m2, world; + for (Actor* icon : icons) + { + BoundingSphere sphere(icon->GetPosition(), ICON_RADIUS); + IconTypes iconType; + if (frustum.Intersects(sphere) && ActorTypeToIconType.TryGet(icon->GetTypeHandle(), iconType)) + { + // Create world matrix + Matrix::Scaling(ICON_RADIUS * 2.0f, m2); + Matrix::RotationY(PI, world); + Matrix::Multiply(m2, world, m1); + Matrix::Billboard(sphere.Center, view.Position, Vector3::Up, view.Direction, m2); + Matrix::Multiply(m1, m2, world); + + // Draw icon + GeometryDrawStateData drawState; + draw.DrawState = &drawState; + draw.Buffer = &InstanceBuffers[static_cast(iconType)]; + draw.World = &world; + draw.Bounds = sphere; + QuadModel->Draw(renderContext, draw); + } + } +} + +void ViewportIconsRendererService::DrawIcons(RenderContext& renderContext, Actor* actor, Mesh::DrawInfo& draw) +{ + auto& view = renderContext.View; + const BoundingFrustum frustum = view.Frustum; + Matrix m1, m2, world; + BoundingSphere sphere(actor->GetPosition(), ICON_RADIUS); + IconTypes iconType; + if (frustum.Intersects(sphere) && ActorTypeToIconType.TryGet(actor->GetTypeHandle(), iconType)) + { + // Create world matrix + Matrix::Scaling(ICON_RADIUS * 2.0f, m2); + Matrix::RotationY(PI, world); + Matrix::Multiply(m2, world, m1); + Matrix::Billboard(sphere.Center, view.Position, Vector3::Up, view.Direction, m2); + Matrix::Multiply(m1, m2, world); + + // Draw icon + GeometryDrawStateData drawState; + draw.DrawState = &drawState; + draw.Buffer = &InstanceBuffers[static_cast(iconType)]; + draw.World = &world; + draw.Bounds = sphere; + QuadModel->Draw(renderContext, draw); + } + + for (auto child : actor->Children) + DrawIcons(renderContext, child, draw); +} + bool ViewportIconsRendererService::Init() { QuadModel = Content::LoadAsyncInternal(TEXT("Engine/Models/Quad")); diff --git a/Source/Engine/Core/Types/LayersMask.h b/Source/Engine/Core/Types/LayersMask.h index bd8e90335..270e2f83e 100644 --- a/Source/Engine/Core/Types/LayersMask.h +++ b/Source/Engine/Core/Types/LayersMask.h @@ -62,7 +62,7 @@ public: LayersMask operator&(const LayersMask& other) const { - return Mask && other.Mask; + return Mask & other.Mask; } LayersMask operator|(const LayersMask& other) const diff --git a/Source/Engine/Foliage/Foliage.cpp b/Source/Engine/Foliage/Foliage.cpp index 84b0573d8..aef2da3dd 100644 --- a/Source/Engine/Foliage/Foliage.cpp +++ b/Source/Engine/Foliage/Foliage.cpp @@ -7,7 +7,6 @@ #include "Engine/Core/Random.h" #include "Engine/Engine/Engine.h" #include "Engine/Graphics/RenderTask.h" -#include "Engine/Level/Scene/Scene.h" #include "Engine/Level/SceneQuery.h" #include "Engine/Profiler/ProfilerCPU.h" #include "Engine/Serialization/Serialization.h" @@ -68,6 +67,8 @@ void Foliage::EnsureRoot() // Cache bounds _box = Root->Bounds; BoundingSphere::FromBox(_box, _sphere); + if (_sceneRenderingKey != -1) + GetSceneRendering()->UpdateGeometry(this, _sceneRenderingKey); } void Foliage::AddToCluster(FoliageCluster* cluster, FoliageInstance& instance) @@ -785,9 +786,15 @@ void Foliage::Deserialize(DeserializeStream& stream, ISerializeModifier* modifie } } +void Foliage::OnLayerChanged() +{ + if (_sceneRenderingKey != -1) + GetSceneRendering()->UpdateGeometry(this, _sceneRenderingKey); +} + void Foliage::OnEnable() { - GetScene()->Rendering.AddGeometry(this); + _sceneRenderingKey = GetSceneRendering()->AddGeometry(this); // Base Actor::OnEnable(); @@ -795,7 +802,7 @@ void Foliage::OnEnable() void Foliage::OnDisable() { - GetScene()->Rendering.RemoveGeometry(this); + GetSceneRendering()->RemoveGeometry(this, _sceneRenderingKey); // Base Actor::OnDisable(); diff --git a/Source/Engine/Foliage/Foliage.h b/Source/Engine/Foliage/Foliage.h index 3b22e1c67..5ba70e977 100644 --- a/Source/Engine/Foliage/Foliage.h +++ b/Source/Engine/Foliage/Foliage.h @@ -19,6 +19,7 @@ DECLARE_SCENE_OBJECT(Foliage); private: bool _disableFoliageTypeEvents; + int32 _sceneRenderingKey = -1; public: @@ -191,6 +192,7 @@ public: bool IntersectsItself(const Ray& ray, float& distance, Vector3& normal) override; void Serialize(SerializeStream& stream, const void* otherObj) override; void Deserialize(DeserializeStream& stream, ISerializeModifier* modifier) override; + void OnLayerChanged() override; protected: diff --git a/Source/Engine/Level/Actors/AnimatedModel.cpp b/Source/Engine/Level/Actors/AnimatedModel.cpp index 45bc701c6..d4065c0b3 100644 --- a/Source/Engine/Level/Actors/AnimatedModel.cpp +++ b/Source/Engine/Level/Actors/AnimatedModel.cpp @@ -439,6 +439,8 @@ void AnimatedModel::UpdateBounds() BoundingBox::Transform(_boxLocal, _world, _box); BoundingSphere::FromBox(_box, _sphere); + if (_sceneRenderingKey != -1) + GetSceneRendering()->UpdateGeometry(this, _sceneRenderingKey); } void AnimatedModel::UpdateSockets() @@ -758,4 +760,6 @@ void AnimatedModel::OnTransformChanged() _transform.GetWorld(_world); BoundingBox::Transform(_boxLocal, _world, _box); BoundingSphere::FromBox(_box, _sphere); + if (_sceneRenderingKey != -1) + GetSceneRendering()->UpdateGeometry(this, _sceneRenderingKey); } diff --git a/Source/Engine/Level/Actors/Decal.cpp b/Source/Engine/Level/Actors/Decal.cpp index c7e8475b3..994b0fb72 100644 --- a/Source/Engine/Level/Actors/Decal.cpp +++ b/Source/Engine/Level/Actors/Decal.cpp @@ -60,6 +60,12 @@ void Decal::OnDebugDrawSelected() #endif +void Decal::OnLayerChanged() +{ + if (_sceneRenderingKey != -1) + GetSceneRendering()->UpdateCommon(this, _sceneRenderingKey); +} + void Decal::Draw(RenderContext& renderContext) { if ((renderContext.View.Flags & ViewFlags::Decals) != 0 && @@ -109,7 +115,7 @@ bool Decal::IntersectsItself(const Ray& ray, float& distance, Vector3& normal) void Decal::OnEnable() { - GetSceneRendering()->AddCommon(this); + _sceneRenderingKey = GetSceneRendering()->AddCommon(this); #if USE_EDITOR GetSceneRendering()->AddViewportIcon(this); #endif @@ -123,7 +129,7 @@ void Decal::OnDisable() #if USE_EDITOR GetSceneRendering()->RemoveViewportIcon(this); #endif - GetSceneRendering()->RemoveCommon(this); + GetSceneRendering()->RemoveCommon(this, _sceneRenderingKey); // Base Actor::OnDisable(); @@ -142,4 +148,7 @@ void Decal::OnTransformChanged() _bounds.Transformation = _world; _bounds.GetBoundingBox(_box); BoundingSphere::FromBox(_box, _sphere); + + if (_sceneRenderingKey != -1) + GetSceneRendering()->UpdateCommon(this, _sceneRenderingKey); } diff --git a/Source/Engine/Level/Actors/Decal.h b/Source/Engine/Level/Actors/Decal.h index 78a92bfd6..7bff6dbff 100644 --- a/Source/Engine/Level/Actors/Decal.h +++ b/Source/Engine/Level/Actors/Decal.h @@ -18,6 +18,7 @@ private: Vector3 _size; OrientedBoundingBox _bounds; Matrix _world; + int32 _sceneRenderingKey = -1; public: @@ -77,6 +78,7 @@ public: #if USE_EDITOR void OnDebugDrawSelected() override; #endif + void OnLayerChanged() override; void Draw(RenderContext& renderContext) override; void Serialize(SerializeStream& stream, const void* otherObj) override; void Deserialize(DeserializeStream& stream, ISerializeModifier* modifier) override; diff --git a/Source/Engine/Level/Actors/EnvironmentProbe.cpp b/Source/Engine/Level/Actors/EnvironmentProbe.cpp index d5939d722..0b9348129 100644 --- a/Source/Engine/Level/Actors/EnvironmentProbe.cpp +++ b/Source/Engine/Level/Actors/EnvironmentProbe.cpp @@ -20,7 +20,8 @@ EnvironmentProbe::EnvironmentProbe(const SpawnParams& params) , _isUsingCustomProbe(false) , _probe(nullptr) { - UpdateBounds(); + _sphere = BoundingSphere(Vector3::Zero, _radius); + BoundingBox::FromSphere(_sphere, _box); } float EnvironmentProbe::GetRadius() const @@ -125,6 +126,8 @@ void EnvironmentProbe::UpdateBounds() { _sphere = BoundingSphere(GetPosition(), GetScaledRadius()); BoundingBox::FromSphere(_sphere, _box); + if (_sceneRenderingKey != -1) + GetSceneRendering()->UpdateCommon(this, _sceneRenderingKey); } void EnvironmentProbe::Draw(RenderContext& renderContext) @@ -150,6 +153,12 @@ void EnvironmentProbe::OnDebugDrawSelected() #endif +void EnvironmentProbe::OnLayerChanged() +{ + if (_sceneRenderingKey != -1) + GetSceneRendering()->UpdateCommon(this, _sceneRenderingKey); +} + void EnvironmentProbe::Serialize(SerializeStream& stream, const void* otherObj) { // Base @@ -190,7 +199,7 @@ bool EnvironmentProbe::IntersectsItself(const Ray& ray, float& distance, Vector3 void EnvironmentProbe::OnEnable() { - GetSceneRendering()->AddCommon(this); + _sceneRenderingKey = GetSceneRendering()->AddCommon(this); #if USE_EDITOR GetSceneRendering()->AddViewportIcon(this); #endif @@ -204,7 +213,7 @@ void EnvironmentProbe::OnDisable() #if USE_EDITOR GetSceneRendering()->RemoveViewportIcon(this); #endif - GetSceneRendering()->RemoveCommon(this); + GetSceneRendering()->RemoveCommon(this, _sceneRenderingKey); // Base Actor::OnDisable(); diff --git a/Source/Engine/Level/Actors/EnvironmentProbe.h b/Source/Engine/Level/Actors/EnvironmentProbe.h index 58fdcf73b..a8fcc8e08 100644 --- a/Source/Engine/Level/Actors/EnvironmentProbe.h +++ b/Source/Engine/Level/Actors/EnvironmentProbe.h @@ -16,6 +16,7 @@ private: float _radius; bool _isUsingCustomProbe; + int32 _sceneRenderingKey = -1; AssetReference _probe; public: @@ -138,6 +139,7 @@ public: #if USE_EDITOR void OnDebugDrawSelected() override; #endif + void OnLayerChanged() 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/ModelInstanceActor.cpp b/Source/Engine/Level/Actors/ModelInstanceActor.cpp index 989eceb9f..42a81244c 100644 --- a/Source/Engine/Level/Actors/ModelInstanceActor.cpp +++ b/Source/Engine/Level/Actors/ModelInstanceActor.cpp @@ -31,9 +31,15 @@ MaterialInstance* ModelInstanceActor::CreateAndSetVirtualMaterialInstance(int32 return result; } +void ModelInstanceActor::OnLayerChanged() +{ + if (_sceneRenderingKey != -1) + GetSceneRendering()->UpdateGeometry(this, _sceneRenderingKey); +} + void ModelInstanceActor::OnEnable() { - GetSceneRendering()->AddGeometry(this); + _sceneRenderingKey = GetSceneRendering()->AddGeometry(this); // Base Actor::OnEnable(); @@ -41,7 +47,7 @@ void ModelInstanceActor::OnEnable() void ModelInstanceActor::OnDisable() { - GetSceneRendering()->RemoveGeometry(this); + GetSceneRendering()->RemoveGeometry(this, _sceneRenderingKey); // Base Actor::OnDisable(); diff --git a/Source/Engine/Level/Actors/ModelInstanceActor.h b/Source/Engine/Level/Actors/ModelInstanceActor.h index 7b2a08fd9..2bf55fcc9 100644 --- a/Source/Engine/Level/Actors/ModelInstanceActor.h +++ b/Source/Engine/Level/Actors/ModelInstanceActor.h @@ -12,6 +12,10 @@ API_CLASS(Abstract) class FLAXENGINE_API ModelInstanceActor : public Actor { DECLARE_SCENE_OBJECT_ABSTRACT(ModelInstanceActor); +protected: + + int32 _sceneRenderingKey = -1; + public: /// @@ -79,6 +83,11 @@ public: return false; } +public: + + // [Actor] + void OnLayerChanged() override; + protected: // [Actor] diff --git a/Source/Engine/Level/Actors/PointLight.cpp b/Source/Engine/Level/Actors/PointLight.cpp index 9341002c1..a83f443cd 100644 --- a/Source/Engine/Level/Actors/PointLight.cpp +++ b/Source/Engine/Level/Actors/PointLight.cpp @@ -15,7 +15,9 @@ PointLight::PointLight(const SpawnParams& params) ShadowsDistance = 2000.0f; ShadowsFadeDistance = 100.0f; ShadowsDepthBias = 0.5f; - UpdateBounds(); + _direction = Vector3::Forward; + _sphere = BoundingSphere(Vector3::Zero, _radius); + BoundingBox::FromSphere(_sphere, _box); } float PointLight::ComputeBrightness() const @@ -62,11 +64,14 @@ void PointLight::UpdateBounds() // Cache bounding box _sphere = BoundingSphere(GetPosition(), GetScaledRadius()); BoundingBox::FromSphere(_sphere, _box); + + if (_sceneRenderingKey != -1) + GetSceneRendering()->UpdateCommon(this, _sceneRenderingKey); } void PointLight::OnEnable() { - GetSceneRendering()->AddCommon(this); + _sceneRenderingKey = GetSceneRendering()->AddCommon(this); #if USE_EDITOR GetSceneRendering()->AddViewportIcon(this); #endif @@ -80,7 +85,7 @@ void PointLight::OnDisable() #if USE_EDITOR GetSceneRendering()->RemoveViewportIcon(this); #endif - GetSceneRendering()->RemoveCommon(this); + GetSceneRendering()->RemoveCommon(this, _sceneRenderingKey); // Base LightWithShadow::OnDisable(); @@ -157,6 +162,12 @@ void PointLight::OnDebugDrawSelected() #endif +void PointLight::OnLayerChanged() +{ + if (_sceneRenderingKey != -1) + GetSceneRendering()->UpdateCommon(this, _sceneRenderingKey); +} + void PointLight::Serialize(SerializeStream& stream, const void* otherObj) { // Base diff --git a/Source/Engine/Level/Actors/PointLight.h b/Source/Engine/Level/Actors/PointLight.h index defa6d749..53c4fd309 100644 --- a/Source/Engine/Level/Actors/PointLight.h +++ b/Source/Engine/Level/Actors/PointLight.h @@ -16,6 +16,7 @@ private: Vector3 _direction; float _radius; + int32 _sceneRenderingKey = -1; public: @@ -101,6 +102,7 @@ public: void OnDebugDraw() override; void OnDebugDrawSelected() override; #endif + void OnLayerChanged() override; void Serialize(SerializeStream& stream, const void* otherObj) override; void Deserialize(DeserializeStream& stream, ISerializeModifier* modifier) override; bool IntersectsItself(const Ray& ray, float& distance, Vector3& normal) override; diff --git a/Source/Engine/Level/Actors/SpotLight.cpp b/Source/Engine/Level/Actors/SpotLight.cpp index ec25ffb5b..c4c5c8c86 100644 --- a/Source/Engine/Level/Actors/SpotLight.cpp +++ b/Source/Engine/Level/Actors/SpotLight.cpp @@ -18,7 +18,14 @@ SpotLight::SpotLight(const SpawnParams& params) ShadowsDistance = 2000.0f; ShadowsFadeDistance = 100.0f; ShadowsDepthBias = 0.5f; - UpdateBounds(); + + _direction = Vector3::Forward; + _cosOuterCone = Math::Cos(_outerConeAngle * DegreesToRadians); + _cosInnerCone = Math::Cos(_innerConeAngle * DegreesToRadians); + _invCosConeDifference = 1.0f / (_cosInnerCone - _cosOuterCone); + const float boundsRadius = Math::Sqrt(1.25f * _radius * _radius - _radius * _radius * _cosOuterCone); + _sphere = BoundingSphere(GetPosition() + 0.5f * GetDirection() * _radius, boundsRadius); + BoundingBox::FromSphere(_sphere, _box); } float SpotLight::ComputeBrightness() const @@ -105,11 +112,14 @@ void SpotLight::UpdateBounds() const float boundsRadius = Math::Sqrt(1.25f * radius * radius - radius * radius * _cosOuterCone); _sphere = BoundingSphere(GetPosition() + 0.5f * GetDirection() * radius, boundsRadius); BoundingBox::FromSphere(_sphere, _box); + + if (_sceneRenderingKey != -1) + GetSceneRendering()->UpdateCommon(this, _sceneRenderingKey); } void SpotLight::OnEnable() { - GetSceneRendering()->AddCommon(this); + _sceneRenderingKey = GetSceneRendering()->AddCommon(this); #if USE_EDITOR GetSceneRendering()->AddViewportIcon(this); #endif @@ -123,7 +133,7 @@ void SpotLight::OnDisable() #if USE_EDITOR GetSceneRendering()->RemoveViewportIcon(this); #endif - GetSceneRendering()->RemoveCommon(this); + GetSceneRendering()->RemoveCommon(this, _sceneRenderingKey); // Base LightWithShadow::OnDisable(); diff --git a/Source/Engine/Level/Actors/SpotLight.h b/Source/Engine/Level/Actors/SpotLight.h index 19f6ab1a3..3d8974669 100644 --- a/Source/Engine/Level/Actors/SpotLight.h +++ b/Source/Engine/Level/Actors/SpotLight.h @@ -21,6 +21,7 @@ private: float _cosOuterCone; float _cosInnerCone; float _invCosConeDifference; + int32 _sceneRenderingKey = -1; public: diff --git a/Source/Engine/Level/Actors/StaticModel.cpp b/Source/Engine/Level/Actors/StaticModel.cpp index 0005e74f9..072f795b2 100644 --- a/Source/Engine/Level/Actors/StaticModel.cpp +++ b/Source/Engine/Level/Actors/StaticModel.cpp @@ -193,6 +193,8 @@ void StaticModel::UpdateBounds() _box = BoundingBox(_transform.Translation); } BoundingSphere::FromBox(_box, _sphere); + if (_sceneRenderingKey != -1) + GetSceneRendering()->UpdateGeometry(this, _sceneRenderingKey); } bool StaticModel::HasContentLoaded() const @@ -245,7 +247,7 @@ void StaticModel::Draw(RenderContext& renderContext) draw.DrawState = &_drawState; draw.Lightmap = _scene->LightmapsData.GetReadyLightmap(Lightmap.TextureIndex); draw.LightmapUVs = &Lightmap.UVsArea; - draw.Flags = GetStaticFlags(); + draw.Flags = _staticFlags; draw.DrawModes = drawModes; draw.Bounds = _sphere; draw.PerInstanceRandom = GetPerInstanceRandom(); diff --git a/Source/Engine/Level/Scene/SceneRendering.cpp b/Source/Engine/Level/Scene/SceneRendering.cpp index ce93b3e1c..dce13814b 100644 --- a/Source/Engine/Level/Scene/SceneRendering.cpp +++ b/Source/Engine/Level/Scene/SceneRendering.cpp @@ -4,10 +4,14 @@ #include "Scene.h" #include "Engine/Graphics/RenderTask.h" #include "Engine/Graphics/RenderView.h" -#include "Engine/Level/Actors/PostFxVolume.h" +#define SCENE_RENDERING_USE_PROFILER 0 #define SCENE_RENDERING_USE_SIMD 0 +#if SCENE_RENDERING_USE_PROFILER +#include "Engine/Profiler/ProfilerCPU.h" +#endif + #if SCENE_RENDERING_USE_SIMD #include "Engine/Core/SIMD.h" @@ -22,14 +26,49 @@ ALIGN_BEGIN(16) struct CullDataSIMD #endif -SceneRendering::SceneRendering(::Scene* scene) - : Scene(scene) +int32 SceneRendering::DrawEntries::Add(Actor* obj) { + int32 key = 0; + for (; key < List.Count(); key++) + { + if (List[key].Actor == nullptr) + break; + } + if (key == List.Count()) + List.AddOne(); + auto& e = List[key]; + e.Actor = obj; + e.LayerMask = obj->GetLayerMask(); + e.Bounds = obj->GetSphere(); + return key; } -void CullAndDraw(const BoundingFrustum& frustum, RenderContext& renderContext, const Array& actors) +void SceneRendering::DrawEntries::Update(Actor* obj, int32 key) +{ + auto& e = List[key]; + ASSERT_LOW_LAYER(obj == e.Actor); + e.LayerMask = obj->GetLayerMask(); + e.Bounds = obj->GetSphere(); +} + +void SceneRendering::DrawEntries::Remove(Actor* obj, int32 key) +{ + if (List.IsEmpty()) + return; + auto& e = List[key]; + ASSERT_LOW_LAYER(obj == e.Actor); + e.Actor = nullptr; +} + +void SceneRendering::DrawEntries::Clear() +{ + List.Clear(); +} + +void SceneRendering::DrawEntries::CullAndDraw(RenderContext& renderContext) { auto& view = renderContext.View; + const BoundingFrustum frustum = view.CullingFrustum; #if SCENE_RENDERING_USE_SIMD CullDataSIMD cullData; { @@ -97,8 +136,10 @@ void CullAndDraw(const BoundingFrustum& frustum, RenderContext& renderContext, c float4 pz2 = SIMD::Load(&cullData.zs[4]); float4 pd2 = SIMD::Load(&cullData.ds[4]); - for (int32 i = 0; i < actors.Count(); i++) + for (int32 i = 0; i < List.Count(); i++) { + auto& e = List[i]; + const auto& sphere = actors[i]->GetSphere(); float4 cx = SIMD::Splat(sphere.Center.X); float4 cy = SIMD::Splat(sphere.Center.Y); @@ -121,21 +162,28 @@ void CullAndDraw(const BoundingFrustum& frustum, RenderContext& renderContext, c if (SIMD::MoveMask(t)) continue; - actors[i]->Draw(renderContext); + e.Actor->Draw(renderContext); } #else - for (int32 i = 0; i < actors.Count(); i++) + for (int32 i = 0; i < List.Count(); i++) { - auto actor = actors[i]; - if (view.RenderLayersMask.HasLayer(actor->GetLayer()) && frustum.Intersects(actor->GetSphere())) - actor->Draw(renderContext); + auto e = List[i]; + if (view.RenderLayersMask.Mask & e.LayerMask && frustum.Intersects(e.Bounds)) + { +#if SCENE_RENDERING_USE_PROFILER + PROFILE_CPU(); + ___tracy_scoped_zone.Name(*e.Actor->GetName(), e.Actor->GetName().Length()); +#endif + e.Actor->Draw(renderContext); + } } #endif } -void CullAndDrawOffline(const BoundingFrustum& frustum, RenderContext& renderContext, const Array& actors) +void SceneRendering::DrawEntries::CullAndDrawOffline(RenderContext& renderContext) { auto& view = renderContext.View; + const BoundingFrustum frustum = view.CullingFrustum; #if SCENE_RENDERING_USE_SIMD CullDataSIMD cullData; { @@ -231,15 +279,26 @@ void CullAndDrawOffline(const BoundingFrustum& frustum, RenderContext& renderCon actors[i]->Draw(renderContext); } #else - for (int32 i = 0; i < actors.Count(); i++) + for (int32 i = 0; i < List.Count(); i++) { - auto actor = actors[i]; - if (actor->GetStaticFlags() & view.StaticFlagsMask && view.RenderLayersMask.HasLayer(actor->GetLayer()) && frustum.Intersects(actor->GetSphere())) - actor->Draw(renderContext); + auto e = List[i]; + if (view.RenderLayersMask.Mask & e.LayerMask && frustum.Intersects(e.Bounds) && e.Actor->GetStaticFlags() & view.StaticFlagsMask) + { +#if SCENE_RENDERING_USE_PROFILER + PROFILE_CPU(); + ___tracy_scoped_zone.Name(*e.Actor->GetName(), e.Actor->GetName().Length()); +#endif + e.Actor->Draw(renderContext); + } } #endif } +SceneRendering::SceneRendering(::Scene* scene) + : Scene(scene) +{ +} + void SceneRendering::Draw(RenderContext& renderContext) { // Skip if disabled @@ -248,13 +307,12 @@ void SceneRendering::Draw(RenderContext& renderContext) auto& view = renderContext.View; // Draw all visual components - const BoundingFrustum frustum = view.CullingFrustum; if (view.IsOfflinePass) { - CullAndDrawOffline(frustum, renderContext, Geometry); + Geometry.CullAndDrawOffline(renderContext); if (view.Pass & DrawPass::GBuffer) { - CullAndDrawOffline(frustum, renderContext, Common); + Common.CullAndDrawOffline(renderContext); for (int32 i = 0; i < CommonNoCulling.Count(); i++) { auto actor = CommonNoCulling[i]; @@ -265,15 +323,21 @@ void SceneRendering::Draw(RenderContext& renderContext) } else { - CullAndDraw(frustum, renderContext, Geometry); + Geometry.CullAndDraw(renderContext); if (view.Pass & DrawPass::GBuffer) { - CullAndDraw(frustum, renderContext, Common); + Common.CullAndDraw(renderContext); for (int32 i = 0; i < CommonNoCulling.Count(); i++) { auto actor = CommonNoCulling[i]; if (view.RenderLayersMask.HasLayer(actor->GetLayer())) + { +#if SCENE_RENDERING_USE_PROFILER + PROFILE_CPU(); + ___tracy_scoped_zone.Name(*actor->GetName(), actor->GetName().Length()); +#endif actor->Draw(renderContext); + } } } } @@ -294,6 +358,9 @@ void SceneRendering::Draw(RenderContext& renderContext) void SceneRendering::CollectPostFxVolumes(RenderContext& renderContext) { +#if SCENE_RENDERING_USE_PROFILER + PROFILE_CPU(); +#endif for (int32 i = 0; i < PostFxProviders.Count(); i++) { PostFxProviders[i]->Collect(renderContext); diff --git a/Source/Engine/Level/Scene/SceneRendering.h b/Source/Engine/Level/Scene/SceneRendering.h index ca76b88d8..7a4bc68d5 100644 --- a/Source/Engine/Level/Scene/SceneRendering.h +++ b/Source/Engine/Level/Scene/SceneRendering.h @@ -4,6 +4,8 @@ #include "Engine/Core/Delegate.h" #include "Engine/Core/Collections/Array.h" +#include "Engine/Core/Math/BoundingSphere.h" +#include "Engine/Level/Actor.h" #include "Engine/Level/Types.h" class SceneRenderTask; @@ -14,7 +16,7 @@ struct RenderView; /// /// Interface for actors that can override the default rendering settings (eg. PostFxVolume actor). /// -class IPostFxSettingsProvider +class FLAXENGINE_API IPostFxSettingsProvider { public: @@ -35,24 +37,37 @@ public: /// /// Scene rendering helper subsystem that boosts the level rendering by providing efficient objects cache and culling implementation. /// -class SceneRendering +class FLAXENGINE_API SceneRendering { friend Scene; - #if USE_EDITOR typedef Function PhysicsDebugCallback; + friend class ViewportIconsRendererService; #endif + struct DrawEntry + { + Actor* Actor; + uint32 LayerMask; + BoundingSphere Bounds; + }; + + struct DrawEntries + { + Array List; + + int32 Add(Actor* obj); + void Update(Actor* obj, int32 key); + void Remove(Actor* obj, int32 key); + void Clear(); + void CullAndDraw(RenderContext& renderContext); + void CullAndDrawOffline(RenderContext& renderContext); + }; private: - // Private data Scene* Scene; - -public: - - // Things to draw - Array Geometry; - Array Common; + DrawEntries Geometry; + DrawEntries Common; Array CommonNoCulling; Array PostFxProviders; #if USE_EDITOR @@ -83,24 +98,36 @@ public: public: - FORCE_INLINE void AddGeometry(Actor* obj) + FORCE_INLINE int32 AddGeometry(Actor* obj) { - Geometry.Add(obj); + return Geometry.Add(obj); } - FORCE_INLINE void RemoveGeometry(Actor* obj) + FORCE_INLINE void UpdateGeometry(Actor* obj, int32 key) { - Geometry.Remove(obj); + Geometry.Update(obj, key); } - FORCE_INLINE void AddCommon(Actor* obj) + FORCE_INLINE void RemoveGeometry(Actor* obj, int32& key) { - Common.Add(obj); + Geometry.Remove(obj, key); + key = -1; } - FORCE_INLINE void RemoveCommon(Actor* obj) + FORCE_INLINE int32 AddCommon(Actor* obj) { - Common.Remove(obj); + return Common.Add(obj); + } + + FORCE_INLINE void UpdateCommon(Actor* obj, int32 key) + { + Common.Update(obj, key); + } + + FORCE_INLINE void RemoveCommon(Actor* obj, int32& key) + { + Common.Remove(obj, key); + key = -1; } FORCE_INLINE void AddCommonNoCulling(Actor* obj) diff --git a/Source/Engine/Particles/ParticleEffect.cpp b/Source/Engine/Particles/ParticleEffect.cpp index 309b760fe..7b8f599fe 100644 --- a/Source/Engine/Particles/ParticleEffect.cpp +++ b/Source/Engine/Particles/ParticleEffect.cpp @@ -311,6 +311,8 @@ void ParticleEffect::UpdateBounds() _box = bounds; BoundingSphere::FromBox(bounds, _sphere); + if (_sceneRenderingKey != -1) + GetSceneRendering()->UpdateGeometry(this, _sceneRenderingKey); } void ParticleEffect::Sync() @@ -515,6 +517,12 @@ void ParticleEffect::OnDebugDrawSelected() #endif +void ParticleEffect::OnLayerChanged() +{ + if (_sceneRenderingKey != -1) + GetSceneRendering()->UpdateGeometry(this, _sceneRenderingKey); +} + void ParticleEffect::Serialize(SerializeStream& stream, const void* otherObj) { // Base @@ -691,7 +699,7 @@ void ParticleEffect::EndPlay() void ParticleEffect::OnEnable() { GetScene()->Ticking.Update.AddTick(this); - GetSceneRendering()->AddGeometry(this); + _sceneRenderingKey = GetSceneRendering()->AddGeometry(this); #if USE_EDITOR GetSceneRendering()->AddViewportIcon(this); GetScene()->Ticking.Update.AddTickExecuteInEditor(this); @@ -707,7 +715,7 @@ void ParticleEffect::OnDisable() GetScene()->Ticking.Update.RemoveTickExecuteInEditor(this); GetSceneRendering()->RemoveViewportIcon(this); #endif - GetSceneRendering()->RemoveGeometry(this); + GetSceneRendering()->RemoveGeometry(this, _sceneRenderingKey); GetScene()->Ticking.Update.RemoveTick(this); // Base diff --git a/Source/Engine/Particles/ParticleEffect.h b/Source/Engine/Particles/ParticleEffect.h index f6dc3788a..ac9a43a91 100644 --- a/Source/Engine/Particles/ParticleEffect.h +++ b/Source/Engine/Particles/ParticleEffect.h @@ -184,6 +184,7 @@ private: uint64 _lastUpdateFrame; float _lastMinDstSqr; Matrix _world; + int32 _sceneRenderingKey = -1; uint32 _parametersVersion = 0; // Version number for _parameters to be in sync with Instance.ParametersVersion Array _parameters; // Cached for scripting API Array _parametersOverrides; // Cached parameter modifications to be applied to the parameters @@ -388,6 +389,7 @@ public: #if USE_EDITOR void OnDebugDrawSelected() override; #endif + void OnLayerChanged() override; void Serialize(SerializeStream& stream, const void* otherObj) override; void Deserialize(DeserializeStream& stream, ISerializeModifier* modifier) override; #if USE_EDITOR diff --git a/Source/Engine/Terrain/Terrain.cpp b/Source/Engine/Terrain/Terrain.cpp index 8aff910f3..58be6f73c 100644 --- a/Source/Engine/Terrain/Terrain.cpp +++ b/Source/Engine/Terrain/Terrain.cpp @@ -47,6 +47,8 @@ void Terrain::UpdateBounds() BoundingBox::Merge(_box, patch->_bounds, _box); } BoundingSphere::FromBox(_box, _sphere); + if (_sceneRenderingKey != -1) + GetSceneRendering()->UpdateGeometry(this, _sceneRenderingKey); } void Terrain::CacheNeighbors() @@ -752,7 +754,7 @@ RigidBody* Terrain::GetAttachedRigidBody() const void Terrain::OnEnable() { - GetSceneRendering()->AddGeometry(this); + _sceneRenderingKey = GetSceneRendering()->AddGeometry(this); #if TERRAIN_USE_PHYSICS_DEBUG GetSceneRendering()->AddPhysicsDebug(this); #endif @@ -763,7 +765,7 @@ void Terrain::OnEnable() void Terrain::OnDisable() { - GetSceneRendering()->RemoveGeometry(this); + GetSceneRendering()->RemoveGeometry(this, _sceneRenderingKey); #if TERRAIN_USE_PHYSICS_DEBUG GetSceneRendering()->RemovePhysicsDebug(this); #endif @@ -803,6 +805,8 @@ void Terrain::OnLayerChanged() Actor::OnLayerChanged(); UpdateLayerBits(); + if (_sceneRenderingKey != -1) + GetSceneRendering()->UpdateGeometry(this, _sceneRenderingKey); } void Terrain::OnActiveInTreeChanged() diff --git a/Source/Engine/Terrain/Terrain.h b/Source/Engine/Terrain/Terrain.h index 5ad8378e9..2800b58b1 100644 --- a/Source/Engine/Terrain/Terrain.h +++ b/Source/Engine/Terrain/Terrain.h @@ -53,6 +53,7 @@ private: char _collisionLod; byte _lodCount; uint16 _chunkSize; + int32 _sceneRenderingKey = -1; float _scaleInLightmap; float _lodDistribution; Vector3 _boundsExtent; @@ -444,6 +445,7 @@ public: #if USE_EDITOR void OnDebugDrawSelected() override; #endif + void OnLayerChanged() override; bool IntersectsItself(const Ray& ray, float& distance, Vector3& normal) override; void Serialize(SerializeStream& stream, const void* otherObj) override; void Deserialize(DeserializeStream& stream, ISerializeModifier* modifier) override; @@ -455,7 +457,6 @@ protected: void OnEnable() override; void OnDisable() override; void OnTransformChanged() override; - void OnLayerChanged() override; void OnActiveInTreeChanged() override; void BeginPlay(SceneBeginData* data) override; void EndPlay() override; diff --git a/Source/Engine/UI/SpriteRender.cpp b/Source/Engine/UI/SpriteRender.cpp index e82c523c3..985b8b2da 100644 --- a/Source/Engine/UI/SpriteRender.cpp +++ b/Source/Engine/UI/SpriteRender.cpp @@ -170,6 +170,12 @@ void SpriteRender::Deserialize(DeserializeStream& stream, ISerializeModifier* mo _paramColor->SetValue(_color); } +void SpriteRender::OnLayerChanged() +{ + if (_sceneRenderingKey != -1) + GetSceneRendering()->UpdateGeometry(this, _sceneRenderingKey); +} + void SpriteRender::OnEndPlay() { // Base @@ -187,7 +193,7 @@ void SpriteRender::OnEndPlay() void SpriteRender::OnEnable() { - GetSceneRendering()->AddGeometry(this); + _sceneRenderingKey = GetSceneRendering()->AddGeometry(this); // Base Actor::OnEnable(); @@ -195,7 +201,7 @@ void SpriteRender::OnEnable() void SpriteRender::OnDisable() { - GetSceneRendering()->RemoveGeometry(this); + GetSceneRendering()->RemoveGeometry(this, _sceneRenderingKey); // Base Actor::OnDisable(); @@ -211,4 +217,6 @@ void SpriteRender::OnTransformChanged() _transform.GetWorld(world); BoundingSphere::Transform(localSphere, world, _sphere); BoundingBox::FromSphere(_sphere, _box); + if (_sceneRenderingKey != -1) + GetSceneRendering()->UpdateGeometry(this, _sceneRenderingKey); } diff --git a/Source/Engine/UI/SpriteRender.h b/Source/Engine/UI/SpriteRender.h index 9bd9eeaf0..6965b1317 100644 --- a/Source/Engine/UI/SpriteRender.h +++ b/Source/Engine/UI/SpriteRender.h @@ -23,6 +23,7 @@ private: MaterialParameter* _paramImageMAD = nullptr; MaterialParameter* _paramColor = nullptr; AssetReference _quadModel; + int32 _sceneRenderingKey = -1; public: @@ -97,6 +98,7 @@ public: void DrawGeneric(RenderContext& renderContext) override; void Serialize(SerializeStream& stream, const void* otherObj) override; void Deserialize(DeserializeStream& stream, ISerializeModifier* modifier) override; + void OnLayerChanged() override; void OnEndPlay() override; protected: diff --git a/Source/Engine/UI/TextRender.cpp b/Source/Engine/UI/TextRender.cpp index 30335aee3..512f91d93 100644 --- a/Source/Engine/UI/TextRender.cpp +++ b/Source/Engine/UI/TextRender.cpp @@ -329,6 +329,8 @@ void TextRender::UpdateLayout() _localBox = box; BoundingBox::Transform(_localBox, _world, _box); BoundingSphere::FromBox(_box, _sphere); + if (_sceneRenderingKey != -1) + GetSceneRendering()->UpdateGeometry(this, _sceneRenderingKey); } bool TextRender::HasContentLoaded() const @@ -421,6 +423,12 @@ void TextRender::OnDebugDrawSelected() #endif +void TextRender::OnLayerChanged() +{ + if (_sceneRenderingKey != -1) + GetSceneRendering()->UpdateGeometry(this, _sceneRenderingKey); +} + bool TextRender::IntersectsItself(const Ray& ray, float& distance, Vector3& normal) { #if USE_PRECISE_MESH_INTERSECTS @@ -480,8 +488,6 @@ void TextRender::Deserialize(DeserializeStream& stream, ISerializeModifier* modi void TextRender::OnEnable() { - GetSceneRendering()->AddGeometry(this); - // Base Actor::OnEnable(); @@ -489,6 +495,7 @@ void TextRender::OnEnable() { UpdateLayout(); } + _sceneRenderingKey = GetSceneRendering()->AddGeometry(this); } void TextRender::OnDisable() @@ -498,7 +505,7 @@ void TextRender::OnDisable() _isLocalized = false; Localization::LocalizationChanged.Unbind(this); } - GetSceneRendering()->RemoveGeometry(this); + GetSceneRendering()->RemoveGeometry(this, _sceneRenderingKey); // Base Actor::OnDisable(); @@ -512,4 +519,6 @@ void TextRender::OnTransformChanged() _transform.GetWorld(_world); BoundingBox::Transform(_localBox, _world, _box); BoundingSphere::FromBox(_box, _sphere); + if (_sceneRenderingKey != -1) + GetSceneRendering()->UpdateGeometry(this, _sceneRenderingKey); } diff --git a/Source/Engine/UI/TextRender.h b/Source/Engine/UI/TextRender.h index fff3915a5..8d01fec49 100644 --- a/Source/Engine/UI/TextRender.h +++ b/Source/Engine/UI/TextRender.h @@ -40,6 +40,7 @@ private: Color _color; TextLayoutOptions _layoutOptions; int32 _size; + int32 _sceneRenderingKey = -1; BoundingBox _localBox; Matrix _world; @@ -169,6 +170,7 @@ public: #if USE_EDITOR void OnDebugDrawSelected() override; #endif + void OnLayerChanged() override; bool IntersectsItself(const Ray& ray, float& distance, Vector3& normal) override; void Serialize(SerializeStream& stream, const void* otherObj) override; void Deserialize(DeserializeStream& stream, ISerializeModifier* modifier) override;