VUE3-Cesium(着色器的使用-编写图案、动画绘图、圆环扩散效果、雷达效果实现)

目录

1. 运用着色器编写图案

​2.着色器实现动画绘图

3.着色器实现圆环扩散效果

4.着色器实现雷达图效果


1. 运用着色器编写图案

1)挤出一个盒子

  const extrudePolygon = new Cesium.PolygonGeometry({
    polygonHierarchy: new Cesium.PolygonHierarchy(
      Cesium.Cartesian3.fromDegreesArray([
        112.417, 23.29, 113.67, 23.56, 114.093, 22.59, 112.838, 22.285,
      ])
    ),
    // extrudedHeight: 30000,
  });

  const instance = new Cesium.GeometryInstance({
    geometry: extrudePolygon,
    id: "挤出四边形",
  });

2)设置材质

const material = new Cesium.Material({
    fabric: {
      // type: "Color",
      // uniforms: {
      //   color: new Cesium.Color(1.0, 0.0, 0.0, 0.5),
      // },
      source: `
      czm_material czm_getMaterial(czm_materialInput materialInput)
      {
          czm_material material = czm_getDefaultMaterial(materialInput);
          material.diffuse = vec3(0.84,0.66,0.81);
          
          return material;
      }
      `,
    },
  });
 console.log(material.shaderSource);

控制台输出:

 

3)着色器设置材质外观

 const appearance = new Cesium.MaterialAppearance({
    fragmentShaderSource: `
    varying vec3 v_positionEC;
    varying vec3 v_normalEC;
    varying vec2 v_st;

   void main()
  {
    vec3 positionToEyeEC = -v_positionEC;

    vec3 normalEC = normalize(v_normalEC);
   #ifdef FACE_FORWARD
    normalEC = faceforward(normalEC, vec3(0.0, 0.0, 1.0), -normalEC);
   #endif

    czm_materialInput materialInput;
    materialInput.normalEC = normalEC;
    materialInput.positionToEyeEC = positionToEyeEC;
    materialInput.st = v_st;
    czm_material material = czm_getMaterial(materialInput);
   //  实现圆
   // float strength = 1.0 - distance(v_st,vec2(0.5,0.5))*2.0;  
   // material.diffuse = vec3(strength);
   // material.alpha = step(0.0,strength);

   // 渐变环
   float strength =  1.0-(abs(distance(v_st,vec2(0.5,0.5))-0.25)*4.0);
   material.diffuse = vec3(strength);
   material.alpha = step(0.0,strength);


   #ifdef FLAT
    gl_FragColor = vec4(material.diffuse + material.emission, material.alpha);
   #else
    gl_FragColor = czm_phong(normalize(positionToEyeEC), material, czm_lightDirectionEC);
   #endif
  }
    `,
  });

4)实例化着色图元

// 创建图元添加
  var primitive = viewer.scene.primitives.add(
    new Cesium.Primitive({
      geometryInstances: [instance],
      appearance: appearance,
    })
  );

  console.log(appearance.vertexShaderSource);
  console.log(appearance.fragmentShaderSource);

控制台输出:

 5)实现效果:


2.着色器实现动画绘图

1)挤出矩形

const extrudePolygon = new Cesium.PolygonGeometry({
    polygonHierarchy: new Cesium.PolygonHierarchy(
      Cesium.Cartesian3.fromDegreesArray([
        112.417, 23.29, 113.67, 23.56, 114.093, 22.59, 112.838, 22.285,
      ])
    ),
    // extrudedHeight: 30000,
  });

  const instance = new Cesium.GeometryInstance({
    geometry: extrudePolygon,
    id: "挤出四边形",
  });

2) 实例化材质:

  const material = new Cesium.Material({
    fabric: {
      // type: "Color",
      uniforms: {
        color: new Cesium.Color(1.0, 0.0, 0.0, 0.5),
        uTime: 0,
      },
      source: `
      czm_material czm_getMaterial(czm_materialInput materialInput)
      {
          czm_material material = czm_getDefaultMaterial(materialInput);
          material.diffuse = vec3(uTime,uTime,0.81);

          return material;
      }
      `,
    },
  });
  console.log(material);
  console.log(material.shaderSource);

3)安装gasp实现补间动画:

GASP是一款可以用来制作动画的js插件。GASP是一个JavaScript动画库,它支持快速开发高性能的 Web 动画。GASP 使我们能够轻松轻松快速的将动画串在一起,来创造一个高内聚的流畅动画序列。

安装:

npm install gsap

yarn add gasp

导入:

import gsap from "gsap";

使用:

第一个参数为要控制元素的选择器,第二个参数为控制元素的动画属性

  gsap.to(material.uniforms, {
    uTime: 1,
    duration: 1,//持续时长
    repeat: -1,//重复次数
    yoyo: true,//是否往返动画
    ease: "linear",//运动模式
    onUpdate: () => {
      console.log("值发生了修改");

    },
  });

4)实例化材质表面和图元

const appearance = new Cesium.MaterialAppearance({
    material: material,
    // translucent: true,
    // closed: true,
  });

  // 创建图元添加
  var primitive = viewer.scene.primitives.add(
    new Cesium.Primitive({
      geometryInstances: [instance],
      appearance: appearance,
    })
  );

  console.log(appearance.vertexShaderSource);
  console.log(appearance.fragmentShaderSource);

5)实现效果:

 3.着色器实现圆环扩散效果

与上实现原理基本相似,通过挤出四边形,在该四边形上绘制半径变化的圆,并通过设置透明度,实现圆环扩散效果。

1)挤出矩形

const extrudePolygon = new Cesium.PolygonGeometry({
    polygonHierarchy: new Cesium.PolygonHierarchy(
      Cesium.Cartesian3.fromDegreesArray([
        112.417, 23.29, 113.67, 23.56, 114.093, 22.59, 112.838, 22.285,
      ])
    ),
    // extrudedHeight: 30000,
  });

  const instance = new Cesium.GeometryInstance({
    geometry: extrudePolygon,
    id: "挤出四边形",
  });

2)利用着色器绘制图形

const material = new Cesium.Material({
    fabric: {
      // type: "Color",
      uniforms: {
        color: new Cesium.Color(1.0, 0.0, 0.0, 0.5),
        uTime: 0,
      },
      source: `
      czm_material czm_getMaterial(czm_materialInput materialInput)
      {
          czm_material material = czm_getDefaultMaterial(materialInput);
          float strength =  1.0 - (abs(distance(materialInput.st,vec2(0.5,0.5))-0.25+uTime)*8.0);
          material.diffuse = vec3(strength,0.0,0.0);
          // step<0.5就为0,否则返回1
          // material.alpha = step(0.5,strength);
          // clamp,可以将内容限制在某个范围内
          if(strength<0.0){
            material.alpha = 0.0;//强度小于0,透明度为0
          }else{
            material.alpha = clamp(0.0,1.0,strength);//最小值,最大值,强度
          }
          
          return material;
      }
      `,
    },
  });
console.log(material.shaderSource);

3)利用gasp实现补间动画

gsap.to(material.uniforms, {
    uTime: 1,
    duration: 1,
    repeat: -1,
    ease: "linear",
    yoyo: true,//往返重复
  });

4)实例化着色器及图元实例

 const appearance = new Cesium.MaterialAppearance({
    material: material,
    // translucent: true,
    // closed: true,
  });
  
  appearance.material.uniforms.uTime = 0.0;
  // 创建图元添加
  var primitive = viewer.scene.primitives.add(
    new Cesium.Primitive({
      geometryInstances: [instance],
      appearance: appearance,
    })
  );
  console.log(appearance);
  console.log(appearance.vertexShaderSource);
  console.log(appearance.fragmentShaderSource);

5)实现效果:

6) 全部代码:

<template>
  <div id="cesiumContainer" ref="cesiumContainer"></div>
</template>

<script setup>
import { onMounted } from "vue";
import * as Cesium from "cesium";
import "./Widgets/widgets.css";
import * as dat from "dat.gui";

import gsap from "gsap";
// console.log(flightData);
const gui = new dat.GUI();

// 设置cesium的token
Cesium.Ion.defaultAccessToken =
  "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiJhMzNkNTE5Zi1mMjY4LTRiN2QtOTRlZC1lOTUyM2NhNDYzNWYiLCJpZCI6NTU0OTYsImlhdCI6MTYyNTAyNjMyOX0.a2PEM4hQGpeuMfeB9-rPp6_Gkm6O-02Dm4apNbv_Dlk";
