我有一个Java应用程序,我在其中计算CPU上的3D模型。计算需要一些时间(秒的数量级 - 分钟),但如果你愿意的话,会在迭代中发生细节。我正在使用JOGL来可视化模型。我希望立即可视化模型,并在准备好后以更新的细节级别更新视图。我有一个设置,这是有效的,但我感觉我做错了(我正在学习这个项目的OpenGL):现在我在FloatBuffer
中缓存新LoD的顶点信息并设置一个标志。渲染循环检查此标志,如果设置它将为VBO分配一个新的数据存储(glBufferData
)。我考虑使用glBufferSubData
来获得更好的性能(分配新的数据存储会导致更高级别的性能提升,这至少是1M顶点)但问题是新的细节级别具有任意数量的顶点(与之前的细节级别不同)我无法预测,当第一次初始化VBO时,缓冲区最大应该有多大。我已经尝试分配一个非常大的,但这让我失去了JVM崩溃或GL 1281错误(我想我正在尝试分配一个太大的缓冲区:1440 * 1440 * 4字节)。我应该使用多个单独的VBO吗?我可以制作一个VBO多大?我应该为顶点颜色,法线和顶点位置设置单独的(一组)VBO吗?准备好新的细节水平时,最佳做法是什么?
额外信息:
来自渲染循环中的检查输出,其中包含一个新的缓冲区数据存储(使用System.currentTimeMillis()
测量的时间),用于不同级别的细节到达,显示性能方面的显着提升:
OpenGL received new data of length 0
Allocating a new data store took 0 ms
OpenGL received new data of length 0
Allocating a new data store took 0 ms
OpenGL received new data of length 360
Allocating a new data store took 3 ms
OpenGL received new data of length 6240
Allocating a new data store took 0 ms
OpenGL received new data of length 34020
Allocating a new data store took 0 ms
OpenGL received new data of length 177840
Allocating a new data store took 1 ms
OpenGL received new data of length 1018980
Allocating a new data store took 7 ms
OpenGL received new data of length 5214660
Allocating a new data store took 20 ms
OpenGL received new data of length 19392000
Allocating a new data store took 59 ms
OpenGL received new data of length 56229840
Allocating a new data store took 157 ms
实际代码:
long before = System.currentTimeMillis();
gl.glBufferData(GL_ARRAY_BUFFER, vertexData.limit() * 4, vertexData, GL_STATIC_DRAW);
System.out.println("Allocating a new data store took " + (System.currentTimeMillis() - before) + " ms");
其中使用vertexData
在包含顶点数据的GLBuffers.newDirectFloatBuffer(...)
上分配float[]
(这在CPU线程上完成)。在旁注中,请注意最大的细节模型如何包含5622984个顶点(每个顶点由10个浮点值组成)。这段代码有效,当我要求用这行代码分配一个大小的缓冲区数据存储时,我的电脑不会抱怨。我很奇怪,因为如果我试图通过硬编码这个字节数来直接在我的init例程中分配一个大小的缓冲区,那么JVM会崩溃......(#Problematic frame:
[nvoglv64.DLL + 0xd16e7b])。如此改变
gl.glBufferData(
GL_ARRAY_BUFFER,
vertexData.limit() * 4,
vertexData,
GL_STATIC_DRAW);
到
gl.glBufferData(
GL_ARRAY_BUFFER,
56229840*4,
vertexData,
GL_STATIC_DRAW);
导致JVM崩溃。
答案 0 :(得分:0)
你想绘制56229840个顶点,每个顶点由3个坐标组成,每个坐标需要4个字节和glBufferData expects a size in bytes。因此,您应该通过56229840 * com.jogamp.common.nio.Buffers.SIZEOF_FLOAT * 3
。
V B O是缓冲区。您可以在glBufferData
中多次致电glBufferSubData
/ glDrawElements
和glDrawArrays
/ GLEventListener.display()
,这就是我在分层绘图系统(硬盘+ CPU)中所做的+ GPU)。想象一下,你的硬盘驱动器上有一个巨大的网格物体,你需要多次通过来填充你的缓冲区,其内存位于本机堆上或Java堆上,你需要更多的传递来填充GPU中的缓冲区。如果CPU中的缓冲区占用1 GB且GPU中的缓冲区小1000倍,则必须进行1000次传输并glBufferData
/ glBufferSubData
调用以绘制网格。