ええ、VBOとCULLフェーシングを使用しますが、それはほとんどすべてのゲームに当てはまります。あなたはそれがプレイヤーに表示されている、場合にのみキューブをレンダリングされてやりたいとブロックは、特定の方法で接触している場合は、ブロックやメイクの頂点を追加する(のが、それは地下だからあなたが見ることができないチャンクをしましょう)それはほとんど「大きなブロック」、またはあなたの場合-チャンクのようです。これは貪欲なメッシュ化と呼ばれ、パフォーマンスが大幅に向上します。ゲーム(ボクセルベース)を開発しており、貪欲なメッシュアルゴリズムを使用しています。
このようなすべてをレンダリングする代わりに:
次のようにレンダリングします。
これの欠点は、最初のワールドビルドでチャンクごとにさらに計算を行う必要があること、またはプレーヤーがブロックを削除/追加する場合です。
ほぼすべてのタイプのボクセルエンジンが、良好なパフォーマンスのためにこれを必要とします。
ブロック面が別のブロック面に接触しているかどうかを確認し、そうであれば、1つ(またはゼロ)のブロック面としてのみレンダリングします。チャンクを非常に高速にレンダリングしている場合は、コストがかかります。
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])));
}
}
}
}
}
}
}