15,609,601 members
Articles / Programming Languages / C#
Article
Posted 6 Sep 2007

50.7K views
57 bookmarked

# SamplePamper Series - Part 1: 3D-Light, Flat-shading and Rotations

Rate me:
This article is one in a series for those who want to know about 3D when it comes to calculation of the light falling on a surface. It will explain in an easy manner for those who don't want to see all those graphical formulas in Greek, as they can be very confusing. Not just for use in C#

## Introduction

This article is Part One of the Sample Pamper series and will apply to those of you who want to know about 3D programming when it comes to shading and lightning of a surface. The most irritating thing for a beginner as I can recall is to see all formulas and signs as we might not know much about them and are only confused by them. Therefore I wanted to ease the pain and show everything more concrete with some complete examples without embedding it into nice objects with interfaces, matrices and the use of DirectX / OpenGL or Glut. Although, there will still be formulas, they will not be the graphical ones in Greek. So there is no fancy code in these examples, but just the important things for learning.

## Requirement

You will need a computer and a calculator to try to find the results by yourself. You must have either Visual Studio .NET or Macromedia Flash 8 installed to try the downloadable source codes. Paper and a pen would be good to be able to do the matrix multiplications. Then you're ready to go!

## The story

When we're drawing a surface in a 3D-environment and want to calculate how the light should fall, we can then use the cross product of two vectors on that surface to get the Normal vector and the Dot product to compute the angle between the Normal and the light vector. What the Normal vector is will be explained soon, hold on.

## The example

This example is a "Flat-shade" which means that the illumination stays constant across the surface. The Normal vector is not actually constant across the polygon surface as we assume when using the "Flat-shading", but it is the first step into the other level of knowledge. Now pretend that we are calculating the light for this surface:

Here we must know the location of the points `(P 0-2)` of the surface and the direction and position `(LP 0-1)` of the light coordinates in space. We can imagine that `P0` has the coordinates `x=5`, `y=10 `and `z=-6` and the point `P2` is `x=8`, `y=1` and `z=-3`, and finally the third point `P1` which has the coordinates`x=2.5`, `y=6` and `z=4`.

### Calculating vector length

We must now also calculate the length of `U` and `V `that will give us the following values:

```Ux = (P2x – P1x) = (8 – 2.5) = 5.5
Uy = (P2y – P1y) = (1 - 6) = -5
Uz = (P2z – P1z) = ((-3) - 4) = -7```

And now we will do the same for the `V `vector:

```Vx = (P2x – P0x) = (8 - 5) = 3
Vy = (P2y – P0y) = (1 - 10) = -9
Vz = (P2z – P0z) = ((-3) - (-6)) = 3```

### The Normal vector

To be able to calculate the light against this surface, we must also have one more vector to know how much light will fall on it. This vector is called the Normal vector. The Normal vector is a vector that will stand out 90 degrees from the surface and to find this vector, we must use something called the Cross product, that is a mathematical way of handling already existing number coordinates on a surface to retrieve this Normal one. In this figure you can see the Normal vector sticking out from the surface front side and being lit on the backside by the light. `U `is the vector between `P1 `and `P2 `and `V `is the vector between point `P2 `and `P0`. The Cross product that follows will use these vectors `U `and `V `to build the `N `vector.

### The cross product

`U X V = |U| * |V| * sin * n`

Where `|U|` denotes the length of vector `U `and `|V|` of vector `V`, and `sin` is the angle between them, and `n` is a unit vector.

### Crossing the matrix

To get `Nx`, cross like the lines in the matrix, explained more below.

There are more things to add into this, but I'm going to exclude them because they are not needed, like the tree unit vectors parallel to the `x`, `y`, and `z`-axes. We compute the cross product of `U` and `V` and start by retrieving the Normal vectors `x` direction (`Nx`) by crossing in the matrix like this:

`Nx = Uy * Vz – Uz * Vy =  (-5 * 3) – (-7 * -9) = -78`

Then we are going to do the same for `Ny`, like this:

`Ny = Uz * Vx – Ux * Vz = (-7 * 3) – (5.5 * 3) = -37.5`

And finally to find the (`Nz`) which should be a negative value in our case (seen in the picture with the surface):

`Nz = Ux * Vy – Uy * Vx = (5.5 * -9) – (-5 * 3) = -34,5`

In these numbers, you can see that the normal vector will have a negative path in the `x`, `y`, and `z`–axes. This points down to the left and into the picture.

### To normalize

Then you must also normalize it by dividing by the length to get the `n `(which is a normalized normal (`N`) vector).

```|N| = sqrt(Nx^2 + Ny^2 + Nz^2) = sqrt(78^2 + 37.5^2 + 34.5^2) = 93.17

n = N / |N| = N / 93.17

nx = Nx / |N| = -78 / 93.17 = -0.84
ny = Ny / |N| = -37.5 / 93.17 = -0.4
nz = Nz / |N| = -34.5 / 93.17 = -0.37```

### The light vector

Now we must compute the vector of the light as we will set to the point (`LP0`) `x=12`, `y=8`, `z=0` and (`LP1`) to `x=5`, `y=6`, `z=0`, and then calculate the vector parts like in the following:

```Lx = (LP0 x – LP1x) = (12 - 5) = 7
Ly = (LP0y – LP1x) = (8 – 6) = 2
Lz = (LP0z – LP1z) = (0 - 0) = 0```

And this must also be normalized to make sense to us.

```lx = Lx / |L| = 7 / sqrt(7^2+2^2+0^2) = 0.96
ly = Ly / |L| = 2 / sqrt(7^2+2^2+0^2) = 0.28
lz = Lz / |L| = 0 / sqrt(7^2+2^2+0^2) = 0```

### The Dot product

There we have it, now you can plug this into another mathematical function, as is the Dot product. We will use this equation to find the angle between the normal and the light vector and it looks like this:

```N . L = |N| * |L| = nx * lx + ny * ly + nz * lz

x = -0.84 * 0.96 + -0.4 * 0.28 + -0.37 * 0 = -0.92```

A negative value means that the light is falling on the backside of the surface as you can see in the picture. Now if you take the inverted sine of the result of `x`, you'll get the angle between the light and the normal vector around –67 degrees, which means that the surface is being lit on its backside by a 67 degree angle. Now you can use this `x `variable to multiply it by the color of the surface to get the shading effect you want. This is called flat shading and is not used so much anymore because it gives the surface a false look when it is lit by a constant all over it. However, it is a good start to get to know about putting light into the picture.

### The rotation matrices

I will also explain rotation around the `x` and `y`-axes here because I've implemented it in the .zip downloadable source code file. It will rotate the polygon surface around the `x` and `y`-axes. If you know how to do a multiplication of matrices then it will be easy for you to add the third one to also be able to rotate around the `z`-axis on your own. This will be briefly explained in this following part.

I guess you have heard about the rotation matrices before, they look like this.

And yes, there is one more for the rotation round the `z`-axis, but I will exclude it from this article.

### The matrix multiplication

The matrix to the left is rotation around the `x`-axis and the one to the right for rotation round the `y`-axis. Now as you can see in the GIF animation above, we are multiplying these matrices together which will result into the following matrix.

Now you have your combined matrix for rotation around both the `x `and the `y`-axis at the same time. We leave the fourth column and row out because those are only needed for translation. To start rotating your surface, you must plug the points `P(0-2)` and the new matrix into a new formula.

```P0newX = (P0x * CoY) + (P0y * 0) + (P0z * -siY)
P0newY = (P0x * (siX * siY)) + (P0y * coX) + (P0z * (siX * coY))
P0newZ = (P0x * (coX * siY)) + (P0y * -siX) + (P0z * (coX * coY))```

This will give you the new position of the point `P0` and you'll have to do the same for all the remaining points to rotate.

```P1newX = (P1x * CoY) + (P1y * 0) + (P1z * -siY)
P1newY = (P1x * (siX * siY)) + (P1y * coX) + (P1z * (siX * coY))
P1newZ = (P1x * (coX * siY)) + (P1y * -siX) + (P1z * (coX * coY))```

And the point `P2` is as follows:

```P2newX = (P2x * CoY) + (P2y * 0) + (P2z * -siY)
P2newY = (P2x * (siX * siY)) + (P2y * coX) + (P2z * (siX * coY))
P2newZ = (P2x * (coX * siY)) + (P2y * -siX) + (P2z * (coX * coY))```

That's it! To see the example, choose the zip that will suit you and download it to play around with it.

## Points of Interest

There are two samples to play around with, one in C# and the other for Macromedia Flash 8. If you want to step even further and learn about the reflection vector, you can hold your eyes wide open for Part Two of this series.

## History

• Version 1.0, uploaded 6 September, 2007
Two versions included for the article, one for C# and the other for Macromedia Flash 8

## References

### Books

• "Tricks of the Windows Game programming gurus – Fundamentals of 2D and 3D game programming". Vol1 - (SAMS) by André LaMothe ISBN: 0-672-31361-8

This software is provided 'as-is' without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose including commercial applications. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. And never could you claim that it is yours.

Written By
Sweden
Professional programmer, degree in Informatics and Applied Systems Science.

 First Prev Next
 The best example code in my life dummy@pawelwoo.com16-Jun-11 13:51 dummy@pawelwoo.com 16-Jun-11 13:51
 Re: The best example code in my life Windmiller20-Sep-11 10:16 Windmiller 20-Sep-11 10:16
 Thank you for telling me, I'm glad it helped you! Despite all the missleading characters that suddenly appeared in this article from a server update Code Project did a couple of years ago, and some pictures are missing. They didn't fix it after that update incident, sorry about that. Thanks again Regards, Morgan The day I became a WhuShu coder..
 Excellent andalmeida6-Sep-07 5:07 andalmeida 6-Sep-07 5:07
 Re: Excellent Windmiller8-Sep-07 3:23 Windmiller 8-Sep-07 3:23
 Re: Excellent andalmeida8-Sep-07 3:34 andalmeida 8-Sep-07 3:34
 Last Visit: 31-Dec-99 18:00     Last Update: 23-Mar-23 14:29 Refresh 1