// cesium默认资源路径
window.CESIUM_BASE_URL = "/";
// 设置默认的视角为中国
Cesium.Camera.DEFAULT_VIEW_RECTANGLE = Cesium.Rectangle.fromDegrees(
  // 西边经度
  89.5,
  // 南边维度
  0.4,
  // 东边经度
  110.4,
  // 北边维度
  81.2
);
// 实现圆的扩散
onMounted(() => {
  var viewer = new Cesium.Viewer("cesiumContainer", {
    // 天地图影像服务
    imageryProvider: new Cesium.WebMapTileServiceImageryProvider({
      url: "http://t0.tianditu.com/img_w/wmts?service=wmts&request=GetTile&version=1.0.0&LAYER=img&tileMatrixSet=w&TileMatrix={TileMatrix}&TileRow={TileRow}&TileCol={TileCol}&style=default&format=tiles&tk=30d07720fa76f07732d83c748bb84211",
      layer: "tdtBasicLayer",
      style: "default",
      format: "image/jpeg",
      tileMatrixSetID: "GoogleMapsCompatible",
    }),
  });

  viewer.scene.globe.enableLighting = true;

  // 设置沙箱允许使用JS
  var iframe = document.getElementsByClassName("cesium-infoBox-iframe")[0];
  iframe.setAttribute(
    "sandbox",
    "allow-same-origin allow-scripts allow-popups allow-forms"
  );
  iframe.setAttribute("src", "");

  // // 隐藏cesiumLogo
  viewer.cesiumWidget.creditContainer.style.display = "none";

  viewer.camera.setView({
    destination: Cesium.Cartesian3.fromDegrees(112.417, 23.29, 100000),
  });

  const extrudePolygon = new Cesium.PolygonGeometry({
    polygonHierarchy: new Cesium.PolygonHierarchy(
      Cesium.Cartesian3.fromDegreesArray([
        112.417, 23.29, 113.67, 23.56, 114.093, 22.59, 112.838, 22.285,
      ])
    ),
    // extrudedHeight: 30000,
  });

  const instance = new Cesium.GeometryInstance({
    geometry: extrudePolygon,
    id: "挤出四边形",
  });

  const material = new Cesium.Material({
    fabric: {
      // type: "Color",
      uniforms: {
        color: new Cesium.Color(1.0, 0.0, 0.0, 0.5),
        uTime: 0,
      },
      source: `
      czm_material czm_getMaterial(czm_materialInput materialInput)
      {
          czm_material material = czm_getDefaultMaterial(materialInput);
          float strength =  1.0 - (abs(distance(materialInput.st,vec2(0.5,0.5))-0.25+uTime)*8.0);
          material.diffuse = vec3(strength,0.0,0.0);
          // step<0.5就为0,否则返回1
          // material.alpha = step(0.5,strength);
          // clamp,可以将内容限制在某个范围内
          if(strength<0.0){
            material.alpha = 0.0;//强度小于0,透明度为0
          }else{
            material.alpha = clamp(0.0,1.0,strength);//最小值,最大值,强度
          }
          
          return material;
      }
      `,
    },
  });

  gsap.to(material.uniforms, {
    uTime: 1,
    duration: 1,
    repeat: -1,
    ease: "linear",
    yoyo: true,//往返重复
  });

  console.log(material.shaderSource);

  const appearance = new Cesium.MaterialAppearance({
    material: material,
    // translucent: true,
    // closed: true,
  });
  
  appearance.material.uniforms.uTime = 0.0;
  // 创建图元添加
  var primitive = viewer.scene.primitives.add(
    new Cesium.Primitive({
      geometryInstances: [instance],
      appearance: appearance,
    })
  );
  console.log(appearance);
  console.log(appearance.vertexShaderSource);
  console.log(appearance.fragmentShaderSource);

  // let fs = appearance.getFragmentShaderSource();
  // console.log(fs);
});
</script>

<style>
* {
  margin: 0;
  padding: 0;
}
#cesiumContainer {
  width: 100vw;
  height: 100vh;
}
</style>

4.着色器实现雷达图效果

实现原理:

通过设置一个矩形盒子,并在其上用着色器绘制圆形,通过对角度的不停旋及动态变换的透明度转实现雷达图效果。

实现代码:

<template>
  <div id="cesiumContainer" ref="cesiumContainer"></div>
</template>

<script setup>
import { onMounted } from "vue";
import * as Cesium from "cesium";
import "./Widgets/widgets.css";
import * as dat from "dat.gui";

import gsap from "gsap";
// console.log(flightData);
const gui = new dat.GUI();

