diff --git a/CMakeLists.txt b/CMakeLists.txt index d0ef940..58d270e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -94,6 +94,8 @@ target_link_libraries(OpenGLProject set(SHADER_FILES shaders/phong.vert shaders/phong.frag + shaders/axes.vert + shaders/axes.frag ) # 将着色器文件复制到可执行文件旁边 diff --git a/main.cpp b/main.cpp index b5ced85..d537241 100644 --- a/main.cpp +++ b/main.cpp @@ -21,15 +21,18 @@ int windowHeight = 768; // 着色器程序ID GLuint programID; +GLuint axesProgramID; // Shader program for axes // GLuint pickingProgramID; // (可选,如果实现拾取) // Uniform ID GLuint MatrixID_MVP, MatrixID_M, MatrixID_V; GLuint LightPosID, LightColorID, LightPowerID, ViewPosID; GLuint TextureSamplerID; +GLuint AxesMatrixID_MVP; // MVP uniform for axes shader // VAO 和 VBO GLuint CubeVAO, CubeVBO_vertices, CubeVBO_normals, CubeVBO_uvs; +GLuint AxesVAO, AxesVBO_vertices, AxesVBO_colors; // GLuint LightVAO; // 用于表示光源的球体 (使用 GLUT 绘制,可能不需要单独VAO) // 纹理 @@ -40,7 +43,7 @@ glm::vec3 cameraPosition = glm::vec3(3.0f, 3.0f, 3.0f); float cameraHorizontalAngle = glm::pi(); // 初始水平角 (pi) float cameraVerticalAngle = 0.0f; // 初始垂直角 float initialFoV = 45.0f; -float cameraSpeed = 3.0f; // 单位/秒 +float cameraSpeed = 9.0f; // 单位/秒 float mouseSpeed = 0.002f; // 鼠标状态 @@ -67,10 +70,11 @@ void mouseMotion(int x, int y); void idle(); void createGradientTexture(); void setupCubeBuffers(); +void setupAxesBuffers(); // Added +void renderAxes(const glm::mat4& projectionMatrix, const glm::mat4& viewMatrix); // Added void renderText(const char* text, float x, float y, float r = 1.0f, float g = 1.0f, float b = 1.0f); // 立方体顶点数据 (位置, 法线, UV) -// 36个顶点,因为每个面有不同法线或UV,不能共享顶点 const GLfloat cube_vertices[] = { // Back face -0.5f, -0.5f, -0.5f, // Bottom-left @@ -116,6 +120,31 @@ const GLfloat cube_vertices[] = { -0.5f, 0.5f, -0.5f, // top-left }; +// Axes vertex data +const GLfloat axes_vertices[] = { + // X-axis (red) + 0.0f, 0.0f, 0.0f, + 2.0f, 0.0f, 0.0f, + // Y-axis (green) + 0.0f, 0.0f, 0.0f, + 0.0f, 2.0f, 0.0f, + // Z-axis (blue) + 0.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 2.0f +}; + +const GLfloat axes_colors[] = { + // X-axis (red) + 1.0f, 0.0f, 0.0f, + 1.0f, 0.0f, 0.0f, + // Y-axis (green) + 0.0f, 1.0f, 0.0f, + 0.0f, 1.0f, 0.0f, + // Z-axis (blue) + 0.0f, 0.0f, 1.0f, + 0.0f, 0.0f, 1.0f +}; + const GLfloat cube_normals[] = { // Back face 0.0f, 0.0f, -1.0f, @@ -273,6 +302,26 @@ void setupCubeBuffers() { glBindVertexArray(0); } +void setupAxesBuffers() { + glGenVertexArrays(1, &AxesVAO); + glBindVertexArray(AxesVAO); + + // Vertex positions + glGenBuffers(1, &AxesVBO_vertices); + glBindBuffer(GL_ARRAY_BUFFER, AxesVBO_vertices); + glBufferData(GL_ARRAY_BUFFER, sizeof(axes_vertices), axes_vertices, GL_STATIC_DRAW); + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)0); + glEnableVertexAttribArray(0); + + // Vertex colors + glGenBuffers(1, &AxesVBO_colors); + glBindBuffer(GL_ARRAY_BUFFER, AxesVBO_colors); + glBufferData(GL_ARRAY_BUFFER, sizeof(axes_colors), axes_colors, GL_STATIC_DRAW); + glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, (void*)0); + glEnableVertexAttribArray(1); + + glBindVertexArray(0); +} void initGL() { glewExperimental = GL_TRUE; @@ -302,6 +351,12 @@ void initGL() { exit(-1); } + axesProgramID = LoadShaders("shaders/axes.vert", "shaders/axes.frag"); + if (axesProgramID == 0) { + std::cerr << "Failed to load axes shaders. Exiting." << std::endl; + exit(-1); + } + // 添加着色器编译状态检查 GLint success; GLchar infoLog[512]; @@ -329,8 +384,12 @@ void initGL() { TextureSamplerID = glGetUniformLocation(programID, "myTextureSampler"); if (TextureSamplerID == -1) std::cerr << "myTextureSampler uniform not found" << std::endl; + AxesMatrixID_MVP = glGetUniformLocation(axesProgramID, "MVP"); + if (AxesMatrixID_MVP == -1) std::cerr << "Axes MVP uniform not found" << std::endl; + createGradientTexture(); setupCubeBuffers(); + setupAxesBuffers(); glutSetCursor(GLUT_CURSOR_NONE); glutWarpPointer(windowWidth / 2, windowHeight / 2); @@ -367,6 +426,23 @@ void renderText(const char* text, float x, float y, float r, float g, float b) { glPopMatrix(); } +void renderAxes(const glm::mat4& projectionMatrix, const glm::mat4& viewMatrix) { + glUseProgram(axesProgramID); + + glm::mat4 ModelMatrixAxes = glm::mat4(1.0); // Identity matrix, axes at origin + glm::mat4 MVP_Axes = projectionMatrix * viewMatrix * ModelMatrixAxes; + + if (AxesMatrixID_MVP != -1) { + glUniformMatrix4fv(AxesMatrixID_MVP, 1, GL_FALSE, &MVP_Axes[0][0]); + } + + glBindVertexArray(AxesVAO); + glLineWidth(2.0f); // Make axes lines thicker + glDrawArrays(GL_LINES, 0, 6); // 3 lines, 2 vertices each + glBindVertexArray(0); + glLineWidth(1.0f); // Reset line width +} + void display() { // 检查OpenGL错误 GLenum err; @@ -383,17 +459,6 @@ void display() { std::cerr << "深度测试未启用" << std::endl; } - // 先绑定着色器程序 - glUseProgram(programID); - - // 检查着色器程序绑定状态 - GLint currentProgram; - glGetIntegerv(GL_CURRENT_PROGRAM, ¤tProgram); - if (currentProgram != programID) { - std::cerr << "着色器程序未正确绑定" << std::endl; - return; - } - glm::vec3 direction( cos(cameraVerticalAngle) * sin(cameraHorizontalAngle), sin(cameraVerticalAngle), @@ -413,6 +478,9 @@ void display() { up ); + // Render Cube + glUseProgram(programID); // Ensure correct shader is used for the cube + glm::mat4 ModelMatrixCube = glm::mat4(1.0); ModelMatrixCube = glm::translate(ModelMatrixCube, glm::vec3(0.0f, 0.0f, 0.0f)); ModelMatrixCube = glm::rotate(ModelMatrixCube, cubeRotationAngle, glm::vec3(0.0f, 1.0f, 0.0f)); @@ -472,6 +540,9 @@ void display() { // 解绑VAO glBindVertexArray(0); + // Render Axes + renderAxes(ProjectionMatrix, ViewMatrix); + // 检查绘制后的OpenGL错误 while((err = glGetError()) != GL_NO_ERROR) { std::cerr << "OpenGL error after rendering: " << err << std::endl; @@ -489,12 +560,12 @@ void display() { glutSolidSphere(0.1, 10, 10); // 渲染操作说明文字 - renderText("操作说明:", 10, windowHeight - 20, 1.0f, 1.0f, 0.0f); - renderText("W/S: 前进/后退", 10, windowHeight - 40); - renderText("A/D: 左移/右移", 10, windowHeight - 60); - renderText("空格/C: 上升/下降", 10, windowHeight - 80); - renderText("鼠标左键拖拽: 视角旋转", 10, windowHeight - 100); - renderText("ESC: 退出程序", 10, windowHeight - 120); + renderText("Controls:", 10, windowHeight - 20, 1.0f, 1.0f, 0.0f); + renderText("W/S: Move Forward/Backward", 10, windowHeight - 40); + renderText("A/D: Strafe Left/Right", 10, windowHeight - 60); + renderText("Space/C: Move Up/Down", 10, windowHeight - 80); + renderText("Left Mouse Drag: Rotate View", 10, windowHeight - 100); + renderText("ESC: Exit Program", 10, windowHeight - 120); glutSwapBuffers(); } @@ -535,6 +606,11 @@ void keyboard(unsigned char key, int x, int y) { glDeleteVertexArrays(1, &CubeVAO); glDeleteProgram(programID); glDeleteTextures(1, &checkerboardTextureID); + // Cleanup for axes + glDeleteBuffers(1, &AxesVBO_vertices); + glDeleteBuffers(1, &AxesVBO_colors); + glDeleteVertexArrays(1, &AxesVAO); + glDeleteProgram(axesProgramID); exit(0); break; } @@ -585,7 +661,6 @@ void mouseMotion(int x, int y) { } } - void idle() { cubeRotationAngle += 0.005f; if (cubeRotationAngle > 2.0f * glm::pi()) { diff --git a/shader_utils.cpp b/shader_utils.cpp index 34928b1..645054b 100644 --- a/shader_utils.cpp +++ b/shader_utils.cpp @@ -16,7 +16,6 @@ GLuint LoadShaders(const char * vertex_file_path, const char * fragment_file_pat sstr << VertexShaderStream.rdbuf(); VertexShaderCode = sstr.str(); VertexShaderStream.close(); - std::cout << "顶点着色器代码:\n" << VertexShaderCode << std::endl; } else { std::cerr << "无法打开 " << vertex_file_path << ". 你是否在正确的目录下运行程序?" << std::endl; getchar(); @@ -31,7 +30,6 @@ GLuint LoadShaders(const char * vertex_file_path, const char * fragment_file_pat sstr << FragmentShaderStream.rdbuf(); FragmentShaderCode = sstr.str(); FragmentShaderStream.close(); - std::cout << "片元着色器代码:\n" << FragmentShaderCode << std::endl; } else { std::cerr << "无法打开 " << fragment_file_path << ". 你是否在正确的目录下运行程序?" << std::endl; getchar(); diff --git a/shaders/axes.frag b/shaders/axes.frag new file mode 100644 index 0000000..44adc0d --- /dev/null +++ b/shaders/axes.frag @@ -0,0 +1,10 @@ +// shaders/axes.frag +#version 330 core + +in vec3 fragmentColor; +out vec3 color; + +void main(){ + color = fragmentColor; +} + diff --git a/shaders/axes.vert b/shaders/axes.vert new file mode 100644 index 0000000..84d9344 --- /dev/null +++ b/shaders/axes.vert @@ -0,0 +1,15 @@ +// shaders/axes.vert +#version 330 core + +layout(location = 0) in vec3 vertexPosition_modelspace; +layout(location = 1) in vec3 vertexColor; + +out vec3 fragmentColor; + +uniform mat4 MVP; + +void main(){ + gl_Position = MVP * vec4(vertexPosition_modelspace, 1.0); + fragmentColor = vertexColor; +} +