最近在做一个opengl的项目,我需要实现的是打开一个mesh数据然后经过opengl进行渲染。发现一个问题,当我先加载网格的顶点数据到array中,然后再调用初始化initializeGL(), 然后paintGL() 这个流程没问题。但是由于我自己重写了openglwidget,所以控件加载完毕之后肯定会调用initializeGL,但是intializeGL的代码如下
void ViewGLWidget::initializeGL()
{
initializeOpenGLFunctions();
//set the background color of the opengl window
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
initShader();
m_vao.create();
m_vao.bind();
m_vbo = QOpenGLBuffer(QOpenGLBuffer::VertexBuffer);
m_vbo.create();
m_vbo.bind();
//m_meshVertxArray stores all the vertices, one vertex
m_vbo.allocate((void *)m_meshVertxArray.data(), sizeof(GLfloat) * m_meshVertxArray.size()*3);
m_shader.setAttributeBuffer(0, GL_FLOAT, 0, 3, sizeof(GLfloat)* 3);
m_shader.enableAttributeArray(0);
m_vbo.release();
m_vao.release();
}
这里已经绑定了顶点数据,但是由于我开始没有加载模型数据,因此这个m_meshVertxArray是空的。那么我们就需要加载完毕之后进行更新数据。试了很多次,把initializeGL代码放到updateVertices之后也不行。一直没有图像或者崩溃,后来我读了 Qt官方关于opengl的例子的helloQt 里面有一个函数
void GLWidget::setupVertexAttribs()
{
m_logoVbo.bind();
QOpenGLFunctions *f = QOpenGLContext::currentContext()->functions();
f->glEnableVertexAttribArray(0);
f->glEnableVertexAttribArray(1);
f->glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat),
nullptr);
f->glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat),
reinterpret_cast<void *>(3 * sizeof(GLfloat)));
m_logoVbo.release();
}
我在想他为什么要单独写成一个函数,读一下逻辑就是再更新vbo的操作。因此我测试了一下,在更新完顶点数据之后更新vbo的数据,果然可以显示了。
结论:vao和vbo的创建必须要在opengl的上下文中进行,我找资料又看到,后面可以更新一下链接,因此vao和vbo的创建需要在initializeGL函数里面,而不能再别的地方。其他地方需要更新vbo的数据即可,不能再次创建
网友评论