aboutsummaryrefslogtreecommitdiff
path: root/src/illuminate/reflect.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/illuminate/reflect.cpp')
-rw-r--r--src/illuminate/reflect.cpp115
1 files changed, 115 insertions, 0 deletions
diff --git a/src/illuminate/reflect.cpp b/src/illuminate/reflect.cpp
new file mode 100644
index 0000000..c7fea98
--- /dev/null
+++ b/src/illuminate/reflect.cpp
@@ -0,0 +1,115 @@
+//
+// Created by Michael Foiani on 11/4/23.
+//
+
+#include "raytracer/raytracer.h"
+
+// helper that reflects vectors
+glm::vec3 reflectVector(
+ glm::vec3 incidentDir,
+ glm::vec3 normal)
+{
+ return incidentDir - 2.f * glm::dot(incidentDir, normal) * normal;
+}
+
+glm::vec4 RayTracer::reflect(
+ glm::vec3 intersectionWorld,
+ glm::vec3 normalWorld,
+ glm::vec3 incidentDir,
+ const RenderShapeData &shape,
+ const RayTraceScene &scene,
+ int depth)
+{
+ auto material = shape.primitive.material;
+ // check if the material is reflective
+ if (material.cReflective == glm::vec4(0.f))
+ {
+ return glm::vec4(0.f);
+ }
+ auto reflectedDir = reflectVector(incidentDir, normalWorld);
+
+ // shoot a ray from the intersection point in the reflected direction
+ auto reflectColors = getPixelFromRay(glm::vec4(intersectionWorld + .001f * reflectedDir, 1.f), glm::vec4(reflectedDir, 0.f), scene, depth + 1);
+ return scene.getGlobalData().ks * material.cReflective * reflectColors;
+}
+
+// EXTRA CREDIT -> refracting
+
+// TRUE REFRACTING
+// get the reflection coefficient from fresnel's equations
+bool REAL_REFRACTING = false;
+float fresnels(
+ float currentMediumIor,
+ float otherMediumIor,
+ float cosAngleIncident,
+ float cosAngleTransmitted)
+{
+ float rPerp = (currentMediumIor * cosAngleIncident - otherMediumIor * cosAngleTransmitted) /
+ (currentMediumIor * cosAngleIncident + otherMediumIor * cosAngleTransmitted);
+ rPerp *= rPerp;
+ float rPara = (otherMediumIor * cosAngleIncident - currentMediumIor * cosAngleTransmitted) /
+ (otherMediumIor * cosAngleIncident + currentMediumIor * cosAngleTransmitted);
+ rPara *= rPara;
+ return (rPerp + rPara) / 2.f;
+}
+
+// Your refracting
+glm::vec4 RayTracer::refract(
+ glm::vec3 intersectionWorld,
+ glm::vec3 normalWorld,
+ glm::vec3 incidentDir,
+ const RenderShapeData& shape,
+ const RayTraceScene &scene,
+ int depth
+)
+{
+ auto material = shape.primitive.material;
+ // check if the material is transparent
+ if (material.cTransparent == glm::vec4(0.f))
+ {
+ return glm::vec4(0.f);
+ }
+
+ // apply snells law to find the sin of refracted angle (squared)
+ incidentDir = glm::normalize(incidentDir);
+ float cosAngleIncident = glm::dot(incidentDir, normalWorld);
+ float currentMediumIor = mediumIor;
+ float otherMediumIor = material.ior;
+
+ if (cosAngleIncident < 0)
+ {
+ // outside the object
+ cosAngleIncident = -cosAngleIncident;
+ }
+ else
+ {
+ // inside the object, invert the normal and swap the Iors
+ normalWorld = -normalWorld;
+ std::swap(currentMediumIor, otherMediumIor);
+ }
+
+ float iorRatio = currentMediumIor / otherMediumIor;
+ float sinAngleTransmittedSquared = iorRatio * iorRatio * (1 - cosAngleIncident * cosAngleIncident);
+ if (sinAngleTransmittedSquared > 1.f) // total internal reflection, not considered
+ {
+ return glm::vec4(0.f);
+ }
+
+ auto cosAngleTransmitted = glm::sqrt(1 - sinAngleTransmittedSquared);
+
+ // compute refracted ray according to snell's law
+ auto refractedDir = glm::normalize(
+ incidentDir * iorRatio
+ + (iorRatio * cosAngleIncident - cosAngleTransmitted) * normalWorld);
+
+ // send a ray in the refracted direction to get the colors
+ auto refractedColors = getPixelFromRay(
+ glm::vec4(intersectionWorld + .001f * refractedDir, 1.f),
+ glm::vec4(refractedDir, 0.f),
+ scene,
+ depth + 1);
+
+ float fresnel = fresnels(currentMediumIor, otherMediumIor, cosAngleIncident, cosAngleTransmitted);
+ auto color = scene.getGlobalData().kt * material.cTransparent * refractedColors * (1 - fresnel);
+ return color;
+} \ No newline at end of file