首页 > 其他分享 >【Unity/大气渲染】单次散射的原理和简单实现

【Unity/大气渲染】单次散射的原理和简单实现

时间:2023-04-14 12:23:28浏览次数:44  
标签:right cdot 散射 Unity PA CP 单次 left

这篇随笔将会简单实现一个基于物理的相对真实的大气渲染效果

如下图,太空中的星球、相对真实的天空盒

如果没有大气,太阳光没有直接照射到的地方将会是一片黑暗

而我们能从太空中看到星球表面泛起的蓝光,日出时的美丽景色,都得于太阳光在大气中的散射

地球的大气中充斥着诸如空气分子,小水滴,尘粒等微小分子

当太阳光遇到这些分子时,会改变辐射方向,我们将这种现象叫做散射

(通常辐射能不会转化为热能,而只是改变方向)

图1

在现实中,散射可能会发生无数次,介于性能,我们只实现一次散射就可以得到一个相对不错的效果

下面是单次散射的简单原理

我们首先思考一下太阳光如何通过大气进入我们的眼睛

假设我们所在的位置为 A点

现在给定一个观察方向,我们看向天空,视线与大气顶部相较于B点,而迎着我们视线方向的太阳光都会进入我们的眼睛

(实际上我们知道,我们的视野不是一条线,而是可以假定为一个视锥体,所以一副画面将会有许多条视线方向充斥着视锥体)

由于我们只计算单次散射,所以只需要计算刚好散射到我们视线方向的太阳光就可以了

图2

但其实!有一件事情

这看似只有一次散射,但散射实际上时时刻刻都在发生,太阳光每向前传播一点就会遇到大气粒子然后发生散射

也就是说光线在这条路径上不断发生着散射,而散射就会造成太阳光向其他方向分散,就可能不会进入我们的眼睛

而单次散射的实际意义是 只计算光的一次转向,两次之后转向的光我们统一按照衰减计算

所以固定方向光线的衰减就是类似的过程,光线在传播过程中不断地被散射,越来越弱

 

因此太阳光进入我们眼睛的整个流程是这样的

 对于给定的视线方向,太阳光沿着固定方向 LightDir 入射,在 CP段 不断被散射衰减,然后与 AB段 形成无数个交点,我们将其成为Pi(i = 1,2....),在 P处 散射一部分光刚好迎着我们的视线方向进入我们的眼睛A点,PA段也不断被散射衰减

·  

为什么要首先给定视线方向,其实这是适应shader的编写,因为我们写shader都是对顶点和片元操作

而模型通常是空心的,我们不会直接取到球中的一个点,而是球最外层的一个点,也就是我们的B点

而我们也知道A点(摄像机坐标),所以直接计算视线方向上散射进摄像机的光

 

在这里我会简单说一下shader计算的具体思路,方便理解公式的推导

我们知道太阳光和 AB段 形成了无数个交点 Pi,在每个交点 Pi 上都有一部分光被散射进摄像机

介于性能,我们不会全部计算,而是将 AB段 均分成 N 份,也就是采样 N 次,计算每个采样点散射进摄像机的光

具体思路为,对于 球模型 的一个顶点,我们将其定为 B点,计算 AB段 的长度,除以采样数量 N,得到 步长step

我们还可以得到 向量AB,进而得到 方向向量AB,乘以 步长step 就可以得到一步前进的向量

从 摄像机A点 开始,循环 N 次,每次计算一个 采样点P,再加上步长step得到下一个采样点,累加得到一条视线方向最终的散射结果

然后 顶点 / 片元 着色器会遍历顶点输出最终的画面效果

下面是公式的简单推导(不涉及具体证明)

我们首先计算到达 P点 的光强,由于只计算在 P点 的一次转向所以 CP 段只计算光的衰减

设定 C点 的入射光强为 Ic,到达 P点 的光强为 Ip

图3

\(Ip=Ic\cdot T\left(CP\right)\)

T(CP) 为光线从 C点 到 P点 的衰减方程,我们又将其叫做 透射函数

到达 P点 后,设定到达 A点 的光强为 Ia

\(Ia=Ip\cdot S\left(CP,PA\right)\cdot T\left(PA\right)\)

T(PA) 和上面一样,是 PA段 的透射函数

S(CP, PA) 是沿 CP方向 传播的光向 PA 方向散射的散射函数

就是从 C点 到达 P点的光 又有多少刚好散射到 PA 方向

简单地代换一下我们就可以知道从 C点 到 A点 的光强

\(Ia=Ic\cdot S\left(CP,PA\right)\cdot T\left(CP\right)\cdot T\left(PA\right)\)

而我们知道 AB段 上有 N 个 P点

所以对于一个顶点,最终到达 摄像机的光强

\(Ia=Ic\cdot\sum_{n=1}^{N}S\left(CP,PA\right)\cdot T\left(CP\right)\cdot T\left(PA\right)\)

也就是说实际上我们只需要知道透射和散射函数就可以了

于是就轮到解释一些非常简单的物理公式

因为我们知道透射衰减实际上也是散射,我们只需要将所有角度的散射加起来(求球面积分)就可以得到衰减

所以来了解这次涉及到的两种主要散射,瑞利散射(Rayleight)和米氏散射(Mie)

 

瑞利散射,指光线在遇到比自身波长小的粒子时发生的散射,而且会更多地散射波长短的光,比如蓝光,所以我们能够看到地球表面有一层薄薄的蓝光

米氏散射,指光线在遇到和自身波长差不多或大一些的粒子时发生的散射,对所有所有波长的光都会同等散射,并且大部分光都会沿着原来原来的方向传播

所以光路的形成得于米氏散射,比如我们熟悉的丁达尔效应

 

瑞利散射函数公式

\(S\left(λ,θ,h\right)=\frac{\pi^{2}\left(n^{2}-1\right)^{2}}{2}\cdot\frac{ρ\left(h\right)}{H_{0}}\cdot\frac{1}{λ^{4}}\left(1+\cos^{2}θ\right)\)

其中 n 为空气折射系数 1.00029

ρ(h) 为密度比率,在海平面为 1,随高度增加指数下降

H0 为标准大气的分子数密度 2.504*10^25

而我们对散射函数进行球面积分,就得到了透射函数

\(β\left(λ,h\right)=\int_{0}^{2\pi}\int_{0}^{\pi}S\left(λ,θ,h\right)\cdot\sinθ\cdot dθ\cdot dφ=\frac{8\pi^{3}\left(n^{2}-1\right)^{2}}{3}\cdot\frac{ρ\left(h\right)}{H_{0}}\cdot\frac{1}{λ^{4}}\)

 

下面我们对透射函数和散射函数进行拆解,这是计划的一部分(为了方便计算和编写)

 

标签:right,cdot,散射,Unity,PA,CP,单次,left
From: https://www.cnblogs.com/IslandZ/p/17316140.html

相关文章

  • Linux_ubuntu_How to resize Launcher in Unity 2D
    via: http://www.dedoimedo.com/computers/ubuntu-unity-2d-resize-launcher.html ChangeUnity2DconfigurationfilesTheconfigurationfilesarelocatedunder /usr/share/unity-2d/shell.Youwillneedsudotoeditthefilescontainedtherein.Youshouldalsocr......
  • 定制 Unity BuildIn Package
    目标&背景在内网Package管理这篇文章中我们提到了如何自建npm工具包,整合unity官方package和公司自定义的私有package此时就会碰到一个新的问题,如果我们修改了unity内建的package时,就必须要考虑如何适配的问题比如:项目中自定义的UI框架中,需要对现有的com.u......
  • Unity Andorid 多渠道管理
    版本修订记录修订日期1.0.0Init2023-2-41.0.1增加IL2Cpp编译2023-2-25目标&背景一般来说手游开发到一定进度,一定会涉及到大量的native交互问题,比如重启App、拉起支付、观看广告等等,而这些大部分情况下都是第三方提供的nativeSDK,而且有时候游戏需......
  • Unity3D之资源管理——Addressables管理详解
    Addressables是可寻址资源系统提供了一种简单的方法通过“地址”加载资源。简化资源包的创建和部署的管理开销。是在AssetBundle之后的另一种资源管理方式。Addressables下载安装设置1.用PackageManager进行安装AddressableSystem,我这里Unity3D是2019.3.11版本,Addressable最新已经......
  • CommunityToolkit.Mvvm8.1 viewmodel使用-旧式写法(2)
     本系列文章导航https://www.cnblogs.com/aierong/p/17300066.htmlhttps://github.com/aierong/WpfDemo(自我Demo地址)  0.说明CommunityToolkit.Mvvm8.1有一个重大更新的功能:源生成器功能,它极大简化我们的mvvm代码但是本篇先总结一下原写法,下篇再总结源生成器......
  • Unity框架:JKFrame2.0学习笔记(二)——Singleton单例模式
    Singleton单例模式的基类,不用mono的类可以直接继承源码namespaceJKFrame{///<summary>///单例模式的基类///</summary>publicabstractclassSingleton<T>whereT:Singleton<T>,new(){privatestaticTinstance;public......
  • wpf CommunityToolkit.Mvvm8.1 MVVM工具包安装引用指南
    CommunityToolkit.Mvvm包(又名MVVM工具包,以前名为Microsoft.Toolkit.Mvvm)是一个现代、快速且模块化的MVVM库。它支持:.NETStandard2.0、.NETStandard2.1和.NET6(UIFramework不支持) 文档地址:https://learn.microsoft.com/zh-cn/dotnet/communitytoolkit/mvvm/......
  • Unity-浏览360图片
    1、导入360全景图,去掉GenerateMipMaps的勾选,防止出现接缝线。2、新建Sphere样式的空对象,坐标与Camera相同3、Camera的ClearFlags设置为:SolidColor4、新建材质球 Shader选择 Skybox/Panormic5、把全景附给材质球,再把材质球托给Sphere的空对象6、相机做一个自......
  • Unity Shader之自定义GUI
    可参考:https://zhuanlan.zhihu.com/p/384871087效果如下:转载请注明出处:https://www.cnblogs.com/jietian331/p/17296261.html......
  • unity xorpay使用HTTP中post方式请求调用接口
    结合:https://www.cnblogs.com/guangzhiruijie/p/16985533.htmlunity自带的UnityWebRequest提供了构成HTTP请求和处理HTTP响应。构造函数:publicUnityWebRequest();publicUnityWebRequest(Uriuri);publicUnityWebRequest(stringurl);publicUnityWebRequest(Uriuri,......