VUE3-Cesium(Primitive详解)

  • Post author:
  • Post category:vue



目录


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

方法在主线程上创建几何的方法。

Name Type Description

options
Object optionalObject with the following properties:

Name Type Default Description

geometryInstances
Array.<

GeometryInstance

> |

GeometryInstance
可选要渲染的几何实例-或单个几何实例。

appearance

Appearance
可选用于渲染图元的外观。

depthFailAppearance

Appearance
可选在深度测试失败时,用于遮盖此图元的外观。

show
Boolean
true
可选确定是否将显示此原语。

modelMatrix

Matrix4

Matrix4.IDENTITY
可选4×4转换矩阵,用于将图元(所有几何实例)从模型转换为世界坐标。

vertexCacheOptimize
Boolean
false
可选如果为

true

,则为顶点着色器之前和之后的缓存优化几何顶点。

interleave
Boolean
false
可选当

true

时,将交错几何图形顶点属性,这可以稍微改善渲染性能,但会增加加载时间。

compressVertices
Boolean
true
可选当

true

时,将压缩几何顶点,这将节省内存。

releaseGeometryInstances
Boolean
true
可选如果为

true

,则该原语不保留对输入的

geometryInstances

的引用以节省内存。

allowPicking
Boolean
true
可选如果为

true

,则只能使用

Scene#pick

来拾取每个几何实例。如果

false

,则保存GPU内存。

cull
Boolean
true
可选如果为

true

,则渲染器视锥体会根据其边界体积来剔除图元和命令。如果您手动剔除原语,请将其设置为

false

可获得较小的性能。

asynchronous
Boolean
true
可选确定基元是异步创建还是阻塞直到准备就绪。

debugShowBoundingVolume
Boolean
false
可选仅用于调试。确定是否显示该图元的命令的边界球。

shadows

ShadowMode

ShadowMode.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>

实现效果:




版权声明:本文为damadashen原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。