VBO와 CULL을 사용하지만 거의 모든 게임에 적용됩니다. 당신이이 플레이어가 볼 수, 경우에만 큐브를 렌더링하고 싶지 및 블록이 특정의 방법으로 접촉하는 경우가 블록과 메이크업의 정점을 추가 (의이 지하 때문에 당신이 볼 수없는 덩어리를 가정 해 봅시다) 거의 "더 큰 블록"또는 귀하의 경우 덩어리입니다. 이를 욕심 메시라고하며 성능을 크게 향상시킵니다. 게임 (voxel 기반)을 개발 중이며 욕심 많은 메시 알고리즘을 사용합니다.
다음과 같이 모든 것을 렌더링하는 대신 :
다음과 같이 렌더링됩니다.
이것의 단점은 초기 월드 빌드에서 또는 플레이어가 블록을 제거 / 추가하는 경우 청크 당 더 많은 계산을 수행해야한다는 것입니다.
거의 모든 유형의 복셀 엔진은 우수한 성능을 위해 이것을 필요로합니다.
블록면이 다른 블록면에 닿아 있는지 확인하고, 그렇다면 : 하나 (또는 0)의 블록면으로 만 렌더링합니다. 청크를 정말 빠르게 렌더링 할 때 비용이 많이 듭니다.
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])));
}
}
}
}
}
}
}