【Unity大气渲染】关于单次大气散射的理论知识

news2025/1/21 21:28:32

参考

最近在实现程序化天空盒,到了实现大气散射这一步,索性查漏补缺,把大气散射这块儿的理论知识补充明白了。跟着【实战】从零实现一套完整单次大气散射_一的推荐,学习这块我直接从Volumetric Atmospheric Scattering啃起。

补充一点!本篇文章实际上是作为一个阅读笔记来写的,因此条条框框并没有写的很清晰~以下的图均来自Volumetric Atmospheric Scattering。

同时部分内容还参考了乐乐女神的: [Rendering] 基于物理的大气渲染

1 引入

材质外观会由光是否能穿透材质决定——半透明物体的渲染结果来自于内部结构与光线相互作用的结果。但如果我们想实现玉石这种半透明物体已经有对应的方法了,例如Fast Subsurface Scattering in Unity中展示的方法渲染出的玉石:

但很遗憾,这种通过Ray Tracing仅模拟出表面材质的效果,是难以渲染出一个真实天空的样子的。除了渲染出“outer shell”,还需要考虑大气效应(atmospheric effects)——模拟出光线穿透大气会发生什么(大气散射),那就需要上体积渲染了!体积渲染(Volumetric Rendering)是计算光在物体内传播的渲染方法,而体积渲染常用的Ray Marching和SDF(Signed Distance Functions)用来模拟大气散射也不是很高效(本人没实操过,是参考的文章里的话~),一种更好的模拟固体半透明物体的方法——体积单散射(Volumetric Single Scattering)就被顺利的提出!

1.1 光在介质中传播

为了节约性能实现高效计算,大部分的游戏引擎(Unity&UE)都假设光在真空中传播,这就意味着物体们就成了唯一能影响光线传播的因素。但现实中光是通过介质传播的!这样我们看到的物体的外观就会收到光线穿透程度的影响。地球表层空气密度低,这样稀薄的大气层导致光线需要传播很远我们才能看到,所以很远很远的山脉看上去就像跟天空连为一体,但靠近我们的物体是不会被大气散射所影响的。

复刻大气散射第一步——了解光如何在介质(例如空气)中传播的。由于光线只有进入人眼才能被人眼到看到,因此在图形学学习过程中往往会把人眼比作rendering的相机。而空气中的分子(介质中的粒子)是可以使穿过它们的光线发生偏转的,那么以人眼(相机)是否看得见偏转后的粒子为划分依据,可以把这些粒子影响观察的过程分为外散射(Out-Scattering)内散射(In-Scattering)

1.2 外散射 Out-Scattering

一束射向相机的光线打在了介质粒子上发生偏转,这就是外散射。

介质密度&传播距离

以上只是一束光线的效果,但真正的光源每秒会发射亿万光子,每个光子都有几率击中介质中的粒子,介质密度越大,光子击中且发生偏转的概率也就越大。

上图体现了一个衰减的过程:向外散射导致光逐渐变暗,传播距离越远越暗。这个变暗的程度是由传播距离和介质密度共同决定的。

1.3 内散射 In-Scattering

有了外散射做参考,内散射就更好理解了:一束本身不是射向相机(其他方向)的光线打在介质粒子上发生偏转后恰好到了朝向相机的方向上,这就是内散射。

相机会同时接收来自同一个光源的直接和间接光线,放大了收到的光子数量,光源周围的光晕(light halos around light sources)就是这么个道理。

2 单次散射过程

上面提到了光线是如何在介质中传播的,这里我们需要进一步知道光线穿过一个行星的大气层时发生了什么。首先定义一点:接下来说的单次散射仅考虑光线从太阳发出只经过一次散射改变方向后射入相机(人眼),即只考虑沿视线发出的内散射:

当然,肯定有很多其他的传播方式,但就如文章Part1末尾的cheat sheet所述,考虑可能的散射路径越多,计算所需的散射次数将呈指数增长。

2.1 PtoA发生的外散射

