如何正确对Marching Cubes生成的地形进行地形编辑?
地形编辑方案优化(解决密度场混乱与编辑速度不一致问题)
问题根源分析
Sebastian Lague方法缺陷
直接对密度值做加减操作,未约束密度范围,多次编辑后密度值会超出设计的[-0.5, 0.5]区间,破坏密度场的梯度连续性,最终导致等值面变形、地形异常。
Cubiquity复刻方法缺陷
- 编辑速度依赖密度梯度:地形高处/低处的梯度方向与初始梯度(y方向0.01)偏差大时,采样点的密度值变化幅度不可控,导致编辑速度不均。
- 采样逻辑未绑定编辑目标:删除/添加地形时,采样点的选取未与编辑方向关联,出现顶部删除瞬间完成这类异常。
改进的编辑方案
核心逻辑
结合两种方法的优势,基于等值面垂直方向的平滑偏移进行编辑,同时约束密度值范围,保证编辑速度统一与密度场连续性。
实现代码(Compute Shader)
[numthreads(8,8,8)] void CSMain(uint3 id : SV_DispatchThreadID) { // 边界防护,避免纹理越界访问 if (id.x >= textureSizeX - 1 || id.y >= textureSizeY - 1 || id.z >= textureSizeZ - 1 || id.x < 1 || id.y < 1 || id.z < 1) return; float3 terraformPoint = /* 传入的画笔中心voxel坐标 */; float3 delta = terraformPoint - float3(id); float dstSqrd = dot(delta, delta); float brushSizeSqrd = brushSize * brushSize; // 超出画笔范围则跳过 if (dstSqrd > brushSizeSqrd) return; // 画笔强度:高斯衰减,边缘过渡更自然 float dst = sqrt(dstSqrd); float intensity = exp(-(dst * dst) / (2 * brushSize * brushSize)); // 计算当前voxel的密度梯度(法线方向) float voxNX = densityTexture[int3(id.x-1, id.y, id.z)]; float voxPX = densityTexture[int3(id.x+1, id.y, id.z)]; float voxNY = densityTexture[int3(id.x, id.y-1, id.z)]; float voxPY = densityTexture[int3(id.x, id.y+1, id.z)]; float voxNZ = densityTexture[int3(id.x, id.y, id.z-1)]; float voxPZ = densityTexture[int3(id.x, id.y, id.z+1)]; float3 gradient = float3(voxPX - voxNX, voxPY - voxNY, voxPZ - voxNZ); float gradientLen = length(gradient); // 默认法线为y轴(初始平面的法线方向) float3 normal = gradientLen > 0.001 ? normalize(gradient) : float3(0, 1, 0); // weight>0:抬升地形(密度向0等值面上方偏移);weight<0:降低地形 float editSign = sign(weight); // 用初始密度梯度(0.01)统一编辑速度,避免高低处差异 float deltaDensity = editSign * intensity * abs(weight) * deltaTime * 0.01; // 更新密度并约束范围 float currentDensity = densityTexture[id]; float newDensity = clamp(currentDensity + deltaDensity, -0.5, 0.5); densityTexture[id] = newDensity; }
关键改进点
- 密度范围约束:用
clamp强制密度值保持在[-0.5, 0.5],彻底解决多次编辑后的密度场混乱问题。 - 统一编辑速度:基于初始密度的梯度值(0.01)缩放变化量,确保不同高度的编辑速度一致,修复Cubiquity方法的速度不均问题。
- 平滑梯度编辑:沿着等值面法线方向调整密度,保证编辑后地形的平滑性,避免暴力加减导致的等值面变形。
- 自然的画笔衰减:采用高斯衰减曲线,让画笔边缘的编辑过渡更柔和,减少地形锯齿。
额外优化建议
- 后处理平滑:编辑完成后增加一个3x3x3的高斯模糊pass,消除多次编辑产生的微小密度噪点,进一步提升等值面平滑度。
- 实时梯度缓存:将密度梯度预计算并缓存到另一个
RWTexture3D,避免每次编辑都重复计算,提升性能。 - 画笔形状扩展:支持圆形、方形等不同画笔形状,通过修改强度计算逻辑实现。
内容的提问来源于stack exchange,提问作者AndrewSargin
相关产品推荐
相关产品推荐

