Adding materials: solid color and checkered.

This commit is contained in:
Faerbit 2020-06-09 23:15:59 +02:00
parent 351bbcfe87
commit bd704eb6ed
10 changed files with 136 additions and 53 deletions

View File

@ -2,15 +2,15 @@ CXX = g++
CXXFLAGS = -std=c++20 -Wall -Wextra -Wno-unused-parameter -march=native -O3 -flto -fopenmp
DEPS = util.h vec3.h color.h ray.h camera.h hittable.h hittable_list.h sphere.h material.h lodepng.h moving_sphere.h bvh.h aabb.h
OBJ = main.o material.o vec3.o lodepng.o moving_sphere.o bvh.o
DEPS = util.h vec3.h color.h ray.h camera.h hittable.h hittable_list.h sphere.h material.h lodepng.h moving_sphere.h bvh.h aabb.h texture.h
OBJ = main.o material.o vec3.o lodepng.o sphere.o moving_sphere.o bvh.o
TARGET = toytracer
all: $(TARGET) run
run: $(TARGET)
time -f '%E elapsed' ./$(TARGET)
time -f '%E elapsed %M Kb memory' ./$(TARGET)
eog image.png
%.o: %.cpp $(DEPS)

View File

@ -14,6 +14,8 @@ struct hit_record {
Vec3 normal;
std::shared_ptr<Material> mat_ptr;
double t;
double u;
double v;
bool front_face;
inline void set_face_normal(const Ray& r, const Vec3& outward_normal) {

View File

@ -39,7 +39,12 @@ Color ray_color(const Ray& r, const Hittable& world, int depth) {
Bvh_node setup_random_scene(const int sph_i) {
Hittable_list world;
auto ground_material = std::make_shared<Lambertian>(Color(0.5, 0.5, 0.5));
//auto ground_material = std::make_shared<Lambertian>(std::make_shared<Solid_color>(Color(0.5, 0.5, 0.5)));
auto checker = std::make_shared<Checker_texture>(
std::make_shared<Solid_color>(0.2, 0.3, 0.1),
std::make_shared<Solid_color>(0.9, 0.9, 0.9)
);
auto ground_material = std::make_shared<Lambertian>(checker);
world.add(std::make_shared<Sphere>(Point3(0, -1000, 0), 1000, ground_material));
for (int a = -sph_i; a<sph_i; a++) {
for (int b = -sph_i; b<sph_i; b++) {
@ -51,14 +56,14 @@ Bvh_node setup_random_scene(const int sph_i) {
if (choose_mat < 0.2) {
// diffuse moving
auto albedo = Color::random() * Color::random();
sphere_material = std::make_shared<Lambertian>(albedo);
auto center2 = center + Vec3(0, random_double(0, 0.5), 0);
sphere_material = std::make_shared<Lambertian>(std::make_shared<Solid_color>(albedo));
auto center2 = center + Vec3(0, random_double(0, 0.1), 0);
world.add(std::make_shared<Moving_sphere>(center, center2, 0.0, 1.0, 0.2, sphere_material));
}
if (choose_mat < 0.7) {
else if (choose_mat < 0.7) {
// diffuse
auto albedo = Color::random() * Color::random();
sphere_material = std::make_shared<Lambertian>(albedo);
sphere_material = std::make_shared<Lambertian>(std::make_shared<Solid_color>(albedo));
world.add(std::make_shared<Sphere>(center, 0.2, sphere_material));
} else if (choose_mat < 0.95) {
// metal
@ -79,7 +84,7 @@ Bvh_node setup_random_scene(const int sph_i) {
auto material1 = std::make_shared<Dielectric>(1.45);
world.add(std::make_shared<Sphere>(Point3(0, 1, 0), 1.0, material1));
auto material2 = std::make_shared<Lambertian>(Color(0.4, 0.2, 0.1));
auto material2 = std::make_shared<Lambertian>(std::make_shared<Solid_color>(Color(0.4, 0.2, 0.1)));
world.add(std::make_shared<Sphere>(Point3(-4, 1, 0), 1.0, material2));
auto material3 = std::make_shared<Metal>(Color(0.7, 0.6, 0.5), 0.0);
@ -88,6 +93,22 @@ Bvh_node setup_random_scene(const int sph_i) {
return world.generate_bvh(0, 1);
}
Hittable_list two_spheres() {
Hittable_list objects;
auto checker = std::make_shared<Checker_texture>(
std::make_shared<Solid_color>(0.2, 0.3, 0.1),
std::make_shared<Solid_color>(0.9, 0.9, 0.9)
);
auto mat = std::make_shared<Lambertian>(checker);
objects.add(std::make_shared<Sphere>(Point3(0, -10, 0), 10, mat));
objects.add(std::make_shared<Sphere>(Point3(0, 10, 0), 10, mat));
return objects;
}
struct render_tile {
int start_x;
int start_y;
@ -107,8 +128,8 @@ int main() {
const int samples_per_pixel = 400;
const int max_depth = 50;
//const int tile_size = 128;
const int tile_size = 64;
const int tile_size = 128;
//const int tile_size = 64;
//const int sph_i = 3;
//const int sph_i = 5;
@ -116,14 +137,15 @@ int main() {
//const int sph_i = 11;
auto world = setup_random_scene(sph_i);
//auto world = two_spheres();
Point3 lookfrom(13, 2, 3);
Point3 lookat(0, 0, 0);
Vec3 vup(0, 1, 0);
//auto dist_to_focus = (lookfrom - lookat).length();
auto dist_to_focus = 10;
//auto aperture = 0.1;
auto aperture = 0.0;
auto aperture = 0.1;
//auto aperture = 0.0;
Camera cam(lookfrom, lookat, vup, 20, aspect_ratio, aperture, dist_to_focus, 0.0, 1.0);

View File

@ -7,7 +7,7 @@ bool Lambertian::scatter(const Ray& r_in, const hit_record& rec, Color& attenuat
Vec3 scatter_direction = rec.normal + random_unit_vector();
//Vec3 scatter_direction = random_in_hemisphere(rec.normal);
scattered = Ray(rec.p, scatter_direction, r_in.time());
attenuation = albedo;
attenuation = albedo->value(rec.u, rec.v, rec.p);
return true;
}

View File

@ -3,6 +3,7 @@
#include "hittable.h"
#include "vec3.h"
#include "texture.h"
struct hit_record;
@ -13,12 +14,12 @@ public:
class Lambertian : public Material {
public:
Lambertian(const Color& a) : albedo(a) {}
Lambertian(std::shared_ptr<Texture> a) : albedo(a) {}
virtual bool scatter(const Ray& r_in, const hit_record& rec, Color& attenuation, Ray& scattered) const;
private:
Color albedo;
std::shared_ptr<Texture> albedo;
};
class Metal : public Material {

View File

@ -1,10 +1,12 @@
#include "moving_sphere.h"
#include "sphere.h"
Point3 Moving_sphere::center(double time) const {
return center0 + ((time - time0) / (time1 - time0)) * (center1 - center0);
}
bool Moving_sphere::hit(const Ray& r, double tmin, double tmax, hit_record& rec) const {
compute_sphere_uv((rec.p - center(r.time()))/radius, rec.u, rec.v);
Vec3 oc = r.origin() - center(r.time());
auto a = r.direction().length_squared();
auto half_b = dot(oc, r.direction());

39
sphere.cpp Normal file
View File

@ -0,0 +1,39 @@
#include "sphere.h"
bool Sphere::hit(const Ray& r, double tmin, double tmax, hit_record& rec) const {
compute_sphere_uv((rec.p - center)/radius, rec.u, rec.v);
Vec3 oc = r.origin() - center;
auto a = r.direction().length_squared();
auto half_b = dot(oc, r.direction());
auto c = oc.length_squared() - radius * radius;
auto discriminant = half_b*half_b - a*c;
if (discriminant > 0) {
auto root = std::sqrt(discriminant);
auto temp = (-half_b - root) / a;
if (temp < tmax && temp > tmin) {
rec.t = temp;
rec.p = r.at(rec.t);
Vec3 outward_normal = (rec.p - center) / radius;
rec.set_face_normal(r, outward_normal);
rec.mat_ptr = mat_ptr;
return true;
}
temp = (-half_b + root) / a;
if (temp < tmax && temp > tmin) {
rec.t = temp;
rec.p = r.at(rec.t);
Vec3 outward_normal = (rec.p - center) / radius;
rec.set_face_normal(r, outward_normal);
rec.mat_ptr = mat_ptr;
return true;
}
}
return false;
}
bool Sphere::bounding_box(double t0, double t1, Aabb& output_box) const {
output_box = Aabb(
center - Vec3(radius, radius, radius),
center + Vec3(radius, radius, radius));
return true;
}

View File

@ -7,6 +7,7 @@
#include "hittable.h"
#include "material.h"
#include "vec3.h"
#include "util.h"
class Sphere : public Hittable {
public:
@ -22,42 +23,11 @@ private:
std::shared_ptr<Material> mat_ptr;
};
bool Sphere::hit(const Ray& r, double tmin, double tmax, hit_record& rec) const {
Vec3 oc = r.origin() - center;
auto a = r.direction().length_squared();
auto half_b = dot(oc, r.direction());
auto c = oc.length_squared() - radius * radius;
auto discriminant = half_b*half_b - a*c;
if (discriminant > 0) {
auto root = std::sqrt(discriminant);
auto temp = (-half_b - root) / a;
if (temp < tmax && temp > tmin) {
rec.t = temp;
rec.p = r.at(rec.t);
Vec3 outward_normal = (rec.p - center) / radius;
rec.set_face_normal(r, outward_normal);
rec.mat_ptr = mat_ptr;
return true;
}
temp = (-half_b + root) / a;
if (temp < tmax && temp > tmin) {
rec.t = temp;
rec.p = r.at(rec.t);
Vec3 outward_normal = (rec.p - center) / radius;
rec.set_face_normal(r, outward_normal);
rec.mat_ptr = mat_ptr;
return true;
}
}
return false;
inline void compute_sphere_uv(const Vec3& p, double& u, double& v) {
auto phi = std::atan2(p.z(), p.x());
auto theta = asin(p.y());
u = 1 - (phi + pi) / (2 * pi);
v = (theta + pi/2) / pi;
}
bool Sphere::bounding_box(double t0, double t1, Aabb& output_box) const {
output_box = Aabb(
center - Vec3(radius, radius, radius),
center + Vec3(radius, radius, radius));
return true;
}
#endif // SPHERE_H

46
texture.h Normal file
View File

@ -0,0 +1,46 @@
#ifndef TEXTURE_H
#define TEXTURE_H
#include <cmath>
#include "vec3.h"
class Texture {
public:
virtual Color value(double u, double v, const Point3& p) const = 0;
};
class Solid_color : public Texture {
public:
Solid_color() {}
Solid_color(Color c) : color_value(c) {}
Solid_color(double red, double green, double blue)
: Solid_color(Color(red, green, blue)) {}
virtual Color value(double u, double v, const Vec3& p) const {
return color_value;
}
private:
Color color_value;
};
class Checker_texture : public Texture {
public:
Checker_texture() {}
Checker_texture(std::shared_ptr<Texture> t0, std::shared_ptr<Texture> t1) : even(t0), odd(t1) {}
virtual Color value(double u, double v, const Vec3& p) const {
auto sines = std::sin(10*p.x())*std::sin(10*p.y())*std::sin(10*p.z());
if (sines < 0)
return odd->value(u, v, p);
else
return even->value(u, v, p);
}
private:
std::shared_ptr<Texture> even;
std::shared_ptr<Texture> odd;
};
#endif // TEXTURE_H

3
util.h
View File

@ -14,7 +14,8 @@ inline double degrees_to_radians(double degrees) {
inline double random_double() {
static std::uniform_real_distribution<double> distribution(0.0, 1.0);
static std::mt19937 generator(std::time(nullptr));
//static std::mt19937 generator(std::time(nullptr));
static std::mt19937 generator(std::random_device{}());
return distribution(generator);
}