Learnopungl notes - II. Lighting: "color", "basic lighting" and "material"

Posted by efron on Sun, 27 Feb 2022 08:27:31 +0100

2, Lighting: color, base lighting, and material

2.1 color

  • Colors that can be digitized are composed of three components: red, green and blue, which are usually abbreviated as RGB. Just use these three values to combine any color. For example, to obtain a coral color, we can define such a color vector:

    glm::vec3 coral(1.0f, 0.5f, 0.31f);
    
  • We set the light source to white. When we multiply the color of the light source by the color value of the object, we get the color reflected by the object (that is, the color we perceive)

    glm::vec3 lightColor(1.0f, 1.0f, 1.0f);
    glm::vec3 toyColor(1.0f, 0.5f, 0.31f);
    glm::vec3 result = lightColor * toyColor; // = (1.0f, 0.5f, 0.31f);
    
    • What happens if we use a green light source?
    glm::vec3 lightColor(0.0f, 1.0f, 0.0f);
    glm::vec3 toyColor(1.0f, 0.5f, 0.31f);
    glm::vec3 result = lightColor * toyColor; // = (0.0f, 0.5f, 0.0f);
    
  • Create a lighting scene -- omitted

2.2 basic lighting

  • Phong lighting model
    • Ambient light
    • diffuse lighting
    • Specular illumination
  • In order to calculate diffuse illumination and specular illumination, the data of surface normal vector needs to be input
  • Full pixel shader code:
    # version 330 core
    out vec4 FragColor;
    
    in vec3 Normal;
    in vec3 FragPos;
    
    uniform vec3 objectColor;
    uniform vec3 lightColor;
    uniform vec3 lightPos;
    uniform vec3 viewPos;
    
    void main()
    {
        // Ambient light
        float ambientStrength = 0.1;
        vec3 ambient = ambientStrength * lightColor;
    
        // Normalize both the normal and the final direction vector
        vec3 norm = normalize(Normal);
        vec3 lightDir = normalize(lightPos - FragPos);
    
        // The norm and lightDir vectors are point multiplied to calculate the actual diffuse emission influence of the light source on the current clip
        float diff = max(dot(norm, lightDir), 0.0);
        vec3 diffuse = diff * lightColor;
    
        // Define a specular intensity variable to give the specular highlight a medium brightness color so that it does not have excessive influence
        float specularStrength = 0.5;
    
        // Calculate the line of sight direction vector and the corresponding reflection vector along the normal axis
        vec3 viewDir = normalize(viewPos - FragPos);
        vec3 reflectDir = reflect(-lightDir, norm);
    
        // Specular component calculation
        float spec = pow(max(dot(viewDir, reflectDir), 0.0), 32);
        vec3 specular = specularStrength * spec * lightColor;
    
        // Calculation and
        vec3 result = (ambient + diffuse + specular) * objectColor;
        FragColor = vec4(result, 1.0);
    }
    


  • Gouraud coloring problem:
    • You can see (yourself or in the image provided) the clear difference between the two triangles in front of the cube. This "streak" is visible because of fragment interpolation. From the example image, we can see that the vertices in the upper right corner of the front of the cube are illuminated by highlights. Since the top right corner vertex of the lower right triangle is bright and the other two vertices of the triangle are not, the bright value is inserted into the other two vertices. So is the triangle in the upper left corner. Because the color of the middle pixel is not directly from the light source, but the result of interpolation, the illumination of the middle pixel is incorrect. The triangles in the upper left corner and the lower right corner collide in brightness, resulting in visible stripes between the two triangles.
    • This effect is more pronounced when more complex shapes are used.

2.3 material

  • texture of material

  • Properties of light
    • Full pixel shader code:
    #version 330 core
    out vec4 FragColor;
    
    struct Material {
        vec3 ambient;
        vec3 diffuse;
        vec3 specular;    
        float shininess;
    }; 
    
    struct Light {
        vec3 position;
    
        vec3 ambient;
        vec3 diffuse;
        vec3 specular;
    };
    
    in vec3 FragPos;  
    in vec3 Normal;  
      
    uniform vec3 viewPos;
    uniform Material material;
    uniform Light light;
    
    void main()
    {
        // ambient
        vec3 ambient = light.ambient * material.ambient;
      	
        // diffuse 
        vec3 norm = normalize(Normal);
        vec3 lightDir = normalize(light.position - FragPos);
        float diff = max(dot(norm, lightDir), 0.0);
        vec3 diffuse = light.diffuse * (diff * material.diffuse);
        
        // 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 * material.specular);  
            
        vec3 result = ambient + diffuse + specular;
        FragColor = vec4(result, 1.0);
    } 
    
  • Exercise: Emerald

Topics: 3d UE4