Created
December 8, 2021 15:29
-
-
Save mazispider/c716b1db801fba09f6113aa8b86868e1 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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