Optimize Scene Rendering (cache drawable bounds and layers for culling with less cache misses)

This commit is contained in:
Wojtek Figat
2021-06-28 22:04:25 +02:00
parent e61ebaa71b
commit d7332509f7
26 changed files with 335 additions and 130 deletions

View File

@@ -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; bool Init() override;
void Dispose() override; void Dispose() override;
}; };
ViewportIconsRendererService ViewportIconsRendererServiceInstance; 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<int32>(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<int32>(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) void ViewportIconsRenderer::DrawIcons(RenderContext& renderContext, Actor* actor)
{ {
auto& view = renderContext.View; auto& view = renderContext.View;
@@ -137,14 +77,73 @@ void ViewportIconsRenderer::DrawIcons(RenderContext& renderContext, Actor* actor
if (const auto scene = SceneObject::Cast<Scene>(actor)) if (const auto scene = SceneObject::Cast<Scene>(actor))
{ {
::DrawIcons(renderContext, scene, draw); ViewportIconsRendererService::DrawIcons(renderContext, scene, draw);
} }
else 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<int32>(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<int32>(iconType)];
draw.World = &world;
draw.Bounds = sphere;
QuadModel->Draw(renderContext, draw);
}
for (auto child : actor->Children)
DrawIcons(renderContext, child, draw);
}
bool ViewportIconsRendererService::Init() bool ViewportIconsRendererService::Init()
{ {
QuadModel = Content::LoadAsyncInternal<Model>(TEXT("Engine/Models/Quad")); QuadModel = Content::LoadAsyncInternal<Model>(TEXT("Engine/Models/Quad"));

View File

@@ -62,7 +62,7 @@ public:
LayersMask operator&(const LayersMask& other) const LayersMask operator&(const LayersMask& other) const
{ {
return Mask && other.Mask; return Mask & other.Mask;
} }
LayersMask operator|(const LayersMask& other) const LayersMask operator|(const LayersMask& other) const

View File

@@ -7,7 +7,6 @@
#include "Engine/Core/Random.h" #include "Engine/Core/Random.h"
#include "Engine/Engine/Engine.h" #include "Engine/Engine/Engine.h"
#include "Engine/Graphics/RenderTask.h" #include "Engine/Graphics/RenderTask.h"
#include "Engine/Level/Scene/Scene.h"
#include "Engine/Level/SceneQuery.h" #include "Engine/Level/SceneQuery.h"
#include "Engine/Profiler/ProfilerCPU.h" #include "Engine/Profiler/ProfilerCPU.h"
#include "Engine/Serialization/Serialization.h" #include "Engine/Serialization/Serialization.h"
@@ -68,6 +67,8 @@ void Foliage::EnsureRoot()
// Cache bounds // Cache bounds
_box = Root->Bounds; _box = Root->Bounds;
BoundingSphere::FromBox(_box, _sphere); BoundingSphere::FromBox(_box, _sphere);
if (_sceneRenderingKey != -1)
GetSceneRendering()->UpdateGeometry(this, _sceneRenderingKey);
} }
void Foliage::AddToCluster(FoliageCluster* cluster, FoliageInstance& instance) 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() void Foliage::OnEnable()
{ {
GetScene()->Rendering.AddGeometry(this); _sceneRenderingKey = GetSceneRendering()->AddGeometry(this);
// Base // Base
Actor::OnEnable(); Actor::OnEnable();
@@ -795,7 +802,7 @@ void Foliage::OnEnable()
void Foliage::OnDisable() void Foliage::OnDisable()
{ {
GetScene()->Rendering.RemoveGeometry(this); GetSceneRendering()->RemoveGeometry(this, _sceneRenderingKey);
// Base // Base
Actor::OnDisable(); Actor::OnDisable();

View File

@@ -19,6 +19,7 @@ DECLARE_SCENE_OBJECT(Foliage);
private: private:
bool _disableFoliageTypeEvents; bool _disableFoliageTypeEvents;
int32 _sceneRenderingKey = -1;
public: public:
@@ -191,6 +192,7 @@ public:
bool IntersectsItself(const Ray& ray, float& distance, Vector3& normal) override; bool IntersectsItself(const Ray& ray, float& distance, Vector3& normal) override;
void Serialize(SerializeStream& stream, const void* otherObj) override; void Serialize(SerializeStream& stream, const void* otherObj) override;
void Deserialize(DeserializeStream& stream, ISerializeModifier* modifier) override; void Deserialize(DeserializeStream& stream, ISerializeModifier* modifier) override;
void OnLayerChanged() override;
protected: protected:

View File

@@ -439,6 +439,8 @@ void AnimatedModel::UpdateBounds()
BoundingBox::Transform(_boxLocal, _world, _box); BoundingBox::Transform(_boxLocal, _world, _box);
BoundingSphere::FromBox(_box, _sphere); BoundingSphere::FromBox(_box, _sphere);
if (_sceneRenderingKey != -1)
GetSceneRendering()->UpdateGeometry(this, _sceneRenderingKey);
} }
void AnimatedModel::UpdateSockets() void AnimatedModel::UpdateSockets()
@@ -758,4 +760,6 @@ void AnimatedModel::OnTransformChanged()
_transform.GetWorld(_world); _transform.GetWorld(_world);
BoundingBox::Transform(_boxLocal, _world, _box); BoundingBox::Transform(_boxLocal, _world, _box);
BoundingSphere::FromBox(_box, _sphere); BoundingSphere::FromBox(_box, _sphere);
if (_sceneRenderingKey != -1)
GetSceneRendering()->UpdateGeometry(this, _sceneRenderingKey);
} }

View File

@@ -60,6 +60,12 @@ void Decal::OnDebugDrawSelected()
#endif #endif
void Decal::OnLayerChanged()
{
if (_sceneRenderingKey != -1)
GetSceneRendering()->UpdateCommon(this, _sceneRenderingKey);
}
void Decal::Draw(RenderContext& renderContext) void Decal::Draw(RenderContext& renderContext)
{ {
if ((renderContext.View.Flags & ViewFlags::Decals) != 0 && if ((renderContext.View.Flags & ViewFlags::Decals) != 0 &&
@@ -109,7 +115,7 @@ bool Decal::IntersectsItself(const Ray& ray, float& distance, Vector3& normal)
void Decal::OnEnable() void Decal::OnEnable()
{ {
GetSceneRendering()->AddCommon(this); _sceneRenderingKey = GetSceneRendering()->AddCommon(this);
#if USE_EDITOR #if USE_EDITOR
GetSceneRendering()->AddViewportIcon(this); GetSceneRendering()->AddViewportIcon(this);
#endif #endif
@@ -123,7 +129,7 @@ void Decal::OnDisable()
#if USE_EDITOR #if USE_EDITOR
GetSceneRendering()->RemoveViewportIcon(this); GetSceneRendering()->RemoveViewportIcon(this);
#endif #endif
GetSceneRendering()->RemoveCommon(this); GetSceneRendering()->RemoveCommon(this, _sceneRenderingKey);
// Base // Base
Actor::OnDisable(); Actor::OnDisable();
@@ -142,4 +148,7 @@ void Decal::OnTransformChanged()
_bounds.Transformation = _world; _bounds.Transformation = _world;
_bounds.GetBoundingBox(_box); _bounds.GetBoundingBox(_box);
BoundingSphere::FromBox(_box, _sphere); BoundingSphere::FromBox(_box, _sphere);
if (_sceneRenderingKey != -1)
GetSceneRendering()->UpdateCommon(this, _sceneRenderingKey);
} }

View File

@@ -18,6 +18,7 @@ private:
Vector3 _size; Vector3 _size;
OrientedBoundingBox _bounds; OrientedBoundingBox _bounds;
Matrix _world; Matrix _world;
int32 _sceneRenderingKey = -1;
public: public:
@@ -77,6 +78,7 @@ public:
#if USE_EDITOR #if USE_EDITOR
void OnDebugDrawSelected() override; void OnDebugDrawSelected() override;
#endif #endif
void OnLayerChanged() override;
void Draw(RenderContext& renderContext) override; void Draw(RenderContext& renderContext) override;
void Serialize(SerializeStream& stream, const void* otherObj) override; void Serialize(SerializeStream& stream, const void* otherObj) override;
void Deserialize(DeserializeStream& stream, ISerializeModifier* modifier) override; void Deserialize(DeserializeStream& stream, ISerializeModifier* modifier) override;

View File

@@ -20,7 +20,8 @@ EnvironmentProbe::EnvironmentProbe(const SpawnParams& params)
, _isUsingCustomProbe(false) , _isUsingCustomProbe(false)
, _probe(nullptr) , _probe(nullptr)
{ {
UpdateBounds(); _sphere = BoundingSphere(Vector3::Zero, _radius);
BoundingBox::FromSphere(_sphere, _box);
} }
float EnvironmentProbe::GetRadius() const float EnvironmentProbe::GetRadius() const
@@ -125,6 +126,8 @@ void EnvironmentProbe::UpdateBounds()
{ {
_sphere = BoundingSphere(GetPosition(), GetScaledRadius()); _sphere = BoundingSphere(GetPosition(), GetScaledRadius());
BoundingBox::FromSphere(_sphere, _box); BoundingBox::FromSphere(_sphere, _box);
if (_sceneRenderingKey != -1)
GetSceneRendering()->UpdateCommon(this, _sceneRenderingKey);
} }
void EnvironmentProbe::Draw(RenderContext& renderContext) void EnvironmentProbe::Draw(RenderContext& renderContext)
@@ -150,6 +153,12 @@ void EnvironmentProbe::OnDebugDrawSelected()
#endif #endif
void EnvironmentProbe::OnLayerChanged()
{
if (_sceneRenderingKey != -1)
GetSceneRendering()->UpdateCommon(this, _sceneRenderingKey);
}
void EnvironmentProbe::Serialize(SerializeStream& stream, const void* otherObj) void EnvironmentProbe::Serialize(SerializeStream& stream, const void* otherObj)
{ {
// Base // Base
@@ -190,7 +199,7 @@ bool EnvironmentProbe::IntersectsItself(const Ray& ray, float& distance, Vector3
void EnvironmentProbe::OnEnable() void EnvironmentProbe::OnEnable()
{ {
GetSceneRendering()->AddCommon(this); _sceneRenderingKey = GetSceneRendering()->AddCommon(this);
#if USE_EDITOR #if USE_EDITOR
GetSceneRendering()->AddViewportIcon(this); GetSceneRendering()->AddViewportIcon(this);
#endif #endif
@@ -204,7 +213,7 @@ void EnvironmentProbe::OnDisable()
#if USE_EDITOR #if USE_EDITOR
GetSceneRendering()->RemoveViewportIcon(this); GetSceneRendering()->RemoveViewportIcon(this);
#endif #endif
GetSceneRendering()->RemoveCommon(this); GetSceneRendering()->RemoveCommon(this, _sceneRenderingKey);
// Base // Base
Actor::OnDisable(); Actor::OnDisable();

View File

@@ -16,6 +16,7 @@ private:
float _radius; float _radius;
bool _isUsingCustomProbe; bool _isUsingCustomProbe;
int32 _sceneRenderingKey = -1;
AssetReference<CubeTexture> _probe; AssetReference<CubeTexture> _probe;
public: public:
@@ -138,6 +139,7 @@ public:
#if USE_EDITOR #if USE_EDITOR
void OnDebugDrawSelected() override; void OnDebugDrawSelected() override;
#endif #endif
void OnLayerChanged() override;
void Serialize(SerializeStream& stream, const void* otherObj) override; void Serialize(SerializeStream& stream, const void* otherObj) override;
void Deserialize(DeserializeStream& stream, ISerializeModifier* modifier) override; void Deserialize(DeserializeStream& stream, ISerializeModifier* modifier) override;
bool HasContentLoaded() const override; bool HasContentLoaded() const override;

View File

@@ -31,9 +31,15 @@ MaterialInstance* ModelInstanceActor::CreateAndSetVirtualMaterialInstance(int32
return result; return result;
} }
void ModelInstanceActor::OnLayerChanged()
{
if (_sceneRenderingKey != -1)
GetSceneRendering()->UpdateGeometry(this, _sceneRenderingKey);
}
void ModelInstanceActor::OnEnable() void ModelInstanceActor::OnEnable()
{ {
GetSceneRendering()->AddGeometry(this); _sceneRenderingKey = GetSceneRendering()->AddGeometry(this);
// Base // Base
Actor::OnEnable(); Actor::OnEnable();
@@ -41,7 +47,7 @@ void ModelInstanceActor::OnEnable()
void ModelInstanceActor::OnDisable() void ModelInstanceActor::OnDisable()
{ {
GetSceneRendering()->RemoveGeometry(this); GetSceneRendering()->RemoveGeometry(this, _sceneRenderingKey);
// Base // Base
Actor::OnDisable(); Actor::OnDisable();

View File

@@ -12,6 +12,10 @@
API_CLASS(Abstract) class FLAXENGINE_API ModelInstanceActor : public Actor API_CLASS(Abstract) class FLAXENGINE_API ModelInstanceActor : public Actor
{ {
DECLARE_SCENE_OBJECT_ABSTRACT(ModelInstanceActor); DECLARE_SCENE_OBJECT_ABSTRACT(ModelInstanceActor);
protected:
int32 _sceneRenderingKey = -1;
public: public:
/// <summary> /// <summary>
@@ -79,6 +83,11 @@ public:
return false; return false;
} }
public:
// [Actor]
void OnLayerChanged() override;
protected: protected:
// [Actor] // [Actor]

View File

@@ -15,7 +15,9 @@ PointLight::PointLight(const SpawnParams& params)
ShadowsDistance = 2000.0f; ShadowsDistance = 2000.0f;
ShadowsFadeDistance = 100.0f; ShadowsFadeDistance = 100.0f;
ShadowsDepthBias = 0.5f; ShadowsDepthBias = 0.5f;
UpdateBounds(); _direction = Vector3::Forward;
_sphere = BoundingSphere(Vector3::Zero, _radius);
BoundingBox::FromSphere(_sphere, _box);
} }
float PointLight::ComputeBrightness() const float PointLight::ComputeBrightness() const
@@ -62,11 +64,14 @@ void PointLight::UpdateBounds()
// Cache bounding box // Cache bounding box
_sphere = BoundingSphere(GetPosition(), GetScaledRadius()); _sphere = BoundingSphere(GetPosition(), GetScaledRadius());
BoundingBox::FromSphere(_sphere, _box); BoundingBox::FromSphere(_sphere, _box);
if (_sceneRenderingKey != -1)
GetSceneRendering()->UpdateCommon(this, _sceneRenderingKey);
} }
void PointLight::OnEnable() void PointLight::OnEnable()
{ {
GetSceneRendering()->AddCommon(this); _sceneRenderingKey = GetSceneRendering()->AddCommon(this);
#if USE_EDITOR #if USE_EDITOR
GetSceneRendering()->AddViewportIcon(this); GetSceneRendering()->AddViewportIcon(this);
#endif #endif
@@ -80,7 +85,7 @@ void PointLight::OnDisable()
#if USE_EDITOR #if USE_EDITOR
GetSceneRendering()->RemoveViewportIcon(this); GetSceneRendering()->RemoveViewportIcon(this);
#endif #endif
GetSceneRendering()->RemoveCommon(this); GetSceneRendering()->RemoveCommon(this, _sceneRenderingKey);
// Base // Base
LightWithShadow::OnDisable(); LightWithShadow::OnDisable();
@@ -157,6 +162,12 @@ void PointLight::OnDebugDrawSelected()
#endif #endif
void PointLight::OnLayerChanged()
{
if (_sceneRenderingKey != -1)
GetSceneRendering()->UpdateCommon(this, _sceneRenderingKey);
}
void PointLight::Serialize(SerializeStream& stream, const void* otherObj) void PointLight::Serialize(SerializeStream& stream, const void* otherObj)
{ {
// Base // Base

View File

@@ -16,6 +16,7 @@ private:
Vector3 _direction; Vector3 _direction;
float _radius; float _radius;
int32 _sceneRenderingKey = -1;
public: public:
@@ -101,6 +102,7 @@ public:
void OnDebugDraw() override; void OnDebugDraw() override;
void OnDebugDrawSelected() override; void OnDebugDrawSelected() override;
#endif #endif
void OnLayerChanged() override;
void Serialize(SerializeStream& stream, const void* otherObj) override; void Serialize(SerializeStream& stream, const void* otherObj) override;
void Deserialize(DeserializeStream& stream, ISerializeModifier* modifier) override; void Deserialize(DeserializeStream& stream, ISerializeModifier* modifier) override;
bool IntersectsItself(const Ray& ray, float& distance, Vector3& normal) override; bool IntersectsItself(const Ray& ray, float& distance, Vector3& normal) override;

View File

@@ -18,7 +18,14 @@ SpotLight::SpotLight(const SpawnParams& params)
ShadowsDistance = 2000.0f; ShadowsDistance = 2000.0f;
ShadowsFadeDistance = 100.0f; ShadowsFadeDistance = 100.0f;
ShadowsDepthBias = 0.5f; 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 float SpotLight::ComputeBrightness() const
@@ -105,11 +112,14 @@ void SpotLight::UpdateBounds()
const float boundsRadius = Math::Sqrt(1.25f * radius * radius - radius * radius * _cosOuterCone); const float boundsRadius = Math::Sqrt(1.25f * radius * radius - radius * radius * _cosOuterCone);
_sphere = BoundingSphere(GetPosition() + 0.5f * GetDirection() * radius, boundsRadius); _sphere = BoundingSphere(GetPosition() + 0.5f * GetDirection() * radius, boundsRadius);
BoundingBox::FromSphere(_sphere, _box); BoundingBox::FromSphere(_sphere, _box);
if (_sceneRenderingKey != -1)
GetSceneRendering()->UpdateCommon(this, _sceneRenderingKey);
} }
void SpotLight::OnEnable() void SpotLight::OnEnable()
{ {
GetSceneRendering()->AddCommon(this); _sceneRenderingKey = GetSceneRendering()->AddCommon(this);
#if USE_EDITOR #if USE_EDITOR
GetSceneRendering()->AddViewportIcon(this); GetSceneRendering()->AddViewportIcon(this);
#endif #endif
@@ -123,7 +133,7 @@ void SpotLight::OnDisable()
#if USE_EDITOR #if USE_EDITOR
GetSceneRendering()->RemoveViewportIcon(this); GetSceneRendering()->RemoveViewportIcon(this);
#endif #endif
GetSceneRendering()->RemoveCommon(this); GetSceneRendering()->RemoveCommon(this, _sceneRenderingKey);
// Base // Base
LightWithShadow::OnDisable(); LightWithShadow::OnDisable();

View File

@@ -21,6 +21,7 @@ private:
float _cosOuterCone; float _cosOuterCone;
float _cosInnerCone; float _cosInnerCone;
float _invCosConeDifference; float _invCosConeDifference;
int32 _sceneRenderingKey = -1;
public: public:

View File

@@ -193,6 +193,8 @@ void StaticModel::UpdateBounds()
_box = BoundingBox(_transform.Translation); _box = BoundingBox(_transform.Translation);
} }
BoundingSphere::FromBox(_box, _sphere); BoundingSphere::FromBox(_box, _sphere);
if (_sceneRenderingKey != -1)
GetSceneRendering()->UpdateGeometry(this, _sceneRenderingKey);
} }
bool StaticModel::HasContentLoaded() const bool StaticModel::HasContentLoaded() const
@@ -245,7 +247,7 @@ void StaticModel::Draw(RenderContext& renderContext)
draw.DrawState = &_drawState; draw.DrawState = &_drawState;
draw.Lightmap = _scene->LightmapsData.GetReadyLightmap(Lightmap.TextureIndex); draw.Lightmap = _scene->LightmapsData.GetReadyLightmap(Lightmap.TextureIndex);
draw.LightmapUVs = &Lightmap.UVsArea; draw.LightmapUVs = &Lightmap.UVsArea;
draw.Flags = GetStaticFlags(); draw.Flags = _staticFlags;
draw.DrawModes = drawModes; draw.DrawModes = drawModes;
draw.Bounds = _sphere; draw.Bounds = _sphere;
draw.PerInstanceRandom = GetPerInstanceRandom(); draw.PerInstanceRandom = GetPerInstanceRandom();

View File

@@ -4,10 +4,14 @@
#include "Scene.h" #include "Scene.h"
#include "Engine/Graphics/RenderTask.h" #include "Engine/Graphics/RenderTask.h"
#include "Engine/Graphics/RenderView.h" #include "Engine/Graphics/RenderView.h"
#include "Engine/Level/Actors/PostFxVolume.h"
#define SCENE_RENDERING_USE_PROFILER 0
#define SCENE_RENDERING_USE_SIMD 0 #define SCENE_RENDERING_USE_SIMD 0
#if SCENE_RENDERING_USE_PROFILER
#include "Engine/Profiler/ProfilerCPU.h"
#endif
#if SCENE_RENDERING_USE_SIMD #if SCENE_RENDERING_USE_SIMD
#include "Engine/Core/SIMD.h" #include "Engine/Core/SIMD.h"
@@ -22,14 +26,49 @@ ALIGN_BEGIN(16) struct CullDataSIMD
#endif #endif
SceneRendering::SceneRendering(::Scene* scene) int32 SceneRendering::DrawEntries::Add(Actor* obj)
: Scene(scene)
{ {
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<Actor*>& 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; auto& view = renderContext.View;
const BoundingFrustum frustum = view.CullingFrustum;
#if SCENE_RENDERING_USE_SIMD #if SCENE_RENDERING_USE_SIMD
CullDataSIMD cullData; CullDataSIMD cullData;
{ {
@@ -97,8 +136,10 @@ void CullAndDraw(const BoundingFrustum& frustum, RenderContext& renderContext, c
float4 pz2 = SIMD::Load(&cullData.zs[4]); float4 pz2 = SIMD::Load(&cullData.zs[4]);
float4 pd2 = SIMD::Load(&cullData.ds[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(); const auto& sphere = actors[i]->GetSphere();
float4 cx = SIMD::Splat(sphere.Center.X); float4 cx = SIMD::Splat(sphere.Center.X);
float4 cy = SIMD::Splat(sphere.Center.Y); float4 cy = SIMD::Splat(sphere.Center.Y);
@@ -121,21 +162,28 @@ void CullAndDraw(const BoundingFrustum& frustum, RenderContext& renderContext, c
if (SIMD::MoveMask(t)) if (SIMD::MoveMask(t))
continue; continue;
actors[i]->Draw(renderContext); e.Actor->Draw(renderContext);
} }
#else #else
for (int32 i = 0; i < actors.Count(); i++) for (int32 i = 0; i < List.Count(); i++)
{ {
auto actor = actors[i]; auto e = List[i];
if (view.RenderLayersMask.HasLayer(actor->GetLayer()) && frustum.Intersects(actor->GetSphere())) if (view.RenderLayersMask.Mask & e.LayerMask && frustum.Intersects(e.Bounds))
actor->Draw(renderContext); {
#if SCENE_RENDERING_USE_PROFILER
PROFILE_CPU();
___tracy_scoped_zone.Name(*e.Actor->GetName(), e.Actor->GetName().Length());
#endif
e.Actor->Draw(renderContext);
}
} }
#endif #endif
} }
void CullAndDrawOffline(const BoundingFrustum& frustum, RenderContext& renderContext, const Array<Actor*>& actors) void SceneRendering::DrawEntries::CullAndDrawOffline(RenderContext& renderContext)
{ {
auto& view = renderContext.View; auto& view = renderContext.View;
const BoundingFrustum frustum = view.CullingFrustum;
#if SCENE_RENDERING_USE_SIMD #if SCENE_RENDERING_USE_SIMD
CullDataSIMD cullData; CullDataSIMD cullData;
{ {
@@ -231,15 +279,26 @@ void CullAndDrawOffline(const BoundingFrustum& frustum, RenderContext& renderCon
actors[i]->Draw(renderContext); actors[i]->Draw(renderContext);
} }
#else #else
for (int32 i = 0; i < actors.Count(); i++) for (int32 i = 0; i < List.Count(); i++)
{ {
auto actor = actors[i]; auto e = List[i];
if (actor->GetStaticFlags() & view.StaticFlagsMask && view.RenderLayersMask.HasLayer(actor->GetLayer()) && frustum.Intersects(actor->GetSphere())) if (view.RenderLayersMask.Mask & e.LayerMask && frustum.Intersects(e.Bounds) && e.Actor->GetStaticFlags() & view.StaticFlagsMask)
actor->Draw(renderContext); {
#if SCENE_RENDERING_USE_PROFILER
PROFILE_CPU();
___tracy_scoped_zone.Name(*e.Actor->GetName(), e.Actor->GetName().Length());
#endif
e.Actor->Draw(renderContext);
}
} }
#endif #endif
} }
SceneRendering::SceneRendering(::Scene* scene)
: Scene(scene)
{
}
void SceneRendering::Draw(RenderContext& renderContext) void SceneRendering::Draw(RenderContext& renderContext)
{ {
// Skip if disabled // Skip if disabled
@@ -248,13 +307,12 @@ void SceneRendering::Draw(RenderContext& renderContext)
auto& view = renderContext.View; auto& view = renderContext.View;
// Draw all visual components // Draw all visual components
const BoundingFrustum frustum = view.CullingFrustum;
if (view.IsOfflinePass) if (view.IsOfflinePass)
{ {
CullAndDrawOffline(frustum, renderContext, Geometry); Geometry.CullAndDrawOffline(renderContext);
if (view.Pass & DrawPass::GBuffer) if (view.Pass & DrawPass::GBuffer)
{ {
CullAndDrawOffline(frustum, renderContext, Common); Common.CullAndDrawOffline(renderContext);
for (int32 i = 0; i < CommonNoCulling.Count(); i++) for (int32 i = 0; i < CommonNoCulling.Count(); i++)
{ {
auto actor = CommonNoCulling[i]; auto actor = CommonNoCulling[i];
@@ -265,15 +323,21 @@ void SceneRendering::Draw(RenderContext& renderContext)
} }
else else
{ {
CullAndDraw(frustum, renderContext, Geometry); Geometry.CullAndDraw(renderContext);
if (view.Pass & DrawPass::GBuffer) if (view.Pass & DrawPass::GBuffer)
{ {
CullAndDraw(frustum, renderContext, Common); Common.CullAndDraw(renderContext);
for (int32 i = 0; i < CommonNoCulling.Count(); i++) for (int32 i = 0; i < CommonNoCulling.Count(); i++)
{ {
auto actor = CommonNoCulling[i]; auto actor = CommonNoCulling[i];
if (view.RenderLayersMask.HasLayer(actor->GetLayer())) 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); actor->Draw(renderContext);
}
} }
} }
} }
@@ -294,6 +358,9 @@ void SceneRendering::Draw(RenderContext& renderContext)
void SceneRendering::CollectPostFxVolumes(RenderContext& renderContext) void SceneRendering::CollectPostFxVolumes(RenderContext& renderContext)
{ {
#if SCENE_RENDERING_USE_PROFILER
PROFILE_CPU();
#endif
for (int32 i = 0; i < PostFxProviders.Count(); i++) for (int32 i = 0; i < PostFxProviders.Count(); i++)
{ {
PostFxProviders[i]->Collect(renderContext); PostFxProviders[i]->Collect(renderContext);

View File

@@ -4,6 +4,8 @@
#include "Engine/Core/Delegate.h" #include "Engine/Core/Delegate.h"
#include "Engine/Core/Collections/Array.h" #include "Engine/Core/Collections/Array.h"
#include "Engine/Core/Math/BoundingSphere.h"
#include "Engine/Level/Actor.h"
#include "Engine/Level/Types.h" #include "Engine/Level/Types.h"
class SceneRenderTask; class SceneRenderTask;
@@ -14,7 +16,7 @@ struct RenderView;
/// <summary> /// <summary>
/// Interface for actors that can override the default rendering settings (eg. PostFxVolume actor). /// Interface for actors that can override the default rendering settings (eg. PostFxVolume actor).
/// </summary> /// </summary>
class IPostFxSettingsProvider class FLAXENGINE_API IPostFxSettingsProvider
{ {
public: public:
@@ -35,24 +37,37 @@ public:
/// <summary> /// <summary>
/// Scene rendering helper subsystem that boosts the level rendering by providing efficient objects cache and culling implementation. /// Scene rendering helper subsystem that boosts the level rendering by providing efficient objects cache and culling implementation.
/// </summary> /// </summary>
class SceneRendering class FLAXENGINE_API SceneRendering
{ {
friend Scene; friend Scene;
#if USE_EDITOR #if USE_EDITOR
typedef Function<void(RenderView&)> PhysicsDebugCallback; typedef Function<void(RenderView&)> PhysicsDebugCallback;
friend class ViewportIconsRendererService;
#endif #endif
struct DrawEntry
{
Actor* Actor;
uint32 LayerMask;
BoundingSphere Bounds;
};
struct DrawEntries
{
Array<DrawEntry> 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:
// Private data
Scene* Scene; Scene* Scene;
DrawEntries Geometry;
public: DrawEntries Common;
// Things to draw
Array<Actor*> Geometry;
Array<Actor*> Common;
Array<Actor*> CommonNoCulling; Array<Actor*> CommonNoCulling;
Array<IPostFxSettingsProvider*> PostFxProviders; Array<IPostFxSettingsProvider*> PostFxProviders;
#if USE_EDITOR #if USE_EDITOR
@@ -83,24 +98,36 @@ public:
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) FORCE_INLINE void AddCommonNoCulling(Actor* obj)

View File

@@ -311,6 +311,8 @@ void ParticleEffect::UpdateBounds()
_box = bounds; _box = bounds;
BoundingSphere::FromBox(bounds, _sphere); BoundingSphere::FromBox(bounds, _sphere);
if (_sceneRenderingKey != -1)
GetSceneRendering()->UpdateGeometry(this, _sceneRenderingKey);
} }
void ParticleEffect::Sync() void ParticleEffect::Sync()
@@ -515,6 +517,12 @@ void ParticleEffect::OnDebugDrawSelected()
#endif #endif
void ParticleEffect::OnLayerChanged()
{
if (_sceneRenderingKey != -1)
GetSceneRendering()->UpdateGeometry(this, _sceneRenderingKey);
}
void ParticleEffect::Serialize(SerializeStream& stream, const void* otherObj) void ParticleEffect::Serialize(SerializeStream& stream, const void* otherObj)
{ {
// Base // Base
@@ -691,7 +699,7 @@ void ParticleEffect::EndPlay()
void ParticleEffect::OnEnable() void ParticleEffect::OnEnable()
{ {
GetScene()->Ticking.Update.AddTick<ParticleEffect, &ParticleEffect::Update>(this); GetScene()->Ticking.Update.AddTick<ParticleEffect, &ParticleEffect::Update>(this);
GetSceneRendering()->AddGeometry(this); _sceneRenderingKey = GetSceneRendering()->AddGeometry(this);
#if USE_EDITOR #if USE_EDITOR
GetSceneRendering()->AddViewportIcon(this); GetSceneRendering()->AddViewportIcon(this);
GetScene()->Ticking.Update.AddTickExecuteInEditor<ParticleEffect, &ParticleEffect::UpdateExecuteInEditor>(this); GetScene()->Ticking.Update.AddTickExecuteInEditor<ParticleEffect, &ParticleEffect::UpdateExecuteInEditor>(this);
@@ -707,7 +715,7 @@ void ParticleEffect::OnDisable()
GetScene()->Ticking.Update.RemoveTickExecuteInEditor(this); GetScene()->Ticking.Update.RemoveTickExecuteInEditor(this);
GetSceneRendering()->RemoveViewportIcon(this); GetSceneRendering()->RemoveViewportIcon(this);
#endif #endif
GetSceneRendering()->RemoveGeometry(this); GetSceneRendering()->RemoveGeometry(this, _sceneRenderingKey);
GetScene()->Ticking.Update.RemoveTick(this); GetScene()->Ticking.Update.RemoveTick(this);
// Base // Base

View File

@@ -184,6 +184,7 @@ private:
uint64 _lastUpdateFrame; uint64 _lastUpdateFrame;
float _lastMinDstSqr; float _lastMinDstSqr;
Matrix _world; Matrix _world;
int32 _sceneRenderingKey = -1;
uint32 _parametersVersion = 0; // Version number for _parameters to be in sync with Instance.ParametersVersion uint32 _parametersVersion = 0; // Version number for _parameters to be in sync with Instance.ParametersVersion
Array<ParticleEffectParameter> _parameters; // Cached for scripting API Array<ParticleEffectParameter> _parameters; // Cached for scripting API
Array<ParameterOverride> _parametersOverrides; // Cached parameter modifications to be applied to the parameters Array<ParameterOverride> _parametersOverrides; // Cached parameter modifications to be applied to the parameters
@@ -388,6 +389,7 @@ public:
#if USE_EDITOR #if USE_EDITOR
void OnDebugDrawSelected() override; void OnDebugDrawSelected() override;
#endif #endif
void OnLayerChanged() override;
void Serialize(SerializeStream& stream, const void* otherObj) override; void Serialize(SerializeStream& stream, const void* otherObj) override;
void Deserialize(DeserializeStream& stream, ISerializeModifier* modifier) override; void Deserialize(DeserializeStream& stream, ISerializeModifier* modifier) override;
#if USE_EDITOR #if USE_EDITOR

View File

@@ -47,6 +47,8 @@ void Terrain::UpdateBounds()
BoundingBox::Merge(_box, patch->_bounds, _box); BoundingBox::Merge(_box, patch->_bounds, _box);
} }
BoundingSphere::FromBox(_box, _sphere); BoundingSphere::FromBox(_box, _sphere);
if (_sceneRenderingKey != -1)
GetSceneRendering()->UpdateGeometry(this, _sceneRenderingKey);
} }
void Terrain::CacheNeighbors() void Terrain::CacheNeighbors()
@@ -752,7 +754,7 @@ RigidBody* Terrain::GetAttachedRigidBody() const
void Terrain::OnEnable() void Terrain::OnEnable()
{ {
GetSceneRendering()->AddGeometry(this); _sceneRenderingKey = GetSceneRendering()->AddGeometry(this);
#if TERRAIN_USE_PHYSICS_DEBUG #if TERRAIN_USE_PHYSICS_DEBUG
GetSceneRendering()->AddPhysicsDebug<Terrain, &Terrain::DrawPhysicsDebug>(this); GetSceneRendering()->AddPhysicsDebug<Terrain, &Terrain::DrawPhysicsDebug>(this);
#endif #endif
@@ -763,7 +765,7 @@ void Terrain::OnEnable()
void Terrain::OnDisable() void Terrain::OnDisable()
{ {
GetSceneRendering()->RemoveGeometry(this); GetSceneRendering()->RemoveGeometry(this, _sceneRenderingKey);
#if TERRAIN_USE_PHYSICS_DEBUG #if TERRAIN_USE_PHYSICS_DEBUG
GetSceneRendering()->RemovePhysicsDebug<Terrain, &Terrain::DrawPhysicsDebug>(this); GetSceneRendering()->RemovePhysicsDebug<Terrain, &Terrain::DrawPhysicsDebug>(this);
#endif #endif
@@ -803,6 +805,8 @@ void Terrain::OnLayerChanged()
Actor::OnLayerChanged(); Actor::OnLayerChanged();
UpdateLayerBits(); UpdateLayerBits();
if (_sceneRenderingKey != -1)
GetSceneRendering()->UpdateGeometry(this, _sceneRenderingKey);
} }
void Terrain::OnActiveInTreeChanged() void Terrain::OnActiveInTreeChanged()

View File

@@ -53,6 +53,7 @@ private:
char _collisionLod; char _collisionLod;
byte _lodCount; byte _lodCount;
uint16 _chunkSize; uint16 _chunkSize;
int32 _sceneRenderingKey = -1;
float _scaleInLightmap; float _scaleInLightmap;
float _lodDistribution; float _lodDistribution;
Vector3 _boundsExtent; Vector3 _boundsExtent;
@@ -444,6 +445,7 @@ public:
#if USE_EDITOR #if USE_EDITOR
void OnDebugDrawSelected() override; void OnDebugDrawSelected() override;
#endif #endif
void OnLayerChanged() override;
bool IntersectsItself(const Ray& ray, float& distance, Vector3& normal) override; bool IntersectsItself(const Ray& ray, float& distance, Vector3& normal) override;
void Serialize(SerializeStream& stream, const void* otherObj) override; void Serialize(SerializeStream& stream, const void* otherObj) override;
void Deserialize(DeserializeStream& stream, ISerializeModifier* modifier) override; void Deserialize(DeserializeStream& stream, ISerializeModifier* modifier) override;
@@ -455,7 +457,6 @@ protected:
void OnEnable() override; void OnEnable() override;
void OnDisable() override; void OnDisable() override;
void OnTransformChanged() override; void OnTransformChanged() override;
void OnLayerChanged() override;
void OnActiveInTreeChanged() override; void OnActiveInTreeChanged() override;
void BeginPlay(SceneBeginData* data) override; void BeginPlay(SceneBeginData* data) override;
void EndPlay() override; void EndPlay() override;

View File

@@ -170,6 +170,12 @@ void SpriteRender::Deserialize(DeserializeStream& stream, ISerializeModifier* mo
_paramColor->SetValue(_color); _paramColor->SetValue(_color);
} }
void SpriteRender::OnLayerChanged()
{
if (_sceneRenderingKey != -1)
GetSceneRendering()->UpdateGeometry(this, _sceneRenderingKey);
}
void SpriteRender::OnEndPlay() void SpriteRender::OnEndPlay()
{ {
// Base // Base
@@ -187,7 +193,7 @@ void SpriteRender::OnEndPlay()
void SpriteRender::OnEnable() void SpriteRender::OnEnable()
{ {
GetSceneRendering()->AddGeometry(this); _sceneRenderingKey = GetSceneRendering()->AddGeometry(this);
// Base // Base
Actor::OnEnable(); Actor::OnEnable();
@@ -195,7 +201,7 @@ void SpriteRender::OnEnable()
void SpriteRender::OnDisable() void SpriteRender::OnDisable()
{ {
GetSceneRendering()->RemoveGeometry(this); GetSceneRendering()->RemoveGeometry(this, _sceneRenderingKey);
// Base // Base
Actor::OnDisable(); Actor::OnDisable();
@@ -211,4 +217,6 @@ void SpriteRender::OnTransformChanged()
_transform.GetWorld(world); _transform.GetWorld(world);
BoundingSphere::Transform(localSphere, world, _sphere); BoundingSphere::Transform(localSphere, world, _sphere);
BoundingBox::FromSphere(_sphere, _box); BoundingBox::FromSphere(_sphere, _box);
if (_sceneRenderingKey != -1)
GetSceneRendering()->UpdateGeometry(this, _sceneRenderingKey);
} }

View File

@@ -23,6 +23,7 @@ private:
MaterialParameter* _paramImageMAD = nullptr; MaterialParameter* _paramImageMAD = nullptr;
MaterialParameter* _paramColor = nullptr; MaterialParameter* _paramColor = nullptr;
AssetReference<Asset> _quadModel; AssetReference<Asset> _quadModel;
int32 _sceneRenderingKey = -1;
public: public:
@@ -97,6 +98,7 @@ public:
void DrawGeneric(RenderContext& renderContext) override; void DrawGeneric(RenderContext& renderContext) override;
void Serialize(SerializeStream& stream, const void* otherObj) override; void Serialize(SerializeStream& stream, const void* otherObj) override;
void Deserialize(DeserializeStream& stream, ISerializeModifier* modifier) override; void Deserialize(DeserializeStream& stream, ISerializeModifier* modifier) override;
void OnLayerChanged() override;
void OnEndPlay() override; void OnEndPlay() override;
protected: protected:

View File

@@ -329,6 +329,8 @@ void TextRender::UpdateLayout()
_localBox = box; _localBox = box;
BoundingBox::Transform(_localBox, _world, _box); BoundingBox::Transform(_localBox, _world, _box);
BoundingSphere::FromBox(_box, _sphere); BoundingSphere::FromBox(_box, _sphere);
if (_sceneRenderingKey != -1)
GetSceneRendering()->UpdateGeometry(this, _sceneRenderingKey);
} }
bool TextRender::HasContentLoaded() const bool TextRender::HasContentLoaded() const
@@ -421,6 +423,12 @@ void TextRender::OnDebugDrawSelected()
#endif #endif
void TextRender::OnLayerChanged()
{
if (_sceneRenderingKey != -1)
GetSceneRendering()->UpdateGeometry(this, _sceneRenderingKey);
}
bool TextRender::IntersectsItself(const Ray& ray, float& distance, Vector3& normal) bool TextRender::IntersectsItself(const Ray& ray, float& distance, Vector3& normal)
{ {
#if USE_PRECISE_MESH_INTERSECTS #if USE_PRECISE_MESH_INTERSECTS
@@ -480,8 +488,6 @@ void TextRender::Deserialize(DeserializeStream& stream, ISerializeModifier* modi
void TextRender::OnEnable() void TextRender::OnEnable()
{ {
GetSceneRendering()->AddGeometry(this);
// Base // Base
Actor::OnEnable(); Actor::OnEnable();
@@ -489,6 +495,7 @@ void TextRender::OnEnable()
{ {
UpdateLayout(); UpdateLayout();
} }
_sceneRenderingKey = GetSceneRendering()->AddGeometry(this);
} }
void TextRender::OnDisable() void TextRender::OnDisable()
@@ -498,7 +505,7 @@ void TextRender::OnDisable()
_isLocalized = false; _isLocalized = false;
Localization::LocalizationChanged.Unbind<TextRender, &TextRender::UpdateLayout>(this); Localization::LocalizationChanged.Unbind<TextRender, &TextRender::UpdateLayout>(this);
} }
GetSceneRendering()->RemoveGeometry(this); GetSceneRendering()->RemoveGeometry(this, _sceneRenderingKey);
// Base // Base
Actor::OnDisable(); Actor::OnDisable();
@@ -512,4 +519,6 @@ void TextRender::OnTransformChanged()
_transform.GetWorld(_world); _transform.GetWorld(_world);
BoundingBox::Transform(_localBox, _world, _box); BoundingBox::Transform(_localBox, _world, _box);
BoundingSphere::FromBox(_box, _sphere); BoundingSphere::FromBox(_box, _sphere);
if (_sceneRenderingKey != -1)
GetSceneRendering()->UpdateGeometry(this, _sceneRenderingKey);
} }

View File

@@ -40,6 +40,7 @@ private:
Color _color; Color _color;
TextLayoutOptions _layoutOptions; TextLayoutOptions _layoutOptions;
int32 _size; int32 _size;
int32 _sceneRenderingKey = -1;
BoundingBox _localBox; BoundingBox _localBox;
Matrix _world; Matrix _world;
@@ -169,6 +170,7 @@ public:
#if USE_EDITOR #if USE_EDITOR
void OnDebugDrawSelected() override; void OnDebugDrawSelected() override;
#endif #endif
void OnLayerChanged() override;
bool IntersectsItself(const Ray& ray, float& distance, Vector3& normal) override; bool IntersectsItself(const Ray& ray, float& distance, Vector3& normal) override;
void Serialize(SerializeStream& stream, const void* otherObj) override; void Serialize(SerializeStream& stream, const void* otherObj) override;
void Deserialize(DeserializeStream& stream, ISerializeModifier* modifier) override; void Deserialize(DeserializeStream& stream, ISerializeModifier* modifier) override;