primitive和entity高阶使用方法(包括shader)

1 加载entity以及使用shader着色器方法

添加entity模型:(下面18个是cesium封装好的模型可以直接调用的)

  1. billboard
  2. box
  3. corridor
  4. cylinder
  5. ellipse
  6. ellipsoid
  7. label
  8. model
  9. tileset
  10. path
  11. plane
  12. point
  13. polygon
  14. polyline
  15. properties
  16. polylineVolume
  17. rectangle
  18. wall

层级结构是:

entityCollection

entity

graphics(上面18均有各自的graphics)

上面十八个是entityCollection可以添加的实体类型,每种不同类型对应的不同的形状和属性,通过viewer.entities.add添加,每个实体中都有一个属性

material, 下面就material详解:

以 ellipse举例:

常用的有

  1. ColorMaterialProperty
  2. ImageMaterialProperty
  3. StripeMaterialProperty
  4. PolylineDashMaterialProperty
  5. ...

 const entity = viewer.entities.add({
        position: Cesium.Cartesian3.fromDegrees(-112.87709, 36.27782),
        ellipse: {
            semiMajorAxis: 10000,
            semiMinorAxis: 10000,
            material: new Cesium.ColorMaterialProperty(Cesium.Color.RED.withAlpha(0.5))
        }
    });

ImageMaterialProperty :

 const entity2 = viewer.entities.add({
        position: Cesium.Cartesian3.fromDegrees(-112.87709, 36.27782),
        ellipse: {
            semiMajorAxis: 10000,
            semiMinorAxis: 10000,
            material: new Cesium.ImageMaterialProperty({
                image: '/Mask_group.png',
                transparent: true,
            }),
        }
    });

CustomMaterialProperty(自定义材质 important!!!)

tip:特别要注意的是很多案例都是封装好一个类但是用到自己的代码中就报错了,主要问题出在

Cesium自定义材质兼容性问题,例如:Cesium.xxxxMaterialProperty = xxxxMaterialProperty,就是把自定义的材质绑定在了cesium对象上,但是新版本不支持这种写法了(应该是1.90之后),正确的做法是把封装好的类直接使用es的方法导出 然后new一个新的对象出来使用

import * as Cesium from "cesium";
//创建一个自定义MaterialProperty
class CustomMaterialProperty {
  constructor() {
    this.definitionChanged = new Cesium.Event(); //
    Cesium.Material._materialCache.addMaterial("colorCustomMaterial", {
      fabric: {
        type: "CustomMaterial",
        uniforms: {
          rgbColor:  new Cesium.Color(0.3, 0.6, 0.9),
        },
        source: `
          uniform vec4 rgbColor;

          czm_material czm_getMaterial(czm_materialInput materialInput)
          {
            czm_material material = czm_getDefaultMaterial(materialInput);
            material.diffuse = rgbColor.rgb;
            material.specular = 0.5;
            material.shininess = 1.5;
            material.alpha = 1.0;
            return material;
          }
          
          `,
      },
      translucent: true,
    });
  }

  getType() {
    return "colorCustomMaterial";
  }
  getValue(time, result) {
    return result;
  }
}
export default CustomMaterialProperty;
const entity = viewer.entities.add({
  position: Cesium.Cartesian3.fromDegrees(116.39, 39.9),
  ellipse: {
    semiMajorAxis: 100000,
    semiMinorAxis: 100000,
    material: new MyCustomMaterialProperty({
      rgbColor: Cesium.Color.RED // 可传递自定义参数
    })
  }
});

2 加载primitive以及使用shader着色器方法

primitive结构

Primitive
  └── PrimitiveCollection
        ├── BillboardCollection    // 管理 Billboard
        ├── LabelCollection        // 管理 Label
        ├── PointPrimitiveCollection // 管理 PointPrimitive
        └── PolylineCollection     // 管理 Polyline

2.1添加简单图元(通过专用集合类管理)

PrimitiveCollection (场景根容器)
├─ PointPrimitiveCollection (点集合)
│  └─ PointPrimitive (单个点)
│
├─ BillboardCollection (广告牌集合)
│  └─ Billboard (单个广告牌)
│
└─ LabelCollection (标签集合)
   └─ Label (单个标签)

2.1.1示例代码

// 创建广告牌集合
const billboards = viewer.scene.primitives.add(new Cesium.BillboardCollection());

// 添加单个广告牌
const billboard = billboards.add({
  position: Cesium.Cartesian3.fromDegrees(116.39, 39.9), // 北京坐标
  image: 'pin.png', // 图标路径
  width: 32,
  height: 32
});

2.2基础几何体(通过 GeometryInstance 包装)

PrimitiveCollection
└─ Primitive (单个几何体容器)
   ├─ GeometryInstance (几何实例)
   │  ├─ PolygonGeometry (多边形几何体)
   │  │  └─ PolygonHierarchy (多边形顶点层级)
   │  │
   │  ├─ PolylineGeometry (普通折线)
   │  ├─ GroundPolylineGeometry (贴地折线)
   │  ├─ BoxGeometry (立方体)
   │  └─ EllipsoidGeometry (球体)
   │
   └─ Appearance (外观)
      ├─ MaterialAppearance (材质外观)
      └─ PerInstanceColorAppearance (按实例颜色外观)

2.2.1

// 定义多边形顶点(上海区域)
const positions = Cesium.Cartesian3.fromDegreesArray([
  121.1, 31.0,
  121.6, 31.0,
  121.6, 31.4,
  121.1, 31.4
]);

// 创建几何实例
const polygonInstance = new Cesium.GeometryInstance({
  geometry: new Cesium.PolygonGeometry({
    polygonHierarchy: new Cesium.PolygonHierarchy(positions),
    height: 1000 // 高度(单位:米)
  }),
  attributes: {
    color: Cesium.ColorGeometryInstanceAttribute.fromColor(
      Cesium.Color.BLUE.withAlpha(0.5)
    )
  }
});

// 创建 Primitive 并添加到场景
const primitive = viewer.scene.primitives.add(new Cesium.Primitive({
  geometryInstances: [polygonInstance],
  appearance: new Cesium.PerInstanceColorAppearance() // 按实例颜色渲染
}));

2.3 贴地图元(与地形交互)

PrimitiveCollection
└─ GroundPrimitive (贴地图元容器)
   └─ GeometryInstance
      └─ PolygonGeometry / PolylineGeometry (必须设置 height: 0)

2.3.1示例代码

// 定义折线路径(纽约到伦敦)
const positions = Cesium.Cartesian3.fromDegreesArray([
  -74.0, 40.7, // 纽约
  0.1, 51.5    // 伦敦
]);

// 创建贴地折线
const groundPolyline = viewer.scene.primitives.add(new Cesium.GroundPrimitive({
  geometryInstances: new Cesium.GeometryInstance({
    geometry: new Cesium.GroundPolylineGeometry({
      positions: positions,
      width: 5.0 // 线宽(单位:米)
    })
  }),
  appearance: new Cesium.PolylineMaterialAppearance({
    material: Cesium.Material.fromType('Color', {
      color: Cesium.Color.RED
    })
  })
}));

2.4复杂对象(直接通过 PrimitiveCollection 添加)

PrimitiveCollection
├─ Model (3D模型)
│  └─ glTF/GLB 模型文件
│
├─ PointCloud (点云)
│  └─ .pnts 点云文件
│
└─ ParticleSystem (粒子系统)
   └─ Particle (粒子)

2.4.1示例代码

// 加载东京塔模型
const position = Cesium.Cartesian3.fromDegrees(139.75, 35.66, 100); // 东京坐标

