体素游戏:渲染块的方式和性能不同

时间:2015-02-02 21:07:18

标签: java opengl lwjgl voxel

我正在使用OpenGL制作类似Minecraft的游戏,我想知道,在没有性能损失的情况下,制作灵活渲染的最佳解决方案是什么。我的意思是有不同类型的块具有不同的绘制方式:通常的块只是带纹理的简单立方体,楼梯更复杂,像水和熔岩的液体块需要纹理更新。我有一个显示列表的块。每个块都有自己的类型(字节值)。根据这个值,我可以找到“完整”块表示(它通常用于所有相同类型的块,并包含名称,绘制方法和附加信息)。现在我需要删除渲染不可见的面(如果块在左边有一个邻居,我们不需要绘制它的左面)。但这意味着我需要将6个参数传递给绘图方法(或数组或掩码)。这是一种很好的绘画方式,还是我选择了一种愚蠢的解决方案?您可以建议以自己的方式绘制不同类型的块吗?

for(int x = 0; x < 16; x++){
        for(int y = 0; y < 128; y++){
            for(int z = 0; z < 16; z++){    
                GL11.glPushMatrix();
                    GL11.glTranslatef(x, y, z);
                    BlockTypes.getBlockType(blocks[x][y][z].type).draw();                   
                GL11.glPopMatrix();
            }
        }
    }       

2 个答案:

答案 0 :(得分:2)

我看了:

  • 立方块的显示列表和3d数组对于体素无限世界最有效。

  • 显示列表在渲染之前预编译所有内容并一次渲染。和阵列最容易在强力绘图中查找块/块,这对于立方体世界来说是最好的。

  • 八叉树最适合碰撞检测。

  • vbo立即改善表现,但有点难度。

  • 我认为显示列表与能够传递大量数据以及多块世界所需的极少瓶颈最有效。

[编辑] 但是没有一个问题所有的3D游戏,尤其是具有如此多单个块的体素游戏是渲染组件。您只需呈现可见的内容。禁用背面&amp;逆时针绘制四边形/三角形。查找遮挡剔除。禁用共享面的渲染。如果他们共享相同的纹理,我甚至想到了将共面面部如两个连接立方体组合成一个的想法。只渲染屏幕可以看到的内容。等等!还要查看int vs byte Java或现代机器。似乎现代机器不再有8位寄存器,总是使用32位。这意味着即使你创建一个字节数组,他们可能会占用相同的空间而不是真正优化任何东西。使用字节也会有一些操作损失。建议使用int存储在内存中并使用字节/位存储在硬盘驱动器上。并将您的地图存储在驱动器上并生成/存储在内存中/从磁盘中拉出您周围的内容。这样可以最小化磁盘空间并最大化CPU / JVM / Java效率

答案 1 :(得分:0)

我建议为每个块和着色器使用VBO,而不是显示列表和固定管道(实际上已弃用)。

使用VBO具有多种优势。它允许您使用着色器,提供比固定管道更多的灵活性。使用着色器,您可以与顶点/索引数据分开发送纹理数据,颜色数据等。同样,VBO一般来说速度更快。

VBO提供更多灵活性的一种方式是使用水和熔岩,这需要纹理更新可以与缓冲分开调用,减少了对整个块进行重新缓冲的需要。

对于隐形人脸检测,我认为这是唯一的方法。不要传递6个参数,只需将块传递给方法即可。您还可以创建一个方法来检索正在检查的块周围的块。