【cesium】修改底图颜色为蓝色科技范儿

2,575 阅读1分钟

cesium中,默认的底图颜色往往难以满足个性化需求,而【蓝色科技】风格常常备受青睐,本文从实操角度介绍实现方法。

image.png

简单来说,我们所用的方法叫做【反色滤镜】,总的分为2个步骤,反色,过滤。具体做法如下:

首先要获取目标影像图层,这里不能直接对div进行操作,因为会将地图上的所有元素都反色过滤了。

 // 获取地图影像图层
  let baseLayer = viewer.imageryLayers.get(0);

其次,定义2个变量,用来控制是否反色,以及过滤的具体值

  //设置2个变量,用来判断是否进行颜色的翻转和过滤
  baseLayer.invertColor = true;
  baseLayer.filterRGB = [0, 50, 100]; //[255,255,255] = > [0,50,100]

接着要获取着色器,方便后续直接操作着色器,写入修改后的glsl。

//   更改底图着色器的代码
  const baseFragmentShader =
    viewer.scene.globe._surfaceShaderSet.baseFragmentShaderSource.sources;

通过打印baseFragmentShader,可以看到里面有3个

image.png

接下来是最关键的步骤,反色+过滤。

// 循环修改着色器
  for (let i = 0; i < baseFragmentShader.length; i++) {
    // console.log(baseFragmentShader[i]);
    const strS = "color = czm_saturation(color, textureSaturation);\n#endif\n";
    let strT = "color = czm_saturation(color, textureSaturation);\n#endif\n";
    if (baseLayer.invertColor) {
      strT += `
        color.r = 1.0 - color.r;
        color.g = 1.0 - color.g;
        color.b = 1.0 - color.b;
      `;
    }
    if (baseLayer.filterRGB) {
      strT += `
        color.r = color.r*${baseLayer.filterRGB[0]}.0/255.0;
        color.g = color.g*${baseLayer.filterRGB[1]}.0/255.0;
        color.b = color.b*${baseLayer.filterRGB[2]}.0/255.0;
      `;
    }

    baseFragmentShader[i] = baseFragmentShader[i].replace(strS, strT);
  }

因为R、G、B都是从0-1,反色就是用1减去原来的值

color.r = 1.0 - color.r;
color.g = 1.0 - color.g;
color.b = 1.0 - color.b;

过滤则是要套用公式,对R、G、B进行操作

color.r = color.r*${baseLayer.filterRGB[0]}.0/255.0;
color.g = color.g*${baseLayer.filterRGB[1]}.0/255.0;
color.b = color.b*${baseLayer.filterRGB[2]}.0/255.0;

strS中的内容是glsl,原本就存在于baseFragmentShader中,而修改后的颜色值,直接用replace进行替换,将strT顶进去,发挥作用。

filterRGB的值可以根据需要进行调整,我试了2个值,都不错 [60, 145, 172] 和[0, 50, 100]

image.png

image.png

完整代码如下,可以封装成一个方法被调用。

export default function modifyMap(viewer) {
  // 获取地图影像图层
  let baseLayer = viewer.imageryLayers.get(0);
  //设置2个变量,用来判断是否进行颜色的翻转和过滤
  baseLayer.invertColor = true;

  baseLayer.filterRGB = [0, 50, 100]; //[255,255,255] = > [0,50,100]
  //   更改底图着色器的代码
  const baseFragmentShader =
    viewer.scene.globe._surfaceShaderSet.baseFragmentShaderSource.sources;
  // console.log(baseFragmentShader);

  // 循环修改着色器
  for (let i = 0; i < baseFragmentShader.length; i++) {
    // console.log(baseFragmentShader[i]);
    const strS = "color = czm_saturation(color, textureSaturation);\n#endif\n";
    let strT = "color = czm_saturation(color, textureSaturation);\n#endif\n";
    if (baseLayer.invertColor) {
      strT += `
        color.r = 1.0 - color.r;
        color.g = 1.0 - color.g;
        color.b = 1.0 - color.b;
      `;
    }
    if (baseLayer.filterRGB) {
      strT += `
        color.r = color.r*${baseLayer.filterRGB[0]}.0/255.0;
        color.g = color.g*${baseLayer.filterRGB[1]}.0/255.0;
        color.b = color.b*${baseLayer.filterRGB[2]}.0/255.0;
      `;
    }

    baseFragmentShader[i] = baseFragmentShader[i].replace(strS, strT);
  }
}