【问题标题】:Reassign shader buffer value重新分配着色器缓冲区值
【发布时间】:2018-08-29 00:48:28
【问题描述】:

this question about growing buffers,有人用以下代码回答。

// 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);

这是我对上面的理解,为了复制A到B:

Bind A
Generate B
Bind B
Write null contents to B at larger size
Copy A to B

我的问题是 A 是着色器的原始顶点缓冲区,但 B 也是(因为改变大小是目标)。在我的代码(C# opentk)中,着色器告诉我缓冲区的 ID 与使用 GL.GetActiveAttrib 的命名着色器变量一致,我找不到如何使它使用与它提供的缓冲区不同的缓冲区。

所以我要么必须重新分配着色器以在之后使用 B,要么进行双重复制:

Bind A
Generate B
Bind B
Write null contents to B at larger size
Copy A to B
Reassign shader to use B
Write null contents to A at larger size (size of B)
Copy B to A

是否可以让它使用特定的缓冲区或避免重复复制?

【问题讨论】:

  • waht 有 GetActiveAttrib 与任何缓冲区对象名称有关。着色器不关心缓冲区,只关心属性。所以最简单的方法就是相应地更新属性指针。

标签: opengl shader


【解决方案1】:

一旦你用glBufferData 设置了缓冲区的大小,这个大小就变得不可变了。这就是为什么需要复制到另一个更大的缓冲区B

好消息是您可以将缓冲区重新绑定到不同的目标。这就是您可以在缓冲区管理器中执行的操作(您似乎错误地将其称为“着色器”。着色器是 GPU 中的一个程序)。不需要第二份。

如果您想保留以前的绑定,GL_COPY_READ_BUFFERGL_COPY_WRITE_BUFFER 目标很有用。这不是你的情况,所以副本更简单:

//The buffer must be bound before copying it
glBindBuffer(GL_ARRAY_BUFFER, oldBuf); //or GL_ELEMENT_ARRAY_BUFFER or whatever it was
//New buffer
glGenBuffers (1, &newBuf);
//GL_COPY_WRITE_BUFFER is needed because GL_ARRAY_BUFFER is in use by oldBuf
glBindBuffer (GL_COPY_WRITE_BUFFER, newBuf);
glBufferData (GL_COPY_WRITE_BUFFER, newSize, ...);
glCopyBufferSubData (GL_ARRAY_BUFFER, GL_COPY_WRITE_BUFFER, 0, 0, old_buffer_size);

现在复制完成,缓冲区oldBuf可以安全删除了。

还有两件事要做:

a) Tell the buffer-manager to use 'newBuf' insted of 'oldBuf'
b) Before using this new buffer, re-bind it to the target you need
   glBindBuffer(GL_ARRAY_BUFFER, newBuf);

嗯,还有一件事要做。当 VAO 被绑定并且 glVertexAttribPointer 建立关联“属性 - 要读取的缓冲区”时,它使用了 oldBuf 缓冲区。但现在你想要另一个缓冲区。所以你必须再次绑定那个 VAO,绑定新的缓冲区并使用 glVertexAttribPointer。


更好的解决方案可能是拥有一个大缓冲区,并且只使用其中的一部分。假设您有一个用于一百万个顶点的 VBO。 1M x 3 浮点 x 4 字节 = 12M 字节。这不是任何不太老的 GPU 都无法处理的大小。

如果您的数据大小发生变化,但没有超过 1M 顶点,那么最简单的方法是使用 glBufferSubData 并上传新数据,即使它只是添加的数据。没有新的缓冲区,没有复制,没有 VAO 状态变化。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-10-25
    • 2011-05-21
    • 2018-10-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多