跳过正文

Unity实现体积光(GodRay)的三种方案

·2317 字·5 分钟
杂谈 Unity Shader 渲染 光照 算法
AxonSin
作者
AxonSin
梦想是复活在赛博世界,成为一名赛博垃圾人。

Unity中实现体积光的三种方式
#

体积光就是让光看起来“有体积”,像是穿过雾气的光柱,或者空气中漂浮着的尘埃被光线照亮的效果。它比普通的光照多了一种在空间中传播的感觉,让游戏画面更有氛围感。

实现体积光的方式有很多,但总的来说可以分为三种:面片方法屏幕空间方法光线步进方法。这三种方法从简单到复杂各有优缺点。


1. 面片方法/粒子特效方法
#

这里先讲面片的实现方法。面片方法很好理解,假设你拿着一根手电筒,手电筒打出了一束光柱。我们并不真的去模拟这些光线在空气中传播,而是直接在手电筒前面摆一个锥形的“透明罩子”,让它看上去像光柱一样。这个“罩子”就是一个模型(比如锥体或者圆柱体),通过材质的透明效果让它变得像一束光。

实现思路:
#

对于直接使用模型模拟的情况,可以创建一个几何体,比如锥体或者一个平面面片。把这个几何体放在光源位置,并让它的方向和光源的方向一致。给几何体加一个材质,材质可以通过渐变纹理让中央部分更亮,边缘更透明。为了更真实,可以再叠加一个噪声纹理,模拟空气中的尘埃。如果光源会动,比如手电筒或者舞台灯光,那么这个几何体也需要随着光源移动和旋转。

还有一个方法比较Trick、就是利用Unity自带的粒子系统进行动态体积光的模拟,这个方法比上一个方法更加富有动态上的美感(但是需要配合Bloom效果,意味整个画面需要有所改变),适合作为一个附加项。

优点和缺点
#

优点

  • 简单,一个几何体加一个材质/使用粒子就能搞定。
  • 性能开销很小,因为是基于物体的材质或者是引擎自带的粒子系统,非常适合性能敏感的场景,比如移动端游戏。
  • 艺术表现力强,通过调整材质的渐变、纹理、透明度等参数,可以轻松制作出各种风格的光柱效果。

缺点

  • 真实感有限,因为它只是一个几何体,并没有模拟光线与空气的真实交互。
  • 遮挡问题比较明显。如果光柱穿过了场景中的墙壁或者其他物体,它不会被正确遮挡,看起来就很假。
  • 靠近光柱时可能看起来很平面,缺乏立体感。

适用场景
#

面片方法特别适合那些对真实感要求不高的场景,比如舞台灯光、探照灯、或者卡通渲染风格的游戏。如果你的项目对性能要求比较高,这种方法并不是最优选择。

参考
#

https://www.youtube.com/watch?v=kbsd6askiCY&t=195s Using Particle System
#

2. 屏幕空间方法:光柱和场景的互动
#

面片方法的问题在于,它不会考虑光柱和场景中的物体之间的遮挡关系。而屏幕空间方法解决了这个问题。它的核心思想是:我们不在三维空间中画光,而是在屏幕上“画光”。可以理解为,我们直接在屏幕上计算光柱的效果,而不是在场景中放一个几何体。

实现思路
#

首先,把光源的位置投影到屏幕上,确定光柱在屏幕上的范围。从光源的屏幕位置出发,向外扩散光线。沿着这些光线的方向,我们对屏幕上的像素进行采样。通过深度缓冲(Depth Buffer),判断光线是否被遮挡。比如,如果光柱前面有一堵墙,通过深度值可以知道光柱应该被遮挡。计算完光柱的强度和遮挡效果后,把它作为一个后处理效果叠加到最终画面上。

优点和缺点
#

优点

  • 动态遮挡效果逼真。比如光柱被墙挡住后,遮挡关系是自动处理的,真实感更好。
  • 可以处理多个光源的体积光效果,比如汽车大灯或者手电筒光柱。
  • 性能开销可以调节,比如可以减少采样点来提升性能。

缺点

  • 它只能处理屏幕上看得见的部分,屏幕外的光柱是无法计算。也就是说如果不出现在屏幕空间则没有体积光。
  • 效果和分辨率密切相关,分辨率越高,计算量越大。
  • 遮挡的精度受限于深度缓冲,如果场景比较复杂,可能会有一些不准确的地方。

适用场景
#

屏幕空间方法特别适合那些需要动态光柱效果的场景,比如手电筒、汽车大灯,或者光线穿过窗户洒进房间的画面。它对硬件的要求不算太高,适用于中高端设备。

参考
#

https://www.youtube.com/watch?v=vnBfbZeV928

3. 光线步进方法
#

上面两种方法都是“假的”体积光,而光线步进方法则是“真的”体积光。它直接在三维空间中模拟了光线在空气、雾气、烟尘中的传播过程。简单来说,它会从摄像机出发,沿着每一条视线(即屏幕上的每个像素)不断采样,计算光线在这些点上的散射和吸收。

实现思路
#

从摄像机出发,沿视线方向,对每条光线进行步进采样(类似于光线追踪)。

每个采样点都会计算光线的强度变化,比如步进一步之后光线在传播中因为散射而变弱,使用数组对当前光线进行记录。

如果采样点被光源照亮,还要计算光线的直接照明效果。

把所有采样点的结果累加起来,得到当前像素的体积光效果。

最后,把体积光效果和场景颜色合成,生成最终画面。

优点和缺点
#

优点

  • 真实感爆表!它可以精确模拟光线在体积介质中的散射、吸收和遮挡。
  • 支持动态雾气、烟尘等复杂效果,比如爆炸后的烟雾中透出的一束光。
  • 灵活性极高,可以表现各种复杂的光照效果。

缺点

  • 计算量巨大,每条光线都需要多次采样(比如说你的步长),对性能要求非常高。
  • 实现难度较大,需要对体积渲染和光照模型有深入理解。
  • 对硬件要求高,通常只适合高端设备和次世代游戏。

适用场景
#

光线步进方法是高质量渲染的终极选择,适合那些需要表现复杂雾气、烟尘或者动态光线传播的场景,比如次世代游戏、电影级别的渲染效果。如果你追求极致的真实感,并且硬件性能允许,那这就是你的最佳选择。

方法 优点 缺点 适用场景
面片方法 简单高效,性能占用低 真实感不足,无法处理遮挡 卡通风格、移动端游戏
屏幕空间方法 动态效果好,可处理遮挡 受屏幕限制,分辨率依赖 手电筒、大灯等动态光柱
光线步进方法 真实感最高,支持复杂动态光线传播 性能开销大,硬件要求高 次世代游戏、电影级别渲染

总的来说,如果性能要求高,可以选择面片方法。如果需要动态效果并且硬件性能允许,屏幕空间方法会是一个很好的平衡。而如果你追求极致的真实感,那就选择光线步进方法。

参考
#

https://www.youtube.com/watch?v=0G8CVQZhMXw&t=199s 这采用了houdini生成3D纹理并使用Shadergraph实现Raymarching的效果

https://www.youtube.com/watch?v=hXYOlXVRRL8&t=570s 上面的省流版

Reply by Email

相关文章

反射算法
·46 字·1 分钟
杂谈 Unity Blender Shader 渲染 算法
Blender导入Unity指南
无厚度_低厚度的zfighting问题
·3192 字·7 分钟
杂谈 Unity Blender Shader 渲染 材质 光照 物理 色彩 故障排除 教程 技巧
Blender导入Unity指南
自定义效果的大杀器——RenderFeature
·2758 字·6 分钟
杂谈 Unity Shader 渲染 材质 光照 色彩 故障排除 配置
问题解决方案