深色模式
材质、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 调小。
对象如何被画出
比较 Entity 与 Primitive,查看几何与材质的边界。
在浏览器本地运行 · 无需账号 · 鼠标拖动旋转,滚轮缩放
底图:Natural Earth II(公共领域);其余几何和地形为教学合成。 数据说明
查看运行源码
此代码直接读取实际运行的实验模块。按 kind 分支定位当前实验,也可查看数据公式和 GLSL。
读取源码…观察任务: 将“透明度”从 1 调到 0.3,旋转相机观察盒子的交叠。再设想只把颜色排列倒过来:哪些数据可以复用?若同时改变每个网格点的高度,答案又有什么变化?
展开解释
色带变化通常可以复用位置和索引,更新颜色映射即可。高度变化会影响几何表达及可能的包围范围,必须让位置计算得到更新。先分清“值变了”和“位置变了”,才能设计合适的更新链路。