From 4a21e9e32525fe23915db97f3439cae780994118 Mon Sep 17 00:00:00 2001 From: Daniel Karbach Date: Mon, 9 Mar 2015 17:42:41 +0100 Subject: [PATCH] don't render chunk that are outside clip space --- src/chunk.cpp | 3 +-- src/chunk.hpp | 2 ++ src/geometry.cpp | 38 ++++++++++++++++++++++++++++++++++++++ src/geometry.hpp | 2 ++ src/shader.hpp | 4 ++++ src/world.cpp | 8 ++++++-- 6 files changed, 53 insertions(+), 4 deletions(-) diff --git a/src/chunk.cpp b/src/chunk.cpp index a485bfb..514431c 100644 --- a/src/chunk.cpp +++ b/src/chunk.cpp @@ -43,8 +43,7 @@ bool Chunk::Intersection( float *dist, glm::vec3 *normal) const { { // rough check - const AABB bb{{0, 0, 0}, {Width(), Height(), Depth()}}; - if (!blank::Intersection(ray, bb, M)) { + if (!blank::Intersection(ray, Bounds(), M)) { return false; } } diff --git a/src/chunk.hpp b/src/chunk.hpp index 185b3ea..b625a17 100644 --- a/src/chunk.hpp +++ b/src/chunk.hpp @@ -26,6 +26,8 @@ public: static glm::vec3 Extent() { return glm::vec3(Width(), Height(), Depth()); } static constexpr int Size() { return Width() * Height() * Depth(); } + static AABB Bounds() { return AABB{ { 0, 0, 0 }, { Width(), Height(), Depth() } }; } + static constexpr bool InBounds(const glm::vec3 &pos) { return pos.x >= 0 && pos.x < Width() && diff --git a/src/geometry.cpp b/src/geometry.cpp index df48ad3..44217e9 100644 --- a/src/geometry.cpp +++ b/src/geometry.cpp @@ -126,4 +126,42 @@ bool Intersection( return true; } +bool CullTest(const AABB &box, const glm::mat4 &MVP) { + // transform corners into clip space + glm::vec4 corners[8] = { + { box.min.x, box.min.y, box.min.z, 1.0f }, + { box.min.x, box.min.y, box.max.z, 1.0f }, + { box.min.x, box.max.y, box.min.z, 1.0f }, + { box.min.x, box.max.y, box.max.z, 1.0f }, + { box.max.x, box.min.y, box.min.z, 1.0f }, + { box.max.x, box.min.y, box.max.z, 1.0f }, + { box.max.x, box.max.y, box.min.z, 1.0f }, + { box.max.x, box.max.y, box.max.z, 1.0f }, + }; + for (glm::vec4 &corner : corners) { + corner = MVP * corner; + corner /= corner.w; + } + + int hits[6] = { 0, 0, 0, 0, 0, 0 }; + + // check how many corners lie outside + for (const glm::vec4 &corner : corners) { + if (corner.x > 1.0f) ++hits[0]; + if (corner.x < -1.0f) ++hits[1]; + if (corner.y > 1.0f) ++hits[2]; + if (corner.y < -1.0f) ++hits[3]; + if (corner.z > 1.0f) ++hits[4]; + if (corner.z < -1.0f) ++hits[5]; + } + + // if all corners are outside any given clip plane, the test is true + for (int hit : hits) { + if (hit == 8) return true; + } + + // otherwise the box might still get culled completely, but can't say for sure ;) + return false; +} + } diff --git a/src/geometry.hpp b/src/geometry.hpp index d74e08e..9a9690b 100644 --- a/src/geometry.hpp +++ b/src/geometry.hpp @@ -32,6 +32,8 @@ bool Intersection( float *dist = nullptr, glm::vec3 *normal = nullptr); +bool CullTest(const AABB &box, const glm::mat4 &MVP); + } #endif diff --git a/src/shader.hpp b/src/shader.hpp index 195376c..ea5b844 100644 --- a/src/shader.hpp +++ b/src/shader.hpp @@ -75,6 +75,10 @@ public: void SetVP(const glm::mat4 &v, const glm::mat4 &p); void SetMVP(const glm::mat4 &m, const glm::mat4 &v, const glm::mat4 &p); + const glm::mat4 &Projection() const { return projection; } + const glm::mat4 &View() const { return view; } + const glm::mat4 &GetVP() const { return vp; } + private: Program program; diff --git a/src/world.cpp b/src/world.cpp index 216f3a2..7f30d71 100644 --- a/src/world.cpp +++ b/src/world.cpp @@ -163,8 +163,12 @@ void World::Render(DirectionalLighting &program) { program.SetView(glm::inverse(player.Transform(player.ChunkCoords()))); for (Chunk &chunk : LoadedChunks()) { - program.SetM(chunk.Transform(player.ChunkCoords())); - chunk.Draw(); + glm::mat4 m(chunk.Transform(player.ChunkCoords())); + program.SetM(m); + glm::mat4 mvp(program.GetVP() * m); + if (!CullTest(Chunk::Bounds(), mvp)) { + chunk.Draw(); + } } } -- 2.39.2