首先考虑外散射,那么就要有上面提及的衰减问题,AB上的每个点P都会有几率偏转,如下图所示:

2.2 PtoA发生的内散射

想要计算P点发生的外散射,首先我们需要知道P点到底有多少光:假设只有一个恒星照亮当前这个行星,那就是太阳,这样的话P点的光都来自于太阳了,这些光一部分来自于内散射:

Sun --> P --> Camera这两步骤就足以近似计算模拟出大部分大气效应了。

2.3 SuntoP发生的外散射

但!如果考虑考虑Sun --> P的过程中光线的外散射,things are getting more complicated...如下图,对于AB中的每个点Pi都需要考虑

  • Sun --> Pi过程中发生的外散射
  • Pi --> Camera过程中发生的外散射

3 理论

3.1 衰减系数T

其实已经来到了这个tutorial的Part2:The Theory Behind Atmospheric Scattering - Alan Zucconi

为了计算肯定要用各种数学参数去模拟上述的这样一个过程,我们从Sun --> P开始,将过程细化成下图,光从太阳出发直到与大气层边缘相交的C点过程中不发生散射,我们定C点的光照强度为I_{C},C进入大气层 --> P过程中发生散射,一路经过衰减后到达P点的光照强度为I_{P}

我们将I_{P}I_{C}比值叫做衰减系数(Transmittance),用以表示某段光线传播路径上光照的衰减程度(没有被散射的光照占比),那么P点接受的光照可以被表示为:

I_{P}=I_{C}T(\overline{CP})

3.2 散射系数S

P点的光强知道之后,接下来就是计算P点发生散射后沿着路径PA到达相机的光照,这里我们先引入一个参数,散射系数(Scattering)

S(\lambda ,\theta ,h)

用以表示这次散射有多少光被反射到了\theta方向上,h是P点的高度,\lambda是波长。

那么有了散射系数S项+衰减系数T项,我们就能表示P to A的光照强度:

I_{PA}=I_{P}S(\lambda ,\theta ,h)T(\overline{PA})=

=I_{C}S(\lambda ,\theta ,h)T(\overline{CP})T(\overline{PA})

依据此就可以总结出以下4点,我直接截图了文章的总结部分,为了方便后续的回顾~

3.3 对AB每一点进行积分

上面一直都是针对AB上的其中一个P,但实际上计算我们需要把每个P点的贡献都考虑进去。A点接收的光强为I_{A},理论上讲想要遍历AB上的所有点P_{i}是不可能的(AB上有无数个点),想要计算I_{A}该怎么做呢?——积分!把AB划分成无数个ds,计算每个ds合起来的结果:

I_{A}=\Sigma I_{PA}ds

实际上就是求个积分,=\int_{A}^{B}I_{PA}ds 

两点需要解释的,

  • ds越小,取的点就越多,结果也就越精确
  • 在后续的shader中会采取遍历P_{i},叠加结果的方式进行计算

将太阳光考虑成平行光

,对于行星大气效应计算来说,我们可以假设太阳光考虑成平行光,那么下图的每个P点对应的C点接收相同强度、相同方向的光。

那么对上述公式可以进行简化:

I_{A}=\sum I_{PA}ds=

=\sum I_{C}S(\lambda ,\theta ,h)T(\overline{CP})T(\overline{PA})ds

=I_{S}\sum S(\lambda ,\theta ,h)T(\overline{CP})T(\overline{PA})ds

其中,用I_{S}替代了I_{C},表示太阳光强度,这样的话其实\theta也是定值,后面会继续对这个式子进行进一步拓展。

4 Rayleigh散射

由于大气层并不是均匀介质,密度和构成会随着海拔的变化而变化,那就不可能得到一个适合所有情况的计算模型,因此需要针对特定情况提出适合的模型。大多数的行星大气光学效应可以通过Rayleigh散射(Rayleigh Scattering)Mie散射(Mie Scattering)这两种模型来计算实现。

  • Rayleigh散射模拟构成大气层的大部分小分子(氧气、氮气)如何反射光线,我们所看到的天空的颜色(白天的蓝色、日落时的红色)就是由Rayleigh散射决定的
  • Mie散射模拟低层大气中悬浮的大分子(花粉、灰尘)如何反射光线,天空中云朵的白色就是由Mie散射决定的

4.1 计算光线占比

光与小分子发生碰撞后,一部分光穿过粒子继续向前;一部分会反弹回来;小部分会向各个方向发散,当然拐弯90°的占比肯定是最小的。下图展示了Rayleigh散射光的分布:

提到某一特定方向上的散射光占比,就能想到我们的散射系数S项:

I=I_{0}S(\lambda ,\theta ,h)

其中I_{0} 表示光线与分子碰撞前.紧接着S项可以细化为:

S(\lambda ,\theta ,h)=\frac{\pi ^{2}(n^{2}-1)^{2}}{2}\frac{\rho (h)}{N}\frac{1}{\lambda ^{4}}(1+cos\theta ^{2})

其中, \lambda是入射光波长;\theta是散射角;h是当前碰撞点的海拔;n是空气折射率,一般取1.00029;N是标准大气密度,一般取2.504\times 10^{25}\rho (h)是高度为h处的相对大气密度(海平面处为1,随着h的增加不断减少),可以理解成h处真正大气密度/海平面大气密度,一般会使用指数函数进行拟合计算:

\rho (h)=exp\left \{ -\frac{h}{H} \right \}

其中,H=8500m,是大气厚度

分析

从上面的公式可以看出,首先,某些方向接收的光比其他方向多得多。其次,波长影响占比还挺大的(散射系数和波长的4次幂成反比),波长越短意味着被散射的越厉害,例如原文列举了三种波长的结果(如下图,其中S=0代表着海平面的散射),红 --> 绿 --> 蓝依次波长变小,散射系数变大。

这也正说明了:

  • 为什么白天天空是蓝色——蓝光在大气里不断被散射
  • 为什么日落的时天空是红色——阳光要穿透更厚的大气层到达人眼,蓝光都被散射出去了,留下了红光

4.2 计算能量占比

计算完被反射到某一特定角度上的光线占比,接下来就是计算经过散射后入射方向上还剩多少光。我们假设经过一次散射损失了占比为\beta (\lambda ,h)的能量,它也被叫做Rayleigh散射系数

\beta (\lambda ,h)=\frac{8\pi ^{3}(n^{2}-1)^{2}}{3}\frac{\rho (h)}{N}\frac{1}{\lambda ^{4}}

海平面Rayleigh散射系数

上面提到过对\overline{AB}上所有的P积分,如果每个ds都要计算一次\beta (\lambda ,h),计算量将会非常大!为了节省计算成本,往往会提取出数值不会变的部分-->h=0时的海平面Rayleigh散射系数:

\beta (\lambda ,h)=\frac{8\pi ^{3}(n^{2}-1)^{2}}{3}\frac{1}{N}\frac{1}{\lambda ^{4}}

其中,h=0. 

分析

下图是不同颜色(波长)和Rayleigh散射系数的关系图,也是通过\lambda\beta这样的关系我们才知道:光线最初从太阳发出到达大气层时波长分布是很广的,进入大气层后跟大气层中的小分子碰撞发生Rayleigh散射,与波长更长的红光相比,蓝光更容易被散射。

这也能从另一个角度说明了:

  • 为什么白天天空是蓝色——光一到达大气层,蓝光就向各个方向散射出来了
  • 为什么日落时天空是红色——日落时分,太阳光穿过大气层几乎平行于海平面传播,拥有很长一段传播光程,在这个过程中蓝光已经被散射的差不多了,到人眼中就只剩下红光啦!

4.3 Rayleigh相位函数

我们的散射系数S项可以被分为两个部分:

S(\lambda ,\theta ,h)=\beta (\lambda ,h)\gamma (\theta )

\gamma (\theta )=\frac{3}{16\pi }(1+cos^{2}\theta )

  • Rayleigh散射系数项\beta(\lambda,h )——描述散射强度,就是4.2介绍的
  • 散射几何项\gamma (\theta )——用以描述其方向性,表示被散射的能量中有多少比例被反射到了\theta方向上,又被叫做Rayleigh散射的相位函数

其中相位函数的推导过程其实很简单,我直接截图原文:

回顾

第4节我们涉及到了:

散射系数S(\lambda ,\theta ,h) 

Rayleigh散射系数\beta (\lambda ,h)

海平面的散射系数\beta (\lambda ,0)

Rayleigh散射相位函数\gamma (\theta )

5 相对大气密度

我们进入了第四部分A Journey Through the Atmosphere的学习,探讨了\rho (h)的作用。

5.1 指数衰减关系 

理论来讲,密度越大的大气层,发生散射的几率越大。由于大气密度会随着高度急剧降低(对流层的温度和大气压会骤降),Rayleigh散射大部分发生在海拔0-60km的低层大气

上图是密度与海拔之间的关系,几乎呈指数衰减的关系,而之前说了, 

\rho (h)=\frac{density(h)}{density(0)}

而海平面(h=0)的密度为1,那可以近似将低层大气的相对密度视为指数关系,也就是上文已经介绍过的:

5.2 大气厚度H

Rayleigh散射H一般取8500m,Mie散射一般取1200m左右。

6 再谈衰减系数

我想有必要再唤起之前3.1中提到的衰减系数(原谅我直接粘贴3.1写的内容,省的翻了嘿嘿~):

啊!我们好像搞清楚了这个衰减到底是怎么一回事了——指数衰减;每次散射衰减出去的量我们也知道了——\beta (\lambda ,h),那接下来要做的岂不就是补充完整上面计算I_{P}的公式了吗!

开动。

6.1 单一碰撞的衰减

暂且不把散射发生仅仅局限在点C和点P,我们另外定两个参数,原始光照强度I_{0}和经过外散射能量衰减之后剩下的光强I_{1},我们就能得到适用于单一碰撞的能量衰减公式: 

I_{1}=I_{0}(1-\beta )

6.2 一段距离x的衰减

参考[Rendering] 基于物理的大气渲染中将简单和复杂情况分开讨论:

简单情况

这里就需要用到微分了,如果我们认为\beta是个定值的话,那么衰减一段距离x后的剩余能量I就是:

I=I_{0}e^{-\beta }=I_{0}exp\left \{ -\beta \right \}

具体推导可以看看原文的这个cheat sheet:

复杂情况

这里的复杂就是指\beta会随着\lambdah变化而变化,就不是定值了,就需要原原本本写成积分的形式:

I=I_{0}exp\left \{ \int \beta (\lambda ,h)ds \right \}

这也正是符合实际计算的情况。 

6.3 计算衰减系数T

还记得在第2节中一共有SuntoP和PtoA两种情况的外散射,二者都需要考虑能量的衰减,都需要考虑衰减系数T。AlanZucconi的文章是从CtpP的角度计算的,也就是T(\overline{CP}),而乐乐女神的文章是从PtoA的角度计算的,也就是T(\overline{PA})

两个角度都没什么问题,推导过程就不放上来了,直接截图给上结果(公式太多了不想再打一遍hhhh):

同样这里首先给定了\beta是定值的前提,你会发现这个公式可以被简化写成:

其中,\beta (\lambda )是海平面的Rayleigh散射系数;后者是光学距离(Optical Depth)

光学距离

对比6.2中简单情况路径取x,这里是更宽泛的CtoP,这部分的积分可以理解为光学距离,也是后续shader中实际需要进行计算的部分,

D(\overline{CP})=\int_{C}^{P}\rho (h)ds

分析

从上述公式可以看出,

  • 随着高度增加,相对大气密度降低,相对密度Rayleigh散射系数不断减小
  • 海平面的Rayleigh散射系数只跟波长相关,甚至不需要在传播路径上进行积分!

7 计算PtoA光照贡献最终项

第2节中已经探讨过PtoA有内散射+外散射;6.3中我们给出了A衰减系数T项的计算公式;4.3的最后我们把散射系数S项页拆分成了两项。

那么我们最终的计算就可以按照下述步骤逐步精简(图来自乐乐女神那篇文章的推导过程截图~):

到这里,就完成了单次散射数学模型的推导过程啦!接下来会继续进行整个shader部分的学习,建立大气渲染模型。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/105650.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

平安夜,愿大家平安健康!

12月24日平安夜(Christmas Eve),是圣诞节前夕的晚上,寓意着耶稣诞生的夜晚会给世人带来平安幸福。 据《圣经》记载,耶稣诞生的那一晚,在旷野看守羊群的牧羊人,突然听见有声音自天上传来,向他们报耶稣降生的…

华为云桌面能为设计行业提供哪些“黑科技”?

华为云桌面能为设计行业提供哪些“黑科技”? 如今,传统设计模式中的软硬件更新迭代成本高、团队协作低效、资产利用率低和上下游进步不同步等缺陷日益显露,已经不能适应市场需求。华为云桌面携手赞奇科技打造出一个全方位的一站式云上内容制作…

[内网渗透]—GPO批量控制域内主机

GPO GPO(组策略管理),用来存储Active Directory中的策略。 自Windows Server2008开始,GPO开始支持计划任务,便于管理域中的计算机和用户,默认情况下,域用户的组策略每90分钟更新一次,但会随机偏移0-30分钟,域控制器的组策略每5分钟刷新一次 应用场景 在拿到域控后,…

数字硬件建模SystemVerilog-组合逻辑建模(3)使用函数表示组合逻辑

数字门级电路可分为两大类:组合逻辑和时序逻辑。锁存器是组合逻辑和时序逻辑的一个交叉点,在后面会作为单独的主题处理。组合逻辑描述了门级电路,其中逻辑块的输出直接反映到该块的输入值的组合,例如,双输入AND门的输出…

艾美捷Annexin V-FITC凋亡检测试剂盒:简单、快速

艾美捷Annexin V-FITC凋亡检测试剂盒:简单、快速的检测,区分凋亡细胞和坏死细胞。 艾美捷Annexin V-FITC凋亡检测试剂盒基本参数: 中文名称:Annexin V-FITC apoptosis detection kit 英文名字:Annexin V-FITC apopto…

Redis6入门到实战------ 四、Redis配置文件介绍

1.1 单位 配置大小单位,开头定义了一些基本的度量单位,只支持bytes,不支持bit 大小写不敏感 1.2 INCLUDES包含 类似jsp中的include,多实例的情况可以把公用的配置文件提取出来 1.3 网络相关配置 1.3.1 bind 默认情况bind127.0.0.1只能接…

linux基础学习-vim使用方法

直接输入vim,进入的是空白vim基本使用 命令模式:按键代表命令 i/a,切换为编辑模式:,切换到末行模式dd,删掉一行(前面可以加数字)yy,复制光标所在行(前面可以加数字)p&…

一建,PMP,软考,优先考哪个?

需要pmp资料可看封面或在文末获取。 这三者的共同点都是含有“项目管理”知识,可以用于项目管理岗位。 根据容易程度和知识点的基础程度来分,最好按照:PMP,软考,一建的顺序来考。 分别介绍一下三者: 【…

Robust Pose Estimation in Crowded Scenes with Direct Pose-Level Inference 阅读笔记

基于直接姿态级推理的拥挤场景鲁棒姿态估计 NeurIPS 2021 论文链接 代码链接 摘要:拥挤场景下的多人姿态估计具有挑战性,因为重叠和遮挡使得难以检测人体边界框并从单个关键点推断姿态线索(关键点位置)。为解决该问题&#xff0…

[MySQL]-死锁案例-唯一索引上的并发插入

[MySQL]-死锁案例-唯一索引上的并发插入 森格 | 2022年12月 本文是对实际work中遇到的死锁问题的复现,其目的是学会去分析死锁日志、还原日志上下文、理解死锁产生原因、MySQL处理机制(回滚事务的选择),最后到死锁的解决方案的提…

7张图,剖析Redis缓存,文末附Redis工具类源码,建议收藏

一、缓存是什么? 缓存就是数据交换的缓存区,是存储数据的地方,一般读写性能较高。 二、缓存的作用和成本 1、缓存的作用 降低后端负载 提高读写效率,降低响应时间 2、缓存的成本 数据一致性成本 代码维护成本 运维成本 三、…

IDEA中新建找不到Vue Component | IDEA右键Create New Servlet找不到Setvlet

💗wei_shuo的个人主页 💫wei_shuo的学习社区 🌐Hello World ! 解决:IDEA中新建找不到Vue Component 打开IDEA,依次打开 (文件——设置——编辑器——文件或代码模板) 找到右侧&#…

Spring—Spring AOP1

文章目录AOP概念的引入AOP相关的概念1.AOP的概述2. AOP的优势3. AOP的底层原理如何利用AOP对原有业务进行增强利用注解方式切入点表达式AOP相关的术语————————————————————————————————AOP概念的引入 首先我们来看一下登录的原理 如上图所示这…

【云原生 | Kubernetes 实战】16、K8s 配置管理中心 ConfigMap 实现微服务配置管理

目录 一、ConfigMap 概述 1.1 什么是 ConfigMap? 1.2 ConfigMap 能解决哪些问题? 1.3 ConfigMap 应用场景 1.4 局限性 二、ConfigMap 创建方法 2.1 根据字面值创建 ConfigMap 2.2 基于文件创建 ConfigMap 2.3 基于目录创建 ConfigMap 2.4 编…

【大数据系列之MySQL】(二十二):MySQL中的分组查询group by

对于常见的函数都是单行函数,说白了就是一一映射,输入一个值则输出对应的值,但是MySQL中还存在聚合函数就是输入一组值则返回一个值,常见的例如:sum、max等 很多时候需要对数据中的某些字段进行分组,探究每…

%27 CORS 跨域资源共享

1、CORS (跨域资源共享) 由一系列的 HTTP 响应头组成,这些响应头可以决定浏览器是否阻止前端 js 代码跨域获取资源 2、CORS 的响应头 (1)、Access-Control-Allow-Origin res.setHeader(‘Access-Control-Allow-Origin’…

web:常见安全问题

一、XSS XSS(Cross-Site Scripting),跨站脚本攻击,因为缩写和css重叠,所以只能叫XSS。跨站脚本攻击是指通过存在安全漏洞的web网站注册用户的浏览器内运行非法的HTML标签或JavaScript进行的一种攻击。 跨站脚本攻击有可能造成一下影响&#…

记一次赤裸裸的教训:All elements are null

wshanshi:记一次赤裸裸的教训…All elements are null… 一、异常信息 数据库查询统计相关业务,未使用分组group by,仅单独使用聚合函数。如下图所示,使用了SUM()函数。 假如数据库中未匹配到相关数据,结果集用List接…

希尔伯特-包络分析步骤与实例

希尔伯特-包络分析流程 对于齿轮箱振动信号而言,由于存在多对齿轮同时参与啮合,那么,测量得到的信号将可能出现多个以齿轮啮合频率或及谐频为载波频率、轴频为调制频率的幅值调制、频率调制或混合调制的情况,除此之外&#xff…

logback+slf4j日志详解

前言 项目中日志系统是必不可少的,目前比较流行的日志框架有log4j、logback等,可能大家还不知道,这两个框架的作者是同一个人,Logback旨在作为流行的log4j项目的后续版本,从而恢复log4j离开的位置。 另外 slf4j(Simp…