Minor update - frustum rework

Complete overhaul of frustum culling
This commit is contained in:
CatChow0 2025-01-12 00:59:43 +01:00
parent ab0355ed97
commit 01a9c940f0
10 changed files with 201 additions and 77 deletions

View File

@ -17,7 +17,6 @@ ApplicationClass::ApplicationClass() : m_ShouldQuit(false)
m_RenderCountString = 0;
m_ModelList = 0;
m_Position = 0;
m_Frustum = 0;
m_DisplayPlane = 0;
m_BathModel = 0;
m_WaterModel = 0;
@ -382,9 +381,6 @@ bool ApplicationClass::Initialize(int screenWidth, int screenHeight, HWND hwnd)
// Create the position class object.
m_Position = new PositionClass;
// Create the frustum class object.
m_Frustum = new FrustumClass;
// Create and initialize the fps object.
m_Fps = new FpsClass();
@ -472,17 +468,6 @@ void ApplicationClass::Shutdown()
m_Physics = 0;
}
// Release the frustum class object.
if (m_Frustum)
{
Logger::Get().Log("Releasing the frustum class object", __FILE__, __LINE__, Logger::LogLevel::Shutdown);
delete m_Frustum;
m_Frustum = 0;
Logger::Get().Log("Frustum class object released", __FILE__, __LINE__, Logger::LogLevel::Shutdown);
}
// Release the display plane object.
if (m_DisplayPlane)
{
@ -1087,6 +1072,15 @@ bool ApplicationClass::Render(float rotation, float x, float y, float z, float t
return false;
}
// Update the render count text.
result = UpdateRenderCountString(GetRenderCount());
if (!result)
{
Logger::Get().Log("Could not update the render count string", __FILE__, __LINE__, Logger::LogLevel::Error);
return false;
}
// Translate to where the bath model will be rendered.
worldMatrix = XMMatrixTranslation(0.0f, -10.0f, 0.0f);
@ -1164,57 +1158,6 @@ bool ApplicationClass::Render(float rotation, float x, float y, float z, float t
return false;
}
// Construct the frustum.
m_Frustum->ConstructFrustum(viewMatrix, projectionMatrix, SCREEN_DEPTH);
// Get the number of models that will be rendered.
modelCount = m_ModelList->GetModelCount();
// Initialize the count of models that have been rendered.
renderCount = 0;
// Go through all the models and render them only if they can be seen by the camera view.
for (i = 0; i < modelCount; i++)
{
// Get the position and color of the sphere model at this index.
m_ModelList->GetData(i, positionX, positionY, positionZ);
// Set the radius of the sphere to 1.0 since this is already known.
radius = 1.0f;
// Check if the sphere model is in the view frustum.
renderModel = m_Frustum->CheckSphere(positionX, positionY, positionZ, radius);
// If it can be seen then render it, if not skip this model and check the next sphere.
if (renderModel)
{
// Move the model to the location it should be rendered at.
worldMatrix = XMMatrixTranslation(positionX, positionY, positionZ);
// Render the model using the light shader.
m_Model->Render(m_Direct3D->GetDeviceContext());
result = m_ShaderManager->RenderlightShader(m_Direct3D->GetDeviceContext(), m_Model->GetIndexCount(), worldMatrix, viewMatrix, projectionMatrix, m_Model->GetTexture(0),
diffuseColor, lightPosition, ambientColor);
if (!result)
{
Logger::Get().Log("Could not render the model using the light shader", __FILE__, __LINE__, Logger::LogLevel::Error);
return false;
}
// Since this model was rendered then increase the count for this frame.
renderCount++;
}
}
// Update the render count text.
result = UpdateRenderCountString(renderCount);
if (!result)
{
Logger::Get().Log("Could not update the render count string", __FILE__, __LINE__, Logger::LogLevel::Error);
return false;
}
// Disable the Z buffer and enable alpha blending for 2D rendering.
m_Direct3D->TurnZBufferOff();
m_Direct3D->EnableAlphaBlending();
@ -1560,10 +1503,10 @@ void ApplicationClass::AddKobject(WCHAR* filepath)
// Liste des fichiers de texture
std::vector<std::wstring> kobjTexture = {
L"assets/Texture/Bricks2K.png"
L"assets/Texture/Bricks2K.png",
L"assets/Texture/EmptyTexture.png"
};
textures.clear();
for (const auto& textureFilename : kobjTexture)
{
@ -1917,6 +1860,11 @@ bool ApplicationClass::RenderPass(const std::vector<std::reference_wrapper<std::
XMMATRIX worldMatrix, scaleMatrix, rotateMatrix, translateMatrix, srMatrix;
bool result;
int renderCount = 0;
ConstructFrustum();
for (const auto& RenderQueue : RenderQueues)
{
for (auto& object : RenderQueue.get())
@ -1927,6 +1875,21 @@ bool ApplicationClass::RenderPass(const std::vector<std::reference_wrapper<std::
return false;
}
XMVECTOR objposition = object->GetPosition();
float x = XMVectorGetX(objposition);
float y = XMVectorGetY(objposition);
float z = XMVectorGetZ(objposition);
float radius = object->GetBoundingRadius();
// Vérifie si l'objet est dans le frustum
if (!m_FrustumCulling.CheckCube(x, y, z, radius, GetFrustumTolerance()))
{
continue;
}
renderCount++;
scaleMatrix = object->GetScaleMatrix();
rotateMatrix = object->GetRotateMatrix();
translateMatrix = object->GetTranslateMatrix();
@ -1981,5 +1944,16 @@ bool ApplicationClass::RenderPass(const std::vector<std::reference_wrapper<std::
}
}
SetRenderCount(renderCount);
return true;
}
void ApplicationClass::ConstructFrustum()
{
XMMATRIX projectionMatrix = m_Direct3D->GetProjectionMatrix();
XMMATRIX viewMatrix;
m_Camera->GetViewMatrix(viewMatrix);
m_FrustumCulling.ConstructFrustum(SCREEN_DEPTH, projectionMatrix, viewMatrix);
}

View File

@ -29,6 +29,7 @@
#include "translateshaderclass.h"
#include "reflectionshaderclass.h"
#include "physics.h"
#include "frustum.h"
#include <WICTextureLoader.h>
#include <comdef.h> // Pour _com_error
@ -104,6 +105,19 @@ public:
Physics* GetPhysics() const { return m_Physics; };
// ----------------------------------- //
// ------------- Frustum ------------- //
// ----------------------------------- //
Frustum GetFrustum() const { return m_FrustumCulling; };
void SetFrustum(Frustum frustum) { m_FrustumCulling = frustum; };
void ConstructFrustum();
int GetRenderCount() const { return m_renderCount; };
void SetRenderCount(int renderCount) { m_renderCount = renderCount; };
float GetFrustumTolerance() const { return m_FrustumCullingTolerance; };
void SetFrustumTolerance(float frustumTolerance) { m_FrustumCullingTolerance = frustumTolerance; };
private:
bool Render(float, float, float, float, float);
bool RenderPhysics(float x, float y, float z);
@ -115,6 +129,7 @@ private:
bool RenderReflectionToTexture();
bool RenderPass(const std::vector<std::reference_wrapper<std::vector<Object*>>>& RenderQueues, XMFLOAT4* diffuse, XMFLOAT4* position, XMFLOAT4* ambient, XMMATRIX view, XMMATRIX projection);
private :
// ------------------------------------- //
@ -140,7 +155,6 @@ private :
int m_screenWidth, m_screenHeight;
CameraClass* m_Camera;
PositionClass* m_Position;
FrustumClass* m_Frustum;
// ------------------------------------ //
// ------------- OBJECTS -------------- //
@ -204,6 +218,14 @@ private :
Physics* m_Physics;
float m_gravity;
XMVECTOR m_previousPosition;
// ------------------------------------------------- //
// ------------------- Frustum --------------------- //
// ------------------------------------------------- //
Frustum m_FrustumCulling;
int m_renderCount;
float m_FrustumCullingTolerance = 5.f;
};
#endif

View File

@ -26,6 +26,7 @@
<ClCompile Include="CelShadingShader.cpp" />
<ClCompile Include="Colorshaderclass.cpp" />
<ClCompile Include="d3dclass.cpp" />
<ClCompile Include="frustum.cpp" />
<ClCompile Include="imguiManager.cpp" />
<ClCompile Include="include\backends\imgui_impl_dx11.cpp" />
<ClCompile Include="include\backends\imgui_impl_win32.cpp" />
@ -79,6 +80,7 @@
<ClInclude Include="CelShadingShader.h" />
<ClInclude Include="Colorshaderclass.h" />
<ClInclude Include="d3dclass.h" />
<ClInclude Include="frustum.h" />
<ClInclude Include="imguiManager.h" />
<ClInclude Include="include\backends\imgui_impl_dx11.h" />
<ClInclude Include="include\backends\imgui_impl_win32.h" />
@ -304,7 +306,10 @@
<CopyFileToFolders Include="assets\Texture\water01.png">
<DestinationFolders Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(OutDir)\assets\Texture\</DestinationFolders>
</CopyFileToFolders>
<Image Include="assets\Texture\EmptyTexture.png" />
<CopyFileToFolders Include="assets\Texture\EmptyTexture.png">
<DestinationFolders Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(OutDir)\assets\Texture\</DestinationFolders>
<DestinationFolders Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(OutDir)\assets\Texture\</DestinationFolders>
</CopyFileToFolders>
<Image Include="KhaoticIcon.ico" />
<CopyFileToFolders Include="sprite01.tga" />
<CopyFileToFolders Include="sprite02.tga" />

View File

@ -219,6 +219,9 @@
<ClCompile Include="textureclass.cpp">
<Filter>Fichiers sources\System</Filter>
</ClCompile>
<ClCompile Include="frustum.cpp">
<Filter>Fichiers sources\System</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="systemclass.h">
@ -383,14 +386,14 @@
<ClInclude Include="object.h">
<Filter>Fichiers d%27en-tête\System</Filter>
</ClInclude>
<ClInclude Include="frustum.h">
<Filter>Fichiers d%27en-tête\System</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<Image Include="KhaoticIcon.ico">
<Filter>Assets</Filter>
</Image>
<Image Include="assets\Texture\EmptyTexture.png">
<Filter>Assets\Texture</Filter>
</Image>
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
@ -620,5 +623,8 @@
<CopyFileToFolders Include="assets\Model\OBJ\plane.obj">
<Filter>Assets\Model\OBJ</Filter>
</CopyFileToFolders>
<CopyFileToFolders Include="assets\Texture\EmptyTexture.png">
<Filter>Assets\Texture</Filter>
</CopyFileToFolders>
</ItemGroup>
</Project>

88
enginecustom/frustum.cpp Normal file
View File

@ -0,0 +1,88 @@
#include "frustum.h"
void Frustum::ConstructFrustum(float screenDepth, XMMATRIX projectionMatrix, XMMATRIX viewMatrix)
{
XMMATRIX matrix;
XMVECTOR planes[6];
// Calculate the minimum Z distance in the frustum.
float zMinimum = -projectionMatrix.r[3].m128_f32[2] / projectionMatrix.r[2].m128_f32[2];
float r = screenDepth / (screenDepth - zMinimum);
projectionMatrix.r[2].m128_f32[2] = r;
projectionMatrix.r[3].m128_f32[2] = -r * zMinimum;
// Create the frustum matrix from the view matrix and updated projection matrix.
matrix = XMMatrixMultiply(viewMatrix, projectionMatrix);
// Calculate near plane of frustum.
planes[0] = XMPlaneNormalize(XMVectorSet(matrix.r[0].m128_f32[3] + matrix.r[0].m128_f32[2],
matrix.r[1].m128_f32[3] + matrix.r[1].m128_f32[2],
matrix.r[2].m128_f32[3] + matrix.r[2].m128_f32[2],
matrix.r[3].m128_f32[3] + matrix.r[3].m128_f32[2]));
// Calculate far plane of frustum.
planes[1] = XMPlaneNormalize(XMVectorSet(matrix.r[0].m128_f32[3] - matrix.r[0].m128_f32[2],
matrix.r[1].m128_f32[3] - matrix.r[1].m128_f32[2],
matrix.r[2].m128_f32[3] - matrix.r[2].m128_f32[2],
matrix.r[3].m128_f32[3] - matrix.r[3].m128_f32[2]));
// Calculate left plane of frustum.
planes[2] = XMPlaneNormalize(XMVectorSet(matrix.r[0].m128_f32[3] + matrix.r[0].m128_f32[0],
matrix.r[1].m128_f32[3] + matrix.r[1].m128_f32[0],
matrix.r[2].m128_f32[3] + matrix.r[2].m128_f32[0],
matrix.r[3].m128_f32[3] + matrix.r[3].m128_f32[0]));
// Calculate right plane of frustum.
planes[3] = XMPlaneNormalize(XMVectorSet(matrix.r[0].m128_f32[3] - matrix.r[0].m128_f32[0],
matrix.r[1].m128_f32[3] - matrix.r[1].m128_f32[0],
matrix.r[2].m128_f32[3] - matrix.r[2].m128_f32[0],
matrix.r[3].m128_f32[3] - matrix.r[3].m128_f32[0]));
// Calculate top plane of frustum.
planes[4] = XMPlaneNormalize(XMVectorSet(matrix.r[0].m128_f32[3] - matrix.r[0].m128_f32[1],
matrix.r[1].m128_f32[3] - matrix.r[1].m128_f32[1],
matrix.r[2].m128_f32[3] - matrix.r[2].m128_f32[1],
matrix.r[3].m128_f32[3] - matrix.r[3].m128_f32[1]));
// Calculate bottom plane of frustum.
planes[5] = XMPlaneNormalize(XMVectorSet(matrix.r[0].m128_f32[3] + matrix.r[0].m128_f32[1],
matrix.r[1].m128_f32[3] + matrix.r[1].m128_f32[1],
matrix.r[2].m128_f32[3] + matrix.r[2].m128_f32[1],
matrix.r[3].m128_f32[3] + matrix.r[3].m128_f32[1]));
for (int i = 0; i < 6; i++)
{
m_planes[i] = planes[i];
}
}
bool Frustum::CheckCube(float xCenter, float yCenter, float zCenter, float radius, float tolerance)
{
// Vérifiez chaque plan du frustum pour voir si le cube est à l'intérieur
for (int i = 0; i < 6; i++)
{
XMVECTOR plane = m_planes[i];
if (XMVectorGetX(plane) * (xCenter - radius) + XMVectorGetY(plane) * (yCenter - radius) + XMVectorGetZ(plane) * (zCenter - radius) + XMVectorGetW(plane) > -tolerance)
continue;
if (XMVectorGetX(plane) * (xCenter + radius) + XMVectorGetY(plane) * (yCenter - radius) + XMVectorGetZ(plane) * (zCenter - radius) + XMVectorGetW(plane) > -tolerance)
continue;
if (XMVectorGetX(plane) * (xCenter - radius) + XMVectorGetY(plane) * (yCenter + radius) + XMVectorGetZ(plane) * (zCenter - radius) + XMVectorGetW(plane) > -tolerance)
continue;
if (XMVectorGetX(plane) * (xCenter + radius) + XMVectorGetY(plane) * (yCenter + radius) + XMVectorGetZ(plane) * (zCenter - radius) + XMVectorGetW(plane) > -tolerance)
continue;
if (XMVectorGetX(plane) * (xCenter - radius) + XMVectorGetY(plane) * (yCenter - radius) + XMVectorGetZ(plane) * (zCenter + radius) + XMVectorGetW(plane) > -tolerance)
continue;
if (XMVectorGetX(plane) * (xCenter + radius) + XMVectorGetY(plane) * (yCenter - radius) + XMVectorGetZ(plane) * (zCenter + radius) + XMVectorGetW(plane) > -tolerance)
continue;
if (XMVectorGetX(plane) * (xCenter - radius) + XMVectorGetY(plane) * (yCenter + radius) + XMVectorGetZ(plane) * (zCenter + radius) + XMVectorGetW(plane) > -tolerance)
continue;
if (XMVectorGetX(plane) * (xCenter + radius) + XMVectorGetY(plane) * (yCenter + radius) + XMVectorGetZ(plane) * (zCenter + radius) + XMVectorGetW(plane) > -tolerance)
continue;
// Si le cube est en dehors de l'un des plans, il n'est pas dans le frustum
return false;
}
// Si le cube est à l'intérieur de tous les plans, il est dans le frustum
return true;
}

12
enginecustom/frustum.h Normal file
View File

@ -0,0 +1,12 @@
#include <DirectXMath.h>
using namespace DirectX;
class Frustum
{
public:
void ConstructFrustum(float screenDepth, XMMATRIX projectionMatrix, XMMATRIX viewMatrix);
bool CheckCube(float xCenter, float yCenter, float zCenter, float radius, float tolerance);
private:
XMVECTOR m_planes[6];
};

View File

@ -11,7 +11,7 @@ Pos=934,36
Size=457,294
[Window][Terrain]
Pos=60,60
Pos=58,62
Size=342,82
[Window][Light]
@ -23,6 +23,6 @@ Pos=471,90
Size=180,79
[Window][Engine Settings]
Pos=106,213
Size=168,77
Pos=106,212
Size=407,81

View File

@ -435,5 +435,12 @@ void imguiManager::WidgetEngineSettingsWindow(ApplicationClass* app)
app->SetVsync(vsync);
}
// float input for frustum tolerance
float frustumTolerance = app->GetFrustumTolerance();
if (ImGui::DragFloat("Frustum Tolerance", &frustumTolerance, 0.1f, 0.0f, 100.0f))
{
app->SetFrustumTolerance(frustumTolerance);
}
ImGui::End();
}

View File

@ -13,6 +13,7 @@ Object::Object() : ModelClass()
m_mass = NULL;
m_isGrounded = false;
m_id = NULL;
m_boundingRadius = 1.0f;
}
Object::~Object()
@ -233,4 +234,9 @@ bool Object::IsPhysicsEnabled() const
void Object::SetPhysicsEnabled(bool state)
{
m_isPhysicsEnabled = state;
}
}
float Object::GetBoundingRadius() const
{
return m_boundingRadius;
}

View File

@ -70,6 +70,8 @@ public:
ShaderType GetActiveShader() const { return m_activeShader; };
void SetActiveShader(ShaderType activeShader) { m_activeShader = activeShader; };
float GetBoundingRadius() const;
public :
bool m_demoSpinning = false;
XMVECTOR m_previousPosition;
@ -91,4 +93,6 @@ private:
std::string m_name;
ShaderType m_activeShader = LIGHTING;
float m_boundingRadius;
};