在OpenGL中,除非我再次重新指定顶点属性,否则为啥我的缓冲区对象不会绘制?
Posted
技术标签:
【中文标题】在OpenGL中,除非我再次重新指定顶点属性,否则为啥我的缓冲区对象不会绘制?【英文标题】:In OpenGL why won't my buffer object draw unless I respecify the vertex attributes again?在OpenGL中,除非我再次重新指定顶点属性,否则为什么我的缓冲区对象不会绘制? 【发布时间】:2016-12-02 23:10:14 【问题描述】:我认为 VAO(顶点数组对象)应该像顶点属性一样存储状态。当我创建一个 VBO 时,我指定了我的顶点属性:
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)nullptr);
glEnableVertexAttribArray(0);
// And so on
如果我绑定另一个 VBO,我必须调用 glVertexAttribPointer 和 glEnableVertexAttribArray 三次,这是每次我切换我的 VBO 时。我只有一个VAO,我从不改变它。有什么不对?我只使用一个顶点布局,如果每次切换时它都会丢失这些信息,我不明白 VAO 会做什么。每个 VAO 是否只有一个 VBO?
【问题讨论】:
【参考方案1】:如果您不想在调用 glDraw* 函数之前重新指定 glVertexAttribPointer,那么您需要多个 VAO 而不仅仅是一个。我认为您混淆了 VBO 和 VAO 是什么。 VBO 只是一块包含数据的惰性内存。 VAO 包含 OpenGL 绘制网格所需的所有信息,包括: - 对包含顶点数据的 Buffer 对象的引用(通常称为 VBO) - 对包含顶点索引的 Buffer 对象的引用(如果您使用 glDrawElements*) - 您将要使用的不同顶点属性的索引及其在包含顶点数据的 Buffer 对象中的布局(使用 glEnableVertexAttribArray 和 glVertexAttribPointer 指定)
所以基本上对于你要绘制的每个网格,你都需要准备一个相应的 vao:
// at scene preparation time
glBindVertexArray(vaoA); // the following functions will only affect vaoA
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_buffer_of_meshA);
glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer_of_meshA);
foreach attrib of meshA
glEnableVertexAttribArray(***);
glVertexAttribPointer(***)
glBindVertexArray(0)
glBindVertexArray(vaoB); // the following functions will only affect vaoB
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_buffer_of_meshB);
glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer_of_meshB);
foreach attrib of meshB
glEnableVertexAttribArray(***);
glVertexAttribPointer(***)
glBindVertexArray(0)
//And now at render time:
void render()
glBindVertexArray(vaoA);
glDrawElements(***);
glBindVertexArray(vaoB);
glDrawElements(***);
更多信息请查看:https://www.opengl.org/wiki/Vertex_Specification
【讨论】:
以上是关于在OpenGL中,除非我再次重新指定顶点属性,否则为啥我的缓冲区对象不会绘制?的主要内容,如果未能解决你的问题,请参考以下文章
openGL之API学习(一六六)glVertexAttrib*函数