Cesium圆锥渐变色实现:融合顶点着色器、Canvas动态贴图与静态纹理的多方案整合

在Cesium中渲染圆锥体时,无论采用顶点着色器Canvas动态贴图 还是静态图片贴图,其渐变色均需满足以下条件:

  1. 圆形结构:渐变范围限定在圆锥底面的圆形区域内。
  2. 径向扩散:颜色从圆心向外逐步变化(如红→黄→蓝)。
  3. 一致性:三种方案均基于"圆形中心→边缘"的渐变逻辑。

方案一:顶点着色器动态计算(实时性最高)

特点 :通过GLSL代码直接计算圆心到边缘的距离,实现纯圆形渐变

javascript 复制代码
// 创建圆锥几何体(底面为圆形)
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动态生成径向渐变贴图(灵活性高)

特点 :通过Canvas绘制径向渐变圆形纹理,贴合圆锥底面。

javascript 复制代码
// 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原生支持径向渐变。
  • 贴图适配:需确保圆锥底面UV映射为正方形区域(避免拉伸)。
  • 灵活性:可动态调整Canvas渐变参数(如颜色分段)。

方案三:静态图片贴图(性能最优)

特点:预加载圆形渐变图片,适合固定渐变逻辑。

javascript 复制代码
// 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);

关键点

  • 图片设计:需手动绘制或生成圆形径向渐变(如Photoshop或程序生成)。
  • 性能优势:无需运行时计算,适合大规模渲染。

三种方案对比与选择建议
方案 渐变类型 实时性 灵活性 性能 适用场景
顶点着色器 ✅ 圆形径向 ✅ 高 ✅ 高 ✅ 高 动态属性驱动、实时变化
Canvas动态贴图 ✅ 圆形径向 ⚠ 中 ✅ 高 ⚠ 中 复杂渐变、交互式调整
静态图片贴图 ✅ 圆形径向 ❌ 低 ❌ 低 ✅ 高 固定渐变、大规模渲染

总结

三种方案均通过圆形结构+径向扩散实现渐变色,区别在于:

  • 顶点着色器:实时计算,适合动态数据。
  • Canvas贴图:灵活定制,适合复杂渐变。
  • 静态贴图:性能最佳,适合固定逻辑。

最终选择建议

  • 需要实时响应属性变化 → 使用顶点着色器。
  • 需要复杂渐变设计 → 使用Canvas动态生成贴图。
  • 需要极致性能 → 使用静态图片贴图。
相关推荐
郑寿昌16 小时前
UE5与UE6在Lumen和Nanite的差异解析
游戏引擎·图形渲染·着色器
魔士于安1 天前
Unity完整小球迷宫项目
前端·unity·游戏引擎·贴图·模型
threelab1 天前
Three.js 动态旋转同心圆着色器 | 三维可视化效果
开发语言·javascript·着色器
魔士于安2 天前
Unity 超市总动员 超市收银台 超市货架 超市购物手推车 超市常见商品
游戏·unity·游戏引擎·贴图·模型
♡すぎ♡2 天前
ShaderLab:海面——顶点变换,程序化生成无需贴图
计算机图形学·opengl·着色器
魔士于安3 天前
Unity windows 同步 异步 打开文件文件夹工具
游戏·unity·游戏引擎·贴图·模型
魔士于安3 天前
unity lowpoly 风格 城市 建筑 道路 交通标志
游戏·unity·游戏引擎·贴图·模型
魔士于安4 天前
Unity UI图片 复活节UI,卡通风格
游戏·ui·unity·游戏引擎·材质·贴图
魔士于安4 天前
unity 卡通风整套资源 小鸟N套带动作+一套卡通风村落 和 相关道具+落叶粒子效果 buildin
游戏·unity·游戏引擎·贴图·模型
CG_MAGIC4 天前
幕后花絮:用Blender打造自己的建筑
3d·blender·贴图·uv·建模教程·渲云渲染