From 26e00f9fea91a3f9bd4e0bd5b9bee95d3d64f339 Mon Sep 17 00:00:00 2001 From: lenn Date: Wed, 11 Feb 2026 17:50:12 +0800 Subject: [PATCH] update --- CMakeLists.txt | 14 +++- camera.h | 2 + lopenglprogram.cpp | 28 ++++++-- lopenglprogram.h | 8 +-- main.cpp | 176 ++++++++++++++++++++++++++++++++++++++------- shader/bg.frag | 25 +++---- 6 files changed, 202 insertions(+), 51 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 1a56302..286459d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,6 +4,9 @@ project(3dviewer) set(CMAKE_EXPORT_COMPILE_COMMANDS ON) include_directories(.) +find_package(glfw3 REQUIRED) +find_package(OpenGL REQUIRED) + add_executable( ${PROJECT_NAME} main.cpp @@ -15,5 +18,14 @@ add_executable( target_link_libraries( ${PROJECT_NAME} PRIVATE - libglfw3.a + glfw3 + OpenGL::GL + X11 + Xrandr + Xi + Xcursor + Xinerama + pthread + dl + m ) diff --git a/camera.h b/camera.h index 7f9658d..a6571f2 100644 --- a/camera.h +++ b/camera.h @@ -82,6 +82,8 @@ public: void triggleFirstMouse() { firstMouse_ = !firstMouse_; } + float Zoom() const { return zoom_; } + private: void updateCameraVectors() { glm::vec3 front; diff --git a/lopenglprogram.cpp b/lopenglprogram.cpp index 0ac3d7d..93b6cb1 100644 --- a/lopenglprogram.cpp +++ b/lopenglprogram.cpp @@ -120,21 +120,35 @@ bool LOpenGLShader::compileShaderFromFile(const std::string &path) { return true; } -LOpenGLProgram::LOpenGLProgram() : linked_(false) { - Create(); -} +LOpenGLProgram::LOpenGLProgram() { Create(); } LOpenGLProgram::~LOpenGLProgram() { - glDeleteProgram(programId_); + if (programId_ != 0) { + glDeleteProgram(programId_); + } } -void LOpenGLProgram::Create() { programId_ = glCreateProgram(); } +void LOpenGLProgram::Create() { + programId_ = glCreateProgram(); + created_ = (programId_ != 0); + linked_ = false; +} -bool LOpenGLProgram::Link() const { +bool LOpenGLProgram::Link() { if (!created_ || linked_ || shaderList_.empty()) { return false; } glLinkProgram(programId_); + GLint success = 0; + glGetProgramiv(programId_, GL_LINK_STATUS, &success); + if (!success) { + char infoLog[512]; + glGetProgramInfoLog(programId_, 512, nullptr, infoLog); + std::cout << "ERROR::PROGRAM::LINK_FAILED\n" << infoLog << std::endl; + linked_ = false; + return false; + } + linked_ = true; return true; } @@ -165,7 +179,7 @@ void LOpenGLProgram::setUniformValue(const std::string &name, float x, float y, } void LOpenGLProgram::setUniformValue(const std::string &name, glm::mat4 value) const { - glUniform4fv(glGetUniformLocation(programId_, name.c_str()), 1, &value[0][0]); + glUniformMatrix4fv(glGetUniformLocation(programId_, name.c_str()), 1, GL_FALSE, &value[0][0]); } bool LOpenGLProgram::addShader(std::unique_ptr shader) { diff --git a/lopenglprogram.h b/lopenglprogram.h index 0232727..9b26279 100644 --- a/lopenglprogram.h +++ b/lopenglprogram.h @@ -41,7 +41,7 @@ public: bool addShader(std::unique_ptr shader); void removeShader(GLuint id); void Create(); - bool Link() const; + bool Link(); void Use() const; bool Linked() const { return linked_; } @@ -55,7 +55,7 @@ public: private: std::list> shaderList_; - GLuint programId_; - bool linked_; - bool created_; + GLuint programId_ = 0; + bool linked_ = false; + bool created_ = false; }; diff --git a/main.cpp b/main.cpp index b46dcf5..fa942ca 100644 --- a/main.cpp +++ b/main.cpp @@ -4,7 +4,10 @@ #include #include #include +#include +#include #include +#include #include #include #include @@ -17,19 +20,28 @@ public: int width; int height; }; - GLWidget(ViewPort port) : viewport_(port), - window_(nullptr, [](GLFWwindow* w){if(w) glfwDestroyWindow(w);}) { + GLWidget(ViewPort port) : viewport_(port) + , window_(nullptr, [](GLFWwindow* w){if(w) glfwDestroyWindow(w);}) + , deinit_(false) { lastX_ = port.width / 2; lastY_ = port.height / 2; initGeometry(); } ~GLWidget() { - if (bgVao_) { - glDeleteVertexArrays(1, &bgVao_); - } - if (bgVbo_) { - glDeleteBuffers(1, &bgVbo_); + if (!deinit_) { + // OpenGL objects should be deleted while a valid context still exists. + if (window_) { + glfwMakeContextCurrent(window_.get()); + } + if (bgVao_) { + glDeleteVertexArrays(1, &bgVao_); + } + if (bgVbo_) { + glDeleteBuffers(1, &bgVbo_); + } + deinit_ = true; } + } void setViewPort(int width, int height) { @@ -37,7 +49,10 @@ public: } bool initGeometry() { - glfwInit(); + if (!glfwInit()) { + std::cout << "Failed to initialize GLFW" << std::endl; + return false; + } glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); @@ -48,18 +63,20 @@ public: if (!window_) { std::cout << "Failed to create GLFW window" << std::endl; glfwTerminate(); - return -1; + return false; } glfwMakeContextCurrent(window_.get()); if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) { std::cout << "Failed to initialize GLAD" << std::endl; - return -1; + return false; } glViewport(0, 0, 800, 600); glfwSetWindowUserPointer(window_.get(), this); glfwSetFramebufferSizeCallback(window_.get(), &GLWidget::framebufferSizeCallback); glfwSetCursorPosCallback(window_.get(), &GLWidget::mouseCallback); + glfwSetScrollCallback(window_.get(), &GLWidget::scrollCallback); + return true; } void setBgShaderPath(std::string vp, std::string fp) { @@ -95,16 +112,100 @@ private: } + void initPanelGeometry_() { + if (panelVbo_) { + glDeleteBuffers(1, &panelVbo_); + panelVbo_ = 0; + } + if (panelVao_) { + glDeleteVertexArrays(1, &panelVao_); + panelVao_ = 0; + } + + const float y = panelHeight_ * 0.5f; + const float x = panelWidth_ * 0.5f; + const float z = panelDepth_ * 0.5f; + + struct V { + float x, y, z; + float nx, ny, nz; + }; + const V verts[24] = { + // 顶面 + {-x, y, -z, 0, 1, 0}, + {x, y, -z, 0, 1, 0}, + {x, y, z, 0, 1, 0 }, + {-x, y, z, 0, 1, 0}, + + // 前面 + {-x, y, z, 0, 0, 1}, + {x, y, z, 0, 0, 1}, + {x, -y, z, 0, 0, 1}, + {-x, -y, z, 0, 0, 1}, + + // 底面 + {-x, -y, -z, 0, -1, 0}, + {x, -y, -z, 0, -1, 0}, + {x, -y, z, 0, -1, 0}, + {-x, -y, z, 0, -1, 0}, + + // 后面 + {-x, y, -z, 0, 0, -1}, + {x, y, -z, 0, 0, -1}, + {x, -y, -z, 0, 0, -1}, + {-x, -y, -z, 0, 0, -1}, + + // 左面 + {-x, y, z, -1, 0, 0}, + {-x, y, -z, -1, 0, 0}, + {-x, -y, -z, -1, 0, 0}, + {-x, -y, z, -1, 0, 0}, + + // 右面 + {x, y, -z, 1, 0, 0}, + {x, y, z, 1, 0, 0}, + {x, -y, z, 1, 0, 0}, + {x, -y, -z, 1, 0, 0}, + }; + + unsigned int idx[36] = { + 0, 1, 2, 0, 2, 3, + 4, 5, 6, 4, 6, 7, + 8, 9, 10, 8, 10, 11, + 12, 13, 14, 12, 14, 15, + 16, 17, 18, 16, 18, 19, + 20, 21, 22, 20, 22, 23, + }; + + glGenVertexArrays(1, &panelVao_); + + } + bool initBgProgram() { auto vshader = std::make_unique(LOpenGLShader::ShaderType::Vertex); auto fshader = std::make_unique(LOpenGLShader::ShaderType::Fragment); - vshader->compileShaderFromFile(bgVertShaderPath_); - fshader->compileShaderFromFile(bgFragShaderPath_); + if (!vshader->compileShaderFromFile(bgVertShaderPath_)) { + std::cout << "Vertex shader compile failed: " << bgVertShaderPath_ << "\n" + << vshader->Log() << std::endl; + return false; + } + if (!fshader->compileShaderFromFile(bgFragShaderPath_)) { + std::cout << "Fragment shader compile failed: " << bgFragShaderPath_ << "\n" + << fshader->Log() << std::endl; + return false; + } bgProg_ = std::make_unique(); - bgProg_->addShader(std::move(vshader)); - bgProg_->addShader(std::move(fshader)); + if (!bgProg_->addShader(std::move(vshader))) { + std::cout << "Failed to attach vertex shader\n"; + return false; + } + if (!bgProg_->addShader(std::move(fshader))) { + std::cout << "Failed to attach fragment shader\n"; + return false; + } bool ret = bgProg_->Link(); if (!ret) { + std::cout << "Failed to link background program\n"; return false; } @@ -119,7 +220,7 @@ private: bgProg_->Use(); bgProg_->setUniformValue("uViewport", glm::vec2(viewport_.width, viewport_.height)); bgProg_->setUniformValue("uMajorStep", 120.0f); - bgProg_->setUniformValue("uMinjorStep", 24.0f); + bgProg_->setUniformValue("uMinorStep", 24.0f); glBindVertexArray(bgVao_); glDrawArrays(GL_TRIANGLES, 0, 6); glBindVertexArray(0); @@ -131,11 +232,20 @@ private: public: void eventLoop() { + if (!window_) { + return; + } initBgGeometry(); - initBgProgram(); + if (!initBgProgram()) { + return; + } while (!glfwWindowShouldClose(window_.get())) { processInput(window_.get()); + glClearColor(0.08f, 0.08f, 0.10f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); drawBg(); + glfwSwapBuffers(window_.get()); + glfwPollEvents(); } } @@ -149,6 +259,7 @@ private: } void onFramebufferSize(int width, int height) { + viewport_ = {width, height}; glViewport(0, 0, width, height); } @@ -171,6 +282,7 @@ private: float ypos = static_cast(y); if (camera_.firstMouse()) { + std::cout << "in firstMouse()\n"; lastX_ = x; lastY_ = y; camera_.triggleFirstMouse(); @@ -186,8 +298,10 @@ private: } static void scrollCallback(GLFWwindow* window, double xoffset, double yoffset) { + std::cout << "scrollCallback\n"; auto* self = static_cast(glfwGetWindowUserPointer(window)); if (!self) { + std::cout << "auto* self = static_cast(glfwGetWindowUserPointer(window)) failed\n"; return; } self->onScrollRoll(xoffset, yoffset); @@ -202,23 +316,35 @@ private: std::unique_ptr> window_; std::string bgFragShaderPath_; std::string bgVertShaderPath_; - unsigned int bgVao_; - unsigned int bgVbo_; + unsigned int bgVao_ = 0; + unsigned int bgVbo_ = 0; + + std::unique_ptr panelProg_; + std::string panelVertShaderPath_; + std::string panelFragShaderPath_; + unsigned int panelVao_ = 0; + unsigned int panelVbo_ = 0; + float panelWidth_ = 0.25; + float panelHeight_ = 0.35; + float panelDepth_ = 0.05; + + ViewPort viewport_{800, 600}; Camera camera_; bool firstMouse_ = true; float lastX_; float lastY_; + + bool deinit_; }; int main() { - - GLWidget glw({600, 800}); - glw.setBgShaderPath("bg.vert", "bg.frag"); - - glw.eventLoop(); - + { + GLWidget glw({600, 800}); + glw.setBgShaderPath("../shader/bg.vert", "../shader/bg.frag"); + glw.eventLoop(); + } glfwTerminate(); return 0; -} \ No newline at end of file +} diff --git a/shader/bg.frag b/shader/bg.frag index 56b79e1..a221400 100644 --- a/shader/bg.frag +++ b/shader/bg.frag @@ -9,9 +9,9 @@ uniform bool uLightMode; float gridLine(float stepPx) { vec2 coord = gl_FragCoord.xy; - vec2 q = coord / stepPx; - - vec2 q = abs(fract(q - 0.5) - 0.5) / fwidth(stepPx); + vec2 q = coord / max(stepPx, 1.0); + vec2 fw = max(fwidth(q), vec2(1e-6)); + q = abs(fract(q - 0.5) - 0.5) / fw; float line = 1.0 - min(min(q.x, q.y), 1.0); return line; @@ -21,27 +21,24 @@ void main() { vec2 viewport = max(uViewport, vec2(1.0)); vec2 uv = gl_FragCoord.xy / viewport; - vec3 topCol, botCol, majCol, minCol; - float majStrength, minStrength; - float vignettePow, vignetteStrength; + vec3 topCol, botCol; + float majorStrength, minorStrength; topCol = vec3(0.99, 0.99, 1.00); botCol = vec3(0.94, 0.95, 0.98); - minorCol = vec3(0.80, 0.82, 0.87); - majorCol = vec3(0.70, 0.73, 0.80); + vec3 minorCol = vec3(0.80, 0.82, 0.87); + vec3 majorCol = vec3(0.70, 0.73, 0.80); - minorStrength = 0.22; - majorStrength = 0.35; - vignettePow = 0.12; - vignetteStrength = 0.35; + minorStrength = 0.28; + majorStrength = 0.45; vec3 col = mix(botCol, topCol, uv.y); float minor = gridLine(max(uMinorStep, 1.0)); float major = gridLine(max(uMajorStep, 1.0)); - col = mix(col, minorCol, minStrength * minor); - col = mix(col, majorCol, majStrength * major); + col = mix(col, minorCol, minorStrength * minor); + col = mix(col, majorCol, majorStrength * major); vec2 p = uv * 2.0 - 1.0; float v = clamp(1.0 - dot(p, p) * 0.12 , 0.0, 1.0);