const model = viewer.scene.primitives.add(Cesium.Model.fromGltf({
  url: 'tokyo_tower.gltf',
  modelMatrix: Cesium.Transforms.eastNorthUpToFixedFrame(position),
  scale: 10.0 // 缩放比例
}));

// 可选:模型加载完成回调
model.readyPromise.then(() => {
  model.color = Cesium.Color.fromAlpha(Cesium.Color.WHITE, 0.8); // 设置透明度
});

2.5 如何通过primitive写shader important!

2.5.1先添加一个材质类(custom Material)

这是我写的一个渐变色的材质demo

import * as Cesium from 'cesium'

let startTime = performance.now()

/**
 * 更新材质时间
 * @param {Cesium.Material} material - 材质对象
 */
const updateMaterialTime = (material) => {
  if (!material) return
  const currentTime = (performance.now() - startTime) / 1000.0
  material.uniforms.time = currentTime
}

/**
 * 创建随时间变化的Primitive材质
 * @param {Cesium.Color} color - 基础颜色
 * @returns {Cesium.MaterialAppearance} 材质外观
 */
const createTimeBasedAppearance = (color = new Cesium.Color(1.0, 0.0, 0.0, 1.0)) => {
  const material = new Cesium.Material({
    fabric: {
      type: 'TimeBased',
      uniforms: {
        color: color,
        time: 0
      },
      source: `
        uniform vec4 color;
        uniform float time;

        czm_material czm_getMaterial(czm_materialInput materialInput) {
          czm_material material = czm_getDefaultMaterial(materialInput);
          vec2 st = materialInput.st;
          
          // 定义目标颜色(这里使用互补色作为示例)
          vec3 targetColor = vec3(1.0 - color.r, 1.0 - color.g, 1.0 - color.b);
          
          // 使用正弦函数创建平滑的过渡效果
          float transition = sin(time * 0.5) * 0.5 + 0.5;
          
          // 在基础颜色和目标颜色之间进行插值
          vec3 finalColor = mix(color.rgb, targetColor, transition);
          
          // 添加轻微的波浪效果增加视觉趣味
          float wave = sin(st.s * 10.0 + time * 6.28) * 0.5 + 0.5;
          finalColor *= (0.9 + wave * 0.1);
          
          material.diffuse = finalColor;
          material.alpha = color.a;

          return material;
        }
      `
    }
  })
  
  const appearance = new Cesium.MaterialAppearance({
    material: material,
    faceForward: true,
    flat: false
  })

  // 添加材质更新函数
  appearance.updateMaterial = () => {
    updateMaterialTime(material)
  }
  
  return appearance
}

export {
  createTimeBasedAppearance
} 

然后就可以开始调用我们写的这个类呢(我这里是用的vue)

// 添加使用自定义材质的图元
const addPrimitive = () => {
  if (!viewer.value || primitiveAdded.value) return
  
  // 创建一个球体几何体
  const sphereGeometry = new Cesium.EllipsoidGeometry({
    radii: new Cesium.Cartesian3(50000.0, 50000.0, 50000.0),
    vertexFormat: Cesium.VertexFormat.POSITION_NORMAL_AND_ST
  })
  
  // 创建几何体实例
  const sphereInstance = new Cesium.GeometryInstance({
    geometry: sphereGeometry,
    modelMatrix: Cesium.Matrix4.multiplyByTranslation(
      Cesium.Transforms.eastNorthUpToFixedFrame(primitivePosition),
      new Cesium.Cartesian3(0, 0, 0),
      new Cesium.Matrix4()
    ),
    id: 'custom-primitive'
  })
  
  // 创建材质外观 (可以传入对应的颜色)
  primitiveAppearance.value = createTimeBasedAppearance(primitiveColor.value)
  
  // 创建图元
  primitive.value = viewer.value.scene.primitives.add(
    new Cesium.Primitive({
      geometryInstances: sphereInstance,
      appearance: primitiveAppearance.value,
      asynchronous: false
    })
  )
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值