Skip to content

自定义瓦片着色器

loading

1. 步骤

内置的影像加载器TileMaterialLoader(包括其子类)有一个material属性,所有瓦片材质均从该材质 clone 得来,修改此material不仅可以改变瓦片默认材质,还可以使用自定义着色器替换材质,利用着色器实现各种特效。自定义瓦片着色器步骤如下:

  1. 编写自定义着色器材质
  2. 获取加载器实例
  3. 修改加载器的material属性

2. 代码

  1. 写一个简单的着色器,将地图反色、降低饱和度,并与原地图色混合:
ts
// 定义着色器
class Filter extends THREE.MeshBasicMaterial {
  constructor(params) {
    super(params);
    this.onBeforeCompile = (shader) => {
      // 修改片段着色器
      shader.fragmentShader = shader.fragmentShader.replace(
        "#include <dithering_fragment>",
        `
          vec4 texel = texture2D( map, vMapUv );
          vec3 inverted = mix(texel.rgb, 1.0 - texel.rgb, 1.0);
          float luminance = dot(inverted, vec3(0.299, 0.587, 0.114));
          vec3 grayscale = vec3(luminance);
          vec3 finalColor = mix(grayscale, inverted, 0.6) * diffuse;
          gl_FragColor =  vec4( finalColor, opacity * texel.a );
        `
      );
    };
  }
}
  1. 使用自定义着色器
ts
// 修改影像加载器的材质
const loader = tt.getImgLoader("image");
loader.material = new Filter({ color: 0xaaccff });
map.reload();

TIP

每块瓦片的材质均是从该着色器 clone 而来,各个材质没有关联,所以运行时修改该着色器的属性如颜色,已有瓦片并不会实时响应。如果要实现实时调整颜色等属性的功能,有两种方案:

  1. 修改属性时,遍历所有瓦片修改每个瓦片的材质属性,效率略低。使用 threejs 内置材质时建议使用该方法。
  2. 重写材质的copy函数,clone 时,将材质的 uniform 以引用方式传递而不是复制,让所有瓦片的材质的 uniform 指向同一个对象。使用自定义着色器时建议使用该方法。


Released under the MIT License.