深色模式
纹理不只是图片
纹理(texture)可以存地图照片,也可以是一块 GPU 可采样的数值数组。气象格点、粒子位置、上一帧计算结果都能放进去。关键问题不在于“能否传一个 Float32Array”,而在于每个纹理元素(texel)的含义是否明确。texel 是数据的存储格,屏幕像素(pixel)是输出画面的格,两者不必一一对应。
数组索引与纹理位置之间差半格,是常见错误。采样与插值从节点、单元和权重解释这段映射。
先约定布局,再写 shader
设合成温度网格宽 W=4、高 H=3,经度变化最快,索引(index)就是 j*W+i。i 是从零开始的列号,j 是行号,W/H 是列数/行数,四者都是无单位整数。第一行是北边还是南边必须写清楚:CPU 数组的顺序、纹理上传的翻转设置和 shader 的纬度映射需要一致。出现“南北翻了”的图,通常是约定冲突,不是投影算法坏了。
归一化纹理坐标(normalized texture coordinates)把整张纹理的宽、高各记作 1,没有米或角度单位。第 (i,j) 个 texel 的中心为:
text
u = (i + 0.5) / W
v = (j + 0.5) / H格点坐标与纹理边界不是一回事。若网格节点包含南北两极,纬度首先映射到节点索引 j,再转换为 texel 中心;直接把纬度线性映射到 [0,1],容易引入半个 texel 的偏移。全球经度周期网格是否重复保存 360° 一列,也会改变映射公式。
科学数值需要自己的格式
照片常用 8 位颜色;温度和矢量常用浮点纹理,避免过早量化(quantization,把连续或高精度数值映射到有限等级)。可以让 RG 存 U/V,B 存辅助量,A 存有效性;也可以使用单通道格式节省带宽。颜色编码和数据编码应分开,不能先把温度变成红蓝图,再从颜色反推原值。
缺测值尤其危险。假设三个节点为 10,第四个为 -1e10 哨兵值(sentinel,用特殊数表示缺测),普通线性过滤会把巨大负值混入正常区域。应明确选择“只要有无效邻居就拒绝”“有效邻居重归一化”或预处理填补,三种策略含义不同。先验证有效性,再做色带映射。
能上传,不等于能计算输出
浮点纹理采样、线性过滤、浮点颜色附件是不同能力。实际组合要检查 WebGL 版本与扩展,不能凭成功创建纹理就认为它一定能作为 framebuffer 输出。Cesium 1.145 的 Texture、Sampler 属于内部渲染接口,教程中的高级适配器需要固定版本;公开 Material 的存在不会把这些底层对象变成稳定 API。
本页标量实验选择易于查看的 RGBA8 教学编码:R/G 保存两个时刻的归一化值,B 保存有效性,温度按 T=10+20*s 解码。量化步长约为 0.078°C;需要更高精度的科学输入时,应选择合适的浮点或其他数值编码。
一个场,多种颜色
在同一组合成场上切换采样、时间和颜色映射。
在浏览器本地运行 · 无需账号 · 鼠标拖动旋转,滚轮缩放
教学合成数据,不代表真实观测或天气预报。规则场用于验证,拟真形态用于观察复杂结构。 数据说明
查看运行源码
此代码直接读取实际运行的实验模块。按 kind 分支定位当前实验,也可查看数据公式和 GLSL。
读取源码…观察任务
观察标量实验的色带与地理位置。若整个场向东错半格,应先修改色带,还是检查 texel 中心?对于 360 列、每列 1° 的不重复周期网格,最后一列之后应接哪里?
展开答案
先检查索引与采样坐标。色带只改变值到颜色的关系,不能修正地理偏移。周期网格最后一列之后接第一列;重复端点网格需要另一套索引处理,不能混用。区域网格则通常禁止跨边界重复。
阅读依据:Cesium 1.145 Texture 源码(internal)、Khronos EXT_color_buffer_float。