added ex04 solution
This commit is contained in:
parent
668e73ba36
commit
f8f9f627d8
5 changed files with 113 additions and 7 deletions
|
@ -100,8 +100,13 @@ bool Triangle::intersect(Ray &ray) const {
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Calculate the normal
|
// Calculate the normal
|
||||||
// IMPLEMENT smooth triangles, if available
|
if (length(this->normal[0]) * length(this->normal[1]) * length(this->normal[2]) > EPSILON)
|
||||||
ray.normal = normalized(crossProduct(edge1, edge2));
|
ray.normal = normalized(u * this->normal[1] + v * this->normal[2] + (1 - u - v) * this->normal[0]);
|
||||||
|
else
|
||||||
|
ray.normal = normalized(crossProduct(edge1, edge2));
|
||||||
|
// calculate the tangent and bitangent vectors as well
|
||||||
|
ray.tangent = normalized(u * this->tangent[1] + v * this->tangent[2] + (1 - u - v) * this->tangent[0]);
|
||||||
|
ray.bitangent = normalized(u * this->bitangent[1] + v * this->bitangent[2] + (1 - u - v) * this->bitangent[0]);
|
||||||
|
|
||||||
// Calculate the surface position
|
// Calculate the surface position
|
||||||
ray.surface = u * this->surface[1] + v * this->surface[2] + (1 - u - v) * this->surface[0];
|
ray.surface = u * this->surface[1] + v * this->surface[2] + (1 - u - v) * this->surface[0];
|
||||||
|
|
|
@ -6,8 +6,42 @@ BrdfShader::BrdfShader(char const *fileName, Color const &scale)
|
||||||
: scale(scale), brdf(std::make_unique<BRDFRead>(fileName)) {}
|
: scale(scale), brdf(std::make_unique<BRDFRead>(fileName)) {}
|
||||||
|
|
||||||
Color BrdfShader::shade(Scene const &scene, Ray const &ray) const {
|
Color BrdfShader::shade(Scene const &scene, Ray const &ray) const {
|
||||||
Color illuminationColor;
|
// Calculate theta and phi
|
||||||
|
float thetaIn = std::acos(dotProduct(-ray.normal, ray.direction));
|
||||||
|
float phiIn = 0.0f;
|
||||||
|
|
||||||
// IMPLEMENT ME
|
// Derive local coordinate system
|
||||||
|
Vector3d const x = crossProduct(-ray.direction, ray.normal);
|
||||||
|
Vector3d const y = crossProduct(ray.normal, x);
|
||||||
|
|
||||||
|
// Accumulate the light over all light sources
|
||||||
|
Color illuminationColor;
|
||||||
|
for (const auto &light : scene.lights()) {
|
||||||
|
Light::Illumination illum;
|
||||||
|
illum = light->illuminate(scene, ray);
|
||||||
|
|
||||||
|
// Diffuse term
|
||||||
|
float const cosine = dotProduct(-illum.direction, ray.normal);
|
||||||
|
if (cosine > 0) {
|
||||||
|
Color color;
|
||||||
|
|
||||||
|
// Avoid numeric instability
|
||||||
|
if (cosine < 1) {
|
||||||
|
float const thetaOut = std::acos(cosine);
|
||||||
|
|
||||||
|
// Project outgoing vector into local coordinate system
|
||||||
|
Vector3d const c = crossProduct(-illum.direction, ray.normal);
|
||||||
|
float const phiOut = std::atan2(dotProduct(c, y), dotProduct(c, x));
|
||||||
|
|
||||||
|
color = Color(brdf->lookupBrdfValues(thetaIn, phiIn, thetaOut, phiOut));
|
||||||
|
} else {
|
||||||
|
color = Color(brdf->lookupBrdfValues(thetaIn, phiIn, 0, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate colors
|
||||||
|
Color const diffuseColor = scale * color * cosine;
|
||||||
|
illuminationColor += diffuseColor * illum.color;
|
||||||
|
}
|
||||||
|
}
|
||||||
return illuminationColor;
|
return illuminationColor;
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,10 +4,51 @@
|
||||||
|
|
||||||
CookTorranceShader::CookTorranceShader(Color const &diffCol, Color const &ctCol, float IOR, float roughness, float diffCoeff, float ctCoeff) : diffuseColor(diffCol * diffCoeff), ctColor(ctCol * ctCoeff), F0(IOR), m(roughness) {}
|
CookTorranceShader::CookTorranceShader(Color const &diffCol, Color const &ctCol, float IOR, float roughness, float diffCoeff, float ctCoeff) : diffuseColor(diffCol * diffCoeff), ctColor(ctCol * ctCoeff), F0(IOR), m(roughness) {}
|
||||||
|
|
||||||
|
float CookTorranceShader::D(float NdotH) const {
|
||||||
|
// Beckmann distribution
|
||||||
|
float const r2 = m * m;
|
||||||
|
float const NdotH2 = NdotH * NdotH;
|
||||||
|
return expf((NdotH2 - 1.0f) / (r2 * NdotH2)) / (4.0f * r2 * powf(NdotH, 4.0f));
|
||||||
|
}
|
||||||
|
|
||||||
|
float CookTorranceShader::F(float VdotH) const {
|
||||||
|
// Schlicks approximation
|
||||||
|
return F0 + (1.0f - F0) * powf(1.0f - VdotH, 5);
|
||||||
|
}
|
||||||
|
|
||||||
|
float CookTorranceShader::G(float NdotH, float NdotV, float VdotH, float NdotL) const { return std::min(1.0f, std::min(2.0f * NdotH * NdotV / VdotH, 2.0f * NdotH * NdotL / VdotH)); }
|
||||||
|
|
||||||
Color CookTorranceShader::shade(Scene const &scene, Ray const &ray) const {
|
Color CookTorranceShader::shade(Scene const &scene, Ray const &ray) const {
|
||||||
Color fragmentColor;
|
Color fragmentColor;
|
||||||
|
|
||||||
// IMPLEMENT ME
|
if (m >= 0.0f) {
|
||||||
|
// Accumulate the light over all light sources
|
||||||
|
for (const auto &light : scene.lights()) {
|
||||||
|
Light::Illumination illum;
|
||||||
|
illum = light->illuminate(scene, ray);
|
||||||
|
|
||||||
|
float const NdotL = std::max(0.0f, dotProduct(-illum.direction, ray.normal));
|
||||||
|
if (NdotL <= 0.0f)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Diffuse term
|
||||||
|
Color const diffuse = this->diffuseColor / float(PI);
|
||||||
|
fragmentColor += diffuse * NdotL * illum.color;
|
||||||
|
|
||||||
|
// Cook-Torrance term
|
||||||
|
// half angle vector
|
||||||
|
Vector3d const H = normalized(-illum.direction - ray.direction);
|
||||||
|
float const NdotH = std::max(0.0f, dotProduct(ray.normal, H));
|
||||||
|
float const NdotV = std::max(0.0f, dotProduct(ray.normal, -ray.direction));
|
||||||
|
float const VdotH = std::max(0.0f, dotProduct(-ray.direction, H));
|
||||||
|
|
||||||
|
if (NdotV * NdotL > EPSILON) {
|
||||||
|
Color const specular = this->ctColor * (F(VdotH) * D(NdotH) * G(NdotH, NdotV, VdotH, NdotL)) / (float(PI) * NdotV * NdotL);
|
||||||
|
|
||||||
|
fragmentColor += specular * NdotL * illum.color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return fragmentColor;
|
return fragmentColor;
|
||||||
}
|
}
|
|
@ -7,7 +7,13 @@ LambertShader::LambertShader(Color const &diffuseColor) : diffuseColor(diffuseCo
|
||||||
Color LambertShader::shade(Scene const &scene, Ray const &ray) const {
|
Color LambertShader::shade(Scene const &scene, Ray const &ray) const {
|
||||||
Color fragmentColor;
|
Color fragmentColor;
|
||||||
|
|
||||||
// IMPLEMENT ME
|
// Accumulate the light over all light sources
|
||||||
|
for (const auto &light : scene.lights()) {
|
||||||
|
Light::Illumination const illum = light->illuminate(scene, ray);
|
||||||
|
// Diffuse term
|
||||||
|
Color const diffuse = this->diffuseColor * std::max(dotProduct(-illum.direction, ray.normal), 0.0f);
|
||||||
|
fragmentColor += diffuse * illum.color;
|
||||||
|
}
|
||||||
|
|
||||||
return fragmentColor;
|
return fragmentColor;
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,27 @@ PhongShader::PhongShader(Color const &diffuseColor, float diffuseCoefficient, Co
|
||||||
Color PhongShader::shade(Scene const &scene, Ray const &ray) const {
|
Color PhongShader::shade(Scene const &scene, Ray const &ray) const {
|
||||||
Color fragmentColor;
|
Color fragmentColor;
|
||||||
|
|
||||||
// IMPLEMENT ME
|
// Calculate the reflection vector
|
||||||
|
Vector3d const reflection = ray.direction - 2 * dotProduct(ray.normal, ray.direction) * ray.normal;
|
||||||
|
|
||||||
|
// Accumulate the light over all light sources
|
||||||
|
for (const auto &light : scene.lights()) {
|
||||||
|
Light::Illumination illum;
|
||||||
|
illum = light->illuminate(scene, ray);
|
||||||
|
|
||||||
|
// Diffuse term
|
||||||
|
Color const diffuse =
|
||||||
|
this->diffuseCoefficient * this->diffuseColor * std::max(dotProduct(-illum.direction, ray.normal), 0.0f);
|
||||||
|
fragmentColor += diffuse * illum.color;
|
||||||
|
|
||||||
|
// Specular term
|
||||||
|
float const cosine = dotProduct(-illum.direction, reflection);
|
||||||
|
if (cosine > 0) {
|
||||||
|
Color const specular = this->specularCoefficient * this->specularColor // highlight
|
||||||
|
* powf(cosine, this->shininessExponent); // shininess factor
|
||||||
|
fragmentColor += specular * illum.color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return fragmentColor;
|
return fragmentColor;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue