diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..c47a1f5 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "src/vendor/glm"] + path = src/vendor/glm + url = https://github.com/g-truc/glm diff --git a/src/main.cpp b/src/main.cpp index 1cd5b34..c4c0321 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,11 +1,24 @@ #include #include +#include #include "vendor/glad/glad.h" +#include "vendor/glm/glm/ext/matrix_transform.hpp" #define GLFW_INCLUDE_NONE #include #define QOI_IMPLEMENTATION #include "vendor/qoi.h" +#include "vendor/glm/glm/vec3.hpp" +#include "vendor/glm/glm/vec4.hpp" +#include "vendor/glm/glm/trigonometric.hpp" +#include "vendor/glm/glm/geometric.hpp" +#include "vendor/glm/glm/mat4x4.hpp" +#include "vendor/glm/glm/gtc/type_ptr.hpp" + + +std::function framebuffer_size_callback = nullptr; +std::function cursor_position_callback = nullptr; + unsigned int create_shader(unsigned int type, const char **source) { unsigned int shader = glCreateShader(type); @@ -63,11 +76,6 @@ unsigned int create_program(const char *vertex_shader_source, const char *fragme return program; } -void framebuffer_size_callback(GLFWwindow *window, int width, int height) -{ - glViewport(0, 0, width, height); -} - int main() { qoi_desc fish_desc; @@ -91,33 +99,81 @@ int main() gladLoadGL(); glfwSwapInterval(1); - glfwSetFramebufferSizeCallback(window, framebuffer_size_callback); + glfwSetFramebufferSizeCallback(window, [](GLFWwindow *_, int width, int height) { + if (framebuffer_size_callback) { + framebuffer_size_callback(width, height); + } + }); + glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED); + glfwSetCursorPosCallback(window, [](GLFWwindow *_, double x, double y) { + if (cursor_position_callback) { + cursor_position_callback(x, y); + } + }); + + glEnable(GL_DEPTH_TEST); float verts[] = { - // position // color // texture coords - 0.0f, 0.5f, 1.0f, 0.0f, 0.0f, 0.5f, 1.0f, - -0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, - 0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, + -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, + 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, + 0.5f, 0.5f, -0.5f, 1.0f, 1.0f, + 0.5f, 0.5f, -0.5f, 1.0f, 1.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, + -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, + + -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 1.0f, 1.0f, + 0.5f, 0.5f, 0.5f, 1.0f, 1.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 1.0f, + -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, + + -0.5f, 0.5f, 0.5f, 1.0f, 0.0f, + -0.5f, 0.5f, -0.5f, 1.0f, 1.0f, + -0.5f, -0.5f, -0.5f, 0.0f, 1.0f, + -0.5f, -0.5f, -0.5f, 0.0f, 1.0f, + -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, + -0.5f, 0.5f, 0.5f, 1.0f, 0.0f, + + 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, + 0.5f, 0.5f, -0.5f, 1.0f, 1.0f, + 0.5f, -0.5f, -0.5f, 0.0f, 1.0f, + 0.5f, -0.5f, -0.5f, 0.0f, 1.0f, + 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, + + -0.5f, -0.5f, -0.5f, 0.0f, 1.0f, + 0.5f, -0.5f, -0.5f, 1.0f, 1.0f, + 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, + -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, + -0.5f, -0.5f, -0.5f, 0.0f, 1.0f, + + -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, + 0.5f, 0.5f, -0.5f, 1.0f, 1.0f, + 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 1.0f }; static const char *vertex_shader_source = "" "#version 330 core\n" - "layout (location = 0) in vec2 aPos;\n" - "layout (location = 1) in vec3 aColor;\n" - "layout (location = 2) in vec2 aTexCoord;\n" - "out vec3 fragColor;\n" + "layout (location = 0) in vec3 aPos;\n" + "layout (location = 1) in vec2 aTexCoord;\n" "out vec2 TexCoord;\n" + "uniform mat4 model;\n" + "uniform mat4 view;\n" + "uniform mat4 projection;\n" "void main()\n" "{\n" - " gl_Position = vec4(aPos.x, aPos.y, 0.0, 1.0);\n" - " fragColor = aColor;\n" + " gl_Position = projection * view * model * vec4(aPos, 1.0);\n" " TexCoord = aTexCoord;\n" "}\0"; static const char *fragment_shader_source = "" "#version 330 core\n" - "in vec3 fragColor;\n" "in vec2 TexCoord;\n" "out vec4 FragColor;\n" "uniform sampler2D tex;\n" @@ -143,26 +199,104 @@ int main() glBindBuffer(GL_ARRAY_BUFFER, buffer); glBufferData(GL_ARRAY_BUFFER, sizeof(verts), &verts, GL_STATIC_DRAW); - // 2D position - glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 7 * sizeof(float), (const void*)0); + // position + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (const void*)0); glEnableVertexAttribArray(0); - // RGB color - glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 7 * sizeof(float), (const void*)(2 * sizeof(float))); + // texture coords + glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (const void*)(3 * sizeof(float))); glEnableVertexAttribArray(1); - // texture coords - glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 7 * sizeof(float), (const void*)(5 * sizeof(float))); - glEnableVertexAttribArray(2); + glm::mat4 projection = glm::mat4(1.0f); + + glm::vec3 camera_position = glm::vec3(0.0f, 0.0f, 3.0f); + glm::vec3 camera_front = glm::vec3(0.0f, 0.0f, -1.0f); + glm::vec3 camera_up = glm::vec3(0.0f, 1.0f, 0.0f); + glm::vec3 camera_down = glm::vec3(0.0f, -1.0f, 0.0f); + + double camera_pitch = 0.0f; + double camera_yaw = 0.0f; + double last_mouse_x, last_mouse_y = 0.0f; + bool mouse_moved_once = false; + + framebuffer_size_callback = [&projection, program](int width, int height) { + projection = glm::perspective(glm::radians(45.0f), (float)width / (float)height, 0.1f, 100.0f); + glUniformMatrix4fv(glGetUniformLocation(program, "projection"), 1, GL_FALSE, glm::value_ptr(projection)); + glViewport(0, 0, width, height); + }; + + cursor_position_callback = [&mouse_moved_once, &last_mouse_x, &last_mouse_y, &camera_pitch, &camera_yaw, &camera_front](double x, double y) { + if (!mouse_moved_once) { + mouse_moved_once = true; + last_mouse_x = x; + last_mouse_y = y; + } + + double x_offset = (x - last_mouse_x) * 0.15; + double y_offset = (last_mouse_y - y) * 0.15; + camera_yaw += x_offset; + camera_pitch += y_offset; + + if (camera_pitch > 89.0f) + camera_pitch = 89.0f; + if (camera_pitch < -89.0f) + camera_pitch = -89.0f; + + double pitch_factor = cos(glm::radians(camera_pitch)); + camera_front = (glm::vec3){ + cos(glm::radians(camera_yaw)) * pitch_factor, + sin(glm::radians(camera_pitch)), + sin(glm::radians(camera_yaw)) * pitch_factor + }; + + last_mouse_x = x; + last_mouse_y = y; + }; + + float delta_time = 0.0f; + float last_frame_time = 0.0f; while (!glfwWindowShouldClose(window)) { + float current_frame_time = glfwGetTime(); + delta_time = current_frame_time - last_frame_time; + last_frame_time = current_frame_time; + + const float camera_speed = 2.0f * delta_time; // adjust accordingly + if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS) { + camera_position += camera_speed * camera_front; + } + if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS) { + camera_position -= camera_speed * camera_front; + } + if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS) { + camera_position -= glm::normalize(glm::cross(camera_front, camera_up)) * camera_speed; + } + if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS) { + camera_position += glm::normalize(glm::cross(camera_front, camera_up)) * camera_speed; + } + if (glfwGetKey(window, GLFW_KEY_E) == GLFW_PRESS) { + camera_position += camera_speed * camera_up; + } + if (glfwGetKey(window, GLFW_KEY_Q) == GLFW_PRESS) { + camera_position += camera_speed * camera_down; + } + glClearColor(0.5, 0.5, 0.5, 1.0); - glClear(GL_COLOR_BUFFER_BIT); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glm::mat4 view = glm::lookAt(camera_position, camera_position + camera_front, camera_up); glUseProgram(program); + glUniformMatrix4fv(glGetUniformLocation(program, "view"), 1, GL_FALSE, glm::value_ptr(view)); + glBindTexture(GL_TEXTURE_2D, texture); glBindVertexArray(vertex_array); - glDrawArrays(GL_TRIANGLES, 0, 3); + + for (int i = 0; i < 12; i++) { + glm::mat4 model = glm::translate(glm::mat4(1.0), glm::vec3(2 * i, 0.0f, 0.0f)); + glUniformMatrix4fv(glGetUniformLocation(program, "model"), 1, GL_FALSE, glm::value_ptr(model)); + glDrawArrays(GL_TRIANGLES, 0, 36); + } glfwSwapBuffers(window); glfwPollEvents(); diff --git a/src/vendor/glm b/src/vendor/glm new file mode 160000 index 0000000..5c46b9c --- /dev/null +++ b/src/vendor/glm @@ -0,0 +1 @@ +Subproject commit 5c46b9c07008ae65cb81ab79cd677ecc1934b903