Ecere SDK

These tutorials, although still very informative and valuable, are somewhat obsolete and no longer supported.

Please visit ecere.org for my current cross platform Object Oriented, GUI & hardware-accelerated 3D Graphics technology.

3D Shading

Seventh part of The 3D Coding Blackhole tutorial series

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

www.ecere.com