# Lighting

Created | |
---|---|

Tags | graphics |

# Overview

Lighting is the technique that models how light interacts with surfaces.

Realistic lighting can be approximated using three terms to model different species of light that occur in a scene: ambient, diffuse, and specular color.

Th colors terms are blended between the light sources and the surface material and multiplied by an intensity. The intensity of each component is determined by the light equation.

color = ambient + diffuse + specular

# Light types

## Directional

- Assumes the light is coming uniformly from one direction.

- Appears to illuminate all objects with equal intensity, as if it were at an infinite distance from the objects.

- Has a direction.

- Do not have a position.

A directional light intensity is defined by the angle between the reverse light direction and the surface normal.

A direction light is far enough away so that its rays can be considered to be hitting the surface of an object all in parallel, like the sun.

## Point

- A point light source radiates light equally in all directions from its position.

- Has a position.

- Do not have a direction.

- Characterized by an attention relative to its distance with the surface.

A point light intensity is defined by the angle between the direction from the vertex to the the light and the surface normal.

The calculation is typically done in world space, so the input vertex position is multiplied with the world transform in the vertex shader, and passed to the fragment shader.

## Spot

- A spot light emits a cone of light. Only objects within the cone are illuminated.

- Has a position.

- Has a direction.

- The cone produces light of two degrees of intensity:
- a central brightly lit section (the umbra) that acts as a point source.

- a surrounding dimly lit section (the penumbra) that merges with the surrounding deep shadow.

## Parallel Point

- Has a position.

- Has a direction.

- Behaves light a directional light but only lit the vertices that are on the side that faces the position of the light.

# Light terms

## Ambient

An ambient light describes a light source that illuminates everything in a scene, regardless of the orientation, position, and surface characteristics of the objects in the scene.

An ambient light is not characterized by a position or a direction.

It is an approximation of indirect light (light that has bounced off other surfaces in the scene).

Ambient lighting prevents the parts of geometry that are not directly lit from being completely black.

Calculated from the product of a material ambient color and a light ambient color.

Ambient = MaterialColor * LightColor

## Diffuse

A diffuse color is the color of an object given by direct illumination.

It represents the tendency of surfaces to reflect light equally in all directions.

Diffuse light follows Lambert’s cosine law.

The direction of the light is negated to obtain the proper direction vector.

The intensity of the reflected light is directly proportional to the cosine of the angle between the normal of the surface and the direction of the light.

The normal direction and light direction vector are unit vectors, so the cosine is equal to the dot product between these vectors.

Diffuse = MaterialColor * LightColor * (NormalDirection . LightDirection)

A dot product can produce values in the [-1, 1] range. A negative value indicates that the face is oriented away from the light source and should not receive any contribution from it. Therefore, the result is restricted to the [0, 1] range.

For point lights, the light attenuation is calculated.

For spot lights, the light attenuation and light falloff is calculated.

## Specular

The specular color is the bright highlight of a shiny object.

It represents the tendency of surfaces to reflect light in a particular direction rather than scatter it in all directions.

The specular color is calculated using the direction to the viewer's eye.

The shininess is used to convert the specular highlight from a linear falloff to an exponential falloff. The shininess is quantified by a specular power value. Lower values are more matte and higher values are shinier.

Shininess is the opposite of roughness, which is a different representation of surfaces.

There are different lighting models to compute the specular term.

### Blinn-Phong

The Blinn-Phong specular term uses the vector that points *halfway* between the direction to the light source and the direction from which the surface is viewed.

HalfwayDirection = (LightDirection + ViewDirection) / 2

A more stable calculation is to compute the halfway vector by normalizing the sum of light direction and view direction.

HalfwayDirection = normalize(LightDirection + ViewDirection)

The intensity of the reflected light is directly proportional to the cosine of the angle between the normal direction and the halfway direction. As these are unity vectors, the value is computed using their dot product.

A dot product can produce values in the [-1, 1] range. Therefore, the result is restricted to the [0, 1] range.

An optimization is to replace the view direction by a unit direction on the z-axis to simulate points at a viewpoint infinitely distant on the z-axis.

Finally, the result is raised to the specular power value.

For point lights, the light attenuation is calculated.

For spot lights, the light attenuation and light falloff is calculated.

Specular = MaterialColor * LightColor * (NormalDirection . HalfwayDirection) ^ SpecularPower

# Light Attenuation over Distance

The light attenuation is determined from the distance between a light source and the vertex being lit.

If the distance is within the light's range applies the following formula is used to calculate light attenuation over distance:

`A = 1 / (Attenuation0 + D * Attenuation1 + D*D * Attenuation2)`

A is the calculated total attenuation and D is the distance from the light source to the vertex. Attenuation0, Attenuation1, and Attenuation2 are attenuation constants that act as coefficients in the formula to obtain a variety of attenuation curves.

# Spot Light Falloff

Spot lights emit a cone of light that has two parts: a bright inner cone and an outer cone.

Light is brightest in the inner cone and isn't present outside the outer cone, with light intensity attenuating between the two areas.

This type of attenuation is commonly referred to as falloff.

The falloff is calculated by the dot product of the spot light's direction vector and the vector from the vertex to the light.

This value is equal to the cosine of the angle between the two vectors, and serves as an indicator of the vertex's position that can be compared to the light's cone angles to determine where the vertex might lie in the inner or outer cones.

