Copy Link
Add to Bookmark
Report

3D Shading

DrWatson's profile picture
Published in 
atari
 · 27 Nov 2023

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

← previous
next →
loading
sending ...
New to Neperos ? Sign Up for free
download Neperos App from Google Play
install Neperos as PWA

Let's discover also

Recent Articles

Recent Comments

Neperos cookies
This website uses cookies to store your preferences and improve the service. Cookies authorization will allow me and / or my partners to process personal data such as browsing behaviour.

By pressing OK you agree to the Terms of Service and acknowledge the Privacy Policy

By pressing REJECT you will be able to continue to use Neperos (like read articles or write comments) but some important cookies will not be set. This may affect certain features and functions of the platform.
OK
REJECT