【unity Shader 学习笔记】5-1 光照模型
在现实生活中,我们如果想看见一个物体,需要一个光源。当光线照在物体上时,会有反射,这个反射包括漫反射以及高光反射。同时,因为反射的原因,会被环境内的其他物体反射到自己身上(间接光照),也就是环境光。
当然其中还有更复杂的散射、折射、吸收
那么,在游戏中,要怎么才能模拟或者还原出这样的效果呢?
着色(shading)
这里指的是,根据材质属性(如漫反射属性等)、光源信息(如光源方向、辐照度等),使用一个等式去计算沿某个观察方向的出射度的过程。这个等式称为称为光照模型(Light Model)。
说人话就是使用光照的渲染过程。用数学来计算光照的公式叫做光照模型。
BRDF
可以将给一个表面着色的过程,理解为给定入射的光线数量和方向,计算出指定方向的出射 光亮度(radiance)。在计算机图形学领域,BRDF (Bidirectional Reflectance DistributionFunction,译作双向反射分布函数 )是一个用来描述表面如何反射光线的方程。顾名思义, BRDF 就是一个描述光如何从给定的两个方向(入射光方向 l 和出射方向 v)在表面进行反射的函数。
这里讲经验光照模式。通过经验得到的,用数学公式,模拟近似于现实生活中的效果。如果这个物体看起来是对的,那么它就是对的。
常见的 BRDF 经验模型有:
[*]Lambert 漫反射模型
[*]Phong 模型
[*]Blinn-Phong 模型
一个物体的光照部分,可以简单拆解为 环境光+漫反射+高光。
Lambert 漫反射模型
公式:
// 漫反射 = 环境光 + 漫反射系数 * 光照颜色 * dot(世界法线,入射光照)
Diffuse = Ambient + Kd * LightColor * dot(N,L) 即,光打到物体表面,它的漫反射和法线以及入射光线有关,且物体的材质(漫反射系数)也会影响。
这里的重点则是 dot(N,L) 。正常情况下,向量的计算一般都会归一化处理。两向量点乘,结果即两向量间的夹角cos 值。lamber dot的结果为 -1~1,但是从亮面到暗面从数值和表现上,通常会将-1~1 映射为 0~1,也称之为半lamber 光照。
float NdotL = dot(N,L);
NdotL = NdotL * 0.5 + 0.5;转到0~1,还可以方便使用贴图,自定义自己的阴影渐变方便映射。
Phong 模型
用来计算高光反射
公式
// phong高光 = 高光颜色 * 高光系数 * pow(max(0,dot(反射向量,观察向量),高光范围))
// specular = specularColor * ks * pow(max(0,dot(R,V)),shininess)这里主要拆分两部分
[*]dot(R,V)
[*]pow(max(0,dot(R,V)),shininess)
R 表示光照反射出去的向量,V 表示人眼观察的方(摄像机)。当人眼越靠近光线反射的位置时,反射的强度也越强。
反射向量 R 的计算
float3 N = normalize(i.worldNormal); // 法线归一化
float3 L = normalize(_WorldSpaceLightPos0.xyz); // 入射光线
// R = 2 * dot(N,L) * N - L;
float3 R = reflect(-L,N); // 反射向量在unity 中,可以使用 reflect 来计算反射向量
为了控制高光的过渡,控制高光范围,使用pow()指数函数来近似效果
BlinnPhong 光照模型
用来计算高光反射
公式
// 半角向量 H 即相当于入射光线和观察方向的中间向量
float3 H = normalize(L+V);
float NdotH = dot(N,H);
// 高光 = 高光颜色 * 高光系数 * pow(max(0,dot(世界法线,半角向量)),高光范围)
//specular = specularColor * ks * pow(max(0,dot(N,H)),shininess)
H 被称为半角向量,即于入射向量和观察向量的中间向量。当 H 越靠近法线 N,从侧面说明,观察向量越靠近光照反射的方向,即亮度越亮。
BlinnPhong 与 Phong 的区别则在于dot(N,H)和dot(R,V),其中最主要的是 半角向量 H 的计算,对比 反射向量 R 的计算复杂度,H 只需要做加法即可。所以 BlinnPhong 相比 Phong 更加常用。
页:
[1]