• Home
  • About
    • Muru Chen photo

      Muru Chen

      Game programmer, Game designer, photographer & Interactive media artist

    • Learn More
    • Email
    • LinkedIn
    • Github
  • Games
  • OpenGL
  • Interactive Arts

Multiple Lightings

Reading time ~1 minute

Directional light

photos of directional light

Calculate light direction

We can just define a light direction in Light class

    struct Light {
        vec3 direction;
        ...
    };
    ...
    void main()
    {
      vec3 lightDir = normalize(-light.direction);
      ...
    }

Point Light

photos of point light

Calculate Attenuation

reduce the intensity of light over the distance a light ray travels

attenuation
    struct Light {
        float constant;
        float linear;
        float quadratic;
        ...
    };
    ...
    void main()
    {
        float distance    = length(light.position - FragPos);
        loat attenuation = 1.0 / (light.constant + light.linear * distance + 
                light.quadratic * (distance * distance));
        ...
    }

Spot Light

We need: the spotlight’s position vector (to calculate the fragment-to-light’s direction vector), the spotlight’s direction vector and the cutoff angle.

spot light

Caculate Angles

We pass the cosine value because it is easier to compare

spot light angle
    struct Light {
        vec3  position;
        vec3  direction;
        float cutOff;
        ...
    };  
    lightingShader.setFloat("light.cutOff",   glm::cos(glm::radians(12.5f)));

calculate the theta θ value and compare this with the cutoff ϕ value to determine if we’re in or outside the spotlight:

if cosθ > cutOff, we can know that θ < ϕ

    float theta = dot(lightDir, normalize(-light.direction));
    
    if(theta > light.cutOff) 
    {       
      // do lighting calculations
    }
    else  // else, use ambient light
      color = vec4(light.ambient * vec3(texture(material.diffuse, TexCoords)), 1.0);

Smooth Edges

Set γ as outer cone angle value

intensity = (θ−γ) / (ϕ−γ)

    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;
    ...
Download codes


OpenGLC++ Share Tweet +1