基于Qt的Opengl可编程管线学习—— VBO(QOpenGLBuffer的使用)

再一次赞扬Qt对OPenGL的支持真的是太棒了。之前一片文章介绍绘制三角形时,顶点位置数据与颜色数据是分开传递的。这篇文章将介绍如何使用Qt的VBO进行顶点数据传递以及数据格式解析。

一、VBO的基本使用流程

基于Qt的Opengl可编程管线学习—— VBO(QOpenGLBuffer的使用)_第1张图片

上图中是QOpenGLBuffer对象的使用方式,使用VBO之前必须调用create()创建。使用时,调用bind()。以告知OPenGL我们在使用的VBO。调用allocate()为VBO对象分配内存传递数据。有了数据还要告知OPenGL数据格式。VBO使用结束解除绑(养成一个好习惯);程序结束VBO自然没有用了,不要忘了调用destroy()释放它。

二、数据格式的设定

数据存放在连续的内存中,要告知OPenGL如何解析数据。方法是调用:void QOpenGLShaderProgram::setAttributeBuffer(int location, GLenum type, int offset, int tupleSize, int stride = 0)参数一:属性位置;参数三:偏移量。一个顶点的所有属性数据视为一组,offset指定某属性距该组最开始的字节数。最后一个参数:一个顶底的所有字节数。

三、绘制

数据准备好,着色器程序编译链接好,moel view projection 矩阵设定好,接着就可以绑定VBO进行绘制了。再次强调VBO用完就解绑了。

四、编码

/头文件

#ifndef OPENGL_WIDGET_H
#define OPENGL_WIDGET_H

#include 
#include 
#include 
#include 
#include 

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();

private:
    QOpenGLShaderProgram *m_program;
    QOpenGLBuffer        m_vbo;
    int                  m_matrixUniform;
    QMatrix4x4           m_pMat;
};

#endif // OPENGL_WIDGET_H




源文件
#include "opengl_widget.h"

OpenGLWidget::OpenGLWidget(QWidget *parent)
    : QOpenGLWidget(parent),
      m_program(nullptr),
      m_vbo(QOpenGLBuffer::VertexBuffer),
      m_matrixUniform(0),
      m_pMat()
{
}

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

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

    m_vbo.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();
}

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);
    m_vbo.bind();
    glDrawArrays(GL_TRIANGLES, 0, 3);
    m_vbo.release();

    m_program->release();
}

void OpenGLWidget::makeObject()
{
    float arrVertex[] = {
        //   position                 color
        0.0f, 0.707f, 0.0f,     1.0f, 0.0f, 0.0f,
        -0.5f, -0.5f, 0.0f,     0.0f, 1.0f, 0.0f,
        0.5f, -0.5f,  0.0f,     0.0f, 0.0f, 1.0f,
    };

    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();
}

 

/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;
}

这次使用的是Qt OPenGLES2.0的东西功能,绘制一个三角形。下一篇将记录Qt OPenGL 纹理。

你可能感兴趣的:(/***OpenGL**/,Qt,Qt,VBO,OpenGLes2.0,opengl,shader)