二、标准光照模型
在1973年,由著名学者裴祥风(Bui Tuong Phong)提出了标准光照模型背后的基本理念。标准光照模型只关心直接光照——直接从光源发射出来照射到物体表面后,经过物体表面的一次反射直接进入摄像机的光线。
- Phong光照模型:使用漫反射和高光发射的和来对反射光照进行建模的基本思想,基于经验的计算高光反射的方法
- Blinn-Phong光照模型:对Phong光照模型的改进,简化了计算且在某些情况下计算更快
- 兰伯特(Lambert)光照模型:计算漫反射光照
环境光
自发光
漫反射
高光反射
这里的高光发射是一种经验模型,并不能完全符合真实世界中的高光发射现象。它可用于计算那些沿着完全镜面反射方向被反射的光线,这可以让物体开起来有光泽,例如金属材质。
计算高光反射需要知道的信息比较多,如表面法线()、视角方向(
)、光源方向(
)、反射方向(
)。
反射方向可通过表面法线、光源方向信息计算得到。假设这些矢量都是单位向量。
反射方向:
反射方向推导过程:
- 由光学反射定律(光学的基本原理)可知,入射光线方向、法线方向、反射光线方向位于同一平面,入射角等于反射角。
- 根据点积公式公式可知,光源光线在法线方向上的投影与反射光线在法线方向上的投影相等。假设投影向量为
,可得如下等式:
- 根据以上关系,通过使用向量的减法可得如下等式:
Phong光照模型高光反射计算公式:
:材质的光泽度(gloss),也被称为反光度(shininess)。它用于控制高光区域的“亮点”有多宽,值越大,亮点越小。
:材质的高光发射颜色,它用于控制该材质对于高光反射的强度和颜色。
:光源的颜色和强度。
- 截取
的结果在
的范围内。
Phong光照模型的问题:
- 镜面反射在某些条件下会失效,特别是当发光属性值较低的时候,对应一个非常大的粗糙的镜面区域。镜面区域边缘迅速减弱并截止。
- 出现上述问题的原因在于视线向量和反射向量的角度不允许大于90度。如果大于90度,点乘的结果就是负数,镜面的贡献成分就会变成0。不同于漫反射测量光源和法线之间的角度,镜面反射测量的是视线和反射方向向量的角度。
Blinn-Phong光照模型:
Blinn-Phong光照模式很大程度上与Phong光照模型是相似的的,是对Phong光照模型的改进。它放弃了使用反射向量计算镜面反射,取而代之的是一个被称为半程向量(halfway vector)的单位向量,它在视线方向和光线方向的中间。半程向量和表面法线向量越接近,镜面反射的成分越大。
半程向量和表面法线之间的夹角永远不会超过90度(除了光源远远低于表面的情况)。
Blinn-Phong光照模型与Phong光照模型产生的反射稍稍有不同,但看起来会更加可信,特别是发光值参数比较低的时候。
半程向量的计算方法:
通过将光源方向向量和视角方向向量相加,然后将结果取归一化。
引入半程向量计算后的结果
Blinn-Phong光照模型高光发射计算公式:
Blinn-Phong光照模型与Phong光照模型的镜面反射的区别:
- Blinn-Phong测量的是法线和半程向量之间的角度,而半程向量是视线方向和反射向量之间的夹角。
- Blinn-Phong比Phong着色性能更高,因为不必计算更加复杂的反射向量。
- 半程向量和表面法线之间的角度经常会比视线和反射向量之间的夹角更小。结果就是,为了获得和Phong着色相似的效果,必须把发光值参数设置的大一点。通常的经验是将其设置为Phong着色的发光值参数的2至4倍。
- Blinn-Phong的镜面发射成分要比Phone锐利一些。这通常需要使用一点小技巧才能获得使用Phong着色所看到的效果。但是Blinn-Phong着色的效果比Phong着色通常更加真实一些。
参考链接:LearnOpenGL-高级光照
Blinn-Phong光照模型的局限性
- 很多重要的物理现象不能表现出来,例如:菲涅尔发射(Fresnel reflection)。
- 各项同性(isotropic):当固定视角和光源方向旋转这个表面时,反射不会发生任何改变。某些表面是具有各项异性(anisotropic)反射性质的,例如拉丝金属、毛发等。
逐顶点、逐像素
哪里计算光照模型?
- 顶点着色器中计算——逐顶点光照(per-vertex lighting)
- 片元着色器中计算——逐像素光照(per-pixel lighting)
逐顶点光照:
也被称为高洛特着色(Gouraud shading)。在每个顶点上计算光照,然后在渲染图元内部进行线性插值,最后输出成像素颜色。
逐像素光照:
也被称为Phong着色(Phong shading)/Phong插值/法线插值着色技术。以每个像素为基础,得到它的法线(通过对顶点法线插值得到,也可以从法线纹理中采样得到),然后进行光照模型的计算。是一种在面片之间对顶点法线进行插值的技术。
逐顶点、逐像素区别:
- 由于顶点数组往往小于像素数目,因此在逐顶点光照的计算量往往小于逐像素光照。
- 逐顶点光照依赖于线性插值来得到像素光照,当有非线性的计算时(如高光发射)时,逐顶点光照会出问题。
- 逐顶点光照会在渲染图元内部对顶点颜色进行插值,这会导致渲染图元内部的颜色总是暗于顶点处的最高颜色值,这在某些情况下会产生明显的棱角现象。
三、Unity中环境光和自发光
在Unity中,场景的环境光可在Window->Lighting->Ambient Source/Ambient Color/Ambient Intensity中控制(旧版本)中控制。Window->Rendering->Lighting->Environment(新版本)中控制。
在Shader中,通过Unity的内置变量UNITY_LIGHTMODEL_AMBIENT可获得环境光的颜色和强度。
在片元着色器输出最后的颜色之前,把材质的自发光颜色添加到输出颜色上即可。