LearnOpengl_CN 光照学习总结

学习网站:投光物 - LearnOpenGL CN (learnopengl-cn.github.io)

1.平行光

定义:假设光源处于无限远处的模型时,它就被称为定向光

重点:所有光线都有着相同的方向,它与光源的位置是没有关系的

问题一:为啥要对light.direction向量取反?

光照计算需求一个从片段至光源的光线方向

#version 330 core
out vec4 FragColor

struct Material
{
sampler2D diffuse;
sampler2D specular;
float shiniess;
};

struct Light
{
vec3 direction;

vec3 ambient;
vec3 diffuse;
vec3 specular;
}

in vec3 FragPos;  
in vec3 Normal;  
in vec2 TexCoords;
  
uniform vec3 viewPos;
uniform Material material;
uniform Light light;

void main()
{
    // ambient
    vec3 ambient = light.ambient * texture(material.diffuse, TexCoords).rgb;
  	
    // diffuse 
    vec3 norm = normalize(Normal);
    vec3 lightDir = normalize(-light.direction);  
    float diff = max(dot(norm, lightDir), 0.0);
    vec3 diffuse = light.diffuse * diff * texture(material.diffuse, TexCoords).rgb;  
    
    // specular
    vec3 viewDir = normalize(viewPos - FragPos);
    vec3 reflectDir = reflect(-lightDir, norm);  
    float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
    vec3 specular = light.specular * spec * texture(material.specular, TexCoords).rgb;  
        
    vec3 result = ambient + diffuse + specular;
    FragColor = vec4(result, 1.0);
} 

2.点光源

定义:光源是处于世界中某一个位置的光源,它会朝着所有方向发光,光线会随着距离逐渐衰减

重点:

  • 衰减(Attenuation):随着光线传播距离的增长逐渐削减光的强度
  • 衰减公式:Fatt=1.0/Kc+Kl∗d+Kq∗d2(常数项Kc、一次项Kl和二次项Kq,d片段距光源的距离)
  • 衰减公式的注意事项:
  1. 常数项通常保持为1.0,它的主要作用是保证分母永远不会比1小,否则的话在某些距离上它反而会增加强度。
  2. 一次项会与距离值相乘,以线性的方式减少强度。
  3. 二次项会与距离的平方相乘,让光源以二次递减的方式减少强度。
  4. 光在近距离时亮度很高,但随着距离变远亮度迅速降低(一次项的影响),最后会以更慢的速度减少亮度(二次项的影响)。
#version 330 core
out vec4 FragColor;

struct Material {
    sampler2D diffuse;
    sampler2D specular;    
    float shininess;
}; 

struct Light {
    vec3 position;

    vec3 ambient;
    vec3 diffuse;
    vec3 specular;

    float constant;
    float linear;
    float quadratic;
};

in vec3 FragPos;  
in vec3 Normal;  
in vec2 TexCoords;
  
uniform vec3 viewPos;
uniform Material material;
uniform Light light;

void main()
{

    // ambient
    vec3 ambient = light.ambient * texture(material.diffuse, TexCoords).rgb;
  	
    // diffuse 
    vec3 norm = normalize(Normal);
     vec3 lightDir = normalize(light.position - FragPos);
    float diff = max(dot(norm, lightDir), 0.0);
    vec3 diffuse = light.diffuse * diff * texture(material.diffuse, TexCoords).rgb;  
    
    // specular
    vec3 viewDir = normalize(viewPos - FragPos);
    vec3 reflectDir = reflect(-lightDir, norm);  
    float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
    vec3 specular = light.specular * spec * texture(material.specular, TexCoords).rgb;  

    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;

    vec3 result = ambient + diffuse + specular;
    FragColor = vec4(result, 1.0);
} 

3.聚光

定义:聚光是位于环境中某个位置的光源,它只朝一个特定方向而不是所有方向照射光线。

重点:

  • LightDir:从片段指向光源的向量。
  • SpotDir:聚光所指向的方向。
  • Phiϕ:指定了聚光半径的切光角。落在这个角度之外的物体都不会被这个聚光所照亮。
  • Thetaθ:LightDir向量和SpotDir向量之间的夹角。在聚光内部的话θ值应该比ϕ值小。
    #version 330 core
    out vec4 FragColor;
    
    struct Material {
        sampler2D diffuse;
        sampler2D specular;    
        float shininess;
    }; 
    
    struct Light {
        vec3 position;  
        vec3 direction;
        float cutOff;
        float outerCutOff;
      
        vec3 ambient;
        vec3 diffuse;
        vec3 specular;
    	
        float constant;
        float linear;
        float quadratic;
    };
    
    in vec3 FragPos;  
    in vec3 Normal;  
    in vec2 TexCoords;
      
    uniform vec3 viewPos;
    uniform Material material;
    uniform Light light;
    
    void main()
    {
            // ambient
            vec3 ambient = light.ambient * texture(material.diffuse, TexCoords).rgb;
            
            // diffuse 
            vec3 norm = normalize(Normal);
            vec3 lightDir=normalize(light.position-FragPos);
            float diff = max(dot(norm, lightDir), 0.0);
            vec3 diffuse = light.diffuse * diff * texture(material.diffuse, TexCoords).rgb;  
            
            // specular
            vec3 viewDir = normalize(viewPos - FragPos);
            vec3 reflectDir = reflect(-lightDir, norm);  
            float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
            vec3 specular = light.specular * spec * texture(material.specular, TexCoords).rgb;  
            
            float theta=dot(lightDir,normalize(-light.direction));
            float epsilon=(light.cutOff - light.outerCutOff);
            float intensity=clamp((theta-light.outerCutOff)/epsilon,0.0,1.0);
            diffuse *= intensity;
            specular *=intensity;
    
            // attenuation
            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;   
                
            vec3 result = ambient + diffuse + specular;
            FragColor = vec4(result, 1.0);
    } 

你可能感兴趣的:(LearnOpeGl,unity,技术美术,游戏引擎,图形渲染,opengl)