From 0603f6934c8e8483b22e05a371dc083ac04d2637 Mon Sep 17 00:00:00 2001 From: dummy Date: Wed, 7 Feb 2018 12:33:15 -0500 Subject: [PATCH] added line borders and correct colors to hex rendering --- .gitmodules | 3 + ext/aixlog | 1 + src/hexgame.cpp | 3 - src/hexgame.h | 1 + src/hexlib.h | 5 +- src/renderer.h | 261 +++++++++++++++++++++++++++++++++--------------- 6 files changed, 191 insertions(+), 83 deletions(-) create mode 160000 ext/aixlog diff --git a/.gitmodules b/.gitmodules index 2f9397a..e2adf70 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,6 @@ [submodule "ext/imgui"] path = ext/imgui url = https://github.com/ocornut/imgui.git +[submodule "ext/aixlog"] + path = ext/aixlog + url = https://github.com/badaix/aixlog.git diff --git a/ext/aixlog b/ext/aixlog new file mode 160000 index 0000000..d4e8ab4 --- /dev/null +++ b/ext/aixlog @@ -0,0 +1 @@ +Subproject commit d4e8ab4f1fe0e44d8246b37c349f566b356636f6 diff --git a/src/hexgame.cpp b/src/hexgame.cpp index ac151df..50cad61 100644 --- a/src/hexgame.cpp +++ b/src/hexgame.cpp @@ -38,7 +38,6 @@ #include "hexgame.h" #include "hexlib.h" #include "renderer.h" -//#include "gooey.h" using std::string; using std::stringstream; @@ -61,8 +60,6 @@ debugLog(string error) v2i viewportDims(1280, 720); vector *hexInfoArray; Layout global_layout(layout_flat, Point(25, 25), Point(viewportDims.x/2,viewportDims.y/2)); -uint32 selected_line_color = 0xFFFFFFFF; -uint32 line_color = 0xFFFFFFFF; uint32 selected_fill_color = 0xF46000FF; uint32 fill_color = 0x5C5C5CFF; diff --git a/src/hexgame.h b/src/hexgame.h index 2d3100a..5809eab 100644 --- a/src/hexgame.h +++ b/src/hexgame.h @@ -3,6 +3,7 @@ #define HEXGAME_H #include +#include #include #include diff --git a/src/hexlib.h b/src/hexlib.h index 0c6fb10..69b08c5 100644 --- a/src/hexlib.h +++ b/src/hexlib.h @@ -16,9 +16,10 @@ using std::vector; struct Point { - const double x; - const double y; + double x; + double y; Point(double x_, double y_): x(x_), y(y_) {} + Point(): x(0), y(0) {} }; diff --git a/src/renderer.h b/src/renderer.h index ec56acf..9043b0e 100644 --- a/src/renderer.h +++ b/src/renderer.h @@ -2,8 +2,7 @@ #ifndef RENDERER_H #define RENDERER_H -#include // rand, srand, RAND_MAX -#include // time +#include // TODO: remove for better logging #include // std::cout @@ -21,20 +20,21 @@ bool initRenderer(SDL_Handles &handles, v2i vpDims); // TODO: re-implement debug erender void debugRender(HexDrawMode mode, hex_info *startHex, hex_info *currentHex); -void renderFrame(const vector *hexes); +void renderFrame(const std::vector *hexes); void freeBuffers(); // forward declarations -GLuint initShaders(); +bool initShaders(GLuint &programID1, GLuint &programID2); // enable debug output https://www.khronos.org/opengl/wiki/OpenGL_Error void openglDebugCallback(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar* message, const void* userParam); -void createScene(vector* hexes); +void createScene(std::vector* hexes); void parseHexToGLBuffer(GLfloat buf[], int idx, const hex_info &hex); -void fillColorBuffer(GLfloat* buf, int len); +bool fillColorBuffer(GLfloat* buf, int len, std::vector *hexes); +// TODO: organize these into a struct/structs since we're using at least 2 now glm::mat4 g_projection_matrix; glm::mat4 g_view_matrix; glm::mat4 g_model_matrix; @@ -44,9 +44,14 @@ GLuint g_vertex_buffer_triangle_count; GLuint g_color_buffer; size_t g_buf_size; GLfloat *g_color_buf_data; -GLuint g_programID; +GLuint g_hex_programID; GLuint g_matrixID; +GLuint g_hex_line_vertexbuffer; +size_t g_line_buf_size; +GLuint g_line_programID; +GLuint g_line_matrixID; + bool initRenderer(SDL_Handles &handles, v2i vpDims) { @@ -97,17 +102,24 @@ initRenderer(SDL_Handles &handles, v2i vpDims) glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); #endif + // TODO: glDebugMessageCallback is only availabe from >v4.3 + // check and warn if context doesn't support this function here glEnable (GL_DEBUG_OUTPUT); glDebugMessageCallback((GLDEBUGPROC) openglDebugCallback, 0); - g_programID = initShaders(); - g_matrixID = glGetUniformLocation(g_programID, "g_MVP"); // shader variable for mvp xform + // hide VRAM debug messages + glDebugMessageControl(GL_DONT_CARE, 33361, GL_DONT_CARE, 0, 0, GL_FALSE); + + initShaders(g_hex_programID, g_line_programID); + g_matrixID = glGetUniformLocation(g_hex_programID, "g_MVP"); // shader variables for mvp xform + g_line_matrixID = glGetUniformLocation(g_line_programID, "g_MVP"); return true; } // TODO: figure out how to keep track of shader state, and pass in struct here -GLuint -initShaders() +// TODO: make reusable by creating 1 program at a time +bool +initShaders(GLuint &programID1, GLuint &programID2) { GLuint VertexArrayID; glGenVertexArrays(1, &VertexArrayID); @@ -131,44 +143,57 @@ initShaders() "out vec3 color;\n" "void main()\n" "{\n" - //" color = vec3(0.5,0,0);\n" " color = fragmentColor;\n" "}"; - +#if 1 + const char * LineFragmentShaderCode = + "#version 330 core\n" + "out vec3 color;\n" + "void main()\n" + "{\n" + " color = vec3(0,0,0);\n" + "}"; +#endif GLuint VertexShaderID = glCreateShader(GL_VERTEX_SHADER); GLuint FragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER); + GLuint LineFragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER); glShaderSource(VertexShaderID, 1, &VertexShaderCode, NULL); glShaderSource(FragmentShaderID, 1, &FragmentShaderCode, NULL); + glShaderSource(LineFragmentShaderID, 1, &LineFragmentShaderCode, NULL); glCompileShader(VertexShaderID); glCompileShader(FragmentShaderID); - - GLuint programID = glCreateProgram(); - glAttachShader(programID, VertexShaderID); - glAttachShader(programID, FragmentShaderID); - glLinkProgram(programID); - - glDetachShader(programID, VertexShaderID); - glDetachShader(programID, FragmentShaderID); + glCompileShader(LineFragmentShaderID); + + programID1 = glCreateProgram(); + glAttachShader(programID1, VertexShaderID); + glAttachShader(programID1, FragmentShaderID); + glLinkProgram(programID1); + + programID2 = glCreateProgram(); + glAttachShader(programID2, VertexShaderID); + glAttachShader(programID2, LineFragmentShaderID); + glLinkProgram(programID2); + + glDetachShader(programID1, VertexShaderID); + glDetachShader(programID1, FragmentShaderID); + glDetachShader(programID2, LineFragmentShaderID); + glDetachShader(programID2, FragmentShaderID); glDeleteShader(VertexShaderID); glDeleteShader(FragmentShaderID); - - return programID; + glDeleteShader(LineFragmentShaderID); + + // TODO: what kind of errors can happen here? + return true; } void -createScene(vector* hexes) +createScene(std::vector* hexes) { //////////////////// // Model, View, Projection Matrices - g_projection_matrix = glm::ortho( - 0.f, // left - 1280.0f, // right - 0.f, // bottom - 720.0f, // top - 0.1f, // zNear - 100.0f // zFar - ); + // left, right, bottom, top, zNear, zFar + g_projection_matrix = glm::ortho(0.f, 1280.0f, 0.f, 720.0f, 0.1f, 100.0f); g_view_matrix = glm::lookAt( glm::vec3(0.0f, 0.0f, 2.0f), // camera position @@ -186,7 +211,7 @@ createScene(vector* hexes) // TODO: index duplicate vertices // http://www.opengl-tutorial.org/intermediate-tutorials/tutorial-9-vbo-indexing/ - // 6 triangles * 3 vertices per triange * 3 floats per vertex = 54 + // 6 triangles * 3 vertices per triangle * 3 floats per vertex = 54 int buf_index = 54; size_t hex_count = hexes->size(); g_buf_size = 6 * 9 * hex_count; @@ -202,14 +227,64 @@ createScene(vector* hexes) glBindBuffer(GL_ARRAY_BUFFER, g_vertexbuffer); glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * g_buf_size, vbuf_data, GL_STATIC_DRAW); - // make some pretty colors + + // color data for hex vertices - srand(time(0)); // seed c library rng - g_color_buf_data = (GLfloat*) std::malloc(sizeof(GLfloat) * g_buf_size); - fillColorBuffer(g_color_buf_data, int(g_buf_size)); + g_color_buf_data = (GLfloat*) std::calloc( g_buf_size, sizeof(GLfloat)); + + if (!fillColorBuffer(g_color_buf_data, (int) g_buf_size, hexes)) + { + // TODO: log fatal error + return; + } + glGenBuffers(1, &g_color_buffer); glBindBuffer(GL_ARRAY_BUFFER, g_color_buffer); glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * g_buf_size, g_color_buf_data, GL_DYNAMIC_DRAW); + + + // Hex Line Vertex Data + + // 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 + g_line_buf_size = hex_count * line_vertices_per_hex * 3; // 3 floats per vertex + GLfloat line_buf_data[g_line_buf_size] = { 0 }; + + int line_buf_idx = 0; + for (int i = 0; i < (int) hex_count; i++) + { + hex_info hxi = (*hexes)[i]; + for (int j = 0; j < 6; j ++) + { + Point p1, p2; + + if (j == 5) // wrap + { + p1 = hxi.vertices[j]; + p2 = hxi.vertices[0]; + } + else + { + p1 = hxi.vertices[j]; + p2 = hxi.vertices[j + 1]; + } + + line_buf_data[line_buf_idx + 0] = p1.x; + line_buf_data[line_buf_idx + 1] = p1.y; + line_buf_data[line_buf_idx + 2] = 0.f; + line_buf_data[line_buf_idx + 3] = p2.x; + line_buf_data[line_buf_idx + 4] = p2.y; + line_buf_data[line_buf_idx + 5] = 0.f; + + line_buf_idx += 6; + } + } + + glGenBuffers(1, &g_hex_line_vertexbuffer); + glBindBuffer(GL_ARRAY_BUFFER, g_hex_line_vertexbuffer); + glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * g_line_buf_size, line_buf_data, GL_STATIC_DRAW); } void @@ -218,7 +293,7 @@ parseHexToGLBuffer(GLfloat buf[], int idx, const hex_info &hex) // triangles for (int i = 0; i < 6; i++) { - if (i == 5) // wrap + if (i == 5) // re-use the first point for the last triangle { // vertex 0 buf[idx + 0] = (GLfloat) hex.XPos; @@ -258,23 +333,53 @@ parseHexToGLBuffer(GLfloat buf[], int idx, const hex_info &hex) } } -void -fillColorBuffer(GLfloat* buf, int len) +bool +fillColorBuffer(GLfloat buf[], int len, std::vector *hexes) { - for (int i = 0; i < len; i++) + if (!buf || len < 1) { - // should be normalized between 0 and 1 - buf[i] = GLfloat((GLfloat) rand() / (GLfloat) RAND_MAX); + // TODO: log fatal error + return false; + } + + if (!hexes || hexes->size() == 0) + { + // TODO: log fatal error + return false; + } + + // 3 floats per vertex, 3 vertexes per triangle, 6 triangles per hex + if (len != (int) hexes->size() * 3 * 3 * 6) + { + // TODO: log fatal error + return false; + } + + int buf_idx; + int buf_len_per_hex = 54; // NOTE: 3 * 3 * 6 + for (int i = 0; i < (int) hexes->size(); i++) + { + buf_idx = i * buf_len_per_hex; + hex_info hxi = (*hexes)[i]; + GLfloat color = (GLfloat) hxi.current_color / (GLfloat) UINT32_MAX; + + for (int j = 0; j < buf_len_per_hex; j++) + { + buf[buf_idx + j] = color; + } } + + return true; } -struct +typedef struct clear_col { - real32 R = 75.0f / 255.0f; - real32 G = 135.0f / 255.0f; - real32 B = 135.0f / 255.0f; - real32 A = 1; -} gl_clear_color; + real32 R; + real32 G; + real32 B; + real32 A; +} clear_col; +clear_col g_clear_col { 75.f / 255.f, 135.f / 255.f, 135.f / 255.f, 1.f }; void openglDebugCallback(GLenum source, GLenum type, GLuint id, GLenum severity, @@ -289,56 +394,56 @@ openglDebugCallback(GLenum source, GLenum type, GLuint id, GLenum severity, } void -renderFrame(const vector *hexes) +renderFrame(std::vector *hexes) { - glClearColor(gl_clear_color.R, gl_clear_color.G, gl_clear_color.B, - gl_clear_color.A); + 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); - - glUseProgram(g_programID); - // Send our transformation to the currently bound shader, - // in the "g_MVP" uniform +#if 1 + glUseProgram(g_hex_programID); + // Send our transformation to the currently bound shader, in the "g_MVP" uniform glUniformMatrix4fv(g_matrixID, 1, GL_FALSE, &g_MVP[0][0]); // 1st attribute buffer : vertices glEnableVertexAttribArray(0); glBindBuffer(GL_ARRAY_BUFFER, g_vertexbuffer); - glVertexAttribPointer( - 0, // attribute 0. No particular reason for 0, but must match the layout in the shader. - 3, // size - GL_FLOAT, // type - GL_FALSE, // normalized? - 0, // stride - (void*)0 // array buffer offset - ); - + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*) 0); // 2nd attribute buffer : colors glEnableVertexAttribArray(1); glBindBuffer(GL_ARRAY_BUFFER, g_color_buffer); - glVertexAttribPointer( - 1, - 3, - GL_FLOAT, - GL_FALSE, - 0, - (void*)0 - ); - + glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, (void*) 0); // get new colors every frame - fillColorBuffer(g_color_buf_data, int(g_buf_size)); + fillColorBuffer(g_color_buf_data, (int) g_buf_size, hexes); glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(GLfloat) * g_buf_size, g_color_buf_data); - glDrawArrays(GL_TRIANGLES, 0, g_vertex_buffer_triangle_count); glDisableVertexAttribArray(0); + glDisableVertexAttribArray(1); +#endif + +#if 1 + glUseProgram(g_line_programID); + // Send our transformation to the currently bound shader, in the "g_MVP" uniform + glUniformMatrix4fv(g_matrixID, 1, GL_FALSE, &g_MVP[0][0]); + + // 1st attribute buffer : vertices + GLuint attrib_index = 0; // TODO: line buffer doesn't render if this is anything other than 0 + glEnableVertexAttribArray(attrib_index); + glBindBuffer(GL_ARRAY_BUFFER, g_hex_line_vertexbuffer); + glVertexAttribPointer(attrib_index, 3, GL_FLOAT, GL_FALSE, 0, (void*) 0); + + glDrawArrays(GL_LINES, 0, g_line_buf_size / 3); +#endif } void freeBuffers() { - free(g_color_buf_data); - g_color_buf_data = 0; + if (g_color_buf_data) + { + free(g_color_buf_data); + g_color_buf_data = 0; + } } #endif // RENDERER_H