✨ Cesium高级特效与着色器开发全指南(API详解+实战示例)
Cesium的核心是基于WebGL的三维渲染引擎,其高级特效开发本质是自定义GLSL着色器 与Cesium渲染流水线的深度融合。Cesium提供了多层级的着色器扩展API:从简单的自定义材质 到直接操作WebGL的Primitive/Appearance,再到全局后处理特效,覆盖从单个实体到整个场景的所有特效需求。以下从API详解、场景适配、代码示例三个维度全面讲解。
📌 基础铺垫:Cesium GLSL扩展与内置变量
Cesium对WebGL的GLSL语言进行了扩展,提供了大量内置uniform变量、函数和宏,是着色器开发的基础:
| 内置变量/函数 |
类型 |
作用 |
czm_time |
float |
从Cesium初始化到当前的时间(秒),用于动态动画 |
czm_frameNumber |
float |
当前渲染帧号,用于帧同步动画 |
czm_modelViewProjectionMatrix |
mat4 |
模型视图投影矩阵,将顶点坐标转换为裁剪坐标 |
czm_modelMatrix |
mat4 |
模型矩阵,将局部坐标转换为世界坐标 |
czm_normalMatrix |
mat3 |
法向量矩阵,用于法向量的世界坐标转换 |
czm_saturation |
float |
饱和度控制(后处理常用) |
czm_hue |
float |
色相控制(后处理常用) |
czm_brightness |
float |
亮度控制(后处理常用) |
czm_pixelRatio |
float |
设备像素比,用于适配高DPI屏幕 |
czm_viewport |
vec4 |
视口信息(x,y,width,height) |
一、自定义材质(Material):实体/Primitive特效开发
1. 核心API详解
Cesium.Material
| 方法/属性 |
定义 |
用途 |
场景 |
fromType(type, options) |
static Material fromType(String type, Object options) |
从Cesium内置材质类型创建材质,支持自定义uniform参数 |
实体颜色动画、纹理滚动、闪烁特效 |
setUniform(name, value) |
void setUniform(String name, Any value) |
更新材质的uniform变量值 |
动态调整特效参数(如闪烁频率、纹理速度) |
ShaderSource |
Object ShaderSource(材质的着色器源码配置) |
定义材质的顶点/片元着色器、uniform变量、属性 |
完全自定义材质逻辑(如水流效果、渐变填充) |
Cesium.MaterialProperty
| 方法/属性 |
定义 |
用途 |
场景 |
CallbackProperty |
new Cesium.CallbackProperty(callback, isConstant) |
动态生成材质属性,每一帧更新uniform变量 |
随时间变化的特效(如无人机航线轨迹、洪水淹没动画) |
ColorMaterialProperty |
new Cesium.ColorMaterialProperty(color) |
颜色材质,支持动态颜色 |
实体高亮、闪烁颜色切换 |
2. 代码示例:动态闪烁材质
场景:低空无人机航线高亮闪烁
javascript
复制代码
// 1. 定义闪烁材质的ShaderSource
const blinkMaterialSource = {
// 自定义uniform变量
uniforms: {
// 闪烁频率(默认2Hz)
frequency: 2.0,
// 基础颜色
baseColor: Cesium.Color.RED,
// 高亮颜色
highlightColor: Cesium.Color.YELLOW
},
// 片元着色器
fragmentShader: `
uniform float frequency;
uniform vec4 baseColor;
uniform vec4 highlightColor;
void main() {
// 基于时间生成闪烁因子(0-1)
float blinkFactor = abs(sin(czm_time * frequency));
// 混合基础颜色与高亮颜色
vec4 finalColor = mix(baseColor, highlightColor, blinkFactor);
gl_FragColor = finalColor;
}
`
};
// 2. 注册自定义材质类型
Cesium.Material._materialCache.addMaterial('BlinkMaterial', {
fabric: {
type: 'BlinkMaterial',
uniforms: blinkMaterialSource.uniforms,
source: blinkMaterialSource.fragmentShader
}
});
// 3. 创建闪烁的无人机航线
const viewer = new Cesium.Viewer('cesiumContainer');
viewer.entities.add({
polyline: {
positions: Cesium.Cartesian3.fromDegreesArray([
116.4, 39.9, 116.5, 39.9, 116.6, 39.9
]),
width: 5.0,
// 使用自定义材质
material: Cesium.Material.fromType('BlinkMaterial', {
frequency: 3.0, // 调整闪烁频率为3Hz
baseColor: Cesium.Color.RED.withAlpha(0.5),
highlightColor: Cesium.Color.YELLOW.withAlpha(1.0)
})
}
});
// 4. 动态更新材质参数(可选)
setInterval(() => {
const material = viewer.entities.values[0].polyline.material.getValue(Cesium.JulianDate.now());
material.setUniform('frequency', Math.random() * 3 + 1); // 随机切换频率
}, 2000);
3. 注意事项
- 自定义材质需通过
Cesium.Material._materialCache.addMaterial注册类型,避免重复创建
- 动态更新uniform时,需通过
material.getValue(Cesium.JulianDate.now())获取当前材质实例
- 复杂材质推荐使用
fabric格式(Cesium官方推荐),支持继承内置材质(如ColorMaterial)
二、Primitive/Appearance:直接操作WebGL的高级渲染
1. 核心API详解
Cesium.Primitive
| 方法/属性 |
定义 |
用途 |
场景 |
new Cesium.Primitive(options) |
Primitive new Primitive(Object options) |
直接创建WebGL渲染的Primitive,完全控制顶点数据、着色器和渲染状态 |
自定义三维模型、大规模点云、地形叠加特效 |
geometryInstances |
Array<GeometryInstance> |
几何实例数组,支持批量渲染多个几何对象 |
批量渲染无人机、POI点等重复实体 |
appearance |
Appearance |
外观配置,控制着色器、渲染状态 |
自定义顶点动画、法向量光照、纹理映射 |
Cesium.Appearance
| 子类名称 |
用途 |
场景 |
PerInstanceColorAppearance |
每个实例独立颜色,无需自定义着色器 |
批量渲染不同颜色的实体(如无人机编队) |
MaterialAppearance |
结合Material使用,支持材质特效 |
带纹理/动画的三维模型 |
CustomAppearance |
完全自定义顶点/片元着色器,直接操作WebGL |
高级特效(如顶点变形、自定义光照) |
2. 代码示例:自定义顶点动画Primitive
场景:低空无人机编队的上下浮动动画
javascript
复制代码
// 1. 创建自定义Appearance
const floatAppearance = new Cesium.CustomAppearance({
// 顶点着色器:给每个顶点添加时间驱动的Y轴偏移
vertexShaderSource: `
attribute vec3 position3DHigh;
attribute vec3 position3DLow;
attribute vec4 color;
uniform float timeOffset;
varying vec4 v_color;
void main() {
// Cesium内置的高精度顶点位置计算
vec3 position = czm_highPrecisionEllipsoidCartographicToCartesian(
position3DHigh, position3DLow
);
// 基于时间的Y轴偏移(模拟上下浮动)
position.y += sin(czm_time + timeOffset) * 10.0;
// 转换为裁剪坐标
gl_Position = czm_modelViewProjectionMatrix * vec4(position, 1.0);
v_color = color;
}
`,
// 片元着色器:传递颜色
fragmentShaderSource: `
varying vec4 v_color;
void main() {
gl_FragColor = v_color;
}
`,
// 自定义uniform变量
uniforms: {
timeOffset: 0.0
},
// 渲染状态
renderState: {
depthTest: { enabled: true },
blending: Cesium.BlendingState.ALPHA_BLEND
}
});
// 2. 创建无人机编队的GeometryInstances
const instances = [];
for (let i = 0; i < 10; i++) {
instances.push(new Cesium.GeometryInstance({
geometry: new Cesium.BoxGeometry({
vertexFormat: floatAppearance.vertexFormat,
dimensions: new Cesium.Cartesian3(2, 2, 2)
}),
modelMatrix: Cesium.Matrix4.multiplyByTranslation(
Cesium.Transforms.eastNorthUpToFixedFrame(
Cesium.Cartesian3.fromDegrees(116.4 + i*0.01, 39.9, 100)
),
new Cesium.Cartesian3(0, 0, 0),
new Cesium.Matrix4()
),
attributes: {
color: Cesium.ColorGeometryInstanceAttribute.fromColor(
Cesium.Color.fromRandom({ alpha: 1.0 })
)
},
// 自定义实例属性(传递给uniform)
id: { timeOffset: i * Math.PI / 5 } // 每个实例的时间偏移不同,实现错落动画
}));
}
// 3. 创建Primitive并添加到场景
const primitive = new Cesium.Primitive({
geometryInstances: instances,
appearance: floatAppearance,
asynchronous: false // 同步加载,立即渲染
});
viewer.scene.primitives.add(primitive);
// 4. 每一帧更新uniform变量
viewer.scene.postRender.addEventListener(() => {
instances.forEach((instance, index) => {
floatAppearance.uniforms.timeOffset = instance.id.timeOffset;
});
});
3. 注意事项
CustomAppearance需严格遵循Cesium的顶点格式(如position3DHigh/position3DLow用于高精度坐标)
- 批量渲染优先使用
GeometryInstance,减少WebGL绘制调用
- 动态更新uniform时,需在
postRender事件中执行,确保每一帧生效
三、PostProcessStage:全局场景后处理特效
1. 核心API详解
Cesium.PostProcessStage
| 方法/属性 |
定义 |
用途 |
场景 |
new Cesium.PostProcessStage(options) |
PostProcessStage new PostProcessStage(Object options) |
创建单步后处理特效,对整个场景的帧缓冲进行处理 |
bloom、模糊、颜色校正、边缘检测 |
uniforms |
Object |
自定义uniform变量,用于传递特效参数(如强度、阈值) |
动态调整后处理效果(如 bloom 强度、色相偏移) |
enabled |
Boolean |
启用/禁用后处理特效 |
按需开启特效(如仅在低空飞行时启用 bloom) |
Cesium.PostProcessStageComposite
| 方法/属性 |
定义 |
用途 |
场景 |
new Cesium.PostProcessStageComposite(options) |
PostProcessStageComposite new PostProcessStageComposite(Object options) |
组合多个后处理特效,按顺序执行 |
复杂后处理流水线(如 bloom + 颜色校正 + vignette) |
2. 代码示例:Bloom发光特效(无人机航迹高亮)
场景:低空无人机航迹的全局发光效果
javascript
复制代码
// 1. 定义Bloom后处理着色器
const bloomStage = new Cesium.PostProcessStage({
name: 'bloom',
fragmentShader: `
uniform sampler2D colorTexture;
uniform vec2 resolution;
uniform float bloomStrength;
uniform float bloomThreshold;
vec4 bloomPass(sampler2D tex, vec2 uv, float strength, float threshold) {
vec4 color = texture2D(tex, uv);
// 提取高亮区域(超过阈值的像素)
float brightness = dot(color.rgb, vec3(0.2126, 0.7152, 0.0722));
if (brightness > threshold) {
// 高斯模糊简化版(3x3卷积)
vec4 blur = vec4(0.0);
for (int i = -1; i <= 1; i++) {
for (int j = -1; j <= 1; j++) {
blur += texture2D(tex, uv + vec2(i, j)/resolution) * 0.111;
}
}
return mix(color, blur, strength);
}
return color;
}
void main() {
gl_FragColor = bloomPass(colorTexture, gl_FragCoord.xy/resolution, bloomStrength, bloomThreshold);
}
`,
// 自定义uniform变量
uniforms: {
bloomStrength: 1.5,
bloomThreshold: 0.8,
resolution: new Cesium.Cartesian2(window.innerWidth, window.innerHeight)
},
// 输入纹理为场景的颜色缓冲
inputTexture: 'colorTexture'
});
// 2. 添加到场景后处理流水线
viewer.scene.postProcessStages.add(bloomStage);
// 3. 动态调整特效参数
viewer.scene.postRender.addEventListener(() => {
bloomStage.uniforms.resolution = new Cesium.Cartesian2(window.innerWidth, window.innerHeight);
});
// 4. 绑定UI控件调整参数(可选)
document.getElementById('strength-slider').addEventListener('input', (e) => {
bloomStage.uniforms.bloomStrength = parseFloat(e.target.value);
});
3. 注意事项
- 后处理着色器的输入纹理默认是
colorTexture(场景颜色缓冲),也可指定depthTexture(深度缓冲)
- 复杂后处理推荐使用
PostProcessStageComposite组合多个步骤,避免单着色器过于复杂
- 移动端需禁用复杂后处理(如 bloom),减少GPU计算压力
四、CustomShader:Cesium 1.100+ 新特性(材质扩展利器)
1. 核心API详解
Cesium.CustomShader
| 方法/属性 |
定义 |
用途 |
场景 |
new Cesium.CustomShader(options) |
CustomShader new CustomShader(Object options) |
扩展Cesium内置材质的着色器,无需完全重写材质 |
模型变形、自定义光照、纹理动画叠加内置材质 |
vertexShaderText |
String |
顶点着色器扩展代码,可注入到内置材质的顶点着色器中 |
顶点动画、模型变形 |
fragmentShaderText |
String |
片元着色器扩展代码,可注入到内置材质的片元着色器中 |
颜色调整、纹理混合、自定义光照 |
uniforms |
Object |
自定义uniform变量,与内置材质的uniform共享 |
动态调整扩展参数 |
2. 代码示例:模型波浪变形特效
场景:低空无人机模型的波浪变形动画
javascript
复制代码
// 1. 创建CustomShader扩展内置材质
const customShader = new Cesium.CustomShader({
// 顶点着色器:给模型顶点添加波浪变形
vertexShaderText: `
uniform float waveAmplitude;
uniform float waveFrequency;
void vertexMain(VertexInput vsInput, inout vec3 positionMC) {
// positionMC是模型局部坐标,基于时间生成波浪偏移
positionMC.y += sin(vsInput.positionMC.x * waveFrequency + czm_time) * waveAmplitude;
positionMC.z += cos(vsInput.positionMC.x * waveFrequency + czm_time) * waveAmplitude;
}
`,
// 片元着色器:叠加颜色调整
fragmentShaderText: `
uniform float saturation;
void fragmentMain(FragmentInput fsInput, inout vec4 diffuseColor) {
// 调整饱和度
float gray = dot(diffuseColor.rgb, vec3(0.2126, 0.7152, 0.0722));
diffuseColor.rgb = mix(vec3(gray), diffuseColor.rgb, saturation);
}
`,
// 自定义uniform变量
uniforms: {
waveAmplitude: 0.5,
waveFrequency: 10.0,
saturation: 1.0
}
});
// 2. 加载无人机模型并应用CustomShader
const model = viewer.scene.primitives.add(Cesium.Model.fromGltf({
url: './drone.gltf',
modelMatrix: Cesium.Transforms.eastNorthUpToFixedFrame(
Cesium.Cartesian3.fromDegrees(116.4, 39.9, 100)
),
scale: 1.0,
// 应用CustomShader扩展材质
customShader: customShader
}));
// 3. 动态更新参数
setInterval(() => {
customShader.uniforms.waveAmplitude = Math.random() * 0.5 + 0.2;
customShader.uniforms.saturation = Math.random() * 1.5 + 0.5;
}, 1000);
3. 注意事项
CustomShader需Cesium 1.100+版本支持,是未来Cesium材质扩展的标准方式
- 顶点着色器扩展需使用
vertexMain函数,片元着色器需使用fragmentMain函数
- 可通过
vsInput/fsInput访问内置顶点/片元属性(如positionMC、normalMC)
🚀 性能优化与最佳实践
1. 着色器性能优化
- 避免在片元着色器中使用复杂循环(如高斯模糊),优先使用后处理的多步渲染
- 复用内置uniform和函数(如
czm_time、czm_modelViewProjectionMatrix),减少自定义变量
- 移动端关闭
depthTest和blending等非必要渲染状态
2. 内存管理
- 动态更新Primitive时,优先使用
primitive.update而非重新创建Primitive
- 后处理特效不用时及时从
postProcessStages中移除,释放纹理内存
- 大规模实体优先使用
EntityCollection或Primitive的geometryInstances,减少WebGL资源占用
3. 场景适配
- 低空经济场景:优先使用
CustomShader实现无人机/航线特效,减少材质创建开销
- 地形叠加特效:使用
GroundPrimitive结合自定义材质,避免地形遮挡
- 全局特效:使用
PostProcessStage实现 bloom、模糊等,提升场景氛围感
通过以上API的深度掌握,你可以实现从单个实体到整个场景的所有高级特效,完全满足Cesium在低空经济、智慧城市等领域的深度开发需求!