Cesium实现渐变面

一、效果图

二、实现思路 

        使用着色器,通过纹理坐标和其他参数计算出材质的颜色和透明度。通过给定的颜色、漫反射强度和透明度,计算出最终的反射颜色和透明度,并且根据给定的中心点位置和当前像素的纹理坐标,计算出距离中心的距离用来做透明度的参考值,然后计算得到的颜色加载到对应的材质上。

三、完整代码

<template>
  <div>
    <button @click="handlePolygon()">渐变面</button>
    <CesiumViewer />
  </div>
</template>
<script setup>
import { ref, onMounted } from "vue";
import CesiumViewer from "./components/cesiumViewer.vue";

let viewer;
onMounted(() => {
  viewer = window.cesiumViewer;
});

const updateResolutionScale = (viewer) => {
  //判断是否支持图像渲染像素化处理
  if (Cesium.FeatureDetection.supportsImageRenderingPixelated()) {
    viewer.resolutionScale = window.devicePixelRatio;
  }
};

const PolyGradientMaterial = `uniform vec4 color;
uniform float diffusePower;
uniform float alphaPower;
uniform float globalAlpha;
uniform vec2 center;

czm_material czm_getMaterial(czm_materialInput materialInput) {
  czm_material material = czm_getDefaultMaterial(materialInput);

  float time = czm_frameNumber/600.;
  float per = fract(time);

  vec2 st = materialInput.st;
  float alpha = distance(st, center);

  material.alpha = color.a * alpha * alphaPower * globalAlpha;
  material.diffuse = color.rgb * diffusePower;
  return material;
}`;

let index = 0;
const arrColor = [
  "rgb(18,76,154)",
  "rgb(15,176,255)",
   "#40C4E4",
   "#42B2BE",
   "rgb(51,176,204)",
    "#8CB7E5",
   "rgb(0,244,188)",
  "#139FF0",
];

const getColor = () => {
  return arrColor[++index % arrColor.length];
};

let totalLabel = 0;

const addPolygon = (positions, color, name) => {
  const polygonOptions = {
    extrudedHeight: 1000,
    polygonHierarchy: new Cesium.PolygonHierarchy(positions),
  };

  const geometry = new Cesium.PolygonGeometry(polygonOptions);

  const geometryInstance = new Cesium.GeometryInstance({
    geometry: geometry,
    id: "chinaocean",
  });

  const material = new Cesium.Material({
    fabric: {
      source: PolyGradientMaterial,
      uniforms: {
        color: Cesium.Color.fromCssColorString(color),
        diffusePower: 1.8,
        alphaPower: 1.2,
        center: new Cesium["Cartesian2"](0.5, 0.5),
        globalAlpha: 0x1,
      },
    },
    translucent: true,
  });

  const primitive = new Cesium.Primitive({
    releaseGeometryInstances: false,
    asynchronous: false,
    geometryInstances: [geometryInstance],
    appearance: new Cesium.EllipsoidSurfaceAppearance({
      material: material,
    }),
  });

  // const removeListener = viewer.scene.postRender.addEventListener(() => {
  //   if (!primitive.ready) {
  //     return;
  //   }

  //   totalLabel += 1;
  //   const position = primitive._boundingSpheres[0].center;
  //   viewer.entities.add({
  //     position,
  //     label: {
  //       text: name,
  //       font: "32px 楷体",
  //       fillColor: Cesium.Color.WHITE,
  //       outlineColor: Cesium.Color.BLACK,
  //       style: Cesium.LabelStyle.FILL_AND_OUTLINE,
  //       outlineWidth: 2,
  //       disableDepthTestDistance: 1000000000,
  //       scale: 0.5,
  //       pixelOffset: new Cesium.Cartesian2(0, -10),
  //       backgroundColor: new Cesium.Color.fromCssColorString(
  //         "rgba(0, 0, 0, 0.7)"
  //       ),
  //       backgroundPadding: new Cesium.Cartesian2(10, 10),
  //       verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
  //     },
  //   });
  //   removeListener();
  // });

  viewer.scene.primitives.add(primitive);
};

const handlePolygon = () => {
  updateResolutionScale(viewer);
  viewer.scene.skyBox.show = false;
  var mapOptions = {
    scene: {
      center: {
        lat: 30.037072,
        lng:   91.091762,
        alt: 1600000.0,
        heading: 160000.0,
        // 视角
        heading: 355,
        pitch: -88,
      },
    },
  };
  viewer.camera.flyTo({
    orientation: {
      heading: Cesium.Math.toRadians(mapOptions.scene.center.heading),
      pitch: Cesium.Math.toRadians(mapOptions.scene.center.pitch),
    },
    destination: Cesium.Cartesian3.fromDegrees(
      mapOptions.scene.center.lng,
      mapOptions.scene.center.lat,
      mapOptions.scene.center.alt
    ),
    duration: 0,
  });

  Cesium.GeoJsonDataSource.load(
    "https://geo.datav.aliyun.com/areas_v3/bound/540100.json"
  ).then((dataSource) => {
    const entities = dataSource.entities.values;
    // 遍历所有实体
    entities.forEach((entity, index) => {
      if (entity.polygon) {
        const positions = entity.polygon.hierarchy._value.positions;
        addPolygon(positions, getColor(index), entity.name);
      }
    });
  });
};
</script>
<style scoped></style>

*注:<CesiumViewer/>

  • 8
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值