diff --git a/src/render_group.cpp b/src/render_group.cpp index db67cb8..a456be6 100644 --- a/src/render_group.cpp +++ b/src/render_group.cpp @@ -42,19 +42,14 @@ rgInitShaderProgram(gl_render_group* rg, const char * vertex_code, const char * 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; @@ -63,32 +58,44 @@ rgInitShaderProgram(gl_render_group* rg, const char * vertex_code, const char * return true; } -void -rgInitGLBufferObject(gl_buffer* buf_obj, uint len, GLenum usage, GLenum target, GLfloat data[]) +gl_buffer * +rgInitGLBuffer(gl_buffer* buffer, uint buffer_len) { - // TODO: why not just assing the pointer to the render group instead of copying here? - buf_obj->buffer_len = len; - buf_obj->buffer = (GLfloat*) std::calloc(len, sizeof(GLfloat)); + buffer->buffer_len = buffer_len; + buffer->buffer = (GLfloat*) std::calloc(buffer_len, sizeof(GLfloat)); - if (data) - { - for (uint i = 0; i < len; i++) - buf_obj->buffer[i] = data[i]; - } + if (!buffer->buffer) + LOG(ERROR) << "Error allocating memory\n"; + + return buffer; +} + +gl_index_buffer * +initGLIndexBuffer(gl_index_buffer* index_buffer, uint buffer_len) +{ + index_buffer->buffer_len = buffer_len; + index_buffer->buffer = (uint*) std::calloc(buffer_len, sizeof(uint)); + + if (!index_buffer->buffer) + LOG(ERROR) << "Error allocating memory\n"; + + return index_buffer; +} - glGenBuffers(1, &buf_obj->buffer_id); - glBindBuffer(target, buf_obj->buffer_id); - glBufferData(target, len * sizeof(GLfloat), buf_obj->buffer, usage); +void +rgSendBufferToGL(gl_buffer* buffer, GLenum usage, GLenum target) +{ + glGenBuffers(1, &buffer->buffer_id); + glBindBuffer(target, buffer->buffer_id); + glBufferData(target, buffer->buffer_len * sizeof(GLfloat), buffer->buffer, usage); } -// NOTE: helper for fillColorBuffer() to convert uint32 color to GLfloat triplet void -convertColor(GLfloat buf[3], uint32 color) +sendIndexBufferToGL(gl_index_buffer* index_buffer, GLenum usage, GLenum target) { - // 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; + glGenBuffers(1, &index_buffer->buffer_id); + glBindBuffer(target, index_buffer->buffer_id); + glBufferData(target, index_buffer->buffer_len * sizeof(uint), index_buffer->buffer, usage); } void @@ -101,7 +108,7 @@ rgFillColorBuffer(GLfloat buf[], int len, std::vector* hexes) { buf_idx = i * buf_len_per_hex; hex_info hxi = (*hexes)[i]; - convertColor(color_buf, hxi.current_color); + utilConvertColor(color_buf, hxi.current_color); for (int j = 0; j < buf_len_per_hex; j+=3) { @@ -112,20 +119,23 @@ rgFillColorBuffer(GLfloat buf[], int len, std::vector* hexes) } } +// Copy assimp data to our structures for openGL bool rgInitEntity(gl_render_group* rg, Entity* e) { - bool retVal = true; - bool useNormals = rg->use_normals = (e->mesh->normals != nullptr); - + rg->draw_indexed = true; + rg->use_normals = (e->mesh->normals != nullptr); uint vertex_buf_len = e->mesh->num_vertices * 3; - GLfloat* vertex_buf = (GLfloat*) std::calloc(vertex_buf_len, sizeof(GLfloat)); - GLfloat* color_buf = (GLfloat*) std::calloc(vertex_buf_len, sizeof(GLfloat)); - GLfloat* normal_buf; - if (useNormals) - normal_buf = (GLfloat*) std::calloc(vertex_buf_len, sizeof(GLfloat)); - // dump vertices, colors, and normals into temporary buffers + GLfloat* vertex_buf = rgInitGLBuffer(&rg->vertex_buffer, vertex_buf_len)->buffer; + GLfloat* color_buf = rgInitGLBuffer(&rg->color_buffer, vertex_buf_len)->buffer; + GLfloat* normal_buf = rgInitGLBuffer(&rg->normal_buffer, vertex_buf_len)->buffer; + uint* index_buf = initGLIndexBuffer(&rg->index_buffer, e->mesh->num_indices)->buffer; + + if (!vertex_buf || !color_buf || !normal_buf || !index_buf) + return false; + + // dump vertices, colors, and normals into render_group buffers uint vertex_index = 0; uint vertex_prop_index = 0; @@ -139,7 +149,7 @@ rgInitEntity(gl_render_group* rg, Entity* e) case 2: vertex_buf[i] = vertex.z; break; } - if (useNormals) { + if (rg->use_normals) { switch (vertex_prop_index) { case 0: normal_buf[i] = normal.x; break; case 1: normal_buf[i] = normal.y; break; @@ -156,41 +166,17 @@ rgInitEntity(gl_render_group* rg, Entity* e) } } - // send vertex and color data to OpenGL - rgInitGLBufferObject(&rg->vertex_buffer, vertex_buf_len, - GL_DYNAMIC_DRAW, GL_ARRAY_BUFFER, vertex_buf); - - rgInitGLBufferObject(&rg->color_buffer, vertex_buf_len, - GL_STATIC_DRAW, GL_ARRAY_BUFFER, color_buf); - - if (useNormals) { - rgInitGLBufferObject(&rg->vertex_normals, vertex_buf_len, - GL_STATIC_DRAW, GL_ARRAY_BUFFER, normal_buf); - } - - // TODO: combine this somehow with rgInitGLBufferObject() - // dump indices into temp buffer - gl_index_buffer index_buffer; - index_buffer.buffer_len = e->mesh->num_indices; - index_buffer.indices = (uint *) std::calloc(e->mesh->num_indices, sizeof(uint)); - + // dump indices for (uint i = 0; i < e->mesh->num_indices; i++) - index_buffer.indices[i] = e->mesh->indices[i]; - - rg->index_buffer = index_buffer; + index_buf[i] = e->mesh->indices[i]; - glGenBuffers(1, &rg->index_buffer.buffer_id); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, rg->index_buffer.buffer_id); - glBufferData(GL_ELEMENT_ARRAY_BUFFER, e->mesh->num_indices * sizeof(uint), - rg->index_buffer.indices, GL_STATIC_DRAW); - - // free temp buffers - std::free(vertex_buf); - if (useNormals) std::free(normal_buf); - std::free(color_buf); - vertex_buf = normal_buf = color_buf = nullptr; + rgSendBufferToGL(&rg->vertex_buffer, GL_DYNAMIC_DRAW, GL_ARRAY_BUFFER); + rgSendBufferToGL(&rg->color_buffer, GL_STATIC_DRAW, GL_ARRAY_BUFFER); + if (rg->use_normals) + rgSendBufferToGL(&rg->normal_buffer, GL_STATIC_DRAW, GL_ARRAY_BUFFER); + sendIndexBufferToGL(&rg->index_buffer, GL_STATIC_DRAW, GL_ELEMENT_ARRAY_BUFFER); - return retVal; + return true; } void @@ -229,7 +215,7 @@ rgDraw(gl_render_group* rg, GLenum draw_mode, glm::mat4 model_matrix, // 3rd attribute buffer: normals if (rg->use_normals) { glEnableVertexAttribArray(2); - glBindBuffer(GL_ARRAY_BUFFER, rg->vertex_normals.buffer_id); + glBindBuffer(GL_ARRAY_BUFFER, rg->normal_buffer.buffer_id); glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 0, (void*) 0); // TODO: testing lighting @@ -239,52 +225,12 @@ rgDraw(gl_render_group* rg, GLenum draw_mode, glm::mat4 model_matrix, } // 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, - glm::vec3 light_position, GLuint light_id) -{ - 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]); - - // TODO: testing lighting - glUniform3f(light_id, light_position.x, light_position.y, light_position.z); - glm::mat3 normal_matrix = glm::transpose(glm::inverse(glm::mat3(model_matrix))); - glUniformMatrix3fv(rg->normal_matrix_id, 1, GL_FALSE, &normal_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); - - // 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); + if (rg->draw_indexed) { + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, rg->index_buffer.buffer_id); + glDrawElements(draw_mode, rg->index_buffer.buffer_len, GL_UNSIGNED_INT, 0); + } else { + glDrawArrays(draw_mode, 0, rg->vertex_buffer.buffer_len / 3); } - - // 3rd attribe buffer : normals - if (rg->use_normals) { - glEnableVertexAttribArray(2); - glBindBuffer(GL_ARRAY_BUFFER, rg->vertex_normals.buffer_id); - glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 0, (void*) 0); - } - - // draw - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, rg->index_buffer.buffer_id); - glDrawElements(draw_mode, rg->index_buffer.buffer_len, GL_UNSIGNED_INT, 0); // cleanup glDisableVertexAttribArray(0); @@ -301,8 +247,8 @@ rgFree(gl_render_group* rg) return; utilSafeFree(rg->vertex_buffer.buffer); - utilSafeFree(rg->vertex_normals.buffer); - utilSafeFree(rg->index_buffer.indices); + utilSafeFree(rg->normal_buffer.buffer); + utilSafeFree(rg->index_buffer.buffer); utilSafeFree(rg->color_buffer.buffer); utilSafeFree(rg); } diff --git a/src/render_group.h b/src/render_group.h index b1224bd..9f6b5a5 100644 --- a/src/render_group.h +++ b/src/render_group.h @@ -15,13 +15,13 @@ struct gl_index_buffer { GLuint buffer_id = 0; size_t buffer_len = 0; - uint* indices = nullptr; + uint* buffer = nullptr; }; struct gl_render_group { gl_buffer vertex_buffer; - gl_buffer vertex_normals; + gl_buffer normal_buffer; gl_buffer color_buffer; gl_index_buffer index_buffer; GLuint program_id = 0; @@ -31,6 +31,7 @@ struct gl_render_group GLuint normal_matrix_id = 0; GLuint vertex_array_id = 0; bool use_normals = false; + bool draw_indexed = false; }; typedef struct gl_buffer gl_buffer; @@ -39,7 +40,9 @@ typedef struct gl_render_group gl_render_group; bool rgInitShaderProgram(gl_render_group* rg, const char * vertex_code, const char * frag_code); -void rgInitGLBufferObject(gl_buffer* buf_obj, uint len, GLenum usage, GLenum target, GLfloat data[]); +gl_buffer * rgInitGLBuffer(gl_buffer* buffer, uint buffer_len); + +void rgSendBufferToGL(gl_buffer* buffer, GLenum usage, GLenum target); bool rgInitEntity(gl_render_group* rg, Entity* e); @@ -49,9 +52,5 @@ void rgDraw(gl_render_group* rg, GLenum draw_mode, glm::mat4 model_matrix, glm::mat4 view_matrix, glm::mat4 projection_matrix, glm::vec3 light_position, GLuint light_id, 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, - glm::vec3 light_position, GLuint light_id); - void rgFree(gl_render_group* rg); diff --git a/src/renderer.cpp b/src/renderer.cpp index 3c36c32..0519119 100644 --- a/src/renderer.cpp +++ b/src/renderer.cpp @@ -355,72 +355,68 @@ fillHexLineBuffer(GLfloat buf[], int len, std::vector* hexes) } bool -createScene(std::vector* hexes, Entity* entities, uint32 entity_count) +initHexGridBuffers(std::vector* hexes) { - initMatrices(PROJ_TYPE); - - // Vertex Data // TODO: index duplicate vertices - // http://www.opengl-tutorial.org/intermediate-tutorials/tutorial-9-vbo-indexing/ - int hex_count = (int) hexes->size(); // 6 triangles * 3 vertices per triangle * 3 floats per vertex = 54 - int vbuf_len = hex_count * 6 * 3 * 3; + uint vbuf_len = hexes->size() * 6 * 3 * 3; + uint line_vertices_per_hex = 6 * 2; // 12 vertices since we're using line segments atm + uint line_buf_len = hexes->size() * line_vertices_per_hex * 3; // 3 floats per vertex - // TODO: surely there's a way to use indexed drawing for line vertices eg) line_loop - // and still use one buffer for multiple shapes/paths gldrawarraysintanced?, gldrawelements? - // https://gamedev.stackexchange.com/questions/104310/opengl-4-5-primitive-restart-vs-base-index - int line_vertices_per_hex = 6 * 2; // 12 vertices since we're using line segments atm - int line_buf_len = hexes->size() * line_vertices_per_hex * 3; // 3 floats per vertex + gl_buffer& vbuf = * rgInitGLBuffer(&g_filled_hex_render_group->vertex_buffer, vbuf_len); + gl_buffer& cbuf = * rgInitGLBuffer(&g_filled_hex_render_group->color_buffer, vbuf_len); + gl_buffer& normal_buf = * rgInitGLBuffer(&g_filled_hex_render_group->normal_buffer, vbuf_len); + gl_buffer& line_buf = * rgInitGLBuffer(&g_hex_line_render_group->vertex_buffer, line_buf_len); - // temporary buffers - GLfloat* vbuf = (GLfloat*) std::calloc(vbuf_len, sizeof(GLfloat)); - GLfloat* cbuf = (GLfloat*) std::calloc(vbuf_len, sizeof(GLfloat)); - GLfloat* line_buf = (GLfloat*) std::calloc(vbuf_len, sizeof(GLfloat)); - - for (int i = 0; i < hex_count; i++) - fillTriangleBufferFromHex(vbuf, 54 * i, (*hexes)[i]); + if (!vbuf.buffer || !cbuf.buffer || !line_buf.buffer || !normal_buf.buffer) + return false; + for (uint i = 0; i < hexes->size(); i++) + fillTriangleBufferFromHex(vbuf.buffer, 54 * i, (*hexes)[i]); - rgInitGLBufferObject(&g_filled_hex_render_group->vertex_buffer, vbuf_len, - GL_DYNAMIC_DRAW, GL_ARRAY_BUFFER, vbuf); + rgSendBufferToGL(&vbuf, GL_DYNAMIC_DRAW, GL_ARRAY_BUFFER); // color data for hex vertices - rgFillColorBuffer(cbuf, vbuf_len, hexes); - rgInitGLBufferObject(&g_filled_hex_render_group->color_buffer, vbuf_len, - GL_DYNAMIC_DRAW, GL_ARRAY_BUFFER, cbuf); + rgFillColorBuffer(cbuf.buffer, vbuf_len, hexes); + rgSendBufferToGL(&cbuf, GL_DYNAMIC_DRAW, GL_ARRAY_BUFFER); // cheat at vertex normals since all hexes lay flat on z-axis - GLfloat* normal_buf = (GLfloat*) std::calloc(vbuf_len, sizeof(GLfloat)); - for (int i = 0; i < vbuf_len; i += 3) { - normal_buf[i] = 0; - normal_buf[i + 1] = 0; - normal_buf[i + 2] = 1; + for (uint i = 0; i < vbuf_len; i += 3) { + normal_buf.buffer[i] = 0; + normal_buf.buffer[i + 1] = 0; + normal_buf.buffer[i + 2] = 1; } - rgInitGLBufferObject(&g_filled_hex_render_group->vertex_normals, vbuf_len, - GL_STATIC_DRAW, GL_ARRAY_BUFFER, normal_buf); + rgSendBufferToGL(&normal_buf, GL_STATIC_DRAW, GL_ARRAY_BUFFER); g_filled_hex_render_group->use_normals = true; // hex line vertex data - fillHexLineBuffer(line_buf, line_buf_len, hexes); - rgInitGLBufferObject(&g_hex_line_render_group->vertex_buffer, line_buf_len, - GL_STATIC_DRAW, GL_ARRAY_BUFFER, line_buf); + fillHexLineBuffer(line_buf.buffer, line_buf_len, hexes); + g_hex_line_render_group->vertex_buffer.buffer_len = line_buf_len; + rgSendBufferToGL(&line_buf, GL_STATIC_DRAW, GL_ARRAY_BUFFER); // TODO: add a color buffer to hex_line and debug render groups to re-use // fragment shaders and simplify draw rgDraw() + return true; +} - // free temporary buffers - std::free(vbuf); - std::free(cbuf); - std::free(line_buf); - std::free(normal_buf); - vbuf = cbuf = line_buf = normal_buf = nullptr; +bool +createScene(std::vector* hexes, Entity* entities, uint32 entity_count) +{ + initMatrices(PROJ_TYPE); + + if (!initHexGridBuffers(hexes)) + return false; // debug draw vertexes - int len = 4 * 3; // 4 vertices, 3 floats per vertex - rgInitGLBufferObject(&g_debug_render_group->vertex_buffer, len, - GL_DYNAMIC_DRAW, GL_ARRAY_BUFFER, 0); + + rgInitGLBuffer(&g_debug_render_group->vertex_buffer, 4 * 3); // 4 vertices * 3 floats per vertex + + if (!g_debug_render_group->vertex_buffer.buffer) + return false; + + rgSendBufferToGL(&g_debug_render_group->vertex_buffer, GL_DYNAMIC_DRAW, GL_ARRAY_BUFFER); // entities @@ -553,7 +549,7 @@ renderFrame(std::vector *hexes, Entity* entities, uint32 entity_count) // every frame through rgDrawIndexed() // entities for (uint i = 0; i < entity_count; i++) { - rgDrawIndexed( + rgDraw( g_entity_render_group, GL_TRIANGLES, entities[i].mesh->model_transform, m_view, m_projection, g_test_light.position, g_test_light.light_ID @@ -565,19 +561,14 @@ void renderDebug(std::vector &vertices) { // TODO: indexed line drawing - real64 buf[4 * 3] = { - vertices[0].x, vertices[0].y, 0, - vertices[1].x, vertices[1].y, 0, - vertices[2].x, vertices[2].y, 0, - vertices[3].x, vertices[3].y, 0, - }; - // copy vertexes to render group - gl_render_group* rg = g_debug_render_group; - for (int i = 0; i < 12; i++) - rg->vertex_buffer.buffer[i] = buf[i]; + GLfloat* buf = g_debug_render_group->vertex_buffer.buffer; + buf[0] = vertices[0].x; buf[1] = vertices[0].y; buf[2] = 0; + buf[3] = vertices[1].x; buf[4] = vertices[1].y; buf[2] = 0; + buf[6] = vertices[2].x; buf[7] = vertices[2].y; buf[8] = 0; + buf[9] = vertices[3].x; buf[10] = vertices[3].y; buf[11] = 0; - rgDraw(rg, GL_LINE_LOOP, g_scene_matrices.model, g_scene_matrices.view, + rgDraw(g_debug_render_group, GL_LINE_LOOP, g_scene_matrices.model, g_scene_matrices.view, g_scene_matrices.projection, g_test_light.position, g_test_light.light_ID, true); } diff --git a/src/util.cpp b/src/util.cpp index 1a49539..272c4e2 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -2,7 +2,7 @@ #include #include -#include "aixlog.hpp" +//#include "aixlog.hpp" #include "util.h" diff --git a/src/util.h b/src/util.h index e278a88..96b57fd 100644 --- a/src/util.h +++ b/src/util.h @@ -6,6 +6,7 @@ typedef float real32; +typedef float GLfloat; typedef double real64; typedef int32_t bool32; typedef int32_t int32; @@ -64,6 +65,15 @@ SafeTruncateToInt32(int64 val) return (int32) val; } +inline void +utilConvertColor(GLfloat buf[3], uint32 color) +{ + // NOTE: not using the alpha values + buf[0] = (GLfloat) ((color >> 24) & 0xFF) / (GLfloat) 255; + buf[1] = (GLfloat) ((color >> 16) & 0xFF) / (GLfloat) 255; + buf[2] = (GLfloat) ((color >> 8) & 0xFF) / (GLfloat) 255; +} + char * utilDumpTextFile(const char* filename); void utilSafeFree(void* mem);