97 lines
4.2 KiB
C++
97 lines
4.2 KiB
C++
#include <array>
|
|
#include <cmath>
|
|
#include "light/light.h"
|
|
#include "scene/scene.h"
|
|
#include "shader/brdfshader.h"
|
|
|
|
BrdfShader::BrdfShader(char const *fileName, Color const &scale)
|
|
: scale(scale), brdf(std::make_unique<BRDFRead>(fileName)) {}
|
|
|
|
Color BrdfShader::shade(Scene const &scene, Ray const &ray) const {
|
|
Color illuminationColor;
|
|
/*
|
|
* Arvids Code
|
|
static auto rebase = [](Vector3d const &axis_x,
|
|
Vector3d const &axis_y,
|
|
Vector3d const &axis_z,
|
|
Vector3d const &vec) {
|
|
auto det = axis_x.x * axis_y.y * axis_z.z +
|
|
axis_x.y * axis_y.z * axis_z.x +
|
|
axis_x.z * axis_y.x * axis_z.y -
|
|
axis_x.x * axis_y.z * axis_z.y -
|
|
axis_x.y * axis_y.x * axis_z.z -
|
|
axis_x.z * axis_y.y * axis_z.x;
|
|
// Calculate resulting vector by using inverse matrix of new base vectors
|
|
return Vector3d{
|
|
((axis_y.y * axis_z.z - axis_y.z * axis_z.y) * vec.x +
|
|
(axis_y.z * axis_z.x - axis_y.x * axis_z.z) * vec.y +
|
|
(axis_y.x * axis_z.y - axis_z.x * axis_y.y) * vec.z) / det,
|
|
((axis_x.z * axis_z.y - axis_x.y * axis_z.z) * vec.x +
|
|
(axis_x.x * axis_z.z - axis_x.z * axis_z.x) * vec.y +
|
|
(axis_z.x * axis_x.y - axis_x.x * axis_z.y) * vec.z) / det,
|
|
((axis_x.y * axis_y.z - axis_x.z * axis_y.y) * vec.x +
|
|
(axis_y.x * axis_x.z - axis_x.x * axis_y.z) * vec.y +
|
|
(axis_x.x * axis_y.y - axis_y.x * axis_x.y) * vec.z) / det
|
|
};
|
|
};
|
|
|
|
for (auto &light: scene.lights()) {
|
|
|
|
auto illum = light->illuminate(scene, ray);
|
|
if (dotProduct(ray.normal, illum.direction) <= EPSILON) {
|
|
continue;
|
|
}
|
|
|
|
auto axis = orthoNormalized(ray.normal, ray.direction, illum.direction);
|
|
auto axis_y = std::get<0>(axis);
|
|
auto axis_x = std::get<1>(axis);
|
|
auto axis_z = std::get<2>(axis);
|
|
|
|
auto N = normalized(rebase(axis_x, axis_y, axis_z, ray.normal));
|
|
auto D = normalized(rebase(axis_x, axis_y, axis_z, -ray.direction));
|
|
auto L = normalized(rebase(axis_x, axis_y, axis_z, -illum.direction));
|
|
D = axis_y * D.y + axis_z * D.z;
|
|
L = axis_y * L.y + axis_z * L.z;
|
|
|
|
illuminationColor += brdf->lookupBrdfValues(std::acos(dotProduct(ray.normal, -ray.direction)),
|
|
0.0f,
|
|
std::acos(dotProduct(illum.direction, ray.normal)),
|
|
std::acos(dotProduct(D, L)));
|
|
}
|
|
*/
|
|
// IMPLEMENT ME
|
|
|
|
for(auto& light : scene.lights()){
|
|
Light::Illumination illum = light->illuminate(scene, ray);
|
|
|
|
Vector3d invertedDirection = -ray.direction;
|
|
Vector3d invertedIllum = -illum.direction;
|
|
|
|
// the dot-product cant be negative otherwise the light ray would come from the inside
|
|
if(dotProduct(invertedIllum, ray.normal) < 0)
|
|
continue;
|
|
|
|
// Calculate coordinate System
|
|
Vector3d axisX = crossProduct(invertedDirection, ray.normal);
|
|
Vector3d axisY = crossProduct(axisX, ray.normal);
|
|
|
|
// Project ray.direction and illum.direction into plane
|
|
Vector2d projectedIllum = Vector2d(dotProduct(axisX, invertedIllum), dotProduct(axisY, invertedIllum));
|
|
Vector2d projectedDirection = Vector2d(dotProduct(axisX, invertedDirection), dotProduct(axisY, invertedDirection));
|
|
|
|
// get Z coordinate for theta angles
|
|
double coordinateZDirection = dotProduct(ray.normal, invertedDirection);
|
|
double coordinateZIllum = dotProduct(ray.normal, invertedIllum);
|
|
|
|
// calculate theta1 and 2
|
|
double theta1Correct = std::atan2(length(projectedDirection), coordinateZDirection);
|
|
double theta2Correct = std::atan2(length(projectedIllum), coordinateZIllum);
|
|
|
|
// calculate phi
|
|
double phi = std::atan2(projectedIllum.u, projectedIllum.v);
|
|
|
|
illuminationColor += brdf->lookupBrdfValues(theta1Correct, 0.0, theta2Correct, phi);
|
|
|
|
}
|
|
return illuminationColor;
|
|
}
|