# 3D Shading

## Seventh part of *The 3D Coding Blackhole* tutorial series

- Computing the Normals
- Doing the Cross Product
- Using a light table

## Computing the Normals

Ok... we deeply discussed vectors and normals in the 3D mathematics tutorial, so here are some implementations:

`float VEC_DotProduct(_3D Vector1, _3D Vector2) `

{

return (Vector1.x*Vector2.x+Vector1.y*Vector2.y+Vector1.z*Vector2.z);

}

_3D VEC_CrossProduct(_3D Vector1, _3D Vector2)

{

return P3D(Vector1.y*Vector2.z-Vector1.z*Vector2.y,

Vector1.z*Vector2.x-Vector1.x*Vector2.z,

Vector1.x*Vector2.y-Vector1.y*Vector2.x);

}

void VEC_Normalize(_3D * Vector)

{

float m=sqrt(Vector->x*Vector->x+Vector->y*Vector->y+Vector->z*Vector->z);

Vector->x/=m;

Vector->y/=m;

Vector->z/=m;

}

For 3D shading, you need to add to ** ENG3D_SetPlane**:

` //Compute the normal of the plane `

PlaneNormal=VEC_CrossProduct(P3D(x2-x1,y2-y1,z2-z1),P3D(x3-x1,y3-y1,z3-z1));

VEC_Normalize(&PlaneNormal);

## Doing the Cross Product

Now, as we said in the maths part, the cosine of the angle between two vectors is equal to their dot product when both vectors are normalized. To find the light reaching a plane, we simply add the ambient light to the cross product of the world coordinate of our normalized light source, multiplied by the maximal light intensity. Here's some code:

Global definitions:

` WORD AmbientLight=20; `

#define MAXLIGHT 32

static Vertex_t LightSource;

WORD light;

And in ** SetPlane**:

` //Compute light intensity from the dot product of the normal and of `

//the lightsource

light=MAXLIGHT*VEC_DotProduct(PlaneNormal,LightSource.World)+AmbientLight;

if(light>MAXLIGHT)light=MAXLIGHT;

if(light<1)light=1;

And you obviously need to initialize the light source, exactly like a normal vertex.

` //Initialize Light Source `

LightSource.Local=P3D(0,0,0);

MAT_Identity(matrix);

TR_Translate(matrix, 10,10,10);

TR_Rotate(matrix, 0,128-32,128);

VEC_MultMatrix(&LightSource.Local,matrix,&LightSource.World);

VEC_Normalize(&LightSource.World);

## Using a light table

A light table is a method of using light intensities on a palette based display. You find the best color match for every color at every intensity. Christopher Lampton made a great light table generator (makelite.cpp) in his book __ Gardens of Imagination__. Unfortunately, that one uses a module of his own for pcx, so you have the choice of either modying it yourself (actually, you only need to load the palette of the pcx, not the image) or using my own modification (makelite.c or makelite.exe). Once we have our light table, we load it in a global array:

`BYTE LightTable[MAXLIGHT+1][256];`

Once you've loaded it, all you need to change in your ** TEX_HLine** function is the following:

` screen[offset]=LightTable[light][color];`

*Copyright © 1996-1998 Jerome St-Louis*