【发布时间】:2013-08-18 16:01:19
【问题描述】:
所以我有一个系统(使用 OpenGL 4.x),我从外部源接收点流(可能带有颜色和/或正常)。我需要将这些点绘制为 GL_POINTS,运行自定义可切换着色器进行着色(颜色可以通过程序生成,或者来自顶点颜色或法线方向)。
流包括以相当规则的间隔(4 到 10 赫兹)接收一组任意计数(通常从 1k 到 70k 点)的点(有或没有法线或颜色),我需要添加这些点到我目前的积分并绘制所有积分到目前为止收到的积分。
我保证我的顶点类型不会改变,我在流式传输开始时被告知,所以我要么使用交错顶点:pos+normal+color、pos+normal、pos+color ,或者只是pos。
我当前的解决方案是在指定最大顶点数的配置文件中分配适当顶点类型的交错顶点 VBO(与周围的 VAO)(使用 DYNAMIC 提示分配)。
随着新点的出现,我通过 glBufferSubData 填充了我当前未填充的 VBO。我保留了当前边界 VBO 到目前为止有多少个顶点的计数(activePoints),如果我当前的更新组的顶点数超过我的边界缓冲区(因为我限制每个 VBO 的顶点数),然后我分配一个新的 VBO 并填充从 0 开始并以我的更新组中剩余的点数(未添加到最后一个缓冲区)结束的范围,如果我还有剩余点我一次又一次地这样做。很少有更新组跨越 2 个以上的缓冲区。
渲染时,我使用 glDrawArrays(m_DrawMode,0,numVertices) 渲染我的所有 VBO (-1),其中 numVertices 等于最大缓冲区允许大小,我的边界缓冲区使用 glDrawArrays(m_DrawMode,startElem,numElems) 到说明它没有被有效顶点完全填充。
当然,在某些时候,我会得到比交互式绘制更多的点,所以我有一个 LRU 机制,可以根据需要释放最旧的(根据 LRU alg)VBO 集。
有没有更优化的方法来做到这一点?缓冲区孤儿?流媒体提示?地图与子数据?还有什么?
第二个问题是我现在被要求删除点(不定期),一次从 10 到 2000 不等。但是这些点在我最初收到它们的顺序中是不规则的。我可以找出它们当前退出的缓冲区中的偏移量,但它更多的是分散而不是范围。我一直在通过找到它们在正确缓冲区中的偏移量并一个接一个地调用范围为 1 的 glBufferSubData 来“删除它们”(它们很少在缓冲区中彼此并排),并将 pos 更改为远离的某个地方他们永远不会被看到。最终我猜应该从这些删除请求中删除缓冲区,但我目前不这样做。
有什么更好的方法来处理这个问题?
【问题讨论】:
-
我强烈建议您使用
glDrawElements (...),而不是将未使用的顶点物理归零。然后你将一个包含所有实际有数据的点的数组传递给它。您可以在内部保留未使用或空闲顶点的列表,但您肯定会浪费总线带宽将空闲顶点归零。让它们保持原样,但承认它们不会被渲染/包含垃圾:) -
那么您是否建议我创建一个删除并创建一个充满索引的新 VBO(或实际上是 IBO),每次说需要删除缓冲区中 300k 中的 4 个点?然后用 glDrawElements 绘制,与 glDrawArrays 相对?
-
不完全。我建议您为顶点缓冲区分配一个大小相等的 IBO,最初它将用 0-n 的值顺序填充(其中 n 是您的 VBO 大小)。当您想删除随机位置的单个顶点或一系列连续顶点时,只需使用
glBufferSubData (...)并将 IndexArray [n] 中的值替换为指向有效顶点的索引。这样,您不必重新定义顶点位置或添加 32 位 w 坐标以在渲染时“隐藏”已删除的顶点,您只需重新定义 16 位索引即可。 -
您不想为此操作创建或删除新的 IBO。与顶点缓冲区相同维度的 16 位 IBO 将比添加 w 坐标消耗更少的内存。理论上,使用巨大的元素数组和
glDrawElements (...)进行渲染可能会更慢,但您肯定会减少删除随机分布顶点的情况的费用。而且您不会增加定义(或更新)顶点位置的费用,因为您不需要每个顶点额外增加 32 位。