如何在OpenGL中增加缓冲区?

如何在OpenGL中增加缓冲区?,opengl,Opengl,是否可以在OpenGL中增加缓冲区 假设我想使用实例渲染。每次在世界上产生一个新对象时,我都必须用实例数据更新缓冲区 在这种情况下,我有一个3个浮点数的缓冲区 std::vector<GLfloat> offsets = {0.0f,0.5f,1.0f}; auto offset_buffer = buffer::makeBuffer(BufferDraw::STATIC_DRAW, offsets); std::vector offset={0.0f,0.5f,1.0f}

是否可以在OpenGL中增加缓冲区

假设我想使用实例渲染。每次在世界上产生一个新对象时,我都必须用实例数据更新缓冲区

在这种情况下,我有一个3个浮点数的缓冲区

  std::vector<GLfloat> offsets = {0.0f,0.5f,1.0f};
  auto offset_buffer = buffer::makeBuffer(BufferDraw::STATIC_DRAW, offsets);
std::vector offset={0.0f,0.5f,1.0f};
自动偏移量=缓冲区::makeBuffer(BufferDraw::静态偏移量);

如果我想要4个元素呢?我必须调用更大大小的glBufferData吗?但旧数据会发生什么情况,会被复制吗?还是我必须完全删除缓冲区并创建一个新的缓冲区

您肯定不会用新的大小调用
glBufferData(…)
。这将孤立旧的缓冲区,并为您提供一个具有更大存储空间的新缓冲区(其内容与以前分配的内存无关)

旧数据将继续存在,只要之前需要它的任何OpenGL命令仍在管道中排队。在这些命令完成后,OpenGL允许回收内存-您不必担心泄漏,但就地增长不会自动发生

GL 3.1引入了复制缓冲区的概念,这将帮助您更高效地执行此操作

考虑下面的伪代码:
在实际情况下,可以将缓冲区数据从任何绑定位置复制到任何其他绑定位置。新的
GL\u COPY\u…\u BUFFER
绑定点很方便,但不是必需的,因为它们不会干扰任何其他绑定。

有一个扩展可以做到这一点,否则您将需要分配新的缓冲区并复制数据并填写新的。否则,旧数据会丢失。我可以直接从OpenGL复制数据,还是必须再次从ram发送到vram?@ratchetfreak:这是哪个扩展?我唯一想到的是。您可以保留比所需更大的缓冲区,然后在填充缓冲区时提交内存页,但扩展所需的最小页大小为64 KiB,浮点值仅为4字节;)在复制数据后,是否可以将新\u缓冲区的句柄更改为旧\u缓冲区的句柄?否则,我将不得不创建一个新的vao。@MaikKlein:嗯,在将数据复制到
new\u buffer
之后,您可以随时调用
glBufferData(…)
上的
old\u buffer
,然后将数据复制回来。在调整原始缓冲区的大小时,可以有效地使用“
new\u buffer
”作为备份,而不会使存储在VAO中的顶点指针无效。当然,如果可以的话,您应该通过过度分配知道将要增长的缓冲区来避免小的增量增长(与制作多个拷贝相关的驱动程序开销相比,少量的内存浪费通常更可取)@MaikKlein如果你预先设置了旧的缓冲区和新的缓冲区,你就可以孤立旧的缓冲区和
交换(旧的缓冲区,新的缓冲区)
// Bind the old buffer to `GL_COPY_READ_BUFFER`
glBindBuffer (GL_COPY_READ_BUFFER, old_buffer);

// Allocate data for a new buffer
glGenBuffers (1, &new_buffer);
glBindBuffer (GL_COPY_WRITE_BUFFER, new_buffer);
glBufferData (GL_COPY_WRITE_BUFFER, ...);

// Copy `old_buffer_size`-bytes of data from `GL_COPY_READ_BUFFER`
//   to `GL_COPY_WRITE_BUFFER` beginning at 0.
glCopyBufferSubData (GL_COPY_READ_BUFFER, GL_COPY_WRITE_BUFFER, 0, 0, old_buffer_size);