#include "GLFW/glfw3.h" #include "GLProgramLoader.hh" #include #include #include #include #include #include // This has to come last. #define GLAD_GL_IMPLEMENTATION #include #include #include #include static void dbg_log(const char* str) { std::cout << str << std::endl; } 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); } } #define VERTEX_SHADER_LOCATION "shaders/shader.vert" #define FRAGMENT_SHADER_LOCATION "shaders/shader.frag" GLuint g_program_id = 0; static GLuint translate_unif; static GLuint rotate_unif; static void init_shaders() { dbg_log("Initialising shaders"); const std::vector> shaders = { {GL_VERTEX_SHADER, VERTEX_SHADER_LOCATION}, {GL_FRAGMENT_SHADER, FRAGMENT_SHADER_LOCATION}, }; try { g_program_id = compile_and_link_program(shaders); } catch (GLProgramException e) { std::cerr << e.what() << std::endl; } catch (...) { std::cerr << "Unexpected exception while compiling shaders." << std::endl; } glUseProgram(g_program_id); translate_unif = glGetUniformLocation(g_program_id, "world_pos"); rotate_unif = glGetUniformLocation(g_program_id, "rotation"); } class Triangle { public: GLfloat data[6]; float m_pos_x; float m_pos_y; float rotation = 0.2f; Triangle(std::array verts) { for (std::size_t i = 0; i < 3; 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 Triangle o1(std::array({ {0.0f, 0.0f}, {0.5f, 0.0f}, {0.5f, 0.5f} })); // Do the work of initialising opengl so we can draw stuff static void init_opengl() { dbg_log("Initialising opengl"); // 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(Triangle::data), o1.data, GL_STATIC_DRAW); glVertexAttribPointer(vertex_data_position, 2, GL_FLOAT, GL_FALSE, 0, NULL); glEnableVertexAttribArray(vertex_data_position); init_shaders(); } int main() { dbg_log("Initialising glfw"); // Initialise GLFW if (!glfwInit()) { exit(EXIT_FAILURE); } glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); // Create our context GLFWwindow *w = glfwCreateWindow(640, 480, "Test", NULL, NULL); if (!w) { glfwTerminate(); exit(EXIT_FAILURE); } glfwMakeContextCurrent(w); glfwSwapInterval(1); // Essentially vsync gladLoadGL(glfwGetProcAddress); // Load openGL using glfw // Set up the key handler glfwSetKeyCallback(w, key_callback); init_opengl(); // Main Loop while(!glfwWindowShouldClose(w)) { float time = glfwGetTime(); 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, 3); glfwSwapBuffers(w); glfwPollEvents(); } glfwDestroyWindow(w); glfwTerminate(); exit(EXIT_SUCCESS); }