OpenGL with QtWidgets:在Qt中使用OpenGL绘制一个三角形

(本文是LearnOpenGL的学习笔记,教程中文翻译地址https://learnopengl-cn.github.io/

0.前言

LearnOpenGL教程目前使用的是glfw+glad的方式来使用OpenGL,而在Qt Widgets框架中也封装了相应的类,并且配合其他工具类,操作起来更加方便。

1.如何实现

在Qt旧版本中,提供有QGLWidget类,从Qt5.4开始提供了QOpenGLWidget类,我们只需要继承并实现相应接口,就可以使用OpenGL绘制一个Qt组件(其中使用OpenGL函数还要借助QOpenGLFunctions相关的类):

class GLTriangle : public QOpenGLWidget, protected QOpenGLFunctions_3_3_Core
{}

继承之后,只需要实现三个虚函数接口,就可以实现绘制:

    //设置OpenGL资源和状态。在第一次调用resizeGL或paintGL之前被调用一次
    void initializeGL() override;
    //渲染OpenGL场景,每当需要更新小部件时使用
    void paintGL() override;
    //设置OpenGL视口、投影等,每当尺寸大小改变时调用
    void resizeGL(int width, int height) override;

QOpenGLWidget是继承自QWidget的,所以做好的组件类像其他Widget类那样使用就行了。

在教程中,是自己封装着色器程序类,Qt已经封装好了一个 QOpenGLShaderProgram,我们可以直接用它。此外还提供了QOpenGLVertexArrayObject、QOpenGLBuffer等封装好的类供我们使用,不过目前主要是简易移植教程代码,尽量使用原有的代码就行了。

剩下的,就是把LearnOpenGL代码移植到QtWidgets中。

2.实现代码

(项目git链接:https://github.com/gongjianbo/OpenGLwithQtWidgets.git

我的GLTriangle类和GLElement类效果图:

其中三角形的实现代码:

#ifndef GLTRIANGLE_H
#define GLTRIANGLE_H

#include <QOpenGLWidget>
#include <QOpenGLFunctions_3_3_Core>
#include <QOpenGLShaderProgram>

//绘制三角形
class GLTriangle : public QOpenGLWidget, protected QOpenGLFunctions_3_3_Core
{
    Q_OBJECT
public:
    explicit GLTriangle(QWidget *parent = nullptr);
    ~GLTriangle();

protected:
    //设置OpenGL资源和状态。在第一次调用resizeGL或paintGL之前被调用一次
    void initializeGL() override;
    //渲染OpenGL场景,每当需要更新小部件时使用
    void paintGL() override;
    //设置OpenGL视口、投影等,每当尺寸大小改变时调用
    void resizeGL(int width, int height) override;

private:
    QOpenGLShaderProgram _shaderProgram;
    GLuint _VAO;
    GLuint _VBO;
};

#endif // GLTRIANGLE_H
#include "GLTriangle.h"

GLTriangle::GLTriangle(QWidget *parent)
    : QOpenGLWidget(parent)
{

}

GLTriangle::~GLTriangle()
{
    glDeleteVertexArrays(1, &_VAO);
    glDeleteBuffers(1, &_VBO);
}

void GLTriangle::initializeGL()
{
    //为当前上下文初始化OpenGL函数解析
    initializeOpenGLFunctions();

    //着色器代码
    //in输入,out输出,uniform从cpu向gpu发送
    const char *vertex_str=R"(#version 330 core
                           layout (location = 0) in vec3 vertices;
                           void main() {
                           gl_Position = vec4(vertices,1.0);
                           })";
    const char *fragment_str=R"(#version 330 core
                             uniform vec3 myColor;
                             void main() {
                             gl_FragColor = vec4(myColor,1.0);
                             })";

    //将source编译为指定类型的着色器,并添加到此着色器程序
    if(!_shaderProgram.addCacheableShaderFromSourceCode(
                QOpenGLShader::Vertex,vertex_str)){
        qDebug()<<"compiler vertex error"<<_shaderProgram.log();
    }
    if(!_shaderProgram.addCacheableShaderFromSourceCode(
                QOpenGLShader::Fragment,fragment_str)){
        qDebug()<<"compiler fragment error"<<_shaderProgram.log();
    }
    //使用addShader()将添加到该程序的着色器链接在一起。
    if(!_shaderProgram.link()){
        qDebug()<<"link shaderprogram error"<<_shaderProgram.log();
    }

    //从LearnOpenGL移植过来
    float vertices[] = {
        -0.5f, -0.5f, 0.0f, // left
        0.5f, -0.5f, 0.0f, // right
        0.0f,  0.5f, 0.0f  // top
    };
    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);

    //unbind
    glBindBuffer(GL_ARRAY_BUFFER, 0);
    glBindVertexArray(0);
}

void GLTriangle::paintGL()
{
    glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT);

    _shaderProgram.bind();
    //传递值
    _shaderProgram.setUniformValue("myColor", QVector3D(0.0f,1.0f,0.0f));
    //绘制三角
    glBindVertexArray(_VAO);
    glDrawArrays(GL_TRIANGLES, 0, 3);

    _shaderProgram.release();
}

void GLTriangle::resizeGL(int width, int height)
{
    glViewport(0,0,width,height);
}

 4.参考

Qt文档:https://doc.qt.io/qt-5.12/qopenglwidget.html

博客:https://www.jianshu.com/p/bccc565b5248

发布了106 篇原创文章 · 获赞 31 · 访问量 13万+

猜你喜欢

转载自blog.csdn.net/gongjianbo1992/article/details/104113006