JOGL:用新的细节级别替换VBO数据

时间:2017-07-01 14:50:14

标签: opengl jogl vbo

我有一个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崩溃。

1 个答案:

答案 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 / glDrawElementsglDrawArrays / GLEventListener.display(),这就是我在分层绘图系统(硬盘+ CPU)中所做的+ GPU)。想象一下,你的硬盘驱动器上有一个巨大的网格物体,你需要多次通过来填充你的缓冲区,其内存位于本机堆上或Java堆上,你需要更多的传递来填充GPU中的缓冲区。如果CPU中的缓冲区占用1 GB且GPU中的缓冲区小1000倍,则必须进行1000次传输并glBufferData / glBufferSubData调用以绘制网格。