OpenGl VBO C ++技术

时间:2010-07-10 06:18:54

标签: c++ opengl graphics vbo terrain

我对在OpenGL程序中正确使用VBO感到困惑。

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

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

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

一旦我得到代码的地形部分,这也不适应不同的车辆和人员。

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

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

或者我对我所能达到的目标的期望是不现实的? 有没有更好的方法可供我使用,我不知道? 我正在寻找像Oblivion或Fallout 3这样的游戏,以及一些无边界行星,看到大量的地形,并想知道地球上的可能性。

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

如果有人能够了解我对VBO的理解是错误的,那将非常感激。

6 个答案:

答案 0 :(得分:9)

  

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

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

  

不包括每个三角形可能需要多次存储。

不应多次存储相同的顶点。使用索引基元(三角形列表或三角形条)。绑定指标的缓冲区,然后使用glDrawElementsglDrawRangeElements。请记住,您可以在OpenGL中使用四边形 - 您不必仅使用三角形。

  

(4096x4096x64)

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

  

我遇到的问题是,大多数消息来源都说单个VBO的大小应该在1-4mb之间,而且VBO越少越好。

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

如果信息来自API开发人员或驱动程序开发人员(ATI或NVidia),则信息可能仅 。或者当绝对肯定作者(教程或文章)在该领域有很多经验而不是另一个无知的想要游戏开发者。来自GDC,Siggraph,ATI,NVidia的文件可能是值得信赖的。应该检查匿名者“某人”写的一些教程是否真的是正确的。

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

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

  

然而根据我的计算,存储每个顶点总共需要大约一千兆字节的数据! (4096x4096x64)

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

  

我正在研究像Oblivion或Fallout 3这样的游戏,以及一些无边界行星,看到大量的地形,并想知道地球上的可能性。

他们不要一次装载所有东西。只有可见的对象,地形的当前“块”和几个附近地形块的低多边形版本才会在任何单个时刻加载。游戏只存储当前使用的对象,或者即将使用的对象。它不断从HDD获取数据。

答案 1 :(得分:1)

顶点的大小决定了它在顶点缓冲区中占用的空间大小。 如果您的顶点只包含一个3D位置,则每个顶点将有12个字节。

  

不包括每个三角形可能需要多次存储。

您可以使用索引缓冲区索引数据,以消除重复顶点的需要。

  

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

是的,创建和销毁会对性能产生负面影响,但不会产生巨大的顶点缓冲区。如果你想拥有一个巨大的地形;在途中加载/释放较小部分的地形数据。

  

我确定我在这里进行了一些大规模的监督,因为最大VBO大小4mb似乎非常低,即使我在64x64块中加载纹理,并且不同的交互式对象会填充也是地图。

如果你使用的是一个64字节的顶点; 4MB购买65536个顶点。 (256×256) 对于任何事情都应该足够了,如果你需要更多的顶点,你可以在几个顶点缓冲区之间分割它们。

免责声明:我个人最近才开始使用OpenGL,对回答OpenGL特定问题没什么帮助。

答案 2 :(得分:1)

如前所述,VBO中顶点的大小取决于您的顶点格式,因此没有固定的格式,因此大小不固定。关于最佳VBO尺寸的统计数据往往会过时,不要期望在第一次使用尺寸和轮廓时才能正确使用它,这不会花费你很长时间。

关于你可以拥有多少个VBO,对于许多VBO来说,是的意味着大量的绘制调用。也没有人说你完全毁掉了它们,你可以根据需要多次重复使用它们。

您正在考虑使用某种分页算法并不是很糟糕,有一种众所周知的地形渲染算法使用这种方法称为Chunked LOD。该算法使用单独的分页线程进行静态地形的核外渲染。

不要试图找到最终的完美解决方案,学会接受不完美。不要依赖每个人给你答案或所有细节只是自己做,看看。您可以随后在实际成为问题时进行重构和/或优化,否则您将无法完成。

答案 3 :(得分:1)

我怀疑你没有按照预期使用高度贴图。你有一个4096x4096的图像,这是一个像素数组,不打算用作顶点。在纹理(也称为高度图)中存储高度的整个点是为了避免几何中的这种细节水平(即,在顶点缓冲区中)。

确切的使用技巧取决于您的背景。如果地形仅用于可视化,我建议将其显示在单个四边形( 4个顶点)上,并使用像light mapsdisplacement mapping或{{3}这样的着色器}。如果它打算与其他对象进行某些交互(例如,在其上行走的字符),则某些几何图形按顺序排列 - 但当然不是4096x4096。 parallax mapping以自己的本地详细程度自适应地对高度图进行采样。

答案 4 :(得分:0)

如果您将数据输入/输出,则需要至少4个VBO,以防您在“四角”边界附近进行渲染。但是当您四处移动时,您可以替换这四个VBO中的数据,而不是一直创建/释放它们。对于这种方法,你应该使用一个“动态”使用标志,让OpenGL知道数据可能会改变,但每次都会使用多次。

答案 5 :(得分:0)

不确定这些东西,但据我所知,你可以使用每个纹理1个vbo的任何大小的vbo,即使模型和纹理数据跨越多个对象的多个peices。可是会混淆。

http://www.swiftless.com/tutorials/opengl/6_vbo.html