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; }