Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save mazispider/c716b1db801fba09f6113aa8b86868e1 to your computer and use it in GitHub Desktop.
Save mazispider/c716b1db801fba09f6113aa8b86868e1 to your computer and use it in GitHub Desktop.
#include "rtweekend.h"
#include "aarect.h"
#include "box.h"
#include "camera.h"
#include "color.h"
#include "hittable_list.h"
#include "material.h"
#include "sphere.h"
#include <iostream>
#include <thread>
#include <vector>
color ray_color(
const ray& r,
const color& background,
const hittable& world,
shared_ptr<hittable> lights,
int depth
) {
hit_record rec;
// If we've exceeded the ray bounce limit, no more light is gathered.
if (depth <= 0)
return color(0, 0, 0);
// If the ray hits nothing, return the background color.
if (!world.hit(r, 0.001, infinity, rec))
return background;
scatter_record srec;
color emitted = rec.mat_ptr->emitted(r, rec, rec.u, rec.v, rec.p);
if (!rec.mat_ptr->scatter(r, rec, srec))
return emitted;
if (srec.is_specular) {
return srec.attenuation
* ray_color(srec.specular_ray, background, world, lights, depth - 1);
}
auto light_ptr = make_shared<hittable_pdf>(lights, rec.p);
mixture_pdf p(light_ptr, srec.pdf_ptr);
ray scattered = ray(rec.p, p.generate(), r.time());
auto pdf_val = p.value(scattered.direction());
return emitted
+ srec.attenuation * rec.mat_ptr->scattering_pdf(r, rec, scattered)
* ray_color(scattered, background, world, lights, depth - 1)
/ pdf_val;
}
hittable_list cornell_box() {
hittable_list objects;
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<diffuse_light>(color(15, 15, 15));
objects.add(make_shared<yz_rect>(0, 555, 0, 555, 555, green));
objects.add(make_shared<yz_rect>(0, 555, 0, 555, 0, red));
objects.add(make_shared<flip_face>(make_shared<xz_rect>(213, 343, 227, 332, 554, light)));
objects.add(make_shared<xz_rect>(0, 555, 0, 555, 555, white));
objects.add(make_shared<xz_rect>(0, 555, 0, 555, 0, white));
objects.add(make_shared<xy_rect>(0, 555, 0, 555, 555, white));
shared_ptr<material> aluminum = make_shared<metal>(color(0.8, 0.85, 0.88), 0.0);
shared_ptr<hittable> box1 = make_shared<box>(point3(0, 0, 0), point3(165, 330, 165), aluminum);
box1 = make_shared<rotate_y>(box1, 15);
box1 = make_shared<translate>(box1, vec3(265, 0, 295));
objects.add(box1);
auto glass = make_shared<dielectric>(1.5);
objects.add(make_shared<sphere>(point3(190, 90, 190), 90, glass));
return objects;
}
void mThreadFunction(const int samples_per_pixel, const int image_width, const int image_height, const camera& cam, const color& background, const hittable_list& world, const std::shared_ptr<hittable_list>& lights, const int max_depth, const int i, const int j, color& px_color) {
color c(0, 0, 0);
px_color = c;
for (int s = 0; s < samples_per_pixel; ++s) {
auto u = (i + random_double()) / (image_width - 1);
auto v = (j + random_double()) / (image_height - 1);
ray r = cam.get_ray(u, v);
px_color += ray_color(r, background, world, lights, max_depth);
}
}
int main() {
// Image
const auto aspect_ratio = 1.0 / 1.0;
const int image_width = 800;
const int image_height = static_cast<int>(image_width / aspect_ratio);
const int samples_per_pixel = 128;
const int max_depth = 25;
// World
auto lights = make_shared<hittable_list>();
lights->add(make_shared<xz_rect>(213, 343, 227, 332, 554, shared_ptr<material>()));
lights->add(make_shared<sphere>(point3(190, 90, 190), 90, shared_ptr<material>()));
auto world = cornell_box();
color background(0, 0, 0);
// Camera
point3 lookfrom(278, 320, -750);
point3 lookat(278, 278, 0);
vec3 vup(0, 1, 0);
auto dist_to_focus = 10.0;
auto aperture = 0.0;
auto vfov = 40.0;
auto time0 = 0.0;
auto time1 = 1.0;
camera cam(lookfrom, lookat, vup, vfov, aspect_ratio, aperture, dist_to_focus, time0, time1);
// Render
std::cout << "P3\n" << image_width << ' ' << image_height << "\n255\n";
for (int j = image_height - 1; j >= 0; j--) {
std::cerr << "\rScanlines remaining: " << j << ' ' << std::flush;
for (int i = 0; i < image_width / 4; i++) {
color pixel_color1(0, 0, 0), pixel_color2(0, 0, 0), pixel_color3(0, 0, 0), pixel_color4(0, 0, 0);
//instantiate threads
std::thread thr1(mThreadFunction, samples_per_pixel, image_width, image_height, std::ref(cam), std::ref(background), std::ref(world), std::ref(lights), max_depth, 4 * i, j, std::ref(pixel_color1));
std::thread thr2(mThreadFunction, samples_per_pixel, image_width, image_height, std::ref(cam), std::ref(background), std::ref(world), std::ref(lights), max_depth, 4 * i + 1, j, std::ref(pixel_color2));
std::thread thr3(mThreadFunction, samples_per_pixel, image_width, image_height, std::ref(cam), std::ref(background), std::ref(world), std::ref(lights), max_depth, 4 * i + 2, j, std::ref(pixel_color3));
std::thread thr4(mThreadFunction, samples_per_pixel, image_width, image_height, std::ref(cam), std::ref(background), std::ref(world), std::ref(lights), max_depth, 4 * i + 3, j, std::ref(pixel_color4));
//wait for all threads to finish their works
thr1.join();
thr2.join();
thr3.join();
thr4.join();
write_color(std::cout, pixel_color1, samples_per_pixel);
write_color(std::cout, pixel_color2, samples_per_pixel);
write_color(std::cout, pixel_color3, samples_per_pixel);
write_color(std::cout, pixel_color4, samples_per_pixel);
}
}
std::cerr << "\nDone.\n";
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment