Skip to content

自定义瓦片着色器≥0.11.4

loading

three-tile 地图瓦片默认使用MeshStandardMaterial材质,可以使用自定义材质实现地图特效。

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>",
                `
        #include <dithering_fragment>
        vec4 texel = texture2D( map, vMapUv );                
        vec3 inverted = 1.0 - texel.rgb; 
        float luminance = dot(inverted, vec3(0.299, 0.587, 0.114));
        vec3 grayscale = vec3(luminance);                            
        vec3 finalColor = mix(grayscale, inverted, 0.6) * diffuse * 2.0;                            
        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.