本文主要是介绍Learn OpenGL 笔记6.1 Advanced Lighting(高级照明),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
之前我们简要介绍了 Phong 照明模型,为我们的场景带来了基本的真实感。但有一些细节,我们将在本章中重点关注。
基础知识:
1.Blinn-Phong
以前模型的弊端:
Phong 照明是一种很好且非常有效的照明近似方法,但它的镜面反射在某些条件下会分解,特别是当光泽度低导致大(粗糙)镜面区域时。 下图显示了当我们在平面纹理平面上使用 1.0 的镜面反射光泽指数时会发生:
发生这种情况的原因是视图和反射向量之间的角度没有超过 90 度。 如果角度大于 90 度,则生成的点积变为负值,这导致镜面反射指数为 0.0。
//镜面高光 = 强度 * 镜面高光参数 * 光的颜色vec3 specular = specularStrength * spec * lightColor;
而其中的spec又等于:viewDir和reflectDir的点积 = |a||b|cos0,所以当图中的光射向里的一面,反射出的光,反射向量,与我们的眼睛向量view的夹角,就大于了90度了。导致cos0 < 0了,没光强了。
// specularfloat specularStrength = 0.5;vec3 viewDir = normalize(viewPos - FragPos);vec3 reflectDir = reflect(-lightDir, norm); float spec = pow(max(dot(viewDir, reflectDir), 0.0), 32);
Blinn-Phong 着色模型的优势:
1977 年,James F. Blinn 引入了 Blinn-Phong 着色模型,作为我们迄今为止使用的 Phong 着色的扩展。 Blinn-Phong 模型在很大程度上相似,但与镜面反射模型略有不同,因此克服了我们的问题。 我们不依赖于反射向量,而是使用所谓的halfway vector中间向量,它是一个单位向量,正好位于视图方向和光方向的中间。 这个中间向量与表面的法向量对齐得越近,镜面反射的贡献就越高。
当视图方向与(现在是假想的)反射向量完美对齐时,中间向量与法线向量完美对齐。 视线方向越接近原始反射方向,镜面高光越强。
无论观察者从哪个方向看,中间向量和表面法线之间的角度都不会超过 90 度(当然,除非光线远低于表面)。 结果与 Phong 反射略有不同,但通常在视觉上更合理,尤其是在镜面反射指数较低的情况下。 Blinn-Phong 着色模型也是早期 OpenGL 固定函数管道中使用的精确着色模型。
获得中间向量很容易,我们将光的方向向量和视图向量相加,并对结果进行归一化:
L:光的向量 V:视图向量(眼睛向量)
Blinn-Phong 的GLSL代码:
vec3 lightDir = normalize(lightPos - FragPos);
vec3 viewDir = normalize(viewPos - FragPos);
vec3 halfwayDir = normalize(lightDir + viewDir);
然后镜面反射项的实际计算变成了表面法线和中间向量之间的点积,以获得它们之间的余弦角,我们再次提炼出一个specular shininess exponent镜面反射光泽指数:
float spec = pow(max(dot(normal, halfwayDir), 0.0), shininess);
vec3 specular = lightColor * spec;
Phong 和 Blinn-Phong 着色之间的另一个细微差别是中间向量和表面法线之间的角度(blinn-phong)通常小于视图和反射向量之间的角度(phong)。 因此,要获得类似于 Phong 着色的视觉效果,必须将镜面反射光泽指数设置得更高一些。 一般的经验法则是将其设置在 Phong 光泽指数的 2 到 4 倍之间。
下面是 Phong 指数设置为 8.0 和 Blinn-Phong 分量设置为 32.0 的两种镜面反射模型之间的比较:
二者切换:
void main()
{[...]float spec = 0.0;if(blinn){vec3 halfwayDir = normalize(lightDir + viewDir); spec = pow(max(dot(normal, halfwayDir), 0.0), 16.0);}else{vec3 reflectDir = reflect(-lightDir, normal);spec = pow(max(dot(viewDir, reflectDir), 0.0), 8.0);}
这篇关于Learn OpenGL 笔记6.1 Advanced Lighting(高级照明)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!