opengl 3+缓冲操作

时间:2014-03-23 17:57:36

标签: c++ opengl

我对调用各种缓冲区函数时发生的过程感兴趣,例如:

GLuint vertexbuffer;
glGenBuffers(1, &vertexbuffer);
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat)*power*12, g_vertex_buffer_data, GL_STATIC_DRAW);

在我接下来的教程中,在用坐标填充顶点数组之后调用它。然后在主循环内部为每个帧调用它:

glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)0 );

glDrawArrays(GL_TRIANGLE_STRIP, 0, 4*power);

glDisableVertexAttribArray(0);

如果缓冲区填充了常量值的数据,是否有必要在每次迭代中进行这些调用?是不是可以在循环之前绑定缓冲区,设置glVertexAttribPointer并从缓冲区循环和绘制?

我会对每次调用所发生的过程感兴趣,例如哪一​​个指示cpu将缓冲区内的数据发送到gpu,它们在那里停留多长时间(渲染完成后它们会重置吗?) ,如果一些值发生变化,缓冲区数据是否可以在不重新绑定整个新缓冲区的情况下进行更改,这样我就可以计算出在主循环内外进行哪些调用。

1 个答案:

答案 0 :(得分:2)

OpenGL是一个状态机,因此在您明确请求更改之前,所有内容都将保持不变。数据将在glBufferData()调用时复制到缓冲区中(至少从用户的角度来看。当数据实际发送到GPU时,将完全控制GL实现。但是就API而言,在返回glBufferData调用之后,可以认为数据存储在该缓冲区对象中)。

只有在实际更改时,才需要为每次绘制调用重新设置顶点属性指针。请注意,在GL_ARRAY_BUFFER调用时,对当前绑定的glVertexAttribPointer()的引用将变为属性指针状态的一部分,因此如果必须重新指定属性指针,你想要从变化中抽取的VBO,即使这个函数的所有参数都保持不变。 这也意味着,与一些常见的误解相反,调用GL_ARRAY_BUFFER时绑定glDrawArrays无关紧要。

  

如果缓冲区填充了常量值的数据,是否有必要   在每次迭代中进行这些调用?是不是有可能   在循环之前绑定缓冲区,设置glVertexAttribPointer和just   从缓冲区循环并绘制?

可以将此状态设置一次,并在内循环中进行绘制调用 - 只要没有其他绘制调用,则需要不同的属性指针状态。 请注意,在现代GL中,还有Vertex Array Objects封装了顶点属性指针状态,因此您只需为对象(或对象组,或者您可能拥有的任何绘制调用)设置一次VAO,并且可以只需再次绑定VAO即可轻松切换它们。

  

我会对每一个发生的过程感兴趣   调用,例如哪个调用指示cpu发送数据   缓冲区到gpu,

正如我已经提到的,GL API没有公开这样的实现细节,就像数据实际移动到GPU一样(GL甚至不需要GPU,只有软件实现)。但是,发明了使用提示以帮助GL实现决定存储缓冲区数据的位置。 GL_STATIC_DRAW VBO可能只会传输一次到GPU并存储在VRAM中(如果有这样的话)。

  

他们待在那里多久(他们会在什么时候重置   渲染完成?),

没有你请求它就没有重置,并且"渲染完成"这不是一个有意义的概念。什么时候会是这样? 在内部,如果存在内存压力,GL实现可能会选择从VRAM中删除一些缓冲区,但该过程对用户完全透明。缓冲区对象仍然存在且可用(但性能可能更差,但如果您的内存不足,则无法避免这种情况。)

  

缓冲区数据可以更改而无需重新绑定a   如果一些值发生变化,整个新的缓冲区,以便我可以计算出来   它调用在主循环的内部和外部。

我并不完全理解这个问题。即使绑定了新的缓冲区,缓冲区数据也不会改变。它们是由GL管理的数据存储的缓冲区对象的整个概念,但内容在用户的控制下完全。您可以更改缓冲区对象的几个字节,而无需重新创建新的缓冲区对象。