mirror of
https://github.com/MorizzG/ray-tracer.git
synced 2025-12-06 04:22:42 +00:00
changed philox to rand
This commit is contained in:
parent
98f0414357
commit
fa90f444ef
17 changed files with 177 additions and 45 deletions
3
.gitmodules
vendored
3
.gitmodules
vendored
|
|
@ -1,6 +1,3 @@
|
|||
[submodule "subprojects/philox"]
|
||||
path = subprojects/philox
|
||||
url = git@github.com:MorizzG/philox
|
||||
[submodule "subprojects/rand"]
|
||||
path = subprojects/rand
|
||||
url = git@github.com:MorizzG/rand
|
||||
|
|
|
|||
21
meson.build
21
meson.build
|
|
@ -12,9 +12,24 @@ add_project_arguments(
|
|||
language : 'cpp'
|
||||
)
|
||||
|
||||
if get_option('native')
|
||||
add_global_arguments(
|
||||
'-march=native',
|
||||
|
||||
philox_proj = subproject('philox', default_options : ['warning_level=0', 'werror=false'])
|
||||
philox_dep = philox_proj.get_variable('philox_dep')
|
||||
language : 'c'
|
||||
)
|
||||
|
||||
add_global_arguments(
|
||||
'-march=native',
|
||||
|
||||
language : 'cpp'
|
||||
)
|
||||
endif
|
||||
|
||||
|
||||
|
||||
rand_proj = subproject('rand', default_options : ['warning_level=0', 'werror=false'])
|
||||
rand_dep = rand_proj.get_variable('rand_dep')
|
||||
|
||||
|
||||
sources = []
|
||||
|
|
@ -22,4 +37,4 @@ subdir('src')
|
|||
|
||||
inc = include_directories('src')
|
||||
|
||||
executable('ray-tracer', sources, include_directories : inc, dependencies : [philox_dep])
|
||||
executable('ray-tracer', sources, include_directories : inc, dependencies : [rand_dep])
|
||||
|
|
|
|||
1
meson.options
Normal file
1
meson.options
Normal file
|
|
@ -0,0 +1 @@
|
|||
option('native', type : 'boolean', value : true)
|
||||
BIN
perf.data
Normal file
BIN
perf.data
Normal file
Binary file not shown.
BIN
perf.data.old
Normal file
BIN
perf.data.old
Normal file
Binary file not shown.
13
src/colour.h
13
src/colour.h
|
|
@ -1,6 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include <cassert>
|
||||
#include <cmath>
|
||||
#include <iomanip>
|
||||
#include <ios>
|
||||
#include <iostream>
|
||||
|
|
@ -43,6 +44,10 @@ class Colour {
|
|||
return *this;
|
||||
}
|
||||
|
||||
constexpr Colour to_gamma2() const {
|
||||
return Colour{std::sqrt(r()), std::sqrt(g()), std::sqrt(b())};
|
||||
}
|
||||
|
||||
std::string to_string() const {
|
||||
std::stringstream ss;
|
||||
|
||||
|
|
@ -74,8 +79,12 @@ constexpr Colour operator+(Colour c1, Colour c2) {
|
|||
return out;
|
||||
}
|
||||
|
||||
inline std::ostream& operator<<(std::ostream& os, Colour colour) {
|
||||
os << FToU8(colour.r()) << ' ' << FToU8(colour.g()) << ' ' << FToU8(colour.b());
|
||||
inline std::ostream& operator<<(std::ostream& os, Colour c) {
|
||||
double r = c.r();
|
||||
double g = c.g();
|
||||
double b = c.b();
|
||||
|
||||
os << FToU8(r) << ' ' << FToU8(g) << ' ' << FToU8(b);
|
||||
|
||||
return os;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -52,18 +52,15 @@ constexpr std::ostream& operator<<(std::ostream& os, const Image& img) {
|
|||
os << "255" << newline;
|
||||
|
||||
for (u32 j = 0; j < img.height(); j++) {
|
||||
std::clog << "\rWriting line " << j << " of " << img.height() << std::flush;
|
||||
|
||||
for (u32 i = 0; i < img.width(); i++) {
|
||||
const Colour col = img[i, j];
|
||||
|
||||
col.CheckValid();
|
||||
|
||||
os << col << newline;
|
||||
// apply gamma 2 transform
|
||||
os << col.to_gamma2() << newline;
|
||||
}
|
||||
}
|
||||
|
||||
std::clog << "\rDone " << newline;
|
||||
|
||||
return os;
|
||||
}
|
||||
|
|
|
|||
11
src/main.cc
11
src/main.cc
|
|
@ -2,10 +2,11 @@
|
|||
#include <memory>
|
||||
|
||||
#include "camera.h"
|
||||
#include "colour.h"
|
||||
#include "image.h"
|
||||
#include "material.h"
|
||||
#include "raytracer.h"
|
||||
#include "renderer.h"
|
||||
#include "renderobject.h"
|
||||
#include "renderobjectlist.h"
|
||||
#include "sphere.h"
|
||||
#include "vec3.h"
|
||||
|
|
@ -15,14 +16,16 @@ int main(int /* argc */, char* /* argv */[]) {
|
|||
|
||||
RenderObjectList world;
|
||||
|
||||
world.Add(std::make_shared<Sphere>(Vec3{0, -100.5, -1}, 100));
|
||||
world.Add(std::make_shared<Sphere>(-Vec3::e_z, 0.5));
|
||||
auto lamb = std::make_shared<Lambertian>(Colour{0.1, 0.4, 0.8});
|
||||
|
||||
world.Add(std::make_unique<Sphere>(Vec3{0, -100.5, -1}, 100, lamb));
|
||||
world.Add(std::make_unique<Sphere>(-Vec3::e_z, 0.5, lamb));
|
||||
|
||||
// camera
|
||||
|
||||
constexpr f64 aspect_ratio = 16.0 / 9.0;
|
||||
|
||||
constexpr u32 image_width = 800;
|
||||
constexpr u32 image_width = 600;
|
||||
constexpr auto image_height = static_cast<u32>(image_width / aspect_ratio);
|
||||
|
||||
// constexpr u32 image_width = 1920;
|
||||
|
|
|
|||
52
src/material.h
Normal file
52
src/material.h
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
#pragma once
|
||||
|
||||
#include <optional>
|
||||
#include <tuple>
|
||||
|
||||
#include "colour.h"
|
||||
#include "rand.h"
|
||||
#include "ray.h"
|
||||
#include "renderobject.h"
|
||||
|
||||
class Material {
|
||||
public:
|
||||
constexpr Material() = default;
|
||||
|
||||
constexpr Material(const Material&) = default;
|
||||
Material& operator=(const Material&) = default;
|
||||
|
||||
constexpr Material(Material&&) = default;
|
||||
Material& operator=(Material&&) = default;
|
||||
|
||||
virtual ~Material() = default;
|
||||
|
||||
RandomGen& rand() const { return rand_; }
|
||||
|
||||
virtual std::optional<std::tuple<Colour, Ray>> Scatter(const Ray& in,
|
||||
const HitRecord& hit_record) const = 0;
|
||||
|
||||
private:
|
||||
mutable RandomGen rand_{};
|
||||
};
|
||||
|
||||
class Lambertian : public Material {
|
||||
public:
|
||||
constexpr explicit Lambertian(Colour albedo) : albedo_{albedo} {}
|
||||
|
||||
std::optional<std::tuple<Colour, Ray>> Scatter(const Ray& /* in */,
|
||||
const HitRecord& hit_record) const override {
|
||||
auto scatter_dir = hit_record.normal + rand().GenOnUnitSphere();
|
||||
|
||||
// TODO: enable
|
||||
/* if (scatter_dir.almost_zero()) {
|
||||
scatter_dir = hit_record.normal;
|
||||
} */
|
||||
|
||||
Ray scattered{hit_record.p, scatter_dir};
|
||||
|
||||
return std::make_tuple(albedo_, scattered);
|
||||
}
|
||||
|
||||
private:
|
||||
Colour albedo_;
|
||||
};
|
||||
|
|
@ -10,6 +10,8 @@ using u64 = uint64_t;
|
|||
using f64 = double;
|
||||
|
||||
constexpr f64 kInf = std::numeric_limits<f64>::infinity();
|
||||
constexpr f64 kNan = std::numeric_limits<f64>::signaling_NaN();
|
||||
|
||||
constexpr f64 kPi = std::numbers::pi_v<f64>;
|
||||
|
||||
constexpr char newline = '\n';
|
||||
|
|
|
|||
|
|
@ -1,11 +1,15 @@
|
|||
#pragma once
|
||||
|
||||
#include <array>
|
||||
#include <cassert>
|
||||
#include <iostream>
|
||||
#include <thread>
|
||||
|
||||
#include "camera.h"
|
||||
#include "colour.h"
|
||||
#include "image.h"
|
||||
#include "interval.h"
|
||||
#include "material.h"
|
||||
#include "rand.h"
|
||||
#include "ray.h"
|
||||
#include "raytracer.h"
|
||||
|
|
@ -14,28 +18,52 @@
|
|||
|
||||
class Renderer {
|
||||
public:
|
||||
constexpr explicit Renderer(Camera camera, u32 samples_per_pixel = 10)
|
||||
: camera_{camera}, samples_per_pixel_{samples_per_pixel} {}
|
||||
constexpr explicit Renderer(Camera camera, u32 samples_per_pixel = 100, u32 max_bounces = 50)
|
||||
: camera_{camera}, samples_per_pixel_{samples_per_pixel}, max_bounces_{max_bounces} {}
|
||||
|
||||
constexpr Image Render(const RenderObject& world) {
|
||||
constexpr u32& samples_per_pixel() { return samples_per_pixel_; }
|
||||
constexpr u32 samples_per_pixel() const { return samples_per_pixel_; }
|
||||
|
||||
constexpr u32& max_bounces() { return max_bounces_; }
|
||||
constexpr u32 max_bounces() const { return max_bounces_; }
|
||||
|
||||
Image Render(const RenderObject& world) {
|
||||
Image img{camera_.image_width(), camera_.image_height()};
|
||||
|
||||
for (u32 j = 0; j < img.height(); j++) {
|
||||
std::clog << "\rWriting line " << j << " of " << img.height() << std::flush;
|
||||
constexpr u32 kNumThreads = 4;
|
||||
|
||||
for (u32 i = 0; i < img.width(); i++) {
|
||||
Colour colour_sum{0.0, 0.0, 0.0};
|
||||
auto render_thread = [this, &world, &img](u32 thread) {
|
||||
for (u32 j = thread; j < img.height(); j += kNumThreads) {
|
||||
std::clog << "\rWriting line " << j << " of " << img.height() << std::flush;
|
||||
|
||||
for (u32 num_sample = 0; num_sample < samples_per_pixel_; num_sample++) {
|
||||
auto ray = SampleRay(i, j);
|
||||
for (u32 i = 0; i < img.width(); i++) {
|
||||
Colour colour_sum{0.0, 0.0, 0.0};
|
||||
|
||||
colour_sum += Cast(ray, world);
|
||||
for (u32 num_sample = 0; num_sample < samples_per_pixel_; num_sample++) {
|
||||
auto ray = SampleRay(i, j);
|
||||
|
||||
colour_sum += Cast(ray, world, max_bounces_);
|
||||
}
|
||||
|
||||
img[i, j] = colour_sum / samples_per_pixel_;
|
||||
}
|
||||
|
||||
img[i, j] = colour_sum / samples_per_pixel_;
|
||||
}
|
||||
};
|
||||
|
||||
// render_thread(0);
|
||||
|
||||
std::array<std::thread, kNumThreads> render_threads;
|
||||
|
||||
for (u32 i = 0; i < kNumThreads; i++) {
|
||||
render_threads[i] = std::thread{render_thread, i};
|
||||
}
|
||||
|
||||
for (auto& t : render_threads) {
|
||||
t.join();
|
||||
}
|
||||
|
||||
std::clog << "\rDone " << newline;
|
||||
|
||||
return img;
|
||||
}
|
||||
|
||||
|
|
@ -53,22 +81,29 @@ class Renderer {
|
|||
return Ray{camera_.centre(), ray_direction};
|
||||
}
|
||||
|
||||
constexpr Colour Cast(const Ray& ray, const RenderObject& world) {
|
||||
auto hit_record = world.hit(ray, Interval::kPositive);
|
||||
constexpr Colour Cast(const Ray& ray, const RenderObject& world, u32 bounces) {
|
||||
auto hit_record = world.hit(ray, Interval{0.001, kInf});
|
||||
|
||||
if (hit_record.has_value()) {
|
||||
Vec3 normal = hit_record->normal;
|
||||
|
||||
if (!hit_record->front_face) {
|
||||
if (!hit_record->front_face || bounces == 0) {
|
||||
return Colour::kBlack;
|
||||
}
|
||||
|
||||
/* Vec3 normal = hit_record->normal;
|
||||
|
||||
Vec3 new_origin = hit_record->p;
|
||||
Vec3 new_direction = rand_.GenOnHemisphere(normal);
|
||||
|
||||
Ray new_ray{new_origin, new_direction};
|
||||
// Vec3 new_direction = rand_.GenOnHemisphere(normal);
|
||||
Vec3 new_direction = normal + rand_.GenOnUnitSphere();
|
||||
|
||||
return 0.5 * Cast(new_ray, world);
|
||||
Ray new_ray{new_origin, new_direction}; */
|
||||
|
||||
auto res = hit_record->mat->Scatter(ray, hit_record.value());
|
||||
|
||||
auto [albedo, out_ray] = res.value();
|
||||
|
||||
assert(bounces > 0);
|
||||
return 0.5 * Cast(out_ray, world, bounces - 1);
|
||||
}
|
||||
|
||||
auto unit_dir = ray.direction().normed();
|
||||
|
|
@ -83,4 +118,5 @@ class Renderer {
|
|||
RandomGen rand_{};
|
||||
|
||||
u32 samples_per_pixel_;
|
||||
u32 max_bounces_;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -5,12 +5,17 @@
|
|||
|
||||
#include "interval.h"
|
||||
#include "ray.h"
|
||||
#include "raytracer.h"
|
||||
#include "vec3.h"
|
||||
|
||||
class Material;
|
||||
|
||||
struct HitRecord {
|
||||
Point3 p;
|
||||
Vec3 normal;
|
||||
f64 t = 0.0;
|
||||
const Material* mat = nullptr;
|
||||
|
||||
f64 t = kNan;
|
||||
bool front_face = true;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -1,18 +1,21 @@
|
|||
#pragma once
|
||||
|
||||
#include <initializer_list>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "interval.h"
|
||||
#include "ray.h"
|
||||
#include "raytracer.h"
|
||||
#include "renderobject.h"
|
||||
|
||||
class RenderObjectList : public RenderObject {
|
||||
public:
|
||||
constexpr RenderObjectList() = default;
|
||||
// explicit RenderObjectList(const SharedRenderObject& obj) { Append(obj); }
|
||||
RenderObjectList(std::initializer_list<SharedRenderObject> objs) : objs_{objs} {}
|
||||
// RenderObjectList(std::initializer_list<RenderObject> objs) : objs_{objs} {}
|
||||
|
||||
constexpr auto begin() { return objs_.begin(); }
|
||||
constexpr auto end() { return objs_.end(); }
|
||||
|
|
@ -20,7 +23,7 @@ class RenderObjectList : public RenderObject {
|
|||
constexpr auto begin() const { return objs_.begin(); }
|
||||
constexpr auto end() const { return objs_.end(); }
|
||||
|
||||
void Add(const SharedRenderObject& obj) { objs_.push_back(obj); }
|
||||
void Add(std::unique_ptr<RenderObject> obj) { objs_.emplace_back(std::move(obj)); }
|
||||
|
||||
void Clear() { objs_.clear(); }
|
||||
|
||||
|
|
@ -43,5 +46,5 @@ class RenderObjectList : public RenderObject {
|
|||
}
|
||||
|
||||
private:
|
||||
std::vector<SharedRenderObject> objs_;
|
||||
std::vector<std::unique_ptr<RenderObject>> objs_;
|
||||
};
|
||||
|
|
|
|||
11
src/sphere.h
11
src/sphere.h
|
|
@ -2,9 +2,11 @@
|
|||
|
||||
#include <cassert>
|
||||
#include <cmath>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
|
||||
#include "interval.h"
|
||||
#include "material.h"
|
||||
#include "ray.h"
|
||||
#include "raytracer.h"
|
||||
#include "renderobject.h"
|
||||
|
|
@ -13,7 +15,9 @@
|
|||
class Sphere : public RenderObject {
|
||||
public:
|
||||
constexpr Sphere() = default;
|
||||
constexpr Sphere(Point3 centre, f64 radius) : centre_{centre}, radius_{radius} {
|
||||
|
||||
Sphere(Point3 centre, f64 radius, const std::shared_ptr<Material>& mat)
|
||||
: centre_{centre}, radius_{radius}, mat_{mat} {
|
||||
assert(radius >= 0);
|
||||
}
|
||||
|
||||
|
|
@ -21,7 +25,7 @@ class Sphere : public RenderObject {
|
|||
constexpr f64 radius() const { return radius_; }
|
||||
|
||||
std::optional<HitRecord> hit(const Ray& ray, Interval ts) const override {
|
||||
HitRecord hit_record;
|
||||
HitRecord hit_record{};
|
||||
|
||||
Vec3 oc = ray.origin() - centre_;
|
||||
|
||||
|
|
@ -66,6 +70,7 @@ class Sphere : public RenderObject {
|
|||
|
||||
hit_record.t = t;
|
||||
hit_record.p = ray.At(t);
|
||||
hit_record.mat = mat_.get();
|
||||
|
||||
if (hit_record.front_face) {
|
||||
hit_record.normal = (hit_record.p - centre_) / radius_;
|
||||
|
|
@ -79,4 +84,6 @@ class Sphere : public RenderObject {
|
|||
private:
|
||||
Point3 centre_{};
|
||||
f64 radius_ = 0.0;
|
||||
|
||||
std::shared_ptr<Material> mat_;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -59,6 +59,12 @@ class Vec3 {
|
|||
return *this;
|
||||
}
|
||||
|
||||
constexpr bool almost_zero() const {
|
||||
f64 eps = 1e-8;
|
||||
|
||||
return std::fabs(x()) < eps && std::fabs(y()) < eps && std::fabs(z()) < eps;
|
||||
}
|
||||
|
||||
constexpr f64 squared() const { return x() * x() + y() * y() + z() * z(); }
|
||||
|
||||
constexpr f64 norm() const { return std::sqrt(squared()); }
|
||||
|
|
|
|||
|
|
@ -1 +0,0 @@
|
|||
Subproject commit cf69284bd2d82b279c34fb1cf90543fd04b3a038
|
||||
|
|
@ -1 +1 @@
|
|||
Subproject commit 4d7680624857241aca166f58b957712b0583fa05
|
||||
Subproject commit 8043050d3c871d241a1274be81bfaf1894f5edb2
|
||||
Loading…
Add table
Add a link
Reference in a new issue