Frustum culling progress

Unlit materials
Renderer cleanup
This commit is contained in:
Antoine Pilote
2021-07-14 22:10:05 -04:00
parent 2b88ee09e3
commit 8ecab5c3ad
16 changed files with 394 additions and 32 deletions

View File

@@ -111,6 +111,7 @@ layout(std140, binding = 32) uniform u_MaterialUniform
float u_AOValue; // 52 byte
int u_HasNormal; // 56 byte
int u_HasDisplacement; // 60 byte
int u_Unlit;
};
float height_scale = 0.00f;
@@ -338,7 +339,6 @@ void main()
finalNormal = finalNormal * 2.0 - 1.0;
finalNormal = v_TBN * normalize(finalNormal);
vec3 N = normalize(finalNormal);
vec3 V = normalize(u_EyePosition - v_FragPos);
vec3 R = reflect(-V, N);
@@ -351,6 +351,12 @@ void main()
float shadow = 0.0f;
vec3 Lo = vec3(0.0);
if (u_Unlit == 1)
{
FragColor = vec4(finalAlbedo, 1.0);
return;
}
for (int i = 0; i < LightCount; i++)
{
vec3 L = normalize(Lights[i].Position - v_FragPos);

View File

@@ -972,6 +972,10 @@ namespace Nuake {
{
if (m_IsMaterialSelected)
{
ImGui::Text("Flags");
bool unlit = m_SelectedMaterial->data.u_Unlit == 1;
ImGui::Checkbox("Unlit", &unlit);
m_SelectedMaterial->data.u_Unlit = (int)unlit;
if (ImGui::CollapsingHeader("Albedo", ImGuiTreeNodeFlags_DefaultOpen))
{
unsigned int textureID = 0;
@@ -982,7 +986,10 @@ namespace Nuake {
std::string texture = FileDialog::OpenFile("*.png | *.jpg");
}
ImGui::SameLine();
//ImGui::Checkbox("Use##1", &(bool)(m_SelectedMaterial->data.u_HasAlbedo));
bool isAlbedo = m_SelectedMaterial->data.u_HasAlbedo == 1;
ImGui::Checkbox("Use##1", &isAlbedo);
m_SelectedMaterial->data.u_HasAlbedo = (int)isAlbedo;
ImGui::SameLine();
ImGui::ColorPicker3("Color", &m_SelectedMaterial->data.m_AlbedoColor.r);
}
@@ -1000,7 +1007,10 @@ namespace Nuake {
}
}
ImGui::SameLine();
//ImGui::Checkbox("Use##2", &m_SelectedMaterial->data.u_HasAO);
bool hasAO = m_SelectedMaterial->data.u_HasAO == 1;
ImGui::Checkbox("Use##1", &hasAO);
m_SelectedMaterial->data.u_HasAO = (int)hasAO;
ImGui::SameLine();
ImGui::DragFloat("Value##2", &m_SelectedMaterial->data.u_AOValue, 0.01f, 0.0f, 1.0f);
}

View File

@@ -50,13 +50,22 @@ namespace Nuake
MeshShape::MeshShape(Ref<Mesh> mesh)
{
m_Mesh = mesh;
btConvexHullShape* trimesh = new btConvexHullShape();
btTriangleMesh* trimesh = new btTriangleMesh();
for (Vertex i : mesh->m_Vertices)
for (unsigned int i = 0; i < mesh->m_Indices.size(); i += 3)
{
trimesh->addPoint(btVector3(i.position.x, i.position.y, i.position.z));
Vector3 tri1 = mesh->m_Vertices[mesh->m_Indices[i]].position;
Vector3 tri2 = mesh->m_Vertices[mesh->m_Indices[i + 1]].position;
Vector3 tri3 = mesh->m_Vertices[mesh->m_Indices[i + 2]].position;
btVector3 btri1 = btVector3(tri1.x, tri1.y, tri1.z);
btVector3 btri2 = btVector3(tri2.x, tri2.y, tri2.z);
btVector3 btri3 = btVector3(tri3.x, tri3.y, tri3.z);
trimesh->addTriangle(btri1, btri2, btri3, false);
}
bShape = trimesh;
bShape = new btBvhTriangleMeshShape(trimesh, false, true);;
}
btCollisionShape* MeshShape::GetBulletShape()

View File

@@ -28,6 +28,12 @@ namespace Nuake
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
}
FrameBuffer::~FrameBuffer()
{
glDeleteFramebuffers(1, &m_FramebufferID);
glDeleteRenderbuffers(1, &m_RenderBuffer);
}
void FrameBuffer::SetTexture(Ref<Texture> texture, GLenum attachment)
{
m_Textures[attachment] = texture;

View File

@@ -22,7 +22,7 @@ namespace Nuake
public:
FrameBuffer(bool hasRenderBuffer, Vector2 size);
~FrameBuffer() { }
~FrameBuffer();
// 0x8CE0 = color attachment 0.
// TODO: Remove blackbox crap

View File

@@ -2,6 +2,7 @@
#include "src/Core/Timestep.h"
#include "src/Core/Maths.h"
#include "src/Resource/Serializable.h"
#include "Frustum.h"
namespace Nuake
{
@@ -13,18 +14,18 @@ namespace Nuake
class EditorCamera;
// TODO: Remove logic from here.
class Camera : public ISerializable
{
private:
CAMERA_TYPE m_Type;
Vector3 Rotation = { 0.0f, 0.0f, 0.0f };
Vector3 Scale = { 1.0f, 1.0f, 1.0f };
Matrix4 m_Perspective;
public:
Frustum m_Frustum;
float AspectRatio = 16.0f / 9.0f;
// TODO: remove duplicate direction and have a proper api.
Vector3 up = Vector3(0.0f, 1.0f, 0.0f);

View File

@@ -0,0 +1,121 @@
#pragma once
#include "src/Core/Maths.h"
#include <glm/matrix.hpp>
namespace Nuake {
class Frustum
{
public:
Frustum() {}
// m = ProjectionMatrix * ViewMatrix
Frustum(Matrix4 m);
// http://iquilezles.org/www/articles/frustumcorrect/frustumcorrect.htm
bool IsBoxVisible(const Vector3& minp, const Vector3& maxp) const;
private:
enum Planes
{
Left = 0,
Right,
Bottom,
Top,
Near,
Far,
Count,
Combinations = Count * (Count - 1) / 2
};
template<Planes i, Planes j>
struct ij2k
{
enum { k = i * (9 - i) / 2 + j - 1 };
};
template<Planes a, Planes b, Planes c>
Vector3 intersection(const Vector3* crosses) const;
Vector4 m_planes[Count];
Vector3 m_points[8];
};
inline Frustum::Frustum(Matrix4 m)
{
m = glm::transpose(m);
m_planes[Left] = m[3] + m[0];
m_planes[Right] = m[3] - m[0];
m_planes[Bottom] = m[3] + m[1];
m_planes[Top] = m[3] - m[1];
m_planes[Near] = m[3] + m[2];
m_planes[Far] = m[3] - m[2];
Vector3 crosses[Combinations] = {
glm::cross(Vector3(m_planes[Left]), Vector3(m_planes[Right])),
glm::cross(Vector3(m_planes[Left]), Vector3(m_planes[Bottom])),
glm::cross(Vector3(m_planes[Left]), Vector3(m_planes[Top])),
glm::cross(Vector3(m_planes[Left]), Vector3(m_planes[Near])),
glm::cross(Vector3(m_planes[Left]), Vector3(m_planes[Far])),
glm::cross(Vector3(m_planes[Right]), Vector3(m_planes[Bottom])),
glm::cross(Vector3(m_planes[Right]), Vector3(m_planes[Top])),
glm::cross(Vector3(m_planes[Right]), Vector3(m_planes[Near])),
glm::cross(Vector3(m_planes[Right]), Vector3(m_planes[Far])),
glm::cross(Vector3(m_planes[Bottom]), Vector3(m_planes[Top])),
glm::cross(Vector3(m_planes[Bottom]), Vector3(m_planes[Near])),
glm::cross(Vector3(m_planes[Bottom]), Vector3(m_planes[Far])),
glm::cross(Vector3(m_planes[Top]), Vector3(m_planes[Near])),
glm::cross(Vector3(m_planes[Top]), Vector3(m_planes[Far])),
glm::cross(Vector3(m_planes[Near]), Vector3(m_planes[Far]))
};
m_points[0] = intersection<Left, Bottom, Near>(crosses);
m_points[1] = intersection<Left, Top, Near>(crosses);
m_points[2] = intersection<Right, Bottom, Near>(crosses);
m_points[3] = intersection<Right, Top, Near>(crosses);
m_points[4] = intersection<Left, Bottom, Far>(crosses);
m_points[5] = intersection<Left, Top, Far>(crosses);
m_points[6] = intersection<Right, Bottom, Far>(crosses);
m_points[7] = intersection<Right, Top, Far>(crosses);
}
// http://iquilezles.org/www/articles/frustumcorrect/frustumcorrect.htm
inline bool Frustum::IsBoxVisible(const Vector3& minp, const Vector3& maxp) const
{
// check box outside/inside of frustum
for (int i = 0; i < Count; i++)
{
if ((glm::dot(m_planes[i], Vector4(minp.x, minp.y, minp.z, 1.0f)) < 0.0) &&
(glm::dot(m_planes[i], Vector4(maxp.x, minp.y, minp.z, 1.0f)) < 0.0) &&
(glm::dot(m_planes[i], Vector4(minp.x, maxp.y, minp.z, 1.0f)) < 0.0) &&
(glm::dot(m_planes[i], Vector4(maxp.x, maxp.y, minp.z, 1.0f)) < 0.0) &&
(glm::dot(m_planes[i], Vector4(minp.x, minp.y, maxp.z, 1.0f)) < 0.0) &&
(glm::dot(m_planes[i], Vector4(maxp.x, minp.y, maxp.z, 1.0f)) < 0.0) &&
(glm::dot(m_planes[i], Vector4(minp.x, maxp.y, maxp.z, 1.0f)) < 0.0) &&
(glm::dot(m_planes[i], Vector4(maxp.x, maxp.y, maxp.z, 1.0f)) < 0.0))
{
return false;
}
}
// check frustum outside/inside box
int out;
out = 0; for (int i = 0; i < 8; i++) out += ((m_points[i].x > maxp.x) ? 1 : 0); if (out == 8) return false;
out = 0; for (int i = 0; i < 8; i++) out += ((m_points[i].x < minp.x) ? 1 : 0); if (out == 8) return false;
out = 0; for (int i = 0; i < 8; i++) out += ((m_points[i].y > maxp.y) ? 1 : 0); if (out == 8) return false;
out = 0; for (int i = 0; i < 8; i++) out += ((m_points[i].y < minp.y) ? 1 : 0); if (out == 8) return false;
out = 0; for (int i = 0; i < 8; i++) out += ((m_points[i].z > maxp.z) ? 1 : 0); if (out == 8) return false;
out = 0; for (int i = 0; i < 8; i++) out += ((m_points[i].z < minp.z) ? 1 : 0); if (out == 8) return false;
return true;
}
template<Frustum::Planes a, Frustum::Planes b, Frustum::Planes c>
inline Vector3 Frustum::intersection(const Vector3* crosses) const
{
float D = glm::dot(glm::vec3(m_planes[a]), crosses[ij2k<b, c>::k]);
Vector3 res = glm::mat3(crosses[ij2k<b, c>::k], -crosses[ij2k<a, c>::k], crosses[ij2k<a, b>::k]) *
Vector3(m_planes[a].w, m_planes[b].w, m_planes[c].w);
return res * (-1.0f / D);
}
}

View File

@@ -0,0 +1,130 @@
#include "Light.h"
#include <src/Vendors/glm/ext/matrix_clip_space.hpp>
#include "src/Rendering/RenderCommand.h"
#include <dependencies/GLEW/include/GL/glew.h>
namespace Nuake
{
DirectionalLight::DirectionalLight()
{
for (int i = 0; i < CSM_SPLIT_AMOUNT; i++)
{
Ref<FrameBuffer> shadowmap = CreateRef<FrameBuffer>(false, glm::vec2(4096, 4096));
Ref<Texture> texture = CreateRef<Texture>(glm::vec2(4096, 4096), GL_DEPTH_COMPONENT);
shadowmap->SetTexture(texture, GL_DEPTH_ATTACHMENT);
m_ShadowMaps[i] = shadowmap;
}
}
DirectionalLight::~DirectionalLight()
{
for (int i = 0; i < CSM_SPLIT_AMOUNT; i++)
{
}
}
void DirectionalLight::CSMViewCalculation(const Matrix4& camView, const Matrix4& camProjection)
{
Matrix4 viewProjection = camProjection * camView;
Matrix4 inverseViewProjection = glm::inverse(viewProjection);
// Calculate the optimal cascade distances
const float range = CSM_FAR_CLIP - CSM_NEAR_CLIP;
const float ratio = CSM_FAR_CLIP / CSM_NEAR_CLIP;
for (int i = 0; i < CSM_SPLIT_AMOUNT; i++)
{
const float p = (i + 1) / static_cast<float>(4);
const float log = CSM_NEAR_CLIP * glm::pow(ratio, p);
const float uniform = CSM_NEAR_CLIP + range * p;
const float d = 0.91f * (log - uniform) + uniform;
m_CascadeSplits[i] = (d - CSM_NEAR_CLIP) / CSM_CLIP_RANGE;
}
//mCascadeSplits[0] = 0.2f;
//mCascadeSplits[1] = 0.45f;
//mCascadeSplits[2] = 1.0f;
float lastSplitDist = 0.0f;
// Calculate Orthographic Projection matrix for each cascade
for (int cascade = 0; cascade < CSM_SPLIT_AMOUNT; cascade++)
{
float splitDist = m_CascadeSplits[cascade];
Vector4 frustumCorners[8] =
{
//Near face
{ 1.0f, 1.0f, -1.0f, 1.0f },
{ -1.0f, 1.0f, -1.0f, 1.0f },
{ 1.0f, -1.0f, -1.0f, 1.0f },
{ -1.0f, -1.0f, -1.0f, 1.0f },
//Far face
{ 1.0f, 1.0f, 1.0f, 1.0f },
{ -1.0f, 1.0f, 1.0f, 1.0f },
{ 1.0f, -1.0f, 1.0f, 1.0f },
{ -1.0f, -1.0f, 1.0f, 1.0f },
};
// Project frustum corners into world space from clip space
for (int i = 0; i < 8; i++)
{
Vector4 invCorner = inverseViewProjection * frustumCorners[i];
frustumCorners[i] = invCorner / invCorner.w;
}
for (int i = 0; i < CSM_SPLIT_AMOUNT; i++)
{
Vector4 dist = frustumCorners[i + 4] - frustumCorners[i];
frustumCorners[i + 4] = frustumCorners[i] + (dist * splitDist);
frustumCorners[i] = frustumCorners[i] + (dist * lastSplitDist);
}
// Get frustum center
Vector3 frustumCenter = Vector3(0.0f);
for (int i = 0; i < 8; i++)
frustumCenter += Vector3(frustumCorners[i]);
frustumCenter /= 8.0f;
// Get the minimum and maximum extents
float radius = 0.0f;
for (int i = 0; i < 8; i++)
{
float distance = glm::length(glm::vec3(frustumCorners[i]) - frustumCenter);
radius = glm::max(radius, distance);
}
radius = std::ceil(radius * 16.0f) / 16.0f;
Vector3 maxExtents = glm::vec3(radius);
Vector3 minExtents = -maxExtents;
// Calculate the view and projection matrix
Vector3 lightDir = -this->Direction;
Matrix4 lightViewMatrix = glm::lookAt(frustumCenter - lightDir * -minExtents.z, frustumCenter, glm::vec3(0.0f, 0.0f, 1.0f));
Matrix4 lightProjectionMatrix = glm::ortho(minExtents.x, maxExtents.x, minExtents.y, maxExtents.y, 0.0f + mCascadeNearPlaneOffset, maxExtents.z - minExtents.z + mCascadeFarPlaneOffset);
// Offset to texel space to avoid shimmering ->(https://stackoverflow.com/questions/33499053/cascaded-shadow-map-shimmering)
Matrix4 shadowMatrix = lightProjectionMatrix * lightViewMatrix;
const float ShadowMapResolution = 4096;
Vector4 shadowOrigin = (shadowMatrix * Vector4(0.0f, 0.0f, 0.0f, 1.0f)) * ShadowMapResolution / 2.0f;
Vector4 roundedOrigin = glm::round(shadowOrigin);
Vector4 roundOffset = roundedOrigin - shadowOrigin;
roundOffset = roundOffset * 2.0f / ShadowMapResolution;
roundOffset.z = 0.0f;
roundOffset.w = 0.0f;
lightProjectionMatrix[3] += roundOffset;
// Store SplitDistance and ViewProjection-Matrix
m_CascadeSplitDepths[cascade] = (CSM_NEAR_CLIP + splitDist * CSM_FAR_CLIP) * 1.0f;
m_CascadeViewProjections[cascade] = lightProjectionMatrix * lightViewMatrix;
lastSplitDist = m_CascadeSplits[cascade];
// -----------------------Debug only-----------------------
// RendererDebug::BeginScene(viewProjection);
// RendererDebug::SubmitCameraFrustum(frustumCorners, glm::mat4(1.0f), GetColor(cascade)); // Draws the divided camera frustums
// RendererDebug::SubmitLine(glm::vec3(0.0f, 0.0f, 0.0f), frustumCenter, GetColor(cascade)); // Draws the center of the frustum (A line pointing from origin to the center)
// RendererDebug::EndScene();
}
}
}

View File

@@ -0,0 +1,79 @@
#pragma once
#include "src/Core/Maths.h"
#include "src/Rendering/Buffers/Framebuffer.h"
namespace Nuake {
enum LightType
{
Point, Directional, Spot, Area
};
class Light
{
public:
LightType Type = Point;
bool Enabled;
Color LightColor = Color(1.0f, 1.0f, 1.0f, 1.0f);
float Intensity = 1.0f;
bool CastShadows;
};
class PointLight : public Light
{
public:
private:
};
class DirectionalLight : public Light
{
public:
DirectionalLight();
~DirectionalLight();
Vector3 Direction;
void CSMViewCalculation(const Matrix4& camView, const Matrix4& camProjection);
inline float GetCascadeSplitDepth(const int i) { return m_CascadeSplitDepths[i]; }
inline float GetCascadeSplit(const int i) { return m_CascadeSplits[i]; }
inline Matrix4 GetCascadeViewProjection(const int i) { return m_CascadeViewProjections[i]; }
private:
static const int CSM_SPLIT_AMOUNT = 4;
const float CSM_NEAR_CLIP = 0.01f;
const float CSM_FAR_CLIP = 1000.0f;
const float CSM_CLIP_RANGE = CSM_FAR_CLIP - CSM_NEAR_CLIP;
const float mCascadeNearPlaneOffset = 0.0;
const float mCascadeFarPlaneOffset = 0.0;
float m_CascadeSplits[CSM_SPLIT_AMOUNT];
float m_CascadeSplitDepths[CSM_SPLIT_AMOUNT];
Matrix4 m_CascadeViewProjections[CSM_SPLIT_AMOUNT];
Ref<FrameBuffer> m_ShadowMaps[CSM_SPLIT_AMOUNT];
};
class SpotLight : public Light
{
public:
Matrix4 Projection;
Vector3 Direction;
float InnerRadius;
float OuterRadius;
private:
};
class AreaLight : public Light
{
public:
Matrix4 Projection;
Vector3 Direction;
float FOV;
float Height;
float Width;
private:
};
}

View File

@@ -7,7 +7,8 @@ namespace Nuake {
FLOAT, UFLOAT,
ARRAY_BUFFER,
ELEMENT_ARRAY_BUFFER,
TRIANGLES
TRIANGLES,
DEPTH_ATTACHMENT, COLOR_ATTACHMENT0, COLOR_ATTACHMENT1
};
class RendererAPI

View File

@@ -21,6 +21,7 @@ namespace Nuake
float u_AOValue;
int u_HasNormal;
int u_HasDisplacement;
int u_Unlit;
};
class Material
@@ -50,7 +51,8 @@ namespace Nuake
0, // u_HasAO
0.5f, // u_AOValue
0, // u_HasNormal
0 // u_HasDisplacement
0, // u_HasDisplacement
0
};
static Ref<Texture> m_DefaultAlbedo;
@@ -73,6 +75,9 @@ namespace Nuake
void SetName(const std::string name);
std::string GetName();
inline void SetUnlit(bool value) {data.u_Unlit = value; }
inline bool GetUnlit() { return data.u_Unlit == 1; }
bool HasAlbedo() { return m_Albedo != nullptr; }
void SetAlbedo(const std::string path) { m_Albedo = CreateRef<Texture>(path); }
void SetAlbedo(Ref<Texture> texture) { m_Albedo = texture; }

View File

@@ -26,7 +26,6 @@ namespace Nuake {
// m_Framebuffers[i] = CreateRef<FrameBuffer>(false, glm::vec2(4096, 4096));
// m_Framebuffers[i]->SetTexture(CreateRef<Texture>(glm::vec2(4096, 4096), GL_DEPTH_COMPONENT), GL_DEPTH_ATTACHMENT);
//}
}
void LightComponent::SetCastShadows(bool toggle)
@@ -94,11 +93,6 @@ namespace Nuake {
Renderer::m_ShadowmapShader->Bind();
}
void LightComponent::Draw(TransformComponent transformComponent, Ref<Camera> cam)
{
}
void LightComponent::DrawDeferred(TransformComponent transformComponent, Camera* cam)
{
Renderer::RegisterDeferredLight(transformComponent, *this, cam);

View File

@@ -29,9 +29,6 @@ namespace Nuake
Ref<FrameBuffer> m_Framebuffer;
bool CastShadows = false;
float Attenuation = 0.0f;
float LinearAttenuation = 0.0f;
float QuadraticAttenuation = 0.0f;
Ref<FrameBuffer> m_Framebuffers[CSM_AMOUNT];
glm::mat4 mViewProjections[CSM_AMOUNT];

View File

@@ -289,7 +289,6 @@ namespace Nuake {
Renderer::m_SkyboxShader->SetUniform1i("equirectangularMap", 6);
Renderer::m_SkyboxShader->SetUniform1i("skybox", 5);
glBindFramebuffer(GL_FRAMEBUFFER, captureFBO);
unsigned int maxMipLevels = 5;
for (unsigned int mip = 0; mip < maxMipLevels; ++mip)

View File

@@ -364,7 +364,6 @@ namespace Nuake {
flatShader->Bind();
flatShader->SetUniformMat4f("u_View", m_EditorCamera->GetTransform());
flatShader->SetUniformMat4f("u_Projection", m_EditorCamera->GetPerspective());
auto boxCollider = m_Registry.view<TransformComponent, BoxColliderComponent, ParentComponent>();
for (auto e : boxCollider)
{
@@ -486,7 +485,6 @@ namespace Nuake {
m_Registry.shrink_to_fit();
}
// Getter
Ref<Camera> Scene::GetCurrentCamera()
{
if (Engine::IsPlayMode)
@@ -494,7 +492,8 @@ namespace Nuake {
Ref<Camera> cam = nullptr;
{
auto view = m_Registry.view<TransformComponent, CameraComponent>();
for (auto e : view) {
for (auto e : view)
{
auto [transform, camera] = view.get<TransformComponent, CameraComponent>(e);
cam = camera.CameraInstance;
break;
@@ -508,7 +507,8 @@ namespace Nuake {
return m_EditorCamera;
}
Ref<Environment> Scene::GetEnvironment() {
Ref<Environment> Scene::GetEnvironment()
{
return m_Environement;
}
@@ -531,7 +531,6 @@ namespace Nuake {
return true;
}
void Scene::ReloadInterfaces()
{
for (auto& i : m_Interfaces)

View File

@@ -75,7 +75,8 @@ namespace Nuake
}
auto bspTriggerView = m_Scene->m_Registry.view<TransformComponent, BSPBrushComponent, TriggerZone>();
for (auto e : bspTriggerView) {
for (auto e : bspTriggerView)
{
auto [transform, brush, trigger] = bspTriggerView.get<TransformComponent, BSPBrushComponent, TriggerZone>(e);
Ref<Physics::MeshShape> meshShape = CreateRef<Physics::MeshShape>(brush.Meshes[0]);
@@ -105,10 +106,12 @@ namespace Nuake
brush.Targets.clear();
auto targetnameView = m_Scene->m_Registry.view<TransformComponent, NameComponent>();
for (auto e2 : targetnameView) {
for (auto e2 : targetnameView)
{
auto [ttransform, name] = targetnameView.get<TransformComponent, NameComponent>(e2);
if (name.Name == brush.target) {
if (name.Name == brush.target)
{
brush.Targets.push_back(Entity{ e2, m_Scene });
}
}
@@ -116,13 +119,15 @@ namespace Nuake
auto bspTriggerView = m_Scene->m_Registry.view<TransformComponent, BSPBrushComponent, TriggerZone>();
for (auto e : bspTriggerView) {
for (auto e : bspTriggerView)
{
auto [transform, brush, trigger] = bspTriggerView.get<TransformComponent, BSPBrushComponent, TriggerZone>(e);
trigger.GhostObject->ScanOverlap();
brush.Targets.clear();
auto targetnameView = m_Scene->m_Registry.view<TransformComponent, NameComponent>();
for (auto e2 : targetnameView) {
for (auto e2 : targetnameView)
{
auto [ttransform, name] = targetnameView.get<TransformComponent, NameComponent>(e2);
if (name.Name == brush.target) {