From 19d92d9e302c755804ad4e59a93f51a28e7e1ab1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?arvid=20schr=C3=B6der?= Date: Mon, 12 Dec 2022 20:24:21 +0100 Subject: [PATCH] Ex06.2 --- shader/materialshader.cpp | 87 ++++++++++++++++++++++++++++++++++----- 1 file changed, 77 insertions(+), 10 deletions(-) diff --git a/shader/materialshader.cpp b/shader/materialshader.cpp index f126a54..e1c1cd8 100644 --- a/shader/materialshader.cpp +++ b/shader/materialshader.cpp @@ -2,27 +2,94 @@ #include "scene/scene.h" #include "shader/materialshader.h" #include +#include -Vector3d tangentToWorldSpace(const Vector3d &surfaceNormal, const Vector3d &surfaceTangent, const Vector3d &surfaceBitangent, const Vector3d &textureNormal) { - return textureNormal.x * surfaceTangent + textureNormal.y * surfaceBitangent + textureNormal.z * surfaceNormal; +Vector3d +tangentToWorldSpace(const Vector3d &surfaceNormal, const Vector3d &surfaceTangent, const Vector3d &surfaceBitangent, + const Vector3d &textureNormal) { + return textureNormal.x * surfaceTangent + textureNormal.y * surfaceBitangent + textureNormal.z * surfaceNormal; } -MaterialShader::MaterialShader() : opacity(1.0f), normalCoefficient(1.0f), diffuseCoefficient(0.5f), reflectance(0.0f), specularCoefficient(0.5f), shininessExponent(8) {} +MaterialShader::MaterialShader() : opacity(1.0f), normalCoefficient(1.0f), diffuseCoefficient(0.5f), reflectance(0.0f), + specularCoefficient(0.5f), shininessExponent(8) {} Color MaterialShader::shade(Scene const &scene, Ray const &ray) const { - Color fragmentColor; + Color fragmentColor; + // IMPLEMENT ME - // IMPLEMENT ME + // (Normal Map) Calculate the new normal vector + Vector3d surfaceNormal = ray.normal; + if (this->normalMap != nullptr) { + auto surfaceNormalMapColor = this->normalMap->color(ray.surface, true); + Vector3d textureNormal = {surfaceNormalMapColor.r, surfaceNormalMapColor.g, surfaceNormalMapColor.b}; + textureNormal = textureNormal * 2.0f - Vector3d{1, 1, 1}; + surfaceNormal = ray.normal * normalCoefficient + + (1 - normalCoefficient) * + tangentToWorldSpace(ray.normal, ray.tangent, ray.bitangent, textureNormal); + } - // (Normal Map) Calculate the new normal vector + // (Diffuse-/Specular Map) Accumulate the light over all light sources + Color surfaceDiffuseColor(0, 0, 0); + if (this->diffuseMap != nullptr) { + surfaceDiffuseColor = this->diffuseMap->color(ray.surface, true); + } - // (Diffuse-/Specular Map) Accumulate the light over all light sources + Color surfaceSpecularColor(0, 0, 0); + if (this->specularMap != nullptr) { + surfaceSpecularColor = this->specularMap->color(ray.surface); + } - // (Reflection Map) Calculate the reflectance, create a reflection ray - // (Alpha Map) Calculate the opacity, create a background ray + // (Reflection Map) Calculate the reflectance, create a reflection ray + Vector3d const reflection = ray.direction - 2 * dotProduct(surfaceNormal, ray.direction) * ray.normal; + float surfaceReflectanceCoefficient = this->reflectance; + if (this->reflectionMap != nullptr) { + auto surfaceReflectiveMapColor = this->reflectionMap->color(ray.surface, true); + surfaceReflectanceCoefficient = surfaceReflectiveMapColor.r; + } + Ray reflectionRay = ray; + reflectionRay.origin = ray.origin + (ray.length - REFR_EPS) * ray.direction; + reflectionRay.direction = normalized(reflection); + reflectionRay.length = INFINITY; + reflectionRay.primitive = nullptr; - return fragmentColor; + // (Alpha Map) Calculate the opacity, create a background ray + float surfaceAlphaCoefficient(1); + if (this->alphaMap != nullptr) { + auto surfaceAlphaMapColor = this->alphaMap->color(ray.surface, true); + surfaceAlphaCoefficient = surfaceAlphaMapColor.r; + } + + Ray propagatedRay = ray; + propagatedRay.origin = ray.origin + (ray.length + REFR_EPS) * ray.direction; + propagatedRay.length = INFINITY; + propagatedRay.primitive = nullptr; + + // Iterate over light sources + for (const auto &light: scene.lights()) { + Light::Illumination const illum = light->illuminate(scene, ray); + + // Diffuse term (lambertian) + Color const diffuse = this->diffuseCoefficient * surfaceDiffuseColor * + std::max(dotProduct(-illum.direction, ray.normal), 0.0f); + fragmentColor += diffuse * illum.color; + + // Specular term (phong) + float const cosine = dotProduct(-illum.direction, reflection); + if (cosine > 0) { + Color const specular = this->specularCoefficient * surfaceSpecularColor // highlight + * powf(cosine, this->shininessExponent); // shininess factor + fragmentColor += specular * illum.color; + } + + // Reflected ray + fragmentColor += scene.traceRay(reflectionRay) * surfaceReflectanceCoefficient * illum.color; + + } + // Opacity + return fragmentColor * surfaceAlphaCoefficient + scene.traceRay(propagatedRay) * (1 - surfaceAlphaCoefficient); + +// return fragmentColor; } bool MaterialShader::isTransparent() const { return this->opacity < 1.0f || this->alphaMap; }