Simple Lighting - Bring our
world to life
by
Ben Kenwright
Well adding a bit of a virtual light to our 3D demo's can make things
look a lot more realistic and enticing :) Won't be long now before your
looking at this demo and rubbing your eyes in disbelief ... wondering how you
can create such amazing demo's using such a simple thing as your browser and a
bit of java.
A simple lighting model we can introduce, is the directional light
model....and its really simple. We'll have the light model, on top of our
camera...so the light will be us, and as we move around, the light on the
triangle faces will change...darker or lighter depending if where facing them.
Thats our simple picture we have...but just so we know, we'll go over other
vectors that are involved here :)
Intensity=Ambient + Diffuse * (L • N)
But I have to go into the various other models and possible lightings, else I
wouldn't feel right. As I think they make sense...well they did to me -
its just a matter of looking at them long enough :) If you don't get it
after 3 hours of looking at it, I'd take a rest..hehe
We can expand the simple model above to include more vector's - more values
such as the viewers location and refection of light off the surface.
Intensity=Ambient + Diffuse * (L • N) + Specular * (R • V)^n
But the true model is never usually used - instead some people came up with
some relatively good approximations, which give a close representation to the
original model. its all by using the H vector.
Now we need to think of some optimisation tricks, as we can't go using the
reflection vector R, as it takes to much to calculate. So for our specular
part, we could use (L dot N) instead of (R dot V)....which is an okay
approximation, but not that realistic.
We can take it a bit further by adding H...which is the vector between Light
(L) and View (V)....(e.g. L+V/2 ).
What H has in common isn't easy to see at first, but we notice that H•V
proportional to R•V...in fact its a factor of 2! Dang that's lucky isn't
it....so we get this:
R•V = (H•V)*2
But then again, we can make a further little optimisation - as its a linear
relationship, so we can make a quick fix, and take away the multiplication of 2,
and modify our power n value to account for this. Saving one extra
calculation here and there soon adds up :)
We are really interested in that angle...the one between H and N ...which we
get using our dot product again...so we have H•N
Intensity=Ambient + Diffuse * (L • N) + Specular * (H • N)^n
Putting this into code - Ambient and Diffuse.
Well we'll only use a simple flat shaded model for our simple applet demo to
start with. We can always re-visit our lighting model later on...as we
might add in the specular code later on...but basic lighting first I think :)
So we'll use this model for basics:
Intensity = Ambient + Diffuse*(L•N)
And remember, we have a Red, Green and Blue intensity, so what you really
have is this:
Ir = A + D*(L•N)
Ig = A + D*(L•N)
Ib = A + D*(L•N)
I've chosen to use A - Ambient, and D - Diffuse, so its easier to type :)
When we go into code, we'll have to make sure of a number of things, as we
want to clip our values, so they are limited to 0-255, as each colour part is
only a 8 bit value.
So we choose A and D so that our Intensity value goes from 0 to 1. Well
make A = 0.3 (or 30%) and D = 0.7 (or 70%).
Flat Lighting -
Download Applet Source Code |
...
void
AddFlatLighting(Triangle
t[],
int
iNumTris)
{
// Ideally:
// Intensity=Ambient + Diffuse * (L • N) + Specular * (R • V)^n
float
PercentageAmbient =
0.3f;
float
PercentageDiffuse =
0.7f;
for(int
i=0; i<iNumTris; i++)
{
Color origColour = t[i].c;
float
red =
origColour.getRed();
float
green =
origColour.getGreen();
float
blue =
origColour.getBlue();
Vector3 vLight =
new
Vector3(0,0,1);
vLight = Vector3.normalize(vLight);
Vector3 vTriNormal = t[i].tn;
float
fDiffuse = Vector3.dot(
vLight, vTriNormal );
if( fDiffuse < 0.0f )
fDiffuse = 0.0f;
int
newred = (int)(red*PercentageAmbient
+ red*PercentageDiffuse*fDiffuse);
int
newgreen = (int)(green*PercentageAmbient
+ green*PercentageDiffuse*fDiffuse);
int
newblue = (int)(blue*PercentageAmbient
+ blue*PercentageDiffuse*fDiffuse);
t[i].tc =
new
Color(newred, newgreen, newblue);
}// End for loop i
}// End AddFlatLighting(..)
... |
|