在QOpenGLWidget第六篇中我们实现了投影转换和相机空间变换,接下来我们继续往下学习vao、vbo随机绘制线;
用vao绘制线有两种方法,第一种,一个vao一个vbo,但是给vbo分配足够大的内存,然后往vbo中写入随机生成的顶点数据;第二种每一条线段对应一个vao和vbo。在这里我们使用第二种方法。
在前面的章节中我们都是使用QOpenGLVertexBuffer和QOpenGLBuffer实现绘制三棱锥,在后面的章节中我们将不再使用QOpenGLVertexBuffer和QOpenGLBuffer,原因有如下:
1、Qt封装的QOpenGLBuffer和QOpenGLVertexBuffer所占得的内存肯定比GLuint大,因为我们要绘制大量的点线、所以为了减少内存的消耗,我们使用OpenGL原生的Gluint;
2、在paintGL渲染函数中我们发现,绘制线段其实只需要vao对象就可以,其实不需要vbo对象,也就是说绘制实体时,我们只需要保存vao。但是在写代码的时候发现QOpenGLBuffer如果定义为临时变量,实体就会绘制不来。但是使用OpenGL原生的GLuint就可以。
下面我们来进行源码实现:
1、删除initOpenGLWidget绘制的三棱锥;
2、为了保存随机生成的线所对应的vao,我们定义个Qvetor<GLuint> m_vaos;成员变量;
QPoint m_lastPt;
QTimer *m_timer = NULL;
QMatrix4x4 m_mvpMatrix;
QVector<GLuint> m_vaos;
QOpenGLShaderProgram *m_shaderProgram;
MouseStatus m_mouseStatus = kMouseNone;
3、在QTimer的触发槽函数中添加随机生成定点数据;
void OpenGLWidget::timeOut()
{
makeCurrent();
int xVal1 = rand() % 4000;
int yVal1 = rand() % 4000;
int zVal1 = rand() % 4000;
int xVal2 = rand() % 4000;
int yVal2 = rand() % 4000;
int zVal2 = rand() % 4000;
float xVals = xVal1 * 1.0 / 4000 * 2 - 1.0;
float yVals = yVal1 * 1.0 / 4000 * 2 - 1.0;
float zVals = zVal1 * 1.0 / 4000 * 2 - 1.0;
float xVale = xVal2 * 1.0 / 4000 * 2 - 1.0;
float yVale = yVal2 * 1.0 / 4000 * 2 - 1.0;
float zVale = zVal2 * 1.0 / 4000 * 2 - 1.0;
GLuint vao;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
float vertices[] = {
xVals, yVals, zVals, xVals, yVals, zVals,
xVale, yVale, zVale, xVale, yVale, zVale,
};
GLuint indices[] = {
0, 1
};
GLuint vboebo[2];
glGenBuffers(2, vboebo);
glBindBuffer(GL_ARRAY_BUFFER, vboebo[0]);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vboebo[1]);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
//顶点属性设置
m_shaderProgram->setAttributeBuffer("vPosition", GL_FLOAT, 0, 3, sizeof(GLfloat) * 6);
m_shaderProgram->enableAttributeArray("vPosition");
//颜色属性设置
m_shaderProgram->setAttributeBuffer("vColor", GL_FLOAT, sizeof(GLfloat) * 3, 3, sizeof(GLfloat) * 6);
m_shaderProgram->enableAttributeArray("vColor");
m_vaos << vao; repaint();
}
4、在paintGL函数中绘制vao数组中的对象;
void OpenGLWidget::paintGL()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
m_shaderProgram->setUniformValue("gWorld", m_mvpMatrix);
for(auto vao : m_vaos)
{
glBindVertexArray(vao);
glDrawElements(GL_LINES, 2, GL_UNSIGNED_INT, 0);
}
}
最后编译运行: