URP - RendererFeature :局部体积雾(可交互)
局部体积雾
独立作品
- ENGINE
- Unity · URP
- TECH
- Shader · rendering · unity · URP · RenderFeature · 后处理
- ROLE
- Shader · 工具
- YEAR
- 2026
案例目录14 小节
射线的表示

包围盒
AABB
AABB — Axis-Aligned Bounding Box,轴对齐包围盒。这里我实现的是AABB,后续在添加旋转控制** “轴对齐”意思是盒子的六个面永远平行于世界坐标系的XYZ轴,不能旋转。这就是为什么代码里能用简单的min/max做求交——每个面都垂直于某一个轴,数学极其简单。
OBB
OBB — Oriented Bounding Box,有向包围盒。 允许任意旋转,盒子可以斜着放,贴合物体形状更紧密。
两者对比:
| AABB | OBB | |
|---|---|---|
| 旋转 | 不能旋转,永远轴对齐 | 任意旋转 |
| 求交复杂度 | 极简单(就是你现在的代码) | 复杂(需要分离轴定理SAT) |
| 贴合度 | 差(斜放物体会有大量空白) | 好 |
| 用途 | 体积雾、碰撞粗检测、BVH | 精确碰撞、物理引擎 |
射线与AABB求交集
因为公式是射线的表达式是:
这里就直接求解:
因为保证交点在box内部,所以射线到box最近点是tmin取最大,最远点tmax则取最小

基础框架搭建
这里我设想的是随意挂在空物体上构建一个局部体积雾,所以需要单独对局部体积雾制作一个类,然后由feature进行全局管理一次性跑完,交互类则是定为一个点可以挂在其他物体上,同理也需要单独一个类
CustomFogVolume
FogVolume类这里给了很多参数控制每个局部体积雾有不同效果,OnDrawGizmosSelected方便编辑器实时调整

CustomFogDisturber
Disturber扰动类,结构比较简单

CustomLocalVolumetricFogFeature
整体管理的Feature,代码和之前的全局体积雾是差不多的没什么区别,主要是传参方面,因为需要编辑器支持,所以需要在Feature中实时检索场景内的体积组件,不过这样数量会限制,不能过多。如果单独设置一个静态管理类的话比如CustomFogDisturberManager,应该可以省去检索的部分开销,但是缺点是没办法实时调整,必须在运行模式下看效果 这里添加存储的数据结构

然后在AddRenderPasses进行数据采集

剩下就是传值了,就是预先处理一下传数组就行,尽量把通道塞满了

CustomLocalVolumetricFogShader
其实和全局雾内容差不多,不过需要跑多次,所以放到循环中,起点和终点换成AABB的min和max

物体交互
交互扰动,这里使用球形的范围渐变来削减密度

添加CurlNoise
原始的CurlNoise公式如下

因为当前是标量场没有方向,所以直接求偏导,也就是采样6次
∂N/∂x ≈ (N(x+e) - N(x-e)) / (2e) //标准公式
这里没有除2e减少开销,而且normalize已经舍弃长度,所以不用除了

整体交互部分代码

这里可以看到边界处有涡流旋转的效果

边界衰减

这里可以得到弱化边界的效果

最终效果
这里把散射强度和扰动强度调的很高方便观察,要是实现非常精确的交互雾的话还是得用粒子雾,局部雾更适合场景摆放,因为光照步进它其实更加精确,不过基于屏幕占比开销会增加很多