繁体   English   中英

使用VBO时需要增加内存

[英]Improving memory needed when using VBOs

我一直在编写一个实验性应用,其中我使用VBO渲染了100个16x16x16立方体的块。 我之所以这样做,是因为有十几个人对VBO进行了夸奖,并且告诉我,与我在我的Minecraft风格游戏中使用的按块显示列表相比,它的性能要好得多。

这是一个痛苦的过程,试图将许多只写得不好的教程改编成只关注单个立方体/三角形的东西,以应付需要的绘图量。 我仍然完全不相信VBO比显示列表更适合我的游戏。

在大多数情况下,我最终对代码进行了调整,以使交错的VBO数据仅构建一次(在加载块时),然后每次render调用时,绑定缓冲区ID并调用glDrawArrays

我正在这个实验性应用程序中逐渐增加块/块的数量,以了解性能如何处理。 在实际游戏中,它必须在每个块中处理16x16x128个块,最多加载20x20个块。 其中大约60%将是渲染的实体块,因此可能有800万块。 使用我开始使用的显示列表方法,该渲染没有太大问题。

但是,即使我现在的VBO渲染性能处于可容忍的水平内,在不达到内存限制的情况下,我也无法生成10个块的半径:

Exception in thread "main" java.lang.OutOfMemoryError: Direct buffer memory
at java.nio.Bits.reserveMemory(Bits.java:658)
at java.nio.DirectByteBuffer.<init>(DirectByteBuffer.java:123)
at java.nio.ByteBuffer.allocateDirect(ByteBuffer.java:306)
at org.lwjgl.BufferUtils.createByteBuffer(BufferUtils.java:60)
at org.lwjgl.BufferUtils.createFloatBuffer(BufferUtils.java:110)
at com.helion3.opengl.rendering.TextureQuadRenderer.<init>(TextureQuadRenderer.java:25)
at com.helion3.opengl.shapes.Chunk.<init>(Chunk.java:13)
at com.helion3.opengl.shapes.World.<init>(World.java:18)
at com.helion3.opengl.Game.start(Game.java:90)
at com.helion3.opengl.Launcher.main(Launcher.java:19)

我非常有信心,我的缓冲区设置了所需的正确计数。 我打电话:

BufferUtils.createFloatBuffer(每个多维数据集使用192浮点(3个顶点,3种颜色,2个纹理坐标乘以6个面,每个面4个顶点)乘以4096块测试中的块数。

现在,在真实游戏中,我不会渲染未暴露在空气中的块面,但是即使在此测试应用程序中进行渲染,我仍只会渲染16x16x16块。

如何更好地管理VBO内存? 我的VBO测试应用渲染代码块代码

VBO在什么时候闪耀着他们每个人都以此为卖主的方式? 大声笑

PS:我想我现在将深入实例化,看看有什么帮助。

现在,在真实游戏中,我不会渲染未暴露在空气中的块面,但是即使在此测试应用程序中进行渲染,我仍只会渲染16x16x16块。

这是非常好的。 我只提到这一点,因为首先,人们在编写Minecraft样式渲染器时常犯的一个错误是试图将所有块发送给OpenGL(如果渲染所有块,则更糟)。 相反,您应该确定哪些表面实际可见,并且仅将其保留在VBO中。 在这里使用空间细分结构会有所帮助。 像Minecraft这样的世界,只有八角形的痕迹,可以轻而易举地存储实际的东西。 (这是给其他在这里遇到此问答的人的)。


要记住的另一件事是,由于所有内容都呈现为多维数据集,因此您不必保留数百万个(相同的)多维数据集(只需翻译)即可。 如果使用实例化,一个即可满足。

使用实例化,每个块仅需要4个整数即可完整描述它(位置3,表面1,从GL_TEXTURE_2D_ARRAY加载)。 整数是更可取的,因为它们的种类较小(唯一的缺点是,较旧的GPU无法有效处理它们)。 假设一个立方体代表1m³。 然后,一个16位整数给出了(65536m)³的世界。 同样,对于Minecraft风格的游戏,您几乎不需要超过256种表面。 因此,请使用8位整数表示这一点。 然后,当您仅考虑可见的表面(即块)时,您的很多体积都不必驻留在VBO中。

这可能是真正的内存保护程序。 从32位浮点数到16位整数可节省50%的内存。 对材料索引使用单个8位整数而不是3×32位浮点颜色会将您的内存需求减少到1/12。


为了进一步降低渲染负载,您可以利用世界上所有多维数据集都是并行的。 这样就可以轻松消除甚至处理不了的隐藏曲面:可以从8 + 6个主要方向上查看一个多维数据集:8个可以看到3个共有一个角的面,而6个方向只能看到您正在查看的面直接可见。 从当前的角度来看,确定每种情况适用的世界上的主要平面非常容易。 因此,您有14种多维数据集基础模板,并在特定情况下对每个子卷进行实例化调用。 八叉树再次帮助您选择哪个实例获得哪个变体。


您应该考虑的另一件事是缓存一致性。 VBO中多维数据集数据的排列和对齐方式以及访问顺序非常重要。 通常,您希望数据能够很好地对齐和合并(尽管使用当前的多路径内存体系结构,分离的数据布局也可以提供很好的性能)。 但是,可以说,您的访问模式不应“到处跳”。 将您的访问分组。 这是显示列表胜过VBO的主要原因:内容是恒定的,驱动程序可以将其内容重新排列为最佳对齐和有序的结构。 您必须对此进行试验。


让您大致了解当前最先进的游戏引擎的功能:DICE的最新报告指出,在即将到来的“战地风云4”游戏中,即使是最复杂的场景,也只能通过大约2000个绘图API生成单个帧电话。 这是一个非常低的数字。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM