This project is about the introduction of lighting concepts and model loading
Software Used
Languages Used
Visual Studio
C++
Explanations
Dot Product
The Cross Product
Optimization: Back-face Culling
Back-face Culling
What is a “Normal”?
Face Normals
What is Light?
Problems with simulating actual photons
Lambertian Reflectance
Specular Reflectance
Basic Types of Light Sources
Directional Light Formula
Point Light Formula
Spot Light Formula
Ambient Term
Light Attenuation [Linear]
Specular Component
Adding Vertex Lighting (Gouraud Shading)
Adding Per-Pixel Lighting (Phong Shading)
Physically Based Rendering
Code
Main
Defines
3D Math
Shaders
Raster Functions
Draw star field
Triangle drawing routine that supports 3D, Texturing and apply Near plane clipping
Load and Draw (including texturing) indexed geometry
Add Directional and Ambient lighting
Add Point light with expanding/shrinking radius (includes attenuation)
dot_product
> dot product between two vectors with x,y,z components
cross_product
> cross product between two vectors with x,y,z components
vec3_normalize
> normalize a vector with x,y,z components
combine_colors
> additively combine two colors
modulate_colors
> multiplicatively combine two colors
saturate
> clamps a value between 0 and 1
vec3_length
> computes the vectors length
Here are some important values for your lights before we begin the lighting routine.
Directional Light: direction = -0.577, -0.577, 0.577; color = 0xFFC0C0F0
Point Light: pos = -1, 0.5, 1; color = 0xFFFFFF00
In order to do lighting we will accomplish this in the vertex shader. We will do per-vertex lighting and store the current lighting color in the vertex’s color data member. In the vertex shader you will transform the vertex’s position and normal into world space by multiplying them by the world matrix.
The Dot Product
Can be used to determine the relationship between two vectors of equal length.
A result of ZERO indicates the two vectors are perpendicular to one another.
A result of 1 or -1 indicates the two vectors are PARALLEL to each other.
It is often important to NORMALIZE vectors before calculating the Dot Product.
The Cross Product
Given two 3D vectors of any length, the cross product can be used to solve a third vector that will be PERPENDICULAR to both.
Notice that any two non-equivalent 3D vectors will form a plane.
The Cross-Product can be used to find the GRADIENT of that plane.
Both the cross product & dot product will come in handy when we start to look at how light should interact with our surfaces.
Optimization: Back-face Culling
Back-face Culling
By winding all of our triangles based on the direction we wish to see them, it becomes possible to detect which side we are looking at using the cross product.
By ignoring “hidden” triangles (such as on the opposite facing side of this cube) we can dramatically decrease time spent rasterizing surfaces that will be obscured anyway.
You can add this check with only a few lines extra lines of code at the top of your triangle drawing routine.
What is a “Normal”?
Remember the “Gradient” from lesson 2? It was a 2D vector perpendicular to the direction of a line.
In a similar fashion a “Normal” is a 3D vector perpendicular to the surface of a plane.
In both cases each one represents whichever direction is considered “Up” relative to that primitive.
Unlike the gradient however, which can be any length. A normal is meant to be “unit length” which indicates it has a magnitude of one.
A triangle’s normal can be found easily by using the cross product and then “normalizing” the resulting 3D vector.
To normalize a vector simply divide each component (xyz) by the current length of the vector.
Face Normals
These are the “true” normals of each primitive in a given mesh. They are calculated as previously shown.
Each vertex assigned to the primitive shares this same exact normal.
As you will see, normals may be used to estimate how much light a surface should receive.
When used to shade a surface, they create a very “faceted” appearance, since each normal reflects the true surface geometry underneath.
Vertex Normals
Unlike face normals, vertex normals are stored independently for each vertex.
Because of this, vertices on a single primitive can actually be different from one another.
By averaging face normals between overlapping vertices, we can simulate smoother surfaces than we actually have access to.
This comes in handy when shading surfaces that are supposed to be more smooth or organic in nature.
What is Light?
Problems with simulating actual photons
Lambertian Reflectance
his refection model is a simple way to approximate the behavior of a perfectly “lambertian” surface.
A lambertian surface, is a material that absorbs and then randomly scatters all outgoing light rays. (perfect diffusion)
A point on this surface appears to be the same luminance regardless of the angle of the observer.
This is fair approximation of the behavior of very rough or “matte” surfaces such as wood or unpainted dry clay.
Specular Reflectance
Unlike lambertian reflectance, specular reflectance is designed to mimic photons bouncing off of the material’s surface before being absorbed & emitted.
This is an effective model for producing the various “highlights” on shiny surfaces.
Generally most visual surfaces can be represented using some combination of lambetinan & specular reflectance.
There are of course some exceptions to this however…
Basic Types of Light Sources
Directional Light Formula
LIGHTRATIO = CLAMP( DOT( -LIGHTDIR, SURFACENORMAL ) )
RESULT = LIGHTRATIO * LIGHTCOLOR * SURFACECOLOR
Directional light sources are actually point light sources at an infinite distance. This assumption works well enough for highly distant light sources such as the Sun.
Point Light Formula
LIGHTDIR = NORMALIZE( LIGHTPOS – SURFACEPOS )
LIGHTRATIO = CLAMP( DOT( LIGHTDIR, SURFACENORMAL ) )
RESULT = LIGHTRATIO * LIGHTCOLOR * SURFACECOLOR
A point light emits light in all directions. To determine the specific incoming light direction for a surface, you must use vector subtraction to solve the vector between the two points.
Spot Light Formula
LIGHTDIR = NORMALIZE( LIGHTPOS – SURFACEPOS ) )
SURFACERATIO = CLAMP( DOT( -LIGHTDIR, CONEDIR ) )
SPOTFACTOR = ( SURFACERATIO > CONERATIO ) ? 1 : 0
LIGHTRATIO = CLAMP( DOT( LIGHTDIR, SURFACENORMAL ) )
RESULT = SPOTFACTOR * LIGHTRATIO * LIGHTCOLOR * SURFACECOLOR
The spot light is essentially a point light which has been restricted to a cone pointed in a specific direction. The dot product is used to determine if the point falls within the cone.
Ambient Term
LIGHTRATIO =
CLAMP( LIGHTRATIO +
AMBIENTTERM )
While far from realistic, the ambient term helps to fill in the missing sense of scattered light within a scene.
Different environments may have significantly different ambient terms. (ex: Cave vs Beach)
Light Attenuation [Linear]
Falloff by Radius
ATTENUATION =
1.0 – CLAMP( MAGNITUDE( LIGHTPOS – SURFACEPOS ) / LIGHTRADIUS )
ATTENUATION =
1.0 – CLAMP( MAGNITUDE( LIGHTPOS – SURFACEPOS ) / LIGHTRADIUS )
Falloff from Cone Edge
ATTENUATION =
1.0 – CLAMP( ( INNERCONERATIO – SURFACERATIO ) / ( INNERCONERATIO – OUTERCONERATIO ) )
To make any falloff [Quadratic], simply multiply the attenuation by itself.
A quadratic curve is much closer to how lights lose energy over distance.
Specular Component
VIEWDIR =
NORMALIZE( CAMWORLDPOS – SURFACEPOS )
HALFVECTOR =
NORMALIZE(( -LIGHTDIR ) + VIEWDIR )
INTENSITY = MAX( CLAMP( DOT( NORMAL, HALFVECTOR ))SPECULARPOWER , 0 )
REFLECTEDLIGHT = LIGHTCOLOR * SPECULARINTENSITY * INTENSITY
Specular highlights represent light that is reflected from a surface to your eye. This adds an extra level of detail & realism to a surface. (ADD this to a light’s lambertian result)
Adding Vertex Lighting (Gouraud Shading)
Adding Per-Pixel Lighting (Phong Shading)
Physically Based Rendering
Modern real-time computer graphics has started to embrace more physically accurate light transport models such as Cook-Torrence.
Unlike models such as Blinn-Phong which are approximations based on observation, these computations are based on physical material properties and how they actually interact with light. (Dielectrics & Metals)
The cost of such shading, while significantly higher does produce more accurate results for a surface under a variety of different lighting conditions.