Skip to content

Commit

Permalink
Added volume rendering support
Browse files Browse the repository at this point in the history
  • Loading branch information
Pedro Jorquera committed Mar 29, 2024
1 parent 4ab7330 commit 9916aea
Show file tree
Hide file tree
Showing 6 changed files with 124 additions and 3 deletions.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ A simple C++ Raytracer based on "Ray Tracing in One Weekend" book.

## Features

* Raytracing sphere geometries with front face detection.
* Raytracing sphere and quads geometries with front face detection.
* Positionable camera.
* Antialising.
* Simple diffuse material.
Expand All @@ -32,6 +32,7 @@ A simple C++ Raytracer based on "Ray Tracing in One Weekend" book.
* Checked textures.
* Perlin noise based textures.
* Diffuse lights.
* Smoke and volume rendering.

## Building

Expand Down
35 changes: 35 additions & 0 deletions src/constantmedium.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
#include "constantmedium.h"

#include <cmath>

using namespace std;

bool ConstantMedium::intersects(const Ray &ray, const Interval &interval, Hit &hit) const {
Hit hit1, hit2;

if (!_boundary->intersects(ray, Interval::UNIVERSE, hit1)) return false;
if (!_boundary->intersects(ray, Interval(hit1.t() + 0.0001, numeric_limits<double>::infinity()), hit2)) return false;

if (hit1.t() < interval.min()) hit1.setT(interval.min());
if (hit2.t() > interval.max()) hit2.setT(interval.max());

if (hit1.t() >= hit2.t()) return false;

if (hit1.t() < 0.0) hit1.setT(0.0);

auto ray_length = ray.dir().length();
auto distance_inside_boundary = (hit2.t() - hit1.t()) * ray_length;
auto hit_distance = _negInvDensity * log(randomDouble());

if (hit_distance > distance_inside_boundary) return false;

hit.setT(hit1.t() + hit_distance / ray_length);
hit.setPoint(ray.at(hit.t()));

hit.setNormal(Vector(1.0, 0.0, 0.0)); // arbitrary
hit.setFrontFace(true); // also arbitrary
hit.setMaterial(_phaseFunction);

return true;
}

27 changes: 27 additions & 0 deletions src/constantmedium.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#pragma once

#include "intersectable.h"
#include "material.h"

#include <memory>

class ConstantMedium : public Intersectable {

private:

std::shared_ptr<Intersectable> _boundary;
double _negInvDensity;
std::shared_ptr<Material> _phaseFunction;

public:

ConstantMedium(std::shared_ptr<Intersectable> b, double d, std::shared_ptr<Texture> a):
_boundary(b), _negInvDensity(-1.0 / d), _phaseFunction(std::make_shared<Isotropic>(a)) {}

ConstantMedium(std::shared_ptr<Intersectable> b, double d, Color c):
_boundary(b), _negInvDensity(-1.0 / d), _phaseFunction(std::make_shared<Isotropic>(c)) {}

bool intersects(const Ray &ray, const Interval &interval, Hit &hit) const override;
Aabb boundingBox() const override { return _boundary->boundingBox(); }

};
8 changes: 7 additions & 1 deletion src/interval.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,10 @@ class Interval {
double _max;

public:


static const Interval EMPTY;
static const Interval UNIVERSE;

Interval(double min = 0,
double max = std::numeric_limits<double>::infinity()):
_min(min), _max(max) {}
Expand Down Expand Up @@ -61,3 +64,6 @@ inline Interval operator+(const Interval& ival, double displacement) {
inline Interval operator+(double displacement, const Interval& ival) {
return ival + displacement;
}

inline const Interval Interval::EMPTY = Interval(std::numeric_limits<double>::infinity(), -std::numeric_limits<double>::infinity());
inline const Interval Interval::UNIVERSE = Interval(-std::numeric_limits<double>::infinity(), +std::numeric_limits<double>::infinity());
35 changes: 34 additions & 1 deletion src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include "bvh.h"
#include "texture.h"
#include "quad.h"
#include "constantmedium.h"

using namespace std;

Expand Down Expand Up @@ -164,15 +165,47 @@ void cornell_box() {
camera.render(scene, "image.png");
}

void cornell_smoke() {
shared_ptr<Scene> scene = make_shared<Scene>();

auto red = make_shared<Lambertian>(Color(.65, .05, .05));
auto white = make_shared<Lambertian>(Color(.73, .73, .73));
auto green = make_shared<Lambertian>(Color(.12, .45, .15));
auto light = make_shared<DiffuseLight>(Color(7, 7, 7));

scene->add(make_shared<Quad>(Point(555,0,0), Vector(0,555,0), Vector(0,0,555), green));
scene->add(make_shared<Quad>(Point(0,0,0), Vector(0,555,0), Vector(0,0,555), red));
scene->add(make_shared<Quad>(Point(113,554,127), Vector(330,0,0), Vector(0,0,305), light));
scene->add(make_shared<Quad>(Point(0,555,0), Vector(555,0,0), Vector(0,0,555), white));
scene->add(make_shared<Quad>(Point(0,0,0), Vector(555,0,0), Vector(0,0,555), white));
scene->add(make_shared<Quad>(Point(0,0,555), Vector(555,0,0), Vector(0,555,0), white));

shared_ptr<Intersectable> box1 = createBox(Point(0,0,0), Point(165,330,165), white);
box1 = make_shared<RotateY>(box1, 15);
box1 = make_shared<Translate>(box1, Vector(265,0,295));

shared_ptr<Intersectable> box2 = createBox(Point(0,0,0), Point(165,165,165), white);
box2 = make_shared<RotateY>(box2, -18);
box2 = make_shared<Translate>(box2, Vector(130,0,65));

scene->add(make_shared<ConstantMedium>(box1, 0.01, Color(0,0,0)));
scene->add(make_shared<ConstantMedium>(box2, 0.01, Color(1,1,1)));

Camera camera(1.0, 500, 50, 1920, 40.0, Point(278, 278, -800), Point(278, 278, 0), Vector(0.0, 1.0, 0.0), Color(0.0, 0.0, 0.0), 0.0);

camera.render(scene, "image.png");
}

int main() {
switch (7) {
switch (8) {
case 1: randomSpheres(); break;
case 2: twoSpheres(); break;
case 3: earth(); break;
case 4: twoPerlinSpheres(); break;
case 5: quads(); break;
case 6: simple_light(); break;
case 7: cornell_box(); break;
case 8: cornell_smoke(); break;
}
return 0;
}
19 changes: 19 additions & 0 deletions src/material.h
Original file line number Diff line number Diff line change
Expand Up @@ -113,3 +113,22 @@ class DiffuseLight : public Material {
}

};

class Isotropic : public Material {

private:

std::shared_ptr<Texture> _albedo;

public:

Isotropic(Color c): _albedo(std::make_shared<SolidColor>(c)) {}
Isotropic(std::shared_ptr<Texture> a): _albedo(a) {}

bool scatter(const Ray &ray, const Hit &hit, Color &attenuation, Ray &scattered) const override {
scattered = Ray(hit.point(), Vector::randomUnitInUnitSphere(), ray.time());
attenuation = _albedo->color(hit.u(), hit.v(), hit.point());
return true;
}

};

0 comments on commit 9916aea

Please sign in to comment.