From 5c162f71636f507fc8e2538af3fa9f0e504365c6 Mon Sep 17 00:00:00 2001 From: cinnaboot Date: Thu, 19 Jul 2018 22:19:11 -0400 Subject: [PATCH] move render group functions to seperate file --- .gdb_history | 1 - src/hexgame.cpp | 4 + src/hexgame.h | 4 +- src/mesh.cpp | 18 ++- src/mesh.h | 2 + src/render_group.cpp | 280 +++++++++++++++++++++++++++++++++++++ src/render_group.h | 52 +++++++ src/renderer.cpp | 318 ++++++------------------------------------- 8 files changed, 403 insertions(+), 276 deletions(-) delete mode 100644 .gdb_history create mode 100644 src/render_group.cpp create mode 100644 src/render_group.h diff --git a/.gdb_history b/.gdb_history deleted file mode 100644 index bca70f3..0000000 --- a/.gdb_history +++ /dev/null @@ -1 +0,0 @@ -q diff --git a/src/hexgame.cpp b/src/hexgame.cpp index f399d87..205086e 100644 --- a/src/hexgame.cpp +++ b/src/hexgame.cpp @@ -453,6 +453,8 @@ cleanUp(SDL_Handles &handles) for (uint i = 0; i < r->entity_count; i++) { std::free(r->entities[i].vertices); r->entities[i].vertices = nullptr; + std::free(r->entities[i].indices); + r->entities[i].indices = nullptr; } std::free(r->entities); @@ -536,7 +538,9 @@ int main(int argc, char* argv[]) // TODO: keep better track of entity memory Entity* e = (Entity*) std::calloc(1, sizeof(Entity)); e->num_vertices = getVertexCount(); + e->num_indices = getIndexCount(); e->vertices = (glm::vec3 *) std::calloc(e->num_vertices, sizeof(glm::vec3)); + e->indices = (uint *) std::calloc (e->num_indices, sizeof(uint)); convertMesh(e); g_render_state->entities = e; g_render_state->entity_count++; diff --git a/src/hexgame.h b/src/hexgame.h index f4a3fec..5ca96b0 100644 --- a/src/hexgame.h +++ b/src/hexgame.h @@ -78,8 +78,10 @@ enum HexDrawMode struct Entity { glm::mat4 model_transform; - glm::vec3 *vertices = nullptr; uint num_vertices = 0; + glm::vec3* vertices = nullptr; + uint num_indices = 0; + uint* indices = nullptr; }; struct render_state diff --git a/src/mesh.cpp b/src/mesh.cpp index f02db93..4824df9 100644 --- a/src/mesh.cpp +++ b/src/mesh.cpp @@ -36,6 +36,13 @@ getVertexCount() return g_scene->mMeshes[0]->mNumVertices; } +uint +getIndexCount() +{ + assert(g_scene); + return g_scene->mMeshes[0]->mNumFaces * 3; // NOTE: assume 3 vertices per face +} + // TODO: probably don't really need to copy this here // let assimp manage the storage, and just reference indexes after passing // to opengl @@ -47,16 +54,25 @@ convertMesh(Entity* e) assert(g_scene); uint numVertices = getVertexCount(); assert(e && e->num_vertices == numVertices); + aiMesh* mesh = g_scene->mMeshes[0]; // copy vertices for (uint i = 0; i < numVertices; i++) { - aiVector3D v_in = g_scene->mMeshes[0]->mVertices[i]; + aiVector3D v_in = mesh->mVertices[i]; glm::vec3 &v_out = e->vertices[i]; v_out.x = v_in.x; v_out.y = v_in.y; v_out.z = v_in.z; } + // copy indices + uint numFaces = g_scene->mMeshes[0]->mNumFaces; + e->num_indices = numFaces * 3; //NOTE: assume 3 vertices per face + for (uint i = 0; i < numFaces; i++) { + for (uint j = 0; j < 3; j++) + e->indices[i * 3 + j] = mesh->mFaces[i].mIndices[j]; + } + return e; } diff --git a/src/mesh.h b/src/mesh.h index 893e9ef..e5595de 100644 --- a/src/mesh.h +++ b/src/mesh.h @@ -16,6 +16,8 @@ bool initAssimp(); uint getVertexCount(); +uint getIndexCount(); + // copy data from assimp for use in our renderer Entity* convertMesh(Entity* e); diff --git a/src/render_group.cpp b/src/render_group.cpp new file mode 100644 index 0000000..dd00aad --- /dev/null +++ b/src/render_group.cpp @@ -0,0 +1,280 @@ + +#include +#include // calloc + +// TODO: decide on extension library +//#include +#include +#include +#include +#include + +#include "aixlog.hpp" + +#include "render_group.h" + + +gl_render_group* +rgCreateGroup() +{ + gl_render_group* rg = (gl_render_group *) std::calloc(1, sizeof(gl_render_group)); + return rg; +} + +bool +rgInitShaderProgram(gl_render_group* rg, const char * vertex_code, const char * frag_code, + const char* model_name, const char* view_name, const char* projection_name) +{ + glGenVertexArrays(1, &rg->vertex_array_id); + glBindVertexArray(rg->vertex_array_id); + GLuint vertex_shader_id = glCreateShader(GL_VERTEX_SHADER); + GLuint fragment_shader_id = glCreateShader(GL_FRAGMENT_SHADER); + + glShaderSource(vertex_shader_id, 1, &vertex_code, NULL); + glShaderSource(fragment_shader_id, 1, &frag_code, NULL); + glCompileShader(vertex_shader_id); + glCompileShader(fragment_shader_id); + + rg->program_id = glCreateProgram(); + glAttachShader(rg->program_id, vertex_shader_id); + glAttachShader(rg->program_id, fragment_shader_id); + glLinkProgram(rg->program_id); + + rg->model_matrix_id = glGetUniformLocation(rg->program_id, model_name); + rg->view_matrix_id = glGetUniformLocation(rg->program_id, view_name); + rg->projection_matrix_id = glGetUniformLocation(rg->program_id, projection_name); + + glDetachShader(rg->program_id, vertex_shader_id); + glDetachShader(rg->program_id, fragment_shader_id); + glDeleteShader(vertex_shader_id); + glDeleteShader(fragment_shader_id); + + // check for errors + GLint isLinked = 0; + glGetProgramiv(rg->program_id, GL_LINK_STATUS, &isLinked); + if (isLinked == GL_FALSE) { + GLint maxLength = 0; + glGetProgramiv(rg->program_id, GL_INFO_LOG_LENGTH, &maxLength); + + // The maxLength includes the NULL character + GLchar infoLog[maxLength]; + glGetProgramInfoLog(rg->program_id, maxLength, &maxLength, &infoLog[0]); + LOG(ERROR) << infoLog << "\n"; + + // The program is useless now. So delete it. + glDeleteProgram(rg->program_id); + + return false; + } + + return true; +} + +// NOTE: this will only work after a call to glBindBuffer +bool +checkGLBufferSize(GLenum buf_type, int expected_size, int line_num) +{ + GLint gl_size; + glGetBufferParameteriv(buf_type, GL_BUFFER_SIZE ,&gl_size); + + if (expected_size != gl_size) + { + LOG(ERROR) << "line: " << line_num << "gl buffer size mismatch\n"; + return false; + } + + return true; +} + +bool +rgInitGLBufferObject(gl_buffer* buf_obj, int len, GLenum usage, GLfloat data[]) +{ + buf_obj->buffer_len = (size_t) len; + buf_obj->buffer = (GLfloat*) std::calloc(len, sizeof(GLfloat)); + + if (data) + { + for (int i = 0; i < len; i++) + buf_obj->buffer[i] = data[i]; + } + + glGenBuffers(1, &buf_obj->buffer_id); + glBindBuffer(GL_ARRAY_BUFFER, buf_obj->buffer_id); + glBufferData(GL_ARRAY_BUFFER, len * sizeof(GLfloat), buf_obj->buffer, usage); + + if (!checkGLBufferSize(GL_ARRAY_BUFFER, len * sizeof(GLfloat), __LINE__)) + return false; + + return true; +} + +// NOTE: helper for fillColorBuffer() to convert uint32 color to GLfloat triplet +void +convertColor(GLfloat buf[3], uint32 color) +{ + // NOTE: not using the alpha values for now + buf[0] = (GLfloat) ((color >> 24) & 0xFF) / (GLfloat) 255; + buf[1] = (GLfloat) ((color >> 16) & 0xFF) / (GLfloat) 255; + buf[2] = (GLfloat) ((color >> 8) & 0xFF) / (GLfloat) 255; +} + +void +rgFillColorBuffer(GLfloat buf[], int len, std::vector* hexes) +{ + int buf_idx; + int buf_len_per_hex = 54; // NOTE: 3 * 3 * 6 + GLfloat color_buf[3]; + for (int i = 0; i < (int) hexes->size(); i++) + { + buf_idx = i * buf_len_per_hex; + hex_info hxi = (*hexes)[i]; + convertColor(color_buf, hxi.current_color); + + for (int j = 0; j < buf_len_per_hex; j+=3) + { + buf[buf_idx + j] = color_buf[0]; + buf[buf_idx + j + 1] = color_buf[1]; + buf[buf_idx + j + 2] = color_buf[2]; + } + } +} + +bool +rgInitEntity(gl_render_group* rg, Entity* e) +{ + bool retVal = true; + + // TODO: entity scaling + e->model_transform = glm::scale(glm::mat4(1), glm::vec3(100, 100, 100)); + + uint entity_buf_len = e->num_vertices * 3; + GLfloat* entity_buf = (GLfloat*) std::calloc(entity_buf_len, sizeof(GLfloat)); + GLfloat* entity_color_buf = (GLfloat*) std::calloc(entity_buf_len, sizeof(GLfloat)); + + // dump vertices into temporary buffer + uint vertex_index = 0; + uint vertex_prop_index = 0; + GLfloat entity_test_color[3]; + convertColor(entity_test_color, 0xF46000FF); + + for (uint j = 0; j < entity_buf_len; j++) { + const glm::vec3& vertex = e->vertices[vertex_index]; + + switch (vertex_prop_index) { + case 0: entity_buf[j] = vertex.x; break; + case 1: entity_buf[j] = vertex.y; break; + case 2: entity_buf[j] = vertex.z; break; + } + + entity_color_buf[j] = entity_test_color[vertex_prop_index]; + vertex_prop_index++; + + if (vertex_prop_index == 3) { + vertex_prop_index = 0; + vertex_index++; + } + } + +#if 1 + if (!rgInitGLBufferObject(&rg->vertex_buffer, entity_buf_len, + GL_DYNAMIC_DRAW, entity_buf)) + retVal = false; + + if (!rgInitGLBufferObject(&rg->color_buffer, entity_buf_len, + GL_STATIC_DRAW, entity_color_buf)) + retVal = false; +#endif + + // TODO: testing indexed draw + + gl_buffer index_buffer; + index_buffer.num_indices = e->num_indices; + // TODO: there's no associated call to free this alloc until we remake + index_buffer.indices = (uint *) std::calloc(e->num_indices, sizeof(uint)); + + for (uint i = 0; i < e->num_indices; i++) + index_buffer.indices[i] = e->indices[i]; + + rg->index_buffer = index_buffer; + + ////////// + + std::free(entity_buf); + std::free(entity_color_buf); + entity_buf = entity_color_buf = nullptr; + + return retVal; +} + +void +rgDraw(gl_render_group* rg, GLenum draw_mode, glm::mat4 model_matrix, + glm::mat4 view_matrix, glm::mat4 projection_matrix, bool update_vertex_data) +{ + glUseProgram(rg->program_id); + glUniformMatrix4fv(rg->model_matrix_id, 1, GL_FALSE, &model_matrix[0][0]); + glUniformMatrix4fv(rg->view_matrix_id, 1, GL_FALSE, &view_matrix[0][0]); + glUniformMatrix4fv(rg->projection_matrix_id, 1, GL_FALSE, &projection_matrix[0][0]); + + // 1st attribute buffer : vertices + glEnableVertexAttribArray(0); + glBindBuffer(GL_ARRAY_BUFFER, rg->vertex_buffer.buffer_id); + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*) 0); + + if (update_vertex_data) + { + glBufferSubData(GL_ARRAY_BUFFER, 0, rg->vertex_buffer.buffer_len * sizeof(GLfloat), + rg->vertex_buffer.buffer); + } + + // 2nd attribute buffer : colors + if (rg->color_buffer.buffer) + { + glEnableVertexAttribArray(1); + glBindBuffer(GL_ARRAY_BUFFER, rg->color_buffer.buffer_id); + glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, (void*) 0); + + // TODO: maybe add an option to not send color data every frame? + glBufferSubData(GL_ARRAY_BUFFER, 0, rg->color_buffer.buffer_len * sizeof(GLfloat), + rg->color_buffer.buffer); + } + // draw + glDrawArrays(draw_mode, 0, rg->vertex_buffer.buffer_len / 3); + + // cleanup + glDisableVertexAttribArray(0); + if (rg->color_buffer.buffer) + glDisableVertexAttribArray(1); +} + +void +rgDrawIndexed(gl_render_group* rg, GLenum draw_mode, glm::mat4 model_matrix, + glm::mat4 view_matrix, glm::mat4 projection_matrix, bool update_vertex_data) +{ + // +} + +void +rgFree(gl_render_group* rg) +{ + assert(rg != nullptr); + gl_buffer bufs[] = {rg->vertex_buffer, rg->color_buffer, rg->index_buffer}; + for (uint i = 0; i < 3; i++) { + gl_buffer& buf = bufs[i]; + if (buf.buffer != nullptr) { + std::free(buf.buffer); + buf.buffer = nullptr; + } + if (buf.indices != nullptr) { + std::free(buf.indices); + buf.indices = nullptr; + } + } + + if (rg->entities != nullptr) { + // TODO: handle entity memory + } + + std::free(rg); + rg = nullptr; +} + diff --git a/src/render_group.h b/src/render_group.h new file mode 100644 index 0000000..eb806b6 --- /dev/null +++ b/src/render_group.h @@ -0,0 +1,52 @@ + +// TODO: put type info into seperate header from hexgame.h +//#include "types.h" +#include "hexgame.h" + +struct gl_buffer +{ + GLuint buffer_id = 0; + size_t buffer_len = 0; // NOTE: number of elements in buffer + GLfloat* buffer = nullptr; + uint num_indices = 0; + uint* indices = nullptr; +} ; + +struct gl_render_group +{ + // NOTE: For now the renderFrame function will assume these are the same size + gl_buffer vertex_buffer; + gl_buffer color_buffer; + gl_buffer index_buffer; + GLuint program_id = 0; + GLuint model_matrix_id = 0; + GLuint view_matrix_id = 0; + GLuint projection_matrix_id = 0; + GLuint vertex_array_id = 0; + Entity* entities = nullptr; +}; + +typedef struct gl_buffer gl_buffer; +typedef struct gl_render_group gl_render_group; + +gl_render_group* rgCreateGroup(); + +// NOTE: model_name, view_name, and projection_name should match the matrix variable +// names in the shader source +bool rgInitShaderProgram(gl_render_group* rg, const char * vertex_code, const char * frag_code, + const char* model_name, const char* view_name, const char* projection_name); + +bool rgInitGLBufferObject(gl_buffer* buf_obj, int len, GLenum usage, GLfloat data[]); + +bool rgInitEntity(gl_render_group* rg, Entity* e); + +void rgFillColorBuffer(GLfloat buf[], int len, std::vector* hexes); + +void rgDraw(gl_render_group* rg, GLenum draw_mode, glm::mat4 model_matrix, + glm::mat4 view_matrix, glm::mat4 projection_matrix, bool update_vertex_data = false); + +void rgDrawIndexed(gl_render_group* rg, GLenum draw_mode, glm::mat4 model_matrix, + glm::mat4 view_matrix, glm::mat4 projection_matrix, bool update_vertex_data = false); + +void rgFree(gl_render_group* rg); + diff --git a/src/renderer.cpp b/src/renderer.cpp index 81f3ca7..99bc795 100644 --- a/src/renderer.cpp +++ b/src/renderer.cpp @@ -21,6 +21,8 @@ #include "hexlib.h" #include "hexgame.h" +#include "renderer.h" +#include "render_group.h" #define MOVE_SPEED 5.f #define ROTATE_SPEED 0.005f @@ -101,45 +103,15 @@ struct camera glm::vec3 left; }; -typedef struct gl_buffer -{ - GLuint buffer_id = 0; - size_t buffer_len = 0; // NOTE: number of elements in buffer - GLfloat* buffer = nullptr; -} gl_buffer; - -typedef struct gl_render_group -{ - // NOTE: For now the renderFrame function will assume these are the same size - gl_buffer vertex_buffer; - gl_buffer color_buffer; - GLuint program_id = 0; - GLuint model_matrix_id = 0; - GLuint view_matrix_id = 0; - GLuint projection_matrix_id = 0; - GLuint vertex_array_id = 0; - Entity* entity = nullptr; -} gl_render_group; gl_matrix_info g_scene_matrices; -gl_render_group g_filled_hex_render_group; -gl_render_group g_hex_line_render_group; -gl_render_group g_debug_render_group; -gl_render_group g_entity_render_group; +gl_render_group* g_filled_hex_render_group = rgCreateGroup(); +gl_render_group* g_hex_line_render_group = rgCreateGroup(); +gl_render_group* g_debug_render_group = rgCreateGroup(); +gl_render_group* g_entity_render_group = rgCreateGroup(); camera g_camera; -void -openglDebugCallback(GLenum source, GLenum type, GLuint id, GLenum severity, - GLsizei length, const GLchar* message, const void* userParam) -{ - LOG((type == GL_DEBUG_TYPE_ERROR) ? ERROR : DEBUG) - << (type == GL_DEBUG_TYPE_ERROR ? "** GL ERROR **" : "") - << ", type: " << type - << ", severity: " << severity - << ", message: " << message << "\n"; -} - bool addTexture(SDL_Handles &handles, const char * path) { @@ -182,57 +154,6 @@ getUnprojectedCoords(int32 x, int32 y, int32 vp_width, int32 vp_height) return v; } -// NOTE: model_name, view_name, and projection_name should match the matrix variable -// names in the shader source -bool -initShaderProgram(gl_render_group &rg, const char * vertex_code, const char * frag_code, - const char* model_name, const char* view_name, const char* projection_name) -{ - glGenVertexArrays(1, &rg.vertex_array_id); - glBindVertexArray(rg.vertex_array_id); - GLuint vertex_shader_id = glCreateShader(GL_VERTEX_SHADER); - GLuint fragment_shader_id = glCreateShader(GL_FRAGMENT_SHADER); - - glShaderSource(vertex_shader_id, 1, &vertex_code, NULL); - glShaderSource(fragment_shader_id, 1, &frag_code, NULL); - glCompileShader(vertex_shader_id); - glCompileShader(fragment_shader_id); - - rg.program_id = glCreateProgram(); - glAttachShader(rg.program_id, vertex_shader_id); - glAttachShader(rg.program_id, fragment_shader_id); - glLinkProgram(rg.program_id); - - rg.model_matrix_id = glGetUniformLocation(rg.program_id, model_name); - rg.view_matrix_id = glGetUniformLocation(rg.program_id, view_name); - rg.projection_matrix_id = glGetUniformLocation(rg.program_id, projection_name); - - glDetachShader(rg.program_id, vertex_shader_id); - glDetachShader(rg.program_id, fragment_shader_id); - glDeleteShader(vertex_shader_id); - glDeleteShader(fragment_shader_id); - - // check for errors - GLint isLinked = 0; - glGetProgramiv(rg.program_id, GL_LINK_STATUS, &isLinked); - if (isLinked == GL_FALSE) { - GLint maxLength = 0; - glGetProgramiv(rg.program_id, GL_INFO_LOG_LENGTH, &maxLength); - - // The maxLength includes the NULL character - GLchar infoLog[maxLength]; - glGetProgramInfoLog(rg.program_id, maxLength, &maxLength, &infoLog[0]); - LOG(ERROR) << infoLog << "\n"; - - // The program is useless now. So delete it. - glDeleteProgram(rg.program_id); - - return false; - } - - return true; -} - void initMatrices(projection_type p) { @@ -291,42 +212,15 @@ initMatrices(projection_type p) g_scene_matrices.MVP = g_scene_matrices.projection * g_scene_matrices.view * g_scene_matrices.model; } -// NOTE: this will only work after a call to glBindBuffer -bool -checkGLBufferSize(GLenum buf_type, int expected_size, int line_num) -{ - GLint gl_size; - glGetBufferParameteriv(buf_type, GL_BUFFER_SIZE ,&gl_size); - - if (expected_size != gl_size) - { - LOG(ERROR) << "line: " << line_num << "gl buffer size mismatch\n"; - return false; - } - - return true; -} - -bool -initGLBufferObject(gl_buffer* buf_obj, int len, GLenum usage, GLfloat data[]) +void +openglDebugCallback(GLenum source, GLenum type, GLuint id, GLenum severity, + GLsizei length, const GLchar* message, const void* userParam) { - buf_obj->buffer_len = (size_t) len; - buf_obj->buffer = (GLfloat*) std::calloc(len, sizeof(GLfloat)); - - if (data) - { - for (int i = 0; i < len; i++) - buf_obj->buffer[i] = data[i]; - } - - glGenBuffers(1, &buf_obj->buffer_id); - glBindBuffer(GL_ARRAY_BUFFER, buf_obj->buffer_id); - glBufferData(GL_ARRAY_BUFFER, len * sizeof(GLfloat), buf_obj->buffer, usage); - - if (!checkGLBufferSize(GL_ARRAY_BUFFER, len * sizeof(GLfloat), __LINE__)) - return false; - - return true; + LOG((type == GL_DEBUG_TYPE_ERROR) ? ERROR : DEBUG) + << (type == GL_DEBUG_TYPE_ERROR ? "** GL ERROR **" : "") + << ", type: " << type + << ", severity: " << severity + << ", message: " << message << "\n"; } bool @@ -394,16 +288,16 @@ initRenderer(SDL_Handles &handles, v2i vpDims) // hide VRAM debug messages glDebugMessageControl(GL_DONT_CARE, 33361, GL_DONT_CARE, 0, 0, GL_FALSE); - if (!initShaderProgram( + if (!rgInitShaderProgram( g_filled_hex_render_group, VERTEX_SHADER_CODE, FRAGMENT_SHADER_CODE, "model", "view", "projection") - || !initShaderProgram( + || !rgInitShaderProgram( g_hex_line_render_group, VERTEX_SHADER_CODE, LINE_FRAGMENT_SHADER_CODE, "model", "view", "projection") - || !initShaderProgram( + || !rgInitShaderProgram( g_debug_render_group, VERTEX_SHADER_CODE, DEBUG_FRAGMENT_SHADER_CODE, "model", "view", "projection") - || !initShaderProgram( + || !rgInitShaderProgram( g_entity_render_group, VERTEX_SHADER_CODE, FRAGMENT_SHADER_CODE, "model", "view", "projection")) { @@ -449,37 +343,6 @@ fillTriangleBufferFromHex(GLfloat buf[], int idx, const hex_info &hex) } } -// NOTE: helper for fillColorBuffer() to convert uint32 color to GLfloat triplet -void -convertColor(GLfloat buf[3], uint32 color) -{ - // NOTE: not using the alpha values for now - buf[0] = (GLfloat) ((color >> 24) & 0xFF) / (GLfloat) 255; - buf[1] = (GLfloat) ((color >> 16) & 0xFF) / (GLfloat) 255; - buf[2] = (GLfloat) ((color >> 8) & 0xFF) / (GLfloat) 255; -} - -void -fillColorBuffer(GLfloat buf[], int len, std::vector* hexes) -{ - int buf_idx; - int buf_len_per_hex = 54; // NOTE: 3 * 3 * 6 - GLfloat color_buf[3]; - for (int i = 0; i < (int) hexes->size(); i++) - { - buf_idx = i * buf_len_per_hex; - hex_info hxi = (*hexes)[i]; - convertColor(color_buf, hxi.current_color); - - for (int j = 0; j < buf_len_per_hex; j+=3) - { - buf[buf_idx + j] = color_buf[0]; - buf[buf_idx + j + 1] = color_buf[1]; - buf[buf_idx + j + 2] = color_buf[2]; - } - } -} - void fillHexLineBuffer(GLfloat buf[], int len, std::vector* hexes) { @@ -541,20 +404,23 @@ createScene(std::vector* hexes, Entity* entities, uint32 entity_count) fillTriangleBufferFromHex(vbuf, 54 * i, (*hexes)[i]); - if (!initGLBufferObject(&g_filled_hex_render_group.vertex_buffer, vbuf_len, GL_DYNAMIC_DRAW, vbuf)) + if (!rgInitGLBufferObject(&g_filled_hex_render_group->vertex_buffer, vbuf_len, + GL_DYNAMIC_DRAW, vbuf)) return false; // color data for hex vertices - fillColorBuffer(cbuf, vbuf_len, hexes); + rgFillColorBuffer(cbuf, vbuf_len, hexes); - if (!initGLBufferObject(&g_filled_hex_render_group.color_buffer, vbuf_len, GL_DYNAMIC_DRAW, cbuf)) + if (!rgInitGLBufferObject(&g_filled_hex_render_group->color_buffer, vbuf_len, + GL_DYNAMIC_DRAW, cbuf)) return false; // hex line vertex data fillHexLineBuffer(line_buf, line_buf_len, hexes); - if (!initGLBufferObject(&g_hex_line_render_group.vertex_buffer, line_buf_len, GL_STATIC_DRAW, line_buf)) + if (!rgInitGLBufferObject(&g_hex_line_render_group->vertex_buffer, line_buf_len, + GL_STATIC_DRAW, line_buf)) return false; // free temporary buffers @@ -568,56 +434,16 @@ createScene(std::vector* hexes, Entity* entities, uint32 entity_count) // 4 vertices, 3 floats per vertex int len = 4 * 3; - if (!initGLBufferObject(&g_debug_render_group.vertex_buffer, len, GL_DYNAMIC_DRAW, 0)) + if (!rgInitGLBufferObject(&g_debug_render_group->vertex_buffer, len, GL_DYNAMIC_DRAW, 0)) return false; - /////////////// // TODO: Testing Entities/assimp model loading - g_entity_render_group.entity = &entities[0]; - entities[0].model_transform = glm::scale(glm::mat4(1), glm::vec3(100, 100, 100)); - - uint entity_buf_len = entities[0].num_vertices * 3; - GLfloat* entity_buf = (GLfloat*) std::calloc(entity_buf_len, sizeof(GLfloat)); - GLfloat* entity_color_buf = (GLfloat*) std::calloc(entity_buf_len, sizeof(GLfloat)); - - // dump vertices into temporary buffer - uint vertex_index = 0; - uint vertex_prop_index = 0; - GLfloat entity_test_color[3]; - convertColor(entity_test_color, 0xF46000FF); - - for (uint j = 0; j < entity_buf_len; j++) { - const glm::vec3& vertex = entities[0].vertices[vertex_index]; - - switch (vertex_prop_index) { - case 0: entity_buf[j] = vertex.x; break; - case 1: entity_buf[j] = vertex.y; break; - case 2: entity_buf[j] = vertex.z; break; - } - - entity_color_buf[j] = entity_test_color[vertex_prop_index]; - vertex_prop_index++; - - if (vertex_prop_index == 3) { - vertex_prop_index = 0; - vertex_index++; - } - } - - if (!initGLBufferObject(&g_entity_render_group.vertex_buffer, entity_buf_len, - GL_DYNAMIC_DRAW, entity_buf)) - return false; + g_entity_render_group->entities = &entities[0]; - if (!initGLBufferObject(&g_entity_render_group.color_buffer, entity_buf_len, - GL_DYNAMIC_DRAW, entity_color_buf)) + if (!rgInitEntity(g_entity_render_group, &entities[0])) return false; - - std::free(entity_buf); - std::free(entity_color_buf); - entity_buf = entity_color_buf = nullptr; - ///////// return true; @@ -707,72 +533,30 @@ rollCamera(bool CW, bool CCW) #endif } -void -drawRenderGroup(gl_render_group* rg, GLenum draw_mode, bool update_vertex_data = false) -{ - glUseProgram(rg->program_id); - - // Send our transformation to the currently bound shader - glm::mat4 model_matrix; - if (rg->entity) - model_matrix = rg->entity->model_transform; - else - model_matrix = g_scene_matrices.model; - - glUniformMatrix4fv(rg->model_matrix_id, 1, GL_FALSE, &model_matrix[0][0]); - glUniformMatrix4fv(rg->view_matrix_id, 1, GL_FALSE, &g_scene_matrices.view[0][0]); - glUniformMatrix4fv(rg->projection_matrix_id, 1, GL_FALSE, &g_scene_matrices.projection[0][0]); - - // 1st attribute buffer : vertices - glEnableVertexAttribArray(0); - glBindBuffer(GL_ARRAY_BUFFER, rg->vertex_buffer.buffer_id); - glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*) 0); - - if (update_vertex_data) - { - glBufferSubData(GL_ARRAY_BUFFER, 0, rg->vertex_buffer.buffer_len * sizeof(GLfloat), - rg->vertex_buffer.buffer); - } - - // 2nd attribute buffer : colors - if (rg->color_buffer.buffer) - { - glEnableVertexAttribArray(1); - glBindBuffer(GL_ARRAY_BUFFER, rg->color_buffer.buffer_id); - glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, (void*) 0); - - // TODO: maybe add an option to not send color data every frame? - glBufferSubData(GL_ARRAY_BUFFER, 0, rg->color_buffer.buffer_len * sizeof(GLfloat), - rg->color_buffer.buffer); - } - // draw - glDrawArrays(draw_mode, 0, rg->vertex_buffer.buffer_len / 3); - - // cleanup - glDisableVertexAttribArray(0); - if (rg->color_buffer.buffer) - glDisableVertexAttribArray(1); -} - void renderFrame(std::vector *hexes) { glClearColor(g_clear_col.R, g_clear_col.G, g_clear_col.B, g_clear_col.A); glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); + glm::mat4 m_model = g_scene_matrices.model; + glm::mat4 m_view = g_scene_matrices.view; + glm::mat4 m_projection = g_scene_matrices.projection; + // filled hexes // get new colors every frame - gl_render_group* rg = &g_filled_hex_render_group; - fillColorBuffer(rg->color_buffer.buffer, rg->color_buffer.buffer_len, hexes); - drawRenderGroup(rg, GL_TRIANGLES); + gl_render_group* rg = g_filled_hex_render_group; + rgFillColorBuffer(rg->color_buffer.buffer, rg->color_buffer.buffer_len, hexes); + rgDraw(rg, GL_TRIANGLES, m_model, m_view, m_projection); // hex lines - drawRenderGroup(&g_hex_line_render_group, GL_LINES); + rgDraw(g_hex_line_render_group, GL_LINES, m_model, m_view, m_projection); // TODO: testing entity rendering - drawRenderGroup(&g_entity_render_group, GL_TRIANGLES); + rg = g_entity_render_group; + rgDraw(rg, GL_TRIANGLES, rg->entities[0].model_transform, m_view, m_projection); } void @@ -787,37 +571,25 @@ renderDebug(std::vector &vertices) }; // copy vertexes to render group - gl_render_group* rg = &g_debug_render_group; + gl_render_group* rg = g_debug_render_group; for (int i = 0; i < 12; i++) rg->vertex_buffer.buffer[i] = buf[i]; - drawRenderGroup(rg, GL_LINE_LOOP, true); + rgDraw(rg, GL_LINE_LOOP, g_scene_matrices.model, g_scene_matrices.view, + g_scene_matrices.projection, true); } void freeBuffers() { - std::vector groups = { + std::vector groups = { g_filled_hex_render_group, g_hex_line_render_group, g_debug_render_group, - //g_entity_render_group TODO: handle enitiy memory separately + g_entity_render_group }; - for (gl_render_group group : groups) - { - if (group.vertex_buffer.buffer) - { - std::free(group.vertex_buffer.buffer); - group.vertex_buffer.buffer = 0; - } - - if (group.color_buffer.buffer) - { - std::free(group.color_buffer.buffer); - group.color_buffer.buffer = 0; - } - } - + for (gl_render_group* group : groups) + rgFree(group); }