#include "lopenglprogram.h" #include "camera.h" #include #include #include #include #include #include #include #include class GLWidget { public: struct ViewPort { int width; int height; }; GLWidget(ViewPort port) : viewport_(port), window_(nullptr, [](GLFWwindow* w){if(w) glfwDestroyWindow(w);}) { lastX_ = port.width / 2; lastY_ = port.height / 2; initGeometry(); } ~GLWidget() { if (bgVao_) { glDeleteVertexArrays(1, &bgVao_); } if (bgVbo_) { glDeleteBuffers(1, &bgVbo_); } } void setViewPort(int width, int height) { viewport_ = {width, height}; } bool initGeometry() { glfwInit(); glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); #if __APPLE__ glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); #endif window_.reset(glfwCreateWindow(800, 600, "3dviewer", nullptr, nullptr)); if (!window_) { std::cout << "Failed to create GLFW window" << std::endl; glfwTerminate(); return -1; } glfwMakeContextCurrent(window_.get()); if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) { std::cout << "Failed to initialize GLAD" << std::endl; return -1; } glViewport(0, 0, 800, 600); glfwSetWindowUserPointer(window_.get(), this); glfwSetFramebufferSizeCallback(window_.get(), &GLWidget::framebufferSizeCallback); glfwSetCursorPosCallback(window_.get(), &GLWidget::mouseCallback); } void setBgShaderPath(std::string vp, std::string fp) { bgVertShaderPath_ = vp; bgFragShaderPath_ = fp; } private: void initBgGeometry() { if (bgVbo_) { glDeleteBuffers(1, &bgVbo_); bgVbo_ = 0; } if (bgVao_) { glDeleteVertexArrays(1, &bgVao_); bgVao_ = 0; } const float verts[] = { -1.0, -1.0, 1.0, -1.0, 1.0, 1.0, -1.0, -1.0, 1.0, 1.0, -1.0, 1.0, }; glGenVertexArrays(1, &bgVao_); glBindVertexArray(bgVao_); glGenBuffers(1, &bgVbo_); glBindBuffer(GL_ARRAY_BUFFER, bgVbo_); glBufferData(GL_ARRAY_BUFFER, sizeof(verts), verts, GL_STATIC_DRAW); glEnableVertexAttribArray(0); glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), (void*)0); glBindVertexArray(0); } bool initBgProgram() { auto vshader = std::make_unique(LOpenGLShader::ShaderType::Vertex); auto fshader = std::make_unique(LOpenGLShader::ShaderType::Fragment); vshader->compileShaderFromFile(bgVertShaderPath_); fshader->compileShaderFromFile(bgFragShaderPath_); bgProg_ = std::make_unique(); bgProg_->addShader(std::move(vshader)); bgProg_->addShader(std::move(fshader)); bool ret = bgProg_->Link(); if (!ret) { return false; } return true; } void drawBg() { if (!bgProg_ || !bgVao_ || !bgVbo_) { std::cout << "check !bgProg_ || !bgVao_ || !bgVbo_ failed\n"; return; } bgProg_->Use(); bgProg_->setUniformValue("uViewport", glm::vec2(viewport_.width, viewport_.height)); bgProg_->setUniformValue("uMajorStep", 120.0f); bgProg_->setUniformValue("uMinjorStep", 24.0f); glBindVertexArray(bgVao_); glDrawArrays(GL_TRIANGLES, 0, 6); glBindVertexArray(0); glDepthMask(GL_TRUE); glEnable(GL_DEPTH_TEST); } public: void eventLoop() { initBgGeometry(); initBgProgram(); while (!glfwWindowShouldClose(window_.get())) { processInput(window_.get()); drawBg(); } } private: static void framebufferSizeCallback(GLFWwindow* window, int width, int height) { auto* self = static_cast(glfwGetWindowUserPointer(window)); if (!self) { return; } self->onFramebufferSize(width, height); } void onFramebufferSize(int width, int height) { glViewport(0, 0, width, height); } void processInput(GLFWwindow* window) { if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS) { glfwSetWindowShouldClose(window, true); } } static void mouseCallback(GLFWwindow* window, double x, double y) { auto* self = static_cast(glfwGetWindowUserPointer(window)); if (!self) { return; } self->onMouseMove(x, y); } void onMouseMove(double x, double y) { float xpos = static_cast(x); float ypos = static_cast(y); if (camera_.firstMouse()) { lastX_ = x; lastY_ = y; camera_.triggleFirstMouse(); } float xoffset = xpos - lastX_; float yoffset = lastY_ - ypos; lastX_ = xpos; lastY_ = ypos; camera_.mouseMoveCallback(xoffset, yoffset); } static void scrollCallback(GLFWwindow* window, double xoffset, double yoffset) { auto* self = static_cast(glfwGetWindowUserPointer(window)); if (!self) { return; } self->onScrollRoll(xoffset, yoffset); } void onScrollRoll(double xoffset, double yoffset) { camera_.mouseScrollCallback(yoffset); } private: std::unique_ptr bgProg_; std::unique_ptr> window_; std::string bgFragShaderPath_; std::string bgVertShaderPath_; unsigned int bgVao_; unsigned int bgVbo_; ViewPort viewport_{800, 600}; Camera camera_; bool firstMouse_ = true; float lastX_; float lastY_; }; int main() { GLWidget glw({600, 800}); glw.setBgShaderPath("bg.vert", "bg.frag"); glw.eventLoop(); glfwTerminate(); return 0; }