1

我正在尝试使用顶点数组通过 LWJGL 渲染大约 2097152 个立方体(不是一次全部)。我已经实现了多种类型的多边形剔除,以将我的性能从大约 2 FPS 提高到大约 60 FPS。在整个项目中,我一直在使用即时模式渲染,我认为是时候升级了。这就是顶点数组的用武之地。

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

我想我做错了什么。所以在你们这些聪明的、有抱负的 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);
        }
    }
}
}

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

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

我的渲染方式有些严重错误。

4

2 回答 2

1

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

一个块进入视图时以及如果/当​​该块被修改时,生成一个块的几何图形。

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

于 2013-01-27T19:31:35.543 回答
1

虽然我读过关于 LWJGL 和 VAO 的文章,但我从未亲自使用过它们,但 VBO 总是为我解决问题。但是,如果我查看您的代码片段,您似乎每帧都调用此片段。所以,本质上你是在改变每一帧的数据,创建一个新的缓冲区,将数据从缓冲区传输到缓冲区,然后在缓冲区中渲染数据。每帧创建一个新的缓冲区是昂贵的,所以这样做一次然后重用你的缓冲区。如果您每帧都更改数据,那么 VAO 和 VBO 可能不会为您提供比立即模式更多的性能。原因在于,在即时模式下,您将每帧的数据传输到 GPU 内存并进行渲染,这种传输成本很高。另一方面,

于 2013-01-27T19:37:25.527 回答