You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Rust中128×256×128体素块迭代与渲染优化问询

体素块生成与可见面渲染优化方案求助

我正在制作规格为128×256×128的体素块,需迭代体素位置完成两个核心操作:先生成体素,再检查相邻体素以仅渲染可见面网格。但当前单块处理耗时约5秒,特此寻求优化该流程的技术方案。

体素创建代码

for x in 0..=width {
    for z in 0..=depth {
        let noise_value1 = noise.get([
            (chunk_position.x + x as f32 * 0.01) as f64,
            (chunk_position.z + z as f32 * 0.01) as f64,
        ]) as f32;
        let mut y = ((noise_value1 * 20.0) + (CHUNK_DEPTH / 3) as f32).round() as usize;
        y = y.min(height);

        chunk_voxels.voxel_array.extend((0..y).map(|n| {
            (
                Position {
                    x: x as u8,
                    y: n as u8,
                    z: z as u8,
                },
                Voxel { voxel_id: 1 },
            )
        }));
    }
}

可见面渲染检查代码

for voxel in voxel_array.iter() {
    if check_for_out_of_bounds(Vec3 {
        x: voxel.0.x as f32,
        y: voxel.0.y as f32 + 1 as f32,
        z: voxel.0.z as f32,
    }) {
        //check for up
        if !voxel_array.contains_key(&Position {
            x: voxel.0.x,
            y: voxel.0.y + 1,
            z: voxel.0.z,
        }) {
            generate_voxel_mesh(
                Vec3 {
                    x: voxel.0.x as f32 + chunk_pos.x,
                    y: voxel.0.y as f32 + chunk_pos.y,
                    z: voxel.0.z as f32 + chunk_pos.z,
                },
                1.0,
                voxel.1.voxel_id,
                mesh_builder,
                Vec3 {
                    x: 0.0,
                    y: 1.0,
                    z: 0.0,
                },
            )
        }
    }
    if check_for_out_of_bounds(Vec3 {
        x: voxel.0.x as f32,
        y: voxel.0.y as f32 - 1 as f32,
        z: voxel.0.z as f32,
    }) {
        //check for down
        if !voxel_array.contains_key(&Position {
            x: voxel.0.x,
            y: voxel.0.y - 1,
            z: voxel.0.z,
        }) {
            generate_voxel_mesh(
                Vec3 {
                    x: voxel.0.x as f32 + chunk_pos.x,
                    y: voxel.0.y as f32 + chunk_pos.y,
                    z: voxel.0.z as f32 + chunk_pos.z,
                },
                1.0,
                voxel.1.voxel_id,
                mesh_builder,
                Vec3 {
                    x: 0.0,
                    y: -1.0,
                    z: 0.0,
                },
            )
        }
    }
    if check_for_out_of_bounds(Vec3 {
        x: voxel.0.x as f32,
        y: voxel.0.y as f32,
        z: voxel.0.z as f32 - 1 as f32,
    }) {
        //check for left
        if !voxel_array.contains_key(&Position {
            x: voxel.0.x,
            y: voxel.0.y,
            z: voxel.0.z - 1,
        }) {
            generate_voxel_mesh(
                Vec3 {
                    x: voxel.0.x as f32 + chunk_pos.x,
                    y: voxel.0.y as f32 + chunk_pos.y,
                    z: voxel.0.z as f32 + chunk_pos.z,
                },
                1.0,
                voxel.1.voxel_id,
                mesh_builder,
                Vec3 {
                    x: 0.0,
                    y: 0.0,
                    z: -1.0,
                },
            )
        }
    }
    if check_for_out_of_bounds(Vec3 {
        x: voxel.0.x as f32,
        y: voxel.0.y as f32,
        z: voxel.0.z as f32 + 1 as f32,
    }) {
        //check for right
        if !voxel_array.contains_key(&Position {
            x: voxel.0.x,
            y: voxel.0.y,
            z: voxel.0.z + 1,
        }) {
            generate_voxel_mesh(
                Vec3 {
                    x: voxel.0.x as f32 + chunk_pos.x,
                    y: voxel.0.y as f32 + chunk_pos.y,
                    z: voxel.0.z as f32 + chunk_pos.z,
                },
                1.0,
                voxel.1.voxel_id,
                mesh_builder,
                Vec3 {
                    x: 0.0,
                    y: 0.0,
                    z: 1.0,
                },
            )
        }
    }
    if check_for_out_of_bounds(Vec3 {
        x: voxel.0.x as f32 - 1 as f32,
        y: voxel.0.y as f32,
        z: voxel.0.z as f32,
    }) {
        //check for forward
        if !voxel_array.contains_key(&Position {
            x: voxel.0.x - 1,
            y: voxel.0.y,
            z: voxel.0.z,
        }) {
            generate_voxel_mesh(
                Vec3 {
                    x: voxel.0.x as f32 + chunk_pos.x,
                    y: voxel.0.y as f32 + chunk_pos.y,
                    z: voxel.0.z as f32 + chunk_pos.z,
                },
                1.0,
                voxel.1.voxel_id,
                mesh_builder,
                Vec3 {
                    x: -1.0,
                    y: 0.0,
                    z: 0.0,
                },
            )
        }
    }
    if check_for_out_of_bounds(Vec3 {
        x: voxel.0.x as f32 + 1 as f32,
        y: voxel.0.y as f32,
        z: voxel.0.z as f32,
    }) {
        //check for back
        if !voxel_array.contains_key(&Position {
            x: voxel.0.x + 1,
            y: voxel.0.y,
            z: voxel.0.z,
        }) {
            generate_voxel_mesh(
                Vec3 {
                    x: voxel.0.x as f32 + chunk_pos.x,
                    y: voxel.0.y as f32 + chunk_pos.y,
                    z: voxel.0.z as f32 + chunk_pos.z,
                },
                1.0,
                voxel.1.voxel_id,
                mesh_builder,
                Vec3 {
                    x: 1.0,
                    y: 0.0,
                    z: 0.0,
                },
            )
        }
    }
}

