From bb8819013ccc40bd45c4347b96431aa6d0309f49 Mon Sep 17 00:00:00 2001 From: vonhyou Date: Thu, 29 Feb 2024 00:15:00 -0500 Subject: [PATCH] work on direct illumination --- src/Geometry.cc | 11 +++++++++-- src/Geometry.h | 10 +++++++++- src/HitRecord.cc | 8 ++++++++ src/HitRecord.h | 11 ++++++++++- src/Light.cc | 19 +++++++++++++++++-- src/Light.h | 12 +++++++++--- src/RayTracer.cc | 25 +++++++++++++++++-------- src/RayTracer.h | 2 +- 8 files changed, 80 insertions(+), 18 deletions(-) diff --git a/src/Geometry.cc b/src/Geometry.cc index 1072868..1969397 100644 --- a/src/Geometry.cc +++ b/src/Geometry.cc @@ -6,6 +6,9 @@ Vector3f Geometry::diffuse() const { return cd; } Vector3f Geometry::specular() const { return cs; } Vector3f Geometry::ambient() const { return ca; } +float Geometry::coefDiffuse() const { return kd; } +float Geometry::coefSpecular() const { return ks; } +float Geometry::coefAmbient() const { return ka; } void Geometry::setTransform(const Matrix4f &transform) { this->transform = transform; @@ -31,6 +34,10 @@ Optional Sphere::intersect(const Ray &r) const { return Optional::nullopt; } +Vector3f Sphere::getNormal(const Vector3f &p) const { + return (p - center).normalized(); +} + bool isInRectangle(const Vector3f &p, const Vector3f &a, const Vector3f &b, const Vector3f &c, const Vector3f &d, const Vector3f &n) { float s1 = (b - a).cross(p - a).dot(n); @@ -43,8 +50,6 @@ bool isInRectangle(const Vector3f &p, const Vector3f &a, const Vector3f &b, } Optional Rectangle::intersect(const Ray &r) const { - Vector3f normal = (p2 - p1).cross(p3 - p1).normalized(); - float denom = normal.dot(r.getDirection()); if (abs(denom) < 1e-6f) return Optional::nullopt; @@ -58,3 +63,5 @@ Optional Rectangle::intersect(const Ray &r) const { return isInRectangle(p, p1, p2, p3, p4, normal) ? Optional(t) : Optional::nullopt; } + +Vector3f Rectangle::getNormal(const Vector3f &p) const { return normal; } diff --git a/src/Geometry.h b/src/Geometry.h index 09c97c0..dc3be95 100644 --- a/src/Geometry.h +++ b/src/Geometry.h @@ -5,6 +5,7 @@ #include "Ray.h" #include +#include using Eigen::Matrix; using Eigen::Matrix4f; @@ -18,6 +19,7 @@ public: virtual ~Geometry() = default; virtual Optional intersect(const Ray &) const = 0; + virtual Vector3f getNormal(const Vector3f &) const = 0; protected: Geometry(Type type, float ka, float kd, float ks, const Vector3f &ca, @@ -34,6 +36,9 @@ public: Vector3f diffuse() const; Vector3f specular() const; Vector3f ambient() const; + float coefDiffuse() const; + float coefSpecular() const; + float coefAmbient() const; void setTransform(const Matrix4f &); }; @@ -45,6 +50,7 @@ public: center(center) {} Optional intersect(const Ray &) const override; + Vector3f getNormal(const Vector3f &) const override; private: float radius; @@ -57,12 +63,14 @@ public: const Vector3f &cs, float pc, const Vector3f &p1, const Vector3f &p2, const Vector3f &p3, const Vector3f &p4) : Geometry(Type::RECTANGLE, ka, kd, ks, ca, cd, cs, pc), p1(p1), p2(p2), - p3(p3), p4(p4) {} + p3(p3), p4(p4), normal((p2 - p1).cross(p3 - p1).normalized()) {} Optional intersect(const Ray &) const override; + Vector3f getNormal(const Vector3f &) const override; private: Vector3f p1, p2, p3, p4; + Vector3f normal; }; #endif // !GEOMETRY_H_ diff --git a/src/HitRecord.cc b/src/HitRecord.cc index bb18770..9f50540 100644 --- a/src/HitRecord.cc +++ b/src/HitRecord.cc @@ -5,3 +5,11 @@ bool HitRecord::operator<(const HitRecord &other) const { } Geometry *HitRecord::geometry() const { return g; } + +Vector3f HitRecord::getPoint() const { + return r.getOrigin() + t * r.getDirection(); +} + +Vector3f HitRecord::normal() const { return n; } + +void HitRecord::calcNormal() { n = g->getNormal(getPoint()); } diff --git a/src/HitRecord.h b/src/HitRecord.h index 705d2a6..87290fc 100644 --- a/src/HitRecord.h +++ b/src/HitRecord.h @@ -2,18 +2,27 @@ #define HITRECORD_H_ #include "Geometry.h" +#include "Ray.h" +#include + +using Eigen::Vector3f; class HitRecord { public: - HitRecord(float t, Geometry *g) : t(t), g(g) {} + HitRecord(float t, const Ray &r, Geometry *g) : t(t), r(r), g(g) {} bool operator<(const HitRecord &) const; private: float t; + Ray r; + Vector3f n; Geometry *g; public: Geometry *geometry() const; + Vector3f getPoint() const; + Vector3f normal() const; + void calcNormal(); }; #endif // !HITRECORD_H_ diff --git a/src/Light.cc b/src/Light.cc index 07d7c27..68fb168 100644 --- a/src/Light.cc +++ b/src/Light.cc @@ -8,6 +8,21 @@ void Light::setGridSize(unsigned int gridSize) { this->gridSize = gridSize; } void Light::setUseCenter(bool useCenter) { this->useCenter = useCenter; } -void PointLight::illumination() const {} +Vector3f PointLight::illumination(const HitRecord &hit, + const vector &geometries) const { + Vector3f shadingPoint = hit.getPoint(); + Vector3f rayDirection = (center - shadingPoint).normalized(); + Geometry *geometry = hit.geometry(); + Ray shadowRay(shadingPoint, rayDirection); -void AreaLight::illumination() const {} + for (auto g : geometries) + if (g != geometry && g->intersect(shadowRay).hasValue()) + return Vector3f::Zero(); + + return Vector3f::Zero(); +} + +Vector3f AreaLight::illumination(const HitRecord &hit, + const vector &geometries) const { + return Vector3f::Zero(); +} diff --git a/src/Light.h b/src/Light.h index c708467..84163ed 100644 --- a/src/Light.h +++ b/src/Light.h @@ -1,11 +1,14 @@ #ifndef LIGHT_H_ #define LIGHT_H_ +#include "HitRecord.h" #include +#include using Eigen::Matrix; using Eigen::Matrix4f; using Eigen::Vector3f; +using std::vector; // Abstract base class for Lights class Light { @@ -13,7 +16,8 @@ public: enum class Type { Point, Area }; virtual ~Light() = default; - virtual void illumination() const = 0; + virtual Vector3f illumination(const HitRecord &, + const vector &) const = 0; protected: Light(Type type, const Vector3f &id, const Vector3f &is) @@ -38,7 +42,8 @@ public: PointLight(const Vector3f &id, const Vector3f &is, Vector3f ¢er) : Light(Type::Point, id, is), center(center) {} - virtual void illumination() const override; + virtual Vector3f illumination(const HitRecord &, + const vector &) const override; private: Vector3f center; @@ -50,7 +55,8 @@ public: const Vector3f &p2, const Vector3f &p3, const Vector3f &p4) : Light(Type::Area, id, is), p1(p1), p2(p2), p3(p3), p4(p4) {} - virtual void illumination() const override; + virtual Vector3f illumination(const HitRecord &, + const vector &) const override; private: Vector3f p1, p2, p3, p4; diff --git a/src/RayTracer.cc b/src/RayTracer.cc index cd51d50..6ae028b 100644 --- a/src/RayTracer.cc +++ b/src/RayTracer.cc @@ -27,14 +27,25 @@ Ray getRay(int x, int y, const Vector3f &camPos, const Vector3f &pxUpperLeft, return Ray(camPos, pxUpperLeft + x * du + y * dv - camPos); } +void RayTracer::calculateColor(const HitRecord &hit, Output *buffer, int i) { + buffer->r(i, 0); + buffer->g(i, 0); + buffer->b(i, 0); + + for (auto light : lights) { + Vector3f contribution = light->illumination(hit, geometries); + buffer->r(i, buffer->r(i) + contribution.x()); + buffer->g(i, buffer->g(i) + contribution.y()); + buffer->b(i, buffer->b(i) + contribution.z()); + } +} + void RayTracer::render(Scene *scene) { int width = scene->getWidth(); int height = scene->getHeight(); - float fov = scene->getFov(); Vector3f cameraPos = scene->getCenter(); Vector3f lookAt = scene->getLookAt(); - Vector3f up = scene->getUpVector(); - float vpHeight = 2 * tan(fov / 180 * M_PI / 2) * lookAt.norm(); + float vpHeight = 2 * tan(scene->getFov() / 180 * M_PI / 2) * lookAt.norm(); float vpWidth = vpHeight * width / height; Vector3f vpU = Vector3f(vpWidth, 0, 0); Vector3f vpV = Vector3f(0, -vpHeight, 0); @@ -54,15 +65,13 @@ void RayTracer::render(Scene *scene) { for (auto g : geometries) { Optional t = g->intersect(ray); if (t.hasValue()) - records.push(HitRecord(t.value(), g)); + records.push(HitRecord(t.value(), ray, g)); } if (!records.empty()) { HitRecord hit = records.top(); - Vector3f diffuse = hit.geometry()->diffuse(); - buffer->r(y * width + x, diffuse.x()); - buffer->g(y * width + x, diffuse.y()); - buffer->b(y * width + x, diffuse.z()); + hit.calcNormal(); + calculateColor(hit, buffer, y * width + x); } } diff --git a/src/RayTracer.h b/src/RayTracer.h index 807b370..6ca8254 100644 --- a/src/RayTracer.h +++ b/src/RayTracer.h @@ -20,10 +20,10 @@ private: std::vector scenes; std::vector lights; std::vector geometries; - std::vector outputs; void parse(); + void calculateColor(const HitRecord &, Output *, int); void render(Scene *); void output(); };