冯氏光照 phong lighting
冯氏光照主要把光照分解成三个分量:
- 环境光(ambient lighting) 模拟物体在暗处也能依稀有点自身颜色 权值=光源颜色*一个小系数
- 漫反射(diffuse lighting) 模拟漫反射,能体现物体的基本的立体结构,也就是正对光源背对光源效果 权值=光源颜色*光线和法向量夹角余弦
- 镜面光(specular lighting) 模拟镜面反射,大概能局部模拟出一些高光效果,相对漫反射多了一个对观察者的依赖,形象的说,反射光线和视线的夹角越小,光越量,这里使用这个夹角\(\theta\) 的n次幂来模拟 权值=\(cos(\theta)^n * light\),这里的n被称作反光度(Shininess)
最后将三个分量的权值加起来,然后乘上物体本来的颜色,就获得了冯氏光照模型的光照效果。其中乘法是将权值(一个三维向量)按位乘物体本色(一个三维向量),本质上是模拟光学上物体在被光照时反射的效果。
如下可得片着色器实现:
//环境光,小系数*光源颜色
float ambientStrength = 0.1;
vec3 ambient = ambientStrength * lightColor;
//漫反射,夹角余弦*光源,Normal为法线向量,先归一化
vec3 norm = normalize(Normal);
//光线向量通过光源-点坐标获得,归一化,光源通过uniform传入
vec3 lightDir = normalize(lightPos - FragPos);
//通过单位向量点乘获得夹角,同时避免负值出现的奇怪情况
float diff = max(dot(norm, lightDir), 0.0);
vec3 diffuse = diff * lightColor;
//镜面反射,这边的镜面反射系数前面预乘了个系数0.5
float specularStrength = 0.5;
//视线向量通过视点-点坐标
vec3 viewDir = normalize(viewPos - FragPos);
//反射光线计算,norm和lightdir在上面计算获得,取反可以画图理解下
vec3 reflectDir = reflect(-lightDir, norm);
//计算余弦的n(32)次幂
float spec = pow(max(dot(viewDir, reflectDir), 0.0), 32);
vec3 specular = specularStrength * spec * lightColor;
//三种光照分量相加,在乘上物体本身颜色,输出
vec3 result = (ambient + diffuse + specular) * objectColor;
FragColor = vec4(result, 1.0);

浙公网安备 33010602011771号