added ex02 solution
This commit is contained in:
parent
d3e64994d4
commit
8b8a53dde6
8 changed files with 141 additions and 31 deletions
|
@ -4,20 +4,24 @@
|
||||||
PointLight::PointLight(Vector3d const &position, float intensity, Color const &color) : Light(intensity, color), position(position) {}
|
PointLight::PointLight(Vector3d const &position, float intensity, Color const &color) : Light(intensity, color), position(position) {}
|
||||||
|
|
||||||
Light::Illumination PointLight::illuminate(Scene const &scene, Ray const &ray) const {
|
Light::Illumination PointLight::illuminate(Scene const &scene, Ray const &ray) const {
|
||||||
// IMPLEMENT ME
|
Vector3d const target = ray.origin + (ray.length - LGT_EPS) * ray.direction;
|
||||||
// Get the point on the surface
|
|
||||||
|
|
||||||
// Create an instance of the Illumination object, fill in the direction (from
|
// Illumination object
|
||||||
// surface point to light source)
|
Illumination illum;
|
||||||
Light::Illumination illum;
|
illum.direction = normalized(target - this->position);
|
||||||
|
|
||||||
|
// Precompute the distance from the light source
|
||||||
|
float const distance = length(target - this->position);
|
||||||
|
|
||||||
// Define a secondary ray from the surface point to the light source.
|
// Define a secondary ray from the surface point to the light source.
|
||||||
|
Ray lightRay;
|
||||||
|
lightRay.origin = target;
|
||||||
|
lightRay.direction = -illum.direction;
|
||||||
|
lightRay.length = distance - LGT_EPS;
|
||||||
|
|
||||||
// If the target is not in shadow... (use scene.findOcclusion())
|
// If the target is not in shadow...
|
||||||
|
if (!scene.findOcclusion(lightRay))
|
||||||
// Compute the brightness-color of this light using inverse squared distance
|
// ... compute the attenuation and light color
|
||||||
// to light source (i.e. 1/(d^2)), the color of this light source and the
|
illum.color = 1.0f / (distance * distance) * this->color * this->intensity;
|
||||||
// intensity
|
|
||||||
|
|
||||||
return illum;
|
return illum;
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,19 +13,78 @@ Box::Box(Vector3d const ¢er, Vector3d const &size, std::shared_ptr<Shader> c
|
||||||
// Primitive functions /////////////////////////////////////////////////////////
|
// Primitive functions /////////////////////////////////////////////////////////
|
||||||
|
|
||||||
bool Box::intersect(Ray &ray) const {
|
bool Box::intersect(Ray &ray) const {
|
||||||
// IMPLEMENT ME!
|
// Project the ray onto the box
|
||||||
|
Vector3d const minBounds = this->center - this->size / 2;
|
||||||
|
Vector3d const maxBounds = this->center + this->size / 2;
|
||||||
|
Vector3d t1 = componentQuotient(minBounds - ray.origin, ray.direction);
|
||||||
|
Vector3d t2 = componentQuotient(maxBounds - ray.origin, ray.direction);
|
||||||
|
|
||||||
// Determine whether the ray intersects the box
|
// Determine the intersection points (tNear, tFar)
|
||||||
|
// We also have to remember the intersection axes (tNearIndex, tFarIndex)
|
||||||
|
float tNear = -INFINITY;
|
||||||
|
float tFar = +INFINITY;
|
||||||
|
int tNearIndex = 0;
|
||||||
|
int tFarIndex = 0;
|
||||||
|
for (int d = 0; d < 3; ++d) {
|
||||||
|
|
||||||
|
// Test the trivial case (and to avoid division by zero errors)
|
||||||
|
if (ray.direction[d] == 0 && (ray.origin[d] < minBounds[d] || ray.origin[d] > maxBounds[d]))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Swap the bounds if necessary
|
||||||
|
if (t1[d] > t2[d])
|
||||||
|
std::swap(t1[d], t2[d]);
|
||||||
|
|
||||||
|
// Check for the near intersection
|
||||||
|
if (t1[d] > tNear) {
|
||||||
|
tNear = t1[d];
|
||||||
|
tNearIndex = d;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for the far intersection
|
||||||
|
if (t2[d] < tFar) {
|
||||||
|
tFar = t2[d];
|
||||||
|
tFarIndex = d;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check whether we missed the box completely
|
||||||
|
if (tFar < 0 || tNear > tFar)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check whether we are on the outside or on the inside of the box
|
||||||
|
float const t = (tNear >= 0 ? tNear : tFar);
|
||||||
|
int const tIndex = tNear >= 0 ? tNearIndex : tFarIndex;
|
||||||
|
|
||||||
// Test whether this is the foremost primitive in front of the camera
|
// Test whether this is the foremost primitive in front of the camera
|
||||||
|
if (ray.length < t)
|
||||||
|
return false;
|
||||||
|
|
||||||
// (Optional for now) Calculate the normal
|
// Calculate the normal
|
||||||
|
ray.normal = Vector3d(0, 0, 0);
|
||||||
|
// Flip the normal if we are on the inside
|
||||||
|
ray.normal[tIndex] = std::copysignf(1.0f, ray.direction[tIndex]) * (tNear < 0.0f ? +1.0f : -1.0f);
|
||||||
|
|
||||||
// (Optional for now) Calculate the surface position
|
// Calculate the surface position and tangent vector
|
||||||
|
Vector3d const target = ray.origin + t * ray.direction;
|
||||||
|
Vector3d const surface = componentQuotient(target - minBounds, maxBounds - minBounds);
|
||||||
|
if (tIndex == 0) {
|
||||||
|
ray.surface = Vector2d(surface[2], surface[1]);
|
||||||
|
ray.tangent = Vector3d(0, 0, 1);
|
||||||
|
} else if (tIndex == 1) {
|
||||||
|
ray.surface = Vector2d(surface[0], surface[2]);
|
||||||
|
ray.tangent = Vector3d(1, 0, 0);
|
||||||
|
} else {
|
||||||
|
ray.surface = Vector2d(surface[0], surface[1]);
|
||||||
|
ray.tangent = Vector3d(1, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
// Set the new length and the current primitive
|
// Set the new length and the current primitive
|
||||||
|
ray.length = t;
|
||||||
|
ray.primitive = this;
|
||||||
|
|
||||||
return false;
|
// True, because the primitive was hit
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bounding box ////////////////////////////////////////////////////////////////
|
// Bounding box ////////////////////////////////////////////////////////////////
|
||||||
|
|
|
@ -27,7 +27,7 @@ bool InfinitePlane::intersect(Ray &ray) const {
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Set the normal
|
// Set the normal
|
||||||
// IMPLEMENT ME
|
ray.normal = this->normal;
|
||||||
|
|
||||||
// Set the new length and the current primitive
|
// Set the new length and the current primitive
|
||||||
ray.length = t;
|
ray.length = t;
|
||||||
|
|
|
@ -36,7 +36,8 @@ bool Sphere::intersect(Ray &ray) const {
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Calculate the normal
|
// Calculate the normal
|
||||||
// IMPLEMENT ME
|
Vector3d const hitPoint = ray.origin + t * ray.direction;
|
||||||
|
ray.normal = normalized(hitPoint - this->center);
|
||||||
|
|
||||||
// Calculate the surface position and tangent vector
|
// Calculate the surface position and tangent vector
|
||||||
float const phi = std::acos(ray.normal.y);
|
float const phi = std::acos(ray.normal.y);
|
||||||
|
|
|
@ -100,7 +100,7 @@ bool Triangle::intersect(Ray &ray) const {
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Calculate the normal
|
// Calculate the normal
|
||||||
// IMPLEMENT ME
|
ray.normal = normalized(crossProduct(edge1, edge2));
|
||||||
|
|
||||||
// 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];
|
||||||
|
|
|
@ -4,9 +4,16 @@
|
||||||
MirrorShader::MirrorShader() {}
|
MirrorShader::MirrorShader() {}
|
||||||
|
|
||||||
Color MirrorShader::shade(Scene const &scene, Ray const &ray) const {
|
Color MirrorShader::shade(Scene const &scene, Ray const &ray) const {
|
||||||
// IMPLEMENT ME
|
|
||||||
// Calculate the reflection vector
|
// Calculate the reflection vector
|
||||||
|
Vector3d const reflection = ray.direction - 2 * dotProduct(ray.normal, ray.direction) * ray.normal;
|
||||||
|
|
||||||
// Create a new reflection ray
|
// Create a new reflection ray
|
||||||
|
Ray reflectionRay = ray;
|
||||||
|
reflectionRay.origin = ray.origin + (ray.length - REFR_EPS) * ray.direction;
|
||||||
|
reflectionRay.direction = normalized(reflection);
|
||||||
|
reflectionRay.length = INFINITY;
|
||||||
|
reflectionRay.primitive = nullptr;
|
||||||
|
|
||||||
// Send the new ray out into the scene and return the result
|
// Send the new ray out into the scene and return the result
|
||||||
return Color(0, 0, 1);
|
return scene.traceRay(reflectionRay);
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,12 +4,48 @@
|
||||||
RefractionShader::RefractionShader(float indexInside, float indexOutside) : indexInside(indexInside), indexOutside(indexOutside) {}
|
RefractionShader::RefractionShader(float indexInside, float indexOutside) : indexInside(indexInside), indexOutside(indexOutside) {}
|
||||||
|
|
||||||
Color RefractionShader::shade(Scene const &scene, Ray const &ray) const {
|
Color RefractionShader::shade(Scene const &scene, Ray const &ray) const {
|
||||||
// IMPLEMENT ME
|
// Circumvent getting environment map color into the mix
|
||||||
// Calculate the refracted ray using the surface normal vector and
|
if (ray.getRemainingBounces() > 0) {
|
||||||
// indexInside, indexOutside
|
// Get the normal of the primitive which was hit
|
||||||
// Also check for total internal reflection
|
Vector3d normalVector = ray.normal;
|
||||||
// Send out a new refracted ray into the scene; recursively call traceRay()
|
|
||||||
return Color(1, 0, 0);
|
// Calculate the index of refraction
|
||||||
|
float refractiveIndex = indexOutside / indexInside;
|
||||||
|
// What if we are already inside the object?
|
||||||
|
if (dotProduct(normalVector, ray.direction) > 0) {
|
||||||
|
normalVector = -normalVector;
|
||||||
|
refractiveIndex = indexInside / indexOutside;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Using the notation from the lecture
|
||||||
|
float cosineTheta = dotProduct(normalVector, -ray.direction);
|
||||||
|
float cosinePhi = std::sqrt(1 + refractiveIndex * refractiveIndex * (cosineTheta * cosineTheta - 1));
|
||||||
|
// Calculate t, the new ray direction
|
||||||
|
Vector3d t = refractiveIndex * ray.direction + (refractiveIndex * cosineTheta - cosinePhi) * normalVector;
|
||||||
|
|
||||||
|
// Create the refraction ray
|
||||||
|
Ray refractionRay = ray;
|
||||||
|
// Reset the ray
|
||||||
|
refractionRay.length = INFINITY;
|
||||||
|
refractionRay.primitive = nullptr;
|
||||||
|
|
||||||
|
// Check whether it is a refraction.
|
||||||
|
if (dotProduct(t, normalVector) <= 0.0) {
|
||||||
|
refractionRay.origin = ray.origin + (ray.length + REFR_EPS) * ray.direction;
|
||||||
|
refractionRay.direction = normalized(t);
|
||||||
|
} else { // Otherwise, it is a total reflection.
|
||||||
|
refractionRay.origin = ray.origin + (ray.length - REFR_EPS) * ray.direction;
|
||||||
|
// Next we get the reflection vector
|
||||||
|
Vector3d const reflectionVector = ray.direction - 2.0f * dotProduct(normalVector, ray.direction) * normalVector;
|
||||||
|
|
||||||
|
// Change the ray direction and origin
|
||||||
|
refractionRay.direction = normalized(reflectionVector);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send out a new refracted ray into the scene
|
||||||
|
return scene.traceRay(refractionRay);
|
||||||
|
}
|
||||||
|
return Color(0.0f, 0.0f, 0.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RefractionShader::isTransparent() const { return true; }
|
bool RefractionShader::isTransparent() const { return true; }
|
||||||
|
|
|
@ -5,8 +5,11 @@
|
||||||
SimpleShadowShader::SimpleShadowShader(Color const &objectColor) : objectColor(objectColor) {}
|
SimpleShadowShader::SimpleShadowShader(Color const &objectColor) : objectColor(objectColor) {}
|
||||||
|
|
||||||
Color SimpleShadowShader::shade(Scene const &scene, Ray const &ray) const {
|
Color SimpleShadowShader::shade(Scene const &scene, Ray const &ray) const {
|
||||||
// IMPLEMENT ME
|
Color fragmentColor;
|
||||||
// loop over all light sources to check for visibility and multiply "light
|
|
||||||
// strength" with this objects albedo (color)
|
// Accumulate the light over all light sources
|
||||||
return Color(0, 1, 0);
|
for (const auto &light : scene.lights())
|
||||||
|
fragmentColor += light->illuminate(scene, ray).color;
|
||||||
|
|
||||||
|
return fragmentColor * this->objectColor;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue