From 8675683d103d0e5198cf3845ea0e55e38d48e592 Mon Sep 17 00:00:00 2001 From: Phireh Date: Sun, 25 May 2025 17:56:43 +0200 Subject: [PATCH] Add UVs to vert shader --- Makefile | 2 +- main.cpp | 162 +++++++++++++++++++++++++++++++++++++++-------- notes.org | 1 + shaders/hex.vert | 1 + 4 files changed, 138 insertions(+), 28 deletions(-) diff --git a/Makefile b/Makefile index 37dd724..3bc906f 100644 --- a/Makefile +++ b/Makefile @@ -5,4 +5,4 @@ CFLAGS=-I./include -I/usr/include/freetype2 -I/usr/include/libpng16 -I/usr/inclu .PHONY: hexnando hexnando: main.cpp - g++ -std=c++20 -Wall -g -Wextra -pedantic -Werror -Wno-calloc-transposed-args -Og main.cpp ${LINK_FLAGS} ${CFLAGS} -o hexnando + g++ -std=c++20 -Wall -g -Wextra -pedantic -Werror -Wno-calloc-transposed-args -Wno-return-type -Wno-unused-parameter -Og main.cpp ${LINK_FLAGS} ${CFLAGS} -o hexnando diff --git a/main.cpp b/main.cpp index 48e8450..b0414b2 100644 --- a/main.cpp +++ b/main.cpp @@ -91,6 +91,7 @@ struct hex_t { glm::vec3 position; float radius; glm::vec3 vertices[7]; + glm::vec2 uvs[7]; glm::vec4 color; uint32_t vao; uint32_t vbo; @@ -119,6 +120,10 @@ struct texture_t { uint32_t h; }; +struct input_t { + uint8_t keys[GLFW_KEY_LAST]; +}; + const int32_t ARRAY_LIMIT = 400; charglyph_t glyphmap[128]; @@ -129,9 +134,12 @@ uint32_t texture_array; glm::mat4 transforms[ARRAY_LIMIT]; int32_t letter_map[ARRAY_LIMIT]; int32_t text_frame_idx; - texture_t pngtex = {}; +camera_t the_camera = {}; +bool dirty_window = true; +input_t frame_input = {}; + // error processing enum err_type { OK = 0, @@ -177,9 +185,15 @@ void glfw_error_callback(int error, const char* description) fprintf(stderr, "GLFW error %d: %s\n", error, description); } -void scroll_callback([[maybe_unused]]GLFWwindow* window, [[maybe_unused]]double xoffset, double yoffset) +void scroll_callback([[maybe_unused]]GLFWwindow *window, [[maybe_unused]]double xoffset, double yoffset) { mouse_scroll = yoffset; + dirty_window = true; +} + +void key_callback([[maybe_unused]]GLFWwindow *window, int key, [[maybe_unused]]int scancode, [[maybe_unused]]int action, [[maybe_unused]]int mods) +{ + frame_input.keys[key] = action; } int path_callback([[maybe_unused]]ImGuiInputTextCallbackData *data) @@ -188,6 +202,44 @@ int path_callback([[maybe_unused]]ImGuiInputTextCallbackData *data) return 0; } +void ogl_debugcb(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, GLchar const* message, void const* user_param) +{ + auto const src_str = [source]() { + switch (source) + { + case GL_DEBUG_SOURCE_API: return "API"; + case GL_DEBUG_SOURCE_WINDOW_SYSTEM: return "WINDOW SYSTEM"; + case GL_DEBUG_SOURCE_SHADER_COMPILER: return "SHADER COMPILER"; + case GL_DEBUG_SOURCE_THIRD_PARTY: return "THIRD PARTY"; + case GL_DEBUG_SOURCE_APPLICATION: return "APPLICATION"; + case GL_DEBUG_SOURCE_OTHER: return "OTHER"; + } + }(); + + auto const type_str = [type]() { + switch (type) + { + case GL_DEBUG_TYPE_ERROR: return "ERROR"; + case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR: return "DEPRECATED_BEHAVIOR"; + case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR: return "UNDEFINED_BEHAVIOR"; + case GL_DEBUG_TYPE_PORTABILITY: return "PORTABILITY"; + case GL_DEBUG_TYPE_PERFORMANCE: return "PERFORMANCE"; + case GL_DEBUG_TYPE_MARKER: return "MARKER"; + case GL_DEBUG_TYPE_OTHER: return "OTHER"; + } + }(); + + auto const severity_str = [severity]() { + switch (severity) { + case GL_DEBUG_SEVERITY_NOTIFICATION: return "NOTIFICATION"; + case GL_DEBUG_SEVERITY_LOW: return "LOW"; + case GL_DEBUG_SEVERITY_MEDIUM: return "MEDIUM"; + case GL_DEBUG_SEVERITY_HIGH: return "HIGH"; + } + }(); + std::cout << src_str << ", " << type_str << ", " << severity_str << ", " << id << ": " << message << '\n'; +} + int read_png(const char *path) { @@ -453,27 +505,57 @@ void create_grid(grid_t *grid, int rows, int columns) the_hexagon->vertices[5] = the_hexagon->position + glm::vec3(radius * glm::cos(glm::radians(60.0)), -radius * glm::sin(glm::radians(60.0)), 0); the_hexagon->vertices[6] = the_hexagon->position + glm::vec3(-radius * glm::cos(glm::radians(60.0)), -radius * glm::sin(glm::radians(60.0)), 0); + // default uv coordinates are a simple 1 unit-sized hexagon mask + the_hexagon->uvs[0] = glm::vec2(0, 0); + the_hexagon->uvs[1] = glm::vec2(-radius, 0); + the_hexagon->uvs[2] = glm::vec2(-radius * glm::cos(glm::radians(60.0)), radius * glm::sin(glm::radians(60.0))); + the_hexagon->uvs[3] = glm::vec2(radius * glm::cos(glm::radians(60.0)), radius * glm::sin(glm::radians(60.0))); + the_hexagon->uvs[4] = glm::vec2(radius, 0); + the_hexagon->uvs[5] = glm::vec2(radius * glm::cos(glm::radians(60.0)), -radius * glm::sin(glm::radians(60.0))); + the_hexagon->uvs[6] = glm::vec2(-radius * glm::cos(glm::radians(60.0)), -radius * glm::sin(glm::radians(60.0))); + + // copy verts + uvs to a temp ordered buffer before sending to GPU + float databuf[7 * 3 + 7 * 2]; + int n = 0; + for (int i = 0; i < 7; ++i) + { + databuf[n++] = the_hexagon->vertices[i].x; + databuf[n++] = the_hexagon->vertices[i].y; + databuf[n++] = the_hexagon->vertices[i].z; + databuf[n++] = the_hexagon->uvs[i].x; + databuf[n++] = the_hexagon->uvs[i].y; + } + glGenVertexArrays(1, &the_hexagon->vao); glGenBuffers(1, &the_hexagon->vbo); glBindVertexArray(the_hexagon->vao); glBindBuffer(GL_ARRAY_BUFFER, the_hexagon->vbo); - glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 7 * 3, the_hexagon->vertices, GL_STATIC_DRAW); + glBufferData(GL_ARRAY_BUFFER, + sizeof(float) * 7 * 3 + // vertices + sizeof(float) * 7 * 2 // normals + , databuf, GL_STATIC_DRAW); - // EBO setup - unsigned int indices[18]; - indices[0] = 0; indices[1] = 2; indices[2] = 1; - indices[3] = 0; indices[4] = 3; indices[5] = 2; - indices[6] = 0; indices[7] = 4; indices[8] = 3; - indices[9] = 0; indices[10] = 5; indices[11] = 4; - indices[12] = 0; indices[13] = 6; indices[14] = 5; - indices[15] = 0; indices[16] = 1; indices[17] = 6; + unsigned int indices[6]; + indices[0] = 1; + indices[1] = 6; + indices[2] = 2; + indices[3] = 5; + indices[4] = 3; + indices[5] = 4; glGenBuffers(1, &the_hexagon->ebo); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, the_hexagon->ebo); - glBufferData(GL_ELEMENT_ARRAY_BUFFER, 6*3 * sizeof(unsigned int), indices, GL_STATIC_DRAW); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, 6 * sizeof(unsigned int), indices, GL_STATIC_DRAW); - glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)0); glEnableVertexAttribArray(0); + glEnableVertexAttribArray(1); + + // vertex position data + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 5, (void*)0); + + // uv data + glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 5, (void*)(sizeof(float) * 3)); + glBindBuffer(GL_ARRAY_BUFFER, 0); glBindVertexArray(0); } @@ -503,6 +585,7 @@ int main([[maybe_unused]]int argc, [[maybe_unused]]char **argv) glfwMakeContextCurrent(window); glfwSwapInterval(1); glfwSetScrollCallback(window, scroll_callback); + glfwSetKeyCallback(window, key_callback); if (!gladLoadGL()) { @@ -517,6 +600,9 @@ int main([[maybe_unused]]int argc, [[maybe_unused]]char **argv) fprintf(stdout, "Compiled using libPNG version %s\n", PNG_LIBPNG_VER_STRING); fprintf(stdout, "Runtime using libPNG version %s\n", png_libpng_ver); + glEnable(GL_DEBUG_OUTPUT); + glDebugMessageCallback(ogl_debugcb, nullptr); + // font library initialization FT_Library ft; @@ -617,7 +703,7 @@ int main([[maybe_unused]]int argc, [[maybe_unused]]char **argv) double cursor_y; double cursor_x_scaled; double cursor_y_scaled; - camera_t the_camera; + bool mouse_pressed; bool right_mouse_pressed; bool mouse_over_gui; @@ -653,18 +739,39 @@ int main([[maybe_unused]]int argc, [[maybe_unused]]char **argv) { TIME_BLOCK(input_handling); /* Input handling */ - if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS) + glfwPollEvents(); + + if (frame_input.keys[GLFW_KEY_W] == GLFW_PRESS) + { the_camera.position.y += 0.1; - if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS) + dirty_window = true; + } + if (frame_input.keys[GLFW_KEY_S] == GLFW_PRESS) + { the_camera.position.y -= 0.1; - if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS) + dirty_window = true; + } + if (frame_input.keys[GLFW_KEY_A] == GLFW_PRESS) + { the_camera.position.x -= 0.1; - if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS) + dirty_window = true; + } + if (frame_input.keys[GLFW_KEY_D] == GLFW_PRESS) + { the_camera.position.x += 0.1; - if (glfwGetKey(window, GLFW_KEY_R) == GLFW_PRESS) + dirty_window = true; + } + if (frame_input.keys[GLFW_KEY_R] == GLFW_PRESS) + { the_camera.size -= glm::vec2(0.1); - if (glfwGetKey(window, GLFW_KEY_F) == GLFW_PRESS) + dirty_window = true; + } + if (frame_input.keys[GLFW_KEY_F] == GLFW_PRESS) + { the_camera.size += glm::vec2(0.1); + dirty_window = true; + } + if (mouse_scroll > 0.0) { the_camera.size -= glm::vec2(0.1); @@ -711,9 +818,14 @@ int main([[maybe_unused]]int argc, [[maybe_unused]]char **argv) glm::mat4 proj_matrix; glm::vec2 cursor_world; + static char image_path[PATH_MAX]; + static int grid_rows = grid.rows; + static int grid_columns = grid.columns; + /* Rendering */ { TIME_BLOCK(hex_render); + glClearColor(0.1f, 0.2f, 0.3f, 1.0f); glClear(GL_COLOR_BUFFER_BIT); @@ -771,7 +883,7 @@ int main([[maybe_unused]]int argc, [[maybe_unused]]char **argv) glBindBuffer(GL_ARRAY_BUFFER, grid.hexes[idx].vbo); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, grid.hexes[idx].ebo); glEnable(GL_CULL_FACE); - glDrawElements(GL_TRIANGLES, 3*6, GL_UNSIGNED_INT, 0); + glDrawElements(GL_TRIANGLE_STRIP, 6, GL_UNSIGNED_INT, 0); glDisable(GL_CULL_FACE); glBindVertexArray(0); } @@ -827,17 +939,12 @@ int main([[maybe_unused]]int argc, [[maybe_unused]]char **argv) } glDisable(GL_BLEND); - glfwPollEvents(); - - static int grid_rows = grid.rows; - static int grid_columns = grid.columns; - static char image_path[PATH_MAX]; if (grid_rows != grid.rows || grid_columns != grid.columns) { create_grid(&grid, grid_rows, grid_columns); } - + // Start the Dear ImGui frame { TIME_BLOCK(gui_render); @@ -901,6 +1008,7 @@ int main([[maybe_unused]]int argc, [[maybe_unused]]char **argv) } glfwSwapBuffers(window); + dirty_window = false; } // Cleanup diff --git a/notes.org b/notes.org index 7a55936..bb85968 100644 --- a/notes.org +++ b/notes.org @@ -2,3 +2,4 @@ - Text rendering optimized yet still taking too much time. Using atlas with GL_TEXTURE_ARRAY - All vertex data lives in the CPU for each hex too - Need UI to modify hex appeareance (show texture from file and then apply it to hex) +- Each hex should be a triangle strip or a triangle fan, not a combo of 6 different triangles diff --git a/shaders/hex.vert b/shaders/hex.vert index dedbc5b..0443488 100644 --- a/shaders/hex.vert +++ b/shaders/hex.vert @@ -1,5 +1,6 @@ #version 330 core layout (location = 0) in vec3 pos; +layout (location = 1) in vec2 uv; uniform mat4 model; uniform mat4 view; uniform mat4 proj;