// 设置cesium的token
Cesium.Ion.defaultAccessToken =
  "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiJhMzNkNTE5Zi1mMjY4LTRiN2QtOTRlZC1lOTUyM2NhNDYzNWYiLCJpZCI6NTU0OTYsImlhdCI6MTYyNTAyNjMyOX0.a2PEM4hQGpeuMfeB9-rPp6_Gkm6O-02Dm4apNbv_Dlk";
// cesium默认资源路径
window.CESIUM_BASE_URL = "/";
// 设置默认的视角为中国
Cesium.Camera.DEFAULT_VIEW_RECTANGLE = Cesium.Rectangle.fromDegrees(
  // 西边经度
  89.5,
  // 南边维度
  0.4,
  // 东边经度
  110.4,
  // 北边维度
  81.2
);
// 实现圆的扩散
onMounted(() => {
  var viewer = new Cesium.Viewer("cesiumContainer", {
    // 天地图影像服务
    imageryProvider: new Cesium.WebMapTileServiceImageryProvider({
      url: "http://t0.tianditu.com/img_w/wmts?service=wmts&request=GetTile&version=1.0.0&LAYER=img&tileMatrixSet=w&TileMatrix={TileMatrix}&TileRow={TileRow}&TileCol={TileCol}&style=default&format=tiles&tk=30d07720fa76f07732d83c748bb84211",
      layer: "tdtBasicLayer",
      style: "default",
      format: "image/jpeg",
      tileMatrixSetID: "GoogleMapsCompatible",
    }),
  });

  viewer.scene.globe.enableLighting = true;

  // 设置沙箱允许使用JS
  var iframe = document.getElementsByClassName("cesium-infoBox-iframe")[0];
  iframe.setAttribute(
    "sandbox",
    "allow-same-origin allow-scripts allow-popups allow-forms"
  );
  iframe.setAttribute("src", "");

  // // 隐藏cesiumLogo
  viewer.cesiumWidget.creditContainer.style.display = "none";

  viewer.camera.setView({
    destination: Cesium.Cartesian3.fromDegrees(112.417, 23.29, 100000),
  });

  const extrudePolygon = new Cesium.PolygonGeometry({
    polygonHierarchy: new Cesium.PolygonHierarchy(
      Cesium.Cartesian3.fromDegreesArray([
        112.417, 23.29, 113.67, 23.56, 114.093, 22.59, 112.838, 22.285,
      ])
    ),
    // extrudedHeight: 30000,
  });

  const instance = new Cesium.GeometryInstance({
    geometry: extrudePolygon,
    id: "挤出四边形",
  });

  const material = new Cesium.Material({
    fabric: {
      // type: "Color",
      uniforms: {
        color: new Cesium.Color(1.0, 0.0, 0.0, 0.5),
        uTime: 0,
      },
      source: `
      czm_material czm_getMaterial(czm_materialInput materialInput)
      {
          czm_material material = czm_getDefaultMaterial(materialInput);
          
          vec2 newSt = mat2(
            cos(uTime), -sin(uTime),
            sin(uTime), cos(uTime)
          )*(materialInput.st-0.5);
          newSt += 0.5;

          //设置透明度
          float alpha = 1.0 - step(0.3,distance(newSt, vec2(0.5)));
          //计算角度
          float angle = atan(newSt.x - 0.5, newSt.y - 0.5);
          //计算强度
          float strength = (angle+3.14)/6.28;

          material.alpha = alpha*strength;
          material.diffuse = mix(vec3(0.0, 0.0, 0.0), vec3(1.0,0.0,0.0), strength);//由黑到红
          
          return material;
      }
      `,
    },
  });

  gsap.to(material.uniforms, {
    uTime: -6.28,
    duration: 1,
    repeat: -1,
    ease: "linear",
    // yoyo: true,
  });

  console.log(material.shaderSource);

  const appearance = new Cesium.MaterialAppearance({
    material: material,
    // translucent: true,
    // closed: true,
  });

  appearance.material.uniforms.uTime = 0.0;
  // 创建图元添加
  var primitive = viewer.scene.primitives.add(
    new Cesium.Primitive({
      geometryInstances: [instance],
      appearance: appearance,
    })
  );
  console.log(appearance);
  console.log(appearance.vertexShaderSource);
  console.log(appearance.fragmentShaderSource);

  // let fs = appearance.getFragmentShaderSource();
  // console.log(fs);
});
</script>

<style>
* {
  margin: 0;
  padding: 0;
}
#cesiumContainer {
  width: 100vw;
  height: 100vh;
}
</style>

实现效果:

 

  • 6
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

HM-hhxx!

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值