InkSoul/content/computergraphic/高级光线传播与复杂外观建模.md

618 lines
22 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

---
title: "高级光线传播与复杂外观建模"
date: 2022-07-27T22:55:53+08:00
---
## 无偏的光线传播方法(Unbiased light transport methods)
### 双向路径追踪(Bidirectional Path Tracing)
双向路径追踪是对之前路径追踪的扩展,生成两个子路径
从光源打出一些sub-path从摄像机出发也可以生成另外一系列的子路径。双向路径追踪会将这些子路径的端点连接起来形成一条完整的路径
![](../../images/bidirectional_path_tracing_theory.png)
### BDPT适用的场景
图例中左图为路径追踪右图为双向路径追踪适用的都是每个像素32个采样点但可见双向路径追踪能产生更好的效果
![](../../images/eg_bidirectional_path_tracing.png)
原因:
在如图场景中光线追踪难以找到一条带有大量能量的路径。此场景中光源往上方角落打出整个场景都是被间接光所照亮的此时光线从摄像机出发后第一次打到的地方往往是diffuse的导致其不好控制它打到之后能量集中的区域
缺点:
实现较难,相对计算速度慢
### Metropolis Light Transport(MLT)
使用统计学上采样的工具--- 马尔可夫链(当前有一个样本,马尔可夫链可以根据当前样本生成和它靠近的下一个样本,并用这些样本估计函数的值)
与均匀采样不同均匀采样时在a和b之间以均等概率选择一个x且相互独立
给定足够的时间马尔可夫链的蒙特卡洛方法可以生成一系列以任意的函数形状为PDF生成的样本
#### 使用马尔可夫方法的原因
蒙特卡洛方法实际上在采样的PDF(p(x))和要积分的函数(f(x))形状一致的时候是最合适的此时variance是最小的
任何未知的函数都可以通过马尔可夫链的方法生成一系列分布和被积函数形状一致的样本
##### 马尔可夫方法具有局部性
马尔可夫方法是一个局部的方法,当给出一个路径时,可以生成它周围跟它相似的路径
如图中蓝色光路,对该光路做出微笑扰动就可以得到一条新路径
不断在一个path周围产生更多path就可以找到所有的path
![](../../images/MLT_caculate.png)
#### MLT方法与BDPT的效果对比
* 优点
在下图中类似的场景下MLT的效果很好其适合做复杂、困难的光线传播
![](../../images/MLT_pros.png)
Caustics是光线经过聚焦打在游泳池底然后被人眼看见。光线要穿过水的表面凹凸不平还有浪会被聚焦到一系列的地方水面有办法将光线聚焦到一系列的线上。这种情况渲染起来非常困难因为假设游泳池底是diffuse的光线会先经过一个specular的水面游泳池底被我们看见也要经过一个specular这种路径简称SDSspecular-diffuse-specular
* 缺点
MLT难以在理论上预估最后收敛的速度(path tracing中使用的蒙特卡洛积分可以分析variance从而预估渲染收敛的时间)
所有操作都是局部的,有些像素收敛快,有的像素收敛慢,使渲染出来的结果图像看上去比较脏
![](../../images/MLT_cons.png)
不适用于渲染动画,因为不同连续帧的收敛速度不同,画面会产生严重抖动
-------------------------------
## 有偏的光线传播方法(biased light transport methods)
### 光子映射(Photon Mapping)
尤其适用于渲染Caustics和Specular-Diffuse-Specular(SDS)
![](../../images/photon_mapping_theory.png)
#### 实现方法
* 从光源出发光子碰到物体后计算所有反射和折射直到光子打到diffuse的物体上停止此时整理所有光子即可得到光子位置信息
![](../../images/photon_mapping_approach.png)
* 从眼睛或相机开始往各个不同方向打出各种各样的子路径计算反射和折射直到打在diffuse的物体上
* 结合上述两步结果计算局部密度估计
局部密度估计是建立在上面的观察上的,一开始打了很多光子,光子分布在物体表面了,从相机出发的一堆光线也打到物体表面上了,那我们看到的物体表面,光子分布越集中的地方就越亮,越不集中就越不亮,当第二趟打到各种不同的物体表面的时候就要做一个局部的密度估计
具体解法:
* 将所有的光子组织成自上而下的加速结构模式,然后可以迅速定位到一个着色点周围有多少个光子,找它最近的一些
* 计算N个光子所占的面的面积
* 计算密度用光子的数量N除以它们占的面积
![](../../images/photon_mapping_cacul.png)
#### N的取值
如果用很少的光子的数量,就会得到一个很有噪声的图,如果用更多的光子,结果虽然会好一些,但是得到的结果会糊
![](../../images/photon_mapping_biased.png)
##### 产生取值问题的原因(有偏的原因)
* 计算密度时我们认为密度时当前这个点的周围取一个微小的面积dA,它里面有多少个光子
$$dN/dA$$
* 实际计算密度为给定光子数计算实际面积
$$\delta N/\delta A$$
* 正常情况下两者接近但不同(光子数量和周围覆盖面积都是有限的)
$$dN/dA != \delta N/\delta A $$
因此密度的估计并不正确dA无限小时才是正确的计算
当实际的面积足够小(打出的光子数量足够多),结果就越接近于正确
所以该方法是有偏(biased)但一致(consistent)的
有偏(biased)得到的结果相比正确的结果只要有任何一点的模糊blurry就是有偏的
一致(consistent):虽然有模糊,但是只要样本足够多,就会最后让它收敛到不模糊的结果
### Vertex Connection and Merging(VCM)
双向路径追踪和光子映射的结合
BDPT中生成两个sub-path再将端点连起来如果有的path满足下述性质就用光子映射将虚线圆内的两个sub-path的贡献结合在一起
性质左边path和右边path的端点在同一个面上此时可认为其中一半是光子
往往用于电影行业渲染
![](../../images/vertex_connection_and_merging.png)
### 实时辐射度算法(Instant Radiosity(IR))
有时又称为多光源算法(many-light approaches)
之前的光线传播往往不区分光的来源(反射或自己发出),实时辐射度算法中就将已经被照亮的区域认为是光源,用于照亮其他区域
#### 计算方法
* 从光源打出很多光线子路径(light sub-path),这些光会停在某些地方,认为停的位置就变成了新的光源(VPL)
* 看到如下图中的着色点后就用新的光源来照亮(相当于实际考虑光线弹射两次)
![](../../images/instant_radiosity.png)
#### 优缺点
* 优点(下图左)
快速,往往会在漫反射场景中有良好的效果
* 缺点(下图右)
在窄的缝隙或接缝处会出现发光
VPL不能做glossy的物体
窄缝发光问题与距离平方向有关在计算light sampling时更改立体角的采样为对面积的采样所以产生了面积乘以cos除以两个点之间的距离的值当两个点距离极近时就会得到一个非常大的结果
![](../../images/instant_radiosity_eg.png)
## 高级外观建模
### 散射介质/参与介质(participating media)
定义在空间中而非简单的表面上,如:
![](../../images/participating_media_fog.png)
![](../../images/participating_media_cloud.png)
--------------------
光在前进的路径上如果穿进了散射介质则会发生散射和吸收
1. 如云中间有光源则其本身会发光
2. 光线路径上如果有很多小的晶体则会把光线随机反射到其他方向上去
3. 传播的过程中也可能会接收到从其他方向反射过来的光
![](../../images/participating_media1.png)
#### 散射计算
类比与物体表面物体为diffuse的才会认为光线被均匀地反射到各个不同的方向上去散射介质也是相同任何一点都会发生散射使用Phase Function(相位函数)定义散射计算
下图相位函数决定了散射的方式和方向(与BRDF类似BRDF决定如何反射相位函数决定如何散射)
![](../../images/participating_media2.png)
#### 散射介质渲染
光线在散射介质内部能传播多远是有这个介质的吸收能力决定当传播停止后再考虑光线的反射方向与光在物体表面的弹射类似只是中间的任何一个点都有可能会发生方向的改变。但始终会找到一个path在将弹射点和光源相连计算整个路径的贡献(不考虑Rendering equation因为渲染方程描述物体表面与物体的作用而非体积间的相互作用)
#### 应用
超能特工队
![](../../images/participating_media_application1.png)
游戏:刺客信条
![](../../images/participating_media_application2.png)
巧克力(流体模拟)
![](../../images/participating_media_demo.png)
### 毛发建模(Hair/fur/fiber)缩写BCSDF
如下图中所示,头发往往是一根一根的,若梳理平整还可暂且视为表面,但大多数情况下,头发都是飘散的
可见头发会有两种高光,一种无色发白,一种有色
![](../../images/hair_appearance.png)
#### 高光计算
如下图中的模型,一根光线打到圆柱上(毛发模型)会散射出一个圆柱,且同时有光线散射到各个方向上
* kajiya-Kay Model
![](../../images/kajiya-kay_model.png)
但表现却不太符合现实与Blinn-Phong类似
![](../../images/eg_kajiya-kay_model.png)
* Marschner Model
该模型广泛使用,考虑了光线打到圆柱上的情形
1. 有部分光被反射记为R
2. 一部分会穿透到头发里发生折射可记为T一根光线要穿透一根头发需要穿透两次因而产生TT的光线传播方式
3. 光线发生一次穿透进入头发内部在头发内壁上发生一次反射后返回返回时再发生一次穿透记为TRT
![](../../images/marschner_model1.png)
在这一模型中(下图左),我们会将头发认为是一个玻璃的圆柱(总体可认为是扭曲,但局部必定是直的)包含两种结构外层cuticle(表层)内层cortex(皮层)
头发内部存在有色素,光线穿透后会有部分被吸收再向外传播
![](../../images/marschner_model2.png)
该模型也考虑了三种光线和模型之间的相互作用(上图右)
将计算结果综合后可得到一个十分拟真的效果
![](../../images/eg_marschner_model.png)
当然上述过程只定义了单根头发与光线的相互作用,与多根头发作用时需要额外计算多次散射
多次散射:光线打到一根头发穿透两次再和第二根,第三根$\dotsb$直到光线进入摄像机(被看见),计算量庞大
应用:
最终幻想15(ff15)
![](../../images/hair_appearance_model_application1.png)
疯狂动物城
![](../../images/hair_appearance_model_application2.png)
-------------------------
### 动物毛发的计算
人的毛发计算模型往往不能用于动物毛发计算,如下图,左侧为人的毛发模型计算结果,可见其不足以描述光线与动物毛发的相互作用
![](../../images/fur_appearance_as_human_fur.png)
* 生物结构
人的毛发与动物毛发的共同点:
都有三个结构cuticle(表皮)、cotex(皮层)、Medulla(髓质,复杂内部结构,光线进入后会反射到各个方向)
不同点:
动物毛发中的髓质更大,光线进入后更容易发生反射
![](../../images/human_fur_vs_animal_fur.png)
由此可见Marschner Model中忽略髓质在动物毛发计算中并不适用
![](../../images/importance_of_medulla.png)
有无髓质的对比
![](../../images/importance_of_medulla2.png)
#### 双层圆柱模型(Double Cylinder Model)
该模型中加入了对髓质的精确描述
![](../../images/double_cylinder_model.png)
光线在打到表面后依旧会发生反射穿过结构后也可能无法到达髓质或是到达后没有发生反射与Marschner Model中一样存在R、TT、TRT
同样会有部分光穿过髓质的时候发散到各个方向上去(TTs),TRT也相同在穿过髓质的过程中两次都有可能被散射形成TRTs
![](../../images/double_cylinder_model_lobes.png)
可以使用5个不同的分量在原来的3个模型上加上2个散射的结果
![](../../images/double_cylinder_model_lobes2.png)
##### 应用
下图中的仓鼠由60万根毛发组成在每像素中有1024个采样点的采样率下每帧需要渲染36.9分钟
![](../../images/60000_fur_fibers_hamster.png)
猩球崛起
![](../../images/double_cylinder_model_application1.png)
狮子王
![](../../images/double_cylinder_model_application2.png)
#### 颗粒材质(Granular Material)
如香料、盐、糖等等
![](../../images/granular_material.png)
计算量很大,但可以做些简化
比如一个沙子城堡,每一单元上由不同石子构成,各自成分占比也可得出,渲染结果在离得近的时候可以看到一粒一粒的,离得远的情况下就会是一个沙丘
![](../../images/granular_material_1.png)
![](../../images/granular_material_application1.png)
![](../../images/granular_material_application2.png)
--------------------
### 表面模型(Surface Models)
#### 半透明材质(Translucent Material)
翻译有些许错误Translucent不应为半透明semitransparent才是半透明两者存在些许差别
光线在穿过透明介质时会涉及到吸收,本身还涉及到散射,说明光线可以从某一个地方进入这一个表面再从另一个地方出这个表面
即并非沿着一个方向传播并被吸收,可以被传导到其他方向上去
![](../../images/translucent_material_jade.png)
![](../../images/translucent_material_jellyfish.png)
在物理上,常常认为光线在某一个点进入某一个表面,在里面发生了大量散射,从另一个点钻出
![](../../images/subsurface_scattering.png)
#### 次表面散射(Subsurface Scattering)
出于描述上述反射过程的目的,将其定义为次表面散射
##### 次表面散射可理解为对BRDF概念的延伸
BRDF: 光线打到这个点,并从这个点出来,所有作用都发生在一个点上
BSSRDF可理解为吧BRDF的概念延伸到从一个点以任意方向进来再从任意一个其他的地方以任意方向出去
![](../../images/BRDF_vs_BSSRDF.png)
* 定义
和BRDF概念一致只是在中间加入了一个Subsurface Scattering,次表面反射对应的BSSRDF规定了光线从哪个点和方向进从哪个点和方向出
$$S(x_i,\omega_i,x_o,\omega_o)$$
* 渲染方程
需要额外考虑从各个方向进入其他点的光,因此需要对方向和面积进行积分
$$L(x_o,\omega_o) = \int_A\int_{H^2} {S(x_i,\omega_i,x_o,\omega_o)L_i(x_i,\omega_i)\cos\theta_id\omega_idA}$$
* Dipole Approximation
以上算法稍显复杂,我们可以采用一下方式进行简化
光线打到物体上与物体底部出现光源类似,会从底部照亮着色点周围的一片,为了物理上的真实,推出一个光源不够,还要对应上方有一个光源,还要对应上方存在一个光源,相当于有两个光源照亮周围着色点的一块
![](../../images/dipole_approximation.png)
* 效果
BRDF类石膏材质效果
![](../../images/eg_BRDF_caarve.png)
BSSRDF,类大理石
![](../../images/eg_BSSRDF_carve.png)
如图,BRDF渲染的皮肤效果显得干燥BSSRDF则能有很好的效果
![](../../images/BRDF_vs_BSSRDF.png)
* 应用
人脸渲染
![](../../images/BSSRDF_application.png)
### 布料(cloth)
* 布料组成
由一系列缠绕的纤维构成,有几个不同的层级
纤维(fiber)是最基础的,纤维可以缠绕成不同的股(ply),不同的股再经过不同的缠绕形成线(yarn)
![](../../images/cloth_yarn_and_ply.png)
Woven or Knitted(编织或针织)
一种是机器织的,一根压一根的,像桌布之类的做法
一种是手工织的,像打毛衣一样
对于布来说,它是纤维缠绕而成的,所以算它的表面模型就非常麻烦,因为与针织或纺织的方向有关
可以通过编织图案计算BRDF模型
* 问题
布料模型大多数并非在一个表面上难以使用BRDF来表示
![](../../images/render_as_surface_limitation.png)
* 解决方案1
所以将织物认为是在空间中分布的体积,然后可以将其划分成超级细小的格子,每一个格子里面大概知道纤维的朝向、分布、复杂程度等等,那就可以将这些性质转化成光线的吸收和散射。将这些性质转换成对云烟雾这种反射介质的渲染,不再将布料当成一个面,而是当成一个体积,体积中任何一个微小的块都知道它的性质
计算量庞大,计算时间长
![](../../images/cloth_render_as_participating_media.png)
* 解决方案2
布料本身是纤维,渲染每一根纤维也能产生很好的效果,计算量同样惊人
![](../../images/cloth_render_as_actual_fibers.png)
* 应用
![](../../images/cloth_application.png)
#### 有细节的材质(Detailed Appearance)
如下图,渲染结果不错但并不真实,因为结果过于完美
![](../../images/detailed_appearance_motivation.png)
真实情况下车上会有高光,高光周围会有类似于蜘蛛网结构的划痕。鼠标上则会有由很多小的凸起形成的高光
![](../../images/detailed_appearance_motivation1.png)
下图由微表面模型渲染得出,结果完美但不真实
![](../../images/detailer_appearance1.png)
加入了实际可能产生不完美的地方
![](../../images/detailer_appearance2.png)
模拟被同方向刷出的各项异性材质
![](../../images/detailer_appearance3.png)
* 微表面模型中的法线分布
微表面模型中重要的是微表面的法线分布,描述分布时,往往使用非常简单的模型(正态分布、高斯),得到的自然是没有什么细节的结果(法线分布没有体现各种各样的变化和细节)
![](../../images/distribution_of_normals.png)
在蜗牛壳上贴了一个大的法线贴图,每个面都可以产生高光,所有高光形成一起就可以变成一个大高光
![](../../images/define_detail1.png)
Metallic flakes:可替换别的模型,例如很多人在车漆中添加的亮片,亮片会形成很多不同的方向,不同方向会形成不同的反光
![](../../images/different_details2.png)
虽然能够定义各种细节,但渲染十分困难,需要渲染接近一个月才能得到这个结果
![](../../images/details_apperance_3.png)
* 渲染困难的原因:
认为每一个微表面是一个镜面,如下图场景中有一个针孔摄像机和一个点光源,那从摄像机打根光线过去,打到哪个表面,就可以知道它的法线,也就可以知道它的镜面反射方向,所以也就很难通过反射的方式让光线打到光源上。从光源打过来也是同理,打到一个微表面,并且知道如何反射,但就是反射不到摄像机上去
![](../../images/difficult_path_sampling_problem.png)
解决:
由于一个像素会覆盖很多的微表面,如果将一个小的范围内的微表面的法线分布计算出来便可代替原本光滑的分布并用在微表面模型里
![](../../images/BRDF_over_a_pixel.png)
* P-NDF的形状
如果考虑像素覆盖的范围,就可以得到各种各样神奇的法线分布(NDF)。可以想象一个像素覆盖了非常多的微表面,那这些微表面自然会显示出一些统计学的规律,那如果覆盖的范围小,就会显示出一些很独特的性质,法线分布就会看上去很有特点
![](../../images/p-NDFs_have_sharp_features.png)
不同类型的法线贴图会引起不同的法线分布
![](../../images/p-NDF_sharps.png)
* 例子和应用
![](../../images/blender_detail.png)
![](../../images/ocean_wave_detail.png)
游戏中的应用-古墓丽影中的雪地
![](../../images/detailed_material_application.png)
#### 波动光学
引入细节后,还用几何光学解释就不对,物理上当物体非常小,小到和光的波长相当时,就不能假设光线是沿直线传播的,而必须假设这个光是一个波,这就会涉及到衍射和干涉现象的发生
![](../../images/wave_optics_application.png)
比如在黑屋里,用点光源照亮一个金属片,会在本身只有一个颜色的金属片上看到各种各样的颜色
![](../../images/Observations_1.png)
![](../../images/Observations_2.png)
白光照射后反射出来的便为白光,如果不是白的就一定有波动光学(Wave Optics)
波动光学得出的BRDF与几何光学的BRDF很像但具有不连续的特点(光会发生干涉,会引起部分区域加强或减弱)
![](../../images/detailed_material_under_wave_optics.png)
以下为波动关系渲染的结果
![](../../images/wave_optics_application.png)
![](../../images/wave_optics_application%202.png)
--------------------
### 程序化材质生成(Procedural Appearance)
用一定的方式指导生成,无需真正地生成,可以动态查询
如下图可定义各种各样的花纹,花瓶打碎后可见花瓶内部纹理,可定义一个三维纹理
![](../../images/procedural_appearance1.png)
存储量在三维下会变得很大可利用noise函数(x,y,z)给定任何x,y,z可得到对应的值,这样可以实现什么时候用就什么时候去查
![](../../images/procedural_appearance2.png)
procedural更多意味着不生成需要时再查询
* 车上的锈
可生成一系列噪声,可对噪声做出一系列操作(二值化(binary noise))铁锈往往是不同区域有不同分布这个噪声如果为0到1当函数值大于0.8时认为是1小于0.8就认为是0
![](../../images/procedural_appearance3.png)
应用最广泛的是柏林(Perlin)噪声
* 生成地形
![](../../images/procedural_appearance4.png)
* 生成海浪
![](../../images/procedural_appearance5.png)
* 生成木头纹理
![](../../images/procedural_appearance6.png)
常用Houdini来做程序化材质且是先程序化生成再拿去使用
-------------------