Skip to content

Commit 8ddc040

Browse files
author
Adrien GIVRY
committed
Two level frustum culling implemented (Models and meshes)
1 parent d2bb954 commit 8ddc040

9 files changed

Lines changed: 269 additions & 105 deletions

File tree

Sources/Overload/OvCore/OvCore.vcxproj

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ xcopy "$(SolutionDir)..\..\Build\OvWindowing\bin\$(Configuration)\*.dll" "$(Solu
123123
xcopy "$(SolutionDir)..\..\Build\OvWindowing\lib\$(Configuration)\*.lib" "$(SolutionDir)..\..\Build\$(ProjectName)\lib\$(Configuration)" /e /y /i /r</Command>
124124
</PostBuildEvent>
125125
<Link>
126-
<AdditionalDependencies>liblua53.a;OvMaths.lib;OvPhysics.lib;OvRendering.lib;OvTools.lib;OvUI.lib;OvAudio.lib;OvDebug.lib;OvWindowing.lib;%(AdditionalDependencies)</AdditionalDependencies>
126+
<AdditionalDependencies>liblua53.a;OvMaths.lib;OvPhysics.lib;OvRendering.lib;OvTools.lib;OvUI.lib;OvAudio.lib;OvDebug.lib;OvWindowing.lib;OvAnalytics.lib;%(AdditionalDependencies)</AdditionalDependencies>
127127
</Link>
128128
</ItemDefinitionGroup>
129129
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
@@ -140,7 +140,7 @@ xcopy "$(SolutionDir)..\..\Build\OvWindowing\lib\$(Configuration)\*.lib" "$(Solu
140140
<Link>
141141
<EnableCOMDATFolding>true</EnableCOMDATFolding>
142142
<OptimizeReferences>true</OptimizeReferences>
143-
<AdditionalDependencies>liblua53.a;OvMaths.lib;OvPhysics.lib;OvRendering.lib;OvTools.lib;OvUI.lib;OvAudio.lib;OvDebug.lib;OvWindowing.lib;%(AdditionalDependencies)</AdditionalDependencies>
143+
<AdditionalDependencies>liblua53.a;OvMaths.lib;OvPhysics.lib;OvRendering.lib;OvTools.lib;OvUI.lib;OvAudio.lib;OvDebug.lib;OvWindowing.lib;OvAnalytics.lib;%(AdditionalDependencies)</AdditionalDependencies>
144144
</Link>
145145
<PostBuildEvent>
146146
<Command>RD /S /Q "$(SolutionDir)..\..\Build\$(ProjectName)\include"

Sources/Overload/OvCore/src/OvCore/ECS/Renderer.cpp

Lines changed: 26 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
* @restrictions: This software may not be resold, redistributed or otherwise conveyed to a third party.
55
*/
66

7+
#include <OvAnalytics/Profiling/ProfilerSpy.h>
8+
79
#include <OvRendering/Resources/Loaders/TextureLoader.h>
810
#include <OvRendering/Data/Frustum.h>
911

