X-Git-Url: https://git.rohieb.name/MicroTrace.git/blobdiff_plain/3396a44710415bde9509afeb02f3ec10a22c6661..0db0dec898ba811c966267d4cb12dad33a1e3545:/PhongShader.cxx

diff --git a/PhongShader.cxx b/PhongShader.cxx
index c44966e..f6bc870 100644
--- a/PhongShader.cxx
+++ b/PhongShader.cxx
@@ -1,5 +1,8 @@
+#include <vector>
+
 #include "PhongShader.hxx"
 #include "Primitive.hxx"
+#include "Scene.hxx"
 
 PhongShader::PhongShader(Scene* scene,
 			 const Vec3f& am_c,
@@ -32,34 +35,65 @@ PhongShader::~PhongShader()
 Vec3f
 PhongShader::Shade(Ray& ray)
 {
-  // surface normal at hit point of object
-  Vec3f normal = ray.hit()->GetNormal(ray);
-  // turn to front if angle > 90°
-  if(normal.dot(ray.direction()) < 0) {
-    normal = normal * -1;
-  }
-  // direction of reflection
-  Vec3f refl_dir = ray.direction() - normal * 2 * normal.dot(ray.direction());
-  refl_dir.normalize();
-
-  // ambient color term
-  Vec3f amb_color = m_ambient_color * m_ka;
+ // surface normal at hit point
+  Vec3f N = ray.hit()->GetNormal(ray);
+  // turn normal to front
+  if(N.dot(ray.direction()) > 0)
+    {
+      N *= -1;
+    }
+ 
+  // reflection vector
+  Vec3f R = ray.direction() - N*2*N.dot(ray.direction());
+  R.normalize();
 
-  Vec3f intensity, light_dir;
+  // ambient term
+  Vec3f color = m_ambient_color * 1.0 * m_ka;
+  
+  // construct shadow ray 
+  Vec3f shadow_org = ray.origin()+ray.direction()*ray.t();
+  Ray shadow_ray;
+  shadow_ray.setOrigin(shadow_org);
+  
 
-  // diffuse and specular color for each light source
-  Vec3f diff_sum;
-  Vec3f spec_sum;
-  for(std::vector<Light*>::iterator it = m_scene->m_lights.begin();
-    it != m_scene->m_lights.end(); it++) {
-    Ray light_ray;
-    (*it)->Illuminate(light_ray, intensity);
-    diff_sum += intensity * light_ray.direction().dot(normal);
-    Vec3f view_dir = ray.direction()*-1; // direction from hitpoint to viewer
-    spec_sum += intensity * pow(fmax(view_dir.dot(refl_dir),0), m_ke);
-  }
-  Vec3f diff_color = m_diffuse_color * m_kd * diff_sum;
-  Vec3f spec_color = m_specular_color * m_ks * spec_sum;
+  int n_area_rays = 1000;
+  std::vector<Light*> lights = m_scene->lights();
+  for(unsigned int i = 0; i < lights.size(); ++i)
+    {
+      Vec3f intensity;
 
-  return amb_color + diff_color + spec_color;
+      int max_s = (lights[i]->IsArea()) ? n_area_rays : 1;
+      Vec3f color_l(0.0f,0.0f,0.0f);
+      for(int s = 0; s < max_s; ++s)
+	{
+	  
+	  if(lights[i]->Illuminate(shadow_ray, intensity))
+	    {
+	      // check for occluders
+	      if(m_scene->Occluded(shadow_ray))
+		{
+		  continue;
+		}
+	      
+	      float IdotN = shadow_ray.direction().dot(N);
+	      if(IdotN > 0)
+		{
+		  // diffuse term
+		  color_l += m_diffuse_color * intensity * IdotN * m_kd;
+		}
+	      
+	      // specular term
+	      float IdotR = shadow_ray.direction().dot(R);
+	      if(IdotR > 0)
+		{
+		  color_l += m_specular_color * intensity * pow(IdotR,m_ke) * m_ks;
+		}
+	    }
+	}
+      color_l /= static_cast<float>(max_s);
+      color += color_l;
+    }
+  color.clamp();
+  
+  return color;
 }