# How to map intensity from dot product to float RGB from 0 to 1?

I'm getting the dot product of the surface normal and light position. The weird thing is the dot product is larger than 1.

Also, I want to map that intensity from 0->1 to Float RGB from 0->1. Here is my code related to the issue:

if (the_object->polys[curr_poly].shading == 1)
{
// compute the dot product between the light source vector
// and normal vector to surface
normal.x = normal.x / Vector_Mag_3D((vector_3d_ptr)&normal);
normal.y = normal.y / Vector_Mag_3D((vector_3d_ptr)&normal);
normal.z = normal.z / Vector_Mag_3D((vector_3d_ptr)&normal);

dp = Dot_Product_3D((vector_3d_ptr)&normal,
(vector_3d_ptr)&light_source);

// test if light ray is reflecting off surface

if (dp > 0)
{
// now cos 0 = (u.v)/|u||v| or

intensity = ambient_light + ( dp / (the_object->polys[curr_poly].normal_length));

float r = the_object->polys[curr_poly].color.R*intensity;
float g = the_object->polys[curr_poly].color.G*intensity;
float b = the_object->polys[curr_poly].color.B*intensity;
Color color = Color(r, g, b, 1);
// intensity now varies from 0-1, 0 being black or grazing and 1 being
// totally illuminated. use the value to index into color table

}


Updated code:

bool bOnce = true;

float normx = normal.x;
float normy = normal.y;
float normz = normal.z;
float mag;
if (bOnce)
{
bOnce = false;
mag =Vector_Mag_3D((vector_3d_ptr)&normal);
}

// compute the dot product between the light source vector
// and normal vector to surface
normal.x = normx / mag;
normal.y = normy / mag;
normal.z = normz / mag;

dp = Dot_Product_3D((vector_3d_ptr)&normal, (vector_3d_ptr)&light_source);


updated code version 2 :

if (dp > 0)
{
// now cos 0 = (u.v)/|u||v| or

intensity = ambient_light + ( dp / (the_object->polys[curr_poly].normal_length));

if (intensity > 1)
intensity = 1;
if (intensity < 0)
intensity = 0;

float r = (float)the_object->polys[curr_poly].color.R /intensity;
float g = (float)the_object->polys[curr_poly].color.G/intensity;
float b = (float)the_object->polys[curr_poly].color.B/intensity;
Color color = Color(r, g, b, 1);
// intensity now varies from 0-1, 0 being black or grazing and 1 being
// totally illuminated. use the value to index into color table



calculating normal vector of the polygon

void calculateNormalLenth(Rasterizer *rasterizer, object* the_object, int index)
{
unsigned int vertex_0, vertex_1, vertex_2;
vector_3d u, v, normal;           // working vectors
vertex_0 = the_object->polys[index].vertex_list[0];
vertex_1 = the_object->polys[index].vertex_list[1];
vertex_2 = the_object->polys[index].vertex_list[2];

// the vector u = vo->v1

rasterizer->Make_Vector_3D((point_3d_ptr)&the_object->vertices_local[vertex_0],
(point_3d_ptr)&the_object->vertices_local[vertex_1],
(vector_3d_ptr)&u);

// the vector v = vo->v2

rasterizer->Make_Vector_3D((point_3d_ptr)&the_object->vertices_local[vertex_0],
(point_3d_ptr)&the_object->vertices_local[vertex_2],
(vector_3d_ptr)&v);

rasterizer->Cross_Product_3D((vector_3d_ptr)&v,
(vector_3d_ptr)&u,
(vector_3d_ptr)&normal);

// compute magnitude of normal and store in polygon structure

the_object->polys[index].normal_length = rasterizer->Vector_Mag_3D((vector_3d_ptr)&normal);
}

• If the dot-product is larger than 1, normalize the vectors first. – tkausl Oct 29 '16 at 10:34
• I normalized the vector as shown above – Ahmed Saleh Oct 29 '16 at 10:34
• You normalize normal but you don't seem to normalize light_source anywhere. – Tyyppi_77 Oct 29 '16 at 10:36
• normal.x = normal.x / Vector_Mag_3D((vector_3d_ptr)&normal); and the two following lines aren't correct, calculate the length once and use this one number for all three divisions. – tkausl Oct 29 '16 at 10:38
• @tkausl You could probably put all that into an answer. – Tyyppi_77 Oct 29 '16 at 10:38

First of all:

normal.x = normal.x / Vector_Mag_3D((vector_3d_ptr)&normal);
normal.y = normal.y / Vector_Mag_3D((vector_3d_ptr)&normal);
normal.z = normal.z / Vector_Mag_3D((vector_3d_ptr)&normal);


This is not normalization. After you divided x by the vectors length, the next call to Vector_Mag_3D will obviously calculate a new, smaller length, hence your vectors direction will change. Calculate the length once and divide all three axis by the same value.

Dot_Product_3D((vector_3d_ptr)&normal,
(vector_3d_ptr)&light_source);


After you fixed the first problem, at least normal should be normalized, what about light_source? Is it normalized? If not, normalize it.

If both vectors are normalized, the dot-product can only result in a number between negative one and one. If you still got a bigger number, either the vectors are not normalized or your dot-product calculation is wrong.

• see the updated code, is it correct ? what about mapping the intensity to the color, is it correct too ? – Ahmed Saleh Oct 29 '16 at 10:48
• That's hard to guess. Does the end result look correct on your computer screen? – Tyyppi_77 Oct 29 '16 at 10:51
• Whats the_object->polys[curr_poly].normal_length? What values can ambient_light have? In your updated code, the normalization should be in the if aswell, otherwise you might divide by a uninitialized float and get garbage values when bOnce is false. – tkausl Oct 29 '16 at 10:52
• normal_length is a precomputed normal using 3 vertices, and ambient_light is 0.5f – Ahmed Saleh Oct 29 '16 at 11:54
• But normal_length is a scalar, right? If thats the length of the resulting normal-vecor, shouldn't it be always one? (I might be wrong, though). Anyway, since the dot-product can be in the range -1 to 1, and if ambient_light is 0.5, and if the_object->polys[curr_poly].normal_length is 1, then the range of intensity is -0.5 and 1.5. You should clamp it to ambient_light and 1.0 (since the intensity can not be lower than ambient intensity). – tkausl Oct 29 '16 at 11:58