feat: add axes shaders and rendering functionality

This commit is contained in:
grtsinry43 2025-05-21 13:25:18 +08:00
parent 82bd391640
commit aecc61b0a6
Signed by: grtsinry43
GPG Key ID: F3305FB3A978C934
5 changed files with 122 additions and 22 deletions

View File

@ -94,6 +94,8 @@ target_link_libraries(OpenGLProject
set(SHADER_FILES
shaders/phong.vert
shaders/phong.frag
shaders/axes.vert
shaders/axes.frag
)
#

115
main.cpp
View File

@ -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<float>(); // 初始水平角 (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, &currentProgram);
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<float>()) {

View File

@ -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();

10
shaders/axes.frag Normal file
View File

@ -0,0 +1,10 @@
// shaders/axes.frag
#version 330 core
in vec3 fragmentColor;
out vec3 color;
void main(){
color = fragmentColor;
}

15
shaders/axes.vert Normal file
View File

@ -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;
}