Qt OpenGL编程常用类

发布于:2025-06-02 ⋅ 阅读:(23) ⋅ 点赞:(0)

Qt提供了丰富的类来支持OpenGL编程,以下是常用的Qt OpenGL相关类:

一、QOpenGLWidget

功能:用于在 Qt 应用程序中嵌入 OpenGL 渲染的窗口部件。替代了旧版的QGLWidget。提供了OpenGL上下文和渲染表面。
继承关系:QWidget → QOpenGLWidget
属性与方法:

QOpenGLWidget 属性表

属性 类型 可读 可写 说明
format QSurfaceFormat ✔️ ✔️ 控制 OpenGL 上下文和表面的格式(如版本、采样数等)
textureFormat GLenum ✔️ ✔️ 在 grabFramebuffer() 中使用的纹理格式(默认为 GL_RGBA
isValid bool ✔️ 检查 OpenGL 上下文和资源是否初始化成功

QOpenGLWidget 核心方法表

1. 初始化与状态控制
方法 参数 返回值 说明
initializeGL() void 虚函数,首次显示时调用,用于初始化 OpenGL 资源
paintGL() void 虚函数,执行实际的 OpenGL 绘制操作
resizeGL(int w, int h) w: 新宽度
h: 新高度
void 虚函数,窗口大小变化时调用,调整视口等
makeCurrent() void 将 OpenGL 上下文绑定到当前线程
doneCurrent() void 释放当前线程的 OpenGL 上下文
2. 上下文与表面
方法 参数 返回值 说明
context() QOpenGLContext* 返回关联的 OpenGL 上下文对象
defaultFramebufferObject() GLuint 返回默认帧缓冲对象的 ID
isValid() bool 检查上下文和表面是否有效
3. 帧缓冲操作
方法 参数 返回值 说明
grabFramebuffer() QImage 捕获当前帧缓冲内容为 QImage
grabFramebuffer(const QRect& rect) rect: 截取区域 QImage 捕获指定区域的帧缓冲内容
4. 格式设置
方法 参数 返回值 说明
setFormat(const QSurfaceFormat& format) format: 表面格式 void 设置 OpenGL 上下文和表面的格式
format() QSurfaceFormat 返回当前的表面格式
5. 事件处理(覆盖自 QWidget)
方法 参数 返回值 说明
paintEvent(QPaintEvent* e) e: 绘制事件 void 内部调用 paintGL(),通常不需要直接重写
resizeEvent(QResizeEvent* e) e: 大小事件 void 内部调用 resizeGL(),通常不需要直接重写

QSurfaceFormat 常用设置(用于 setFormat()

方法 参数 说明
setVersion(int major, int minor) major: 主版本号
minor: 次版本号
设置 OpenGL 版本(如 3.3)
setProfile(QSurfaceFormat::OpenGLContextProfile profile) CoreProfile/CompatibilityProfile 设置核心或兼容模式
setSamples(int numSamples) numSamples: 采样数 设置多重采样抗锯齿(MSAA)
setDepthBufferSize(int size) size: 深度缓冲位数 设置深度缓冲精度(如 24)

用法示例

// 设置 OpenGL 版本和格式
QSurfaceFormat format;
format.setVersion(3, 3);
format.setProfile(QSurfaceFormat::CoreProfile);
format.setSamples(4); // 4x MSAA

QOpenGLWidget widget;
widget.setFormat(format);

// 重写虚函数实现渲染
class MyGLWidget : public QOpenGLWidget {
protected:
    void initializeGL() override {
        // 初始化 OpenGL 状态和资源
        initializeOpenGLFunctions();
        glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
    }
    void paintGL() override {
        // 执行绘制操作
        glClear(GL_COLOR_BUFFER_BIT);
        // 绘制代码...
    }
    void resizeGL(int w, int h) override {
        // 调整视口等
        glViewport(0, 0, w, h);
    }
};

注意事项

  1. 线程安全:OpenGL 调用必须在拥有上下文的线程中执行(通常为主线程)。

  2. 资源释放:在析构前需调用 doneCurrent() 释放上下文。

  3. 多平台兼容:不同平台对 OpenGL 特性的支持可能不同,需检查 format() 的实际结果。

 

二、QOpenGLWindow

功能:基于窗口的 OpenGL 渲染,比 QOpenGLWidget 更轻量级。适合全屏OpenGL应用。

继承关系:QWindow → QOpenGLWindow
关键特性:

  • 没有 Qt 窗口部件的开销

  • 适合全屏 OpenGL 应用

  • 支持多线程渲染

属性与方法:

QOpenGLWindow 属性表

属性 类型 可读 可写 说明
format QSurfaceFormat ✔️ ✔️ 控制 OpenGL 上下文和表面的格式(版本、采样等)
isValid bool ✔️ 检查 OpenGL 上下文是否有效
textureFormat GLenum ✔️ ✔️ grabFramebuffer() 使用的纹理格式(默认为 GL_RGBA

QOpenGLWindow 核心方法表

1. 初始化与渲染控制
方法 参数 返回值 说明
initializeGL() void 虚函数,初始化 OpenGL 资源(首次显示时调用)
paintGL() void 虚函数,执行 OpenGL 绘制操作
resizeGL(int w, int h) w: 新宽度
h: 新高度
void 虚函数,响应窗口大小变化
makeCurrent() void 绑定 OpenGL 上下文到当前线程
doneCurrent() void 释放当前线程的上下文
2. 上下文与表面
方法 参数 返回值 说明
context() QOpenGLContext* 返回关联的 OpenGL 上下文
defaultFramebufferObject() GLuint 返回默认帧缓冲对象的 ID
isValid() bool 检查上下文和表面是否有效
3. 帧缓冲操作
方法 参数 返回值 说明
grabFramebuffer() QImage 捕获当前帧缓冲为 QImage
grabFramebuffer(const QRect& rect) rect: 截取区域 QImage 捕获指定区域的帧缓冲
4. 信号
方法 参数 返回值 说明
frameSwapped() void 信号,帧交换完成时触发(用于同步)
5. 格式设置
方法 参数 返回值 说明
setFormat(const QSurfaceFormat& format) format: 表面格式 void 设置 OpenGL 上下文格式
format() QSurfaceFormat 返回当前格式

与 QOpenGLWidget 的关键区别

特性 QOpenGLWindow QOpenGLWidget
继承关系 直接继承 QWindow 继承 QWidget
使用场景 更适合全屏/独立窗口应用 适合嵌入 Qt 部件树的 UI
性能开销 更低(无 Qt 部件树开销) 略高(需要处理 Qt 事件系统)
多线程支持 更友好(可与 QOpenGLContext 灵活配合) 需谨慎处理线程绑定
事件处理 直接接收原生窗口事件 通过 Qt 事件系统处理

用法示例:

class MyGLWindow : public QOpenGLWindow {
protected:
    void initializeGL() override {
        initializeOpenGLFunctions();
        glClearColor(0.1f, 0.2f, 0.4f, 1.0f);
    }
    void paintGL() override {
        glClear(GL_COLOR_BUFFER_BIT);
        // 绘制代码...
    }
    void resizeGL(int w, int h) override {
        glViewport(0, 0, w, h);
    }
};

int main(int argc, char **argv) {
    QGuiApplication app(argc, argv);

    QSurfaceFormat format;
    format.setVersion(4, 1);
    format.setProfile(QSurfaceFormat::CoreProfile);

    MyGLWindow window;
    window.setFormat(format);
    window.resize(800, 600);
    window.show();

    return app.exec();
}

注意事项

  1. 线程安全:OpenGL 调用必须在拥有上下文的线程中(通常为主线程)。

  2. 资源管理:在析构前需调用 doneCurrent() 释放上下文。

  3. 平台差异:某些 OpenGL 特性可能在不同平台上表现不同,需测试实际支持情况。

三、QOpenGLFunctions

功能:提供跨平台的 OpenGL ES 2.0+ / OpenGL 1.5+ 函数访问(避免直接使用平台相关的函数指针)。

继承关系:无基类(通常通过 多重继承 或 组合 方式使用)。

关键特性:

  • 确保正确的函数指针在不同平台上可用

  • 通常通过继承或组合方式使用

属性与方法: 

QOpenGLFunctions 核心方法表

1. 初始化
方法 参数 返回值 说明
initializeOpenGLFunctions() bool 初始化函数指针,必须调用后才能使用其他方法
2. 上下文检查
方法 参数 返回值 说明
hasOpenGLFeature(QOpenGLFunctions::OpenGLFeature feature) feature: 要检查的特性(如Multitexture bool 检查当前上下文是否支持特定功能
3. OpenGL 函数封装(常用示例)
方法 等效 OpenGL 函数 参数说明
glClear(GLbitfield mask) glClear mask: 如 GL_COLOR_BUFFER_BIT
glDrawArrays(GLenum mode, GLint first, GLsizei count) glDrawArrays modeGL_TRIANGLES 等
glBindBuffer(GLenum target, GLuint buffer) glBindBuffer targetGL_ARRAY_BUFFER 等
glUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) glUniformMatrix4fv 设置 4x4 矩阵统一变量
glGenTextures(GLsizei n, GLuint* textures) glGenTextures 生成纹理 ID
glGetError() glGetError 返回 OpenGL 错误代码
4. 扩展功能检查
方法 参数 返回值 说明
isInitialized() bool 检查是否已初始化函数指针

OpenGLFeature 枚举(用于功能检查)

枚举值 说明
Multitexture 是否支持多纹理
Shaders 是否支持着色器
Buffers 是否支持 VBO
Framebuffers 是否支持 FBO
BlendColor 是否支持混合颜色

用法示例:

方式1:多重继承
class MyRenderer : public QObject, protected QOpenGLFunctions {
public:
    MyRenderer() {
        initializeOpenGLFunctions(); // 必须初始化
    }

    void render() {
        glClear(GL_COLOR_BUFFER_BIT); // 直接调用封装的OpenGL函数
        glDrawArrays(GL_TRIANGLES, 0, 3);
    }
};
方式2:组合模式
class MyRenderer {
public:
    MyRenderer(QOpenGLContext* context) {
        m_funcs = context->functions();
        m_funcs->initializeOpenGLFunctions();
    }

    void render() {
        m_funcs->glClear(GL_COLOR_BUFFER_BIT);
    }

private:
    QOpenGLFunctions* m_funcs;
};

与原生 OpenGL 的对比

场景 QOpenGLFunctions

网站公告

今日签到

点亮在社区的每一天
去签到