diff --git a/.gitignore b/.gitignore index c795b05..9785597 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ -build \ No newline at end of file +build +.cache diff --git a/CMakeLists.txt b/CMakeLists.txt index fc6dc08..65fe7a5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,7 +3,8 @@ cmake_minimum_required(VERSION 3.21) project(Exponent CXX) set(CMAKE_CXX_STANDARD 20) +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address -fsanitize=undefined") add_subdirectory(glfw) add_subdirectory(src) -add_subdirectory(glm) \ No newline at end of file +add_subdirectory(glm) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 0f715ef..305171e 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -2,6 +2,8 @@ add_executable(Exponent main.cc GLProgramLoader.cc stb_image.cc + Quad.cc + Mesh.cc ) target_link_libraries(Exponent PUBLIC glfw glm::glm) @@ -10,4 +12,4 @@ target_include_directories(Exponent PUBLIC ${CMAKE_SOURCE_DIR}/include) target_compile_definitions(Exponent PRIVATE GLFW_INCLUDE_NONE) file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/shaders/shader.frag" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/shaders/") -file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/shaders/shader.vert" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/shaders/") \ No newline at end of file +file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/shaders/shader.vert" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/shaders/") diff --git a/src/Mesh.cc b/src/Mesh.cc new file mode 100644 index 0000000..f0ec28c --- /dev/null +++ b/src/Mesh.cc @@ -0,0 +1,22 @@ +#include "Mesh.hh" + +#include +#include +#include + +Mesh::Mesh(std::span verts) { + glGenVertexArrays(1, &vao); + glBindVertexArray(vao); + + glGenBuffers(1, &vbo); + glBindBuffer(GL_ARRAY_BUFFER, vbo); + glBufferData(GL_ARRAY_BUFFER, verts.size() * sizeof(glm::vec2), verts.data(), GL_STATIC_DRAW); + // TODO: Handle if the buffer can't be allocated + + glVertexAttribPointer(vertex_data_position, 2, GL_FLOAT, GL_FALSE, 0, NULL); + glEnableVertexAttribArray(vertex_data_position); +} + +Mesh::~Mesh() { + glDeleteVertexArrays(1, &vao); +} diff --git a/src/Mesh.hh b/src/Mesh.hh new file mode 100644 index 0000000..f453a9d --- /dev/null +++ b/src/Mesh.hh @@ -0,0 +1,25 @@ +#pragma once + +#include +#include +#include + +class Mesh { + const static GLuint vertex_data_position = 0; + + private: +// std::array m_verts; + GLuint vbo; + GLuint vao; + + public: + Mesh(std::span verts); + + ~Mesh(); + + Mesh(Mesh &m) = delete; + + void bindVAO() { + glBindVertexArray(vao); + } +}; diff --git a/src/Quad.cc b/src/Quad.cc new file mode 100644 index 0000000..7d1d24e --- /dev/null +++ b/src/Quad.cc @@ -0,0 +1,29 @@ +#include "Quad.hh" + +#include +#include + +Quad::Quad(std::span verts, const Uniform &uniform_data) + : m_mesh(verts) { + m_uniform_data.rotation = uniform_data.rotation; + m_uniform_data.world_pos = uniform_data.world_pos; +} + +glm::vec2 Quad::get_position_vector() { + return glm::vec2(m_pos_x, m_pos_y); +} + +void Quad::draw(){ + float time = glfwGetTime(); + + m_rotation = 2*sin(time); + + m_pos_x = 0.25*sin(time); + m_pos_y = 0.5*cos(time); + + glUniform2f(m_uniform_data.world_pos, m_pos_x, m_pos_y); + glUniform1f(m_uniform_data.rotation, m_rotation); + + m_mesh.bindVAO(); + glDrawArrays(GL_TRIANGLES, 0, 6); +} diff --git a/src/Quad.hh b/src/Quad.hh new file mode 100644 index 0000000..065e931 --- /dev/null +++ b/src/Quad.hh @@ -0,0 +1,24 @@ +#pragma once + +#include "Mesh.hh" +#include "src/Uniform.hh" + +#include +#include + +class Quad { +public: + Uniform m_uniform_data; + Mesh m_mesh; + float m_pos_x = 0; + float m_pos_y = 0.0f; + float m_rotation = 0.0f; + + Quad(std::span verts, const Uniform &uniform_data); + + Quad(Quad &q) = delete; + + glm::vec2 get_position_vector(); + + void draw(); +}; diff --git a/src/Uniform.hh b/src/Uniform.hh new file mode 100644 index 0000000..6d02e3c --- /dev/null +++ b/src/Uniform.hh @@ -0,0 +1,8 @@ +#pragma once + +#include + +struct Uniform { + GLuint world_pos; + GLuint rotation; +}; diff --git a/src/main.cc b/src/main.cc index ca711f4..e3d87bc 100644 --- a/src/main.cc +++ b/src/main.cc @@ -2,12 +2,16 @@ #include "GLProgramLoader.hh" +#include "Quad.hh" + #include #include #include #include #include +#include + #include // This has to come last. @@ -24,6 +28,20 @@ static void dbg_log(const char* str) { std::cout << str << std::endl; } +void GLAPIENTRY +MessageCallback( GLenum source, + GLenum type, + GLuint id, + GLenum severity, + GLsizei length, + const GLchar* message, + const void* userParam ) +{ + fprintf( stderr, "GL CALLBACK: %s type = 0x%x, severity = 0x%x, message = \n\t%s\n", + ( type == GL_DEBUG_TYPE_ERROR ? "** GL ERROR **" : "" ), + type, severity, message ); +} + static void key_callback(GLFWwindow *w, int key, int scancode, int action, int mods) { if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS) { glfwSetWindowShouldClose(w, GL_TRUE); @@ -60,30 +78,13 @@ static void init_shaders() { rotate_unif = glGetUniformLocation(g_program_id, "rotation"); } -class Quad { -public: - GLfloat data[12]; - float m_pos_x = 0; - float m_pos_y = 0; - float rotation = 0.0f; - - Quad(std::array verts) { - for (std::size_t i = 0; i < 6; i++) { - data[i*2] = verts[i][0]; - data[i*2+1] = verts[i][1]; - } - } - - std::array get_world_projection() { - return std::array({m_pos_x, m_pos_y}); - } -}; - static GLuint vertex_buf[2]; static GLuint array_buf[2]; static const GLuint vertex_data_position = 0; -static Quad o1(std::array({ +static Quad *o1; + +static std::array verts({ // Tri 2 {0.0f, 0.0f}, {0.5f, 0.0f}, @@ -92,24 +93,22 @@ static Quad o1(std::array({ {0.0f, 0.0f}, {0.5f, 0.5f}, {0.0f, 0.5f}, - })); +}); // Do the work of initialising opengl so we can draw stuff static void init_opengl() { dbg_log("Initialising opengl"); + + // During init, enable debug output + glEnable ( GL_DEBUG_OUTPUT ); + glDebugMessageCallback( MessageCallback, 0 ); + // Configure the context's capabilities glClearColor(0.0, 0.0, 0.0, 1.0); - glGenVertexArrays(2, array_buf); - glBindVertexArray(array_buf[0]); - - glGenBuffers(2, vertex_buf); - glBindBuffer(GL_ARRAY_BUFFER, vertex_buf[0]); - glBufferData(GL_ARRAY_BUFFER, sizeof(Quad::data), o1.data, GL_STATIC_DRAW); - glVertexAttribPointer(vertex_data_position, 2, GL_FLOAT, GL_FALSE, 0, NULL); - glEnableVertexAttribArray(vertex_data_position); - init_shaders(); + + o1 = new Quad(std::span(verts), (Uniform){.world_pos = translate_unif, .rotation = rotate_unif}); } int main() { @@ -140,26 +139,16 @@ int main() { // Main Loop while(!glfwWindowShouldClose(w)) { - float time = glfwGetTime(); - - o1.rotation = 2*sin(time); - - o1.m_pos_x = 0.25*sin(time); - o1.m_pos_y = 0.5*cos(time); - glClear(GL_COLOR_BUFFER_BIT); - - glUniform2fv(translate_unif, 1, o1.get_world_projection().data()); - glUniform1f(rotate_unif, o1.rotation); - - glBindVertexArray(array_buf[0]); - glDrawArrays(GL_TRIANGLES, 0, 6); + + o1->draw(); glfwSwapBuffers(w); glfwPollEvents(); } + delete(o1); glfwDestroyWindow(w); glfwTerminate(); exit(EXIT_SUCCESS); -} \ No newline at end of file +}