【五十,投光物-03聚光-手电筒光效】

聚光

  • 位于场景中某一处;
  • 只朝某个方向照射;
  • 只有照射方向确定半径范围内的物体被照亮;

例子:路灯,手电筒。

工作示意图

light_casters_spotlight_angles.png

  • LightDir:从片段指向光源的向量。
  • SpotDir:聚光所指向的方向。
  • Phiϕ:定义聚光半径的切光角。每个落在这个角度之外的,聚光都不会照亮。
  • Thetaθ:LightDir向量和SpotDir向量之间的角度。θ值应该比Φ值小,这样才会在聚光内。

手电筒

手电筒(Flashlight)是一个在观察者位置的聚光,通常瞄准玩家透视图的前面。一个手电筒是一个普通的聚光,根据玩家的位置和方向持续的更新它的位置和方向。
我们需要为着色器提供:

  • 位置向量
  • 聚光方向向量
  • 聚光切角
struct Light
{
    vec3 position;
    vec3 direction;
    float cutOff;
    ...
};

在代码中设置相关值:

glUniform3f(lightPosLoc, camera.Position.x, camera.Position.y, camera.Position.z);
glUniform3f(lightSpotdirLoc, camera.Front.x, camera.Front.y, camera.Front.z);
glUniform1f(lightSpotCutOffLoc, glm::cos(glm::radians(12.5f)));

我们给片段着色器传递的是余弦值:这么做的原因是在片段着色器中,我们计算LightDir和SpotDir向量的点乘,而点乘返回一个余弦值,不是一个角度,所以我们不能直接把一个角度和余弦值对比。为了获得这个角度,我们必须计算点乘结果的反余弦,这个操作开销是很大的。所以为了节约一些性能,我们先计算给定切光角的余弦值,然后把结果传递给片段着色器。由于每个角度都被表示为余弦了,我们可以直接对比它们,而不用进行任何开销高昂的操作。

运行效果

手电筒运行效果

手电筒光效代码

你可能感兴趣的:(【五十,投光物-03聚光-手电筒光效】)