0
\$\begingroup\$

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

        the_object->polys[curr_poly].shade = color.ToUInt32();
}

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

                    the_object->polys[curr_poly].shade =  color.ToUInt32();

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);
}
\$\endgroup\$
  • 1
    \$\begingroup\$ If the dot-product is larger than 1, normalize the vectors first. \$\endgroup\$ – tkausl Oct 29 '16 at 10:34
  • \$\begingroup\$ I normalized the vector as shown above \$\endgroup\$ – Ahmed Saleh Oct 29 '16 at 10:34
  • \$\begingroup\$ You normalize normal but you don't seem to normalize light_source anywhere. \$\endgroup\$ – Tyyppi_77 Oct 29 '16 at 10:36
  • 1
    \$\begingroup\$ 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. \$\endgroup\$ – tkausl Oct 29 '16 at 10:38
  • \$\begingroup\$ @tkausl You could probably put all that into an answer. \$\endgroup\$ – Tyyppi_77 Oct 29 '16 at 10:38
2
\$\begingroup\$

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.

\$\endgroup\$
  • \$\begingroup\$ see the updated code, is it correct ? what about mapping the intensity to the color, is it correct too ? \$\endgroup\$ – Ahmed Saleh Oct 29 '16 at 10:48
  • \$\begingroup\$ That's hard to guess. Does the end result look correct on your computer screen? \$\endgroup\$ – Tyyppi_77 Oct 29 '16 at 10:51
  • 1
    \$\begingroup\$ 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. \$\endgroup\$ – tkausl Oct 29 '16 at 10:52
  • \$\begingroup\$ normal_length is a precomputed normal using 3 vertices, and ambient_light is 0.5f \$\endgroup\$ – Ahmed Saleh Oct 29 '16 at 11:54
  • \$\begingroup\$ 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). \$\endgroup\$ – tkausl Oct 29 '16 at 11:58

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.