mirror of
https://github.com/vonhyou/ray-tracer-comp371.git
synced 2025-06-08 07:22:01 +00:00
work on direct illumination
This commit is contained in:
parent
184812c533
commit
bb8819013c
8 changed files with 80 additions and 18 deletions
|
@ -6,6 +6,9 @@
|
||||||
Vector3f Geometry::diffuse() const { return cd; }
|
Vector3f Geometry::diffuse() const { return cd; }
|
||||||
Vector3f Geometry::specular() const { return cs; }
|
Vector3f Geometry::specular() const { return cs; }
|
||||||
Vector3f Geometry::ambient() const { return ca; }
|
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) {
|
void Geometry::setTransform(const Matrix4f &transform) {
|
||||||
this->transform = transform;
|
this->transform = transform;
|
||||||
|
@ -31,6 +34,10 @@ Optional<float> Sphere::intersect(const Ray &r) const {
|
||||||
return Optional<float>::nullopt;
|
return Optional<float>::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Vector3f Sphere::getNormal(const Vector3f &p) const {
|
||||||
|
return (p - center).normalized();
|
||||||
|
}
|
||||||
|
|
||||||
bool isInRectangle(const Vector3f &p, const Vector3f &a, const Vector3f &b,
|
bool isInRectangle(const Vector3f &p, const Vector3f &a, const Vector3f &b,
|
||||||
const Vector3f &c, const Vector3f &d, const Vector3f &n) {
|
const Vector3f &c, const Vector3f &d, const Vector3f &n) {
|
||||||
float s1 = (b - a).cross(p - a).dot(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<float> Rectangle::intersect(const Ray &r) const {
|
Optional<float> Rectangle::intersect(const Ray &r) const {
|
||||||
Vector3f normal = (p2 - p1).cross(p3 - p1).normalized();
|
|
||||||
|
|
||||||
float denom = normal.dot(r.getDirection());
|
float denom = normal.dot(r.getDirection());
|
||||||
if (abs(denom) < 1e-6f)
|
if (abs(denom) < 1e-6f)
|
||||||
return Optional<float>::nullopt;
|
return Optional<float>::nullopt;
|
||||||
|
@ -58,3 +63,5 @@ Optional<float> Rectangle::intersect(const Ray &r) const {
|
||||||
return isInRectangle(p, p1, p2, p3, p4, normal) ? Optional<float>(t)
|
return isInRectangle(p, p1, p2, p3, p4, normal) ? Optional<float>(t)
|
||||||
: Optional<float>::nullopt;
|
: Optional<float>::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Vector3f Rectangle::getNormal(const Vector3f &p) const { return normal; }
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
#include "Ray.h"
|
#include "Ray.h"
|
||||||
|
|
||||||
#include <Eigen/Core>
|
#include <Eigen/Core>
|
||||||
|
#include <Eigen/Dense>
|
||||||
|
|
||||||
using Eigen::Matrix;
|
using Eigen::Matrix;
|
||||||
using Eigen::Matrix4f;
|
using Eigen::Matrix4f;
|
||||||
|
@ -18,6 +19,7 @@ public:
|
||||||
|
|
||||||
virtual ~Geometry() = default;
|
virtual ~Geometry() = default;
|
||||||
virtual Optional<float> intersect(const Ray &) const = 0;
|
virtual Optional<float> intersect(const Ray &) const = 0;
|
||||||
|
virtual Vector3f getNormal(const Vector3f &) const = 0;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Geometry(Type type, float ka, float kd, float ks, const Vector3f &ca,
|
Geometry(Type type, float ka, float kd, float ks, const Vector3f &ca,
|
||||||
|
@ -34,6 +36,9 @@ public:
|
||||||
Vector3f diffuse() const;
|
Vector3f diffuse() const;
|
||||||
Vector3f specular() const;
|
Vector3f specular() const;
|
||||||
Vector3f ambient() const;
|
Vector3f ambient() const;
|
||||||
|
float coefDiffuse() const;
|
||||||
|
float coefSpecular() const;
|
||||||
|
float coefAmbient() const;
|
||||||
void setTransform(const Matrix4f &);
|
void setTransform(const Matrix4f &);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -45,6 +50,7 @@ public:
|
||||||
center(center) {}
|
center(center) {}
|
||||||
|
|
||||||
Optional<float> intersect(const Ray &) const override;
|
Optional<float> intersect(const Ray &) const override;
|
||||||
|
Vector3f getNormal(const Vector3f &) const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
float radius;
|
float radius;
|
||||||
|
@ -57,12 +63,14 @@ public:
|
||||||
const Vector3f &cs, float pc, const Vector3f &p1,
|
const Vector3f &cs, float pc, const Vector3f &p1,
|
||||||
const Vector3f &p2, const Vector3f &p3, const Vector3f &p4)
|
const Vector3f &p2, const Vector3f &p3, const Vector3f &p4)
|
||||||
: Geometry(Type::RECTANGLE, ka, kd, ks, ca, cd, cs, pc), p1(p1), p2(p2),
|
: 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<float> intersect(const Ray &) const override;
|
Optional<float> intersect(const Ray &) const override;
|
||||||
|
Vector3f getNormal(const Vector3f &) const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Vector3f p1, p2, p3, p4;
|
Vector3f p1, p2, p3, p4;
|
||||||
|
Vector3f normal;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // !GEOMETRY_H_
|
#endif // !GEOMETRY_H_
|
||||||
|
|
|
@ -5,3 +5,11 @@ bool HitRecord::operator<(const HitRecord &other) const {
|
||||||
}
|
}
|
||||||
|
|
||||||
Geometry *HitRecord::geometry() const { return g; }
|
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()); }
|
||||||
|
|
|
@ -2,18 +2,27 @@
|
||||||
#define HITRECORD_H_
|
#define HITRECORD_H_
|
||||||
|
|
||||||
#include "Geometry.h"
|
#include "Geometry.h"
|
||||||
|
#include "Ray.h"
|
||||||
|
#include <Eigen/Core>
|
||||||
|
|
||||||
|
using Eigen::Vector3f;
|
||||||
|
|
||||||
class HitRecord {
|
class HitRecord {
|
||||||
public:
|
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;
|
bool operator<(const HitRecord &) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
float t;
|
float t;
|
||||||
|
Ray r;
|
||||||
|
Vector3f n;
|
||||||
Geometry *g;
|
Geometry *g;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Geometry *geometry() const;
|
Geometry *geometry() const;
|
||||||
|
Vector3f getPoint() const;
|
||||||
|
Vector3f normal() const;
|
||||||
|
void calcNormal();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // !HITRECORD_H_
|
#endif // !HITRECORD_H_
|
||||||
|
|
19
src/Light.cc
19
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 Light::setUseCenter(bool useCenter) { this->useCenter = useCenter; }
|
||||||
|
|
||||||
void PointLight::illumination() const {}
|
Vector3f PointLight::illumination(const HitRecord &hit,
|
||||||
|
const vector<Geometry *> &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<Geometry *> &geometries) const {
|
||||||
|
return Vector3f::Zero();
|
||||||
|
}
|
||||||
|
|
12
src/Light.h
12
src/Light.h
|
@ -1,11 +1,14 @@
|
||||||
#ifndef LIGHT_H_
|
#ifndef LIGHT_H_
|
||||||
#define LIGHT_H_
|
#define LIGHT_H_
|
||||||
|
|
||||||
|
#include "HitRecord.h"
|
||||||
#include <Eigen/Core>
|
#include <Eigen/Core>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
using Eigen::Matrix;
|
using Eigen::Matrix;
|
||||||
using Eigen::Matrix4f;
|
using Eigen::Matrix4f;
|
||||||
using Eigen::Vector3f;
|
using Eigen::Vector3f;
|
||||||
|
using std::vector;
|
||||||
|
|
||||||
// Abstract base class for Lights
|
// Abstract base class for Lights
|
||||||
class Light {
|
class Light {
|
||||||
|
@ -13,7 +16,8 @@ public:
|
||||||
enum class Type { Point, Area };
|
enum class Type { Point, Area };
|
||||||
|
|
||||||
virtual ~Light() = default;
|
virtual ~Light() = default;
|
||||||
virtual void illumination() const = 0;
|
virtual Vector3f illumination(const HitRecord &,
|
||||||
|
const vector<Geometry *> &) const = 0;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Light(Type type, const Vector3f &id, const Vector3f &is)
|
Light(Type type, const Vector3f &id, const Vector3f &is)
|
||||||
|
@ -38,7 +42,8 @@ public:
|
||||||
PointLight(const Vector3f &id, const Vector3f &is, Vector3f ¢er)
|
PointLight(const Vector3f &id, const Vector3f &is, Vector3f ¢er)
|
||||||
: Light(Type::Point, id, is), center(center) {}
|
: Light(Type::Point, id, is), center(center) {}
|
||||||
|
|
||||||
virtual void illumination() const override;
|
virtual Vector3f illumination(const HitRecord &,
|
||||||
|
const vector<Geometry *> &) const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Vector3f center;
|
Vector3f center;
|
||||||
|
@ -50,7 +55,8 @@ public:
|
||||||
const Vector3f &p2, const Vector3f &p3, const Vector3f &p4)
|
const Vector3f &p2, const Vector3f &p3, const Vector3f &p4)
|
||||||
: Light(Type::Area, id, is), p1(p1), p2(p2), p3(p3), p4(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<Geometry *> &) const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Vector3f p1, p2, p3, p4;
|
Vector3f p1, p2, p3, p4;
|
||||||
|
|
|
@ -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);
|
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) {
|
void RayTracer::render(Scene *scene) {
|
||||||
int width = scene->getWidth();
|
int width = scene->getWidth();
|
||||||
int height = scene->getHeight();
|
int height = scene->getHeight();
|
||||||
float fov = scene->getFov();
|
|
||||||
Vector3f cameraPos = scene->getCenter();
|
Vector3f cameraPos = scene->getCenter();
|
||||||
Vector3f lookAt = scene->getLookAt();
|
Vector3f lookAt = scene->getLookAt();
|
||||||
Vector3f up = scene->getUpVector();
|
float vpHeight = 2 * tan(scene->getFov() / 180 * M_PI / 2) * lookAt.norm();
|
||||||
float vpHeight = 2 * tan(fov / 180 * M_PI / 2) * lookAt.norm();
|
|
||||||
float vpWidth = vpHeight * width / height;
|
float vpWidth = vpHeight * width / height;
|
||||||
Vector3f vpU = Vector3f(vpWidth, 0, 0);
|
Vector3f vpU = Vector3f(vpWidth, 0, 0);
|
||||||
Vector3f vpV = Vector3f(0, -vpHeight, 0);
|
Vector3f vpV = Vector3f(0, -vpHeight, 0);
|
||||||
|
@ -54,15 +65,13 @@ void RayTracer::render(Scene *scene) {
|
||||||
for (auto g : geometries) {
|
for (auto g : geometries) {
|
||||||
Optional<float> t = g->intersect(ray);
|
Optional<float> t = g->intersect(ray);
|
||||||
if (t.hasValue())
|
if (t.hasValue())
|
||||||
records.push(HitRecord(t.value(), g));
|
records.push(HitRecord(t.value(), ray, g));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!records.empty()) {
|
if (!records.empty()) {
|
||||||
HitRecord hit = records.top();
|
HitRecord hit = records.top();
|
||||||
Vector3f diffuse = hit.geometry()->diffuse();
|
hit.calcNormal();
|
||||||
buffer->r(y * width + x, diffuse.x());
|
calculateColor(hit, buffer, y * width + x);
|
||||||
buffer->g(y * width + x, diffuse.y());
|
|
||||||
buffer->b(y * width + x, diffuse.z());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,10 +20,10 @@ private:
|
||||||
std::vector<Scene *> scenes;
|
std::vector<Scene *> scenes;
|
||||||
std::vector<Light *> lights;
|
std::vector<Light *> lights;
|
||||||
std::vector<Geometry *> geometries;
|
std::vector<Geometry *> geometries;
|
||||||
|
|
||||||
std::vector<Output *> outputs;
|
std::vector<Output *> outputs;
|
||||||
|
|
||||||
void parse();
|
void parse();
|
||||||
|
void calculateColor(const HitRecord &, Output *, int);
|
||||||
void render(Scene *);
|
void render(Scene *);
|
||||||
void output();
|
void output();
|
||||||
};
|
};
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue