VUE3-Cesium(Primitive详解)

目录

1.Primitive

 1.1 Members:

 1.2 Methods:

 1.3 示例:

2. 着色器材质

3.创建图元点击交互事件

4.通过着色器更改图元颜色

4.1 MaterialAppearance

4.2 片段着色器fragmentShaderSource

4.3 片段着色器示例代码: 


1.Primitive

new Cesium.Primitive ( options )

图元表示 场景 中的几何。几何可以来自单个 GeometryInstance 如下面的示例1所示,或者来自实例数组,即使几何图形来自不同几何类型,例如 RectangleGeometry 和 EllipsoidGeometry a>如代码示例2所示。

基本体将几何实例与描述完整阴影的 Appearance 组合在一起,包括 材料 和 RenderState 。大致而言,几何实例定义了结构和位置,外观定义了视觉特征。解耦的几何形状和外观使我们能够混合并匹配其中的大多数,并彼此独立地添加新的几何形状或外观。

将多个实例组合成一个原语称为批处理,可显着提高静态数据的性能。可以单独选择实例; Scene#pick 返回其 GeometryInstance#id 。使用每个实例的外观,例如 PerInstanceColorAppearance ,每个实例也可以具有唯一的颜色。

几何 可以在网络工作者或主线程上创建和批处理。前两个例子显示将通过使用几何描述在Web工作者上创建的几何。第三个例子显示了如何通过显式调用 createGeometry 方法在主线程上创建几何的方法。

NameTypeDescription
optionsObjectoptionalObject with the following properties:
NameTypeDefaultDescription
geometryInstancesArray.< GeometryInstance > | GeometryInstance可选要渲染的几何实例-或单个几何实例。
appearanceAppearance可选用于渲染图元的外观。
depthFailAppearanceAppearance可选在深度测试失败时,用于遮盖此图元的外观。
showBooleantrue 可选确定是否将显示此原语。
modelMatrixMatrix4Matrix4.IDENTITY 可选4x4转换矩阵,用于将图元(所有几何实例)从模型转换为世界坐标。
vertexCacheOptimizeBooleanfalse 可选如果为 true ,则为顶点着色器之前和之后的缓存优化几何顶点。
interleaveBooleanfalse 可选当 true 时,将交错几何图形顶点属性,这可以稍微改善渲染性能,但会增加加载时间。
compressVerticesBooleantrue 可选当 true 时,将压缩几何顶点,这将节省内存。
releaseGeometryInstancesBooleantrue 可选如果为 true ,则该原语不保留对输入的 geometryInstances 的引用以节省内存。
allowPickingBooleantrue 可选如果为 true ,则只能使用 Scene#pick 来拾取每个几何实例。如果 false ,则保存GPU内存。
cullBooleantrue 可选如果为 true ,则渲染器视锥体会根据其边界体积来剔除图元和命令。如果您手动剔除原语,请将其设置为 false 可获得较小的性能。
asynchronousBooleantrue 可选确定基元是异步创建还是阻塞直到准备就绪。
debugShowBoundingVolumeBooleanfalse 可选仅用于调试。确定是否显示该图元的命令的边界球。
shadowsShadowModeShadowMode.DISABLED 可选确定此图元是否投射或接收来自光源的阴影。

Examples:

// 1. Draw a translucent ellipse on the surface with a checkerboard pattern
var instance = new Cesium.GeometryInstance({
  geometry : new Cesium.EllipseGeometry({
      center : Cesium.Cartesian3.fromDegrees(-100.0, 20.0),
      semiMinorAxis : 500000.0,
      semiMajorAxis : 1000000.0,
      rotation : Cesium.Math.PI_OVER_FOUR,
      vertexFormat : Cesium.VertexFormat.POSITION_AND_ST
  }),
  id : 'object returned when this instance is picked and to get/set per-instance attributes'
});
scene.primitives.add(new Cesium.Primitive({
  geometryInstances : instance,
  appearance : new Cesium.EllipsoidSurfaceAppearance({
    material : Cesium.Material.fromType('Checkerboard')
  })
}));
// 2. Draw different instances each with a unique color
var rectangleInstance = new Cesium.GeometryInstance({
  geometry : new Cesium.RectangleGeometry({
    rectangle : Cesium.Rectangle.fromDegrees(-140.0, 30.0, -100.0, 40.0),
    vertexFormat : Cesium.PerInstanceColorAppearance.VERTEX_FORMAT
  }),
  id : 'rectangle',
  attributes : {
    color : new Cesium.ColorGeometryInstanceAttribute(0.0, 1.0, 1.0, 0.5)
  }
});
var ellipsoidInstance = new Cesium.GeometryInstance({
  geometry : new Cesium.EllipsoidGeometry({
    radii : new Cesium.Cartesian3(500000.0, 500000.0, 1000000.0),
    vertexFormat : Cesium.VertexFormat.POSITION_AND_NORMAL
  }),
  modelMatrix : Cesium.Matrix4.multiplyByTranslation(Cesium.Transforms.eastNorthUpToFixedFrame(
    Cesium.Cartesian3.fromDegrees(-95.59777, 40.03883)), new Cesium.Cartesian3(0.0, 0.0, 500000.0), new Cesium.Matrix4()),
  id : 'ellipsoid',
  attributes : {
    color : Cesium.ColorGeometryInstanceAttribute.fromColor(Cesium.Color.AQUA)
  }
});
scene.primitives.add(new Cesium.Primitive({
  geometryInstances : [rectangleInstance, ellipsoidInstance],
  appearance : new Cesium.PerInstanceColorAppearance()
}));
// 3. Create the geometry on the main thread.
scene.primitives.add(new Cesium.Primitive({
  geometryInstances : new Cesium.GeometryInstance({
      geometry : Cesium.EllipsoidGeometry.createGeometry(new Cesium.EllipsoidGeometry({
        radii : new Cesium.Cartesian3(500000.0, 500000.0, 1000000.0),
        vertexFormat : Cesium.VertexFormat.POSITION_AND_NORMAL
      })),
      modelMatrix : Cesium.Matrix4.multiplyByTranslation(Cesium.Transforms.eastNorthUpToFixedFrame(
        Cesium.Cartesian3.fromDegrees(-95.59777, 40.03883)), new Cesium.Cartesian3(0.0, 0.0, 500000.0), new Cesium.Matrix4()),
      id : 'ellipsoid',
      attributes : {
        color : Cesium.ColorGeometryInstanceAttribute.fromColor(Cesium.Color.AQUA)
      }
  }),
  appearance : new Cesium.PerInstanceColorAppearance()
}));

See:

1.1  Members:

 1.2 Methods:

​ 

 1.3 示例:

通过两种方式添加模型:

1)通过entity方式添加:

// entity方式添加
  var entity = viewer.entities.add({
    //创建矩形
    rectangle: {
      coordinates: Cesium.Rectangle.fromDegrees(
        // 西边经度
        89.5,
        // 南边维度
        30,
        // 东边经度
        110.4,
        // 北边维度
        40
      ),
      material: Cesium.Color.RED.withAlpha(0.5),
    },
  });

2)通过primitive方式添加:

// primivite创建矩形
  // 01-创建几何体
  let rectGeometry = new Cesium.RectangleGeometry({
    rectangle: Cesium.Rectangle.fromDegrees(
      // 西边的经度
      115,
      // 南边维度
      20,
      // 东边经度
      135,
      // 北边维度
      30
    ),
    // 距离表面高度
    height: 0,
    vertexFormat: Cesium.PerInstanceColorAppearance.VERTEX_FORMAT,
  });

  // 02-创建几何体实例
  let instance = new Cesium.GeometryInstance({
    geometry: rectGeometry,
    attributes: {
      color: Cesium.ColorGeometryInstanceAttribute.fromColor(
        Cesium.Color.RED.withAlpha(0.5)
      ),
    },
  });

  // 03-设置外观
  let appearance = new Cesium.PerInstanceColorAppearance({
    flat: true,
  });
  // 04-图元
  let primitive = new Cesium.Primitive({
    geometryInstances: instance,
    appearance: appearance,
  });
  // 05-添加到viewer
  viewer.scene.primitives.add(primitive);

  viewer.camera.setView(viewer.entities);

实现效果:

上面盒子为entity方式创建,下面为primitive方式创建

 3)使用primitive添加多个盒子

// primitive方式添加
  var instance = new Cesium.GeometryInstance({
    //创建矩形几何体
    geometry: new Cesium.RectangleGeometry({
      rectangle: Cesium.Rectangle.fromDegrees(
        // 西边经度
        89.5,
        // 南边维度
        10,
        // 东边经度
        110.4,
        // 北边维度
        20
      ),
      height: 1000,//高度
      // vertexFormat: Cesium.EllipsoidSurfaceAppearance.VERTEX_FORMAT,//椭球体表面顶点格式化(默认)
    }),
    // attributes: {
    //   color: Cesium.ColorGeometryInstanceAttribute.fromColor(Cesium.Color.RED),
    // },
  });

  const instance2 = new Cesium.GeometryInstance({
    //创建圆几何体
    geometry: new Cesium.CircleGeometry({
      center: Cesium.Cartesian3.fromDegrees(110.4, 40, 0),
      radius: 1000000,//半径
      // vertexFormat: Cesium.PerInstanceColorAppearance.VERTEX_FORMAT,
    }),
  });
  var primitiveRect = new Cesium.Primitive({
    geometryInstances: [instance, instance2],
    appearance: new Cesium.EllipsoidSurfaceAppearance({
      material: Cesium.Material.fromType("Color", {
        color: Cesium.Color.RED.withAlpha(0.5),
      }),
    }),
  });
  viewer.scene.primitives.add(primitiveRect);

实现效果:

上方矩形为entity方式创建,下方矩形和圆形为primitive方式创建: 

2. 着色器材质

在上面对primitiveRect进行实例化时,可以通过appearance对多个图元的材质进行设置,例如设置为红色,0.5透明度:

 var primitiveRect = new Cesium.Primitive({
    geometryInstances: [instance, instance2],
    appearance: new Cesium.EllipsoidSurfaceAppearance({//设置同意材质颜色
      material: Cesium.Material.fromType("Color", {
        color: Cesium.Color.RED.withAlpha(0.5),
      }),
    }),
  });

在对实例进行创建时,也可以通过attributes单独进行设置图元的材质,例如:

// primitive
  var instance = new Cesium.GeometryInstance({
    geometry: new Cesium.RectangleGeometry({
      rectangle: Cesium.Rectangle.fromDegrees(
        // 西边经度
        89.5,
        // 南边维度
        10,
        // 东边经度
        110.4,
        // 北边维度
        20
      ),
      height: 1000,
      // vertexFormat: Cesium.EllipsoidSurfaceAppearance.VERTEX_FORMAT,
      vertexFormat: Cesium.PerInstanceColorAppearance.VERTEX_FORMAT,//设置顶点格式化
    }),
    attributes: {
      color: Cesium.ColorGeometryInstanceAttribute.fromColor(
        Cesium.Color.SKYBLUE
      ),
    },
  });
 const instance2 = new Cesium.GeometryInstance({
    geometry: new Cesium.CircleGeometry({
      center: Cesium.Cartesian3.fromDegrees(110.4, 40, 0),
      radius: 1000000,
      vertexFormat: Cesium.PerInstanceColorAppearance.VERTEX_FORMAT,
    }),
    attributes: {
      color: new Cesium.ColorGeometryInstanceAttribute(1, 1, 0, 0.5),
    },
    id: "circle",
  });

在进行实例化时,使用PerInstanceColorAppearance()设置单独的图元材质:

var primitive = new Cesium.Primitive({
    geometryInstances: [instance, instance2],
    appearance: new Cesium.PerInstanceColorAppearance(),//设置使用自己设置的材质颜色
  });

实现效果:

3.创建图元点击交互事件

通过实例化用户输入事件,自定义鼠标左键点击事件,实现对圆图元材质的更改:

// 创建一个交互事件
  var handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);
  handler.setInputAction(function (movement) {
    var pickedObject = viewer.scene.pick(movement.position);
    console.log(pickedObject);
    console.log(Cesium.defined(pickedObject));
    if (Cesium.defined(pickedObject)) {
      console.log(pickedObject);
      var attributes =
        pickedObject.primitive.getGeometryInstanceAttributes("circle");//获取几何体属性
      attributes.color = Cesium.ColorGeometryInstanceAttribute.toValue(
        Cesium.Color.GREEN.withAlpha(0.5)
      );
    }
  }, Cesium.ScreenSpaceEventType.LEFT_CLICK);

点击前:

 点击后:

4.通过着色器更改图元颜色

4.1 MaterialAppearance

new Cesium.MaterialAppearance ( options )

Example:

var primitive = new Cesium.Primitive({
  geometryInstances : new Cesium.GeometryInstance({
    geometry : new Cesium.WallGeometry({
            materialSupport :  Cesium.MaterialAppearance.MaterialSupport.BASIC.vertexFormat,
      // ...
    })
  }),
  appearance : new Cesium.MaterialAppearance({
    material : Cesium.Material.fromType('Color'),
    faceForward : true
  })

});

 4.2 片段着色器fragmentShaderSource

fragmentShaderSource : String

片段着色器的GLSL源代码。完整片段着色器源代码是根据程序 MaterialAppearance#material 而构建的, MaterialAppearance#flat 和 MaterialAppearance#faceForward 。使用 MaterialAppearance#getFragmentShaderSource 获取完整的源代码。

material : Material

Scene/MaterialAppearance.js 69

用于确定片段颜色的材料。与其他 MaterialAppearance 不同属性,它不是只读的,因此外观的材质可以随时更改。

Default Value:  Material.ColorType

See:

4.3 片段着色器示例代码: 

<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";
// 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", {});

  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),//红色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);//material中的source内容

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

  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);
     material.diffuse = vec3(v_st,0.81);//渐变色
     // material.emission = vec3(0.5,0.5,0.5);//发光
     // material.specular = 1.0;
     material.specular = 1.0;//高光(为1.0时有镜面反射效果)
     material.alpha = 1.0;//透明度

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

  // 创建图元添加
  var primitive = viewer.scene.primitives.add(
    new Cesium.Primitive({
      geometryInstances: [instance],
      appearance: 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>

实现效果:

 

 

  • 2
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

HM-hhxx!

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

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

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

打赏作者

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

抵扣说明:

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

余额充值