add dummy global illum

This commit is contained in:
Shuo Feng 2024-03-20 01:07:39 -04:00
parent bb70580274
commit 5cf306cbbe
Signed by: sfeng
GPG key ID: 1E83AE6CD1C037B1
4 changed files with 84 additions and 22 deletions

View file

@ -20,6 +20,8 @@ Vector3f Light::is() const { return is_; }
bool Light::isUse() const { return use; }
Vector3f PointLight::getCenter() const { return center; }
Vector3f PointLight::illumination(const HitRecord &hit,
const vector<Geometry *> &geometries) const {
Vector3f shadingPoint = hit.point();
@ -46,6 +48,10 @@ Vector3f PointLight::illumination(const HitRecord &hit,
return specular_ + ambient_ + diffuse_;
}
Vector3f AreaLight::getCenter() const {
return p1 + (p4 - p1) / 2 + (p2 - p1) / 2;
}
Vector3f AreaLight::illumination(const HitRecord &hit,
const vector<Geometry *> &geometries) const {
Vector3f u = p4 - p1;
@ -54,7 +60,7 @@ Vector3f AreaLight::illumination(const HitRecord &hit,
Vector3f color = Vector3f::Zero();
if (useCenter) {
color += PointLight(*this, p1 + (u + v) / 2).illumination(hit, geometries);
color += PointLight(*this, getCenter()).illumination(hit, geometries);
} else {
for (int y = 0; y < gridSize; ++y)
for (int x = 0; x < gridSize; ++x) {

View file

@ -18,6 +18,7 @@ public:
virtual ~Light() = default;
virtual Vector3f illumination(const HitRecord &,
const vector<Geometry *> &) const = 0;
virtual Vector3f getCenter() const = 0;
protected:
Light(Type type, const Vector3f &id, const Vector3f &is)
@ -36,6 +37,7 @@ public:
void setGridSize(unsigned int);
void setUseCenter(bool);
void setIsUse(bool);
Type type() const;
Vector3f id() const;
Vector3f is() const;
bool isUse() const;
@ -52,6 +54,9 @@ public:
private:
Vector3f p1, p2, p3, p4;
public:
Vector3f getCenter() const override;
};
class PointLight : public Light {
@ -67,6 +72,9 @@ public:
private:
Vector3f center;
public:
Vector3f getCenter() const override;
};
#endif // !LIGHT_H_

View file

@ -1,5 +1,6 @@
#include "RayTracer.h"
#include "HitRecord.h"
#include "Light.h"
#include "Output.h"
#include "Parser.h"
#include "Progress.h"
@ -7,6 +8,7 @@
#include "Ray.h"
#include <Eigen/Core>
#include <algorithm>
#include <cmath>
#include <iostream>
#include <queue>
@ -89,26 +91,22 @@ void RayTracer::render() {
for (int j = 0; j < gridHeight; ++j)
for (int i = 0; i < gridWidth; ++i) {
Ray ray = getRay(x, y, i, j);
for (int rayNum = 0; rayNum < raysPerPixel; ++rayNum) {
utils::Optional<Vector3f> result = trace(ray);
if (result.hasValue()) {
accumulate += result.value() * raysPerPixel;
success += raysPerPixel;
accumulate += result.value();
success++;
}
}
}
if (!success)
color = accumulate / success;
} else {
Ray ray = getRay(x, y);
priority_queue<HitRecord> records;
for (auto g : geometries) {
Optional<float> t = g->intersect(ray);
if (t.hasValue())
records.push(HitRecord(t.value(), ray, g));
}
Optional<HitRecord> hitRecord = getHitRecord(ray);
if (!records.empty()) {
HitRecord hit = records.top();
hit.calcNormal();
if (hitRecord.hasValue()) {
HitRecord hit = hitRecord.value();
color = calculateColor(hit, y * width + x);
}
}
@ -130,6 +128,33 @@ Vector3f RayTracer::calculateColor(const HitRecord &hit, int i) const {
return result;
}
/**
* Find the nearest geometry to intersect
*/
Optional<HitRecord> RayTracer::getHitRecord(Ray r) const {
priority_queue<HitRecord> records;
for (auto g : geometries) {
Optional<float> t = g->intersect(r);
if (t.hasValue())
records.push(HitRecord(t.value(), r, g));
}
if (!records.empty()) {
HitRecord result = records.top();
result.calcNormal();
return Optional<HitRecord>(result);
}
return Optional<HitRecord>::nullopt;
}
Light *RayTracer::singleLightSource() const {
for (auto light : lights)
if (light->isUse())
return light;
return nullptr;
}
// helper functions
Ray getRay(int x, int y) {
using namespace camera;
@ -151,21 +176,39 @@ void writeColor(int i, const Vector3f &color) {
Output::current->b(i, color.z());
}
Vector3f trace(Ray r, int bounce, float prob) {
Vector3f RayTracer::trace(HitRecord hit, int bounce, float prob) const {
float dice = utils::Random::get();
if (bounce && (dice > prob)) {
return Vector3f(1, 0, 1).array() * trace(r, bounce - 1, prob).array();
return Vector3f(1, 0, 1).array() * trace(hit, bounce - 1, prob).array();
} else {
Light *light = singleLightSource();
Vector3f point = hit.point();
Vector3f direction = (light->getCenter() - point).normalized();
Ray shadowRay(point, direction);
Geometry *geometry = hit.geometry();
for (auto g : geometries)
if (g != geometry && g->intersect(shadowRay).hasValue() &&
g->type() == Geometry::Type::SPHERE)
return Vector3f::Zero();
return geometry->cd().array() * light->id().array() *
std::max(0.0f, hit.normal().dot(direction));
}
return Vector3f(1, 1, 1);
}
utils::Optional<Vector3f> trace(Ray r) {
Vector3f color =
trace(r, Scene::current->maxBounce(), Scene::current->probTerminate());
utils::Optional<Vector3f> RayTracer::trace(Ray r) const {
Optional<HitRecord> hitRecord = getHitRecord(r);
if (hitRecord.hasValue()) {
Vector3f color = trace(hitRecord.value(), Scene::current->maxBounce(),
Scene::current->probTerminate());
if (color != Vector3f::Zero())
return utils::Optional<Vector3f>(color);
}
return utils::Optional<Vector3f>::nullopt;
}

View file

@ -3,6 +3,7 @@
#include "../external/json.hpp"
#include "Geometry.h"
#include "HitRecord.h"
#include "Light.h"
#include "Output.h"
#include "Scene.h"
@ -22,8 +23,12 @@ private:
std::vector<Output *> outputs;
void parse();
Vector3f calculateColor(const HitRecord &, int) const;
void render();
Optional<HitRecord> getHitRecord(Ray) const;
Vector3f calculateColor(const HitRecord &, int) const;
Light *singleLightSource() const;
Optional<Vector3f> trace(Ray) const;
Vector3f trace(HitRecord, int, float) const;
};
#endif // !RAY_TRACER_H_