Course list http://www.c-jump.com/bcc/
Mimic lights that are far, far away, thus having the same direction for every point in the scene.
Using directional lights simlifies math.
Mimic the light sources that are near the scene or within the scene:
street lights, ceiling lights, desk lamps, etc.
A lighting model is an algorithm, a mathematical function, that determines how a surface interacts with light.
Required reading:
Learning Modern 3D Graphics Programming Chapter 9. Lights On
lighting tutorial by Lighthouse3d.com
The base object color can be described by its "material"
The light source has a color of light
Materials and lights can have four individual color components:
Ambient, Diffuse, Specular, and Emit
Each component can contribute to the final color of the pixel by using formula:
vec4 final_color = vec4( 0, 0, 0, 1 ); vec3 color = vec3( R, G, B ); final_color = vec4( final_color.rgb + color * intensity, 1.0 );
OpenGL clamps colors that it writes to the output image to the range [0, 1]. Any light intensity that exceeds 1.0, whether alone or combined with other lights, can cause unpleasant visual effects.
Lighting of a surface is made up of the following independent components:
Diffuse – the closest to the term "color" of an object
Specular – the "shininess" of the object. This light is reflected more strongly in a particular direction. Its color is related to the color of the light source.
Ambient – a minimum amount of light to simulate "global illumination" of the environment. Preventis unlit areas from becoming too dark.
Emit – a "glowing" object
|
|
The diffuse light intensity equals cosine between the vector pointing towards the light (L) and the normal vector (N) to the surface
The cosine can be computed based on the dot product:
|
|
|
|
Sample code from Learning Modern 3D Graphics Programming Chapter 9. Lights On:
|
|
The light calculation can be done in the world space or in the camera space. Using world space is very common. The model matrix mM transforms vertex positions into the world space. We compute it on the CPU side and then pass it to the GPU via uniform variable:
mM = mtx_trans * mtx_all_rot * mtx_scale;
Here, mtx_all_rot includes all rotations. Although it could be used to transform normals from model to world space, scaling of objects also affects the direction of normal vectors. A standard way to transform normals into the world space is to use the transposed inversed model matrix. Its calculation can be done in the vertex shader:
mat4 tiM = transpose( inverse( mM ) ); fN = ( tiM * vNormal ).xyz;
However, the vertex shader recomputes tiM for every vertex, which is inefficient. A better way is to compute the normal rotation matrix mR on the CPU side
myModel->mR = glm::transpose( glm::inverse( myModel->mM ));
and then pass it to the vertex shader as an additional uniform variable:
uniform mat4 mR; // matrix only for rotation of normals out vec3 fN; // interpolated and sent to the fragment shader //... void main () { fN = ( mR * vNormal ).xyz; // transfrom normal vectors //...
The light position is also given in the world space. To use a light source that rotates with the model (e.g. rotating desk with a desk lamp on it), use the following modification for the previous vertex shader:
// UPDATE! -- rotate the light source vec3 rotating_light = normalize( mRotations*vLight ).xyz;
And then in your fragment shader:
float cos_incidence = dot( normal_in_cam_space, rotating_light );
The angle between the surface normal and the light source vector is called the angle of incidence of the light.
GLSL smooth type qualifier is one of the interpolation qualifiers in GLSL. The value is interpolated in a perspective-correct fashion. This is the default if no qualifier is present.
// Declaration in vertex shader smooth out vec4 interpolated_color; // Declaration in fragment shader smooth in vec4 interpolated_color;
Other choices are flat and noperspective. See http://www.opengl.org/wiki/Type_Qualifier_(GLSL) article for details.
|
|
|
|
The impact of shininess on the specular light
float Is = pow( max( dot( N, H ), 0.0), shininess );
will vary per pixel as follows:
|
|
|
|
|
Sources of lights cannot be seen -- only their effects
As demonstrated, OpenGL supports
light per vertex (fast),
light per fragment (slower)