优化方案

1. 体素存储结构重构

哈希表的contains_key存在哈希计算与查找开销,直接改用三维数组存储体素,访问速度接近O(0):

// 定义固定尺寸的三维数组,None代表空体素
let mut voxel_grid = [[[Option<Voxel>; 128]; 256]; 128];

生成体素时直接填充数组,避免键值对的内存分配与拷贝:

let chunk_x_offset = chunk_position.x as f64 * 0.01;
let chunk_z_offset = chunk_position.z as f64 * 0.01;

for x in 0..=width {
    for z in 0..=depth {
        let noise_value1 = noise.get([
            chunk_x_offset + (x as f32 * 0.01) as f64,
            chunk_z_offset + (z as f32 * 0.01) as f64,
        ]) as f32;
        let mut y = ((noise_value1 * 20.0) + (CHUNK_DEPTH / 3) as f32).round() as usize;
        y = y.min(height);

        for n in 0..y {
            voxel_grid[x][n][z] = Some(Voxel { voxel_id: 1 });
        }
    }
}

2. 可见面检查逻辑精简

  • 预定义6个方向的偏移量数组,消除代码冗余:
    const DIRECTIONS: [(i8, i8, i8, Vec3); 6] = [
        (0, 1, 0, Vec3 {x:0.0,y:1.0,z:0.0}), // 上
        (0, -1, 0, Vec3 {x:0.0,y:-1.0,z:0.0}), // 下
        (0, 0, -1, Vec3 {x:0.0,y:0.0,z:-1.0}), // 左
        (0, 0, 1, Vec3 {x:0.0,y:0.0,z:1.0}), // 右
        (-1, 0, 0, Vec3 {x:-1.0,y:0.0,z:0.0}), // 前
        (1, 0, 0, Vec3 {x:1.0,y:0.0,z:0.0}), // 后
    ];
    
  • 合并边界检查与体素存在性判断,避免重复调用check_for_out_of_bounds:
    for x in 0..128 {
        for y in 0..256 {
            for z in 0..128 {
                if let Some(voxel) = &voxel_grid[x][y][z] {
                    for &(dx, dy, dz, dir) in &DIRECTIONS {
                        let nx = x as i8 + dx;
                        let ny = y as i8 + dy;
                        let nz = z as i8 + dz;
    
                        // 相邻位置越界 或 无体素时渲染面
                        let should_render = if nx < 0 || nx >= 128 || ny < 0 || ny >= 256 || nz < 0 || nz >= 128 {
                            true
                        } else {
                            voxel_grid[nx as usize][ny as usize][nz as usize].is_none()
                        };
    
                        if should_render {
                            generate_voxel_mesh(
                                Vec3 {
                                    x: x as f32 + chunk_pos.x,
                                    y: y as f32 + chunk_pos.y,
                                    z: z as f32 + chunk_pos.z,
                                },
                                1.0,
                                voxel.voxel_id,
                                mesh_builder,
                                dir,
                            );
                        }
                    }
                }
            }
        }
    }
    

3. 噪声采样与计算优化

  • 提前计算chunk级别的噪声偏移值,避免循环内重复计算chunk_position.x/z * 0.01;
  • 若使用的噪声库支持批量采样,一次性生成所有x/z坐标的噪声值,减少函数调用开销;
  • 尝试用floor()替代round()(若业务允许),降低浮点运算成本。

4. 网格生成批量优化

  • 预定义各方向面的顶点模板,仅需添加体素偏移量即可生成顶点坐标,避免重复计算;
  • 收集所有需要渲染的面数据,一次性提交给mesh_builder,减少单步调用的 overhead。

内容的提问来源于stack exchange,提问作者NewUser69420

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 22:52:03