mirror of
https://github.com/vonhyou/ray-tracer-comp371.git
synced 2025-06-07 23:12:00 +00:00
finish global illumination
This commit is contained in:
parent
e59c6dbea4
commit
a63aedc323
5 changed files with 41 additions and 20 deletions
|
@ -40,6 +40,8 @@ Vector3f Sphere::normal(const Vector3f &p) const {
|
||||||
return (p - center).normalized();
|
return (p - center).normalized();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Vector3f Sphere::sample() const { return center + Vector3f(radius, 0, 0); }
|
||||||
|
|
||||||
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);
|
||||||
|
@ -67,3 +69,5 @@ Optional<float> Rectangle::intersect(const Ray &r) const {
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector3f Rectangle::normal(const Vector3f &p) const { return normal_; }
|
Vector3f Rectangle::normal(const Vector3f &p) const { return normal_; }
|
||||||
|
|
||||||
|
Vector3f Rectangle::sample() const { return p1; }
|
||||||
|
|
|
@ -20,6 +20,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 normal(const Vector3f &) const = 0;
|
virtual Vector3f normal(const Vector3f &) const = 0;
|
||||||
|
virtual Vector3f sample() 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,
|
||||||
|
@ -54,6 +55,7 @@ public:
|
||||||
|
|
||||||
Optional<float> intersect(const Ray &) const override;
|
Optional<float> intersect(const Ray &) const override;
|
||||||
Vector3f normal(const Vector3f &) const override;
|
Vector3f normal(const Vector3f &) const override;
|
||||||
|
Vector3f sample() const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
float radius;
|
float radius;
|
||||||
|
@ -70,6 +72,7 @@ public:
|
||||||
|
|
||||||
Optional<float> intersect(const Ray &) const override;
|
Optional<float> intersect(const Ray &) const override;
|
||||||
Vector3f normal(const Vector3f &) const override;
|
Vector3f normal(const Vector3f &) const override;
|
||||||
|
Vector3f sample() const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Vector3f p1, p2, p3, p4;
|
Vector3f p1, p2, p3, p4;
|
||||||
|
|
10
src/Light.cc
10
src/Light.cc
|
@ -22,6 +22,10 @@ bool Light::isUse() const { return use; }
|
||||||
|
|
||||||
Vector3f PointLight::getCenter() const { return center; }
|
Vector3f PointLight::getCenter() const { return center; }
|
||||||
|
|
||||||
|
bool lightOnSurface(Vector3f center, Geometry *g) {
|
||||||
|
return (g->sample() - center).dot(g->normal(center)) < 1e-5;
|
||||||
|
}
|
||||||
|
|
||||||
Vector3f PointLight::illumination(const HitRecord &hit,
|
Vector3f PointLight::illumination(const HitRecord &hit,
|
||||||
const vector<Geometry *> &geometries) const {
|
const vector<Geometry *> &geometries) const {
|
||||||
Vector3f shadingPoint = hit.point();
|
Vector3f shadingPoint = hit.point();
|
||||||
|
@ -30,9 +34,9 @@ Vector3f PointLight::illumination(const HitRecord &hit,
|
||||||
Ray shadowRay(shadingPoint, rayDirection);
|
Ray shadowRay(shadingPoint, rayDirection);
|
||||||
|
|
||||||
for (auto g : geometries)
|
for (auto g : geometries)
|
||||||
if (g != geometry && g->intersect(shadowRay).hasValue() &&
|
if (g != geometry && g->intersect(shadowRay).hasValue())
|
||||||
g->type() == Geometry::Type::SPHERE)
|
if (g->type() == Geometry::Type::SPHERE || !lightOnSurface(center, g))
|
||||||
return Vector3f::Zero();
|
return Vector3f::Zero();
|
||||||
|
|
||||||
Vector3f ambient_ =
|
Vector3f ambient_ =
|
||||||
geometry->ka() * geometry->ca().array() * Scene::current->ai().array();
|
geometry->ka() * geometry->ca().array() * Scene::current->ai().array();
|
||||||
|
|
|
@ -67,6 +67,11 @@ void RayTracer::parse() {
|
||||||
lights.push_back(Parser::getLight(*i));
|
lights.push_back(Parser::getLight(*i));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Vector3f gammaCorrection(Vector3f color, float gammaInv) {
|
||||||
|
return Vector3f(std::pow(color.x(), gammaInv), std::pow(color.y(), gammaInv),
|
||||||
|
std::pow(color.z(), gammaInv));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Render the current scene
|
* Render the current scene
|
||||||
*
|
*
|
||||||
|
@ -109,7 +114,7 @@ void RayTracer::render() {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (success)
|
if (success)
|
||||||
color = accumulate / success;
|
color = gammaCorrection(accumulate / success, 1.0f / 2.1f);
|
||||||
} else {
|
} else {
|
||||||
Ray ray = getRay(x, y);
|
Ray ray = getRay(x, y);
|
||||||
Optional<HitRecord> hitRecord = getHitRecord(ray);
|
Optional<HitRecord> hitRecord = getHitRecord(ray);
|
||||||
|
@ -141,15 +146,12 @@ Vector3f RayTracer::calculateColor(const HitRecord &hit, int i) const {
|
||||||
/**
|
/**
|
||||||
* Find the nearest geometry to intersect
|
* Find the nearest geometry to intersect
|
||||||
*/
|
*/
|
||||||
Optional<HitRecord> RayTracer::getHitRecord(Ray r, const Geometry *self,
|
Optional<HitRecord> RayTracer::getHitRecord(Ray r, const Geometry *self) const {
|
||||||
bool notRectangle) const {
|
|
||||||
priority_queue<HitRecord> records;
|
priority_queue<HitRecord> records;
|
||||||
for (auto g : geometries) {
|
for (auto g : geometries) {
|
||||||
Optional<float> t = g->intersect(r);
|
Optional<float> t = g->intersect(r);
|
||||||
if (t.hasValue() && g != self)
|
if (t.hasValue() && g != self)
|
||||||
if (!notRectangle ||
|
records.push(HitRecord(t.value(), r, g));
|
||||||
notRectangle && g->type() != Geometry::Type::RECTANGLE)
|
|
||||||
records.push(HitRecord(t.value(), r, g));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!records.empty()) {
|
if (!records.empty()) {
|
||||||
|
@ -161,12 +163,8 @@ Optional<HitRecord> RayTracer::getHitRecord(Ray r, const Geometry *self,
|
||||||
return Optional<HitRecord>::nullopt;
|
return Optional<HitRecord>::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
Optional<HitRecord> RayTracer::getHitRecord(Ray r, const Geometry *g) const {
|
|
||||||
return getHitRecord(r, g, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
Optional<HitRecord> RayTracer::getHitRecord(Ray r) const {
|
Optional<HitRecord> RayTracer::getHitRecord(Ray r) const {
|
||||||
return getHitRecord(r, nullptr, false);
|
return getHitRecord(r, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
Light *RayTracer::singleLightSource() const {
|
Light *RayTracer::singleLightSource() const {
|
||||||
|
@ -199,8 +197,8 @@ void writeColor(int i, const Vector3f &color) {
|
||||||
|
|
||||||
Vector3f getRandomDirection() {
|
Vector3f getRandomDirection() {
|
||||||
RETRY_RANDOM:
|
RETRY_RANDOM:
|
||||||
float x = (float)rand() / RAND_MAX;
|
float x = ((float)rand() / RAND_MAX) * 2 - 1;
|
||||||
float y = (float)rand() / RAND_MAX;
|
float y = ((float)rand() / RAND_MAX) * 2 - 1;
|
||||||
if (x * x + y * y > 1)
|
if (x * x + y * y > 1)
|
||||||
goto RETRY_RANDOM;
|
goto RETRY_RANDOM;
|
||||||
|
|
||||||
|
@ -222,6 +220,17 @@ Vector3f getGlobalRandDirection(Vector3f normal) {
|
||||||
return local2World * getRandomDirection();
|
return local2World * getRandomDirection();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool lightOnSurface(HitRecord hit, const Light *l) {
|
||||||
|
Vector3f center = l->getCenter();
|
||||||
|
Geometry *g = hit.geometry();
|
||||||
|
Geometry::Type type = g->type();
|
||||||
|
if (type == Geometry::Type::RECTANGLE) {
|
||||||
|
return (g->sample() - center).dot(g->normal(center)) < 1e-5;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
Vector3f RayTracer::trace(HitRecord hit, int bounce, float prob) const {
|
Vector3f RayTracer::trace(HitRecord hit, int bounce, float prob) const {
|
||||||
RETRY_TRACING:
|
RETRY_TRACING:
|
||||||
bool finish = !bounce || ((float)rand() / RAND_MAX < prob);
|
bool finish = !bounce || ((float)rand() / RAND_MAX < prob);
|
||||||
|
@ -238,14 +247,16 @@ RETRY_TRACING:
|
||||||
direction.normalize();
|
direction.normalize();
|
||||||
Ray ray(point + hit.normal() * 1e-6, direction);
|
Ray ray(point + hit.normal() * 1e-6, direction);
|
||||||
|
|
||||||
Optional<HitRecord> hitRecord = getHitRecord(ray, geometry, finish);
|
Optional<HitRecord> hitRecord = getHitRecord(ray, geometry);
|
||||||
Vector3f traceColor = Vector3f::Zero();
|
Vector3f traceColor = Vector3f::Zero();
|
||||||
if (!finish && hitRecord.hasValue())
|
if (!finish && hitRecord.hasValue())
|
||||||
traceColor = trace(hitRecord.value(), bounce - 1, prob);
|
traceColor = trace(hitRecord.value(), bounce - 1, prob);
|
||||||
else if (!finish && !hitRecord.hasValue())
|
else if (!finish && !hitRecord.hasValue())
|
||||||
goto RETRY_TRACING;
|
goto RETRY_TRACING;
|
||||||
else if (finish && !hitRecord.hasValue())
|
else if (finish)
|
||||||
traceColor = light->id();
|
if (!hitRecord.hasValue() ||
|
||||||
|
(hitRecord.hasValue() && lightOnSurface(hitRecord.value(), light)))
|
||||||
|
traceColor = light->id();
|
||||||
|
|
||||||
return traceColor.array() * geometry->cd().array() *
|
return traceColor.array() * geometry->cd().array() *
|
||||||
std::max(0.0f, hit.normal().dot(direction));
|
std::max(0.0f, hit.normal().dot(direction));
|
||||||
|
|
|
@ -24,7 +24,6 @@ private:
|
||||||
|
|
||||||
void parse();
|
void parse();
|
||||||
void render();
|
void render();
|
||||||
Optional<HitRecord> getHitRecord(Ray, const Geometry *, bool) const;
|
|
||||||
Optional<HitRecord> getHitRecord(Ray, const Geometry *) const;
|
Optional<HitRecord> getHitRecord(Ray, const Geometry *) const;
|
||||||
Optional<HitRecord> getHitRecord(Ray) const;
|
Optional<HitRecord> getHitRecord(Ray) const;
|
||||||
Vector3f calculateColor(const HitRecord &, int) const;
|
Vector3f calculateColor(const HitRecord &, int) const;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue