]> git.localhorst.tv Git - blank.git/commitdiff
don't render chunk that are outside clip space
authorDaniel Karbach <daniel.karbach@localhorst.tv>
Mon, 9 Mar 2015 16:42:41 +0000 (17:42 +0100)
committerDaniel Karbach <daniel.karbach@localhorst.tv>
Mon, 9 Mar 2015 16:42:41 +0000 (17:42 +0100)
src/chunk.cpp
src/chunk.hpp
src/geometry.cpp
src/geometry.hpp
src/shader.hpp
src/world.cpp

index a485bfbb7d37c61eab4f80c091f1b78659c29b01..514431cbdd636209368d86127cf812d5facfcad7 100644 (file)
@@ -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;
                }
        }
index 185b3eabefd5deb1076b77f36dd8a45950257900..b625a17f7c4518f9d57f89f4bfff818dbe3feab5 100644 (file)
@@ -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() &&
index df48ad3deac2c440f66d89f8fb69e69aac1e9b88..44217e981b49601c68be580eead0385efa6b45e2 100644 (file)
@@ -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;
+}
+
 }
index d74e08e6b6fc8c29a5bc104ce381d6f0632e6289..9a9690b245cd59c0fff0c14baa6c74800120b054 100644 (file)
@@ -32,6 +32,8 @@ bool Intersection(
        float *dist = nullptr,
        glm::vec3 *normal = nullptr);
 
+bool CullTest(const AABB &box, const glm::mat4 &MVP);
+
 }
 
 #endif
index 195376c0ce093ab5bdf13ebe601a688febff4d63..ea5b84474223fab1da9bb8fd18ad1c7e859643c9 100644 (file)
@@ -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;
 
index 216f3a2d007916ae902747d8eee5b4b8b2470108..7f30d71efc1930d9658c5b2633038499c6c62e7b 100644 (file)
@@ -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();
+               }
        }
 }