根据教程:ogldev一步步开始,记录学习历程
聚光灯光源
聚光灯光源是结合了平行光方向的特性和点光源随距离衰减的特性,并且离光源越远,照亮圆形区域越大,即光源呈锥形。 在现实中一个例子为手电筒。
如图所示,即为聚光灯光源的锥形效果:
- L为光源方向
- 我们只想让光源照亮红色夹角之间的区域,即2α的角度
- V为光源到某个像素的向量
- 如果β大于α则该像素不位于照亮区域内
- 为了得到夹角的余弦值,可以使用向量间点积来得到
如果按照在区域内就能照亮,区域外就不能,则会在照亮区域和不照亮区域之间形成很明显的边界,没有过渡的效果。
聚光灯光源从照亮区域的中心向边缘慢慢衰减,如果L和V向量重合时,夹角为0,点积(夹角余弦值)为1,随着夹角增大,余弦值减小。但是夹角从0到一个比较小的角,余弦值变化很缓慢,衰减不明显。
比如聚光灯夹角为20°,余弦值为0.939,[0.939,1]这个变化范围太小,不好作为衰减参数,应该使得衰减参数范围为[0,1],所以把余弦值范围映射到[0,1]方法如下:
计算原理即为:使用大范围——[0,1],和小范围——[cosα,1]的比例——(1-0)/(1-cosα)=d
对小范围进行映射扩张,如果是α<=β<=1 —— 1-(1-cosβ)*((1-0)/(1-cosα))
实现聚光灯光源
首先定义聚光灯光源的结构体,聚光灯光源集成点光源的结构体,并且多出了光源的方向向量和照亮的夹角两个参数
opengl_light.h:
struct SpotLight : public PointLight
{
Vector3f Direction;
float Cutoff;
SpotLight()
{
LoadVector3(Direction,0.0f, 0.0f, 0.0f);
Cutoff = 0.0f;
}
};
之后在Light类中加入用于获取聚光灯光源Uniform变量的索引
opengl_light.h:
GLuint m_numSpotLightsLocation;
struct {
GLuint Color;
GLuint AmbientIntensity;
GLuint DiffuseIntensity;
GLuint Position;
GLuint Direction;
GLuint Cutoff;
struct {
GLuint Constant;