OpenGL入门第一步:创建窗口、重写虚函数

OpenGL入门第二步:颜色、纹理设置(解析)-CSDN博客

OpenGL入门第三步:矩阵变换、坐标系统-CSDN博客

OpenGL入门第四步:摄像机视角变换与交互-CSDN博客

目录

1、创建一个QOpenGLWidget 子类

2、重写虚函数

3、了解OpenGL绘图,重写函数


1、创建一个QOpenGLWidget 子类

2、重写虚函数

initializeGL:设置OpenGL资源和状态。在第一次调用resizeGL()或paintGL()之前被调用一次。

resizeGL :窗口尺寸变化时调用。

paintGL: 窗口更新时调用,渲染 OpenGL 场景。

makeCurrent: 绑定当前OpenGL上下文。

doneCurrent :释放当前OpenGL上下文。

如果要重绘场景 应该调用 update 而不是 resizeGL

所有跟 OpenGL 相关的操作都应该发生在 initializeGL、resizeGL、paintGL 三个函数内 或者在 调用 makeCurrent 之后。

3、了解OpenGL绘图,重写函数

openGL绘制3d的本质其实就是画三角形,所有的面都是由三角形组成。

要绘制三角形就要了解渲染管线(如下)。

需要我们参与的是顶点着色器、几何着色器(可无)、片段着色器。 

所以在重写虚函数的时候,在initializeGL函数中写着色器。

QOpenGLFunctions* f = context()->functions();:这行代码获取了与 OpenGL 上下文相关的函数指针

 在顶点着色器中通过

layout (location = 0) in vec3 aPos;将位置变量的属性位置值设为0

着色器的另外一种写法(路径默认在bin里面)

设置顶点数据

 先记住下面3个概念。

代码中创建vbo、vao和ebo。把顶点数据放入vbo,把索引放入ebo。

通过调用 enableAttributeArray 方法并传递数组索引(在这里是 0),可以告诉图形渲染引擎要启用对应索引的属性数组。

通过调用setAttributeBuffer 方法设置着色器程序(shaderProgram)的属性缓冲区(attribute buffer)。

  • setAttributeBuffer:这是一个函数调用,用于将属性数据绑定到着色器程序的特定属性位置。

  • 0:表示要绑定的属性位置索引。在这里,索引 0 可能对应着某个特定的顶点属性,比如位置、颜色或其他属性。这个与enableAttributeArray的值对应,这两处都是因为在顶点着色器中设置了0表示位置

  • GL_FLOAT:指定了属性数据的类型。这里使用了 GL_FLOAT,表示浮点型数据。

  • 0:可能是属性数据在缓冲区中的起始偏移量。

  • 3:表示每个顶点属性的组件数量。例如,如果是位置属性,可能有 x、y、z 三个组件。

  • 3 * sizeof(float):计算了每个顶点属性的字节大小。这里假设每个浮点数(float)占用 4 个字节(sizeof(float)),所以 3 * 4 = 12 字节。

 resizeGL函数控制视口

  

 paintGL函数实时绘制

绑定着色器和vao

f->glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);:调用了 glClear 函数来清除颜色缓冲区和深度缓冲区。GL_COLOR_BUFFER_BIT 表示要清除颜色数据,GL_DEPTH_BUFFER_BIT 表示要清除深度数据。通过使用位或操作符 |,将这两个标志组合在一起。

f->glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);:这行代码使用 glDrawElements 函数来绘制三角形。GL_TRIANGLES 指定了要绘制的图元类型为三角形。6 表示绘制要取顶点数(前面设置了索引3个点一组,输入的必须是3的倍数)。GL_UNSIGNED_INT 指定了索引数据的类型为无符号整数。0 有待确认

还有一种三角绘制:

f->glDrawArrays(GL_TRIANGLES, 0, 3);:GL_TRIANGLES:指定要绘制的几何图形类型为三角形。0:表示三角形的起始顶点索引。3:表示要绘制的三角形的顶点数量。

具体代码 

#ifndef OPENGLWIDGET_H
#define OPENGLWIDGET_H

#include <QOpenGLWidget>
#include <QOpenGLShaderProgram>
#include <QOpenGLBuffer>
#include <QOpenGLVertexArrayObject>
#include <QOpenGLTexture>
#include <QElapsedTimer>

QT_BEGIN_NAMESPACE
namespace Ui { class openGLWidget; }
QT_END_NAMESPACE

class openGLWidget : public QOpenGLWidget
{
    Q_OBJECT

public:
    openGLWidget(QWidget *parent = nullptr);
    ~openGLWidget();
protected:
    virtual void initializeGL() override;
    virtual void resizeGL(int w, int h) override;
    virtual void paintGL() override;

private:
    QOpenGLShaderProgram shaderProgram;
    QOpenGLBuffer vbo;
    QOpenGLBuffer ebo {QOpenGLBuffer(QOpenGLBuffer::IndexBuffer)};
    QOpenGLVertexArrayObject vao;

private:
    Ui::openGLWidget *ui;
};
#endif // OPENGLWIDGET_H
#include "openGLWidget.h"
#include "./ui_openGLWidget.h"

#include <QOpenGLFunctions>
#include <QtMath>

openGLWidget::openGLWidget(QWidget *parent)
    : QOpenGLWidget(parent)
    , ui(new Ui::openGLWidget)
{
    ui->setupUi(this);
}

openGLWidget::~openGLWidget()
{
    makeCurrent();
    vao.destroy();
    vbo.destroy();
    ebo.destroy();
    doneCurrent();
    delete ui;
}

void openGLWidget::initializeGL()
{
    // 设置用来清空屏幕的颜色 这里设置为黑色
    QOpenGLFunctions *f = context()->functions();
    f->glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
    // 顶点着色器
    shaderProgram.addCacheableShaderFromSourceCode(QOpenGLShader::Vertex, R"(
        #version 330 core
        layout (location = 0) in vec3 aPos;// 位置变量的属性位置值为0

        void main()
        {
            gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0); // 注意我们如何把一个vec3作为vec4的构造器的参数
        }
    )");
    // 片段着色器
    shaderProgram.addCacheableShaderFromSourceCode(QOpenGLShader::Fragment, R"(
        #version 330 core
        out vec4 FragColor;

        void main()
        {
            FragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f);
        }
    )");
    // 编译链接
    if(!shaderProgram.link()) {
        qDebug() << shaderProgram.log();
    };
    // 顶点数据
    float vertices[] = {
        0.5f, 0.5f, 0.0f,   // 右上角
        0.5f, -0.5f, 0.0f,  // 右下角
        -0.5f, -0.5f, 0.0f, // 左下角
        -0.5f, 0.5f, 0.0f   // 左上角
    };
    // 顶点索引
    uint indices[] = {
        // 注意索引从0开始!
        // 此例的索引(0,1,2,3)就是顶点数组vertices的下标,
        // 这样可以由下标代表顶点组合成矩形

        0, 1, 3, // 第一个三角形
        1, 2, 3  // 第二个三角形
    };
    // 创建VAO VBO EBO
    vao.create();
    vao.bind();
    vbo.create();
    vbo.bind();
    ebo.create();
    ebo.bind();
    vbo.allocate(vertices, sizeof(vertices));
    ebo.allocate(indices, sizeof(indices));
    shaderProgram.enableAttributeArray(0);
    shaderProgram.setAttributeBuffer(0, GL_FLOAT, 0, 3, 3 * sizeof(float));
}

void openGLWidget::resizeGL(int w, int h)
{
    // 窗口尺寸发生变化时,设置视口大小, 这里把视口设置与窗口一样大
    QOpenGLFunctions *f = context()->functions();
    f->glViewport(0, 0, w, h);
}

void openGLWidget::paintGL()
{
    QOpenGLFunctions* f = context()->functions();
    f->glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    shaderProgram.bind();
    vao.bind();
    f->glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
}

  • 11
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值