diff --git a/src/Geometry.cc b/src/Geometry.cc index 0a29ab8..6b544c4 100644 --- a/src/Geometry.cc +++ b/src/Geometry.cc @@ -3,22 +3,23 @@ #include #include -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; } -float Geometry::getPhong() const { return phong; } +Vector3f Geometry::cd() const { return cd_; } +Vector3f Geometry::cs() const { return cs_; } +Vector3f Geometry::ca() const { return ca_; } +float Geometry::kd() const { return kd_; } +float Geometry::ks() const { return ks_; } +float Geometry::ka() const { return ka_; } +float Geometry::phong() const { return phong_; } +Geometry::Type Geometry::type() const { return type_; } void Geometry::setTransform(const Matrix4f &transform) { this->transform = transform; } Optional Sphere::intersect(const Ray &r) const { - Vector3f originCenter = r.getOrigin() - center; - float a = r.getDirection().dot(r.getDirection()); - float b = 2.0f * originCenter.dot(r.getDirection()); + Vector3f originCenter = r.origin() - center; + float a = r.direction().dot(r.direction()); + float b = 2.0f * originCenter.dot(r.direction()); float c = originCenter.dot(originCenter) - radius * radius; float delta = b * b - 4 * a * c; @@ -35,7 +36,7 @@ Optional Sphere::intersect(const Ray &r) const { return Optional::nullopt; } -Vector3f Sphere::getNormal(const Vector3f &p) const { +Vector3f Sphere::normal(const Vector3f &p) const { return (p - center).normalized(); } @@ -51,18 +52,18 @@ bool isInRectangle(const Vector3f &p, const Vector3f &a, const Vector3f &b, } Optional Rectangle::intersect(const Ray &r) const { - float denom = normal.dot(r.getDirection()); + float denom = normal_.dot(r.direction()); if (abs(denom) < 1e-6f) return Optional::nullopt; - float t = -normal.dot(r.getOrigin() - p1) / denom; + float t = -normal_.dot(r.origin() - p1) / denom; if (t <= 0) return Optional::nullopt; - Vector3f p = r.getOrigin() + t * r.getDirection(); + Vector3f p = r.origin() + t * r.direction(); - return isInRectangle(p, p1, p2, p3, p4, normal) ? Optional(t) - : Optional::nullopt; + return isInRectangle(p, p1, p2, p3, p4, normal_) ? Optional(t) + : Optional::nullopt; } -Vector3f Rectangle::getNormal(const Vector3f &p) const { return normal; } +Vector3f Rectangle::normal(const Vector3f &p) const { return normal_; } diff --git a/src/Geometry.h b/src/Geometry.h index b3d1eee..2b8c947 100644 --- a/src/Geometry.h +++ b/src/Geometry.h @@ -19,27 +19,29 @@ public: virtual ~Geometry() = default; virtual Optional intersect(const Ray &) const = 0; - virtual Vector3f getNormal(const Vector3f &) const = 0; + virtual Vector3f normal(const Vector3f &) const = 0; protected: Geometry(Type type, float ka, float kd, float ks, const Vector3f &ca, const Vector3f &cd, const Vector3f &cs, float pc) - : type(type), ka(ka), kd(kd), ks(ks), ca(ca), cd(cd), cs(cs), phong(pc) {} + : type_(type), ka_(ka), kd_(kd), ks_(ks), ca_(ca), cd_(cd), cs_(cs), + phong_(pc) {} - Type type; - float ka, kd, ks; // coefficients for ambient, diffuse and specular - Vector3f ca, cd, cs; // ambient, diffuse and specular reflection color - float phong; // phone coefficient, for `pc` + Type type_; + float ka_, kd_, ks_; // coefficients for ambient, diffuse and specular + Vector3f ca_, cd_, cs_; // ambient, diffuse and specular reflection color + float phong_; // phone coefficient, for `pc` Matrix4f transform = Matrix4f::Identity(); public: - Vector3f diffuse() const; - Vector3f specular() const; - Vector3f ambient() const; - float coefDiffuse() const; - float coefSpecular() const; - float coefAmbient() const; - float getPhong() const; + Vector3f cd() const; + Vector3f cs() const; + Vector3f ca() const; + float kd() const; + float ks() const; + float ka() const; + float phong() const; + Type type() const; void setTransform(const Matrix4f &); }; @@ -51,7 +53,7 @@ public: center(center) {} Optional intersect(const Ray &) const override; - Vector3f getNormal(const Vector3f &) const override; + Vector3f normal(const Vector3f &) const override; private: float radius; @@ -64,14 +66,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), normal((p2 - p1).cross(p3 - p1).normalized()) {} + p3(p3), p4(p4), normal_((p2 - p1).cross(p3 - p1).normalized()) {} Optional intersect(const Ray &) const override; - Vector3f getNormal(const Vector3f &) const override; + Vector3f normal(const Vector3f &) const override; private: Vector3f p1, p2, p3, p4; - Vector3f normal; + Vector3f normal_; }; #endif // !GEOMETRY_H_ diff --git a/src/HitRecord.cc b/src/HitRecord.cc index 6a07ee7..261e449 100644 --- a/src/HitRecord.cc +++ b/src/HitRecord.cc @@ -4,16 +4,16 @@ bool HitRecord::operator<(const HitRecord &other) const { return this->t > other.t; // to get the nearest t } -Geometry *HitRecord::geometry() const { return g; } +Geometry *HitRecord::geometry() const { return geometry_; } -Vector3f HitRecord::getPoint() const { - return r.getOrigin() + t * r.getDirection(); +Vector3f HitRecord::point() const { + return ray_.origin() + t * ray_.direction(); } Vector3f HitRecord::viewDirection() const { - return -r.getDirection().normalized(); + return -ray_.direction().normalized(); } -Vector3f HitRecord::normal() const { return n; } +Vector3f HitRecord::normal() const { return normal_; } -void HitRecord::calcNormal() { n = g->getNormal(getPoint()); } +void HitRecord::calcNormal() { normal_ = geometry_->normal(point()); } diff --git a/src/HitRecord.h b/src/HitRecord.h index c7fad17..599db5a 100644 --- a/src/HitRecord.h +++ b/src/HitRecord.h @@ -9,18 +9,18 @@ using Eigen::Vector3f; class HitRecord { public: - HitRecord(float t, const Ray &r, Geometry *g) : t(t), r(r), g(g) {} + HitRecord(float t, const Ray &r, Geometry *g) : t(t), ray_(r), geometry_(g) {} bool operator<(const HitRecord &) const; private: float t; - Ray r; - Vector3f n; - Geometry *g; + Ray ray_; + Vector3f normal_; + Geometry *geometry_; public: Geometry *geometry() const; - Vector3f getPoint() const; + Vector3f point() const; Vector3f viewDirection() const; Vector3f normal() const; void calcNormal(); diff --git a/src/Light.cc b/src/Light.cc index 2b0030a..a23cd0c 100644 --- a/src/Light.cc +++ b/src/Light.cc @@ -1,4 +1,6 @@ #include "Light.h" +#include "Scene.h" + #include #include @@ -12,34 +14,34 @@ void Light::setUseCenter(bool useCenter) { this->useCenter = useCenter; } void Light::setIsUse(bool isUse) { this->use = isUse; } -Vector3f Light::getDiffuse() const { return diffuse; } +Vector3f Light::id() const { return id_; } -Vector3f Light::getSpecular() const { return specular; } +Vector3f Light::is() const { return is_; } bool Light::isUse() const { return use; } Vector3f PointLight::illumination(const HitRecord &hit, const vector &geometries) const { - Vector3f shadingPoint = hit.getPoint(); + Vector3f shadingPoint = hit.point(); Vector3f rayDirection = (center - shadingPoint).normalized(); Geometry *geometry = hit.geometry(); Ray shadowRay(shadingPoint, rayDirection); for (auto g : geometries) - if (g != geometry && g->intersect(shadowRay).hasValue()) + if (g != geometry && g->intersect(shadowRay).hasValue() && + g->type() == Geometry::Type::SPHERE) return Vector3f::Zero(); - Vector3f ambient_ = geometry->coefAmbient() * geometry->ambient(); + Vector3f ambient_ = + geometry->ka() * geometry->ca().array() * Scene::current->ai().array(); - Vector3f diffuse_ = geometry->coefDiffuse() * geometry->diffuse().array() * - diffuse.array() * + Vector3f diffuse_ = geometry->kd() * geometry->cd().array() * id_.array() * std::max(0.0f, hit.normal().dot(rayDirection)); Vector3f halfWay = (hit.viewDirection() + rayDirection).normalized(); Vector3f specular_ = - geometry->coefSpecular() * geometry->specular().array() * - specular.array() * - pow(std::max(0.0f, hit.normal().dot(halfWay)), geometry->getPhong()); + geometry->ks() * geometry->cs().array() * is_.array() * + pow(std::max(0.0f, hit.normal().dot(halfWay)), geometry->phong()); return specular_ + ambient_ + diffuse_; } @@ -55,9 +57,12 @@ Vector3f AreaLight::illumination(const HitRecord &hit, color += PointLight(*this, p1 + (u + v) / 2).illumination(hit, geometries); } else { for (int y = 0; y < gridSize; ++y) - for (int x = 0; x < gridSize; ++x) - color += PointLight(*this, p1 + (u * x + v * y) / gridSize) - .illumination(hit, geometries); + for (int x = 0; x < gridSize; ++x) { + Vector3f contribution = + PointLight(*this, p1 + (u * x + v * y) / gridSize) + .illumination(hit, geometries); + color += contribution; + } } return color / gridSize / gridSize; diff --git a/src/Light.h b/src/Light.h index 60afbce..7f21867 100644 --- a/src/Light.h +++ b/src/Light.h @@ -21,11 +21,11 @@ public: protected: Light(Type type, const Vector3f &id, const Vector3f &is) - : type(type), diffuse(id), specular(is) {} + : type_(type), id_(id), is_(is) {} - Type type; - Vector3f diffuse; - Vector3f specular; + Type type_; + Vector3f id_; + Vector3f is_; Matrix4f transform = Matrix4f::Identity(); // optional member `transform` unsigned int gridSize = 0; // optional member `n` bool useCenter = false; // optional member `usecenter` @@ -36,8 +36,8 @@ public: void setGridSize(unsigned int); void setUseCenter(bool); void setIsUse(bool); - Vector3f getDiffuse() const; - Vector3f getSpecular() const; + Vector3f id() const; + Vector3f is() const; bool isUse() const; }; @@ -60,7 +60,7 @@ public: : Light(Type::Point, id, is), center(center) {} PointLight(const AreaLight &al, const Vector3f ¢er) - : PointLight(al.getDiffuse(), al.getSpecular(), center) {} + : PointLight(al.id(), al.is(), center) {} virtual Vector3f illumination(const HitRecord &, const vector &) const override; diff --git a/src/Output.cc b/src/Output.cc index 840212b..222e585 100644 --- a/src/Output.cc +++ b/src/Output.cc @@ -2,6 +2,8 @@ #include +Output *Output::current = nullptr; + void Output::write() { std::ofstream fout(path, std::ios_base::out | std::ios_base::binary); fout << "P6\n" << width << ' ' << height << '\n' << "255" << std::endl; diff --git a/src/Output.h b/src/Output.h index d7a065d..8cf7b9c 100644 --- a/src/Output.h +++ b/src/Output.h @@ -33,6 +33,8 @@ public: float g(int) const; void b(int, float); float b(int) const; + + static Output *current; }; #endif // !OUTPUT_H_ diff --git a/src/Ray.cc b/src/Ray.cc index 4cafd1d..fddd2f5 100644 --- a/src/Ray.cc +++ b/src/Ray.cc @@ -1,5 +1,5 @@ #include "Ray.h" -Vector3f Ray::getOrigin() const { return origin; } +Vector3f Ray::origin() const { return origin_; } -Vector3f Ray::getDirection() const { return direction; } +Vector3f Ray::direction() const { return direction_; } diff --git a/src/Ray.h b/src/Ray.h index 9fe5b37..a344e5d 100644 --- a/src/Ray.h +++ b/src/Ray.h @@ -7,15 +7,15 @@ using Eigen::Vector3f; class Ray { public: - Ray(const Vector3f &o, const Vector3f &d) : origin(o), direction(d) {} + Ray(const Vector3f &o, const Vector3f &d) : origin_(o), direction_(d) {} private: - Vector3f origin; - Vector3f direction; + Vector3f origin_; + Vector3f direction_; public: - Vector3f getOrigin() const; - Vector3f getDirection() const; + Vector3f origin() const; + Vector3f direction() const; }; #endif // !RAY_H_ diff --git a/src/RayTracer.cc b/src/RayTracer.cc index c79add8..1209fae 100644 --- a/src/RayTracer.cc +++ b/src/RayTracer.cc @@ -27,27 +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); +void RayTracer::calculateColor(const HitRecord &hit, int i) { + Vector3f result(0, 0, 0); for (auto light : lights) - if (light->isUse()) { - Vector3f contribution = - light->illumination(hit, geometries).cwiseMax(0.0f).cwiseMin(1.0f) / - lights.size(); - buffer->r(i, buffer->r(i) + contribution.x()); - buffer->g(i, buffer->g(i) + contribution.y()); - buffer->b(i, buffer->b(i) + contribution.z()); - } + result += light->isUse() ? light->illumination(hit, geometries) + : Vector3f::Zero(); + + result = result.cwiseMax(0.0f).cwiseMin(1.0f); + Output::current->r(i, result.x()); + Output::current->g(i, result.y()); + Output::current->b(i, result.z()); } -void RayTracer::render(Scene *scene) { - int width = scene->getWidth(); - int height = scene->getHeight(); - Vector3f cameraPos = scene->getCenter(); - Vector3f lookAt = scene->getLookAt(); - float vpHeight = 2 * tan(scene->getFov() / 180 * M_PI / 2) * lookAt.norm(); +void RayTracer::render() { + int width = Scene::current->width(); + int height = Scene::current->height(); + Vector3f cameraPos = Scene::current->center(); + Vector3f lookAt = Scene::current->lookAt(); + float vpHeight = + 2 * tan(Scene ::current->fov() / 180 * M_PI / 2) * lookAt.norm(); float vpWidth = vpHeight * width / height; Vector3f vpU = Vector3f(vpWidth, 0, 0); Vector3f vpV = Vector3f(0, -vpHeight, 0); @@ -57,8 +55,8 @@ void RayTracer::render(Scene *scene) { Vector3f vpUpperLeft = cameraPos + lookAt - vpU / 2.0 - vpV / 2.0; Vector3f pxUpperLeft = vpUpperLeft + (du + dv) / 2.0; - Output *buffer = - new Output(scene->getBackgroundColor(), scene->getName(), width, height); + Output::current = new Output(Scene::current->backgroundColor(), + Scene::current->name(), width, height); for (int y = 0; y < height; ++y) for (int x = 0; x < width; ++x) { @@ -73,11 +71,9 @@ void RayTracer::render(Scene *scene) { if (!records.empty()) { HitRecord hit = records.top(); hit.calcNormal(); - calculateColor(hit, buffer, y * width + x); + calculateColor(hit, y * width + x); } } - - outputs.push_back(buffer); } void RayTracer::output() { @@ -88,8 +84,9 @@ void RayTracer::output() { void RayTracer::run() { parse(); - for (auto scene : scenes) - render(scene); - - output(); + for (auto scene : scenes) { + Scene::current = scene; + render(); + Output::current->write(); + } } diff --git a/src/RayTracer.h b/src/RayTracer.h index 43a9075..764bd05 100644 --- a/src/RayTracer.h +++ b/src/RayTracer.h @@ -22,8 +22,8 @@ private: std::vector outputs; void parse(); - void calculateColor(const HitRecord &, Output *, int); - void render(Scene *); + void calculateColor(const HitRecord &, int); + void render(); void output(); }; diff --git a/src/Scene.cc b/src/Scene.cc index 9c48128..f9d9840 100644 --- a/src/Scene.cc +++ b/src/Scene.cc @@ -1,33 +1,37 @@ #include "Scene.h" -string Scene::getName() const { return name; } +Scene *Scene::current = nullptr; -int Scene::getWidth() { return width; } +string Scene::name() const { return name_; } -int Scene::getHeight() { return height; } +int Scene::width() { return width_; } -float Scene::getFov() { return fov; } +int Scene::height() { return height_; } -Vector3f Scene::getCenter() const { return center; } +float Scene::fov() { return fov_; } -Vector3f Scene::getUpVector() const { return up; } +Vector3f Scene::ai() const { return ai_; } -Vector3f Scene::getLookAt() const { return lookAt; } +Vector3f Scene::center() const { return center_; } -Vector3f Scene::getBackgroundColor() const { return backgroundColor; } +Vector3f Scene::up() const { return up_; } + +Vector3f Scene::lookAt() const { return lookAt_; } + +Vector3f Scene::backgroundColor() const { return bgc_; } void Scene::setRaysPerPixel(const Eigen::VectorXi &raysPerPixel) { - this->raysPerPixel = raysPerPixel; + this->raysPerPixel_ = raysPerPixel; } void Scene::setAntialiasing(bool antialiasing) { - this->antialiasing = antialiasing; + this->antialiasing_ = antialiasing; } void Scene::setTwoSideRender(bool twoSideRender) { - this->twoSideRender = twoSideRender; + this->twoSideRender_ = twoSideRender; } void Scene::setGlobalIllum(bool globalIllum) { - this->globalIllum = globalIllum; + this->globalIllum_ = globalIllum; } diff --git a/src/Scene.h b/src/Scene.h index 8ac10e0..6775ac2 100644 --- a/src/Scene.h +++ b/src/Scene.h @@ -12,38 +12,40 @@ public: Scene(string name, int width, int height, float fov, const Vector3f ¢er, const Vector3f &up, const Vector3f &lookAt, const Vector3f &ai, const Vector3f &bgc) - : name(name), width(width), height(height), fov(fov), center(center), - up(up), lookAt(lookAt), ai(ai), backgroundColor(bgc) {} + : name_(name), width_(width), height_(height), fov_(fov), center_(center), + up_(up), lookAt_(lookAt), ai_(ai), bgc_(bgc) {} private: - string name; - int width; - int height; - float fov; - Vector3f center; - Vector3f up; - Vector3f lookAt; - Vector3f ai; // ambient intensity - Vector3f backgroundColor; + string name_; + int width_; + int height_; + float fov_; + Vector3f center_; + Vector3f up_; + Vector3f lookAt_; + Vector3f ai_; // ambient intensity + Vector3f bgc_; - Eigen::VectorXi raysPerPixel; - bool antialiasing = false; - bool twoSideRender = false; - bool globalIllum = false; + Eigen::VectorXi raysPerPixel_; + bool antialiasing_ = false; + bool twoSideRender_ = false; + bool globalIllum_ = false; public: - string getName() const; - int getWidth(); - int getHeight(); - float getFov(); - Vector3f getCenter() const; - Vector3f getUpVector() const; - Vector3f getLookAt() const; - Vector3f getBackgroundColor() const; + string name() const; + int width(); + int height(); + float fov(); + Vector3f ai() const; + Vector3f center() const; + Vector3f up() const; + Vector3f lookAt() const; + Vector3f backgroundColor() const; void setRaysPerPixel(const Eigen::VectorXi &); void setAntialiasing(bool); void setTwoSideRender(bool); void setGlobalIllum(bool); + static Scene *current; }; #endif // !SCENE_H_