基础光照
冯氏光照模型(Phong Lighting Model)
现实世界的光照是极其复杂的,而且会受到诸多因素的影响,这是我们有限的计算能力所无法模拟的。 因此OpenGL的光照使用的是简化的模型,对现实的情况进行近似,这样处理起来会更容易一些,而且看起来也差不多一样。 这些光照模型都是基于我们对光的物理特性的理解。其中一个模型被称为
冯氏光照模型(Phong Lighting Model)。 冯氏光照模型的主要结构由3个分量组成:环境(Ambient)、漫反射(Diffuse)和镜面(Specular)光照。
环境光(Ambient Lighting) > 即使在黑暗的情况下,世界上通常也仍然有一些光亮(月亮、远处的光),所以物体几乎永远不会是完全黑暗的。为了模拟这个,我们会使用一个环境光照常量,它永远会给物体一些颜色。
光通常都不是来自于同一个光源,而是来自于我们周围分散的很多光源,即使它们可能并不是那么显而易见。光的一个属性是,它可以向很多方向发散并反弹,从而能够到达不是非常直接临近的点。所以,光能够在其它的表面上反射,对一个物体产生间接的影响。考虑到这种情况的算法叫做全局照明(Global Illumination)算法,但是这种算法既开销高昂又极其复杂。 由于我们现在对那种又复杂又开销高昂的算法不是很感兴趣,所以我们将会先使用一个简化的全局照明模型,即环境光照。正如你在上一节所学到的,我们使用一个很小的常量(光照)颜色,添加到物体片段的最终颜色中,这样子的话即便场景中没有直接的光源也能看起来存在有一些发散的光。 把环境光照添加到场景里非常简单。我们用光的颜色乘以一个很小的常量环境因子,再乘以物体的颜色,然后将最终结果作为片段的颜色:
void main() { float ambientStrength = 0.1; vec3 ambient = ambientStrength * lightColor; vec3 result = ambient * objectColor; FragColor = vec4(result, 1.0); }漫反射光照(Diffuse Lighting) > 模拟光源对物体的方向性影响(Directional Impact)。它是冯氏光照模型中视觉上最显著的分量。物体的某一部分越是正对着光源,它就会越亮。 > 主要计算在于
光照方向、光照分量 dot(norm, lightDir)、非负数截断 max(xx, 0)> 我们对norm和lightDir向量进行点乘,计算光源对当前片段实际的漫发射影响。结果值再乘以光的颜色,得到漫反射分量。两个向量之间的角度越大,漫反射分量就会越小cpp #version 330 core out vec4 FragColor; in vec3 Normal; in vec3 FragPos; uniform vec3 lightPos; uniform vec3 lightColor; uniform vec3 objectColor; void main() { // ambient float ambientStrength = 0.1; vec3 ambient = ambientStrength * lightColor; // diffuse vec3 norm = normalize(Normal); vec3 lightDir = normalize(lightPos - FragPos); //点乘的集合意义,投影(分量)大小 float diff = max(dot(norm, lightDir), 0.0); vec3 diffuse = diff * lightColor; vec3 result = (ambient + diffuse) * objectColor; FragColor = vec4(result, 1.0); }//不等比的缩放会导致原本的法线不再垂直于表面,此时需要法线矩阵来修复 Normal = mat3(transpose(inverse(model))) * aNormal;镜面光照(Specular Lighting):模拟有光泽物体上面出现的亮点。镜面光照的颜色相比于物体的颜色会更倾向于光的颜色。
和漫反射光照一样,镜面光照也是依据光的方向向量和物体的法向量来决定的,但是它也依赖于观察方向,例如玩家是从什么方向看着这个片段的。 镜面光照是基于光的反射特性。如果我们想象物体表面像一面镜子一样,那么,无论我们从哪里去看那个表面所反射的光,镜面光照都会达到最大化
观察点通常使用相机的位置, 和漫反射类似,只是镜面光照是反射光在观察方向的分量#version 330 core out vec4 FragColor; in vec3 Normal; in vec3 FragPos; uniform vec3 lightPos; uniform vec3 viewPos; uniform vec3 lightColor; uniform vec3 objectColor; uniform float specularStrengthPow; void main() { // ambient float ambientStrength = 0.1; vec3 ambient = ambientStrength * lightColor; // diffuse vec3 norm = normalize(Normal); vec3 lightDir = normalize(lightPos - FragPos); float diff = max(dot(norm, lightDir), 0.0); vec3 diffuse = diff * lightColor; // specular float specularStrength = 0.5; vec3 viewDir = normalize(viewPos - FragPos); vec3 reflectDir = reflect(-lightDir, norm); float spec = pow(max(dot(viewDir, reflectDir), 0.0), 256); vec3 specular = specularStrength * spec * lightColor; vec3 result = (ambient + diffuse + specular) * objectColor; //vec3 result = (ambient + diffuse ) * objectColor; //vec3 result = specular* objectColor; //vec3 result = objectColor; FragColor = vec4(result, 1.0); }