2022-11-25 14:58:29 +01:00
|
|
|
#include "light/light.h"
|
|
|
|
#include "scene/scene.h"
|
|
|
|
#include "shader/phongshader.h"
|
|
|
|
|
|
|
|
PhongShader::PhongShader(Color const &diffuseColor, float diffuseCoefficient, Color const &specularColor,
|
|
|
|
float specularCoefficient, float shininessExponent)
|
2022-11-28 20:24:29 +01:00
|
|
|
: diffuseColor(diffuseColor), diffuseCoefficient(diffuseCoefficient), specularColor(specularColor),
|
|
|
|
specularCoefficient(specularCoefficient), shininessExponent(shininessExponent) {}
|
2022-11-25 14:58:29 +01:00
|
|
|
|
|
|
|
Color PhongShader::shade(Scene const &scene, Ray const &ray) const {
|
2022-11-28 20:24:29 +01:00
|
|
|
Color fragmentColor;
|
2022-11-25 14:58:29 +01:00
|
|
|
|
2022-12-06 13:48:21 +01:00
|
|
|
// Calculate the reflection vector
|
|
|
|
Vector3d const reflection = ray.direction - 2 * dotProduct(ray.normal, ray.direction) * ray.normal;
|
|
|
|
|
|
|
|
// Accumulate the light over all light sources
|
|
|
|
for (const auto &light : scene.lights()) {
|
|
|
|
Light::Illumination illum;
|
|
|
|
illum = light->illuminate(scene, ray);
|
|
|
|
|
|
|
|
// Diffuse term
|
|
|
|
Color const diffuse =
|
|
|
|
this->diffuseCoefficient * this->diffuseColor * std::max(dotProduct(-illum.direction, ray.normal), 0.0f);
|
|
|
|
fragmentColor += diffuse * illum.color;
|
|
|
|
|
|
|
|
// Specular term
|
|
|
|
float const cosine = dotProduct(-illum.direction, reflection);
|
|
|
|
if (cosine > 0) {
|
|
|
|
Color const specular = this->specularCoefficient * this->specularColor // highlight
|
|
|
|
* powf(cosine, this->shininessExponent); // shininess factor
|
|
|
|
fragmentColor += specular * illum.color;
|
|
|
|
}
|
|
|
|
}
|
2022-12-12 20:24:08 +01:00
|
|
|
return fragmentColor;
|
2022-11-25 14:58:29 +01:00
|
|
|
}
|