Skip to content

材质、Appearance 与 Shader ​

几何定义“有哪些表面”,外观决定“怎样画这些表面”。Cesium 的 Material 组织材质计算;Appearance 连接几何属性、着色程序与渲染状态;shader 是 GPU 执行的程序。它们相互配合,却不能任意替换。实体的材质属性、Primitive 的 Appearance 和模型的 CustomShader 属于不同入口。

示例中的 mix 就是加权平均。可先用采样与插值里的小数字算一遍,再观察颜色过渡。

顶点属性插值后进入片元材质计算的过程

先让输入与消费者匹配 ​

顶点属性(attribute)随顶点变化,例如位置、法线和纹理坐标(texture coordinates)。纹理坐标通常写成 (s,t) 或 (u,v),是纹理中的无量纲位置,不自动具有经纬度含义。uniform 是一次绘制中共享的参数,例如时间、色带范围和纹理。顶点阶段的输出会经过光栅化插值,成为片元阶段的输入。一个片元(fragment)是待处理的屏幕样本,还要经过深度、混合等步骤才影响最终像素。

下面使用 Cesium 的 Fabric 材质接口,让纹理坐标控制两种颜色之间的过渡。几何需要提供 st 属性,Appearance 也必须支持该材质输入。

以下对象构造片段假设已执行 import * as Cesium from 'cesium';显示对象还需要前后文说明的场景装配步骤。

js
const material = new Cesium.Material({
  fabric: {
    type: 'LessonGradient',
    uniforms: {
      lowColor: new Cesium.Color(0.05, 0.57, 0.53, 1),
      highColor: new Cesium.Color(0.85, 0.47, 0.03, 1),
    },
    source: `
      czm_material czm_getMaterial(czm_materialInput input) {
        czm_material m = czm_getDefaultMaterial(input);
        m.diffuse = mix(lowColor.rgb, highColor.rgb, input.st.s);
        m.alpha = 1.0;
        return m;
      }
    `,
  },
});

mix(a,b,w) 表示线性插值(linear interpolation):(1−w)*a+w*b,对 RGB 三个颜色分量分别计算。w=0 取 a,w=1 取 b,w=0.5 取两者平均;w 没有单位。这段程序只计算材质,不是完整的独立 WebGL shader。Cesium 会把它组合进适当的着色流程。input.st.s 通常表示二维纹理坐标的第一分量;它不是经度,也不是气象 U 分量,除非应用明确建立了对应关系。

颜色变化不一定需要重建几何 ​

如果温度网格位置不变,只有数值变化,可以保持网格并更新纹理或 uniform。把每次时间切换都写成创建整套几何,会浪费 CPU 与上传资源。反过来,若 ZG 真正改变表面高度,仅改变颜色就没有表达几何变化。ZG 常用来标记位势高度,但真实含义与单位仍以数据元信息为准。

还要区分材质 alpha 与渲染状态。输出透明颜色不保证对象采用了正确的混合、深度写入和排序路径。重叠透明表面需要同时考虑这些状态,不能只把 alpha 调小。

对象如何被画出EXPERIMENT 05 · CESIUM 1.145.0

对象如何被画出

比较 Entity 与 Primitive,查看几何与材质的边界。

在浏览器本地运行 · 无需账号 · 鼠标拖动旋转,滚轮缩放

底图:Natural Earth II(公共领域);其余几何和地形为教学合成。 数据说明
查看运行源码

此代码直接读取实际运行的实验模块。按 kind 分支定位当前实验,也可查看数据公式和 GLSL。

读取源码…

观察任务: 将“透明度”从 1 调到 0.3,旋转相机观察盒子的交叠。再设想只把颜色排列倒过来:哪些数据可以复用?若同时改变每个网格点的高度,答案又有什么变化?

展开解释

色带变化通常可以复用位置和索引,更新颜色映射即可。高度变化会影响几何表达及可能的包围范围,必须让位置计算得到更新。先分清“值变了”和“位置变了”,才能设计合适的更新链路。

官方延伸:Material 与 Fabric、MaterialAppearance。

气象学 · 数学基础 · 地理可视化