百人计划-传统经验光照模型详解

参考资料:
百人计划-传统经验光照模型详解
《Unity Shader入门精要》 第6章 基础光照
Shader学习 (12)使用Unity和UE4实现三个经典光照模型

代码标注为C++只是为了会有高亮好看,实际是ShaderLab

经验光照模型只是看上去近似,不是真正正确的光照模型。

漫反射(Diffuse)

漫反射假设一束光达到着色点后均匀的向各个反向反射,而根据Lambert余弦定理认为反射光强度与入射角度与法线方向的余弦成正比,因此就有了漫反射公式。

镜面反射/高光 (Specular)

镜面反射与入射光和观察角度有关。正常计算应该计算出射方向与观察方向(从着色点指向摄像机的方向,UE中的CameraDirectionVector是从摄像机指向着色点的向量,要注意取反)的夹角,但是出射方向计算复杂,一般使用半程向量(观察方向与入射方向的和的单位向量)与法线方向的夹角近似计算。

环境光(ambient)

环境光是为了模拟现实世界中光的反射会经过多次弹射照亮其他物体的效果,环境光一般是一个常量,也可以使用环境光贴图。

几种光照模型

Lambert模型

最简单的光照模型,只考虑用Lambert余弦定理计算得到的漫反射的光照模型。

Half-Lambert模型

使用Lambert模型计算光照时,会把计算结果截取到 [0, 1] 的范围,导致在夹角大于90°时就全是黑色,这看上去不太符合现实世界,因为完全没有全局光照,因此Half-Lambert提出:dot(n,l) * 0.5 + 0.5 ,这样将大于90°的半球也点亮。

1
2
3
4
5
6
fixed4 fragmentShader(in v2f i) : SV_TARGET{
//...
fixed3 halfLambert = dot(worldNormal, worldLight) * 0.5 + 0.5;
fixed3 color = ambient + _LightColor0.rgb * _Diffuse.rgb * halfLambert;
return fixed4(color, 1.0);
}

Phong模型

Phong模型是第一个有影响力的光照模型,由越南学者裴祥风(Bui Tuong Phong)提出,将环境光,漫反射和镜面反射的结果相加。

Blinn-Phong模型

Blinn-Phong模型是在Phong模型上的改进,使用半程向量和法线的夹角代替出射方向和观察方向的夹角,简化了计算。

Blinn-Phon 光照模型的高光反射部分看起来更大、更亮一些。

着色频率

着色频率一般有逐平面着色(Flat shading),逐顶点着色(Gouraud shading)和逐像素着色(Phong shading),区别在于对于光照的计算在渲染流水线的哪个阶段,逐顶点着色在顶点着色器计算光照,逐像素着色在片元着色器计算光照。

计算光照时需要注意要将顶点着色器中计算好的法线在片元着色器中 归一化
原因是在片元着色器中每个片元计算用到的法线是由顶点着色器中计算好的法线插值得来的,如果不进行归一化,插值得到的法线的模长不为一,点乘计算出的结果会看起来不平滑:

观察上图中的高光部分可以明显看出区别。

在UE和Unity中分别实现各种光照模型

UE5 Unity
AtmosphericLightVector WorldLightDir
CameraDirectionVector -ViewDir
PixelNormal WS WorldNormalDir

UE5


从左至右依次:Lambert,Half-Lambert,Blinn-Phong+Half-Lambert

Unity


从左至右依次:逐顶点Lambert,逐像素Lambert,逐像素Half-Lambert,逐顶点Blinn-Phong,逐像素Blinn-Phong,逐像素Blinn-Phong+Half-Lambert


百人计划-传统经验光照模型详解
https://kenny-hoho.github.io/2023/07/09/百人计划-经验光照模型/
作者
Kenny-hoho
发布于
2023年7月9日
许可协议