Opengl JOGL:使用新的详细级别替换VBO数据

Opengl JOGL:使用新的详细级别替换VBO数据,opengl,jogl,vbo,Opengl,Jogl,Vbo,我有一个Java应用程序,其中我在CPU上计算3D模型。计算需要一些时间(秒-分钟的数量级),但会以迭代的形式进行,如果您愿意的话,会有详细的级别。我使用JOGL来可视化模型。我想立即可视化模型,并在视图准备就绪时使用新的细节级别更新视图。我有一个这样的设置,但我感觉我做错了什么(我正在学习OpenGL与这个项目):现在我缓存一个新LoD的顶点信息在一个FloatBuffer中,并设置一个标志。渲染循环检查此标志,如果设置了此标志,它将为VBO分配一个新的数据存储(glBufferData)。我

我有一个Java应用程序,其中我在CPU上计算3D模型。计算需要一些时间(秒-分钟的数量级),但会以迭代的形式进行,如果您愿意的话,会有详细的级别。我使用JOGL来可视化模型。我想立即可视化模型,并在视图准备就绪时使用新的细节级别更新视图。我有一个这样的设置,但我感觉我做错了什么(我正在学习OpenGL与这个项目):现在我缓存一个新LoD的顶点信息在一个
FloatBuffer
中,并设置一个标志。渲染循环检查此标志,如果设置了此标志,它将为VBO分配一个新的数据存储(
glBufferData
)。我考虑过使用
glBufferSubData
以获得更好的性能(分配新的数据存储会导致更高级别的性能出现问题,至少有1M个顶点),但问题是新的详细级别具有任意数量的顶点(与前一个详细级别不同),我无法预测,第一次初始化VBO时,缓冲区最大应为多大。我曾尝试分配一个非常大的缓冲区,但这会导致JVM崩溃或GL1281错误(我想我正在尝试分配一个太大的缓冲区:1440*1440*4字节)。我应该使用多个独立的VBO吗?我可以制作多大的VBO?我是否应该为顶点颜色、法线和顶点位置设置单独的(一组)VBO?当新的细节级别准备就绪时,最佳实践是什么

额外信息

使用inits在渲染循环中进行检查时,输出一个新的缓冲区数据存储(使用
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
是使用包含顶点数据的
float[]
上的
GLBuffers.newDirectFloatBuffer(…)
分配的(这是在CPU线程上完成的)。在旁注中,请注意最大的细节模型如何包含5622984个顶点(每个顶点由10个浮点值组成)。这段代码有效,当我的电脑被要求用这行代码分配一个大小相同的缓冲区数据存储时,它不会抱怨。我很奇怪,因为如果我试图在init例程中通过硬编码这个字节量来直接分配一个大小相同的缓冲区,JVM就会崩溃。。。(#有问题的框架: [nvoglv64.DLL+0xd16e7b])。如此变化

 gl.glBufferData(
            GL_ARRAY_BUFFER,
            vertexData.limit() * 4,
            vertexData,
            GL_STATIC_DRAW);


导致JVM崩溃。

您要绘制56229840个顶点,每个顶点由3个坐标组成,每个坐标占用4个字节和1个字节。因此,您应该传递
56229840*com.jogamp.common.nio.Buffers.SIZEOF_FLOAT*3


VBO是一个缓冲区。您可以在
GLEventListener.display()
中多次调用
glBufferData
/
glBufferSubData
glDrawElements
glDrawArrays,这就是我在分层绘图系统(硬盘驱动器+CPU+GPU)中所做的。假设您的硬盘上有一个巨大的网格,您将需要几次传递来填充内存位于本机堆或Java堆上的缓冲区,并且您将需要更多的传递来填充GPU中的缓冲区。如果CPU中的缓冲区占用1GB,而GPU中的缓冲区要小1000倍,则必须进行1000次传输和
glBufferData
/
glBufferSubData
调用才能绘制网格。

我不想绘制56229840个顶点(我的错,我编辑了原始帖子),我的意思是绘制5622984个顶点,每个顶点由10个浮点值组成:x、y、z、r、g、b、a、nx、ny和nz(坐标、颜色和法线)。在我的代码示例中,56229840是浮点缓冲区的长度(因此
vertexData.limit()
=56229840)。我很困惑,用硬编码的等效值替换运行时值会导致崩溃。
 gl.glBufferData(
            GL_ARRAY_BUFFER,
            56229840*4,
            vertexData,
            GL_STATIC_DRAW);