冯氏光照模型
示例Fragment Shader
#version 330 core
//光源位置
uniform vec3 lightPos;
//光源颜色
uniform vec3 lightColor;
//环境光强度
uniform float ambientStrength;
//相机位置
uniform vec3 viewPos;
//镜面反射高光强度因子
uniform uint powValue;
uniform sampler2D borderSampler2D;
uniform sampler2D containerSampler2D;
in vec3 FragPos;
in vec3 Normal;
in vec2 texCoord;
out vec4 FragColor;
void main()
{
float ambient;
//环境光强度乘以光源的颜色 得到一个 环境光照强度
if( ambientStrength < 0.0f ){
ambient = 0.0f;
}else if( ambientStrength > 1.0f ){
ambient = 1.0f;
}else{
ambient = ambientStrength;
}
//计算漫反射光照,基本算法如下:
// 光源到当前顶点的方向向量 点乘以 顶点法线向量 == 光线方向与顶点发现向量的角度
// 这个角度就可以当成漫反射光照强度 diff
// 需要注意的是,由于在真是环境中,如果光线方向和顶点法线向量的夹角超过 90 度的时候
// 光线是看不见的,所以要排除掉 大于 90度 的情况(暂时不考虑特别的情况)
vec3 norm = normalize(Normal);
vec3 lightDir = normalize(lightPos - FragPos);
float diff = max(dot(lightDir, norm), 0.0);
//计算镜面光照,基本算法如下:
// 1. 通过入射光线的方向向量 和 顶点法线向量 计算出反射光线的方向
// 2. 通过观察者的位置 和 当前顶点的位置 计算出 观察者观察当前顶点的 方向向量
// 3. 通过 反射光线方向向量 和 观察视线方向向量 计算出两者的夹角, 这个夹角用来
// 计算镜面反射光照强度的因子 specFactor
// 4. 我们知道 在 镜面反射中,反射光强度 随着 视线和反射光线的角度 的增大而极具下降
// 这个强度衰减的过程是非线性的,而是类似指数级的的衰减,那么 我们就可以利用 指数
// 来模拟这个衰减的过程:
// float spec = pow(specFactor, 幂值)
// 此处求出的 spec 称为镜面反射的高光强度
// 上述的 幂值 可以用来表示衰减的急剧程度, 幂指越大,spec的值变化越急剧,衰减就越剧烈
// 在现实中,镜面光照感越强,这样让人觉得 物体表面越平滑有光泽
vec3 reflectDir = normalize(reflect(-lightDir, norm));
vec3 viewDir = normalize(viewPos - FragPos);
float specFactor = max(dot(reflectDir, viewDir), 0.0);
float spec = pow(specFactor, powValue);
//我们此处要接受光照的对象是 带有金属边框的木头箱子
//可以知道,能够镜面反射光线的只有金属边框,木头部分基本无法做镜面反射,所以我们忽略
//判断 当前顶点是 金属边框 还是 木头 是 通过一张 灰度图 纹理 来指明
//当前的纹理中,灰度值为 0 的部分是木头, 不为0 的部分是金属
vec3 result;
vec4 borderTexFrag = texture2D(borderSampler2D, texCoord);
vec4 containerTexFrag = texture2D(containerSampler2D, texCoord);
//环境光照 加上 光源光照 等于总的光照
//总的光照 乘以 物体的颜色 就计算出了 物体在光照下 呈现出的颜色
if( borderTexFrag.x == 0.0f ){
result = ((ambient + diff) * lightColor) * containerTexFrag.xyz;
}else{
result = ((ambient + diff + spec) * lightColor) * containerTexFrag.xyz;
}
FragColor = vec4(result, 1.0f);
}