是的,使用VBO和CULL Face,但这几乎适用于所有游戏。您想要做的就是仅在播放器可见的情况下渲染立方体,并且如果块以特定方式触摸(例如,由于位于地下而无法看到的块),则添加块的顶点并制作它几乎就像一个“更大的块”,或者在您的情况下是一块。这称为贪婪网格划分,它可以大大提高性能。我正在开发一个游戏(基于Voxel),它使用贪婪的网格划分算法。
而不是像这样渲染所有内容:
它像这样渲染:
不利的一面是,您必须在初始世界构建的每个块上进行更多的计算,或者如果玩家移除/添加一个块。
几乎所有类型的体素引擎都需要此才能获得良好的性能。
它的作用是检查块面是否正在接触另一个块面,如果是,则:仅渲染为一个(或零个)块面。当您真正快速地渲染块时,这是一个昂贵的尝试。
public void greedyMesh(int p, BlockData[][][] blockData){
boolean[][][][] mask = new boolean[blockData.length][blockData[0].length][blockData[0][0].length][6];
for(int side=0; side<6; side++){
for(int x=0; x<blockData.length; x++){
for(int y=0; y<blockData[0].length; y++){
for(int z=0; z<blockData[0][0].length; z++){
if(data[x][y][z] > Material.AIR && !mask[x][y][z][side] && blockData[x][y][z].faces[side]){
if(side == 0 || side == 1){
int width = 0;
int height = 0;
loop:
for(int i=y; i<blockData[0].length; i++){
if(i == y){
for(int j=z; j<blockData[0][0].length; j++){
if(!mask[x][i][j][side] && blockData[x][i][j].id == blockData[x][y][z].id && blockData[x][i][j].faces[side]){
width++;
}else{
break;
}
}
}else{
for(int j=0; j<width; j++){
if(mask[x][i][z+j][side] || blockData[x][i][z+j].id != blockData[x][y][z].id || !blockData[x][i][z+j].faces[side]){
break loop;
}
}
}
height++;
}
for(int i=0; i<height; i++){
for(int j=0; j<width; j++){
mask[x][y+i][z+j][side] = true;
}
}
if(side == 0)
meshes.get(p).add(new Mesh(new VoxelVector3i(x+1, y, z), new VoxelVector3i(x+1, y+height, z+width), new VoxelVector3i(1, 0, 0), Material.getColor(data[x][y][z])));
else
meshes.get(p).add(new Mesh(new VoxelVector3i(x, y, z+width), new VoxelVector3i(x, y+height, z), new VoxelVector3i(-1, 0, 0), Material.getColor(data[x][y][z])));
}else if(side == 2 || side == 3){
int width = 0;
int height = 0;
loop:
for(int i=x; i<blockData.length; i++){
if(i == x){
for(int j=z; j<blockData[0][0].length; j++){
if(!mask[i][y][j][side] && blockData[i][y][j].id == blockData[x][y][z].id && blockData[i][y][j].faces[side]){
width++;
}else{
break;
}
}
}else{
for(int j=0; j<width; j++){
if(mask[i][y][z+j][side] || blockData[i][y][z+j].id != blockData[x][y][z].id || !blockData[i][y][z+j].faces[side]){
break loop;
}
}
}
height++;
}
for(int i=0; i<height; i++){
for(int j=0; j<width; j++){
mask[x+i][y][z+j][side] = true;
}
}
if(side == 2)
meshes.get(p).add(new Mesh(new VoxelVector3i(x, y+1, z+width), new VoxelVector3i(x+height, y+1, z), new VoxelVector3i(0, 1, 0), Material.getColor(data[x][y][z])));
else
meshes.get(p).add(new Mesh(new VoxelVector3i(x+height, y, z+width), new VoxelVector3i(x, y, z), new VoxelVector3i(0, -1, 0), Material.getColor(data[x][y][z])));
}else if(side == 4 || side == 5){
int width = 0;
int height = 0;
loop:
for(int i=x; i<blockData.length; i++){
if(i == x){
for(int j=y; j<blockData[0].length; j++){
if(!mask[i][j][z][side] && blockData[i][j][z].id == blockData[x][y][z].id && blockData[i][j][z].faces[side]){
width++;
}else{
break;
}
}
}else{
for(int j=0; j<width; j++){
if(mask[i][y+j][z][side] || blockData[i][y+j][z].id != blockData[x][y][z].id || !blockData[i][y+j][z].faces[side]){
break loop;
}
}
}
height++;
}
for(int i=0; i<height; i++){
for(int j=0; j<width; j++){
mask[x+i][y+j][z][side] = true;
}
}
if(side == 4)
meshes.get(p).add(new Mesh(new VoxelVector3i(x+height, y, z+1), new VoxelVector3i(x, y+width, z+1), new VoxelVector3i(0, 0, 1), Material.getColor(data[x][y][z])));
else
meshes.get(p).add(new Mesh(new VoxelVector3i(x, y, z), new VoxelVector3i(x+height, y+width, z), new VoxelVector3i(0, 0, -1), Material.getColor(data[x][y][z])));
}
}
}
}
}
}
}