<think>好的,用户现在想要一个使用OpenGL、GLAD、GLFW和GLM库绘制三角形网格的完整代码示例。我需要先回顾之前的对话和用户提供的引用内容,确保满足他们的需求。
首先,用户在上一次的问题中已经询问了三维渲染的基础教程,我给出了初始化环境、顶点缓冲、着色器配置、坐标变换和渲染循环的示例。现在用户需要完整的代码,可能希望有一个可以直接编译运行的例子,这样他们可以快速上手。
接下来,用户提到了参考站内的引用,特别是引用[1]关于Geometry Shader实现法线可视化和引用[2]关于实例化渲染。不过用户这次的问题并没有提到需要法线可视化或实例化,所以可能这些引用只是作为背景信息,当前需求更基础,是绘制三角形网格。不过,我需要注意是否需要将这些引用内容整合进去,但根据用户的问题,他们明确要求的是绘制三角形网格的完整代码,所以暂时可能不需要包括Geometry Shader或实例化的部分,除非用户特别说明。
现在,我需要构建一个完整的代码示例,涵盖GLFW窗口的创建、GLAD的初始化、顶点数据的定义、VAO/VBO的设置、着色器的编译、模型视图投影矩阵的应用以及渲染循环。用户提到的库包括GLAD、GLFW和GLM,所以必须确保代码中正确使用这些库的功能。
首先,考虑代码结构:初始化GLFW,创建窗口,初始化GLAD,设置视口,处理输入。然后是着色器的编写,顶点和片段着色器需要正确读取顶点数据并应用变换矩阵。顶点数据部分需要定义一个三角形网格,可能使用多个三角形组成一个简单的形状,比如立方体或平面网格。但用户请求的是三角形网格,可能一个简单的例子更合适,比如两个三角形组成的四边形,或者单个三角形。不过为了展示网格,可能使用多个三角形更好。
然后,设置VAO和VBO,绑定顶点数据,配置顶点属性指针。接着是着色器的编译和链接,确保uniform变量正确传递模型、视图、投影矩阵。使用GLM库来生成这些矩阵,例如视图矩阵使用lookAt,投影矩阵使用perspective。
在渲染循环中,清除颜色和深度缓冲,设置uniform矩阵,绘制顶点数组。同时处理窗口的交换缓冲和事件轮询。需要启用深度测试以确保正确的三维渲染效果,这在之前的回答中已经提到过优化建议,所以代码中应包括glEnable(GL_DEPTH_TEST)。
还需要处理窗口大小调整的回调函数,以正确更新视口。输入处理部分,比如按下ESC关闭窗口。
检查用户可能需要的额外功能,比如颜色变化,可能在片段着色器中添加颜色属性,或者随时间旋转模型,以展示动态效果。例如,在模型矩阵中加入旋转,根据时间变化,让三角形网格旋转起来,这样用户可以看到效果。
需要确保代码的完整性和正确性,用户应该能够复制代码,安装必要的库后直接编译运行。因此,代码中的每个步骤都要详细,包括头文件的包含、库的链接说明,以及可能的编译指令。
可能还需要注意GLAD的初始化顺序,必须在GLFW的上下文创建之后初始化。GLFW窗口的创建参数,比如OpenGL版本设为3.3,核心配置文件,这对现代OpenGL是必要的。
最后,生成相关问题,考虑用户可能接下来会问的内容,比如如何添加纹理、光照,或者如何处理更复杂的网格,以及性能优化等问题。这些问题需要与当前主题相关,帮助用户进一步学习。</think>以下是使用OpenGL核心模式配合GLAD/GLFW/GLM实现三角形网格的完整代码示例,包含关键注释和实现细节:
### 完整代码实现
```cpp
#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <iostream>
// 顶点着色器源码
const char* vertexShaderSource = R"(
#version 330 core
layout (location = 0) in vec3 aPos;
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
void main() {
gl_Position = projection * view * model * vec4(aPos, 1.0);
}
)";
// 片段着色器源码
const char* fragmentShaderSource = R"(
#version 330 core
out vec4 FragColor;
void main() {
FragColor = vec4(0.2, 0.6, 1.0, 1.0); // 蓝色调
}
)";
// 窗口回调函数
void framebuffer_size_callback(GLFWwindow* window, int width, int height) {
glViewport(0, 0, width, height);
}
int main() {
// 初始化GLFW
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
// 创建窗口
GLFWwindow* window = glfwCreateWindow(800, 600, "Triangle Mesh", NULL, NULL);
glfwMakeContextCurrent(window);
glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
// 初始化GLAD
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) {
std::cout << "Failed to initialize GLAD" << std::endl;
return -1;
}
// 定义三角形网格顶点数据(两个三角形组成四边形)
float vertices[] = {
// 第一个三角形
-0.5f, -0.5f, 0.0f,
0.5f, -0.5f, 0.0f,
0.0f, 0.5f, 0.0f,
// 第二个三角形
0.5f, -0.5f, 0.0f,
0.5f, 0.5f, 0.0f,
0.0f, 0.5f, 0.0f
};
// 创建VAO/VBO
unsigned int VAO, VBO;
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
// 编译着色器
unsigned int vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);
glCompileShader(vertexShader);
unsigned int fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
glCompileShader(fragmentShader);
// 创建着色器程序
unsigned int shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
glLinkProgram(shaderProgram);
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
// 启用深度测试
glEnable(GL_DEPTH_TEST);
// 渲染循环
while (!glfwWindowShouldClose(window)) {
// 清除缓冲
glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// 创建变换矩阵
glm::mat4 model = glm::rotate(glm::mat4(1.0f), (float)glfwGetTime(), glm::vec3(0.5f, 1.0f, 0.0f));
glm::mat4 view = glm::lookAt(glm::vec3(2.0f, 2.0f, 2.0f),
glm::vec3(0.0f, 0.0f, 0.0f),
glm::vec3(0.0f, 1.0f, 0.0f));
glm::mat4 projection = glm::perspective(glm::radians(45.0f), 800.0f/600.0f, 0.1f, 100.0f);
// 传递矩阵到着色器
glUseProgram(shaderProgram);
glUniformMatrix4fv(glGetUniformLocation(shaderProgram, "model"), 1, GL_FALSE, &model[0][0]);
glUniformMatrix4fv(glGetUniformLocation(shaderProgram, "view"), 1, GL_FALSE, &view[0][0]);
glUniformMatrix4fv(glGetUniformLocation(shaderProgram, "projection"), 1, GL_FALSE, &projection[0][0]);
// 绘制网格
glBindVertexArray(VAO);
glDrawArrays(GL_TRIANGLES, 0, 6);
glfwSwapBuffers(window);
glfwPollEvents();
}
// 清理资源
glDeleteVertexArrays(1, &VAO);
glDeleteBuffers(1, &VBO);
glDeleteProgram(shaderProgram);
glfwTerminate();
return 0;
}
```
### 关键特性说明
1. **现代OpenGL特性**:
- 使用核心模式(Core Profile)
- 顶点数组对象(VAO)管理状态
- 矩阵变换通过GLM实现[^2]
2. **运行效果**:
- 两个旋转的蓝色三角形组成动态四边形
- 启用深度测试防止绘制顺序错误
- 摄像机使用`glm::lookAt`实现三维观察
3. **编译说明**:
- 需要链接GLFW3、GLAD、GLM库
- 建议使用CMake管理项目
- OpenGL版本要求3.3+