news 2026/7/31 9:03:22

全实时雪地渲染技术-开源项目

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
全实时雪地渲染技术-开源项目

「16-全实时雪地渲染技术-巴比伦JS」
/~1a003ZscWu~:/
链接:https://pan.quark.cn/s/4d5472d3a776

SNOWFLOW

一个实时雪地渲染技术演示。基于 WebGPU + Babylon.js,全程手写 WGSL。

仓库中没有任何纹理、网格、HDRI 或动画数据——你在屏幕上看到的一切,都是在加载时由 GPU 实时生成的。

▶ 在线演示 snowflow-lilac.vercel.app

运行要求:​ 支持 WebGPU 的桌面浏览器(Chrome/Edge 113+、Firefox 141+、Safari 26+)以及独立显卡或较新的集成显卡。

设计上不提供 WebGL 回退:若检测到navigator.gpu缺失,页面会明确提示并停止运行。


操作控制

操作

功能

点击画面

捕获指针

W / A / S / D

相对摄像机方向移动

鼠标

视角转动 · 滚轮缩放

Shift

冲刺

右键长按

雪地冲浪​ — 在雪面上滑行并掀起雪浪

1 – 5

五个法术(2 号为持续施法)

F1 / `

设置面板与性能叠加层

叠加层将所有美术参数暴露为实时滑块——太阳角度、风向、次表面散射半径、形变深度、色调映射曲线、曝光等——并附带帧时间图(中位数 / 95% / 1% Low)、Draw Call、三角形数与各系统 CPU 耗时分解。任意系统均可单独关闭,并提供法线、深度、级联覆盖、形变缓冲区与原始阴影贴图的调试视图。


核心功能

地形

采用嵌套环形几何 Clipmap

  • 8 个环,内层间距 8.5 cm,半径约 870 m,33.3 万三角面

  • 仅一个静态网格,一次 Draw Call

  • 顶点仅携带(gridIndex, ringLevel);世界坐标放置、CDLOD 过渡与位移全部在顶点着色器中完成,CPU 无需重建,每帧无数据上传

底层高度场由分层梯度噪声 + 解析导数生成,围绕单一主导风呈各向异性:

  • 宽阔的横卧沙丘脊线

  • 长距离低缓起伏

  • 沿风向剪切的中尺度漂移(迎风/背风不对称)

  • 稀疏岩石露头

高度场一次性烘焙为4096² RG32F 纹理并镜像回 CPU,角色接地采样的是与绘制完全一致的表面,而非其重实现版本。


雪地着色

  • 多尺度法线:烘焙宏观坡度 + 解析雪脊与波纹 + 三层平铺细节,陡坡面三平面投影

  • 包裹漫反射 +深度相关蓝调次表面散射(背散射)​ + GGX 高光

  • SH 环境光(包含求解出的雪地反弹光)

  • 程序化视角相关闪光(受掠射角门控)

压缩度、湿度与结冰作为表面状态通道被材质读取,而非独立材质。

阴影为手写三级级联,带世界空间 PCSS:

  • 遮挡物搜索 → 半影估计 → 旋转泊松滤波

  • 世界空间纹素对齐,基于旋转不变包围球稳定

Babylon.js 内置级联生成器在此不可用:地形没有与绘制匹配的 CPU 几何,因此每个投射物必须注册其实际使用的顶点程序。


形变系统(Deformation)

持久化、累加式地形状态缓冲区

  • 两个2048² RGBA16F​ Target,覆盖 80 m(3.9 cm/纹素)

  • 每帧一次全屏 Pass(Ping-Pong),在同一 Dispatch 中完成滚动、松弛与泼溅

  • 环面寻址(Toroidal):UV =fract(worldXZ / size),视口跟随玩家而无需拷贝缓冲区,新暴露纹素由同一 Pass 检测并清零

四个通道:凹陷深度、位移质量、压缩度、结冰。

第二个通道(位移质量)区分了“带隆起雪埂的轨迹”与“扁平脚印贴花”。

回填逻辑:

  • 各向异性扩散(松散雪埂坍塌速度是压实沟底的 3 倍)

  • 雪埂向凹陷处塌陷

  • 上风向风驱填充

  • 缓慢指数衰减:约71% 的轨迹深度在一分钟后保留,期间持续扩散、软化

形变为真实几何,在最终渲染与三级阴影级联中通过同一 Include 生效,因此轨迹自投影、雪埂破坏轮廓。

脚掌、冲浪雪浪、五个法术均通过同一个brush()调用写入同一缓冲区。


角色系统

完全程序化生成​ —— 无骨骼文件、无动画片段、无手工网格。

  • 18 根骨骼,绑定姿势来自数值表

  • 几何体(兜帽、躯干、手臂、裤腿、靴子、腰带)在加载时从该表放样生成

  • 运动由运动状态求解,而非播放动画

脚部踩踏:距离驱动的站立/摆动状态机在触地瞬间精确写入一次脚的全局位置并绝对锁定,双骨骼 IK 朝向该点拉伸——已踩住的脚不可能滑动,因为代码中没有任何逻辑能移动它。步态相位随地面行进距离推进,步幅与地面速度在数学上天然一致。

衣物:Verlet 布料,4 个布片,带距离、弯曲与形状记忆约束,9 个身体碰撞胶囊体,下摆贴合雪面。褶皱存在于静止形状而非法线贴图中。

36×12 的布料求解结果在顶点着色器中通过 Catmull-Rom 重建渲染为 72×32 表面,曲面细分与模拟开销完全解耦。

兜帽边缘与袖口的壳毛发(Shell Fur)为局部圆环体,发射 22 次,通过哈希发丝场进行 Alpha Test。

仅一张小纹理承载所有数据:第 0–3 行存骨骼矩阵,第 4 行起存模拟布料节点。每帧一次上传,无额外分配。


雪地冲浪(Snow-Surf)

雪浪为扫掠网格(Swept Mesh),而非粒子特效。

  • 脊柱为滑板路径,每 30 cm 重采样一次,存入 96×3 数据纹理

  • 网格本身是(column, row, side)的静态晶格,所有顶点在 VS 中放置

  • 19 米与 2 米的雪浪消耗相同的 Buffer 与相同的 4.6 KB 上传带宽

横截面为基于转向切线积分的破波浪:

  • 切线从底部略低于水平到顶端 284°,一个卷曲参数即可连续控制从低矮堆积到悬垂唇缘的形态

  • 振幅与卷曲按两侧分别解析,转弯外侧承担绝大部分积雪

  • 峰值墙高在全速刻划时达 2.4 m,0.88 秒后坍塌,雪浪长度 = 寿命 × 速度,无需第二个常数

法线从与几何完全相同的wakePoint差分得出,二者永不冲突。

两类喷溅源自同一脊柱:

  • 紧贴波峰的密集慢速水帘

  • 飞离的弹道颗粒

  • 附加屏幕空间速度拖尾与满载边缘的镜头抖动


五个法术

一种水体材质、一个网格、一次 Draw Call、八股水流。

其中四个法术移动同一连贯水体,结构上属于同一种对象:沿脊柱的扫掠曲面,带半径、平行输运标架与泡沫通道——与冲浪雪浪构造相同。未启用的股流通过清零行关闭,Draw Call 数量不随法术数量变化。

法术

描述

Sweep(横扫)

新月形雪泥从地面升起向外推进,犁出沟壑并抛起雪埂

Ribbon(缎带)

持续施法,追踪手部与准星,绘制进动的 8 字,在掠过的雪面刻下细曲线;释放后头部锁定准星加速,水流以释放时的弯曲形态弧线击中目标

Bloom(绽放)

定点喷发:带隆起边缘的陨石坑 + 沿自身轴线升降的束腰柱体 + 4 秒底部照亮的坠落帷幕

Crystallise(结晶)

沿黄金角螺旋生长的六棱柱,Alpha 混合 + 深度写入,透过冰层可见雪地但棱柱互不穿透;切面法线来自屏幕空间导数,边缘绝对锐利

Vortex(漩涡)

环绕玩家的三股螺旋上升雪流,空中质量沿螺旋以切向速度发射;唯一写入负凹陷的系统

折射:无需场景拷贝与二次不透明 Pass。天空 LUT 已存储地平线下求解出的雪地反弹光,沿折射射线单次采样即可物理估算任意方向后方颜色;三次不同折射率采样得到色散,路径长度吸收得到色调。

每帧声明4 个池化动态光源,全部运行与太阳相同的snowSubsurface逻辑——法术通过雪埂顶部照亮雪地,而非仅在近面打亮。

雪地、长袍、雪浪、空中喷溅、水体与冰层全部从同一 Include 读取同一光照池。


天空与大气

Nishita 单次散射积分 + 多重散射近似 + 迭代求解雪地反弹,烘焙为等距柱状 LUT + SH 辐照度 + Mip 层级高光。

采用解析大气而非捕获 HDRI:整体观感高度依赖 10–15° 仰角的太阳——

  • 调整太阳高度时,地平线暖调、天顶渐变、环境色调与直射阳光颜色同步变化

远景为在天空盒上光线步进的高度场:

  • 无几何,天然位于一切之后

  • 解析法线,山脊相互遮挡

  • 朝向太阳进行二次短步进以生成自身投射阴影

  • 使用雪地材质逻辑照明,受同一大气雾化,与近景雪地在颜色上无缝衔接


后处理管线

相机空间深度预 Pass(线性视图深度作为 Varying 传递 + 高光掩码)驱动整条链路:

  1. TAA:Halton(2,3) 抖动直接写入投影矩阵并整帧冻结,确保预 Pass 与最终 Pass 亚像素对齐;基于深度的重投影、方差裁剪、五点 Catmull-Rom 历史采样

  2. Bloom:三级,阈值基于曝光值,仅太阳盘、闪光与受照喷溅参与;预过滤使用 Karis 平均

  3. 体积光(God Rays):沿射线向太阳方向在预 Pass 中积分天空可见性;太阳仰角高时自动淡出

  4. 景深:刻意轻微,焦平面跟踪 Spring Arm 自身长度,按各采样点的模糊圈加权

  5. 屏幕空间反射:仅作用于冰面,由预 Pass 掩码门控,Crystallise 未施放时整帧跳过

  6. AgX / ACES 色调映射 → 对比度自适应锐化 → 颗粒感 → 暗角


性能数据

测量环境:WebGPU Timestamp Queries,2560×1440,Chrome / Win11 / RTX 5070 Ti,全系统开启

指标

数值

GPU 帧时间

3.22 ms

— 基础场景(Clipmap、雪地、3 级联、天空、角色、形变、预 Pass)

1.64 ms

— 后处理链

~1.1 ms

— 远景

~1.2 ms

— 角色(骨骼、布料、毛发、喷溅)

< 0.02 ms

Draw Calls

15–19

三角形数

~353,000

90 FPS 预算余量

7.9 ms

渲染循环零分配:所有 Buffer 构造时定长,每帧写入均进入预分配的 Typed Array;所有材质、程序化纹理与渲染管线均在加载界面显式isReady()门控并预热,确保首个法术施放不会在帧中间编译管线。

显存占用约 350 MB

  • 4096² 高度纹理

  • 两个 2048² 形变 Target

  • 三个 2048² 阴影级联

  • 天空与细节 LUT


本地运行

npm install npm run dev # Vite 开发服务器,端口 :5173 npm run build # 生产构建至 dist/ npm run preview # 预览生产构建

目录结构

src/ ├── main.js # 入口与帧调度 ├── core/ # 设置、输入、相机臂、性能、加载、GPU 辅助 ├── terrain/ # 高度场、Clipmap 网格、形变状态缓冲 ├── render/ # 天空 + IBL、阴影级联、深度预 Pass ├── character/ # 骨骼、程序化几何、布料求解、雪面接触 ├── vfx/ # 池化粒子、雪地冲浪雪浪 ├── spells/ # 五个法术、共享水体、光源池 ├── post/ # 后处理链 ├── ui/ # 设置面板与性能叠加层 └── shaders/ # 全部 WGSL,lib/ 存放共享 Include

资产与许可证

无任何第三方美术资产。

运行中看到的每一张“纹理”、每一个环境贴图、每一个网格,均由 GPU 在加载时实时生成:

  • 天空 = 大气积分

  • 雪粒与地形 = 噪声

  • 角色 = 数值表放样

  • 织物编织与毛发 = 片元着色器实时求值

运行时依赖:@babylonjs/core@babylonjs/materials(Apache-2.0)

构建依赖:Vite(MIT),不参与最终输出分发。

本项目源码基于 MIT 许可证发布。


版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/31 9:01:57

TCP拥塞控制算法探测:从原理到实战的完整指南

在网络性能优化和故障排查过程中&#xff0c;我们经常需要了解服务器使用的TCP拥塞控制算法。无论是为了调优网络参数、诊断性能瓶颈&#xff0c;还是单纯出于技术好奇心&#xff0c;掌握服务器拥塞控制算法的探测方法都是网络工程师和开发者的必备技能。 本文将系统讲解TCP拥…

作者头像 李华
网站建设 2026/7/31 9:00:24

从毛囊干预到白发逆转:生物科技如何科学延缓头发变白

那天下午&#xff0c;我正刷着手机&#xff0c;一条视频突然闯入视线——画面里&#xff0c;几缕灰白的发丝在某种操作下&#xff0c;颜色竟然逐渐恢复。评论区炸了锅&#xff0c;有人说“这要是早十年知道&#xff0c;我现在就是百万富翁了”&#xff0c;也有人质疑“真的假的…

作者头像 李华
网站建设 2026/7/31 8:59:40

Android OAID集成实战:MSA SDK 1.0.25避坑与多厂商适配指南

1. 项目概述&#xff1a;为什么OAID集成是Android开发者的必修课如果你最近在更新你的Android应用&#xff0c;特别是涉及到广告归因、用户行为分析或者风控反作弊模块&#xff0c;那么“OAID”这个词一定频繁地出现在你的视野里。它不是什么新潮的技术&#xff0c;但绝对是当前…

作者头像 李华
网站建设 2026/7/31 8:58:44

Nginx反向代理配置实战:单域名多端口服务统一入口与HTTPS部署

1. 项目缘起&#xff1a;一个域名&#xff0c;多个服务&#xff0c;如何优雅地统一入口&#xff1f; 最近在折腾自己的个人服务器&#xff0c;场景很典型&#xff1a;一台云主机上&#xff0c;跑了不止一个应用。比如&#xff0c;一个主站博客跑在 3000 端口&#xff0c;一个后…

作者头像 李华