聚光
- 位于场景中某一处;
- 只朝某个方向照射;
- 只有照射方向确定半径范围内的物体被照亮;
例子:路灯,手电筒。
工作示意图
- 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向量的点乘,而点乘返回一个余弦值,不是一个角度,所以我们不能直接把一个角度和余弦值对比。为了获得这个角度,我们必须计算点乘结果的反余弦,这个操作开销是很大的。所以为了节约一些性能,我们先计算给定切光角的余弦值,然后把结果传递给片段着色器。由于每个角度都被表示为余弦了,我们可以直接对比它们,而不用进行任何开销高昂的操作。
网友评论