Learn OpenGL 笔记3.5 - Light casters

Light casters 就是光线投掷者的意思。

基础知识:

1.Directional Light(平行光)

当光源很远时,来自光源的光线彼此接近平行

直接用一个向量direction定义光源方向

struct Light {
    // vec3 position; // no longer necessary when using directional lights.
    vec3 direction;
  
    vec3 ambient;
    vec3 diffuse;
    vec3 specular;
};
[...]
void main()
{
  vec3 lightDir = normalize(-light.direction);
  [...]
}

2.Point lights(点光源)

Attenuation(衰减)

这里 d 表示从片段到光源的距离。 然后为了计算衰减值,我们定义了 3 个(可配置的)项:常数项 Kc、线性项 Kl 和二次项 Kq。

 

 实现衰减:

struct Light {
    vec3 position;  
  
    vec3 ambient;
    vec3 diffuse;
    vec3 specular;
	
    float constant;
    float linear;
    float quadratic;
}; 

配置参数:

lightingShader.setFloat("light.constant",  1.0f);
lightingShader.setFloat("light.linear",    0.09f);
lightingShader.setFloat("light.quadratic", 0.032f);	

计算衰减:

float distance    = length(light.position - FragPos);
float attenuation = 1.0 / (light.constant + light.linear * distance + 
    		    light.quadratic * (distance * distance));    
ambient  *= attenuation; 
diffuse  *= attenuation;
specular *= attenuation;   

3.Spotlight(聚光源)

 

  • LightDir: the vector pointing from the fragment to the light source.
  • SpotDir: the direction the spotlight is aiming at.(聚光源的核心方向向量)
  • Phi ϕϕ: the cutoff angle that specifies the spotlight's radius. Everything outside this angle is not lit by the spotlight.(cutoff angle 截止角)
  • Theta θθ: the angle between the LightDir vector and the SpotDir vector. The θθ value should be smaller than ΦΦ to be inside the spotlight.

实现Flashlight(手电筒) 

会随玩家位置和方向变换的聚光灯

定义:

struct Light {
    vec3  position;
    vec3  direction;
    float cutOff;
    ...
};  

赋值:(注意:这里角度用cos值来表示,用来节省计算资源)

lightingShader.setVec3("light.position",  camera.Position);
lightingShader.setVec3("light.direction", camera.Front);
lightingShader.setFloat("light.cutOff",   glm::cos(glm::radians(12.5f)));

超过聚光灯范围的颜色去掉

float theta = dot(lightDir, normalize(-light.direction));
    
if(theta > light.cutOff) 
{       
  // do lighting calculations
}
else  // else, use ambient light so scene isn't completely dark outside the spotlight.
  color = vec4(light.ambient * vec3(texture(material.diffuse, TexCoords)), 1.0);

Smooth/Soft edges(柔和边缘)

为了创建平滑边缘聚光灯的效果,我们要模拟具有inner cone内锥体和outer cone外锥体的聚光灯。 从内锥体到外锥体的边缘逐渐变暗。

要从里到外渐变暗,所以需要两个边界,从一个到另一个逐渐变暗。

Here ϵ (epsilon) is the cosine difference between the inner (ϕ) and the outer cone (γ) (ϵ=ϕ−γ). The resulting I value is then the intensity of the spotlight at the current fragment.(分母的值是  里面的边界 - 外面的边界,分子的值是  当前的角度 - 外面的边界,两者一除,角度只要一等于外面的边界,光线就直接变成0了)

实际运用:(clamp表示取0到1中间的值)


float theta     = dot(lightDir, normalize(-light.direction));
float epsilon   = light.cutOff - light.outerCutOff;
float intensity = clamp((theta - light.outerCutOff) / epsilon, 0.0, 1.0);    
...
// we'll leave ambient unaffected so we always have a little light.
diffuse  *= intensity;
specular *= intensity;
...

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值