`Cosine = (VertexToLightDirection . SpotLightDirection)`

This value is compared to the cosine of the spotlight's inner and outer cone angles.

- If the value is less than or equal to the cosine of the outer cone angle, the vertex lies beyond the outer cone and receives no light.

- If the value is greater than the cosine of the inner cone angle, then the vertex is within the inner cone and receives the maximum amount of light.

# Lighting Model

We use an approximation consisting of three terms to model different species of light that occur in a scene: ambient, diffuse, and specular.

Th color component is blended between the light and the material and multiplied by a different intensity. The intensity of each component is determined by the light equation.

## Phong

The light calculations are done per pixel, in camera space.

In the vertex function, we convert the positions and directions into camera space.

### Vertex

- Calculate the position of the object from the perspective of the camera

**float4** position_model = **float4**(input_position, 1);
position_model = modelViewProjection_transform * position_model;

- Calculate the normal from the perspective of the camera

**float3** normal_model = float4(input_normal, 0);
normal_camera = (normalize(modelViewProjection_transform * normal_model.xyz);

- Calculate the view vector from the perspective of the camera

**float3** position_camera = (modelView_transform * position_model).xyz;
eyeDirection_camera = float3(0,0,0) - position_camera;

- Calculate the direction of the light from the position of the camera

```
float3 lightPosition_camera = (view_transform * float4(lightPosition, 1)).xyz;
lightDirection_camera = lightPosition_camera + eyeDirection_camera
```

### Fragment

- The ambient color is constant.

**float4** ambientColor = materialAmbientColor;

- Calculate the diffuse color using the dot product between the surface normal and the light vector to estimate how much the surface is facing towards the light.

**float3** n = normalize(normal_camera);
float3 l = normalize(lightDirection_camera);
float n_dot_l = saturate(dot(n, l));
float4 diffuseColor = lightColor * n_dot_l * materialDiffuseColor;

- Calculate the specular color using the dot product to calculate how close the reflection of the light is pointing towards the viewer. The angle is raised by the shininess factor to control the size of the highlight.

**float3** e = normalize(eyeDirection_camera);
float3 r = -l + 2 * n_dot_l * n;
float e_dot_r = saturate(dot(e, r));
float intensity = pow(e_dot_r, materialShininess);
float4 specularColor = materialSpecularColor * lightColor * intensity;

- Combine the ambient, specular and diffuse colors to get the final color

`color = (ambientColor + diffuseColor + specularColor);`

## Deferred Lighting with Shadow Maps

Requires two passes, four color buffers (including two g-buffers), a depth buffer and a stencil buffer.

- A shadow pass draw the scene from the perspective of the directional light to the depth buffer to find out which pixel is occluded.

- A deferred lighting pass to generate g-buffer attributes to apply the point light volume to find out which pixel is affected. Use the light accumulation to generate the final color in the frame buffer.

# Reflection

Reflection occurs when light bounces off of a reflective surface.

In a mirror reflection, all light bounces off at an angle equal to its incident angle.

To simulate reflection, a cubic texture is sampled using the reflected vector as the texture coordinates.

# Refraction

Refraction occurs when light passes from one medium to another.

The amount the light bends is proportional to the ratio between the indices of refraction of the two media it is passing between.

The index of refraction of a substance is a quantity that characterizes how much it slows down the propagation of light, relative to a vacuum.

Refraction follows the *Snell’s law* which states that the ratio of the sines of the incident and transmitted angles is equal to the inverse ratio of the indices of refraction of the media.

# Reflection & Reflection

- The
*normal*is perpendicular to the interface between the two media.

- The
*incident ray*is traveling toward the center of the image.

- The
*reflected ray*is traveling away from the center of the image.

- The
*refracted ray*is traveling away from the center of the image.

# Normal Mapping

Increase the apparent complexity of surfaces without using additional geometry.

Requires a normal and orthonormal axes (tangent and bitangent) for each vertex.

These three axes are the tangent frame.

# Image Based Lighting (IBL)

- Compute the radiance of a scene in all directions using an irradiance cubemap.

- Sample from this cubemap to get the quantity of incoming light.

### Vertex

Transform the position, normal and tangent vectors.

- Calculate the position of the object from the perspective of the camera

`out.position = modelViewProjectionTransform * in.position;`

- Calculate the normal and tangent from the perspective of the camera

```
out.normal = normalTransform * in.normal;
out.tangent = normalTransform * in.tangent;
```

- Calculate the bitangent as the cross product of the normal and tangent.

`out.bitangent = normalTransform * cross(in.normal, in.tangent);`

# Shadows

## Shadow Buffer

A shadow buffer is similar to a depth buffer.

It stores depth information from the viewpoint of a light source instead of from the viewpoint of the camera.

- For each light, render to the shadow buffer:
- Disable all color writes.

- Set a viewport to the dimensions of the shadow buffer.

- Clear that viewport of depth information.

- Set up the views and projections from the light's viewpoint.

- Render any objects in the scene that should be shadowed.

- Render the scene with shadows
- Enable all color writes.

- Reset the viewport dimensions

- Clear the viewport of color and depth informaiton.

- Set up the transformations.

- Set the shadow buffer in a texture stage.

- Render objects in the view frustum.

The shadow buffer works by comparing the z texture coordinate values with those values recorded in the shadow buffer.

A point is shadowed if the shadow buffer value is greater than the z texture coordinate.