Cesium--Primitive随相机高度缩放的实现

效果就如图所示,这样的效果在cesium中本来是有Cesium.NearFarScalar这样的方法进行实现的,但是奈何考虑的性能问题在加载众多的点要素时,我选择了使用primitive的形式进行效果展现,那在primitive中就没提供Cesium.NearFarScalar属性去实现"近大远小"或者"远小近大"的效果。

不废话了先说思路,然后直接放代码,代码里面注释不多,关键是思路对齐。

我的需求是要实现数千个或者上万个站点的告警闪烁效果(一闪一闪的),所以在前期的实现上我就用Cesium.EllipseGeometry进行几何的加载,并使用着色器加图片的形式进行告警效果。但是出现的问题就是,primitive中的EllipseGeometry无法动态调整semiMajorAxis和semiMinorAxis.......

好吧,就只能换思路,思路也简单,就是根据相机视角的高度动态调整图片的大小即可。

javascript 复制代码
 const collection = new Cesium.PrimitiveCollection({ show:true })
      collection.customName = 'HasOrder'
const axis = 1500;
const instance = new Cesium.GeometryInstance({
               id: Date.now(),
              geometry: new Cesium.EllipseGeometry({
                center: Cesium.Cartesian3.fromDegrees('经度', '纬度', 50),
                semiMajorAxis: axis,
                semiMinorAxis: axis,
                rotation: Cesium.Math.toRadians(0)
              }),
              attributes: {}
            })

const instances = []; 
instances.push(instance)

//关键在这里面
const dynamicWarnGLSL = `
  uniform sampler2D image;
  uniform float scale;

  vec4 czm_getMaterial(vec2 vUv,vec2 viewPort,vec4 fragCoord)
  {

    vec2 st = vUv;
    vec2 center = vec2(0.5, 0.5);

    // 应用缩放
    vec2 translatedSt = st - center;
    vec2 scaledSt = translatedSt / scale;
    vec2 finalSt = scaledSt + center;

    // 使用step函数检查边界,性能更好
    float inBounds = step(0.0, finalSt.x) * step(finalSt.x, 1.0) * 
                    step(0.0, finalSt.y) * step(finalSt.y, 1.0);

    vec4 img = texture(image, finalSt);
    img.a = img.a * inBounds ;
    if(img.a != 0.0){
    img.a = sin(czm_frameNumber/35.0)+0.95;
    }
    return img;
  }
        `

const vertexShaderSource = `
    in vec3 position3DHigh;
    in vec3 position3DLow;
    in vec3 normal;
    in vec2 st;
    in float batchId;
    out vec3 v_positionEC;
    out vec3 v_normalEC;
    out vec2 v_st;

    void main() {
        vec4 p = czm_computePosition();
        v_positionEC = (czm_modelViewRelativeToEye * p).xyz; 
        v_normalEC = czm_normal * normal; 
        v_st = st;

        gl_Position = czm_modelViewProjectionRelativeToEye * p;
    }
`;

const fragmentShaderSource = `
  in vec2 v_st;
  in vec3 v_positionEC;
  in vec3 v_normalEC;
  void main()  {
      vec3 positionToEyeEC = -v_positionEC;
      vec3 normalEC = normalize(v_normalEC);
      czm_materialInput materialInput;
      materialInput.normalEC = normalEC;
      materialInput.positionToEyeEC = positionToEyeEC;
      materialInput.st = v_st;
      //窗口尺寸
      vec2 viewPort = gl_FragCoord.xy / czm_viewport.zw;
      vec4 color = czm_getMaterial(v_st,viewPort,gl_FragCoord);
      out_FragColor = color;
  }
`;

 const primitive = new Cesium.Primitive({
          geometryInstances: noHasOrderList,
          appearance: new Cesium.MaterialAppearance({
            material: new Cesium.Material({
              fabric: {
                type: 'dynamicsPoint',
                uniforms: {
                  image: '图片',
                  scale:1.0
                },
                source: dynamicWarnGLSL
              }
            }),
            vertexShaderSource: vertexShaderSource,
            fragmentShaderSource: fragmentShaderSource,
            flat: true
          })
        })
collection.add(primitive)
        viewer.scene.primitives.add(collection)

//监控相机的变化
   // 监听相机变化(用于改变告警图层点位的尺寸)
    viewer.camera.changed.addEventListener(() => {
      try{
        const cameraHeight = viewer.camera.positionCartographic.height;
        let scale = 1.0;
        if (cameraHeight >= maxHeight) {
            scale = maxScale;
        } else if (cameraHeight <= minHeight) {
            scale = minScale;
        } else {
            const t = (cameraHeight - minHeight) / (maxHeight - minHeight);
            scale = minScale + t * delta;
        }
        const layerName = "HasOrder";//primitive收集器的名称
        //查找需要的primitive
        for (let i = 0; i < viewer.scene.primitives._primitives.length; i++) {
          let primitive = viewer.scene.primitives._primitives[i]
          if (primitive.hasOwnProperty('customName')) {
            if (primitive.customName.indexOf(layerName) != -1) {
              primitive._primitives[0].appearance.material.uniforms.scale = scale;
            }
          }
        }
      }catch(error){
        console.log(error);
      }
   
    });
相关推荐
Hi202402174 小时前
如何实现xtreme1与Apollo相机外参的双向转换
数码相机·标定·相机外参
sali-tec15 小时前
C# 基于halcon的视觉工作流-章66 四目匹配
开发语言·人工智能·数码相机·算法·计算机视觉·c#
gaosushexiangji1 天前
sCMOS相机Gloria 6504 工作模式与行时间详解
数码相机
fengfuyao9851 天前
光场相机成像系统与普通相机二维成像的模拟方法详解
数码相机
格林威1 天前
多相机拼接:消除重叠区域的6个核心方法,附OpenCV+Halcon实战代码!
人工智能·数码相机·opencv·计算机视觉·机器人·视觉检测·制造
合方圆~小文3 天前
双变焦摄像头实现双画面监控的原理
数据库·人工智能·数码相机·模块测试
_李小白3 天前
【Android FrameWork】延伸阅读:Camera2与V4L2CameraHAL
android·数码相机
_李小白3 天前
【Android FrameWork】延伸阅读:Camera1、Camera2 与CameraX
android·数码相机
爱凤的小光4 天前
图漾FM855-E1相机专栏
数码相机