虽然OpenGL 3.x本身的最新参考文献似乎很少,但OpenGL的实际低级操作相对简单。然而,我在试图甚至概念化如何操纵VBO以呈现动态世界时遇到了严重的麻烦。
显然,旧的直接模式方式不适用,但从那里我去哪里?我是否编写了某种场景结构,然后将其转换为一组顶点并将其传输到VBO,我将如何存储翻译数据?如果是这样,那么代码看起来会如何?
基本上真的不确定如何继续。
答案 0 :(得分:9)
如果您的整个世界都是真正的动态,您可以使用GL_STREAM_DRAW_ARB
使用标记并重置每个帧上的数据。不要费心去操纵它,只是尝试尽可能高效地流式传输。
但是,我假设您有一个由多个相对于彼此移动的刚性对象组成的场景。在这种情况下,为每个对象使用一个VBO并指定GL_STATIC_DRAW_ARB
用法标志。然后,您可以为对象的每个实例设置modelview变换,并使用每个实例的一个绘制调用来渲染它们。
经验法则(在PC上)是每CPU的CPU发出不超过一次的绘图调用。这是一个粗略的估计,但它有一些道理。如果您保持低于此限制,请不要担心将多个独立对象放入单个VBO或其他性能技巧。
答案 1 :(得分:9)
简答:
使用 glMapBufferRange 并仅更新需要修改的子范围。
答案很长:
诀窍是用 glMapBufferRange 映射已经存在的缓冲区,然后只映射你需要的范围。鉴于这些假设:
然后,您可以使用 glMapBufferRange 仅更新更改的部分,并保留其余数据。使用 glBufferData 的完整上传速度很慢,因为它们会删除旧的内存存储并分配一个新内存。这是上传新数据的补充。 glMapBufferRange 只允许您读/写现有数据,不进行分配或解除分配。
但是,如果使用骨架动画,而是将顶点变换作为每顶点4x4矩阵传递到顶点着色器,并在那里进行计算。每个顶点数据当然是用 glVertexAttribPointer 指定的。
另外,请记住,您可以在顶点着色器中读取纹理数据,并且OpenGL 3.1引入了一些新的实例绘制调用; glDrawArraysInstanced 和 glDrawElementsInstanced 。这些组合可用于特定于实例的查找。即,您可以使用相同的几何数据绑定来实例绘制调用,但是发送位置或您需要的每个顶点数据作为纹理或纹理数组。这可以避免混合和匹配不同的顶点数组数据。
想象一下,如果要渲染相同模型的100个实例,但具有不同的位置或颜色方案。甚至是纹理贴图。
答案 2 :(得分:5)
使用VBO并不意味着您只需要使用单个绘制调用来渲染整个场景。您仍然可以发出多个绘制调用,并在此过程中设置不同的转换矩阵。
例如,如果您使用的是场景图,则场景图中的每个模型都可以对应一个绘图调用。在这种情况下,使用VBO的最简单方法是为每个模型创建一个单独的VBO。
作为优化,您可以将多个模型组合到一个VBO中,然后在进行绘制调用时传入非零偏移;这从VBO中剔除了正确的模型。将多个绘制调用组合成单个绘制调用也是可取的,但如果它们需要独立的变换则不可能。 (实际上,如果你使用实例化或顶点混合,它在某些情况下可能,但我建议首先将基础知识放在首位。)