Ex06.2
This commit is contained in:
parent
9121a3281a
commit
19d92d9e30
1 changed files with 77 additions and 10 deletions
|
@ -2,27 +2,94 @@
|
|||
#include "scene/scene.h"
|
||||
#include "shader/materialshader.h"
|
||||
#include <cmath>
|
||||
#include <iostream>
|
||||
|
||||
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; }
|
||||
|
|
Loading…
Reference in a new issue