HTML5建模怎么创建地形_高度图生成地形方法【教程】

15次阅读

关键限制是html5不提供地形建模能力,需用webgl(如Three.js)运行时解析高度图像素生成BufferGeometry;核心是将PNG灰度值0–255映射为Y坐标,须确保无跨域、加载完成、无缩放失真,推荐2ⁿ+1尺寸。

HTML5建模怎么创建地形_高度图生成地形方法【教程】

WebGL 场景中用 heightmap 生成地形的关键限制

html5 本身不提供地形建模能力,所谓“HTML5 建模”实际依赖 WebGL(通常通过 Three.js 等库)加载高度图(heightmap)并构造顶点网格。浏览器无法直接执行离线建模操作,所有地形必须在运行时由 javaScript 解析图像像素、生成 BufferGeometry 并赋予材质。

怎么把一张 PNG 高度图转成 Three.js 可用的地形网格

核心是读取灰度图每个像素的亮度值(0–255),映射为顶点 Y 坐标。常见错误是直接用 ImageBitmapcanvas.getContext('2d') 读取后忽略图像是否跨域、是否已加载完成、是否被缩放抗锯齿干扰。

  • 高度图必须是纯灰度 PNG(无 alpha 通道干扰),推荐尺寸为 2n+1(如 513×513),便于细分和 LOD
  • fetch + createImageBitmap 加载,避免 canvas drawImage 的自动缩放失真
  • getImageData 读取像素后,遍历 data 数组,每 4 字节data[i](R 通道即灰度)作为高度源
  • 生成顶点时注意:X/Z 坐标按网格索引等距铺开,Y = heightScale * (grayValue / 255)heightScale 决定地形起伏幅度
const img = await createImageBitmap(response); const canvas = new OffscreenCanvas(img.width, img.height); const ctx = canvas.getContext('2d'); ctx.drawImage(img, 0, 0); const data = ctx.getImageData(0, 0, img.width, img.height).data; const geometry = new THREE.PlaneGeometry(width, depth, img.width - 1, img.height - 1); const vertices = geometry.attributes.position.Array; for (let i = 0; i < data.length; i += 4) {   const x = (i / 4) % img.width;   const z = math.floor((i / 4) / img.width);   const h = (data[i] / 255) * heightScale; // 仅用 R 通道   const idx = (z * (img.width) + x) * 3;   vertices[idx + 1] = h; // Y 分量 }

为什么用 THREE.PlaneGeometry 而不是 THREE.BoxGeometry 或手写顶点

BoxGeometry 是封闭立方体,无法表达连续起伏表面;手写完整顶点+索引虽灵活但极易出错(法线、UV、索引顺序)。而 PlaneGeometry 提供规整的 XY 网格拓扑,只需修改 Y 值即可复用其 UV 和法线计算逻辑,且内置 rotateX(Math.PI / 2) 可快速让平面朝上。

  • 务必调用 geometry.computeVertexNormals(),否则光照会全黑或异常
  • 若需平滑过渡,可在修改顶点后调用 geometry.mergeVertices()(对大图慎用,性能下降明显)
  • UV 默认从 (0,0) 到 (1,1),若高度图需重复贴图,应手动重写 geometry.attributes.uv.array

移动端和低配设备上高度图地形卡顿的根源

问题不在“画质”,而在顶点数爆炸:513×513 网格产生约 26 万顶点,WebGL 渲染管线需逐顶点计算光照+变换,低端 GPU 显存带宽不足,requestAnimationFrame 掉帧严重。

立即学习前端免费学习笔记(深入)”;

  • 真实项目中应预设 LOD 层级:远距离用 129×129 网格,中距离 257×257,近处才用原图精度
  • 禁用 antialias: true(尤其在 ios safari),它会让 WebGLRenderingContext 内部多一倍渲染路径
  • 高度图纹理本身建议压缩为 KTX2 格式并启用 EXT_texture_compression_bptc,减小 GPU 显存占用

真正难的不是“怎么画出来”,而是怎么让同一张 heightmap 在 iphone SE 和 RTX 4090 上都保持 60fps——这取决于你是否愿意为不同设备动态切换几何精度、是否接受用 WebAssembly 预处理高度图而非 JS 实时解析。

text=ZqhQzanResources