用途
CesiumJS CustomShader 用于向 Model、Cesium3DTileset、VoxelPrimitive 的渲染管线注入用户编写的 GLSL 代码。它把 glTF 属性、feature ID 以及 EXT_structural_metadata 暴露给逐顶点和逐片元代码,并通过内置的 czm_modelVertexOutput 和 czm_modelMaterial 结构体返回结果。本技能专注于编写 shader 主体。
相关但不在本技能范围内:Fabric Material、ImageBasedLighting、PostProcessStage(见 cesiumjs-materials-shaders);通过 Cesium3DTileStyle 声明式逐要素着色及 VoxelPrimitive 配置(见 cesiumjs-3d-tiles);Model.fromGltfAsync、动画、ModelFeature.getProperty()(见 cesiumjs-models-particles)。在 glTF 中编写 EXT_structural_metadata / EXT_mesh_features 属于工具链问题,不是运行时范畴。
版本基线:CesiumJS 1.144,所有导入使用 ES module 风格。
主要能力
- 着色器函数签名:
void vertexMain(VertexInput vsInput, inout czm_modelVertexOutput vsOutput)与void fragmentMain(FragmentInput fsInput, inout czm_modelMaterial material)。参数名是契约的一部分,重命名会破坏着色器。 - Uniforms:通过
{ type, value }声明,type 取 UniformType,JS 值类型必须匹配(如 VEC3 → Cartesian3)。支持 TextureUniform(url 或 typedArray + width + height,二者只能其一),仅支持 SAMPLER_2D,SAMPLER_CUBE 会在构造时抛错。运行时可调用shader.setUniform()更新。 - Varyings:声明后自动生成 vertex 的 out 与 fragment 的 in。支持 FLOAT、VEC2–VEC4、MAT2–MAT4,无 INT/BOOL/SAMPLER 变体。
- 模式与光照:CustomShaderMode 有 MODIFY_MATERIAL(默认,在材质阶段后、光照前运行)与 REPLACE_MATERIAL(完全跳过材质阶段)。LightingModel 有 UNLIT(跳过光照,flat-shaded)与 PBR(物理基础渲染,可用时带 IBL);省略则保留模型默认光照。
- 半透明:CustomShaderTranslucencyMode 控制 alpha 写入如何处理——INHERIT(默认,仅当源材质半透明时 alpha 才生效)、OPAQUE、TRANSLUCENT。在不透明模型上用 INHERIT 写 material.alpha 会被静默忽略。
- 属性:vsInput.attributes / fsInput.attributes 暴露 glTF 顶点属性,名称区分大小写,必须带坐标空间后缀(如 positionMC、positionWC、positionEC、normalMC、normalEC、tangent/bitangent、texCoord_N、color_N、joints_N、weights_N)。构造函数会扫描着色器文本并抛出 DeveloperError。自定义下划线前缀属性(如 _SURFACE_TEMP)会被小写化并去掉前缀。
- FeatureIds:统一三种 glTF 来源:featureId_N(含 EXT_mesh_features 的属性与隐式属性,也覆盖 feature ID 纹理,仅片元)、instanceFeatureId_N(来自 EXT_instance_features + EXT_mesh_gpu_instancing)、命名别名。旧版 3D Tiles 1.0 的 BATCH_ID / _BATCHID 会透明重命名为 featureId_0。GLSL 类型始终为 int。
- Metadata(EXT_structural_metadata):属性属性(逐顶点,顶点与片元)、属性纹理(逐纹素,仅片元)、属性表(逐要素,按 feature ID 索引,1.139 加入)。同时提供 metadataClass.<prop>.noData/defaultValue/minValue/maxValue 与 metadataStatistics.<prop> 的统计字段(需 tileset.json 声明 statistics)。属性 ID 会按 GLSL 标识符规则做净化,净化后碰撞为未定义行为。
使用方式
最小示例(Model):
import { CustomShader, Model } from "cesium";
const shader = new CustomShader({
fragmentShaderText: `
void fragmentMain(FragmentInput fsInput, inout czm_modelMaterial material) {
material.diffuse = vec3(1.0, 0.0, 0.0);
}
`,
});
const model = await Model.fromGltfAsync({ url: "./aircraft.glb", customShader: shader });
viewer.scene.primitives.add(model);
应用方式:Model 可构造函数选项或可变属性(支持热替换与置空);Cesium3DTileset 同样支持构造选项与可变属性,但只影响 Model 支撑的瓦片内容;VoxelPrimitive 为仅片元子集。引擎每帧自动调用 customShader.update(frameState),使用完后调用 customShader.destroy() 释放 GPU 纹理资源。
构造函数参数:mode、lightingModel、translucencyMode、uniforms、varyings、vertexShaderText、fragmentShaderText。通常至少需要 vertexShaderText 或 fragmentShaderText 之一。
可视化评估建议:添加带着色器的 Model 后,等待模型达到可渲染状态,然后显式框定已知目标点,不要依赖加载后的第一帧或极小的默认缩放。公开模型评估可设置 minimumPixelSize(通常 256–400)、使用适度缩放,并在判断着色器效果时添加轮廓或强烈色彩。
示例文件:01-diffuse-tint.js(时间 uniform 驱动 diffuse)、02-texture-swap.js、03-feature-id-tileset.js、04-translucent-override.js、05-vertex-displacement.js、06-metadata-ramp.js、07-voxel-shader.js。
适用场景
- 为 glTF 模型编写自定义逐顶点/逐片元着色。
- 在 3D Tiles 上按 feature ID 做分类着色。
- 读取并可视化 EXT_structural_metadata(属性属性/纹理/表)。
- 体素(VoxelPrimitive)的逐体素元数据着色与光线步进逻辑。
- 顶点位移与程序化平面着色(REPLACE_MATERIAL + UNLIT)。
限制与注意事项
- 坐标空间后缀必需;在错误阶段使用(如顶点中的 positionEC、片元中的 normalMC)或使用裸 position/normal/tangent/bitangent 会抛出 DeveloperError。
- 修改 czm_modelVertexOutput.positionMC 会位移顶点,但不会更新图元的包围球,大幅位移可能被视锥剔除。
- SAMPLER_CUBE 在构造时被拒绝,仅支持 SAMPLER_2D。
- Cesium3DTileset.customShader 标记为 @experimental,使用 3D Tiles 规范中尚未最终确定的表面,可能不遵循标准弃用策略。其 JSDoc 指出与 Cesium3DTileStyle 搭配可能导致未定义行为,不要在同一瓦片集上组合使用。
- VoxelPrimitive 仅片元,提供 vertexShaderText 会被静默忽略;其 fsInput.attributes 仅有 positionEC 与 normalEC,无 featureIds、metadataClass,metadataStatistics 仅有 minValue 与 maxValue。将 customShader 置为 undefined 会回退到 VoxelPrimitive.DefaultCustomShader。
- 1.139 破坏性变更:unsigned 整数元数据不再转有符号 int,把 UINT 属性赋给 GLSL int 将无法编译,需使用匹配的无符号类型。
- 1.130 破坏性变更:fsInput.voxel.positionUv/positionShapeUv/positionLocal 已移除,改用 fsInput.attributes.positionEC;fsInput.voxel.surfaceNormal → fsInput.attributes.normalEC。
- 1.142 修复后,内置默认体素着色器能更稳健地处理常见元数据类型,仅在需要显式分类、着色、过滤或光线步进逻辑时保留自定义着色器。
- 带 EXT_structural_metadata 的公开 .glb 资产较少,多数真实元数据位于 3D Tiles 上。
- 其余版本说明(1.139–1.142):#13170 修复点云属性精度;#13124 增加属性表元数据访问;#13135 增加属性纹理支持的元数据类型;#13231 元数据变量正则扩展到 metadataClass 与 metadataStatistics;#13247 NGA-GPM 本地扩展与自定义着色器回归修复;#13258 当元数据存在于类定义时,不再对缺失元数据的图元禁用自定义着色器;#13323 通过降精度提供有限的双精度元数据支持。
完整枚举值与内置 czm_* 自动 uniform(如 czm_frameNumber、czm_pi、czm_model、czm_view、czm_projection、czm_modelView、czm_normal、czm_lightDirectionEC、czm_sunDirectionWC、czm_eyeHeight、czm_sceneMode、czm_viewerPositionWC、czm_splitPosition)见 REFERENCE.md。