OpenGL:使用Vertex Arrays渲染数千个立方体,效果不佳

时间:2013-01-27 18:58:08

标签: java opengl rendering lwjgl vertex-array

我试图使用顶点数组使用LWJGL渲染大约2097152个多维数据集(不是一次全部都不是)。我已经实现了多种类型的多边形剔除,以将我的性能从大约2 FPS增加到大约60 FPS。在整个项目中,我一直在使用立即模式渲染,我认为现在是升级的时候了。这里是顶点数组的来源。

我不想使用VBO,所以我现在一直在试验VAO。我似乎无法获得实用(或高效)的渲染方法。遗憾的是,我尝试的一切都让我的FPS比立即模式更差。每个帧我为每个具有可见多边形的立方体加载一个FloatBuffer,然后使用常见的顶点数组方法绘制它们。这个设置让我感到头疼,因为我使用的立体模式比使用立即模式更少,而不是剔除任何多边形。

我认为我做错了什么。因此,在那些有光泽,有抱负的OpenGL / LWJGL程序员中,有谁知道如何以更有效和高效的方式完成这项工作?

这是我的渲染代码(截断到不是太乱了):

for(int z = 0; z < chunk.bpc; z++) {
for(int y = 0; y < chunk.bpc; y++) {
    for(int x = 0; x < chunk.bpc; x++) {
        if(((z == chunk.bpc - 1 || z == 0) || (y == chunk.bpc - 1 || y == 0) || (x == chunk.bpc - 1 || x == 0)) 
            && chunk.data[(x * chunk.bpc + z) * chunk.bpc + y] == i) {

                List<Float> vertices = new ArrayList<Float>();

                float xp = x + locX, yp = y + locY, zp = z + locZ;

            if(z == chunk.bpc - 1 && chunk.z$ == null) {
                vertices.add(xp); vertices.add(yp); vertices.add(zp + size);
                vertices.add(xp + size); vertices.add(yp); vertices.add(zp + size);
                vertices.add(xp + size); vertices.add(yp + size); vertices.add(zp + size);
                vertices.add(xp); vertices.add(yp + size); vertices.add(zp + size);
            }

            if(z == 0 && chunk.z_ == null) {
                vertices.add(xp); vertices.add(yp); vertices.add(zp);
                vertices.add(xp); vertices.add(yp + size); vertices.add(zp);
                vertices.add(xp + size); vertices.add(yp + size); vertices.add(zp);
                vertices.add(xp + size); vertices.add(yp); vertices.add(zp);
            }

            if(y == chunk.bpc - 1 && chunk.y$ == null) {
                vertices.add(xp); vertices.add(yp + size); vertices.add(zp);
                vertices.add(xp); vertices.add(yp + size); vertices.add(zp + size);
                vertices.add(xp + size); vertices.add(yp + size); vertices.add(zp + size);
                vertices.add(xp + size); vertices.add(yp + size); vertices.add(zp);
            }

            if(y == 0 && chunk.y_ == null) {
                vertices.add(xp); vertices.add(yp); vertices.add(zp);
                vertices.add(xp + size); vertices.add(yp); vertices.add(zp);
                vertices.add(xp + size); vertices.add(yp); vertices.add(zp + size);
                vertices.add(xp); vertices.add(yp); vertices.add(zp + size);
            }

            if(x == chunk.bpc - 1 && chunk.x$ == null) {
                vertices.add(xp + size); vertices.add(yp); vertices.add(zp);
                vertices.add(xp + size); vertices.add(yp + size); vertices.add(zp);
                vertices.add(xp + size); vertices.add(yp + size); vertices.add(zp + size);
                vertices.add(xp + size); vertices.add(yp); vertices.add(zp + size);
            }

            if(x == 0 && chunk.x_ == null) {
                vertices.add(xp); vertices.add(yp); vertices.add(zp);
                vertices.add(xp); vertices.add(yp); vertices.add(zp + size);
                vertices.add(xp); vertices.add(yp + size); vertices.add(zp + size);
                vertices.add(xp); vertices.add(yp + size); vertices.add(zp);
            }

            float[] verts = new float[vertices.size()];
            for(int a = 0; a < verts.length; a++) {
                verts[a] = vertices.get(a);
            }

            FloatBuffer cubeBuffer = BufferUtils.createFloatBuffer(verts.length);
            cubeBuffer.put(verts);
            cubeBuffer.flip();

            GL11.glEnableClientState(GL11.GL_VERTEX_ARRAY);

            GL11.glVertexPointer(3, 0, cubeBuffer);

            GL11.glDrawArrays(GL11.GL_QUADS, 0, verts.length / 3);

            GL11.glDisableClientState(GL11.GL_VERTEX_ARRAY);
        }
    }
}
}

(只是忽略其中的一些变量,它们只是剔除不同的多边形)

所以我不知道是否有更有效的方法来做到这一点,但是如果有的话,如果我能得到一些指针会很好。提前致谢!哦,......

我的呈现方式极其错误。

2 个答案:

答案 0 :(得分:1)

不要每帧重新生成几何。内部渲染循环中的动态内存分配通常是个坏主意。

当一个块进入视图时以及是否/当该块被修改时,为块生成的几何

也许使用LRU缓存来存储几何体,以便缓慢地从缓存中清除不可见的块。

答案 1 :(得分:1)

虽然我读过关于LWJGL和VAO的内容,但我从来没有亲自使用它们,但是VBO总是为我做的。但是,如果我查看您的代码段,您似乎每帧都会调用此代码段。因此,实际上您每帧都在更改数据,创建新缓冲区,将数据传输到缓冲区,然后在缓冲区中渲染数据。每帧创建一个新的缓冲区是昂贵的,所以这样做一次然后重用你的缓冲区。如果你每帧都在改变数据,那么VAO和VBO可能不会给你提供比立即模式更多的性能。原因在于,在立即模式下,您将每帧的数据传输到GPU内存并进行渲染,这种转移非常昂贵。另一方面,如果数据没有改变每一帧,那么VAO和VBO(以及早期的显示列表)允许您将数据存储在GPU内存中,从而使您无需每次从RAM传输数据通过PCI-E总线到GPU内存。