Search code examples
3dshaderlight

blinn_phong illumination on a cube, Diffuse and Specular light are not working properly


I'm implementing a small 3d renderer and I'm stuck at blinn_phong illumination model.

These are the steps that I've made until now.

1- calculate all the vertex normal

for (uint16_t i = 0; i < Cube->m_indices.size() - 2; i+= 3)
{
    Vec3 Normal;
    Vec3 p1(Cube->m_vertices[Cube->m_indices[i + 1]].position - Cube->m_vertices[Cube->m_indices[i]].position);
    Vec3 p2(Cube->m_vertices[Cube->m_indices[i + 2]].position - Cube->m_vertices[Cube->m_indices[i]].position);
    Normal = p1.Cross(p2);
    Normal.Normalize();
    Cube->m_vertices[Cube->m_indices[i]].normal = Cube->m_vertices[Cube->m_indices[i]].normal + Vec4(Normal, 0);
    Cube->m_vertices[Cube->m_indices[i + 1]].normal = Cube->m_vertices[Cube->m_indices[i + 1]].normal + Vec4(Normal, 0);
    Cube->m_vertices[Cube->m_indices[i + 2]].normal = Cube->m_vertices[Cube->m_indices[i + 2]].normal + Vec4(Normal, 0);
}

for (uint16_t i = 0; i < Cube->m_vertices.size(); ++i)
{
    Cube->m_vertices[i].normal.Normalize();
}

2- transform positions and normals into eye-space. Positions with modelview matrix and normals with inverse-transpose of modelview matrix.

3- Calculate normal per pixel using barycentric coordinates.

4- Calculate blinn_phong

Color Rasterizer::BlinnPhongColor(Vertex p_position, Vec3 p_normal, Vertex p_lightPosition, Vec3 p_lightcomp, Color p_color)
{
  Vertex position1(Mat4::ScreenToView(p_position.position, 
  m_rtexture.GetWidth(), m_rtexture.GetHeight()));

  Vec3 lightDir(p_lightPosition.position - position1.position);
  lightDir.Normalize();

  float lambert = std::max(lightDir.dot(p_normal), 0.0f);
  float specular = 0.0f;

  if (lambert > 0.0f)
  {
     Vec3 viewDir = (position1.position *-1);
     viewDir.Normalize();

     Vec3 halfDir = (lightDir + viewDir);
     halfDir.Normalize();

     float specAngle = std::max(halfDir.dot(p_normal), 0.0f);
     specular = pow(specAngle, 14.0);
  }
  Color amb = p_color * (p_lightcomp.x);
  Color diff = p_color * (p_lightcomp.y * lambert);
  Color spec = Color(255, 255, 255) * (p_lightcomp.z * specular);
  Color total = spec;
  return total;
} 

*(p_lightcomp.x ,y z => ambient, diffuse, specular light component value).

This is what I get from the calculation.

a- Ambient light only.

ambient light

b- Diffuse light only.

Diffuse light

c- and finalllly a weirdest Specular light only.

Spec?

I've been trying to solve this since last Sunday and still couldn't find any solution!

Please help!

Thank you -Hans

*P.S!! light position is at (0,0,0) and cube position is at (0,0, -2) and I've made rotation of 45 degree on x and y axis. Sorry for not specifying this!

EDIT: following Rabbid76 's comment, first test with fabs(lightDor.dot(p_normal));

1- no change with ambient and spec. but Diffuse color changed. Diffuse Color changed

2- test with second line where normal = position. Diffuse color and Specular colors were Black.


Solution

  • I've found the answer to my problem. I did mix clockwise/counterclockwise primitives. This changes all the calculations for normal vectors.

    Thank you @Rabbid76