opengl 教程(21) 聚光灯
原帖地址:http://ogldev.atspace.co.uk/www/tutorial21/tutorial21.html
???? 本篇教程中,我們來學習聚光燈的的光照效果,聚光燈有光源位置,也會隨著傳播距離增加而衰減,還有照射方向,另外聚光燈增加的特性是,它的照射范圍在一個圓錐內,類似探照燈的效果。
下圖顯示了聚光燈的效果:
?????? 聚光燈的方向用黑色的箭頭L表示,而我們的光照效果將會限制在兩條紅線內。我們可以通過光線方向,和紅線的夾角來定義光照范圍,對于視線向量V,我們可以用L和V進行點積,如果結果小于cone的角,則不會有聚光燈效果。
主要代碼:
lighting_technique.h
struct SpotLight : public PointLight
{
Vector3f Direction;
float Cutoff;
SpotLight()
{
Direction = Vector3f(0.0f, 0.0f, 0.0f);
Cutoff = 0.0f;
}
};
在聚光燈類中,我們定義了2個新的屬性,光照方向以及光照圓錐夾角。
lighting_technique.cpp
struct SpotLight
{
struct PointLight Base;
vec3 Direction;
float Cutoff;
};
...
uniform int gNumSpotLights;
...
uniform SpotLight gSpotLights[MAX_SPOT_LIGHTS];
定義多個聚光燈光源。
vec4 CalcPointLight(struct PointLight l, vec3 Normal)
{
vec3 LightDirection = WorldPos0 - l.Position;
float Distance = length(LightDirection);
LightDirection = normalize(LightDirection);
vec4 Color = CalcLightInternal(l.Base, LightDirection, Normal);
float Attenuation = l.Atten.Constant +
l.Atten.Linear * Distance +
l.Atten.Exp * Distance * Distance;
return Color / Attenuation;
}
修改點光源shader代碼,使用結構作為參數。
vec4 CalcSpotLight(struct SpotLight l, vec3 Normal)
{
vec3 LightToPixel = normalize(WorldPos0 - l.Base.Position);
float SpotFactor = dot(LightToPixel, l.Direction);
if (SpotFactor > l.Cutoff) {
vec4 Color = CalcPointLight(l.Base, Normal);
return Color * (1.0 - (1.0 - SpotFactor) * 1.0/(1.0 - l.Cutoff));
}
else {
return vec4(0,0,0,0);
}
}
上面是計算聚光燈效果的函數。
...
for (int i = 0 ; i < gNumSpotLights ; i++) {
TotalLight += CalcSpotLight(gSpotLights[i], Normal);
}
...
和點光源的光照的計算方式相同,對于多光源,我們可以累加聚光燈的效果,從而得到最終像素的光照顏色。
lighting_technique.cpp
void LightingTechnique::SetSpotLights(unsigned int NumLights, const SpotLight* pLights)
{
glUniform1i(m_numSpotLightsLocation, NumLights);
for (unsigned int i = 0 ; i < NumLights ; i++) {
glUniform3f(m_spotLightsLocation[i].Color, pLights[i].Color.x, pLights[i].Color.y, pLights[i].Color.z);
glUniform1f(m_spotLightsLocation[i].AmbientIntensity, pLights[i].AmbientIntensity);
glUniform1f(m_spotLightsLocation[i].DiffuseIntensity, pLights[i].DiffuseIntensity);
glUniform3f(m_spotLightsLocation[i].Position, pLights[i].Position.x, pLights[i].Position.y, pLights[i].Position.z);
Vector3f Direction = pLights[i].Direction;
Direction.Normalize();
glUniform3f(m_spotLightsLocation[i].Direction, Direction.x, Direction.y, Direction.z);
glUniform1f(m_spotLightsLocation[i].Cutoff, cosf(ToRadian(pLights[i].Cutoff)));
glUniform1f(m_spotLightsLocation[i].Atten.Constant, pLights[i].Attenuation.Constant);
glUniform1f(m_spotLightsLocation[i].Atten.Linear, pLights[i].Attenuation.Linear);
glUniform1f(m_spotLightsLocation[i].Atten.Exp, pLights[i].Attenuation.Exp);
}
}
上面是給uniform變量賦值。
程序執行后效果如下:
總結
以上是生活随笔為你收集整理的opengl 教程(21) 聚光灯的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 公司使用360安全产品造成的CRM系统故
- 下一篇: poj 1321 棋盘问题(dfs)