聚光
撰写时间:2026-07-25
修订时间:2026-07-26
概述
聚光 (spot light) 是从一个点射向特定目标的光源,并且光线被束缚在一个顶部位于光源位置的圆锥体的范围内。此外,聚光也存在衰减的情况。常见的聚光如手电筒、车灯、探照灯等所射出的光线。
在为其建模时,聚光除了具备点光的uLightPos, uLightAttenuation, uLightColor, uLightIntensity等属性之外,还需要uSpotConeDir属性, 代表聚光所照向的方向,以及uInnerCutoff, uOuterCutoff的属性,分别代表内锥角及外锥角的余弦值。其中,内锥角区域内的光线完全覆盖,而外锥角区域内的光线从中心向四周逐渐平滑地衰减至0。
在着色器中实现功能
顶点着色器的代码无需改变。
片断着色器中,先添加相应的uniform属性:
然后在calcDirectLightings函数中,在之前已经计算出衰减因子attenuation的基础上,先计算聚光射向表面的光线与聚光射向目标的光线之间的夹角(余弦值):
注意这里的向量方向,之前的光线方向均是从表面指向光源的向量,而与之不同的是,这里却要求从光源分别指向表面及目标的向量。
代码vec3 SL = uSpotConeDir;暗示着该变量在客户端须已经过归一化处理,因此在片断着色器中无需再进行归一化。
接着,根据外锥角及内锥角的值,将cosTheta钳制在此范围内。
然后,将spotFactor与attenuation相乘,并将结果存储为finalAttenuation。
最后,将finalAttenuation应用到directLightings上面,并返回后者的值。
相应完整代码
客户端:
聚光的修改完全集中于片断着色器的calcDirectLightings函数中。
运行应用。
一盏聚光灯从左上角照下来,场景中所有网络物体均或多或少地落在光照范围内。因聚光灯是斜照,因此被照亮部分显示为一个椭圆形。若修改代码,让聚光灯垂直照向地板,则被照亮部分显示为一个正圆。
