起因
学了点OpenGL的基础知识,想找个GUI框架来显示渲染结果。一开始用GLFW,但那个窗口太简陋了,连个按钮都没有。后来发现Qt自带QOpenGLWidget,可以很方便地把OpenGL嵌入到Qt界面里。于是就试着写了个能旋转的立方体。
基本原理
OpenGL渲染的基本流程:
- 定义顶点数据(三角形的三个点)
- 把顶点数据传到GPU(VBO)
- 告诉GPU怎么解释这些数据(VAO)
- 写顶点着色器(处理每个顶点的位置变换)
- 写片元着色器(处理每个像素的颜色)
- 绘制
听起来简单,但每一步都有坑。
在Qt中使用OpenGL
继承QOpenGLWidget,重写三个虚函数:
class MyGLWidget : public QOpenGLWidget, protected QOpenGLFunctions {
protected:
void initializeGL() override; // 初始化OpenGL
void resizeGL(int w, int h) override; // 窗口大小改变时调用
void paintGL() override; // 每帧绘制
};
initializeGL里做初始化:编译着色器、创建VBO/VAO。
resizeGL里设置视口和投影矩阵。
paintGL里做实际的绘制。
着色器代码
顶点着色器(GLSL):
#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec3 aColor;
out vec3 ourColor;
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
void main() {
gl_Position = projection * view * model * vec4(aPos, 1.0);
ourColor = aColor;
}
片元着色器:
#version 330 core
in vec3 ourColor;
out vec4 FragColor;
void main() {
FragColor = vec4(ourColor, 1.0);
}
这段代码的意思是:把3D坐标通过model、view、projection三个矩阵变换到屏幕坐标,然后把顶点颜色插值传给片元着色器。
立方体数据
一个立方体有6个面,每个面2个三角形,每个三角形3个顶点。所以总共36个顶点。每个顶点需要位置(xyz)和颜色(rgb)。
float vertices[] = {
// positions // colors
-0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, // 红
0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f,
0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f,
// ... 以此类推,36个顶点
};
旋转动画
用QTimer定时刷新,每帧改变model矩阵的旋转角度:
void MyGLWidget::paintGL() {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
QMatrix4x4 model;
model.rotate(angle, 1.0f, 1.0f, 0.5f); // 绕(1,1,0.5)轴旋转
shaderProgram->bind();
shaderProgram->setUniformValue("model", model);
// ... 绘制
}
// 在initializeGL中设置定时器
QTimer *timer = new QTimer(this);
connect(timer, &QTimer::timeout, [this]() {
angle += 2.0f;
update(); // 触发paintGL
});
timer->start(16); // 约60fps
踩过的坑
- 忘记开深度测试:不开
glEnable(GL_DEPTH_TEST)的话,立方体背面会画到前面来,看起来很诡异 - 着色器编译失败不报错:需要手动检查编译状态,用
glGetShaderiv(GL_COMPILE_STATUS) - VAO/VBO绑定顺序:必须先绑VAO再绑VBO再设置属性指针,顺序错了就黑屏
- Qt和OpenGL版本:QOpenGLWidget默认可能是OpenGL 2.1,需要在main函数里设置
QSurfaceFormat
效果
最终效果是一个在深色背景上缓缓旋转的彩色立方体,每个面颜色不同。虽然很简单,但整个流程跑通了:着色器编译、顶点数据、矩阵变换、实时渲染。
学习资源推荐
OpenGL的学习资料其实不多,但有几个质量特别高的:
- LearnOpenGL(
learnopengl.com):最推荐的入门教程,有中文翻译版。从基础渲染到PBR、阴影都有,示例代码完整可运行 - 赵新政的OpenGL教程:在Telegram上有免费版本,讲得很详细,适合中文用户。比看英文文档轻松很多
- Qt官方的OpenGL示例:Qt Creator里搜OpenGL,有很多Example,特别适合学怎么在Qt里集成OpenGL
赵新政的教程在Telegram上可以免费获取,LearnOpenGL也有中文社区翻译版。这两个配合着看效果最好。
下一步打算加个光照模型,让立方体看起来有立体感。然后试试加载3D模型文件。