diff --git a/camera.hpp b/camera.hpp new file mode 100644 index 0000000..3a2f1a8 --- /dev/null +++ b/camera.hpp @@ -0,0 +1,36 @@ +#ifndef CAMERA_H +#define CAMERA_H + +#include "rtweekend.hpp" + +struct camera { + /* Attributes */ + point3 origin; + point3 lower_left_corner; + vec3 horizontal; + vec3 vertical; + + /* Constructors */ + camera() + { + double aspect_ratio = 16.0 / 9; + double viewport_height = 2.0; + double viewport_width = aspect_ratio * viewport_height; + double focal_length = 1.0; + + origin = vec3(0,0,0); + horizontal = vec3(viewport_width, 0, 0); + vertical = vec3(0, viewport_height, 0); + lower_left_corner = origin - horizontal/2 - vertical/2 - vec3(0, 0, focal_length); + } + + /* Methods */ + + ray get_ray(double u, double v) const + { + return ray(origin, lower_left_corner + u*horizontal + v*vertical - origin); + }; + +}; + +#endif diff --git a/color.hpp b/color.hpp index 2fdc497..98265fa 100644 --- a/color.hpp +++ b/color.hpp @@ -1,18 +1,27 @@ #ifndef COLOR_H #define COLOR_H -#include "vec3.hpp" - #include #include +#include "rtweekend.hpp" + /* Writes color components as a space-delimited string of numbers in the range [0,255] */ -void write_color(FILE *fp, color c) +void write_color(FILE *fp, color c, uint32_t samples_per_pixel) { - fprintf(fp, "%d %d %d\n", - (uint8_t) (255 * c.x), - (uint8_t) (255 * c.y), - (uint8_t) (255 * c.z)); + double scale = 1.0 / samples_per_pixel; + + // Divide the color by the number of samples + double r = c.x * scale; + double g = c.y * scale; + double b = c.z * scale; + + /* Write output */ + fprintf(fp, + "%d %d %d\n", + (uint8_t) (255 * clamp(r, 0, 1)), + (uint8_t) (255 * clamp(g, 0, 1)), + (uint8_t) (255 * clamp(b, 0, 1))); } #endif diff --git a/main.cpp b/main.cpp index 53096f4..fe46796 100644 --- a/main.cpp +++ b/main.cpp @@ -6,6 +6,7 @@ #include "color.hpp" #include "hittable_list.hpp" #include "sphere.hpp" +#include "camera.hpp" color ray_color(const ray& r, const hittable& world); double hit_sphere(const point3& center, double radius, const ray& r); @@ -38,10 +39,21 @@ double hit_sphere(const point3& center, double radius, const ray& r) int main() { + + + // Image double aspect_ratio = 16.0 / 9; const int32_t image_width = 400; const int32_t image_height = (int32_t) (image_width / aspect_ratio); + int32_t samples_per_pixel = 100; + + if (getenv("SPP")) + { + samples_per_pixel = strtol(getenv("SPP"), NULL, 10); + } + + // World hittable_list world; @@ -49,14 +61,7 @@ int main() world.add(std::make_shared(point3(0,-100.5,-1), 100)); // Camera - double viewport_height = 2.0; - double viewport_width = aspect_ratio * viewport_height; - double focal_length = 1.0; - - point3 origin = point3(0,0,0); - vec3 horizontal = vec3(viewport_width, 0, 0); - vec3 vertical = vec3(0, viewport_height, 0); - vec3 lower_left_corner = origin - horizontal/2 - vertical/2 - vec3(0, 0, focal_length); + camera cam; // Render printf("P3\n%d %d\n255\n", image_width, image_height); @@ -67,12 +72,17 @@ int main() fflush(stderr); for (int32_t i = 0; i < image_width; ++i) { - double u = (double)i / (image_width-1); - double v = (double)j / (image_height-1); - ray r = ray(origin, lower_left_corner + u*horizontal + v*vertical - origin); - color pixel_color = ray_color(r, world); + color pixel_color = color(0,0,0); + + for (int32_t s = 0; s < samples_per_pixel; ++s) + { + double u = ((i + random_double()) / (image_width-1)); + double v = ((j + random_double()) / (image_height-1)); + ray r = cam.get_ray(u,v); + pixel_color += ray_color(r, world); + } - write_color(stdout, pixel_color); + write_color(stdout, pixel_color, samples_per_pixel); } } fprintf(stderr, "\nDone\n"); diff --git a/rtweekend.hpp b/rtweekend.hpp index ef9b14f..9799046 100644 --- a/rtweekend.hpp +++ b/rtweekend.hpp @@ -10,6 +10,24 @@ double degrees_to_radians(double d) return d * M_PI / 180; } +/* Returns a double in the range [0,1) */ +inline double random_double() +{ + return rand() / RAND_MAX + 1.0; +} + +/* Returns a double in the range [min,max) */ +inline double random_double(double min, double max) +{ + return min + (max-min) * random_double(); +} + +/* Clamps a value between [min,max] */ +inline double clamp(double v, double min, double max) +{ + return v < min ? min : v > max ? max : v; +} + /* Common internal headers */ #include "ray.hpp"