cloudy-raytracer/shader/brdfshader.cpp

50 lines
1.6 KiB
C++
Raw Normal View History

2022-11-30 17:29:04 +01:00
#include <array>
#include <cmath>
2022-11-25 14:58:29 +01:00
#include "light/light.h"
#include "scene/scene.h"
#include "shader/brdfshader.h"
BrdfShader::BrdfShader(char const *fileName, Color const &scale)
2022-11-29 13:15:48 +01:00
: scale(scale), brdf(std::make_unique<BRDFRead>(fileName)) {}
2022-11-25 14:58:29 +01:00
Color BrdfShader::shade(Scene const &scene, Ray const &ray) const {
2022-12-06 13:48:21 +01:00
// Calculate theta and phi
float thetaIn = std::acos(dotProduct(-ray.normal, ray.direction));
float phiIn = 0.0f;
// Derive local coordinate system
Vector3d const x = crossProduct(-ray.direction, ray.normal);
Vector3d const y = crossProduct(ray.normal, x);
// Accumulate the light over all light sources
2022-11-25 14:58:29 +01:00
Color illuminationColor;
2022-12-06 13:48:21 +01:00
for (const auto &light : scene.lights()) {
Light::Illumination illum;
illum = light->illuminate(scene, ray);
// Diffuse term
float const cosine = dotProduct(-illum.direction, ray.normal);
if (cosine > 0) {
Color color;
// Avoid numeric instability
if (cosine < 1) {
float const thetaOut = std::acos(cosine);
// Project outgoing vector into local coordinate system
Vector3d const c = crossProduct(-illum.direction, ray.normal);
float const phiOut = std::atan2(dotProduct(c, y), dotProduct(c, x));
color = Color(brdf->lookupBrdfValues(thetaIn, phiIn, thetaOut, phiOut));
} else {
color = Color(brdf->lookupBrdfValues(thetaIn, phiIn, 0, 0));
}
2022-11-25 14:58:29 +01:00
2022-12-06 13:48:21 +01:00
// Calculate colors
Color const diffuseColor = scale * color * cosine;
illuminationColor += diffuseColor * illum.color;
}
2022-12-06 13:48:21 +01:00
}
2022-11-25 14:58:29 +01:00
return illuminationColor;
}