From c547d11cd595d4e4261b7adf44bdb93fd1716af2 Mon Sep 17 00:00:00 2001 From: EmaMaker Date: Sun, 12 Feb 2023 14:36:59 +0100 Subject: [PATCH] chunks: drop per-chunk chunkmesh Use a single mesher. This, on top of the previous commits, shaves off another 20MB of total RAM usage, using a total of about 120MB for a standard world (16 chunk size, 8 render distance), of which 22 in heap --- include/chunk.hpp | 3 ++ include/chunkmesh.hpp | 38 ---------------- include/chunkmesher.hpp | 20 +++++++++ src/CMakeLists.txt | 2 +- src/chunk.cpp | 11 +++++ src/chunkmanager.cpp | 21 ++++----- src/{chunkmesh.cpp => chunkmesher.cpp} | 60 +++++++++----------------- 7 files changed, 66 insertions(+), 89 deletions(-) delete mode 100644 include/chunkmesh.hpp create mode 100644 include/chunkmesher.hpp rename src/{chunkmesh.cpp => chunkmesher.cpp} (88%) diff --git a/include/chunk.hpp b/include/chunk.hpp index 69966cf..d6de175 100644 --- a/include/chunk.hpp +++ b/include/chunk.hpp @@ -46,6 +46,9 @@ namespace Chunk IntervalMap& getBlocks() { return (this->blocks); } Block* getBlocksArray(int* len) { return (this->blocks.toArray(len)); } + public: + GLuint VAO{0}, VBO{0}, EBO{0}, colorBuffer{0}, vIndex{0}; + private: glm::vec3 position{}; IntervalMap blocks{}; diff --git a/include/chunkmesh.hpp b/include/chunkmesh.hpp deleted file mode 100644 index cc89fe1..0000000 --- a/include/chunkmesh.hpp +++ /dev/null @@ -1,38 +0,0 @@ -#ifndef CHUNKMESH_H -#define CHUNKMESH_H - -#include -#include - -#include - -#include "chunk.hpp" -#include "globals.hpp" -#include "shader.hpp" -#include - -class ChunkMesh -{ - -public: - ChunkMesh(Chunk::Chunk *c); - ~ChunkMesh(); - - void mesh(); - void draw(); - - Chunk::Chunk *chunk{nullptr}; - glm::mat4 model = glm::mat4(1.0f); - -private: - void quad(glm::vec3 bottomLeft, glm::vec3 topLeft, glm::vec3 topRight, glm::vec3 bottomRight, Block block, bool backFace); - - std::vector vertices; - std::vector colors; - std::vector indices; - - - GLuint VAO{0}, VBO{0}, EBO{0}, colorBuffer{0}, vIndex{0}; -}; - -#endif \ No newline at end of file diff --git a/include/chunkmesher.hpp b/include/chunkmesher.hpp new file mode 100644 index 0000000..4633e63 --- /dev/null +++ b/include/chunkmesher.hpp @@ -0,0 +1,20 @@ +#ifndef CHUNKMESH_H +#define CHUNKMESH_H + +#include +#include + +#include + +#include "chunk.hpp" +#include "globals.hpp" +#include "shader.hpp" +#include + +void mesh(Chunk::Chunk* chunk); +void draw(Chunk::Chunk* chunk, glm::mat4 model); + +void quad(glm::vec3 bottomLeft, glm::vec3 topLeft, glm::vec3 topRight, glm::vec3 bottomRight, Block block, bool backFace); + + +#endif \ No newline at end of file diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 5c8f1c6..e079b2a 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_minimum_required(VERSION 3.2) project(OpenGLTest) -set(SOURCE_FILES main.cpp chunk.cpp chunkmanager.cpp chunkmesh.cpp chunkgenerator.cpp spacefilling.cpp stb_image.cpp utils.cpp OpenSimplexNoise.cpp) +set(SOURCE_FILES main.cpp chunk.cpp chunkmanager.cpp chunkmesher.cpp chunkgenerator.cpp spacefilling.cpp stb_image.cpp utils.cpp OpenSimplexNoise.cpp) add_executable(OpenGLTest ${SOURCE_FILES}) diff --git a/src/chunk.cpp b/src/chunk.cpp index 73a3047..baa5e0e 100644 --- a/src/chunk.cpp +++ b/src/chunk.cpp @@ -18,11 +18,21 @@ namespace Chunk { this->position = pos; this->blocks.insert(0, CHUNK_VOLUME, Block::AIR); + this->setState(CHUNK_STATE_EMPTY, true); // std::cout << "CHUNK" << std::endl; + glGenVertexArrays(1, &(this->VAO)); + glGenBuffers(1, &(this->colorBuffer)); + glGenBuffers(1, &(this->VBO)); + glGenBuffers(1, &(this->EBO)); + } Chunk ::~Chunk() { + glDeleteVertexArrays(1, &(this->VAO)); + glDeleteBuffers(1, &(this->colorBuffer)); + glDeleteBuffers(1, &(this->VBO)); + glDeleteBuffers(1, &(this->EBO)); } Block Chunk::getBlock(int x, int y, int z) @@ -37,6 +47,7 @@ namespace Chunk } void Chunk::setBlocks(int start, int end, Block b){ + if(b != Block::AIR) this->setState(CHUNK_STATE_EMPTY, false); this->blocks.insert(start < 0 ? 0 : start, end >= CHUNK_VOLUME ? CHUNK_VOLUME : end, b); } diff --git a/src/chunkmanager.cpp b/src/chunkmanager.cpp index 241ac9a..a65a520 100644 --- a/src/chunkmanager.cpp +++ b/src/chunkmanager.cpp @@ -5,14 +5,14 @@ #include "chunk.hpp" #include "chunkgenerator.hpp" #include "chunkmanager.hpp" -#include "chunkmesh.hpp" +#include "chunkmesher.hpp" #include "globals.hpp" #include #include #include -std::unordered_map chunks; +std::unordered_map chunks; namespace chunkmanager { @@ -88,21 +88,22 @@ namespace chunkmanager // std::cout << "Checking" << i << ", " << j << ", " << k <getPosition() /*+ glm::vec3(static_cast(CHUNK_SIZE))*/; + glm::vec3 chunk = chunks.at(index)->getPosition() /*+ glm::vec3(static_cast(CHUNK_SIZE))*/; + glm::mat4 model = glm::translate(glm::mat4(1.0), ((float)CHUNK_SIZE)*chunk); total++; int a{0}; for (int i = 0; i < 8; i++) { - glm::vec4 vertex = glm::vec4(chunk.x + (float)(i & 1), chunk.y + (float)((i & 2) >> 1), chunk.z + (float)((i & 4) >> 2), 500.0f) * (theCamera.getProjection() * theCamera.getView() * chunks.at(index).model); + glm::vec4 vertex = glm::vec4(chunk.x + (float)(i & 1), chunk.y + (float)((i & 2) >> 1), chunk.z + (float)((i & 4) >> 2), 500.0f) * (theCamera.getProjection() * theCamera.getView() * model); vertex = glm::normalize(vertex); a += (-vertex.w <= vertex.x && vertex.x <= vertex.w && -vertex.w <= vertex.y && vertex.y <= vertex.w /*&& -vertex.w < vertex.z && vertex.z < vertex.w*/); @@ -110,14 +111,14 @@ namespace chunkmanager if (a) { toGpu++; - chunks.at(index).draw(); + draw(chunks.at(index), model); } } } void destroy() { - // for (auto &n : chunks) - // delete n.second; + for (auto &n : chunks) + delete n.second; } }; \ No newline at end of file diff --git a/src/chunkmesh.cpp b/src/chunkmesher.cpp similarity index 88% rename from src/chunkmesh.cpp rename to src/chunkmesher.cpp index 259ef0d..e49b4cb 100755 --- a/src/chunkmesh.cpp +++ b/src/chunkmesher.cpp @@ -3,36 +3,17 @@ #include "block.hpp" #include "chunk.hpp" -#include "chunkmesh.hpp" +#include "chunkmesher.hpp" #include "globals.hpp" #include "spacefilling.hpp" #include "utils.hpp" -ChunkMesh::~ChunkMesh() -{ - // if(this->VAO) glDeleteVertexArrays(1, &(this->VAO)); - // if(this->EBO) glDeleteBuffers(1, &(this->EBO)); - // if(this->VBO) glDeleteBuffers(1, &(this->VBO)); - // if(this->colorBuffer) glDeleteBuffers(1, &(this->colorBuffer)); +std::vector vertices; +std::vector colors; +std::vector indices; +GLuint vIndex{0}; - // if(this->chunk) delete this->chunk; -} - -ChunkMesh::ChunkMesh(Chunk::Chunk *c) -{ - this->chunk = c; - - glGenVertexArrays(1, &(this->VAO)); - glGenBuffers(1, &(this->colorBuffer)); - glGenBuffers(1, &(this->VBO)); - glGenBuffers(1, &(this->EBO)); - - this->model = glm::translate(model, (float)CHUNK_SIZE * c->getPosition()); - - // std::cout << "CHUNK MESH " << c << std::endl; -} - -void ChunkMesh::mesh() +void mesh(Chunk::Chunk* chunk) { /* @@ -60,12 +41,11 @@ void ChunkMesh::mesh() indices.clear(); vIndex = 0; + if(chunk->getState(Chunk::CHUNK_STATE_EMPTY)) return; + // convert tree to array since it is easier to work with it int length{0}; - Block *blocks = this->chunk->getBlocksArray(&length); - - if (length == 0) - return; + Block *blocks = chunk->getBlocksArray(&length); int k, l, u, v, w, h, n, j, i; int x[]{0, 0, 0}; @@ -209,18 +189,18 @@ void ChunkMesh::mesh() { // bind the Vertex Array Object first, then bind and set vertex buffer(s), and then configure vertex attributes(s). - glBindVertexArray(VAO); + glBindVertexArray(chunk->VAO); - glBindBuffer(GL_ARRAY_BUFFER, VBO); + glBindBuffer(GL_ARRAY_BUFFER, chunk->VBO); glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(GLfloat), &(vertices[0]), GL_STATIC_DRAW); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, chunk->EBO); glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(GLuint), &(indices[0]), GL_STATIC_DRAW); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void *)0); glEnableVertexAttribArray(0); - glBindBuffer(GL_ARRAY_BUFFER, colorBuffer); + glBindBuffer(GL_ARRAY_BUFFER, chunk->colorBuffer); glBufferData(GL_ARRAY_BUFFER, colors.size() * sizeof(GLfloat), &(colors[0]), GL_STATIC_DRAW); glEnableVertexAttribArray(1); @@ -230,7 +210,7 @@ void ChunkMesh::mesh() // glDisableVertexAttribArray(1); glBindVertexArray(0); - vIndex = (GLuint)(indices.size()); + chunk->vIndex = (GLuint)(indices.size()); vertices.clear(); indices.clear(); @@ -239,24 +219,24 @@ void ChunkMesh::mesh() } -void ChunkMesh::draw() +void draw(Chunk::Chunk* chunk, glm::mat4 model) { // glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); // wireframe mode - if (vIndex > 0) + if(!chunk->getState(Chunk::CHUNK_STATE_EMPTY)) { theShader->use(); - theShader->setMat4("model", this->model); + theShader->setMat4("model", model); theShader->setMat4("view", theCamera.getView()); theShader->setMat4("projection", theCamera.getProjection()); - glBindVertexArray(VAO); - glDrawElements(GL_TRIANGLES, vIndex , GL_UNSIGNED_INT, 0); + glBindVertexArray(chunk->VAO); + glDrawElements(GL_TRIANGLES, chunk->vIndex , GL_UNSIGNED_INT, 0); glBindVertexArray(0); } } -void ChunkMesh::quad(glm::vec3 bottomLeft, glm::vec3 topLeft, glm::vec3 topRight, glm::vec3 bottomRight, Block block, bool backFace) +void quad(glm::vec3 bottomLeft, glm::vec3 topLeft, glm::vec3 topRight, glm::vec3 bottomRight, Block block, bool backFace) { vertices.push_back(bottomLeft.x);