如何使用 OpenGL 3.x VBO 渲染动态世界?

发布于 2024-08-11 21:42:59 字数 214 浏览 7 评论 0原文

尽管 OpenGL 3.x 本身的最新参考文献似乎很少,但 OpenGL 的实际低级操作相对简单。然而,我在试图概念化如何操纵 VBO 来渲染动态世界时遇到了严重的困难。

显然旧的立即模式方式不适用,但是从那里我该去哪里呢?我是否编写某种场景结构,然后将其转换为一组顶点并将其流式传输到 VBO,我将如何存储翻译数据?如果是这样的话,代码看起来会怎么样?

基本上真的不知道如何继续。

Although there seem to be very few up to date references for OpenGL 3.x itself, the actual low level manipulation of OpenGL is relatively straight forward. However I am having serious trouble trying to even conceptualise how one would manipulate VBOs in order to render a dynamic world.

Obviously the immediate mode ways of old are non applicable, but from there where do I go? Do I write some kind of scene structure and then convert that to a set of vertices and stream that to the VBO, how would I store translation data? If so how would that look code wise?

Basically really unsure how to continue.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

手心的温暖 2024-08-18 21:42:59

如果您的整个世界确实是动态的,您可以使用 GL_STREAM_DRAW_ARB 使用标志并重置每个帧上的数据。不必费心去操纵它,只需尝试尽可能高效地进行流传输即可。

但是,我假设您有一个由多个相对移动的刚性对象组成的场景。在这种情况下,为每个对象使用一个 VBO 并指定 GL_STATIC_DRAW_ARB 使用标志。然后,您可以为对象的每个实例设置模型视图变换,并为每个实例使用一次绘制调用来渲染它们。

经验法则(在 PC 上)是每 MHz CPU 发出不超过一次绘制调用。这是一个粗略的估计,但有一定道理。如果您低于此限制,请不要担心将多个独立对象放入单个 VBO 或其他性能技巧。

If your entire world is truly dynamic, you can use the GL_STREAM_DRAW_ARB usage flag and reset the data on each frame. Don't bother manipulating it, just try to stream as efficient as possible.

However, I assume that you have a scene that consists of multiple rigid objects that move relative to each other. In this case, use one VBO for each object and specify the GL_STATIC_DRAW_ARB usage flag. You can then set the modelview transform for each instance of an object and render them using one draw call per instance.

A rule of thumb (on the PC) is to issue not more than one draw call per MHz of your CPU. This is a crude estimate, but there's some truth to it. Don't worry about putting multiple independent objects into a single VBO or other performance tricks if you stay below this limit.

单身狗的梦 2024-08-18 21:42:59

简短回答:

使用glMapBufferRange并仅更新需要修改的子范围。

长答案:

技巧是使用glMapBufferRange映射已经存在的缓冲区,然后仅映射您需要的范围。假设有以下假设:

  • 您的几何体使用逐顶点动画变形
  • 模型的顶点数在动画过程中保持不变。

然后,您可以使用glMapBufferRange仅更新更改的部分,而保留其余数据。使用glBufferData的完整上传速度慢得像乌龟,因为它们删除旧的内存存储并分配新的内存存储。这还不包括上传新数据。 glMapBufferRange 只允许您读取/写入现有数据,它不进行分配或释放。

但是,如果您使用骨架动画,则应将顶点变换作为每个顶点的 4x4 矩阵传递到顶点着色器,并在那里进行计算。当然,每个顶点数据是用glVertexAttribPointer指定的。

另外,请记住,您可以在顶点着色器中读取纹理数据,并且 OpenGL 3.1 引入了一些新的实例绘制调用; glDrawArraysInstancedglDrawElementsInstanced。这些组合可用于特定于实例的查找。即,您可以使用相同的几何数据绑定进行实例绘制调用,但发送位置或您需要的任何每个顶点数据作为纹理或纹理数组。这可以使您免于混合和匹配不同的顶点数组数据集。

想象一下,如果您想要渲染同一模型的 100 个实例,但具有不同的位置或配色方案。甚至纹理贴图。

Short answer:

Use glMapBufferRange and only update the subrange that needs modification.

Long answer:

The trick is to map the already existing buffer with glMapBufferRange, and then only map the range you need. Given these assumptions:

  • Your geometry uses per-vertex animation morphing
  • The vertex count for models is constant during animation.

Then you can use glMapBufferRange to update only the changing parts, and leave the rest of the data alone. Full uploads using glBufferData are slow as a turtle, because they delete the old memory store and allocates a new one. That's in addition to uploading the new data. glMapBufferRange only lets you read/write existing data, it does no allocation or deallocation.

However, if you use skeleton animation, rather pass vertex transformations as 4x4 matrices per-vertex to the vertex shader, and do the calculations there. Per-vertex data is of course specified with glVertexAttribPointer.

Also, remember that you can read texture data in the vertex shader, and that OpenGL 3.1 introduced some new instance draw calls; glDrawArraysInstanced and glDrawElementsInstanced. Those combined can be used for instance-specific lookups. I.e you can do instance draw calls with the same geometry data bound, but send positions or whatever per-vertex data you need as textures or texture-arrays. This can save you from mixing and matching different vertex array data sets.

Imagine if you want to render 100 instances of the same model, but with different positions or color schemes. Or even texture maps.

回忆凄美了谁 2024-08-18 21:42:59

使用 VBO 并不意味着您必须仅使用一次绘制调用来渲染整个场景。您仍然可以发出多个绘制调用,并在此过程中设置不同的变换矩阵。

例如,如果您使用场景图,则场景图中的每个模型都可以对应于单个绘制调用。在这种情况下,使用 VBO 最简单的方法是为每个模型创建一个单独的 VBO。

作为一种优化,您可以将多个模型组合到一个 VBO 中,然后在进行绘制调用时传入非零偏移量;这会从 VBO 中提取出正确的模型。还希望将多个绘制调用合并为一个绘制调用,但如果它们需要独立的转换,则这是不可能的。 (实际上,如果您使用实例化或顶点混合,在某些情况下是可能的,但我建议首先了解基础知识。)

Using VBOs doesn't mean you have to render your entire scene with only single draw call. You can still issue multiple draw calls, and set up different transformation matrices along the way.

For example, if you're using a scenegraph, each model in the scenegraph can correspond to a single draw call. In such a case, the easiest way to use VBOs is creating a separate VBO for each model.

As an optimization, you might be able to combine several models into a single VBO, then pass in non-zero offsets when making your draw calls; this plucks out the correct model from the VBO. It's also desirable to combine multiple draw calls into a single draw call, but that's not possible if they need to have independent transforms. (Actually it is possible in certain situations if you use instancing or vertex blending, but I suggest getting the basics out of the way first.)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文