From db696bc49c4a9198abe9670548f90a6123d556b9 Mon Sep 17 00:00:00 2001 From: LaG1924 <12997935+LaG1924@users.noreply.github.com> Date: Sat, 7 Oct 2017 21:38:51 +0500 Subject: 2017-10-07 --- src/Render.cpp | 7 +-- src/RendererWorld.cpp | 129 +++++++++++++++++++++++++++++++++++++++++++++----- src/RendererWorld.hpp | 5 ++ 3 files changed, 126 insertions(+), 15 deletions(-) diff --git a/src/Render.cpp b/src/Render.cpp index c607a2d..0011e1c 100644 --- a/src/Render.cpp +++ b/src/Render.cpp @@ -302,6 +302,7 @@ void Render::RenderGui() { ImGui::Text("TPS: %.1f (%.2fms)", 1000.0f / gameTime, gameTime); ImGui::Text("Sections loaded: %d", (int)DebugInfo::totalSections); ImGui::Text("SectionsRenderer: %d (%d)", (int)DebugInfo::renderSections, (int)DebugInfo::readyRenderer); + ImGui::Text("Culled sections: %d", (int)DebugInfo::renderSections - world->culledSections); ImGui::Text("Player pos: %.1f %.1f %.1f OnGround=%d", world->GameStatePtr()->player->pos.x, world->GameStatePtr()->player->pos.y, world->GameStatePtr()->player->pos.z,world->GameStatePtr()->player->onGround); ImGui::Text("Player vel: %.1f %.1f %.1f", world->GameStatePtr()->player->vel.x, world->GameStatePtr()->player->vel.y, world->GameStatePtr()->player->vel.z); ImGui::Text("Player health: %.1f/%.1f", world->GameStatePtr()->g_PlayerHealth, 20.0f); @@ -432,8 +433,8 @@ void Render::RenderGui() { static float sense = sensetivity; ImGui::SliderFloat("Sensetivity", &sense, 0.01f, 1.0f); - static float frameTime = 16.0f; - ImGui::SliderFloat("Frame time", &frameTime, 0.0f, 32.0f); + static float targetFps = 60.0f; + ImGui::SliderFloat("Target FPS", &targetFps, 1.0f, 300.0f); static bool wireframe = isWireframe; @@ -449,7 +450,7 @@ void Render::RenderGui() { sensetivity = sense; isWireframe = wireframe; - timer.SetDelayLength(std::chrono::duration(frameTime)); + timer.SetDelayLength(std::chrono::duration(1.0/targetFps * 1000.0)); } ImGui::Separator(); diff --git a/src/RendererWorld.cpp b/src/RendererWorld.cpp index 0661b9a..c50ff44 100644 --- a/src/RendererWorld.cpp +++ b/src/RendererWorld.cpp @@ -1,6 +1,107 @@ #include "RendererWorld.hpp" #include "DebugInfo.hpp" +class Frustum { + enum FrustumSide + { + RIGHT = 0, + LEFT, + BOTTOM, + TOP, + BACK, + FRONT, + }; + + enum PlaneData + { + A = 0, + B, + C, + D, + }; + + glm::mat4 vp; + + float frustum[6][4]; + + void NormalizePlane(FrustumSide side) + { + float magnitude = (float)sqrt(frustum[side][A] * frustum[side][A] + + frustum[side][B] * frustum[side][B] + + frustum[side][C] * frustum[side][C]); + + frustum[side][A] /= magnitude; + frustum[side][B] /= magnitude; + frustum[side][C] /= magnitude; + frustum[side][D] /= magnitude; + } + +public: + Frustum() {} + + ~Frustum() {} + + void UpdateFrustum(const glm::mat4& vpmat) { + vp = vpmat; + return; + + float *clip = glm::value_ptr(vp); + + + frustum[RIGHT][A] = clip[3] - clip[0]; + frustum[RIGHT][B] = clip[7] - clip[4]; + frustum[RIGHT][C] = clip[11] - clip[8]; + frustum[RIGHT][D] = clip[15] - clip[12]; + NormalizePlane(RIGHT); + + + frustum[LEFT][A] = clip[3] + clip[0]; + frustum[LEFT][B] = clip[7] + clip[4]; + frustum[LEFT][C] = clip[11] + clip[8]; + frustum[LEFT][D] = clip[15] + clip[12]; + NormalizePlane(LEFT); + + frustum[BOTTOM][A] = clip[3] + clip[1]; + frustum[BOTTOM][B] = clip[7] + clip[5]; + frustum[BOTTOM][C] = clip[11] + clip[9]; + frustum[BOTTOM][D] = clip[15] + clip[13]; + NormalizePlane(BOTTOM); + + frustum[TOP][A] = clip[3] - clip[1]; + frustum[TOP][B] = clip[7] - clip[5]; + frustum[TOP][C] = clip[11] - clip[9]; + frustum[TOP][D] = clip[15] - clip[13]; + NormalizePlane(TOP); + + frustum[BACK][A] = clip[3] - clip[2]; + frustum[BACK][B] = clip[7] - clip[6]; + frustum[BACK][C] = clip[11] - clip[10]; + frustum[BACK][D] = clip[15] - clip[14]; + NormalizePlane(BACK); + + frustum[FRONT][A] = clip[3] + clip[2]; + frustum[FRONT][B] = clip[7] + clip[6]; + frustum[FRONT][C] = clip[11] + clip[10]; + frustum[FRONT][D] = clip[15] + clip[14]; + NormalizePlane(FRONT); + } + + //Return true, if tested point is visible + bool TestPoint(VectorF point) { + glm::vec4 p = vp * glm::vec4(point.glm(), 1); + glm::vec3 res = glm::vec3(p) / p.w; + return (res.x < 1 && res.x > -1 && res.y < 1 && res.y > -1 && res.z > 0); + for (int i = 0; i < 6; i++) + { + if (frustum[i][A] * point.x + frustum[i][B] * point.y + frustum[i][C] * point.z + frustum[i][D] <= 0) + { + return false; + } + } + return true; + } +}; + void RendererWorld::WorkerFunction(size_t workerId) { EventListener tasksListener; @@ -87,6 +188,7 @@ void RendererWorld::UpdateAllSections(VectorF playerPos) } RendererWorld::RendererWorld(std::shared_ptr ptr):gs(ptr) { + frustum = std::make_unique(); MaxRenderingDistance = 2; numOfWorkers = 2; @@ -297,9 +399,12 @@ void RendererWorld::Render(RenderState & renderState) { glUniform2f(windowSizeLoc, renderState.WindowWidth, renderState.WindowHeight); glCheckError(); + frustum->UpdateFrustum(projView); + sectionsMutex.lock(); + size_t culledSections = sections.size(); for (auto& section : sections) { - sectionsMutex.unlock(); + sectionsMutex.unlock(); std::vector sectionCorners = { Vector(0, 0, 0), Vector(0, 0, 16), @@ -310,28 +415,28 @@ void RendererWorld::Render(RenderState & renderState) { Vector(16, 16, 0), Vector(16, 16, 16), }; - bool isBreak = true; - glm::mat4 vp = projection * view; - for (auto &it : sectionCorners) { - glm::vec3 point(section.second.GetPosition().x * 16 + it.x, - section.second.GetPosition().y * 16 + it.y, - section.second.GetPosition().z * 16 + it.z); - glm::vec4 p = vp * glm::vec4(point, 1); - glm::vec3 res = glm::vec3(p) / p.w; - if (res.x < 1 && res.x > -1 && res.y < 1 && res.y > -1 && res.z > 0) { - isBreak = false; + bool isVisible = false; + for (const auto &it : sectionCorners) { + VectorF point(section.second.GetPosition().x * 16 + it.x, + section.second.GetPosition().y * 16 + it.y, + section.second.GetPosition().z * 16 + it.z); + if (frustum->TestPoint(point)) { + isVisible = true; break; } } + double lengthToSection = (gs->player->pos - VectorF(section.first.x*16,section.first.y*16,section.first.z*16)).GetLength(); - if (isBreak && lengthToSection > 30.0f) { + if (!isVisible && lengthToSection > 30.0f) { sectionsMutex.lock(); + culledSections--; continue; } section.second.Render(renderState); sectionsMutex.lock(); } + this->culledSections = culledSections; sectionsMutex.unlock(); glCheckError(); } diff --git a/src/RendererWorld.hpp b/src/RendererWorld.hpp index 751f1a7..b020006 100644 --- a/src/RendererWorld.hpp +++ b/src/RendererWorld.hpp @@ -8,6 +8,8 @@ #include +class Frustum; + class RendererWorld { //General std::shared_ptr gs; @@ -27,6 +29,7 @@ class RendererWorld { std::map sections; Shader *blockShader; void UpdateAllSections(VectorF playerPos); + std::unique_ptr frustum; //Entities Shader *entityShader; std::vector entities; @@ -46,4 +49,6 @@ public: void Update(double timeToUpdate); GameState *GameStatePtr(); + + int culledSections = 0; }; \ No newline at end of file -- cgit v1.2.3