cesium 修改底图着色器

部署运行你感兴趣的模型镜像

一般cesium中瓦片底图使用的api为:

WebMapTileServiceImageryProvider

但是关于改api我们发现ceisum并不支持在该api直接修改着色器的属性。只有简单属性的修改

   // this.tileLayer.brightness = params.brightness;

      // this.tileLayer.contrast = params.contrast;

      // this.tileLayer.hue = params.hue;

      // this.tileLayer.saturation = params.saturation;

这并不满足需求。

翻阅资料我们发现viewer.scene.globe._surfaceShaderSet.baseFragmentShaderSource.sources这个属性中是全局着色器的实现。我们在不想修改源代码的情况下可以改这里的代码,从而实现瓦片着色器的修改。只需写好着色器代码替换颜色相关的着色器代码就行。这里我移植three着色器代码到cesium中

  • three着色器
<!DOCTYPE html>
<html lang="zh-cn">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
    <title>three-tile最小化应用</title>
    <style>
      html,
      body {
        color: white;
        background-color: #333;
        height: 100%;
        min-height: 600px;
        width: 100%;
        padding: 0;
        margin: 0;
        display: flex;
        overflow: hidden;
        flex-direction: column;
        text-align: center;
      }
      #map {
        height: 100%;
        width: 100%;
      }
      #loading {
        position: absolute;
        bottom: 0px;
        left: 20px;
      }
      .controls {
        position: absolute;
        top: 20px;
        right: 20px;
        display: flex;
      }
      button {
        background-color: #333;
        border: 1px solid white;
        border-radius: 5px;
        padding: 0 5px;
        box-shadow: 0 0 5px black;
        margin-right: 10px;
      }
    </style>
    <script type="importmap">
      {
            "imports": {
                "three": "https://unpkg.com/three@0.171.0/build/three.module.js",
                "three-tile": "https://unpkg.com/three-tile@0.11.10/dist",
                "three-tile/plugin": "https://unpkg.com/three-tile@0.11.10/dist/plugin"
            }
        }
    </script>
  </head>
  <body>
    <div id="map"></div>
    <div id="loading">-</div>
    <div class="controls">
      <button onclick="handleReset()">原始样式</button>
      <button onclick="handlFilter()">自定义着色器</button>
      <button onclick="setStyle(0xaaccff)">蓝色</button>
      <button onclick="setStyle(0x88ffcc)">绿色</button>
      <button onclick="setStyle(0xffaaaa)">红色</button>
    </div>
    <script type="module">
      import * as THREE from "three";
      import * as tt from "three-tile";
      import * as plugin from "three-tile/plugin";
      console.log(`three-tile v${tt.version} start!`);
      //==============================================================
      // 定义着色器
      class Filter extends THREE.MeshBasicMaterial {
        constructor(params) {
          super(params);
          this.onBeforeCompile = (shader) => {
            // 修改片段着色器  replace替换代码
            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 );
                            `
            );
          };
        }
      }
      //==============================================================
      // 修改影像加载器的材质为Filter
    //   const loader = tt.getImgLoader("image");
    //   loader.material = new Filter({
    //   });
      //==============================================================
      // 创建地图
      const map = tt.TileMap.create({
        // 影像数据源
        imgSource: new plugin.GDSource({
          style: 7
        }),
        minLevel: 4,
        lon0: 90,
        // 地图经纬度范围
        bounds: [60, 0, 145, 60],
      });
      // 地图旋转到xz平面
      map.rotateX(-Math.PI / 2);
      // 初始化场景
      const viewer = new plugin.GLViewer("#map");
      viewer.scene.background = new THREE.Color(0x000022);
      // 地图添加到场景
      viewer.scene.add(map);
      //==============================================================
      // 地图中心经纬度高度(m)转为世界坐标
      const centerPostion = map.geo2world(new THREE.Vector3(116.4, 39.92, 0));
      // 摄像机经纬度高度(m)转为世界坐标
      const cameraPosition = map.geo2world(new THREE.Vector3(116.4, 39.91, 10000));
      viewer.flyTo(centerPostion, cameraPosition, false);
      //==============================================================
      // 显示地图加载进度
      function showLoading(map, id) {
        const el = document.querySelector("#loading");
        if (el) {
          map.addEventListener("loading-start", (evt) => {
            el.innerHTML = "Started: " + evt.itemsLoaded + " of " + evt.itemsTotal + " files.";
          });
          map.addEventListener("loading-progress", (evt) => {
            el.innerHTML = "Loading: " + evt.itemsLoaded + " of " + evt.itemsTotal + " files.";
          });
          map.addEventListener("loading-complete", () => {
            el.innerHTML = "Loading complete!";
          });
          map.addEventListener("loading-error", (url) => {
            el.innerHTML = "There was an error loading " + url;
          });
        }
      }
      showLoading(map);
      //===========================================================
      // 修改着色器

      window.handlFilter = function() {
        // 修改影像加载器的材质
       const loader = tt.getImgLoader("image"); 
       loader.material = new Filter({
          color: 0xaacc
        });
        map.reload();
      };
      window.setStyle = (color) => {
        loader.material.color.set(color);
        map.reload();
      };
    </script>
  </body>
</html>

  • ceisum集成
      const baseFragmentShader =
        viewer.scene.globe._surfaceShaderSet.baseFragmentShaderSource.sources;

        
      // 循环修改着色器
      for (let i = 0; i < baseFragmentShader.length; i++) {
        const strS =
          "color = czm_saturation(color, textureSaturation);\n#endif\n";
        let strT =
          "color = czm_saturation(color, textureSaturation);\n#endif\n";

        strT += `
  // 定义要保留的特定颜色范围(例如:水的蓝色)
  vec3 targetColor = vec3(145.0/255.0, 171.0/255.0, 188.0/255.0); // 目标颜色
  float colorThreshold = 0.25; // 颜色相似度阈值
  
  // 计算当前颜色与目标颜色的差异
  float colorDiff = length(color.rgb - targetColor);
  
  // 只有当颜色差异大于阈值时才应用滤镜效果
  if (colorDiff > colorThreshold) {
  vec3 diffuse = vec3(0.17, 0.56, 0.99);
    vec3 inverted = 1.0 - color.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;
    color.rgb = finalColor;
      `;

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

您可能感兴趣的与本文相关的镜像

ACE-Step

ACE-Step

音乐合成
ACE-Step

ACE-Step是由中国团队阶跃星辰(StepFun)与ACE Studio联手打造的开源音乐生成模型。 它拥有3.5B参数量,支持快速高质量生成、强可控性和易于拓展的特点。 最厉害的是,它可以生成多种语言的歌曲,包括但不限于中文、英文、日文等19种语言

Cesium 中加载底图通常涉及使用 `CesiumWebMapServiceImageryProvider` 或其子类来加载各种类型的影像服务。以下是一个基本的源代码示例,展示了如何加载一个 WMS 服务作为底图[^1]。 ### 示例:加载 WMS 底图 ```javascript const viewer = new Cesium.Viewer('cesiumContainer'); // 创建一个 WMS 图层提供者 const wms = new Cesium.WebMapServiceImageryProvider({ url: 'https://your-wms-service-url/wms', subdomains: ['s1', 's2'], customTags: { // 自定义标签可以用于传递额外参数 time: () => { return Cesium.JulianDate.now().secondsOfDay; } }, getCustomUrlTemplate: function() { // 可以在此处修改 URL 模板 return this.url + '?service=WMS&version=2.0.0&request=GetMap&layers={layers}&styles={styles}&format=image/png&transparent=true&height={height}&width={width}&srs={crs}&bbox={bbox-epsg-3857}'; } }); // 添加到 Viewer 的影像图层中 viewer.imageryLayers.addImageryProvider(wms); ``` ### 示例:加载高德地图(WMTS) 如果你希望加载的是像高德地图这样的 WMTS 服务,也可以通过 `Cesium.WebMapTileServiceImageryProvider` 来实现: ```javascript const viewer = new Cesium.Viewer('cesiumContainer'); const amap = new Cesium.WebMapTileServiceImageryProvider({ url: 'https://webst0{s}.is.autonavi.com/appmaptile?style=6&x={x}&y={y}&z={z}', subdomains: ['1', '2', '3', '4'], maximumLevel: 18, tilingScheme: new Cesium.WebMercatorTilingScheme() }); viewer.imageryLayers.addImageryProvider(amap); ``` ### 动态调整滤镜与反色 如果需要对底图进行动态滤镜或反色处理,可以通过修改 `imageryLayers` 的 `alpha`, `brightness`, `contrast`, `hue`, `saturation`, `gamma`, `invertColor` 等属性来实现。例如: ```javascript const layer = viewer.imageryLayers.addImageryProvider(amap); layer.alpha = 1.0; // 设置透明度 layer.brightness = 1.5; // 提高亮度 layer.contrast = 1.2; // 提高对比度 layer.hue = 0.5; // 改变色调 layer.saturation = 2.0; // 提高饱和度 layer.gamma = 1.0; // 调整伽马值 layer.invertColors = true; // 启用颜色反转 ``` 这些属性可以直接在运行时修改,允许开发者根据需求实时调整底图的视觉效果。 ### 示例:劫持 Shader 实现滤镜效果 如引用中提到的,如果需要更复杂的滤镜效果(如反色),可能需要通过修改渲染管线中的着色器(Shader)来实现。虽然这不是官方推荐的做法,但在某些情况下可以作为一种临时解决方案: ```javascript viewer.scene.postProcessStages.fxaa.enabled = false; const fragmentShaderSource = ` in vec4 v_color; out vec4 fragColor; void main() { vec4 color = texture(sampler2D, v_texCoord); // 反色处理 fragColor = vec4(1.0 - color.r, 1.0 - color.g, 1.0 - color.b, color.a); } `; const postStage = new Cesium.PostProcessStage({ fragmentShader: fragmentShaderSource }); viewer.scene.postProcessStages.add(postStage); ``` 上述代码展示了一个简单的后处理阶段,通过自定义片段着色器实现了图像的反色效果。这种方式可以在不直接修改 Cesium 源码的情况下实现较为复杂的视觉效果。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值