在Cesium中渲染圆锥体时,无论采用顶点着色器、Canvas动态贴图还是静态图片贴图,其渐变色均需满足以下条件:
特点:通过GLSL代码直接计算圆心到边缘的距离,实现纯圆形渐变。
// 创建圆锥几何体(底面为圆形)
const coneGeometry = Cesium.CylinderGeometry.createGeometry(
new Cesium.CylinderGeometry({
length: 200000,
topRadius: 0,
bottomRadius: 100000, // 底面半径
vertexFormat: Cesium.PerInstanceColorAppearance.VERTEX_FORMAT,
})
);
// 自定义着色器:基于UV距离计算圆形渐变
const material = new Cesium.Material({
fabric: {
type: 'RadialGradientCone',
source: `
czm_material czm_getMaterial(czm_materialInput materialInput) {
czm_material material = czm_getDefaultMaterial(materialInput);
// 计算当前像素到圆心的距离(UV坐标系中)
vec2 st = materialInput.st;
vec2 center = vec2(0.5, 0.5); // 圆心位置
float distance = length(st - center); // 径向距离
// 归一化到 [0,1],确保渐变从中心向外扩展
float normalizedDistance = clamp(distance / 0.5, 0.0, 1.0);
// 圆形渐变逻辑(红→黄→蓝)
if (normalizedDistance < 0.33) {
material.diffuse = vec3(1.0, 0.0, 0.0); // 红色
} else if (normalizedDistance < 0.66) {
material.diffuse = vec3(1.0, 1.0, 0.0); // 黄色
} else {
material.diffuse = vec3(0.0, 0.0, 1.0); // 蓝色
}
// 透明度随距离增加而降低
material.alpha = 1.0 - normalizedDistance * 0.5;
return material;
}
`,
uniforms: {},
},
});
// 应用到Primitive
const geometryInstance = new Cesium.GeometryInstance({ geometry: coneGeometry });
const primitive = new Cesium.Primitive({
geometryInstances: geometryInstance,
appearance: new Cesium.MaterialAppearance({
material: material,
closed: true,
}),
});
viewer.scene.primitives.add(primitive);
关键点:
length(st - center)
:确保渐变方向从圆心向外。clamp(distance / 0.5, 0.0, 1.0)
:限制渐变范围在圆形区域内。特点:通过Canvas绘制径向渐变圆形纹理,贴合圆锥底面。
// 1. 创建Canvas并绘制圆形径向渐变
const canvas = document.createElement('canvas');
canvas.width = 256;
canvas.height = 256;
const ctx = canvas.getContext('2d');
// 定义径向渐变(圆心→边缘)
const gradient = ctx.createRadialGradient(128, 128, 0, 128, 128, 128);
gradient.addColorStop(0, 'red');
gradient.addColorStop(0.5, 'yellow');
gradient.addColorStop(1, 'blue');
ctx.fillStyle = gradient;
ctx.fillRect(0, 0, 256, 256);
// 2. 将Canvas转换为ImageResource
const imageResource = new Cesium.ImageResource({
source: canvas,
});
// 3. 创建贴图材质(圆形渐变)
const imageMaterial = new Cesium.Material({
fabric: {
type: 'ImageRadialGradient',
source: `
czm_material czm_getMaterial(czm_materialInput materialInput) {
czm_material material = czm_getDefaultMaterial(materialInput);
vec2 st = materialInput.st;
vec4 color = texture(imageMap, st);
material.diffuse = color.rgb;
material.alpha = color.a;
return material;
}
`,
uniforms: {
imageMap: imageResource,
},
},
});
// 应用到Primitive
const geometryInstance = new Cesium.GeometryInstance({ geometry: coneGeometry });
const primitive = new Cesium.Primitive({
geometryInstances: geometryInstance,
appearance: new Cesium.MaterialAppearance({
material: imageMaterial,
closed: true,
}),
});
viewer.scene.primitives.add(primitive);
关键点:
createRadialGradient
:Canvas API原生支持径向渐变。特点:预加载圆形渐变图片,适合固定渐变逻辑。
// 1. 准备静态圆形渐变图片(如 gradient.png)
const imageMaterial = new Cesium.Material({
fabric: {
type: 'StaticRadialGradient',
source: `
czm_material czm_getMaterial(czm_materialInput materialInput) {
czm_material material = czm_getDefaultMaterial(materialInput);
vec2 st = materialInput.st;
vec4 color = texture(staticMap, st);
material.diffuse = color.rgb;
material.alpha = color.a;
return material;
}
`,
uniforms: {
staticMap: 'path/to/gradient.png', // 需预先绘制圆形渐变
},
},
});
// 应用到Primitive
const geometryInstance = new Cesium.GeometryInstance({ geometry: coneGeometry });
const primitive = new Cesium.Primitive({
geometryInstances: geometryInstance,
appearance: new Cesium.MaterialAppearance({
material: imageMaterial,
closed: true,
}),
});
viewer.scene.primitives.add(primitive);
关键点:
方案 | 渐变类型 | 实时性 | 灵活性 | 性能 | 适用场景 |
---|---|---|---|---|---|
顶点着色器 | ✅ 圆形径向 | ✅ 高 | ✅ 高 | ✅ 高 | 动态属性驱动、实时变化 |
Canvas动态贴图 | ✅ 圆形径向 | ⚠ 中 | ✅ 高 | ⚠ 中 | 复杂渐变、交互式调整 |
静态图片贴图 | ✅ 圆形径向 | ❌ 低 | ❌ 低 | ✅ 高 | 固定渐变、大规模渲染 |
三种方案均通过圆形结构+径向扩散实现渐变色,区别在于:
最终选择建议: