opengl 教程(21) 聚光灯
2013-01-26 08:25
281 查看
原帖地址:http://ogldev.atspace.co.uk/www/tutorial21/tutorial21.html
本篇教程中,我们来学习聚光灯的的光照效果,聚光灯有光源位置,也会随着传播距离增加而衰减,还有照射方向,另外聚光灯增加的特性是,它的照射范围在一个圆锥内,类似探照灯的效果。
下图显示了聚光灯的效果:
聚光灯的方向用黑色的箭头L表示,而我们的光照效果将会限制在两条红线内。我们可以通过光线方向,和红线的夹角来定义光照范围,对于视线向量V,我们可以用L和V进行点积,如果结果小于cone的角,则不会有聚光灯效果。
在聚光灯类中,我们定义了2个新的属性,光照方向以及光照圆锥夹角。
lighting_technique.cpp
定义多个聚光灯光源。
修改点光源shader代码,使用结构作为参数。
上面是计算聚光灯效果的函数。
和点光源的光照的计算方式相同,对于多光源,我们可以累加聚光灯的效果,从而得到最终像素的光照颜色。
lighting_technique.cpp
上面是给uniform变量赋值。
程序执行后效果如下:
本篇教程中,我们来学习聚光灯的的光照效果,聚光灯有光源位置,也会随着传播距离增加而衰减,还有照射方向,另外聚光灯增加的特性是,它的照射范围在一个圆锥内,类似探照灯的效果。
下图显示了聚光灯的效果:
聚光灯的方向用黑色的箭头L表示,而我们的光照效果将会限制在两条红线内。我们可以通过光线方向,和红线的夹角来定义光照范围,对于视线向量V,我们可以用L和V进行点积,如果结果小于cone的角,则不会有聚光灯效果。
主要代码:
lighting_technique.hstruct 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) 聚光灯
- Qt下使用OpenGL(21)-根据NeHe的教程改写的
- OpenGL教程翻译 第二十一课 聚光灯
- 【Qt OpenGL教程】21:线、反走样、正投影和简单的声音
- Kendo UI开发教程(21): Kendo MVVM 数据绑定(十) Source
- 用OpenInventor实现的NeHe OpenGL教程-第十四课
- OpenGL基础教程(1):体系结构一览
- 【OpenGL】OpenGL引擎开发视频教程
- JeffMolofee(NeHe)的OPENGL教程-第一课[1]-ReSizeGLScene
- JeffMolofee(NeHe)的OPENGL教程-第一课[7]-WinMain
- 用OpenInventor实现的NeHe OpenGL教程-第十三课
- 用OpenInventor实现的NeHe OpenGL教程-第三十课
- 用OpenInventor实现的NeHe OpenGL教程-第四十七课
- Vaadin Web应用开发教程(21):UI组件-Embedded组件
- Qt下使用OpenGL(9)-根据NeHe的教程改写的
- OpenGL教程之漫游3D世界
- Qt下使用OpenGL(12)-根据NeHe的教程改写的
- Android开发之OpenGL+ES教程
- Qt下使用OpenGL(15)-根据NeHe的教程改写的
- 又一个opengl教程,多多益善