23.7方向光


文档摘要

## 23.7 方向光 前面几个小节,定义了一个 ,它包含了光源的位置、颜色、强度,这几乎是一个光源的所有参数了。 但是世界上的光源有很多种,又需要增加或减少一些参数来对其进行描述,下面列举一些: 方向光(Directional Light): 又叫平行光、定向光,光源发出的光子,几乎平行朝目标发射。一般将太阳光看做方向光。 点光(Point Light): 光源发出的光子,向四面八方发射,到一定距离后消亡。例如萤火虫的光。 聚光(Spot Light): 光源发出的光子,向一个方向发射,形成锥形桶。例如手电筒。 这一小节就先介绍方向光(Directional Light)。 方向光特点 方向光有以下特点: 与位置无关,仅有方向属性。 无衰减 方向光的实现 2.

23.7 方向光

CLion项目文件位于 samples\classic_lighting\directional_light

前面几个小节,定义了一个Light,它包含了光源的位置、颜色、强度,这几乎是一个光源的所有参数了。

但是世界上的光源有很多种,又需要增加或减少一些参数来对其进行描述,下面列举一些:

  1. 方向光(Directional Light): 又叫平行光、定向光,光源发出的光子,几乎平行朝目标发射。一般将太阳光看做方向光。
  2. 点光(Point Light): 光源发出的光子,向四面八方发射,到一定距离后消亡。例如萤火虫的光。
  3. 聚光(Spot Light): 光源发出的光子,向一个方向发射,形成锥形桶。例如手电筒。

这一小节就先介绍方向光(Directional Light)。

1. 方向光特点

方向光有以下特点:

  1. 与位置无关,仅有方向属性。
  2. 无衰减

2. 方向光的实现

2.1 修改片段Shader

片段着色器,在上一节的 Light的基础之上,稍作修改。

将坐标改成方向,去除掉计算光线方向的操作,直接使用传入的方向即可。

//file:data/shader/directional_light.frag ...... struct DirectionalLight { vec3 dir;//方向 alignment:12 offset:0 vec3 color;//颜色 alignment:12 offset:16 float intensity;//强度 alignment:4 offset:28 }; //灯光 layout(std140) uniform DirectionalLightBlock { DirectionalLight data; }u_directional_light; ...... void main() { ...... //diffuse vec3 normal=normalize(v_normal); vec3 light_dir=normalize(u_directional_light.data.dir);//使用方向光的方向 float diffuse_intensity = max(dot(normal,-light_dir),0.0); vec3 diffuse_color = u_directional_light.data.color * diffuse_intensity * u_directional_light.data.intensity * texture(u_diffuse_texture,v_uv).rgb; //specular vec3 reflect_dir=reflect(light_dir,v_normal); vec3 view_dir=normalize(u_view_pos-v_frag_pos); float spec=pow(max(dot(view_dir,reflect_dir),0.0),u_specular_highlight_shininess); float specular_highlight_intensity = texture(u_specular_texture,v_uv).r;//从纹理中获取高光强度 vec3 specular_color = u_directional_light.data.color * spec * specular_highlight_intensity * texture(u_diffuse_texture,v_uv).rgb; o_fragColor = vec4(ambient_color + diffuse_color + specular_color,1.0); }

2.2 设置UBO

结合上面提到的多种光源特性,对Light 进行整理,只保留颜色、强度基础属性,更新UBO的操作全放在子类。

新增DirectionalLight 继承 Light

//file:source/lighting/directional_light.cpp using namespace rttr; RTTR_REGISTRATION//注册反射 { registration::class_<DirectionalLight>("DirectionalLight") .constructor<>()(rttr::policy::ctor::as_raw_ptr); } DirectionalLight::DirectionalLight():Light() { } DirectionalLight::~DirectionalLight() { } void DirectionalLight::set_color(glm::vec3 color) { Light::set_color(color); UniformBufferObjectManager::UpdateUniformBlockSubData3f("u_directional_light","data.color",color_); }; void DirectionalLight::set_intensity(float intensity) { Light::set_intensity(intensity); UniformBufferObjectManager::UpdateUniformBlockSubData1f("u_directional_light","data.intensity",intensity_); }; void DirectionalLight::Update() { glm::vec3 rotation=game_object()->GetComponent<Transform>()->rotation(); glm::mat4 eulerAngleYXZ = glm::eulerAngleYXZ(glm::radians(rotation.y), glm::radians(rotation.x), glm::radians(rotation.z)); glm::vec3 light_rotation=glm::vec3(eulerAngleYXZ * glm::vec4(0,0,-1,0));//Transform旋转 * 默认朝向 UniformBufferObjectManager::UpdateUniformBlockSubData3f("u_directional_light","data.dir",light_rotation); }

DirectionalLight::Update 计算光的方向,首先是给一个默认的方向 (0,0,-1),然后把Transform的Rotation作用到它上面。

3. 测试

LoginScene:Awake() 创建GameObject,挂上DirectionalLight组件。

LoginScene:Update() 旋转GameObject,做出光方向改变的效果。

--file:example/login_scene.lua function LoginScene:Awake() ...... self:CreateLight() ...... end --- 创建灯 function LoginScene:CreateLight() self.go_light_= GameObject.new("directional_light") self.go_light_:AddComponent(Transform) local light=self.go_light_:AddComponent(DirectionalLight) light:set_color(glm.vec3(1.0,1.0,1.0)) light:set_intensity(1.0) end function LoginScene:Update() ...... --6s 绕Y旋转一圈 self.go_light_:GetComponent(Transform):set_rotation(glm.vec3(0,(Time:TimeSinceStartup()*60)%360,0)) ...... end

效果如下:


发布者: 作者: 转发
评论区 (0)
U