2022-11-25 14:58:29 +01:00
|
|
|
#include "light/light.h"
|
|
|
|
#include "scene/scene.h"
|
|
|
|
#include "shader/cooktorranceshader.h"
|
|
|
|
|
2022-11-28 20:55:22 +01:00
|
|
|
CookTorranceShader::CookTorranceShader(Color const &diffCol, Color const &ctCol, float IOR, float roughness,
|
|
|
|
float diffCoeff, float ctCoeff) : diffuseColor(diffCol * diffCoeff),
|
|
|
|
ctColor(ctCol * ctCoeff), F0(IOR),
|
|
|
|
m(roughness) {}
|
2022-11-25 14:58:29 +01:00
|
|
|
|
|
|
|
Color CookTorranceShader::shade(Scene const &scene, Ray const &ray) const {
|
2022-11-28 20:55:22 +01:00
|
|
|
Color fragmentColor;
|
2022-11-25 14:58:29 +01:00
|
|
|
|
2022-11-28 20:55:22 +01:00
|
|
|
// IMPLEMENT ME
|
|
|
|
for (auto &light: scene.lights()) {
|
|
|
|
auto illum = light->illuminate(scene, ray);
|
|
|
|
auto N = ray.normal;
|
|
|
|
auto V = ray.direction;
|
|
|
|
auto L = illum.direction;
|
2022-11-28 23:51:33 +01:00
|
|
|
auto H = normalized(V + L);
|
2022-11-25 14:58:29 +01:00
|
|
|
|
2022-11-28 20:55:22 +01:00
|
|
|
auto NV = dotProduct(N, V);
|
|
|
|
auto NL = dotProduct(N, L);
|
|
|
|
auto NH = dotProduct(N, H);
|
|
|
|
auto VH = dotProduct(V, H);
|
|
|
|
|
|
|
|
float rhoD = 1.0f / PI;
|
|
|
|
|
|
|
|
|
|
|
|
|
2022-11-28 23:51:33 +01:00
|
|
|
auto rhoS = F(VH) * D(NH) * G(NH, NV, VH, NL) / (4 * NV * NL);
|
2022-11-28 20:55:22 +01:00
|
|
|
auto rhoPD = diffuseColor * rhoD + ctColor * rhoS;
|
|
|
|
|
|
|
|
|
2022-11-28 23:51:33 +01:00
|
|
|
fragmentColor += illum.color * std::abs(NL) * rhoPD;
|
2022-11-28 20:55:22 +01:00
|
|
|
}
|
|
|
|
|
2022-11-28 23:51:33 +01:00
|
|
|
return diffuseColor * fragmentColor;
|
2022-11-28 20:55:22 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
float CookTorranceShader::D(float NdotH) const {
|
|
|
|
float divisor = 4.0f * m * m * std::pow(cos(NdotH), 4);
|
2022-11-28 23:51:33 +01:00
|
|
|
float exponent = std::pow(tan(NdotH) / m, 2);
|
|
|
|
return 1 / divisor * std::exp(- 1.0f * exponent);
|
2022-11-28 20:55:22 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
float CookTorranceShader::F(float VdotH) const {
|
2022-11-28 23:51:33 +01:00
|
|
|
return F0 + (1 - F0) * std::pow(1 - VdotH, 5);
|
2022-11-28 20:55:22 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
float CookTorranceShader::G(float NdotH, float NdotV, float VdotH, float NdotL) const {
|
2022-11-28 23:51:33 +01:00
|
|
|
if (std::abs(NdotL) < 0.1f) {
|
|
|
|
return std::min(1.0f, std::min(2 * NdotH * NdotV / VdotH, 2 * NdotH * NdotL / VdotH));
|
|
|
|
} else if (std::abs(NdotV) < 0.1f) {
|
|
|
|
return 2 * NdotH * NdotL / VdotH;
|
|
|
|
} else {
|
|
|
|
return 1;
|
|
|
|
}
|
2022-11-28 20:55:22 +01:00
|
|
|
}
|