terrain

Real-time terrain generation using marching cubes
git clone git://git.christianermann.dev/terrain
Log | Files | Refs | README | LICENSE

commit c63216862550a584b6dcb1b0969efed01383ed4f
parent 392c2c87c3bd3600b9275ea31ffc8c2faac6e288
Author: Christian Ermann <christianermann@gmail.com>
Date:   Wed, 18 Aug 2021 17:34:47 -0500

Removed mesh double buffering

Diffstat:
Minclude/chunk.h | 7+++----
Minclude/mesh.h | 13+++++++------
Msrc/chunk.c | 38+++++++++++++++++++++++++-------------
Msrc/chunk_manager.c | 9+++------
Msrc/mesh.c | 83++++++++++++++++++++++++++++++++++++-------------------------------------------
5 files changed, 76 insertions(+), 74 deletions(-)

diff --git a/include/chunk.h b/include/chunk.h @@ -3,6 +3,7 @@ #include "mesh.h" #include "sdf.h" +#include "threadpool.h" #include <pthread.h> @@ -20,16 +21,14 @@ typedef struct { UpdateArgs *update_args; pthread_mutex_t mesh_mutex; - bool mesh_updated; + int mesh_update_count; } Chunk; void Chunk_init(Chunk *c); void Chunk_free(Chunk *c); void Chunk_updateOrigin(Chunk *c, IVec3 origin); - -void Chunk_setUpdateArgs(Chunk *c, SDF f, float isolevel); -void Chunk_updateFunc(void *arg); +void Chunk_updateMesh(Chunk *c, SDF f, float isolevel, ThreadPool *pool); void Chunk_drawMesh(Chunk *c); diff --git a/include/mesh.h b/include/mesh.h @@ -14,18 +14,19 @@ typedef struct { unsigned int index_count; unsigned int *indices; - unsigned int draw_index; - unsigned int write_index; - unsigned int vao[2]; - unsigned int vbo[2]; - unsigned int ebo[2]; + unsigned int vao; + unsigned int vbo; + unsigned int ebo; + + bool buffers_mapped; } Mesh; void Mesh_init(Mesh *m, unsigned int vertex_count, unsigned int index_count); void Mesh_free(Mesh *m); -void Mesh_swapBuffers(Mesh *m); +void Mesh_mapBuffers(Mesh *m); +void Mesh_unmapBuffers(Mesh *m); void Mesh_draw(const Mesh *m); diff --git a/src/chunk.c b/src/chunk.c @@ -1,6 +1,7 @@ #include "chunk.h" #include "marching_cubes.h" +#include "threadpool.h" #include <stdlib.h> @@ -33,7 +34,7 @@ void Chunk_init(Chunk *c) c->update_args = UpdateArgs_make(c); pthread_mutex_init(&c->mesh_mutex, NULL); - c->mesh_updated = false; + c->mesh_update_count = 0; } void Chunk_free(Chunk *c) @@ -138,14 +139,7 @@ static void Chunk_updateMeshData(Chunk *c, SDF f, float isolevel) } } -void Chunk_setUpdateArgs(Chunk *c, SDF f, float isolevel) -{ - c->update_args->chunk = c; - c->update_args->f = f; - c->update_args->isolevel = isolevel; -} - -void Chunk_updateFunc(void *arg) +static void Chunk_updateMeshFunc(void *arg) { UpdateArgs *args = (UpdateArgs*)arg; @@ -153,11 +147,30 @@ void Chunk_updateFunc(void *arg) Chunk_updateMeshData(args->chunk, args->f, args->isolevel); - args->chunk->mesh_updated = true; + args->chunk->mesh_update_count -= 1; pthread_mutex_unlock(&args->chunk->mesh_mutex); } +void Chunk_updateMesh(Chunk *c, SDF f, float isolevel, ThreadPool *pool) +{ + c->update_args->chunk = c; + c->update_args->f = f; + c->update_args->isolevel = isolevel; + + pthread_mutex_lock(&c->mesh_mutex); + + if (c->mesh_update_count == 0 && !c->mesh.buffers_mapped) + { + Mesh_mapBuffers(&c->mesh); + } + c->mesh_update_count += 1; + + pthread_mutex_unlock(&c->mesh_mutex); + + ThreadPool_addWork(pool, Chunk_updateMeshFunc, c->update_args); +} + void Chunk_updateOrigin(Chunk *c, IVec3 origin) { pthread_mutex_lock(&c->mesh_mutex); @@ -171,10 +184,9 @@ void Chunk_drawMesh(Chunk *c) { if (pthread_mutex_trylock(&c->mesh_mutex) == 0) { - if (c->mesh_updated) + if (c->mesh_update_count == 0 && c->mesh.buffers_mapped) { - Mesh_swapBuffers(&c->mesh); - c->mesh_updated = false; + Mesh_unmapBuffers(&c->mesh); } pthread_mutex_unlock(&c->mesh_mutex); } diff --git a/src/chunk_manager.c b/src/chunk_manager.c @@ -48,9 +48,7 @@ static void ChunkManager_createChunks(ChunkManager *cm) cm->origin[2] + cm->offsets[i][2] }; Chunk_updateOrigin(&cm->chunks[i], chunk_origin); - Chunk_setUpdateArgs(&cm->chunks[i], cm->f, cm->isolevel); - ThreadPool_addWork(cm->pool, Chunk_updateFunc, - cm->chunks[i].update_args); + Chunk_updateMesh(&cm->chunks[i], cm->f, cm->isolevel, cm->pool); } } @@ -100,9 +98,8 @@ static void ChunkManager_updateChunkMeshes(ChunkManager *cm) cm->origin[2] + cm->offsets[i][2] }; Chunk_updateOrigin(&cm->chunks[j], chunk_origin); - Chunk_setUpdateArgs(&cm->chunks[j], cm->f, cm->isolevel); - ThreadPool_addWork(cm->pool, Chunk_updateFunc, - cm->chunks[j].update_args); + Chunk_updateMesh(&cm->chunks[j], cm->f, cm->isolevel, + cm->pool); cm->is_new_offset[i] = false; cm->is_old_chunk[j] = false; diff --git a/src/mesh.c b/src/mesh.c @@ -12,35 +12,24 @@ void Mesh_init(Mesh *m, unsigned int vertex_count, unsigned int index_count) m->index_capacity = index_count; m->index_count = 0; - m->draw_index = 0; - m->write_index = 1; + glGenVertexArrays(1, &m->vao); + glBindVertexArray(m->vao); - glGenVertexArrays(2, m->vao); - glGenBuffers(2, m->vbo); - glGenBuffers(2, m->ebo); - for (int i = 0; i < 2; i++) - { - glBindVertexArray(m->vao[i]); - - glBindBuffer(GL_ARRAY_BUFFER, m->vbo[i]); - glBufferData(GL_ARRAY_BUFFER, sizeof *m->vertices * vertex_count, NULL, - GL_STATIC_DRAW); - - glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vec3), 0); - glEnableVertexAttribArray(0); + glGenBuffers(1, &m->vbo); + glBindBuffer(GL_ARRAY_BUFFER, m->vbo); + glBufferData(GL_ARRAY_BUFFER, sizeof *m->vertices * vertex_count, NULL, + GL_STATIC_DRAW); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m->ebo[i]); - glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof *m->indices * index_count, - NULL, GL_STATIC_DRAW); + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vec3), (GLvoid*)0); + glEnableVertexAttribArray(0); - glBindVertexArray(0); - } - glBindBuffer(GL_ARRAY_BUFFER, m->vbo[m->write_index]); - m->vertices = glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY); + glGenBuffers(1, &m->ebo); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m->ebo); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof *m->indices * index_count, + NULL, GL_STATIC_DRAW); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m->ebo[m->write_index]); - m->indices = glMapBuffer(GL_ELEMENT_ARRAY_BUFFER, GL_WRITE_ONLY); + glBindVertexArray(0); } void Mesh_free(Mesh *m) @@ -50,40 +39,44 @@ void Mesh_free(Mesh *m) m->index_capacity = 0; m->index_count = 0; - - glBindBuffer(GL_ARRAY_BUFFER, m->vbo[m->write_index]); - glUnmapBuffer(GL_ARRAY_BUFFER); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m->ebo[m->write_index]); - glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER); + Mesh_unmapBuffers(m); - glDeleteVertexArrays(2, m->vao); - glDeleteBuffers(2, m->vbo); - glDeleteBuffers(2, m->ebo); + glDeleteVertexArrays(1, &m->vao); + glDeleteBuffers(1, &m->vbo); + glDeleteBuffers(1, &m->ebo); } -void Mesh_swapBuffers(Mesh *m) +void Mesh_mapBuffers(Mesh *m) { - glBindBuffer(GL_ARRAY_BUFFER, m->vbo[m->draw_index]); + glBindBuffer(GL_ARRAY_BUFFER, m->vbo); m->vertices = glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY); - glBindBuffer(GL_ARRAY_BUFFER, m->vbo[m->write_index]); - glUnmapBuffer(GL_ARRAY_BUFFER); - - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m->ebo[m->draw_index]); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m->ebo); m->indices = glMapBuffer(GL_ELEMENT_ARRAY_BUFFER, GL_WRITE_ONLY); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m->ebo[m->write_index]); + m->buffers_mapped = true; +} + +void Mesh_unmapBuffers(Mesh *m) +{ + glBindBuffer(GL_ARRAY_BUFFER, m->vbo); + glUnmapBuffer(GL_ARRAY_BUFFER); + m->vertices = NULL; + + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m->ebo); glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER); + m->indices = NULL; - unsigned int temp = m->draw_index; - m->draw_index = m->write_index; - m->write_index = temp; + m->buffers_mapped = false; } void Mesh_draw(const Mesh *m) { - glBindVertexArray(m->vao[m->draw_index]); - glDrawElements(GL_TRIANGLES, m->index_count, GL_UNSIGNED_INT, (GLvoid*)0); - glBindVertexArray(0); + if (!m->buffers_mapped) + { + glBindVertexArray(m->vao); + glDrawElements(GL_TRIANGLES, m->index_count, GL_UNSIGNED_INT, 0); + glBindVertexArray(0); + } }