Skip to content

添加水体

loading

与 sky 类似,直接把 threejs 的 water 示例搬过来即可

ts
function initWater() {
  const center = map.geo2map(new THREE.Vector3(89.4, 42.7));
  const waterGeometry = new THREE.PlaneGeometry(300 * 1000, 300 * 1000);

  const water = new Water(waterGeometry, {
    textureWidth: 512,
    textureHeight: 512,
    waterNormals: new THREE.TextureLoader().load("../waternormals.jpg", function (texture) {
      texture.wrapS = texture.wrapT = THREE.RepeatWrapping;
    }),
    sunDirection: new THREE.Vector3(),
    sunColor: 0xffffff,
    waterColor: 0x001e0f,
    distortionScale: 1,
    alpha: 1,
  });
  water.material.transparent = true;
  water.material.uniforms["size"].value = 0.1;
  water.position.set(center.x, center.y + 5, 200);

  const before = water.onBeforeRender;
  const after = water.onAfterRender;
  water.onBeforeRender = (renderer, scene, camera, geometry, material, group) => {
    map.autoUpdate = false;
    before.call(water, renderer, scene, camera, geometry, material, group);
  };
  water.onAfterRender = (renderer, scene, camera, geometry, material, group) => {
    map.autoUpdate = true;
    after.call(water, renderer, scene, camera, geometry, material, group);
  };
  map.add(water);

  viewer.addEventListener("update", () => {
    water.material.uniforms["time"].value += 1.0 / 60.0;
  });

  return water;
}

TIP

water 模型内部渲染在前会修改 camer 位置做离屛渲染,这会触发地图的 LOD 造成地图抖动,所以需要在 water 渲染前禁止地图更新,渲染后再放开.

TIP

水面与陆地交界有些生硬,我想可以用 threejs 的 FXAA、SAO 等后期缓解,有兴趣的同学可以试试。


Released under the MIT License.