@@ -70,44 +72,44 @@ void OvCore::ECS::Renderer::FindAndSortDrawables
7072
Resources::Material* p_defaultMaterial
7173
)
7274
{
73-
auto camera = FindMainCamera(p_scene);
74-
7575
for (OvCore::ECS::Components::CModelRenderer* modelRenderer : p_scene.GetFastAccessComponents().modelRenderers)
7676
{
77-
const auto& position = modelRenderer->owner.transform.GetWorldPosition();
78-
const auto& scale = modelRenderer->owner.transform.GetWorldScale();
79-
8077
if (modelRenderer->owner.IsActive())
8178
{
8279
if (auto model = modelRenderer->GetModel())
8380
{
84-
if (!p_frustum || p_frustum->SphereInFrustum(position.x, position.y, position.z, model->GetBoundingSphere().radius * std::max(std::max(std::max(scale.x, scale.y), scale.z), 0.0f)))
81+
float distanceToActor = OvMaths::FVector3::Distance(modelRenderer->owner.transform.GetWorldPosition(), p_cameraPosition);
82+
83+
if (auto materialRenderer = modelRenderer->owner.GetComponent<OvCore::ECS::Components::CMaterialRenderer>())
8584
{
86-
float distanceToActor = OvMaths::FVector3::Distance(modelRenderer->owner.transform.GetWorldPosition(), p_cameraPosition);
85+
const auto& transform = modelRenderer->owner.transform.GetFTransform();
8786

88-
if (auto materialRenderer = modelRenderer->owner.GetComponent<OvCore::ECS::Components::CMaterialRenderer>())
87+
if (!p_frustum || p_frustum->BoundingSphereInFrustum(model->GetBoundingSphere(), transform))
8988
{
9089
const OvCore::ECS::Components::CMaterialRenderer::MaterialList& materials = materialRenderer->GetMaterials();
9190

9291
for (auto mesh : model->GetMeshes())
9392
{
94-
OvCore::Resources::Material* material = nullptr;
95-
96-
if (mesh->GetMaterialIndex() < MAX_MATERIAL_COUNT)
93+
if (!p_frustum || p_frustum->BoundingSphereInFrustum(mesh->GetBoundingSphere(), transform))
9794
{
98-
material = materials.at(mesh->GetMaterialIndex());
99-
if (!material || !material->GetShader())
100-
material = p_defaultMaterial;
101-
}
102-
103-
if (material)
104-
{
105-
Drawable element = { modelRenderer->owner.transform.GetWorldMatrix(), mesh, material, materialRenderer->GetUserMatrix() };
106-
107-
if (material->IsBlendable())
108-
p_transparents.emplace(distanceToActor, element);
109-
else
110-
p_opaques.emplace(distanceToActor, element);
95+
OvCore::Resources::Material* material = nullptr;
96+
97+
if (mesh->GetMaterialIndex() < MAX_MATERIAL_COUNT)
98+
{
99+
material = materials.at(mesh->GetMaterialIndex());
100+
if (!material || !material->GetShader())
101+
material = p_defaultMaterial;
102+
}
103+
104+
if (material)
105+
{
106+
Drawable element = { transform.GetWorldMatrix(), mesh, material, materialRenderer->GetUserMatrix() };
107+
108+
if (material->IsBlendable())
109+
p_transparents.emplace(distanceToActor, element);
110+
else
111+
p_opaques.emplace(distanceToActor, element);
112+
}
111113
}
112114
}
113115
}

Sources/Overload/OvEditor/include/OvEditor/Core/EditorRenderer.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,12 @@ namespace OvEditor::Core
115115
*/
116116
void RenderAmbientSphereVolume(OvCore::ECS::Components::CAmbientSphereLight& p_ambientSphereLight);
117117

118+
/**
119+
* Render the the bounding spheres of the given model renderer
120+
* @param p_modelRenderer
121+
*/
122+
void RenderBoundingSpheres(OvCore::ECS::Components::CModelRenderer& p_modelRenderer, bool p_perMesh = false);
123+
118124
/**
119125
* Render model
120126
*/

Sources/Overload/OvEditor/src/OvEditor/Core/EditorRenderer.cpp

Lines changed: 81 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -159,41 +159,42 @@ void OvEditor::Core::EditorRenderer::RenderSceneForActorPicking(OvRendering::Dat
159159
for (auto modelRenderer : scene.GetFastAccessComponents().modelRenderers)
160160
{
161161
auto& actor = modelRenderer->owner;
162-
const auto& position = actor.transform.GetWorldPosition();
163-
const auto& scale = actor.transform.GetWorldScale();
164162

165163
if (actor.IsActive())
166164
{
167165
if (auto model = modelRenderer->GetModel())
168166
{
169-
if (!p_frustum || p_frustum->SphereInFrustum(position.x, position.y, position.z, model->GetBoundingSphere().radius * std::max(std::max(std::max(scale.x, scale.y), scale.z), 0.0f)))
167+
if (auto materialRenderer = modelRenderer->owner.GetComponent<OvCore::ECS::Components::CMaterialRenderer>())
170168
{
171-
if (auto materialRenderer = modelRenderer->owner.GetComponent<OvCore::ECS::Components::CMaterialRenderer>())
169+
if (!p_frustum || p_frustum->BoundingSphereInFrustum(model->GetBoundingSphere(), actor.transform.GetFTransform()))
172170
{
173171
const OvCore::ECS::Components::CMaterialRenderer::MaterialList& materials = materialRenderer->GetMaterials();
174172
auto modelMatrix = actor.transform.GetWorldMatrix();
175173
PreparePickingMaterial(actor);
176174

177175
for (auto mesh : model->GetMeshes())
178176
{
179-
OvCore::Resources::Material* material = nullptr;
180-
181-
if (mesh->GetMaterialIndex() < MAX_MATERIAL_COUNT)
177+
if (!p_frustum || p_frustum->BoundingSphereInFrustum(mesh->GetBoundingSphere(), actor.transform.GetFTransform()))
182178
{
183-
material = materials.at(mesh->GetMaterialIndex());
184-
if (!material || !material->GetShader())
185-
material = &m_emptyMaterial;
186-
}
187-
188-
if (material)
189-
{
190-
m_actorPickingMaterial.SetBackfaceCulling(material->HasBackfaceCulling());
191-
m_actorPickingMaterial.SetFrontfaceCulling(material->HasFrontfaceCulling());
192-
m_actorPickingMaterial.SetColorWriting(material->HasColorWriting());
193-
m_actorPickingMaterial.SetDepthTest(material->HasDepthTest());
194-
m_actorPickingMaterial.SetDepthWriting(material->HasDepthWriting());
195-
196-
m_context.renderer->DrawMesh(*mesh, m_actorPickingMaterial, &modelMatrix);
179+
OvCore::Resources::Material* material = nullptr;
180+
181+
if (mesh->GetMaterialIndex() < MAX_MATERIAL_COUNT)
182+
{
183+
material = materials.at(mesh->GetMaterialIndex());
184+
if (!material || !material->GetShader())
185+
material = &m_emptyMaterial;
186+
}
187+
188+
if (material)
189+
{
190+
m_actorPickingMaterial.SetBackfaceCulling(material->HasBackfaceCulling());
191+
m_actorPickingMaterial.SetFrontfaceCulling(material->HasFrontfaceCulling());
192+
m_actorPickingMaterial.SetColorWriting(material->HasColorWriting());
193+
m_actorPickingMaterial.SetDepthTest(material->HasDepthTest());
194+
m_actorPickingMaterial.SetDepthWriting(material->HasDepthWriting());
195+
196+
m_context.renderer->DrawMesh(*mesh, m_actorPickingMaterial, &modelMatrix);
197+
}
197198
}
198199
}
199200
}
@@ -294,13 +295,15 @@ void OvEditor::Core::EditorRenderer::RenderActorAsSelected(OvCore::ECS::Actor& p
294295
{
295296
if (p_actor.IsActive())
296297
{
297-
/* Render static mesh outline */
298+
/* Render static mesh outline and bounding spheres */
298299
if (auto modelRenderer = p_actor.GetComponent<OvCore::ECS::Components::CModelRenderer>(); modelRenderer && modelRenderer->GetModel())
299300
{
300301
if (p_toStencil)
301302
RenderModelToStencil(p_actor.transform.GetWorldMatrix(), *modelRenderer->GetModel());
302303
else
303304
RenderModelOutline(p_actor.transform.GetWorldMatrix(), *modelRenderer->GetModel());
305+
306+
RenderBoundingSpheres(*modelRenderer, false);
304307
}
305308

306309
/* Render camera component outline */
@@ -476,6 +479,62 @@ void OvEditor::Core::EditorRenderer::RenderAmbientSphereVolume(OvCore::ECS::Comp
476479
m_context.renderer->SetCapability(OvRendering::Settings::ERenderingCapability::DEPTH_TEST, depthTestBackup);
477480
}
478481

482+
void OvEditor::Core::EditorRenderer::RenderBoundingSpheres(OvCore::ECS::Components::CModelRenderer& p_modelRenderer, bool p_perMesh)
483+
{
484+
using namespace OvCore::ECS::Components;
485+
using namespace OvPhysics::Entities;
486+
487+
bool depthTestBackup = m_context.renderer->GetCapability(OvRendering::Settings::ERenderingCapability::DEPTH_TEST);
488+
m_context.renderer->SetCapability(OvRendering::Settings::ERenderingCapability::DEPTH_TEST, false);
489+
490+
/* Draw the sphere collider if any */
491+
if (auto model = p_modelRenderer.GetModel())
492+
{
493+
auto& actor = p_modelRenderer.owner;
494+
495+
OvMaths::FVector3 actorScale = actor.transform.GetWorldScale();
496+
OvMaths::FQuaternion actorRotation = actor.transform.GetWorldRotation();
497+
OvMaths::FVector3 actorPosition = actor.transform.GetWorldPosition();
498+
499+
if (p_perMesh)
500+
{
501+
for (auto mesh : model->GetMeshes())
502+
{
503+
float radiusScale = std::max(std::max(std::max(actorScale.x, actorScale.y), actorScale.z), 0.0f);
504+
float scaledRadius = mesh->GetBoundingSphere().radius * radiusScale;
505+
auto sphereOffset = OvMaths::FQuaternion::RotatePoint(mesh->GetBoundingSphere().position, actorRotation) * radiusScale;
506+
507+
OvMaths::FVector3 boundingSphereCenter = actorPosition + sphereOffset;
508+
509+
for (float i = 0; i <= 360.0f; i += 10.0f)
510+
{
511+
m_context.shapeDrawer->DrawLine(boundingSphereCenter + actorRotation * (OvMaths::FVector3{ cos(i * (3.14f / 180.0f)), sin(i * (3.14f / 180.0f)), 0.f } *scaledRadius), boundingSphereCenter + actorRotation * (OvMaths::FVector3{ cos((i + 10.0f) * (3.14f / 180.0f)), sin((i + 10.0f) * (3.14f / 180.0f)), 0.f } *scaledRadius), OvMaths::FVector3{ 1.f, 0.f, 0.f }, 1.f);
512+
m_context.shapeDrawer->DrawLine(boundingSphereCenter + actorRotation * (OvMaths::FVector3{ 0.f, sin(i * (3.14f / 180.0f)), cos(i * (3.14f / 180.0f)) } *scaledRadius), boundingSphereCenter + actorRotation * (OvMaths::FVector3{ 0.f, sin((i + 10.0f) * (3.14f / 180.0f)), cos((i + 10.0f) * (3.14f / 180.0f)) } *scaledRadius), OvMaths::FVector3{ 1.f, 0.f, 0.f }, 1.f);
513+
m_context.shapeDrawer->DrawLine(boundingSphereCenter + actorRotation * (OvMaths::FVector3{ cos(i * (3.14f / 180.0f)), 0.f, sin(i * (3.14f / 180.0f)) } *scaledRadius), boundingSphereCenter + actorRotation * (OvMaths::FVector3{ cos((i + 10.0f) * (3.14f / 180.0f)), 0.f, sin((i + 10.0f) * (3.14f / 180.0f)) } *scaledRadius), OvMaths::FVector3{ 1.f, 0.f, 0.f }, 1.f);
514+
}
515+
}
516+
}
517+
else
518+
{
519+
float radiusScale = std::max(std::max(std::max(actorScale.x, actorScale.y), actorScale.z), 0.0f);
520+
float scaledRadius = model->GetBoundingSphere().radius * radiusScale;
521+
auto sphereOffset = OvMaths::FQuaternion::RotatePoint(model->GetBoundingSphere().position, actorRotation) * radiusScale;
522+
523+
OvMaths::FVector3 boundingSphereCenter = actorPosition + sphereOffset;
524+
525+
for (float i = 0; i <= 360.0f; i += 10.0f)
526+
{
527+
m_context.shapeDrawer->DrawLine(boundingSphereCenter + actorRotation * (OvMaths::FVector3{ cos(i * (3.14f / 180.0f)), sin(i * (3.14f / 180.0f)), 0.f } *scaledRadius), boundingSphereCenter + actorRotation * (OvMaths::FVector3{ cos((i + 10.0f) * (3.14f / 180.0f)), sin((i + 10.0f) * (3.14f / 180.0f)), 0.f } *scaledRadius), OvMaths::FVector3{ 1.f, 0.f, 0.f }, 1.f);
528+
m_context.shapeDrawer->DrawLine(boundingSphereCenter + actorRotation * (OvMaths::FVector3{ 0.f, sin(i * (3.14f / 180.0f)), cos(i * (3.14f / 180.0f)) } *scaledRadius), boundingSphereCenter + actorRotation * (OvMaths::FVector3{ 0.f, sin((i + 10.0f) * (3.14f / 180.0f)), cos((i + 10.0f) * (3.14f / 180.0f)) } *scaledRadius), OvMaths::FVector3{ 1.f, 0.f, 0.f }, 1.f);
529+
m_context.shapeDrawer->DrawLine(boundingSphereCenter + actorRotation * (OvMaths::FVector3{ cos(i * (3.14f / 180.0f)), 0.f, sin(i * (3.14f / 180.0f)) } *scaledRadius), boundingSphereCenter + actorRotation * (OvMaths::FVector3{ cos((i + 10.0f) * (3.14f / 180.0f)), 0.f, sin((i + 10.0f) * (3.14f / 180.0f)) } *scaledRadius), OvMaths::FVector3{ 1.f, 0.f, 0.f }, 1.f);
530+
}
531+
}
532+
}
533+
534+
m_context.renderer->SetCapability(OvRendering::Settings::ERenderingCapability::DEPTH_TEST, depthTestBackup);
535+
m_context.renderer->SetRasterizationLinesWidth(1.0f);
536+
}
537+
479538
void OvEditor::Core::EditorRenderer::RenderModelAsset(OvRendering::Resources::Model& p_model)
480539
{
481540
FMatrix4 model = OvMaths::FMatrix4::Scaling({ 3.f, 3.f, 3.f });

Sources/Overload/OvGame/src/OvGame/Core/GameRenderer.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,9 +65,11 @@ void OvGame::Core::GameRenderer::RenderScene()
6565

6666
m_context.renderer->Clear(camera, true, true, false);
6767

68+
bool disableFrustum = m_context.inputManager->GetKeyState(OvWindowing::Inputs::EKey::KEY_C) == OvWindowing::Inputs::EKeyState::KEY_DOWN;
69+
6870
uint8_t glState = m_context.renderer->FetchGLState();
6971
m_context.renderer->ApplyStateMask(glState);
70-
m_context.renderer->RenderScene(*currentScene, cameraPosition, nullptr, &m_emptyMaterial);
72+
m_context.renderer->RenderScene(*currentScene, cameraPosition, disableFrustum ? nullptr : &camera.GetFrustum(), &m_emptyMaterial);
7173
m_context.renderer->ApplyStateMask(glState);
7274
}
7375
else

Sources/Overload/OvRendering/include/OvRendering/Data/Frustum.h

Lines changed: 37 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,10 @@
77
#pragma once
88

99
#include <OvMaths/FMatrix4.h>
10+
#include <OvMaths/FTransform.h>
1011

1112
#include "OvRendering/API/Export.h"
13+
#include "OvRendering/Geometry/BoundingSphere.h"
1214

1315
namespace OvRendering::Data
1416
{
@@ -18,20 +20,46 @@ namespace OvRendering::Data
1820
class API_OVRENDERING Frustum
1921
{
2022
public:
21-
// Call this every time the camera moves to update the frustum
23+
/**
24+
* Update frustum values
25+
* @param p_viewProjection
26+
*/
2227
void CalculateFrustum(const OvMaths::FMatrix4& p_viewProjection);
2328

24-
// This takes a 3D point and returns TRUE if it's inside of the frustum
25-
bool PointInFrustum(float x, float y, float z) const;
29+
/**
30+
* Returns true if the given point is in frustum
31+
* @param p_x
32+
* @param p_y
33+
* @param p_z
34+
*/
35+
bool PointInFrustum(float p_x, float p_y, float p_z) const;
2636

27-
// This takes a 3D point and a radius and returns TRUE if the sphere is inside of the frustum
28-
bool SphereInFrustum(float x, float y, float z, float radius) const;
37+
/**
38+
* Returns true if the given sphere is in frustum
39+
* @param p_x
40+
* @param p_y
41+
* @param p_z
42+
* @param p_radius
43+
*/
44+
bool SphereInFrustum(float p_x, float p_y, float p_z, float p_radius) const;
2945

30-
// This takes the center and half the length of the cube.
31-
bool CubeInFrustum(float x, float y, float z, float size) const;
46+
/**
47+
* Returns true if the given cube is in frustum
48+
* @param p_x
49+
* @param p_y
50+
* @param p_z
51+
* @param p_size
52+
*/
53+
bool CubeInFrustum(float p_x, float p_y, float p_z, float p_size) const;
54+
55+
/**
56+
* Returns true if the given bouding sphere is in frustum
57+
* @param p_boundingSphere
58+
* @param p_transform
59+
*/
60+
bool BoundingSphereInFrustum(const OvRendering::Geometry::BoundingSphere& p_boundingSphere, const OvMaths::FTransform& p_transform) const;
3261

3362
private:
34-
// This holds the A B C and D values for each side of our frustum.
35-
float m_Frustum[6][4];
63+
float m_frustum[6][4];
3664
};
3765
}

0 commit comments

Comments
 (0)