diff --git a/shader/materialshader.cpp b/shader/materialshader.cpp index 5f6550a..d3907c0 100644 --- a/shader/materialshader.cpp +++ b/shader/materialshader.cpp @@ -6,20 +6,24 @@ Vector3d tangentToWorldSpace(const Vector3d &surfaceNormal, const Vector3d &surfaceTangent, const Vector3d &surfaceBitangent, - const Vector3d &textureNormal) { + 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) {} + specularCoefficient(0.5f), shininessExponent(8) +{} -Color MaterialShader::shade(Scene const &scene, Ray const &ray) const { +Color MaterialShader::shade(Scene const &scene, Ray const &ray) const +{ Color fragmentColor; // IMPLEMENT ME // (Normal Map) Calculate the new normal vector Vector3d surfaceNormal = ray.normal; - if (this->normalMap != nullptr) { + 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}; @@ -30,12 +34,14 @@ Color MaterialShader::shade(Scene const &scene, Ray const &ray) const { // (Diffuse-/Specular Map) Accumulate the light over all light sources Color surfaceDiffuseColor(0, 0, 0); - if (this->diffuseMap != nullptr) { + if (this->diffuseMap != nullptr) + { surfaceDiffuseColor = this->diffuseMap->color(ray.surface, true); } Color surfaceSpecularColor(0, 0, 0); - if (this->specularMap != nullptr) { + if (this->specularMap != nullptr) + { surfaceSpecularColor = this->specularMap->color(ray.surface, true); } @@ -43,7 +49,8 @@ Color MaterialShader::shade(Scene const &scene, Ray const &ray) const { // (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) { + if (this->reflectionMap != nullptr) + { auto surfaceReflectiveMapColor = this->reflectionMap->color(ray.surface, true); surfaceReflectanceCoefficient = surfaceReflectiveMapColor.r; } @@ -55,7 +62,8 @@ Color MaterialShader::shade(Scene const &scene, Ray const &ray) const { // (Alpha Map) Calculate the opacity, create a background ray float surfaceAlphaCoefficient(1); - if (this->alphaMap != nullptr) { + if (this->alphaMap != nullptr) + { auto surfaceAlphaMapColor = this->alphaMap->color(ray.surface, true); surfaceAlphaCoefficient = surfaceAlphaMapColor.r; } @@ -66,7 +74,8 @@ Color MaterialShader::shade(Scene const &scene, Ray const &ray) const { propagatedRay.primitive = nullptr; // Iterate over light sources - for (const auto &light: scene.lights()) { + for (const auto &light: scene.lights()) + { Light::Illumination const illum = light->illuminate(scene, ray); // Diffuse term (lambertian) @@ -76,7 +85,8 @@ Color MaterialShader::shade(Scene const &scene, Ray const &ray) const { // Specular term (phong) float const cosine = dotProduct(-illum.direction, reflection); - if (cosine > 0) { + if (cosine > 0) + { Color const specular = this->specularCoefficient * surfaceSpecularColor // highlight * powf(cosine, this->shininessExponent); // shininess factor fragmentColor += specular * illum.color; @@ -85,10 +95,21 @@ Color MaterialShader::shade(Scene const &scene, Ray const &ray) const { } // Reflected ray - fragmentColor += scene.traceRay(reflectionRay) * surfaceReflectanceCoefficient * reflectance; + if (surfaceReflectanceCoefficient > 0) + { + Color const reflectionColor = scene.traceRay(reflectionRay); + fragmentColor += surfaceReflectanceCoefficient * reflectionColor * reflectance; + } // Opacity - return fragmentColor * surfaceAlphaCoefficient + scene.traceRay(propagatedRay) * (1 - surfaceAlphaCoefficient); + if (surfaceAlphaCoefficient < 1) + { + Color const background = scene.traceRay(propagatedRay); + fragmentColor = (1 - surfaceAlphaCoefficient) * background + surfaceAlphaCoefficient * fragmentColor; + } + + return fragmentColor; } -bool MaterialShader::isTransparent() const { return this->opacity < 1.0f || this->alphaMap; } +bool MaterialShader::isTransparent() const +{ return this->opacity < 1.0f || this->alphaMap; }