平行光:当使用一个假设光源处于无限远处的模型时,被称为定向光。因为它的光线都有着相同的方向,与光源的位置无关。
理解:太阳光便为平行光
定义一个光线方向向量而不是位置向量来模拟一个定向光
1 struct Light { 2 // vec3 position; // 使用定向光就不再需要了 3 vec3 direction; 4 5 vec3 ambient; 6 vec3 diffuse; 7 vec3 specular; 8 }; 9 ... 10 void main() 11 { 12 vec3 lightDir = normalize(-light.direction); 13 ... 14 }
光照计算中采用的都是一个从片段到光源的光线方向。light.direction是人们的习惯,由光源指向物体的方向。所以需要取反。
二、点光源
是处于世界中某一个位置的光源,它会朝着所有方向发光,但光线会随着距离逐渐衰减,例如:灯泡
衰减
随着光线传播距离的增长逐渐消减光的强度通常叫做衰减
随距离减少光强度的一种方式是使用一个线性方程。这样的方程能够随着距离的增长线性地减少光的强度,从而让远处的物体更暗。然而,这样的线性方程通常会看起来比较假。在现实世界中,灯在近处通常会非常亮,但随着距离的增加光源的亮度一开始会下降非常快,但在远处时剩余的光强度就会下降的非常缓慢了。所以,我们需要一个不同的公式来减少光的强度。
d:代表片段距光源的距离。
Kc:常数项;Kl:一次项;Kq:二次项。
常数项通常保持为1.0,作用为:保证值永远小于1,否则的话在某些距离上反而会增加强度
一次项会与距离值相乘,以线性的方式较少强度
二次项会与距离的平方相乘,让光源以二次递减的方式减少强度。二次项在距离比较小的时候影响会比一次项小很多,但当距离值比较大的时候就会比一次项更大了。
由于二次项的存在,光线会在大部分时候以线性的方式衰退,直到距离变得足够大,让二次项超过一次项,光的强度会以更快的速度下降。这样的结果就是,光在近距离时亮度很高,但随着距离变远亮度迅速降低,最后会以更慢的速度减少亮度。下面这张图显示了在100的距离内衰减的效果:
实现衰减:
为了实现衰减,在片段着色器中我们还需要三个额外的值:也就是公式中的常数项、一次项和二次项。它们最好储存在之前定义的Light结构体中。
然后我们将在OpenGL中设置这些项:我们希望光源能够覆盖50的距离,所以我们会使用表格中对应的常数项、一次项和二次项:
1 cubeShader.setFloat("light.constant",1.0f); 2 cubeShader.setFloat("light.linear",0.09f); 3 cubeShader.setFloat("light.quadratic",0.032f);
计算衰减:
length函数为GLSL内建的函数
1 float distance = length(light.position - fragPos); 2 float attenuation = 1.0/(light.constant + light.linear * distance + light。quadratic *(distance,distance));
接下来,我们将包含这个衰减值到光照计算中,将它分别乘以环境光、漫反射和镜面光颜色。
1 ambient *= attenuation; 2 diffuse *= attenuation; 3 specular *= attenuation;