我正在尝试决定在类似Minecraft的游戏中渲染一堆具有不同纹理的立方体的最有效方法是什么。
我发现了instanced rendering。我所做的是我创建了一个单独的“立方体模型”,它存储了立方体的所有顶点,法线和纹理坐标,我创建了一个数组缓冲区并将其传递给GPU一次。然后我创建了一个(转换矢量,纹理索引)结构数组,我使用实例渲染来反复重绘同一个立方体,每次翻译并with the appropriate texture。
(希望Notch不介意我使用他的纹理,直到我自己制作)
问题在于,并非所有6个边都将具有相同的纹理,并且我正在试图弄清楚如何使每个块类型的它们不同。我提出的两个解决方案是:
第二种解决方案需要传递更多(可能是多余的)数据。我不确定实例化渲染的好处有多大......所以我不知道是否会更好,例如,最多256个“通过”(每个块类型1个)或“一个大”传递“包含所有数据,并在一次拍摄中渲染每个块。
或许还有另一种我不知道的方法?
答案 0 :(得分:6)
我认为你不能用实例有效地做到这一点。绝大多数面部/立方体永远不可见,您可以通过不渲染来节省大量时间。不幸的是,这会使每个立方体成为不同的对象。
标准解决方案(以及如何在Minecraft中完成)是将您的地形划分为多个扇区。计算哪些面是可见的并将它们上传到GPU。当一个多维数据集发生变化时,你只需要重新上传它的扇区。渲染扇区时,您只需绘制基元而无需任何其他计算。
您可以根据sparse voxel octrees执行某些操作。这是更多的工作,但你将能够有效和准确地告诉你世界的哪些部分是可见的。
答案 1 :(得分:2)
我知道这个问题差不多有两年了,但是我可以制作一个存储所有单个纹理的3D纹理,其中z纹理坐标就像块ID一样。使用3D纹理,您现在可以立即绑定所有单独的块纹理,这意味着您可以使用实例渲染将转换与blockID一起传递,以获取3D采样器的正确块纹理。
答案 2 :(得分:1)
在我的nVidia 8600M GT上我发现,实例化在中间表现最佳,具有适度的顶点和实例计数,但我最终实例化几个顶点数千次,以消除冗余数据以及更新的努力它
我选择 2 ,在顶点数组中使用纹理数组和单个实例化立方体,并使用“每个实例数组”的纹理索引选择面部纹理,其中6个指数甚至可以包含在几个整数中。
对于提供实例属性,GL_ARB_instanced_arrays
也可以使用,其中一个不需要使用gl_InstanceID
访问缓冲区(可预测,因此在大多数情况下更快)。
如果你需要具有特定于实例的纹理坐标,我会绑定一个额外的每个实例和顶点纹理坐标数组,以及相应修改的着色器。
答案 3 :(得分:0)
答案很晚,但有人肯定需要它。
在主块类中有一个返回纹理的方法,带有face的参数。在需要多个纹理的各个类中,重写此方法并使用switch case或一系列if / else语句。
这是方法在块类中的样子:
public int getBlockTexture(int face){
if(face = top){
return grass top
} else if(face = bottom){
return grass bottom
} else {
return grass side
}
}
至于如何在渲染器中使用它,请在渲染每个面之前抓取纹理。类似于你如何剔除。