本文主要参考了冯乐乐老师的《Unity Shader入门精要 》一书,再加上网上一些参考资料而写。
笔者使用的是 Unity 2018.2.0f2 + VS2017,书中使用的是 Unity 5.2.1 ,由于版本更新,所以本文的一些shader代码会与原文中有一些差异。建议读者使用与 Unity 2018 相近的版本,避免一些因为版本不一致而出现的问题。
从宏观上说,渲染包含了两个部分:①决定一个像素的可见性 ②决定一个像素上的光照计算。 而为了方便的计算光照计算,我们会采用光照模型
本文着重记录的是光照模型的作用原理,因此本文中实现的Shader均不可直接运用于项目之中,而在往后的篇章,我会给出包含了完整光照模型的,可真正使用的Shader
目录
一. 我们如何看见事物
我们在描述一个物体外貌时时常会说 “这物体是什么什么颜色的”,而在中学时,我们学的物理知识告诉我们,如果你看到这个物体是红色的,那就说明这个物体反射了很多红色光的波长,而吸收了其它颜色的波长。如果一个物体是黑色的,则说明这个物体吸收了大部分的波长。而这种物理现象也是我们在Shader要处理的问题。简单的说,可以分成这3个现象。
- 光源发射出光线
- 光线与物体相交,部分光线被吸收,部分光线被散射
- 摄像机吸收了部分光线,产生图像
1.1 光源
既然有光,那就必定有光源。在渲染中,我们通常把光源当做一个点,用
表示光源方向。同时,为了量化光源发射出来的光,我们使用 辐照度(irradiance)来量化光。一般对于平行光,它的辐照度可以通过计算在垂直于
的单位面积上单位时间内穿过的能量来得到。
在计算光照模型时,我们需要知道一个物体表面的辐照度,但是物体表面往往不是和
垂直的,所以为了得到这种情况下辐照度,我们可以通过计算光源方向
和表面法线
之间的夹角的余弦值来得到。而且,这里默认方向矢量的摸都为1
左图中,光垂直照射到物体表面,所以光线之间的垂直距离保持不变;右图中,光是斜照到物体表面,所以光线间距离为 d /
θ ,因此单位面积上接收到的光线数目比左图少。
因为辐照度是和照射到物体表面时光线之间的距离 d /
θ 成反比,即与
θ 成正比。
θ 可以用光源方向
和表面法线
点积得到。
1.2 吸收和散射
光源与物体相交一般会有两个结果:散射(scattering)和 吸收(absorption)。
散射只改变光线方向,不改变光线密度和颜色。而吸收只改变光线密度和颜色,不改变其方向。光想在散射后一般有两种方向:
① 散射到物体内部,这种现象称为 折射(refraction)或 透射(transmission)
② 散射到外部,这种现象称为 反射(reflection),对于不透明物体,折射进入物体内部的光线还会继续与内部的颗粒相交,同样会发生折射和反射现象,而此时从物体表面重新射出的光线将具有和入射光线不同的方向分布和颜色。
折射的光线会在物体内部传播,有一部分会重新从表面发射出去
所以就产生了两种散射方向。为了区分这两种方向,我们在光照模型中使用了不同的部分来计算:
I . 高光反射(specular)部分表示物体表面是如何反射光线的
II . 漫反射(diffuse)部分表示有多少光线会被折射,吸收和散射出表面
我们引入 出射度(exitance)这个概念来描述出射度,而辐照度和出射度是满足线性关系的,而它们的比值就是材质的漫反射和高光反射属性。
在本文中,我们是假设漫反射部分是没有方向性的,即光线在所有方向上是平均分布的。同时,我们也只考虑某一个特定方向上的高光发射。
1.3 着色
根据 ① 材质属性(如漫反射,高光反射等属性) ② 光源信息(光源方向,光照强度等),使用一个等式去计算沿某个观察方向的出射度的过程,这个过程就叫做着色(shading)。而这个等式也称为 光照模型 (Light Model),而光照模型也这是本文所重点探讨的。光照模型不止一种,不同的光照模型对应着不同的作用。
1.4 BRDF 光照模型
当光线从某个方向照射到一个物体表面时,有多少光线被反射?反射方向有哪些?而 BRDF(Bidirectional Reflectance Distribution Funtion)回答了这些问题。当给定模型表面上的一个点时,BRDF 包含了对该点外观的完整描述。简单的说,BRDF可以从给定的入射光线的方向和辐照度计算出某个出射方向上的光照能量分布。本文涉及的光照模型均是经验模型,并不能真实地反映物体和光线之间的交互。但即便如此,经验模型也被应用了多年。
二. 标准光照模型
1973年,著名学者Bui Tuong Phong提出了标准光照模型的基本概念https://en.wikipedia.org/wiki/Bui_Tuong_Phong
标准光照模型只关注直接光照,简单得说就是 直接从光源发射出来照射到物体表面后,经过一次反射后直接进入摄像机的光线。基本方法是把进入摄像机的光线分成4个部分,每个部分分别有一种分发来计算其贡献度
- 自发光 用
表示,意义为:当给定一个方向时,物体表面会往这个方向发射多少辐射量。 在没有全局光照的情况下,自发光不会照亮周围的物体,而仅仅是自身看起来更亮了。
- 高光反射