我对调用各种缓冲区函数时发生的过程感兴趣,例如:
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,它们在那里停留多长时间(渲染完成后它们会重置吗?) ,如果一些值发生变化,缓冲区数据是否可以在不重新绑定整个新缓冲区的情况下进行更改,这样我就可以计算出在主循环内外进行哪些调用。
答案 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管理的数据存储的缓冲区对象的整个概念,但内容在用户的控制下完全。您可以更改缓冲区对象的几个字节,而无需重新创建新的缓冲区对象。