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::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<float> Sphere::intersect(const Ray &r) const {
|
|||
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,
|
||||
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<float> 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<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)
|
||||
: Optional<float>::nullopt;
|
||||
}
|
||||
|
||||
Vector3f Rectangle::getNormal(const Vector3f &p) const { return normal; }
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include "Ray.h"
|
||||
|
||||
#include <Eigen/Core>
|
||||
#include <Eigen/Dense>
|
||||
|
||||
using Eigen::Matrix;
|
||||
using Eigen::Matrix4f;
|
||||
|
@ -18,6 +19,7 @@ public:
|
|||
|
||||
virtual ~Geometry() = default;
|
||||
virtual Optional<float> 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<float> 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<float> intersect(const Ray &) const override;
|
||||
Vector3f getNormal(const Vector3f &) const override;
|
||||
|
||||
private:
|
||||
Vector3f p1, p2, p3, p4;
|
||||
Vector3f normal;
|
||||
};
|
||||
|
||||
#endif // !GEOMETRY_H_
|
||||
|
|
|
@ -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()); }
|
||||
|
|
|
@ -2,18 +2,27 @@
|
|||
#define HITRECORD_H_
|
||||
|
||||
#include "Geometry.h"
|
||||
#include "Ray.h"
|
||||
#include <Eigen/Core>
|
||||
|
||||
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_
|
||||
|
|
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 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_
|
||||
#define LIGHT_H_
|
||||
|
||||
#include "HitRecord.h"
|
||||
#include <Eigen/Core>
|
||||
#include <vector>
|
||||
|
||||
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<Geometry *> &) 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<Geometry *> &) 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<Geometry *> &) const override;
|
||||
|
||||
private:
|
||||
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);
|
||||
}
|
||||
|
||||
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<float> 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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -20,10 +20,10 @@ private:
|
|||
std::vector<Scene *> scenes;
|
||||
std::vector<Light *> lights;
|
||||
std::vector<Geometry *> geometries;
|
||||
|
||||
std::vector<Output *> outputs;
|
||||
|
||||
void parse();
|
||||
void calculateColor(const HitRecord &, Output *, int);
|
||||
void render(Scene *);
|
||||
void output();
|
||||
};
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue