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