#include #include #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(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; }