Untitled
unknown
c_cpp
9 months ago
9.4 kB
3
Indexable
#include "imgui.h" #include "backends/imgui_impl_glfw.h" #include "backends/imgui_impl_opengl3.h" #include "glad/glad.h" #include "GLFW/glfw3.h" #include "glm/ext.hpp" #include "config.h" #include <array> #include <fstream> #include <iostream> #include <optional> cg::Window _window; cg::Camera _camera; constexpr auto window_width = 1280; constexpr auto window_height = 720; constexpr auto window_title = "OpenGL"; constexpr auto gl_major = 4; constexpr auto gl_minor = 6; constexpr auto glsl_version = "#version 460"; constexpr auto clear_color = glm::vec4(0.45f, 0.55f, 0.60f, 0.90f); static unsigned int gl_print_error(void) { unsigned int error = glGetError(); if (error == 0) std::cout << "No GL errors." << std::endl; else std::cerr << "GL Error: " << error << std::endl; return error; } static void glfw_error_callback(int error, const char* description) { std::cerr << "GLFW Error: " << error << " " << description << std::endl; } static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode) { switch (key) { case GLFW_KEY_ESCAPE: glfwSetWindowShouldClose(window, true); break; default: break; } } GLFWwindow* init_window(void) { glfwSetErrorCallback(glfw_error_callback); if (glfwInit() == GLFW_FALSE) return nullptr; /* * Required for Apple. */ glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, gl_major); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, gl_minor); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); /* * Create the graphics context and make it current. */ GLFWwindow* const window = glfwCreateWindow(window_width, window_height, window_title, nullptr, nullptr); if (window == nullptr) return nullptr; glfwMakeContextCurrent(window); /* * Set event callbacks. */ glfwSetKeyCallback(window, key_callback); /* * Load OpenGL with GLAD. * Crashes if GL functions are called without this. */ gladLoadGL(); return window; } static void init_ImGui(GLFWwindow* window) { /* * ImGui context. */ IMGUI_CHECKVERSION(); ImGui::CreateContext(); ImGuiIO& io = ImGui::GetIO(); io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; /* * ImGui style. */ ImGui::StyleColorsDark(); ImGui_ImplGlfw_InitForOpenGL(window, true); ImGui_ImplOpenGL3_Init(glsl_version); } static void reset_viewport(GLFWwindow* window) { int display_w = 0; int display_h = 0; glfwGetFramebufferSize(window, &display_w, &display_h); glViewport(0, 0, display_w, display_h); } static void clear(void) { glClearColor(clear_color.x * clear_color.w, clear_color.y * clear_color.w, clear_color.z * clear_color.w, clear_color.w); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); } static void render_ImGui(void) { bool show_demo_window = true; ImGui_ImplOpenGL3_NewFrame(); ImGui_ImplGlfw_NewFrame(); ImGui::NewFrame(); if (show_demo_window == true) { ImGui::ShowDemoWindow(&show_demo_window); } ImGui::Render(); } static void display_ImGui(void) { ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData()); } static void cleanup_ImGui(void) { ImGui_ImplOpenGL3_Shutdown(); ImGui_ImplGlfw_Shutdown(); ImGui::DestroyContext(); } static void cleanup_window(GLFWwindow* window) { glfwDestroyWindow(window); glfwTerminate(); } static std::optional<std::string> read_shader(const std::string& path) { std::string result; std::ifstream in(path, std::ios::in | std::ios::binary); if (in.good() == false) return std::nullopt; in.seekg(0, std::ios::end); size_t size = in.tellg(); if (size == -1) return std::nullopt; result.resize(size); in.seekg(0, std::ios::beg); in.read(&result[0], size); return result; } /* * Copy the shader source string here just in case. * c_str will point to garbage if a string reference goes out of scope. */ static unsigned int compile_shader(const std::string shader_source, unsigned int type) { unsigned int shader = glCreateShader(type); const char* c_str = shader_source.c_str(); glShaderSource(shader, 1, &c_str, nullptr); glCompileShader(shader); /* * Compile error checking. */ int is_compiled = 0; glGetShaderiv(shader, GL_COMPILE_STATUS, &is_compiled); if (is_compiled == 0) { std::string log; int length = 0; glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &length); log.resize(length); glGetShaderInfoLog(shader, length, nullptr, &log[0]); std::string type_s = type == GL_VERTEX_SHADER ? "vertex" : "fragment"; std::cerr << "Failed to compile " << type_s << " shader." << std::endl; std::cerr << log << std::endl; glDeleteShader(shader); return 0; } return shader; } static unsigned int create_shader(const std::string& vertex_source, const std::string& fragment_source) { unsigned int program = glCreateProgram(); unsigned int vertex_shader = compile_shader(vertex_source, GL_VERTEX_SHADER); if (vertex_shader == 0) return 0; unsigned int fragment_shader = compile_shader(fragment_source, GL_FRAGMENT_SHADER); if (fragment_shader == 0) return 0; glAttachShader(program, vertex_shader); glAttachShader(program, fragment_shader); glLinkProgram(program); glValidateProgram(program); glDeleteShader(vertex_shader); glDeleteShader(fragment_shader); glDetachShader(program, vertex_shader); glDetachShader(program, fragment_shader); return program; } static void init(void) { /* * Enable z-buffer. */ glEnable(GL_DEPTH_TEST); std::array vertices { -0.5f,-0.5f,-0.5f, -0.5f,-0.5f, 0.5f, -0.5f, 0.5f, 0.5f, 0.5f, 0.5f,-0.5f, -0.5f,-0.5f,-0.5f, -0.5f, 0.5f,-0.5f, 0.5f,-0.5f, 0.5f, -0.5f,-0.5f,-0.5f, 0.5f,-0.5f,-0.5f, 0.5f, 0.5f,-0.5f, 0.5f,-0.5f,-0.5f, -0.5f,-0.5f,-0.5f, -0.5f,-0.5f,-0.5f, -0.5f, 0.5f, 0.5f, -0.5f, 0.5f,-0.5f, 0.5f,-0.5f, 0.5f, -0.5f,-0.5f, 0.5f, -0.5f,-0.5f,-0.5f, -0.5f, 0.5f, 0.5f, -0.5f,-0.5f, 0.5f, 0.5f,-0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f,-0.5f,-0.5f, 0.5f, 0.5f,-0.5f, 0.5f,-0.5f,-0.5f, 0.5f, 0.5f, 0.5f, 0.5f,-0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f,-0.5f, -0.5f, 0.5f,-0.5f, 0.5f, 0.5f, 0.5f, -0.5f, 0.5f,-0.5f, -0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, -0.5f, 0.5f, 0.5f, 0.5f,-0.5f, 0.5f }; std::array triangle { -2.0f, 0.0f, 0.0f, 0.0f, 2.0f, 0.0f, 2.0f, 0.0f, 0.0f, -2.0f, 0.0f, 0.0f, -2.0f, -2.0f, 0.0f, 0.0f, -2.0f, 0.0f, -2.0f, 0.0f, 0.0f, 0.0f, -2.0f, 0.0f, 2.0f, 0.0f, 0.0f }; /* * Load draw data to the GPU memory. */ unsigned int vbo = 0; glGenBuffers(1, &vbo); glBindBuffer(GL_ARRAY_BUFFER, vbo); glBufferData(GL_ARRAY_BUFFER, sizeof(triangle), &triangle[0], GL_STATIC_DRAW); /* * Specify the format of the data. */ unsigned int vao = 0; glGenVertexArrays(1, &vao); glBindVertexArray(vao); glVertexAttribPointer(0, 3, GL_FLOAT, false, sizeof(float) * 3, 0); glEnableVertexAttribArray(0); std::cout << "Data init check:" << std::endl; if (gl_print_error() != 0) return; /* * Setup shaders. */ const auto vertex_source = read_shader("resources/shaders/vertex.glsl"); const auto fragment_source = read_shader("resources/shaders/fragment.glsl"); if (vertex_source.has_value() == false || fragment_source.has_value() == false) { std::cerr << "Failed to read shaders." << std::endl; return; } unsigned int program = create_shader(vertex_source.value(), fragment_source.value()); if (program == 0) { std::cerr << "Failed to compile shaders." << std::endl; return; } glUseProgram(program); /* * Projection. * FOV, Aspect, Z_NEAR, Z_FAR */ glm::mat4 projection = glm::perspective(45.0f, 4.0f / 3.0f, 1.0f, 100.0f); /* * View. * Eye not in the center so we are outside the object. * Center at 0. * Up = y direction. */ glm::vec3 eye = glm::vec3(0.0f, 0.0f, 5.0f); glm::vec3 center = glm::vec3(0.0f); glm::vec3 up = glm::vec3(0.0f, 1.0f, 0.0f); glm::mat4 view = glm::lookAt(eye, center, up); /* * Model. * Order of operations is important. */ glm::mat4 model = glm::mat4(1.0f); model = glm::scale(model, glm::vec3(1.0f, 1.0f, 1.0f)); model = glm::rotate(model, 0.0f, glm::vec3(0.0f, 1.0f, 0.0f)); model = glm::translate(model, glm::vec3(0.0f, 0.5f, 0.0f)); /* * Set PVM matrix. */ glm::mat4 pvm = projection * view * model; unsigned int u_pvm = glGetUniformLocation(program, "u_pvm"); glUniformMatrix4fv(u_pvm, 1, GL_TRUE, glm::value_ptr(pvm)); } static void render(void) { glDrawArrays(GL_TRIANGLES, 0, 9); } static void run(void) { GLFWwindow* window = init_window(); if (window == nullptr) std::exit(1); init_ImGui(window); init(); /* * Main loop. * Runs every frame. */ while (glfwWindowShouldClose(window) == 0) { glfwPollEvents(); render_ImGui(); reset_viewport(window); clear(); render(); display_ImGui(); glfwSwapBuffers(window); } /* * Cleanup. */ cleanup_ImGui(); cleanup_window(window); } int main(void) { /* * Keep main function brief. */ run(); }
Editor is loading...
Leave a Comment