Monday, April 25, 2011

How lighting works

Simply rendering geometry and applying a color or texture won't get us too far down the realism path. To get more visually accurate renders we need to take into account light:

Skull with 1 point light

In 3D application lighting is essential to get us a realistic feel, rendering a sphere with no lights will make it look flat, or more exactly a circle, it's the surface lighting that actually makes the sphere look like a sphere. In this post I will explain what we will need to know about lights before implementing them. Please note that lighting only solves part of the problem, you will not see any shadows from an object on the ground (or other objects).


In real file light travels as rays, bounced around in the space and finally enters our eye. This causes a lot different effects. Because such computations are expensive we use lighting models, these models approximate how an object in a scene would have been illuminated by natural light.
Our model will be a simple sum of coefficients. Each one of these coefficients will be used to simulate a certain type of illumination.
Our light will be:

lightFactor = emissive + ambient + diffuse + specular

The emissive factor represents the amount of light that the objects cats itself. For example a light bulb should always be completely illuminated independent of how many other light are in the scene (considering the bulb is turned on). The emissive factor will be a simple constant number.

The ambient factor is the light the object receives from the environment. This is the light that is bounced around on all surfaces and then reaches our object, also known as indirect light. This light seems to come from all directions and is independent of any light sources. The factor itself should be calculated as:

Ka * ambientColor

where Ka is the ambiect reflection factor of the surface and ambientColor is the color of the ambiental light. Because of this an object with ambient light only will look very flat:

Skull rendered only with ambient light
What really gives our object shape is the light that travels from the source directly to our object and then is reflected in all directions, this is known as diffuse light. This is dependent of the light direction at the contact point and the surface normal:

The smaller the incidence angle (theta) is the more light is reflected (in all directions) by the object. Our diffuse term has to take all of these into account. Lambert's cosine law states that the amount of light diffusely reflected is directly proportional with the cosine of the incidence angle. To get this effect we will use the following ecuation:

diffuse = Kd * lightColor * max(0,N·I)

In this equation Kd is the diffuse factor of the surface, lightColor is the color of the light we are rendering with, N is the normal to the surface and I is the normalized inverted incidence vector. The middle dot is used to symbolize vector dot product. We use maximum to clamp remove any negative values as these represent light coming from behind the surface and not from it's front (if we don't do this the object will get illuminated on the opposite side of the light too and this should not happen). The diffuse light looks like this:

Skull rendered with diffuse light only
As you can see on the opposite side of the light the object is completely black, that's why we need ambient light.

But objects don't just reflect light in all directions, they also have more shiny surfaces that reflect a more focused light. The result will be highlights like the ones on the skull at the top, this are called specular highlights, here the skull is rendered with specular highlights only:

Skull rendered only with specular light
The equation to get this effect we have to take into account the angle between the viewer and the object too. To do this will use the vector that is halfway between the incident ray and the ray the observer is looking at the point. By doing a dot product between the Normal and this normalized vector we get the relation we need. Of course this will give us an effect similar to that of the diffuse term, to make the light decrease rapidly while the angle increases we must also raise the result from the dot product to a power. The higher the power the more shiny the object will look, in this sample I've used 100 as the power. The specular light equation looks like this:

specular = Ks * lightColor * max(N·H,0) ^ specularPower

In this equation Ks is the specular factor of the surface, lightColor is the color of the light, N is the normal of the surface, H is the normalized vector that is halfway between the normalized incidence vector (form object to light source) and normalized view vector (from object to observer).

By adding all of these together we will get something like this:

1 comment:

  1. The LED IES file needs to be manipulated by inserting the source lumen value for the "-1" within the IES file. Crystal Chandelier

    ReplyDelete