Compare commits

..

No commits in common. "4ccba24017262c300083f7c0f6b46cf12a662612" and "93330c85c2ebfcb27295bfd92e7817ccec41c624" have entirely different histories.

7 changed files with 42 additions and 198 deletions

View File

@ -3,9 +3,3 @@
Ray tracing rendering experiments Ray tracing rendering experiments
https://raytracing.github.io/ https://raytracing.github.io/
Produced PPM images can be converted to PNG with `imagemagick`:
```
convert image.ppm image.png
```

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 MiB

View File

@ -5,40 +5,22 @@
class camera class camera
{ {
public: public:
camera( const double ASPECT_RATIO = 16.0 / 9.0;
point3 lookfrom, const double VIEWPORT_HEIGHT = 2.0;
point3 lookat, const double VIEWPORT_WIDTH = ASPECT_RATIO * VIEWPORT_HEIGHT;
vec3 vup, const double FOCAL_LENGTH = 1.0;
double vfov, // vertical field of view in degrees
double aspect_ratio, camera() :
double aperture, origin_ (point3(0,0,0)),
double focus_dist) horizontal_ (vec3(VIEWPORT_WIDTH,0.0,0.0)),
vertical_ (vec3(0.0, VIEWPORT_HEIGHT, 0.0))
{ {
auto theta = degrees_to_radians(vfov); lower_left_corner_ = origin_ - horizontal_/2 - vertical_/2 - vec3(0,0,FOCAL_LENGTH);
auto h = tan(theta/2);
auto viewport_height = 2.0 * h;
auto viewport_width = aspect_ratio * viewport_height;
w_ = unit_vector(lookfrom - lookat);
u_ = unit_vector(cross(vup, w_));
v_ = cross(w_, u_);
origin_ = lookfrom;
horizontal_ = focus_dist * viewport_width * u_;
vertical_ = focus_dist * viewport_height * v_;
lower_left_corner_ = origin_ - horizontal_/2 - vertical_/2 - focus_dist * w_;
lens_radius_ = aperture / 2;
} }
ray get_ray(double s, double t) const ray get_ray(double u, double v) const
{ {
vec3 rd = lens_radius_ * random_in_unit_disk(); return ray(origin_, lower_left_corner_ + u*horizontal_ + v*vertical_ - origin_);
vec3 offset = (u_ * rd.x()) + (v_ * rd.y());
return ray(
origin_ + offset,
lower_left_corner_ + s*horizontal_ + t*vertical_ - origin_ - offset);
} }
private: private:
@ -46,6 +28,4 @@ class camera
point3 lower_left_corner_; point3 lower_left_corner_;
vec3 horizontal_; vec3 horizontal_;
vec3 vertical_; vec3 vertical_;
vec3 u_, v_, w_;
double lens_radius_;
}; };

View File

