mirror of
https://github.com/MorizzG/ray-tracer.git
synced 2025-12-06 04:22:42 +00:00
added Materials
Lambertian: scatter ray randomly with absorption Metal: reflect ray with absorption
This commit is contained in:
parent
aaae4a8196
commit
79869930cf
7 changed files with 92 additions and 38 deletions
|
|
@ -27,7 +27,6 @@ if get_option('native')
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
rand_proj = subproject('rand', default_options : ['warning_level=0', 'werror=false'])
|
rand_proj = subproject('rand', default_options : ['warning_level=0', 'werror=false'])
|
||||||
rand_dep = rand_proj.get_variable('rand_dep')
|
rand_dep = rand_proj.get_variable('rand_dep')
|
||||||
|
|
||||||
|
|
|
||||||
16
src/colour.h
16
src/colour.h
|
|
@ -44,6 +44,14 @@ class Colour {
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
constexpr Colour& operator*=(const Colour& c) {
|
||||||
|
r_ *= c.r();
|
||||||
|
g_ *= c.g();
|
||||||
|
b_ *= c.b();
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
constexpr Colour to_gamma2() const {
|
constexpr Colour to_gamma2() const {
|
||||||
return Colour{std::sqrt(r()), std::sqrt(g()), std::sqrt(b())};
|
return Colour{std::sqrt(r()), std::sqrt(g()), std::sqrt(b())};
|
||||||
}
|
}
|
||||||
|
|
@ -79,6 +87,14 @@ constexpr Colour operator+(Colour c1, Colour c2) {
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
constexpr Colour operator*(Colour c1, Colour c2) {
|
||||||
|
Colour out{c1};
|
||||||
|
|
||||||
|
out *= c2;
|
||||||
|
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
inline std::ostream& operator<<(std::ostream& os, Colour c) {
|
inline std::ostream& operator<<(std::ostream& os, Colour c) {
|
||||||
double r = c.r();
|
double r = c.r();
|
||||||
double g = c.g();
|
double g = c.g();
|
||||||
|
|
|
||||||
21
src/main.cc
21
src/main.cc
|
|
@ -1,5 +1,6 @@
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
#include "camera.h"
|
#include "camera.h"
|
||||||
#include "colour.h"
|
#include "colour.h"
|
||||||
|
|
@ -16,10 +17,24 @@ int main(int /* argc */, char* /* argv */[]) {
|
||||||
|
|
||||||
RenderObjectList world;
|
RenderObjectList world;
|
||||||
|
|
||||||
auto lamb = std::make_shared<Lambertian>(Colour{0.1, 0.4, 0.8});
|
/* auto lamb = std::make_shared<Lambertian>(Colour{0.7, 0.0, 0.5});
|
||||||
|
auto metal = std::make_shared<Metal>(Colour{0.3, 0.3, 0.3});
|
||||||
|
|
||||||
world.Add(std::make_unique<Sphere>(Vec3{0, -100.5, -1}, 100, lamb));
|
auto ground = std::make_unique<Sphere>(Point3{0, -100.5, -1}, 100, metal);
|
||||||
world.Add(std::make_unique<Sphere>(-Vec3::e_z, 0.5, lamb));
|
auto sphere = std::make_unique<Sphere>(-Vec3::e_z, 0.5, lamb);
|
||||||
|
|
||||||
|
world.Add(std::move(ground));
|
||||||
|
world.Add(std::move(sphere)); */
|
||||||
|
|
||||||
|
auto material_ground = std::make_shared<Lambertian>(Colour(0.8, 0.8, 0.0));
|
||||||
|
auto material_center = std::make_shared<Lambertian>(Colour(0.7, 0.3, 0.3));
|
||||||
|
auto material_left = std::make_shared<Metal>(Colour(0.8, 0.8, 0.8), 0.05);
|
||||||
|
auto material_right = std::make_shared<Metal>(Colour(0.8, 0.5, 0.4), 0.5);
|
||||||
|
|
||||||
|
world.Add(std::make_unique<Sphere>(Point3(0.0, -100.5, -1.0), 100.0, material_ground));
|
||||||
|
world.Add(std::make_unique<Sphere>(Point3(0.0, 0.0, -1.0), 0.5, material_center));
|
||||||
|
world.Add(std::make_unique<Sphere>(Point3(-1.0, 0.0, -1.0), 0.5, material_left));
|
||||||
|
world.Add(std::make_unique<Sphere>(Point3(1.0, 0.0, -1.0), 0.5, material_right));
|
||||||
|
|
||||||
// camera
|
// camera
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,13 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <cassert>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
#include <tuple>
|
#include <tuple>
|
||||||
|
|
||||||
#include "colour.h"
|
#include "colour.h"
|
||||||
#include "rand.h"
|
#include "rand.h"
|
||||||
#include "ray.h"
|
#include "ray.h"
|
||||||
|
#include "raytracer.h"
|
||||||
#include "renderobject.h"
|
#include "renderobject.h"
|
||||||
|
|
||||||
class Material {
|
class Material {
|
||||||
|
|
@ -37,10 +39,9 @@ class Lambertian : public Material {
|
||||||
const HitRecord& hit_record) const override {
|
const HitRecord& hit_record) const override {
|
||||||
auto scatter_dir = hit_record.normal + rand().GenOnUnitSphere();
|
auto scatter_dir = hit_record.normal + rand().GenOnUnitSphere();
|
||||||
|
|
||||||
// TODO: enable
|
if (scatter_dir.almost_zero()) {
|
||||||
/* if (scatter_dir.almost_zero()) {
|
|
||||||
scatter_dir = hit_record.normal;
|
scatter_dir = hit_record.normal;
|
||||||
} */
|
}
|
||||||
|
|
||||||
Ray scattered{hit_record.p, scatter_dir};
|
Ray scattered{hit_record.p, scatter_dir};
|
||||||
|
|
||||||
|
|
@ -50,3 +51,23 @@ class Lambertian : public Material {
|
||||||
private:
|
private:
|
||||||
Colour albedo_;
|
Colour albedo_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class Metal : public Material {
|
||||||
|
public:
|
||||||
|
constexpr Metal(Colour albedo, f64 fuzz) : albedo_{albedo}, fuzz_{fuzz} { assert(fuzz <= 1); }
|
||||||
|
|
||||||
|
std::optional<std::tuple<Colour, Ray>> Scatter(const Ray& in,
|
||||||
|
const HitRecord& hit_record) const override {
|
||||||
|
auto reflect_dir = in.direction().reflect(hit_record.normal).normed();
|
||||||
|
|
||||||
|
reflect_dir += fuzz_ * rand().GenOnUnitSphere();
|
||||||
|
|
||||||
|
Ray scattered{hit_record.p, reflect_dir};
|
||||||
|
|
||||||
|
return std::make_tuple(albedo_, scattered);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
Colour albedo_;
|
||||||
|
f64 fuzz_;
|
||||||
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <philox.h>
|
#include <philox.hh>
|
||||||
|
|
||||||
#include "raytracer.h"
|
#include "raytracer.h"
|
||||||
#include "vec3.h"
|
#include "vec3.h"
|
||||||
|
|
|
||||||
|
|
@ -76,7 +76,7 @@ class Renderer {
|
||||||
|
|
||||||
pixel_centre += random_shift;
|
pixel_centre += random_shift;
|
||||||
|
|
||||||
auto ray_direction = pixel_centre - camera_.centre();
|
auto ray_direction = (pixel_centre - camera_.centre()).normed();
|
||||||
|
|
||||||
return Ray{camera_.centre(), ray_direction};
|
return Ray{camera_.centre(), ray_direction};
|
||||||
}
|
}
|
||||||
|
|
@ -84,28 +84,8 @@ class Renderer {
|
||||||
constexpr Colour Cast(const Ray& ray, const RenderObject& world, u32 bounces) {
|
constexpr Colour Cast(const Ray& ray, const RenderObject& world, u32 bounces) {
|
||||||
auto hit_record = world.hit(ray, Interval{0.001, kInf});
|
auto hit_record = world.hit(ray, Interval{0.001, kInf});
|
||||||
|
|
||||||
if (hit_record.has_value()) {
|
// background
|
||||||
if (!hit_record->front_face || bounces == 0) {
|
if (!hit_record.has_value()) {
|
||||||
return Colour::kBlack;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Vec3 normal = hit_record->normal;
|
|
||||||
|
|
||||||
Vec3 new_origin = hit_record->p;
|
|
||||||
|
|
||||||
// Vec3 new_direction = rand_.GenOnHemisphere(normal);
|
|
||||||
Vec3 new_direction = normal + rand_.GenOnUnitSphere();
|
|
||||||
|
|
||||||
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();
|
auto unit_dir = ray.direction().normed();
|
||||||
|
|
||||||
f64 a = 0.5 * (unit_dir.y() + 1.0);
|
f64 a = 0.5 * (unit_dir.y() + 1.0);
|
||||||
|
|
@ -113,6 +93,25 @@ class Renderer {
|
||||||
return (1.0 - a) * Colour{1.0, 1.0, 1.0} + a * Colour{0.5, 0.7, 1.0};
|
return (1.0 - a) * Colour{1.0, 1.0, 1.0} + a * Colour{0.5, 0.7, 1.0};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// hit
|
||||||
|
|
||||||
|
if (!hit_record->front_face || bounces == 0) {
|
||||||
|
return Colour::kBlack;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto res = hit_record->mat->Scatter(ray, hit_record.value());
|
||||||
|
|
||||||
|
if (!res.has_value()) {
|
||||||
|
// absorped
|
||||||
|
return Colour::kBlack;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto [albedo, out_ray] = res.value();
|
||||||
|
|
||||||
|
assert(bounces > 0);
|
||||||
|
return albedo * Cast(out_ray, world, bounces - 1);
|
||||||
|
}
|
||||||
|
|
||||||
Camera camera_;
|
Camera camera_;
|
||||||
|
|
||||||
RandomGen rand_{};
|
RandomGen rand_{};
|
||||||
|
|
|
||||||
20
src/vec3.h
20
src/vec3.h
|
|
@ -65,15 +65,13 @@ class Vec3 {
|
||||||
return std::fabs(x()) < eps && std::fabs(y()) < eps && std::fabs(z()) < eps;
|
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 squared() const;
|
||||||
|
|
||||||
constexpr f64 norm() const { return std::sqrt(squared()); }
|
constexpr f64 norm() const;
|
||||||
|
|
||||||
constexpr Vec3 normed() const {
|
constexpr Vec3 normed() const;
|
||||||
auto r = *this;
|
|
||||||
r /= norm();
|
constexpr Vec3 reflect(Vec3 normal) const;
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::array<f64, 3> xyz_;
|
std::array<f64, 3> xyz_;
|
||||||
|
|
@ -119,4 +117,10 @@ constexpr Vec3 cross(const Vec3& u, const Vec3& v) {
|
||||||
u.x() * v.y() - u.y() - v.x()};
|
u.x() * v.y() - u.y() - v.x()};
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr Vec3 normed(const Vec3& v) { return v.normed(); }
|
constexpr f64 Vec3::squared() const { return dot(*this, *this); }
|
||||||
|
|
||||||
|
constexpr f64 Vec3::norm() const { return std::sqrt(squared()); }
|
||||||
|
|
||||||
|
constexpr Vec3 Vec3::normed() const { return *this / norm(); }
|
||||||
|
|
||||||
|
constexpr Vec3 Vec3::reflect(Vec3 normal) const { return *this - 2 * dot(*this, normal) * normal; }
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue