基于Qt的Opengles可编程管线学习——VAO(QOpenGLVertexArrayObject的使用)

标准OPenGLes2.0还没有引进VAO,应该是OpenGL3.0以后才有。不过Qt封装的OPenGLes2.0可以使用VAO,它就是QOpenGLVertexArrayObject。其用法与OpenGL3.0中的VAO用法一样。本文假设您熟悉OpenGL的vao。接下来我们一起来学习这个类的用法。

一、QOpenGLVertexArrayObject的使用流程

和VBO用法(可参考博主另外一篇博文)一样首先要调用QOpenGLVertexArrayObject::create()创建该对象。创建成功您就可以对它绑定某个VBO的状态,需要绘制时将其绑定到OPenGL上下文,最后要销毁掉。做法如下:

1.初始化: 

Bind the VAO ----> Set vertex data state for this visual object --->  Unbind (release()) the VAO

2.渲染:

Bind the VAO ----> Call a glDraw*() function ---->  Unbind (release()) the VAO

二、示例代码

#ifndef OPENGL_WIDGET_H
#define OPENGL_WIDGET_H

#include <QOpenGLFunctions>
#include <QOpenGLWidget>
#include <QOpenGLShader>
#include <QOpenGLShaderProgram>
#include <QOpenGLBuffer>
#include <QOpenGLVertexArrayObject>

class OpenGLWidget : public QOpenGLWidget,
        protected QOpenGLFunctions
{
    Q_OBJECT

public:
    explicit OpenGLWidget(QWidget *parent = nullptr);
    ~OpenGLWidget();

protected:
    virtual void initializeGL() override;
    virtual void resizeGL(int w, int h) override;
    virtual void paintGL() override;

private:
    void makeObject();
    void makeObject_2();
    void setVertexAttribute();
private:
    QOpenGLShaderProgram        *m_program;
    QOpenGLBuffer               m_vbo;
    int                         m_matrixUniform;
    QMatrix4x4                  m_pMat;
    QOpenGLVertexArrayObject    m_vao;
    QOpenGLBuffer               m_vbo_2;
    QOpenGLVertexArrayObject    m_vao_2;
};

#endif // OPENGL_WIDGET_

/

#include "opengl_widget.h"
OpenGLWidget::OpenGLWidget(QWidget *parent)
    : QOpenGLWidget(parent),
      m_program(nullptr),
      m_vbo(QOpenGLBuffer::VertexBuffer),
      m_matrixUniform(0),
      m_pMat(),
      m_vao(),
      m_vbo_2(QOpenGLBuffer::VertexBuffer),
      m_vao_2()
{
}

OpenGLWidget::~OpenGLWidget()
{
    m_vbo.destroy();
    m_vbo_2.destroy();

    m_vao.destroy();
    m_vao_2.destroy();
}

void OpenGLWidget::initializeGL()
{
    initializeOpenGLFunctions();
    glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
    makeCurrent();

    m_vbo.create();
    m_vbo_2.create();

    m_program = new QOpenGLShaderProgram(this);
    m_program->addShaderFromSourceFile(QOpenGLShader::Vertex,
                                       ":/vertex_shader.glsl");
    m_program->addShaderFromSourceFile(QOpenGLShader::Fragment,
                                       ":/fragment_shader.glsl");

    if (!m_program->link())
        close();

    m_matrixUniform = m_program->uniformLocation("matrix");

    makeObject();
    makeObject_2();
}

void OpenGLWidget::resizeGL(int w, int h)
{
    float aspect = float(w)/float(h?h:1);
    float fov = 45.0f, zNear = 0.1f, zFar = 100.f;
    m_pMat.setToIdentity();
    m_pMat.perspective(fov, aspect, zNear, zFar);
}

void OpenGLWidget::paintGL()
{
    glClear(GL_COLOR_BUFFER_BIT);

    m_program->bind();

    QMatrix4x4 mvMat;
    mvMat.translate(0.0f, 0.0f, -3.0f);
    m_program->setUniformValue(m_matrixUniform, m_pMat*mvMat);
    {
        QOpenGLVertexArrayObject::Binder vaoBind(&m_vao_2);
        glDrawArrays(GL_TRIANGLE_STRIP, 0, 3);
    }
    {
        QOpenGLVertexArrayObject::Binder vaoBind(&m_vao);
        glDrawArrays(GL_TRIANGLE_STRIP, 0, 3);
    }
    m_program->release();
}

void OpenGLWidget::makeObject()
{
    makeCurrent();

    float arrVertex[] {
        //   position                 color
        0.0f, 0.5f, 0.0f,     1.0f, 0.0f, 0.0f,
        0.0f, -0.5f, 0.0f,     0.0f, 1.0f, 0.0f,
        -1.0f, 0.0f,  0.0f,     0.0f, 0.0f, 1.0f
    };

    QOpenGLVertexArrayObject::Binder vaoBind(&m_vao);
    m_vbo.bind();
    m_vbo.allocate(arrVertex, sizeof(arrVertex));

    int attr = -1;
    attr = m_program->attributeLocation("posAttr");
    m_program->setAttributeBuffer(attr, GL_FLOAT, 0,
                                  3, sizeof(float) * 6);
    m_program->enableAttributeArray(attr);

    attr = m_program->attributeLocation("colAttr");
    m_program->setAttributeBuffer(attr, GL_FLOAT, 3 * sizeof(float),
                                  3, sizeof(float) * 6);
    m_program->enableAttributeArray(attr);
    m_vbo.release();
}
void OpenGLWidget::makeObject_2()
{
    makeCurrent();

    float arrVertex[] {
        //   position                 color
        0.0f, 0.5f, 0.0f,     1.0f, 0.0f, 0.0f,
        0.0f, -0.5f, 0.0f,     0.0f, 1.0f, 0.0f,
        1.0f, 0.0f,  0.0f,     0.0f, 0.0f, 1.0f
    };

    QOpenGLVertexArrayObject::Binder vaoBind(&m_vao_2);
    m_vbo_2.bind();
    m_vbo_2.allocate(arrVertex, sizeof(arrVertex));

    int attr = -1;
    attr = m_program->attributeLocation("posAttr");
    m_program->setAttributeBuffer(attr, GL_FLOAT, 0,
                                  3, sizeof(float) * 6);
    m_program->enableAttributeArray(attr);

    attr = m_program->attributeLocation("colAttr");
    m_program->setAttributeBuffer(attr, GL_FLOAT, 3 * sizeof(float),
                                  3, sizeof(float) * 6);
    m_program->enableAttributeArray(attr);
    m_vbo_2.release();
}

/v s///

#ifdef GL_ES
// Set default precision to medium
precision mediump int;
precision mediump float;
#endif

attribute vec4 posAttr;
attribute vec4 colAttr;
varying vec4 col;
uniform mat4 matrix;

void main()
{
    col = colAttr;
    gl_Position = matrix * posAttr;
}

/f s/


#ifdef GL_ES
// Set default precision to medium
precision mediump int;
precision mediump float;
#endif

varying vec4 col;

void main()
{
    gl_FragColor = col;
}

三、运行结果

程序运行结果如下图所示是两个挨一起的三角形

四、总结

QOpenGLVertexArrayObject的使用很简单。就像Qt文档所说:This class(QOpenGLVertexArrayObject::Binder) is to QOpenGLVertexArrayObject as QMutexLocker is to QMutex.这句话的要表达的意思是:借助Binder类绑定时,Binder对象析构时会调用vao.release();

之前一直有个疑问,我要在一个场景中使用多个VBO,绘制多个物体如何实现。没错就是VAO。

  • 5
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值