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 heapvertex-deduplication
parent
ec2feb919f
commit
c547d11cd5
|
@ -46,6 +46,9 @@ namespace Chunk
|
||||||
IntervalMap<Block>& getBlocks() { return (this->blocks); }
|
IntervalMap<Block>& getBlocks() { return (this->blocks); }
|
||||||
Block* getBlocksArray(int* len) { return (this->blocks.toArray(len)); }
|
Block* getBlocksArray(int* len) { return (this->blocks.toArray(len)); }
|
||||||
|
|
||||||
|
public:
|
||||||
|
GLuint VAO{0}, VBO{0}, EBO{0}, colorBuffer{0}, vIndex{0};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
glm::vec3 position{};
|
glm::vec3 position{};
|
||||||
IntervalMap<Block> blocks{};
|
IntervalMap<Block> blocks{};
|
||||||
|
|
|
@ -1,38 +0,0 @@
|
||||||
#ifndef CHUNKMESH_H
|
|
||||||
#define CHUNKMESH_H
|
|
||||||
|
|
||||||
#include <glad/glad.h>
|
|
||||||
#include <GLFW/glfw3.h>
|
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
#include "chunk.hpp"
|
|
||||||
#include "globals.hpp"
|
|
||||||
#include "shader.hpp"
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
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<GLfloat> vertices;
|
|
||||||
std::vector<GLfloat> colors;
|
|
||||||
std::vector<GLuint> indices;
|
|
||||||
|
|
||||||
|
|
||||||
GLuint VAO{0}, VBO{0}, EBO{0}, colorBuffer{0}, vIndex{0};
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
#ifndef CHUNKMESH_H
|
||||||
|
#define CHUNKMESH_H
|
||||||
|
|
||||||
|
#include <glad/glad.h>
|
||||||
|
#include <GLFW/glfw3.h>
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "chunk.hpp"
|
||||||
|
#include "globals.hpp"
|
||||||
|
#include "shader.hpp"
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
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
|
|
@ -1,7 +1,7 @@
|
||||||
cmake_minimum_required(VERSION 3.2)
|
cmake_minimum_required(VERSION 3.2)
|
||||||
project(OpenGLTest)
|
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})
|
add_executable(OpenGLTest ${SOURCE_FILES})
|
||||||
|
|
||||||
|
|
|
@ -18,11 +18,21 @@ namespace Chunk
|
||||||
{
|
{
|
||||||
this->position = pos;
|
this->position = pos;
|
||||||
this->blocks.insert(0, CHUNK_VOLUME, Block::AIR);
|
this->blocks.insert(0, CHUNK_VOLUME, Block::AIR);
|
||||||
|
this->setState(CHUNK_STATE_EMPTY, true);
|
||||||
// std::cout << "CHUNK" << std::endl;
|
// std::cout << "CHUNK" << std::endl;
|
||||||
|
glGenVertexArrays(1, &(this->VAO));
|
||||||
|
glGenBuffers(1, &(this->colorBuffer));
|
||||||
|
glGenBuffers(1, &(this->VBO));
|
||||||
|
glGenBuffers(1, &(this->EBO));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Chunk ::~Chunk()
|
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)
|
Block Chunk::getBlock(int x, int y, int z)
|
||||||
|
@ -37,6 +47,7 @@ namespace Chunk
|
||||||
}
|
}
|
||||||
|
|
||||||
void Chunk::setBlocks(int start, int end, Block b){
|
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);
|
this->blocks.insert(start < 0 ? 0 : start, end >= CHUNK_VOLUME ? CHUNK_VOLUME : end, b);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,14 +5,14 @@
|
||||||
#include "chunk.hpp"
|
#include "chunk.hpp"
|
||||||
#include "chunkgenerator.hpp"
|
#include "chunkgenerator.hpp"
|
||||||
#include "chunkmanager.hpp"
|
#include "chunkmanager.hpp"
|
||||||
#include "chunkmesh.hpp"
|
#include "chunkmesher.hpp"
|
||||||
#include "globals.hpp"
|
#include "globals.hpp"
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
std::unordered_map<std::uint32_t, ChunkMesh> chunks;
|
std::unordered_map<std::uint32_t, Chunk::Chunk*> chunks;
|
||||||
|
|
||||||
namespace chunkmanager
|
namespace chunkmanager
|
||||||
{
|
{
|
||||||
|
@ -88,21 +88,22 @@ namespace chunkmanager
|
||||||
// std::cout << "Checking" << i << ", " << j << ", " << k <<std::endl;
|
// std::cout << "Checking" << i << ", " << j << ", " << k <<std::endl;
|
||||||
if (chunks.find(index) == chunks.end())
|
if (chunks.find(index) == chunks.end())
|
||||||
{
|
{
|
||||||
chunks.insert(std::make_pair(index, ChunkMesh(new Chunk::Chunk(glm::vec3(i, j, k)))));
|
chunks.insert(std::make_pair(index, new Chunk::Chunk(glm::vec3(i, j, k))));
|
||||||
generateChunk(chunks.at(index).chunk);
|
generateChunk(chunks.at(index));
|
||||||
chunks.at(index).mesh();
|
mesh(chunks.at(index));
|
||||||
// std::cout << "Creating new chunk" << i << ", " << j << ", " << k <<std::endl;
|
// std::cout << "Creating new chunk" << i << ", " << j << ", " << k <<std::endl;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
glm::vec3 chunk = chunks.at(index).chunk->getPosition() /*+ glm::vec3(static_cast<float>(CHUNK_SIZE))*/;
|
glm::vec3 chunk = chunks.at(index)->getPosition() /*+ glm::vec3(static_cast<float>(CHUNK_SIZE))*/;
|
||||||
|
glm::mat4 model = glm::translate(glm::mat4(1.0), ((float)CHUNK_SIZE)*chunk);
|
||||||
|
|
||||||
total++;
|
total++;
|
||||||
|
|
||||||
int a{0};
|
int a{0};
|
||||||
for (int i = 0; i < 8; i++)
|
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);
|
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*/);
|
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)
|
if (a)
|
||||||
{
|
{
|
||||||
toGpu++;
|
toGpu++;
|
||||||
chunks.at(index).draw();
|
draw(chunks.at(index), model);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void destroy()
|
void destroy()
|
||||||
{
|
{
|
||||||
// for (auto &n : chunks)
|
for (auto &n : chunks)
|
||||||
// delete n.second;
|
delete n.second;
|
||||||
}
|
}
|
||||||
};
|
};
|
|
@ -3,36 +3,17 @@
|
||||||
|
|
||||||
#include "block.hpp"
|
#include "block.hpp"
|
||||||
#include "chunk.hpp"
|
#include "chunk.hpp"
|
||||||
#include "chunkmesh.hpp"
|
#include "chunkmesher.hpp"
|
||||||
#include "globals.hpp"
|
#include "globals.hpp"
|
||||||
#include "spacefilling.hpp"
|
#include "spacefilling.hpp"
|
||||||
#include "utils.hpp"
|
#include "utils.hpp"
|
||||||
|
|
||||||
ChunkMesh::~ChunkMesh()
|
std::vector<GLfloat> vertices;
|
||||||
{
|
std::vector<GLfloat> colors;
|
||||||
// if(this->VAO) glDeleteVertexArrays(1, &(this->VAO));
|
std::vector<GLuint> indices;
|
||||||
// if(this->EBO) glDeleteBuffers(1, &(this->EBO));
|
GLuint vIndex{0};
|
||||||
// if(this->VBO) glDeleteBuffers(1, &(this->VBO));
|
|
||||||
// if(this->colorBuffer) glDeleteBuffers(1, &(this->colorBuffer));
|
|
||||||
|
|
||||||
// if(this->chunk) delete this->chunk;
|
void mesh(Chunk::Chunk* 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()
|
|
||||||
{
|
{
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -60,12 +41,11 @@ void ChunkMesh::mesh()
|
||||||
indices.clear();
|
indices.clear();
|
||||||
vIndex = 0;
|
vIndex = 0;
|
||||||
|
|
||||||
|
if(chunk->getState(Chunk::CHUNK_STATE_EMPTY)) return;
|
||||||
|
|
||||||
// convert tree to array since it is easier to work with it
|
// convert tree to array since it is easier to work with it
|
||||||
int length{0};
|
int length{0};
|
||||||
Block *blocks = this->chunk->getBlocksArray(&length);
|
Block *blocks = chunk->getBlocksArray(&length);
|
||||||
|
|
||||||
if (length == 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
int k, l, u, v, w, h, n, j, i;
|
int k, l, u, v, w, h, n, j, i;
|
||||||
int x[]{0, 0, 0};
|
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).
|
// 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);
|
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);
|
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);
|
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void *)0);
|
||||||
glEnableVertexAttribArray(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);
|
glBufferData(GL_ARRAY_BUFFER, colors.size() * sizeof(GLfloat), &(colors[0]), GL_STATIC_DRAW);
|
||||||
|
|
||||||
glEnableVertexAttribArray(1);
|
glEnableVertexAttribArray(1);
|
||||||
|
@ -230,7 +210,7 @@ void ChunkMesh::mesh()
|
||||||
// glDisableVertexAttribArray(1);
|
// glDisableVertexAttribArray(1);
|
||||||
glBindVertexArray(0);
|
glBindVertexArray(0);
|
||||||
|
|
||||||
vIndex = (GLuint)(indices.size());
|
chunk->vIndex = (GLuint)(indices.size());
|
||||||
|
|
||||||
vertices.clear();
|
vertices.clear();
|
||||||
indices.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
|
// glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); // wireframe mode
|
||||||
if (vIndex > 0)
|
if(!chunk->getState(Chunk::CHUNK_STATE_EMPTY))
|
||||||
{
|
{
|
||||||
theShader->use();
|
theShader->use();
|
||||||
theShader->setMat4("model", this->model);
|
theShader->setMat4("model", model);
|
||||||
theShader->setMat4("view", theCamera.getView());
|
theShader->setMat4("view", theCamera.getView());
|
||||||
theShader->setMat4("projection", theCamera.getProjection());
|
theShader->setMat4("projection", theCamera.getProjection());
|
||||||
|
|
||||||
glBindVertexArray(VAO);
|
glBindVertexArray(chunk->VAO);
|
||||||
glDrawElements(GL_TRIANGLES, vIndex , GL_UNSIGNED_INT, 0);
|
glDrawElements(GL_TRIANGLES, chunk->vIndex , GL_UNSIGNED_INT, 0);
|
||||||
glBindVertexArray(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);
|
vertices.push_back(bottomLeft.x);
|
Loading…
Reference in New Issue