
Cesium 的地球渲染在 Web 端已经演进了很多年从 WebGL 1.0 到 WebGL 2.0基本都在老渲染管线的框架内做优化。真正让“数字地球”重新有讨论空间的是 WebGPU 带来的底层变化计算着色器、存储缓冲、显式资源绑定、更高效的遮挡剔除。这次我们来看 WebGPU 版 Cesium 方向的 Atmosphere 模块重点拆“基础大气和光照”这一部分。Atmosphere 这个名字直译是“大气层”放到数字地球场景里它要做的事情非常明确让地球边缘出现真实的大气散射光晕让太阳光照在球面和地形上看起来像真实日光而不是一张硬贴图。相比传统 Cesium 里自带的 Atmosphere 效果WebGPU 版本可以更直接地把瑞利散射、米氏散射、预计算 LUT、天空照度和地表光照合成到一起性能控制也更有把握。这篇文章会围绕三件事展开第一Atmosphere 模块要解决什么问题和 WebGPU 数字地球整体架构的关系是什么第二当你自己搭建 WebGPU 版 Cesium 或类似数字地球原型时基础大气和光照应该怎么分模块设计和验证第三部署运行、功能测试、性能观察、常见排错怎么做。这属于偏图形渲染工程的内容需要一点 WGSL 和渲染管线基础但不是必须读完论文才能上手。1. Atmosphere 核心能力速览先把“基础大气和光照”模块的能力边界列出来。下面的表格不是某个具体发行版的功能清单而是从 WebGPU 数字地球工程实践角度整理的模块参考能力具体实现以你选择的源码仓库或实验分支为准。能力项说明模块类型数字地球场景中的大气散射与光照渲染模块渲染 APIWebGPUWGSL Shader依赖navigator.gpu与 Canvas 的 WebGPU 上下文基础效果地球边缘大气散射、天空背景、太阳方向光照、地表光照统一散射模型瑞利散射 Rayleigh 米氏散射 Mie可组合出高空蓝紫色散射和低空灰白色光晕核心优化方向屏幕空间 Ray Marching或预计算散射 LUT 后做采样合成减少逐像素重复计算联动关系可与 Cesium 的相机系统、地形高程、影像瓦片、太阳位置联动硬件前提需要支持 WebGPU 的浏览器和 GPU 后端通常要求显卡驱动支持 D3D12 / Vulkan / Metal显存占用无输入材料提供具体数值需按实际场景分辨率、纹理 LUT 大小与后端 GPU 实测观察是否支持 CPUWebGPU 本身面向 GPU 计算通用 CPU 回退通常不现实需要按目标浏览器能力确认启动方式需要构建工具启动本地开发服务无法像普通静态页面直接双击打开是否提供 API模块内部表现为 Shader Module、Pipeline、Uniform Binding工程侧再看是否封装为 TS 类是否支持批量任务不是图像生成类工具不存在批量任务大量场景对象更新需自行管理 Render Pass适用场景WebGIS 可视化平台、数字孪生大屏、三维地球展示、Cesium 二次开发与渲染实验一句话总结这个模块的价值Cesium 负责把地球的几何、瓦片和相机管好Atmosphere 负责把“这层光”渲染对让场景看起来像真实拍摄的大气环境而不是 CAD 风格的线框球。2. 适用场景与使用边界WebGPU 版 Cesium 的 Atmosphere 不是给普通业务后台用的组件它的适用场景集中在需要高质量数字地球表现的前端项目。第一类是 WebGIS 展示平台。比较典型的是城市级数字孪生、智慧园区、自然资源三维场景。这类项目已经有 Cesium 地形、影像、倾斜摄影或模型数据但默认光照表现比较平加了基础大气和光照模块后太阳方向、昼夜变化、视角远近的光感会更统一。第二类是三维地球可视化大屏。多用于态势展示、仿真信息呈现、宏观数据叠加。这里的大气效果更多是氛围感不需要严格物理精确但需要平滑帧率GPU 占用不能失控。第三类是 Cesium 底层渲染研究。有人想验证 WebGPU 在 Cesium 中的可行性和收益Atmosphere 是一个很好的切入点因为大气效果效果直观、数据链路短适合快速验证。使用边界也要说清楚。当前 WebGPU 还不是所有浏览器默认功能完全一致Windows 上通常走 D3D12 后端macOS 上走 MetalLinux 取决于 Vulkan 驱动。如果你还在维护大量老旧机器或必须兼容 IE 级别浏览器的场景WebGPU 版 Cesium 现在不是可选方案。另外Atmosphere 模块并不解决所有“好看”的问题。它只负责大气和光照地球上的水体反射、动态云层、阴影、雾效是独立模块。不要期待接入大气模块后整个场景自动变成电影级效果。3. 环境准备与前置条件在开始部署前先确认环境。因为材料里没有给出指定版本下面给出一套通用检查项实际项目需要按你的源码包版本微调。3.1 浏览器与 GPU 后端WebGPU 目前需要浏览器支持。建议使用较新的 Chrome、Edge 版本并在chrome://gpu或edge://gpu中确认 WebGPU 状态。macOS Safari 也有一定支持但版本差异较大开发时最好先把 Chrome 作为主测试浏览器。从底层看GPU 后端是否可用取决于系统图形 APIWindows需要 D3D12 可用显卡驱动基本要相对较新。macOS通过 Metal 后端Apple Silicon 和较新的 AMD 显卡兼容性更好。Linux依赖 Vulkan驱动配置不正确时容易遇到问题。对于老显卡可以通过 Chrome 的 SwiftShader 软件 WebGPU 回退来验证逻辑但性能不具参考价值只能用来排查渲染流程是否正确。3.2 开发工具链如果用 TypeScript 做工程化开发推荐按下面的基础组合准备依赖用途Node.js 18运行 npm / pnpm 脚本Vite本地开发服务器与构建TypeScript参数类型、资源绑定描述更可控WGSL在.wgsl文件或内联字符串中编写着色器如果你的工程需要和 Cesium 一起使用建议先保留一套官方 Cesium 基础场景做对照这样能快速判断大气模块是否影响地球瓦片加载。3.3 文件目录规划Atmosphere 模块最好独立成目录避免和业务代码混在一起。推荐如下结构src/ renderer/ device.ts # WebGPU adapter / device / context 封装 atmosphere/ shaders/ sky.wgsl scattering.wgsl atmosphere.ts # Atmosphere 模块入口 uniform.ts # 相机和光照参数 scene/ globe.ts # 地球几何与纹理采样 main.ts这样做的原因是大气和光照参数变化频繁需要和场景对象生命周期解耦Shader 目录独立也方便后续替换散射模型或切换预计算 LUT 实现。4. 初始化 WebGPU 与大气的渲染框架这一节不依赖某个具体开源实现给出的是自己组合 WebGPU 场景时最常用的三层结构请求 Adapter 并创建 Device。获取 Canvas 的 WebGPU context配置format。创建 Uniform Buffer 和 Render Pipeline绘制场景或全屏后处理。4.1 创建 WebGPU 设备基础初始化代码通常长这样async function createWebGPUDevice(canvas: HTMLCanvasElement) { const adapter await navigator.gpu.requestAdapter({ powerPreference: high-performance }); if (!adapter) { throw new Error(WebGPU 不可用请检查浏览器和 GPU 后端状态); } const device await adapter.requestDevice(); const context canvas.getContext(webgpu); if (!context) { throw new Error(Canvas 无法创建 WebGPU 上下文); } const format navigator.gpu.getPreferredCanvasFormat(); context.configure({ device, format, alphaMode: opaque }); return { device, context, format }; }从材料看WebGPU 版 Cesium 属于实验性探索方向所以如果你看到的工程项目还附带自己的 loader 或 fork请以它的导出方式为准。上面这段代码是 WebGPU 标准入门的通用写法不绑定某一家实现。4.2 与 Cesium 场景的关系把 WebGPU 大气渲染接到 Cesium 场景中有两条常见路线路线一Cesium 用 WebGL 继续渲染地形和影像WebGPU 大气层以独立图层或后处理叠加方式输出。优点是接入成本低缺点是两套渲染器之间需要共享相机参数深度衔接麻烦。路线二整体渲染走 WebGPUCesium 只提供数据源、瓦片解析和相机管理WebGPU 负责最终绘制。优点是渲染控制力更强缺点是需要替换大量 Cesium 的默认渲染流程工程量明显上升。能明显看到“WebGPU 版 Cesium”的方向必然是第二条路线只是在演进过程中大气和光照模块会先独立跑通再逐步接入完整地球。所以在你做功能测试的时候也应该先给一个独立 WebGPU 球体场景把大气调通再接真实 Cesium 瓦片避免首次接入就去排查数据加载问题。5. 基础大气散射与光照实现思路基础大气和光照是整个 Atmosphere 系列笔记里最核心的部分。下面回到图形原理层面讲清楚实现要素。5.1 相机射线与场景相交大气效果通常不是像普通物体一样用 Mesh 渲染而是在 Pixel 阶段对每一条视线射线做球体相交再沿射线累积大气散射颜色。核心思路可以简化成给定射线原点和方向。求射线与大气外边界球相交进入大气。沿射线步进采样。在每个采样点计算光照方向和观察方向的夹角。根据高度和夹角用散射系数加权累积颜色。与地表颜色混合。用伪代码表示fn computeAtmosphereColor( rayDir: vec3f32, sunDir: vec3f32, cameraPos: vec3f32 ) - vec3f32 { var color vec3f32(0.0, 0.0, 0.0); let steps 32u; let stepLength (atmosphereTopRadius - earthRadius) / f32(steps); for (var i 0u; i steps; i i 1u) { // 射线位置 let t stepLength * f32(i); let worldPos cameraPos rayDir * t; // 当前高度 let h length(worldPos) - earthRadius; if (h 0.0) { break; } // 简化指数密度 let density exp(-h / scaleHeight); // 当前点是球面上方判断太阳是否被地球遮挡 // 这里省略精确遮挡测试仅示意 color calcScattering(density, worldPos, sunDir) * stepLength; } return color; }实际工程里这样纯逐像素步进的开销较大通常还需要降低步进层数或在低分辨率渲染后再上采样。另一条主流路线是预计算散射 LUT把散射积分结果存入纹理后续逐像素直接采样极大降低每帧重复计算量。5.2 瑞利散射与米氏散射Atmosphere 基础大气效果最常用的两个物理模型瑞利散射波长越短散射越强阳光穿过大气时蓝光散射最强。卫星视角下地球边缘的蓝色光晕主要来自瑞利散射。米氏散射由大气中的气溶胶和水汽造成散射方向性较强看太阳方向时会出现白色或淡黄色光晕。对这两个模型分别设置 scaleHeight、散射系数、相位函数系数再把两种散射结果相加就可以得到基础大气带。WGSL 中实现相位函数可以参考这种形式fn rayleighPhase(cosTheta: f32) - f32 { let factor 3.0 / (16.0 * PI); return factor * (1.0 cosTheta * cosTheta); } fn miePhase(cosTheta: f32) - f32 { let g 0.76; let g2 g * g; let denom 1.0 g2 - 2.0 * g * cosTheta; return 3.0 / (8.0 * PI) * ((1.0 - g2) * (1.0 cosTheta * cosTheta)) / pow(denom, 1.5); }注意真实项目中的系数、相位函数形式很多需要按你选择的物理模型和审美目标调整。5.3 太阳光方向参数Atmosphere 的光照方向通常来自太阳在场景中的位置。Cesium 中可以通过当前时间计算太阳方向也可以手动拖一个光源角度便于调试。在 WebGPU 中把太阳方向统一放进 Uniform Bufferconst uniformBuffer device.createBuffer({ size: 64, // 至少能放下 cameraPos、sunDir 等参数实际对齐按 16 字节计算 usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST, });WGSL 侧声明类似struct AtmosphereParams { cameraPos: vec3f32, sunDir: vec3f32, sunIntensity: f32, };太阳高度角改变时大气散射颜色也应该随之变化。日落时阳光穿过大气路径长蓝色被散射掉更多只剩红色和橙色如果模块计算出的日落场景没有这种变化大概率是采样步长、散射系数或遮挡判断的问题。5.4 与地表光照合并基础光照不只是“天空余光”地表也应该受到太阳光照影响。常见做法是先计算大气透射率或光照衰减再作为地表材质的一个光照输入。做法步骤先用 WebGPU Render Pass 渲染地表和模型。地平面上方场景存入颜色缓冲同时存下深度。第二个 Pass 根据深度重建世界坐标或视线长度配合大气 LUT 计算雾化颜色。最终混合得到“近处清晰、远处被大气覆盖”的效果。如果只实现“地球边缘大气”不实现地表光照合并从远处看效果还可以但视角拉近后地表像纸片一样这是因为缺失了大气造成的空气透视。6. 功能测试与效果验证6.1 最基础验证浅蓝到深蓝的边缘渐变启动项目后把相机放到太空视角让地球占据画面中心区域。预期结果地球边缘出现一圈蓝色光晕。光晕在朝向太阳的一侧更亮。远离太阳一侧的光晕偏暗但仍有微量散射。判断标准边缘渐变是否平滑有没有锯齿噪点。如果是刚接入 WebGPU 的场景第一次调试常见问题是渲染结果偏黑或偏白。偏黑时先检查太阳方向是否归一化以及光线步进的高度范围是否把射线限死在大气层外。偏白时检查累积步长是否过大或散射系数是否过高这类问题最直接的观察窗口是“降低步长后画面是否明显变暗”。6.2 太阳高度变化测试需要做一个简单的相机和光源控制。let sunElevation 30 * Math.PI / 180; let sunDirX Math.cos(sunElevation); let sunDirY Math.sin(sunElevation); // 刷新时传给 uniform uniformData.sunDir [sunDirX, sunDirY, 0];用例设计太阳角度预期效果主要观察点90 度场景明亮大气边缘淡蓝大气是否过曝30 度东侧亮蓝西侧偏暗大气光晕带角度散射方向是否一致0 度附近冷暖对比明显地平线偏红米氏散射是否明显发灰负角度地球暗面但卫星边缘仍有一圈微光大气遮挡是否正确这个测试可以用来判断散射模型是否真正生效而不是简单的“蓝色描边”。6.3 地表光照联动测试切换到近地表视角把相机高度降到几十公里以内。预期结果正下方地表应受太阳方向光照阴影侧自然变暗。远处山体或地形有一种“被空气笼罩”的灰蓝色效果。相机从高空拉低过程中大气颜色应逐渐变淡不会出现突然切换。判断标准前后帧连续性是否平滑。如果拉近时大气浓度突然变为 0多半是大气外边界高度和地球半径参数不匹配导致射线在进入大气前就结束步进。6.4 WebGPU 渲染环境验证验证分为三步打开浏览器的 WebGPU 状态页确认 API 可用。在页面中绘制一个最基本的三角形确认渲染管线正常。接入 Atmosphere 模块先不加载 Cesium 瓦片用纯色球体代替地球。这样做可以减少干扰项先保证大气和光照逻辑正确再叠加影像瓦片。7. 接口 API 与可配置参数虽然材料中未给出该模块的现成 API但从工程封装角度来看一个可维护的 Atmosphere 模块至少需要暴露以下几类参数。7.1 构造参数export interface AtmosphereModuleOptions { enableScattering: boolean; enableMie: boolean; sunIntensity: number; rayleighScaleHeight: number; mieScaleHeight: number; steps: number; resolutionScale: number; }这类配置的意义是方便在调参和正式渲染之间切换避免为了试一个参数去改 Shader 重新编译。7.2 Uniform 数据结构建议所有跟相机、光源相关的动态参数都放进 Uniform Buffer每帧更新一次不要直接写在 Shader 常量里。const params { cameraPos: new Float32Array(3), sunDir: new Float32Array(3), sunIntensity: 1.0, rayleighScaleHeight: 8500.0, steps: 32.0 };这种做法的好处是方便后续加入时间动画、太阳轨迹、或者从 Cesium 外部同步相机位置。7.3 回调接口模块可以提供 onFrame、onResize、onCameraChanged 一类回调供外部业务统一驱动渲染循环。这里不再给出绑定特定框架的代码因为不同工程的事件循环不一致但接口设计要保证“大气渲染只依赖输入参数不主动查询全局状态”。8. 资源占用与性能观察在 WebGPU 版 Cesium 场景里性能是比功能更敏感的问题。因为数字地球项目往往已经加载大量地形瓦片、矢量数据和模型Atmosphere 如果再占用过高整体体验就会崩。8.1 显存占用观察方法没有具体材料支撑这里不给具体显存数字但观察方法是一套可靠流程打开浏览器 DevTools 的 Performance 面板。在 Rendering 选项里勾选并启用 WebGPU 相关统计能力。切换不同分辨率、不同 LUT 大小、不同 Ray March 步数记录变化。对比“关闭大气模块”和“开启大气模块”时的帧时间差异。正常情况下大气渲染不应该是场景中最大的显存消费者更大开销通常来自影像纹理、地形 mesh 和阴影贴图。如果大气模块导致显存飙升优先检查是否把逐帧渲染结果都存成了永久纹理或者 LUT 尺寸过于浪费。8.2 计算量与分辨率Atmosphere 的渲染成本和屏幕分辨率强相关Ray March 步数从 32 翻到 64Pixel Shader 循环体翻倍。LUT 分辨率从 128 提高到 256增加的往往是预计算时间运行时采样额外开销不大。全屏后处理一旦叠加分辨率越高采样成本越高。实际调优可以按这个顺序来先固定 Ray March 步数为 32看效果是否可接受。如果不满意提高散射采样质量而不是盲目增加步数。如果 Canvas 显示尺寸已经超过 4K考虑降低内部渲染分辨率再用双线性或双三次上采样。8.3 低端 GPU 下的降级策略低端 GPU 上优先建议做分级策略当帧时间超过阈值时自动减少 Ray March 步数。关闭米氏散射只保留瑞利散射。使用粗糙模式不再做预计算 LUT 多级采样。这一层不是必须写进 WebGPU 版 Cesium 核心代码但在工程实际中很有价值。很多数字孪生大屏运行在集成显卡或云渲染环境里不能假定用户都有一张高性能独立显卡。9. 常见问题与排查方法WebGPU 版本还在快速演进碰到的问题会比较杂。下面把最容易遇到的几类问题列出来。问题现象可能原因排查方式解决方案navigator.gpu不存在浏览器不支持 WebGPU或未开启实验特性打开chrome://gpu或浏览器文档确认升级浏览器或打开相应实验开关页面黑屏控制台少报错渲染管线创建失败或 Canvas 未正确 configure先用三角形测试管线再接入大气模块检查 shader 编译报错、Pipeline 描述是否符合 WebGPU 规范大气边缘出现明显噪点Ray March 步数不足或采样分布不合理单帧截图放大观察边缘提高步数或增加 LUT大气颜色过于饱和散射系数或步长过大调低散射系数观察颜色变化趋势以视觉效果为准逐步调参太阳方向效果不明显Uniform 未正确更新或太阳方向被归一化后的值错误在代码中打印 uniform 参数先固定一个太阳方向再联动时间WebGPU Device Lost驱动崩溃或长时间后台切换引起 GPU 上下文重置监听device.lost事件并查看 reason实现自动重建 Device 和 Pipleline与 Cesium 瓦片深度穿插WebGPU 大气层与 Cesium 相机深度权重不一致单独渲染大气层关闭瓦片排查相机矩阵统一两套系统的投影矩阵和相机位置基准高温或高负载时画面闪烁显存带宽不足或后端驱动驱动有 bug限制帧率降低内部渲染分辨率引入动态分辨率缩放或提供画面质量开关另有两个容易忽略的问题。第一WebGPU 对资源布局的要求比 WebGL 更严格。Uniform Buffer 的 stride 对齐、纹理格式要匹配。如果数据错位太阳方向显示不对排查难度还会高一些。第二如果用了多个 Render Pass必须正确管理 Render Attachment 的 loadOp 和 storeOp。大气后处理想保留 Cesium 之前渲染的地球影像就需要在 Load 时设置 clear 为 false以避免覆盖前一帧结果。10. 最佳实践与使用建议Atmosphere 模块接入数字地球项目时建议从一开始就按工程化方式管理参数。第一次接入时不急着加载真实地形先准备一个简单球体场景。在这个场景里调好大气散射颜色、太阳方向和地表光照。这样能快速定位问题是出在算法层还是 Cesium 数据对接层。尽量保留一套低画质配置。大屏项目往往需要 7x24 小时运行不可能每次都开全分辨率高质量渲染。发布前至少要提供“低性能模式”与“高质量模式”两套开关。显存、内存、Canvas 分辨率要分开管理。页面分辨率不等于物理渲染分辨率可以设置一个 renderScale 变量在大屏上运行时用低分辨率渲染再缩放显示。Shader 代码尽量独立成文件。WGSL 代码放内联字符串调试和复用都不方便。建议直接用.wgsl文件加载或通过 Vite 插件处理。在真实 Cesium 场景中接入时考虑权限和边界。渲染大气和光照不涉及隐私问题但如果你的数字地球项目叠加了卫星影像、实时监控、人员位置等数据必须确认数据来源合法、展示范围合规不能因为“只是做可视化”就忽略授权边界。如果后续加入真实时间系统来模拟太阳位置还要考虑不同时区的地址是否被正确处理。对于涉及单位内部系统和地图数据的项目建议先在内网或测试环境验证。不要把未脱敏的管理数据、地形数据放到公网演示避免踩到数据合规红线。11. 总结与下一步这篇文章里没有堆叠某一份具体仓库的接口文档而是把 WebGPU 版 Cesium 的 Atmosphere“基础大气和光照”拆成一个可复用的工程技术路径。从模块定位、环境准备、设备初始化、Shader 原理、参数设置到常见问题排查都过了一遍。如果你接下来要自己实现或者研究这一类模块建议第一步先别管 Cesium 的多种数据加载先跑通一个可旋转球体在球体外边界套上大气散射。把太阳方向做成可以拖动的调试参数再逐步优化为预计算 LUT。最容易踩的坑有两个一是把大气渲染当成简单“蓝色描边”没有从散射物理和视线上区分地面和大气层导致远近视角效果割裂二是过早接入 Cesium 瓦片遇到黑屏后分不清是大气模块问题还是瓦片加载问题。下一步可以考虑和地形阴影结合。Atmosphere 只是基础光照的一维更复杂的是地形遮挡导致的局部阴影、云层对光照的衰减、以及水面太阳反射。把那层效果加进来后数字地球的整体真实感会有一次明显提升。