@ -9,22 +9,17 @@
#include <iostream> #include <iostream>
const double ASPECT_RATIO = 16.0 / 9.0; const double ASPECT_RATIO = 16.0 / 9.0;
const int WIDTH = 1920; const int WIDTH = 384;
const int HEIGHT = static_cast<int>(WIDTH / ASPECT_RATIO); const int HEIGHT = static_cast<int>(WIDTH / ASPECT_RATIO);
const int SAMPLES_PER_PIXEL = 8; const int SAMPLES_PER_PIXEL = 100;
const int MAX_DEPTH = 5; const int MAX_DEPTH = 50;
// fee2aa
//
const colour pink(254.0/255.0, 226.0/255.0, 170.0/255.0);
const colour grey(0.133, 0.133, 0.133);
colour ray_colour(const ray& r, const hittable& world, int depth) colour ray_colour(const ray& r, const hittable& world, int depth)
{ {
hit_record rec; hit_record rec;
if (depth <= 0) if (depth <= 0)
{ {
return grey; return colour(0,0,0);
} }
if (world.hit(r, 0.001, infinity, rec)) if (world.hit(r, 0.001, infinity, rec))
@ -37,96 +32,43 @@ colour ray_colour(const ray& r, const hittable& world, int depth)
return attenuation * ray_colour(scattered, world, depth-1); return attenuation * ray_colour(scattered, world, depth-1);
} }
return grey; return colour(0,0,0);
} }
vec3 unit_direction = unit_vector(r.direction()); vec3 unit_direction = unit_vector(r.direction());
auto t = 0.5 * (unit_direction.y() + 1.0) + 0.5; auto t = 0.5 * (unit_direction.y() + 1.0);
return lerp(grey, pink, t); auto a = colour(0.5, 0.6, 0.7);
} auto b = colour(1.0, 1.0, 1.0);
hittable_list random_scene() return lerp(a, b, t);
{
hittable_list world;
//auto ground_material = make_shared<lambertian>(pink);
//world.add(make_shared<sphere>(point3(0,-1000,0), 1000, ground_material));
//for (int a = -11; a < 11; a++)
//{
// for (int b = -11; b < 11; b++)
// {
// auto choose_mat = random_double();
// point3 centre(a + 0.9*random_double(), 0.2, b + 0.9*random_double());
// if ((centre - point3(4, 0.2, 0)).length() > 0.9)
// {
// shared_ptr<material> sphere_material;
// if (choose_mat < 0.8)
// {
// // diffuse
// //auto albedo = colour::random() * colour::random();
// sphere_material = make_shared<lambertian>(pink);
// world.add(make_shared<sphere>(centre, 0.2, sphere_material));
// }
// else if (choose_mat < 0.95)
// {
// // metal
// auto fuzz = random_double(0, 0.5);
// sphere_material = make_shared<metal>(pink, fuzz);
// world.add(make_shared<sphere>(centre, 0.2, sphere_material));
// }
// else
// {
// // glass
// sphere_material = make_shared<dielectric>(1.5);
// world.add(make_shared<sphere>(centre,0.2, sphere_material));
// }
// }
// }
//}
auto material1 = make_shared<dielectric>(1.5);
world.add(make_shared<sphere>(point3(0, 0, 0), 3.0, material1));
//auto material2 = make_shared<lambertian>(pink);
//world.add(make_shared<sphere>(point3(-4, 1, 0), 1.0, material2));
auto material3 = make_shared<metal>(pink, 0.5);
int sphere_count = 10;
for (int i = 0; i < sphere_count; i++)
{
float a = 6.28 * (float)i/sphere_count - 100.0;
float r = 8.0;
float x = r*sin(a);
float y = 2.0*cos(a);
float z = r*cos(a);
point3 pos(x,y,z);
world.add(make_shared<sphere>(pos, 2.0, material3));
}
return world;
} }
int main() int main()
{ {
std::cout << "P3\n" << WIDTH << ' ' << HEIGHT << "\n255\n"; std::cout << "P3\n" << WIDTH << ' ' << HEIGHT << "\n255\n";
hittable_list world = random_scene(); hittable_list world;
auto dist_to_target = 10.0; world.add(make_shared<sphere>(
auto dist_to_focus = dist_to_target + 1.0; point3(0,0,-1),
auto cam_y = 1.0; 0.5,
point3 lookfrom(0,cam_y,-dist_to_target); make_shared<lambertian>(colour(0.7,0.3,0.3))));
point3 lookat(0,0,0); world.add(make_shared<sphere>(
vec3 vup(0,1,0); point3(0,-100.5,-1),
auto aperture = 0.5; 100,
make_shared<lambertian>(colour(0.8,0.8,0.0))));
camera cam(lookfrom, lookat, vup, 47, ASPECT_RATIO, aperture, dist_to_focus); world.add(make_shared<sphere>(
point3(1,0,-1),
0.5,
make_shared<metal>(colour(0.8,0.6,0.2))));
world.add(make_shared<sphere>(
point3(-1,0,-1),
0.5,
make_shared<metal>(colour(0.8,0.8,0.8))));
camera cam;
for (int j = HEIGHT - 1; j >= 0; --j) for (int j = HEIGHT - 1; j >= 0; --j)
{ {

View File

@ -13,13 +13,6 @@ class material
ray& scattered) const = 0; ray& scattered) const = 0;
}; };
double schlick(double cosine, double refraction_index)
{
auto r0 = (1-refraction_index) / (1+refraction_index);
r0 = r0*r0;
return r0 + (1-r0)*pow(1-cosine, 5);
}
class lambertian : public material class lambertian : public material
{ {
public: public:
@ -44,9 +37,7 @@ class lambertian : public material
class metal : public material class metal : public material
{ {
public: public:
metal(const colour& a, double f) : metal(const colour& a) : albedo_(a) {}
albedo_(a),
fuzz_(f < 1 ? f : 1) {}
virtual bool scatter( virtual bool scatter(
const ray& r_in, const ray& r_in,
@ -55,55 +46,11 @@ class metal : public material
ray& scattered) const ray& scattered) const
{ {
vec3 reflected = reflect(unit_vector(r_in.direction()), rec.normal); vec3 reflected = reflect(unit_vector(r_in.direction()), rec.normal);
scattered = ray(rec.p, reflected + fuzz_*random_in_unit_sphere()); scattered = ray(rec.p, reflected);
attenuation = albedo_; attenuation = albedo_;
return dot(scattered.direction(), rec.normal) > 0; return dot(scattered.direction(), rec.normal) > 0;
} }
private: private:
colour albedo_; colour albedo_;
double fuzz_;
};
class dielectric : public material
{
public:
dielectric(double ri) : refraction_index_(ri) {}
virtual bool scatter(
const ray& r_in,
const hit_record& rec,
colour& attenuation,
ray& scattered) const
{
attenuation = colour(1.0,1.0,1.0);
double etai_over_etat = rec.front_face ? (1.0 / refraction_index_) : refraction_index_;
vec3 unit_direction = unit_vector(r_in.direction());
double cos_theta = fmin(dot(-unit_direction, rec.normal), 1.0);
double sin_theta = sqrt(1.0 - cos_theta*cos_theta);
if (etai_over_etat * sin_theta > 1.0)
{
vec3 reflected = reflect(unit_direction, rec.normal);
scattered = ray(rec.p, reflected);
return true;
}
double reflect_prob = schlick(cos_theta, etai_over_etat);
if (random_double() < reflect_prob)
{
vec3 reflected = reflect(unit_direction, rec.normal);
scattered = ray(rec.p, reflected);
return true;
}
vec3 refracted = refract(unit_direction, rec.normal, etai_over_etat);
scattered = ray(rec.p, refracted);
return true;
}
private:
double refraction_index_;
}; };

View File

@ -160,26 +160,7 @@ vec3 random_in_hemisphere(const vec3& normal)
} }
} }
vec3 random_in_unit_disk()
{
while(true)
{
auto p = vec3(random_double(-1,1), random_double(-1,1), 0);
if (p.length_squared() >= 1) continue;
return p;
}
}
vec3 reflect(const vec3& v, const vec3& n) vec3 reflect(const vec3& v, const vec3& n)
{ {
return v - 2*dot(v,n)*n; return v - 2*dot(v,n)*n;
} }
vec3 refract(const vec3& uv, const vec3& n, double etai_over_etat)
{
auto cos_theta = dot(-uv, n);
vec3 r_out_parallel = etai_over_etat * (uv + cos_theta*n);
vec3 r_out_perp = -sqrt(1.0 - r_out_parallel.length_squared()) * n;
return r_out_parallel + r_out_perp;
}