c++ - C++ 中的 OpenGl VBO 技术

标签 c++ opengl graphics vbo terrain

对于在 OpenGL 程序中正确使用 VBO,我有点困惑。

我想创建一个地形分页算法,使用从 4096x4096 灰度高度图调用的 map 作为“整体” map 。

据我所知,存储在 VBO 中的每个顶点将占用 64 个字节。

我遇到的问题是,大多数来源都指出单个 VBO 的大小应在 1-4mb 之间,VBO 越少越好。 然而根据我的计算,存储每个顶点总共需要大约 1 GB 的数据! (4096x4096x64) 这不包括每个顶点可能需要为每个三角形存储多次。

一旦我完成了代码的地形部分,这也无法容纳这张 map 上的不同车辆和人员。

我看到的另一个解决方案是在程序运行时从硬盘驱动器中分页数据,但是另一个消息来源说在程序运行时创建和销毁是一个坏主意,而且最好的做法是尽可能少的 IBO。

我真正想知道的是,我错过了什么? 我确信我在这里做了某种大规模的疏忽,因为 4mb 的最大 VBO 大小似乎非常小,即使我正在加载 64x64 block 中的纹理,以及也会填充 map 的不同交互对象。

或者我对自己能取得的成就的期望是不切实际的? 有没有我不知道的更好的方法? 我在看像 Oblivion 或 Fallout 3 这样的游戏,在某种程度上看 Boundless Planet,看到巨大的地形,想知道这到底是怎么可能的。

我了解如何编码,这不是我第一次深入研究 OpenGL,而是我第一次尝试理解和使用 VBO。

如果有人能阐明我对 VBO 的理解哪里出了问题,将不胜感激。

最佳答案

From what I've read, each vertex stored in the VBO will take up 64 bytes.

根据顶点格式,它可以占用任意多的字节。
position + normal + texcoords = 4*(3+3+2) = 每个顶点 32 字节
position + normal + texcoords + tangent vector (for bump) = 4*(3+3+2+3) = 44 bytes

That's not including that each vertice may need to be stored multiple times for each triangle.

不应该多次存储相同的顶点。使用索引图元(三角形列表或三角形带)。为索引绑定(bind)缓冲区,然后使用 glDrawElementsglDrawRangeElements .请记住,您可以在 OpenGL 中使用四边形 - 您不必只使用三角形。

(4096x4096x64)

您不需要为 map 上的每个像素创建四边形。有些区域是完全平坦的(即高度不会改变),因此添加额外的三角形会浪费资源。如果将某种网格简化算法添加到完成的景观中,您应该能够删除相当多的三角形。此外,过多的多边形会导致问题 - 三角形或四边形应该占用多个像素。如果有多个基元应该占用同一个像素,渲染结果会有点“嘈杂”。因此,您必须考虑所需的详细程度。

The problem I have is that most sources state that a single VBO should be between 1-4mb in size, and less VBOs is better.

我不会相信所有来源,尤其是互联网上的来源。很多写教程的人远算不上“专家”。另一件事是,在 DirectX(不是 OpenGL)中,建议尽可能将所有(即具有兼容顶点格式的所有对象)放入一个大型静态顶点缓冲区(VBO 模拟),并避免切换缓冲区以减少渲染调用的 CPU 开销。因此,“VBO 不应大于 4 MB”的建议对我来说非常可疑。

只有来自 API 开发人员或驱动程序开发人员(ATI 或 NVidia)的信息才可能是可信的。或者当绝对确定(教程或文章的)作者在该领域有很多经验,而不是另一个无知的想成为游戏开发者的时候。来自 GDC、Siggraph、ATI、NVidia 的文档可能是可信的。应检查匿名“某人”编写的一些教程是否确实正确。

无论如何,关于性能,微软有两个文档: "Top Issues for Windows Titles" "Performance Optimizations (Direct3D 9)" (DirectX 的东西,但一些建议可以适用于 OpenGL)。

此外,NVidia 还收集了 OpenGL resources ,其中包括与性能相关的实用程序( GLexpert 可能对您有用,并且有 NVIdia OpenGL SDK 等)。一般来说,当您尝试提高性能时,尝试不同的技术并衡量结果,而不是盲目地听从别人的建议。查看使用一种或另一种技术每秒可额外获得多少帧。

Yet according to my calculations, storing each vertex would take a total of about a gigabyte of data! (4096x4096x64)

如果您以这种方式构建整个 map ,这是正确的。但是没有理由一次加载整个 map ,所以你只需要立即可见的 map block 。

I'm looking at games like Oblivion or Fallout 3, and to some extend Boundless Planet, and seeing massive terrains, and wondering how on earth that can be possible.

他们不会一次加载所有内容。任何时候都只加载可见的对象、当前地形“ block ”和附近少数地形 block 的低多边形版本。游戏仅存储当前使用或即将使用的对象。它不断地从 HDD 获取数据。

关于c++ - C++ 中的 OpenGl VBO 技术,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3218097/

相关文章:

opengl - 使用 Cg 的 OpenGL 中的多个渲染目标

math - 如何伪造在 Z 轴上移动的 2D Sprite ?

c++ - 未定义的行为和顺序点

android - 如何在 Qt 中使用 Google-Cloud-Messaging API

c 编程 - Mandelbrot 集

c++ - 在 OpenGL 中将纹理传递给着色器

c++ - 如何创建优化的图形多色记录器?

c# - 如何在 C# 中创建光泽按钮?

c++ - 如何实时监控不同的 OpenMP 线程?

c++ - 想在 visual studio community 中运行程序时打开命令提示符