#include #define GLFW_INCLUDE_NONE #include #include #include #include #include #include "hex_math.h" #define log_err(str, ...) do { fprintf(stderr, "[ERROR] (%s:%d): " str "\n", __FILE__, __LINE__, ##__VA_ARGS__); } while (0) #define log_debug(str, ...) do { fprintf(stderr, "[DEBUG] (%s:%d): " str "\n", __FILE__, __LINE__, ##__VA_ARGS__); } while (0) char *read_entire_file(char *path) { FILE *f = fopen(path, "rb"); size_t length = 0; char *buf = NULL; if (f) { fseek(f, 0, SEEK_END); length = ftell(f); fseek(f, 0, SEEK_SET); if (length) { buf = malloc(length + 1); fread(buf, 1, length, f); buf[length] = '\0'; } } return buf; } static void glfw_error_callback(int errcode, const char *description) { fprintf(stderr, "[GLFW ERROR][ERRCODE %d] %s\n", errcode, description); } void set_uniform(GLuint program_id, const char *name, vec4f value) { GLint location = glGetUniformLocation(program_id, name); glUniform4f(location, value.x, value.y, value.z, value.w); } int main(void) { GLFWwindow *window; if (!glfwInit()) return -1; glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); window = glfwCreateWindow(800, 800, "Hello Hex", NULL, NULL); if (!window) return -1; glfwMakeContextCurrent(window); if (glewInit() != GLEW_OK) return -1; glfwSetErrorCallback(glfw_error_callback); // build and compile our shader program // ------------------------------------ char * vertexShaderSource = read_entire_file("shaders/vertex.glsl"); char *fragmentShaderSource = read_entire_file("shaders/fragment.glsl"); // vertex shader unsigned int vertex_shader = glCreateShader(GL_VERTEX_SHADER); glShaderSource(vertex_shader, 1, &vertexShaderSource, NULL); glCompileShader(vertex_shader); // check for shader compile errors int success; char infoLog[512]; glGetShaderiv(vertex_shader, GL_COMPILE_STATUS, &success); if (!success) { glGetShaderInfoLog(vertex_shader, 512, NULL, infoLog); fprintf(stderr, "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n %s\n", infoLog); } // fragment shader unsigned int fragment_shader = glCreateShader(GL_FRAGMENT_SHADER); glShaderSource(fragment_shader, 1, &fragmentShaderSource, NULL); glCompileShader(fragment_shader); // check for shader compile errors if (!success) { glGetShaderInfoLog(fragment_shader, 512, NULL, infoLog); fprintf(stderr, "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n %s\n", infoLog); } // link shaders unsigned int shader_program = glCreateProgram(); glAttachShader(shader_program, vertex_shader); glAttachShader(shader_program, fragment_shader); glLinkProgram(shader_program); // check for linking errors glGetProgramiv(shader_program, GL_LINK_STATUS, &success); if (!success) { glGetShaderInfoLog(shader_program, 512, NULL, infoLog); fprintf(stderr, "ERROR::SHADER::PROGRAM::COMPILATION_FAILED\n %s\n", infoLog); } glDeleteShader(vertex_shader); glDeleteShader(fragment_shader); vec4f background_color; background_color.r = 0.1f; background_color.g = 0.2f; background_color.b = 0.3f; background_color.a = 1.0f; hexgrid_t grid; grid.rows = 10; grid.columns = 10; grid.hexes = calloc(1, sizeof(hex_t) * grid.rows * grid.columns); // Scale of hexagon relative to screen. A 1:1 hexagon would reach the entire horizontal space float scale = 1.0f / 5.0f; for (size_t i = 0; i < grid.columns; ++i) { for (size_t j = 0; j < grid.rows; ++j) { // Offset the X and Y coordinates of adjacent hexagons so they do not cut each other float offset = 0.0f; if (j % 2) offset = sint(1.0f/6); grid.hexes[i*grid.rows+j].position.x = (0.0f + j*(1 + cost(1.0f/6))); grid.hexes[i*grid.rows+j].position.y = (0.0f + i*(sint(1.0f/6))*2.0f) + offset; grid.hexes[i*grid.rows+j].position.z = 0.0f; grid.hexes[i*grid.rows+j].position.w = 1.0f; fprintf(stdout, "Position of hex %ld %ld is %f %f\n", i, j, grid.hexes[i*grid.rows+j].position.x, grid.hexes[i*grid.rows+j].position.y); } } // Get OpenGL objects for (size_t i = 0; i < grid.rows * grid.columns; ++i) { hex_t *hex = &grid.hexes[i]; // VAO setup glGenVertexArrays(1, &hex->vao); glBindVertexArray(hex->vao); // VBO setup float *vertices = hex->vertices; vertices[0] = hex->position.x * scale; vertices[1] = hex->position.y * scale; vertices[2] = hex->position.z; log_debug("Adding vertex %f %f %f", vertices[0], vertices[1], vertices[2]); for (int j = 1; j < 7; ++j) { vertices[j*3] = (hex->position.x + cost((j-1)/6.0f)) * scale; vertices[j*3+1] = (hex->position.y + sint((j-1)/6.0f)) * scale; vertices[j*3+2] = hex->position.z; log_debug("Adding vertex %f %f %f", vertices[j*3], vertices[j*3+1], vertices[j*3+2]); } glGenBuffers(1,&hex->vbo); glBindBuffer(GL_ARRAY_BUFFER, hex->vbo); glBufferData(GL_ARRAY_BUFFER, 7*3*sizeof(float), vertices, GL_STATIC_DRAW); // EBO setup unsigned int *indices = hex->indices; indices[0] = 0; indices[1] = 1; indices[2] = 2; indices[3] = 0; indices[4] = 2; indices[5] = 3; indices[6] = 0; indices[7] = 3; indices[8] = 4; indices[9] = 0; indices[10] = 4; indices[11] = 5; indices[12] = 0; indices[13] = 5; indices[14] = 6; indices[15] = 0; indices[16] = 6; indices[17] = 1; glGenBuffers(1,&hex->ebo); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, hex->ebo); glBufferData(GL_ELEMENT_ARRAY_BUFFER, 6*3 * sizeof(unsigned int), indices, GL_STATIC_DRAW); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)0); glEnableVertexAttribArray(0); } //glBindVertexArray(0); //glBindBuffer(GL_ARRAY_BUFFER, 0); //glBindVertexArray(0); while (!glfwWindowShouldClose(window)) { int width, height; glfwGetFramebufferSize(window, &width, &height); glViewport(0, 0, width, height); glClearColor(background_color.r, background_color.g, background_color.b, 1.0f); glClear(GL_COLOR_BUFFER_BIT); glUseProgram(shader_program); //glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); for (size_t i = 0; i < grid.rows * grid.columns; ++i) { // Set uniforms vec4f hex_color; hex_color.r = (float)i / (grid.rows * grid.columns); hex_color.g = (float)i / (grid.rows * grid.columns); hex_color.b = (float)i / (grid.rows * grid.columns); hex_color.a = 1.0f; set_uniform(shader_program, "uniform_color", hex_color); glBindVertexArray(grid.hexes[i].vao); //log_debug("Binding VAO %d VBO %d EBO %d", grid.hexes[i].vao, grid.hexes[i].vbo, grid.hexes[i].ebo); glBindBuffer(GL_ARRAY_BUFFER, grid.hexes[i].vbo); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, grid.hexes[i].ebo); glDrawElements(GL_TRIANGLES, 3*6, GL_UNSIGNED_INT, 0); } glfwPollEvents(); glfwSwapBuffers(window); } return 0; }