### Scene Setup with Metal Materials (C++) Source: https://raytracing.github.io/books/RayTracingInOneWeekend Demonstrates how to integrate the 'metal' material into a scene, specifically within the main function of a C++ ray tracing application. It shows the creation of 'lambertian' and 'metal' material instances with different colors and fuzz values, assigning them to objects in the scene. ```cpp int main() { ... auto material_ground = make_shared(color(0.8, 0.8, 0.0)); auto material_center = make_shared(color(0.1, 0.2, 0.5)); auto material_left = make_shared(color(0.8, 0.8, 0.8), 0.3); auto material_right = make_shared(color(0.8, 0.6, 0.2), 1.0); ... } ``` -------------------------------- ### Main Ray Tracing Logic with Scene and Camera Setup in C++ Source: https://raytracing.github.io/books/RayTracingInOneWeekend The main function sets up the image dimensions, world geometry (spheres), and camera parameters. It then iterates through pixels, casting rays and determining their color using the `ray_color` function. ```C++ #include "rtweekend.h" #include "color.h" #include "ray.h" #include "vec3.h" #include "hittable.h" #include "hittable_list.h" #include "sphere.h" #include double hit_sphere(const point3& center, double radius, const ray& r) { ... } color ray_color(const ray& r, const hittable& world) { hit_record rec; if (world.hit(r, 0, infinity, rec)) { return 0.5 * (rec.normal + color(1,1,1)); } vec3 unit_direction = unit_vector(r.direction()); auto a = 0.5*(unit_direction.y() + 1.0); return (1.0-a)*color(1.0, 1.0, 1.0) + a*color(0.5, 0.7, 1.0); } int main() { // Image auto aspect_ratio = 16.0 / 9.0; int image_width = 400; // Calculate the image height, and ensure that it's at least 1. int image_height = int(image_width / aspect_ratio); image_height = (image_height < 1) ? 1 : image_height; // World hittable_list world; world.add(make_shared(point3(0,0,-1), 0.5)); world.add(make_shared(point3(0,-100.5,-1), 100)); // Camera auto focal_length = 1.0; auto viewport_height = 2.0; auto viewport_width = viewport_height * (double(image_width)/image_height); auto camera_center = point3(0, 0, 0); // Calculate the vectors across the horizontal and down the vertical viewport edges. auto viewport_u = vec3(viewport_width, 0, 0); auto viewport_v = vec3(0, -viewport_height, 0); // Calculate the horizontal and vertical delta vectors from pixel to pixel. auto pixel_delta_u = viewport_u / image_width; auto pixel_delta_v = viewport_v / image_height; // Calculate the location of the upper left pixel. auto viewport_upper_left = camera_center - vec3(0, 0, focal_length) - viewport_u/2 - viewport_v/2; auto pixel00_loc = viewport_upper_left + 0.5 * (pixel_delta_u + pixel_delta_v); // Render std::cout << "P3\n" << image_width << ' ' << image_height << "\n255\n"; for (int j = 0; j < image_height; j++) { std::clog << "\rScanlines remaining: " << (image_height - j) << ' ' << std::flush; for (int i = 0; i < image_width; i++) { auto pixel_center = pixel00_loc + (i * pixel_delta_u) + (j * pixel_delta_v); auto ray_direction = pixel_center - camera_center; ray r(camera_center, ray_direction); color pixel_color = ray_color(r, world); write_color(std::cout, pixel_color); } } std::clog << "\rDone. \n"; } ``` -------------------------------- ### Scene Setup for Total Internal Reflection (C++) Source: https://raytracing.github.io/books/RayTracingInOneWeekend Configures a scene in C++ to demonstrate total internal reflection by creating a sphere with a refractive index lower than the surrounding medium (an air bubble in water). This setup allows glancing rays to reflect internally, while more direct rays refract. ```cpp auto material_ground = make_shared(color(0.8, 0.8, 0.0)); auto material_center = make_shared(color(0.1, 0.2, 0.5)); auto material_left = make_shared(1.00 / 1.33); auto material_right = make_shared(color(0.8, 0.6, 0.2), 1.0); ``` -------------------------------- ### Use Max Depth in main() in C++ Source: https://raytracing.github.io/books/RayTracingInOneWeekend Demonstrates how to set the `max_depth` parameter for the camera in the `main` function. This example sets the maximum ray bounce depth to 50, affecting how many times rays can recursively bounce within the scene. ```C++ cam.max_depth = 50; ``` -------------------------------- ### C++ shared_ptr and make_shared Allocation Examples Source: https://raytracing.github.io/books/RayTracingInOneWeekend Demonstrates the usage of `std::shared_ptr` and `std::make_shared` for dynamic memory allocation and management in C++. `shared_ptr` provides reference counting for automatic memory deallocation, while `make_shared` simplifies object creation and allocation. ```cpp shared_ptr double_ptr = make_shared(0.37); shared_ptr vec3_ptr = make_shared(1.414214, 2.718281, 1.618034); shared_ptr sphere_ptr = make_shared(point3(0,0,0), 1.0); ``` ```cpp auto double_ptr = make_shared(0.37); auto vec3_ptr = make_shared(1.414214, 2.718281, 1.618034); auto sphere_ptr = make_shared(point3(0,0,0), 1.0); ``` -------------------------------- ### C++ Camera Class for Ray Tracing Setup Source: https://raytracing.github.io/books/RayTracingInOneWeekend This C++ class defines the parameters and initialization logic for a camera used in ray tracing. It calculates the camera's orientation, viewport dimensions, and pixel delta vectors based on user-defined properties like aspect ratio, image dimensions, field of view, and lookat parameters. The `initialize` method is crucial for setting up the internal camera frame. ```cpp class camera { public: double aspect_ratio = 1.0; // Ratio of image width over height int image_width = 100; // Rendered image width in pixel count int samples_per_pixel = 10; // Count of random samples for each pixel int max_depth = 10; // Maximum number of ray bounces into scene double vfov = 90; // Vertical view angle (field of view) point3 lookfrom = point3(0,0,0); // Point camera is looking from point3 lookat = point3(0,0,-1); // Point camera is looking at vec3 vup = vec3(0,1,0); // Camera-relative "up" direction ... private: int image_height; double pixel_samples_scale; point3 center; point3 pixel00_loc; vec3 pixel_delta_u; vec3 pixel_delta_v; vec3 u, v, w; void initialize() { image_height = int(image_width / aspect_ratio); image_height = (image_height < 1) ? 1 : image_height; pixel_samples_scale = 1.0 / samples_per_pixel; center = lookfrom; // Determine viewport dimensions. auto focal_length = (lookfrom - lookat).length(); auto theta = degrees_to_radians(vfov); auto h = std::tan(theta/2); auto viewport_height = 2 * h * focal_length; auto viewport_width = viewport_height * (double(image_width)/image_height); // Calculate the u,v,w unit basis vectors for the camera coordinate frame. w = unit_vector(lookfrom - lookat); u = unit_vector(cross(vup, w)); v = cross(w, u); // Calculate the vectors across the horizontal and down the vertical viewport edges. vec3 viewport_u = viewport_width * u; // Vector across viewport horizontal edge vec3 viewport_v = viewport_height * -v; // Vector down viewport vertical edge // Calculate the horizontal and vertical delta vectors from pixel to pixel. pixel_delta_u = viewport_u / image_width; pixel_delta_v = viewport_v / image_height; // Calculate the location of the upper left pixel. auto viewport_upper_left = center - (focal_length * w) - viewport_u/2 - viewport_v/2; pixel00_loc = viewport_upper_left + 0.5 * (pixel_delta_u + pixel_delta_v); } ... private: }; ``` -------------------------------- ### Scene Setup with Wide-Angle Camera (C++) Source: https://raytracing.github.io/books/RayTracingInOneWeekend Demonstrates setting up a scene with two spheres using a wide-angle camera (90° FOV). This code configures camera parameters like aspect ratio, image width, samples per pixel, and max depth before rendering the scene. ```cpp int main() { hittable_list world; auto R = std::cos(pi/4); auto material_left = make_shared(color(0,0,1)); auto material_right = make_shared(color(1,0,0)); world.add(make_shared(point3(-R, 0, -1), R, material_left)); world.add(make_shared(point3( R, 0, -1), R, material_right)); camera cam; cam.aspect_ratio = 16.0 / 9.0; cam.image_width = 400; cam.samples_per_pixel = 100; cam.max_depth = 50; cam.vfov = 90; cam.render(world); } ``` -------------------------------- ### Scene Setup with Hollow Glass Sphere in C++ Source: https://raytracing.github.io/books/RayTracingInOneWeekend Demonstrates scene construction in C++ using `std::make_shared` to add various geometric primitives with different material properties. It specifically shows how to create a hollow glass sphere by nesting a dielectric sphere with a refractive index of air/glass (1.00/1.50) inside a larger dielectric sphere with a refractive index of glass (1.50). ```C++ auto material_ground = make_shared(color(0.8, 0.8, 0.0)); auto material_center = make_shared(color(0.1, 0.2, 0.5)); auto material_left = make_shared(1.50); auto material_bubble = make_shared(1.00 / 1.50); auto material_right = make_shared(color(0.8, 0.6, 0.2), 0.0); world.add(make_shared(point3( 0.0, -100.5, -1.0), 100.0, material_ground)); world.add(make_shared(point3( 0.0, 0.0, -1.2), 0.5, material_center)); world.add(make_shared(point3(-1.0, 0.0, -1.0), 0.5, material_left)); world.add(make_shared(point3(-1.0, 0.0, -1.0), 0.4, material_bubble)); world.add(make_shared(point3( 1.0, 0.0, -1.0), 0.5, material_right)); ``` -------------------------------- ### Scene Update for Glass Material (C++) Source: https://raytracing.github.io/books/RayTracingInOneWeekend Demonstrates updating a scene to use a dielectric material for a sphere. This snippet shows how to create a `shared_ptr` to a `dielectric` object with a refractive index of 1.50 and assign it to a scene object, illustrating the application of refraction in scene setup. ```C++ auto material_ground = make_shared(color(0.8, 0.8, 0.0)); auto material_center = make_shared(color(0.1, 0.2, 0.5)); auto material_left = make_shared(1.50); auto material_right = make_shared(color(0.8, 0.6, 0.2), 1.0); ``` -------------------------------- ### C++: Set Up Camera and Render Scene Rays Source: https://raytracing.github.io/books/RayTracingInOneWeekend This C++ code sets up the camera parameters, calculates viewport dimensions, and generates rays for each pixel in the image. It initializes a ray_color function that currently returns black. ```cpp #include "color.h" #include "ray.h" #include "vec3.h" #include color ray_color(const ray& r) { return color(0,0,0); } int main() { // Image auto aspect_ratio = 16.0 / 9.0; int image_width = 400; // Calculate the image height, and ensure that it's at least 1. int image_height = int(image_width / aspect_ratio); image_height = (image_height < 1) ? 1 : image_height; // Camera auto focal_length = 1.0; auto viewport_height = 2.0; auto viewport_width = viewport_height * (double(image_width)/image_height); auto camera_center = point3(0, 0, 0); // Calculate the vectors across the horizontal and down the vertical viewport edges. auto viewport_u = vec3(viewport_width, 0, 0); auto viewport_v = vec3(0, -viewport_height, 0); // Calculate the horizontal and vertical delta vectors from pixel to pixel. auto pixel_delta_u = viewport_u / image_width; auto pixel_delta_v = viewport_v / image_height; // Calculate the location of the upper left pixel. auto viewport_upper_left = camera_center - vec3(0, 0, focal_length) - viewport_u/2 - viewport_v/2; auto pixel00_loc = viewport_upper_left + 0.5 * (pixel_delta_u + pixel_delta_v); // Render std::cout << "P3\n" << image_width << " " << image_height << "\n255\n"; for (int j = 0; j < image_height; j++) { std::clog << "\rScanlines remaining: " << (image_height - j) << ' ' << std::flush; for (int i = 0; i < image_width; i++) { auto pixel_center = pixel00_loc + (i * pixel_delta_u) + (j * pixel_delta_v); auto ray_direction = pixel_center - camera_center; ray r(camera_center, ray_direction); color pixel_color = ray_color(r); write_color(std::cout, pixel_color); } } std::clog << "\rDone. \n"; } ``` -------------------------------- ### Build and Run C++ Ray Tracer with CMake Source: https://raytracing.github.io/books/RayTracingInOneWeekend Instructions for building a C++ project using CMake and running the executable to generate a PPM image file. This covers both debug and release builds, and how to redirect output to a file. ```bash # Build debug version cmake -B build cmake --build build # Run debug version and redirect output to image.ppm build\Debug\inOneWeekend.exe > image.ppm # Build release version cmake --build build --config release # Run release version and redirect output to image.ppm build\Release\inOneWeekend.exe > image.ppm # Build and run on Mac/Linux (release) # build/inOneWeekend > image.ppm ``` -------------------------------- ### Configure Camera Parameters in C++ Main Function Source: https://raytracing.github.io/books/RayTracingInOneWeekend This C++ code snippet demonstrates how to initialize and configure camera parameters such as aspect ratio, image width, and samples per pixel within the main function of a ray tracing application. It then calls a render method on the configured camera object. ```cpp int main() { ... camera cam; cam.aspect_ratio = 16.0 / 9.0; cam.image_width = 400; cam.samples_per_pixel = 100; cam.render(world); } ``` -------------------------------- ### Configure Camera and Render Scene in C++ Source: https://raytracing.github.io/books/RayTracingInOneWeekend Sets up a camera with specific aspect ratio, image width, samples per pixel, and maximum depth. It then defines the camera's position, look-at point, and up vector before rendering a world containing spheres. This code is essential for initializing the rendering environment. ```cpp world.add(make_shared(point3(-1.0, 0.0, -1.0), 0.5, material_left)); world.add(make_shared(point3(-1.0, 0.0, -1.0), 0.4, material_bubble)); world.add(make_shared(point3( 1.0, 0.0, -1.0), 0.5, material_right)); camera cam; cam.aspect_ratio = 16.0 / 9.0; cam.image_width = 400; cam.samples_per_pixel = 100; cam.max_depth = 50; cam.vfov = 90; cam.lookfrom = point3(-2,2,1); cam.lookat = point3(0,0,-1); cam.vup = vec3(0,1,0); cam.render(world); } ``` -------------------------------- ### Create Scene with Metal Spheres (C++) Source: https://raytracing.github.io/books/RayTracingInOneWeekend Sets up a main function to create a scene containing multiple spheres with different materials, including metal spheres. It initializes a `hittable_list` to hold the world geometry, defines various material instances (lambertian and metal), and adds spheres with specified positions, radii, and materials to the world. Camera parameters are also configured. ```cpp #include "rtweekend.h" #include "camera.h" #include "hittable.h" #include "hittable_list.h" #include "material.h" #include "sphere.h" #include int main() { hittable_list world; auto material_ground = std::make_shared(color(0.8, 0.8, 0.0)); auto material_center = std::make_shared(color(0.1, 0.2, 0.5)); auto material_left = std::make_shared(color(0.8, 0.8, 0.8)); auto material_right = std::make_shared(color(0.8, 0.6, 0.2)); world.add(std::make_shared(point3( 0.0, -100.5, -1.0), 100.0, material_ground)); world.add(std::make_shared(point3( 0.0, 0.0, -1.2), 0.5, material_center)); world.add(std::make_shared(point3(-1.0, 0.0, -1.0), 0.5, material_left)); world.add(std::make_shared(point3( 1.0, 0.0, -1.0), 0.5, material_right)); camera cam; cam.aspect_ratio = 16.0 / 9.0; cam.image_width = 400; cam.samples_per_pixel = 100; cam.max_depth = 50; cam.render(world); } ``` -------------------------------- ### Camera Class Initialization for Ray Tracing (C++) Source: https://raytracing.github.io/books/RayTracingInOneWeekend Initializes the camera parameters for ray tracing, including image dimensions, field of view, camera position, and orientation. This section calculates viewport dimensions, camera basis vectors (u, v, w), pixel deltas, and the defocus disk radii based on user-defined parameters like `vfov`, `lookfrom`, `lookat`, `defocus_angle`, and `focus_dist`. ```C++ void initialize() { image_height = int(image_width / aspect_ratio); image_height = (image_height < 1) ? 1 : image_height; pixel_samples_scale = 1.0 / samples_per_pixel; center = lookfrom; // Determine viewport dimensions. auto focal_length = (lookfrom - lookat).length(); auto theta = degrees_to_radians(vfov); auto h = std::tan(theta/2); auto viewport_height = 2 * h * focus_dist; auto viewport_width = viewport_height * (double(image_width)/image_height); // Calculate the u,v,w unit basis vectors for the camera coordinate frame. w = unit_vector(lookfrom - lookat); u = unit_vector(cross(vup, w)); v = cross(w, u); // Calculate the vectors across the horizontal and down the vertical viewport edges. vec3 viewport_u = viewport_width * u; // Vector across viewport horizontal edge vec3 viewport_v = viewport_height * -v; // Vector down viewport vertical edge // Calculate the horizontal and vertical delta vectors to the next pixel. pixel_delta_u = viewport_u / image_width; pixel_delta_v = viewport_v / image_height; // Calculate the location of the upper left pixel. auto viewport_upper_left = center - (focus_dist * w) - viewport_u/2 - viewport_v/2; pixel00_loc = viewport_upper_left + 0.5 * (pixel_delta_u + pixel_delta_v); // Calculate the camera defocus disk basis vectors. auto defocus_radius = focus_dist * std::tan(degrees_to_radians(defocus_angle / 2)); defocus_disk_u = u * defocus_radius; defocus_disk_v = v * defocus_radius; } ``` -------------------------------- ### Include rtweekend.h for Color Calculations in C++ Source: https://raytracing.github.io/books/RayTracingInOneWeekend Demonstrates the inclusion of the common header `rtweekend.h` in `color.h`. This ensures that `color.h` can implicitly use definitions like `infinity` and `pi` without redefining them. ```C++ #include "rtweekend.h" #include ``` -------------------------------- ### Include Interval Class in Common Headers Source: https://raytracing.github.io/books/RayTracingInOneWeekend Shows the inclusion of the 'interval.h' header file alongside other common headers like 'color.h', 'ray.h', and 'vec3.h'. This makes the Interval class functionality available for use in other parts of the ray tracing project. ```C++ // Common Headers #include "color.h" #include "interval.h" #include "ray.h" #include "vec3.h" ``` -------------------------------- ### Camera Render Method Implementation - C++ Source: https://raytracing.github.io/books/RayTracingInOneWeekend Provides the implementation for the `render` method within the camera class. This method orchestrates the image rendering process, including initialization, pixel iteration, ray generation, and color writing. ```cpp class camera { public: double aspect_ratio = 1.0; // Ratio of image width over height int image_width = 100; // Rendered image width in pixel count void render(const hittable& world) { initialize(); std::cout << "P3\n" << image_width << ' ' << image_height << "\n255\n"; for (int j = 0; j < image_height; j++) { std::clog << "\rScanlines remaining: " << (image_height - j) << ' ' << std::flush; for (int i = 0; i < image_width; i++) { auto pixel_center = pixel00_loc + (i * pixel_delta_u) + (j * pixel_delta_v); auto ray_direction = pixel_center - center; ray r(center, ray_direction); color pixel_color = ray_color(r, world); write_color(std::cout, pixel_color); } } std::clog << "\rDone. \n"; } private: int image_height; // Rendered image height point3 center; // Camera center point3 pixel00_loc; // Location of pixel 0, 0 vec3 pixel_delta_u; // Offset to pixel to the right vec3 pixel_delta_v; // Offset to pixel below void initialize() { image_height = int(image_width / aspect_ratio); image_height = (image_height < 1) ? 1 : image_height; center = point3(0, 0, 0); // Determine viewport dimensions. auto focal_length = 1.0; auto viewport_height = 2.0; auto viewport_width = viewport_height * (double(image_width)/image_height); // Calculate the vectors across the horizontal and down the vertical viewport edges. auto viewport_u = vec3(viewport_width, 0, 0); auto viewport_v = vec3(0, -viewport_height, 0); // Calculate the horizontal and vertical delta vectors from pixel to pixel. pixel_delta_u = viewport_u / image_width; pixel_delta_v = viewport_v / image_height; // Calculate the location of the upper left pixel. auto viewport_upper_left = center - vec3(0, 0, focal_length) - viewport_u/2 - viewport_v/2; ``` -------------------------------- ### Include rtweekend.h for Sphere Definitions in C++ Source: https://raytracing.github.io/books/RayTracingInOneWeekend Demonstrates that `sphere.h` includes `rtweekend.h`. This ensures access to necessary math constants and utility functions for defining sphere geometry. ```C++ #include "rtweekend.h" #include "vec3.h" ``` -------------------------------- ### Camera Class for Multi-Sampled Ray Generation in C++ Source: https://raytracing.github.io/books/RayTracingInOneWeekend The `camera` class is enhanced to support multi-sampling. It includes parameters like `samples_per_pixel` and introduces `get_ray(i,j)` which utilizes `sample_square()` to generate rays directed at randomly sampled points within each pixel. The `render()` method iterates through pixels, accumulates colors from multiple samples, and then scales the final color before writing it. ```cpp class camera { public: double aspect_ratio = 1.0; int image_width = 100; int samples_per_pixel = 10; void render(const hittable& world) { initialize(); std::cout << "P3\n" << image_width << ' ' << image_height << "\n255\n"; for (int j = 0; j < image_height; j++) { std::clog << "\rScanlines remaining: " << (image_height - j) << ' ' << std::flush; for (int i = 0; i < image_width; i++) { color pixel_color(0,0,0); for (int sample = 0; sample < samples_per_pixel; sample++) { ray r = get_ray(i, j); pixel_color += ray_color(r, world); } write_color(std::cout, pixel_samples_scale * pixel_color); } } std::clog << "\rDone. \n"; } ... private: int image_height; double pixel_samples_scale; point3 center; point3 pixel00_loc; vec3 pixel_delta_u; vec3 pixel_delta_v; void initialize() { image_height = int(image_width / aspect_ratio); image_height = (image_height < 1) ? 1 : image_height; pixel_samples_scale = 1.0 / samples_per_pixel; center = point3(0, 0, 0); ... } ray get_ray(int i, int j) const { // Construct a camera ray originating from the origin and directed at randomly sampled // point around the pixel location i, j. auto offset = sample_square(); auto pixel_sample = pixel00_loc + ((i + offset.x()) * pixel_delta_u) + ((j + offset.y()) * pixel_delta_v); auto ray_origin = center; auto ray_direction = pixel_sample - ray_origin; return ray(ray_origin, ray_direction); } vec3 sample_square() const { // Returns the vector to a random point in the [-.5,-.5]-[+.5,+.5] unit square. return vec3(random_double() - 0.5, random_double() - 0.5, 0); } color ray_color(const ray& r, const hittable& world) const { ... } }; #endif ``` -------------------------------- ### Configuring Camera for Depth of Field in C++ Source: https://raytracing.github.io/books/RayTracingInOneWeekend Initializes and configures a camera object for rendering, setting parameters such as aspect ratio, image width, samples per pixel, and vertical field of view. It also defines the camera's position, look-at point, and enables depth-of-field effects by setting the defocus angle and focus distance. ```cpp int main() { ... camera cam; cam.aspect_ratio = 16.0 / 9.0; cam.image_width = 400; cam.samples_per_pixel = 100; cam.max_depth = 50; cam.vfov = 20; cam.lookfrom = point3(-2,2,1); cam.lookat = point3(0,0,-1); cam.vup = vec3(0,1,0); cam.defocus_angle = 10.0; cam.focus_dist = 3.4; cam.render(world); } ``` -------------------------------- ### PPM Image Generation Main Loop (C++) Source: https://raytracing.github.io/books/RayTracingInOneWeekend The main function for rendering a simple PPM image. It sets up image dimensions, iterates through each pixel, calculates a color based on pixel coordinates, and uses the 'write_color' function to output the pixel data to standard output. It includes progress logging to standard error. ```cpp #include "color.h" #include "vec3.h" #include int main() { // Image int image_width = 256; int image_height = 256; // Render std::cout << "P3\n" << image_width << ' ' << image_height << "\n255\n"; for (int j = 0; j < image_height; j++) { std::clog << "\rScanlines remaining: " << (image_height - j) << ' ' << std::flush; for (int i = 0; i < image_width; i++) { auto pixel_color = color(double(i)/(image_width-1), double(j)/(image_height-1), 0); write_color(std::cout, pixel_color); } } std::clog << "\rDone. \n"; } ``` -------------------------------- ### Schlick Approximation for Glass Material in C++ Source: https://raytracing.github.io/books/RayTracingInOneWeekend Implements a dielectric material using Schlick's approximation to model realistic glass reflectivity that varies with the viewing angle. It handles ray scattering, refraction, and reflection based on the incident ray and material properties. Dependencies include 'ray', 'hit_record', 'color', and vector math utilities. ```C++ class dielectric : public material { public: dielectric(double refraction_index) : refraction_index(refraction_index) {} bool scatter(const ray& r_in, const hit_record& rec, color& attenuation, ray& scattered) const override { attenuation = color(1.0, 1.0, 1.0); double ri = rec.front_face ? (1.0/refraction_index) : refraction_index; vec3 unit_direction = unit_vector(r_in.direction()); double cos_theta = std::fmin(dot(-unit_direction, rec.normal), 1.0); double sin_theta = std::sqrt(1.0 - cos_theta*cos_theta); bool cannot_refract = ri * sin_theta > 1.0; vec3 direction; if (cannot_refract || reflectance(cos_theta, ri) > random_double()) direction = reflect(unit_direction, rec.normal); else direction = refract(unit_direction, rec.normal, ri); scattered = ray(rec.p, direction); return true; } private: // Refractive index in vacuum or air, or the ratio of the material's refractive index over // the refractive index of the enclosing media double refraction_index; static double reflectance(double cosine, double refraction_index) { // Use Schlick's approximation for reflectance. auto r0 = (1 - refraction_index) / (1 + refraction_index); r0 = r0*r0; return r0 + (1-r0)*std::pow((1 - cosine),5); } }; ``` -------------------------------- ### Generate Random Point in Unit Disk (C++) Source: https://raytracing.github.io/books/RayTracingInOneWeekend Generates a random 2D point uniformly distributed within a unit disk. This function is crucial for simulating defocus blur by selecting random points on the camera's aperture. It uses a rejection sampling method, repeatedly generating points in a square until one falls within the unit circle. ```C++ inline vec3 random_in_unit_disk() { while (true) { auto p = vec3(random_double(-1,1), random_double(-1,1), 0); if (p.length_squared() < 1) return p; } } ``` -------------------------------- ### Use Interval in Main Ray Color Function Source: https://raytracing.github.io/books/RayTracingInOneWeekend Demonstrates the 'interval' class being used in the 'ray_color' function within 'main.cc'. It initializes the ray intersection interval to cover the entire range from 0 to infinity, allowing the 'world.hit' function to find the closest intersection. ```C++ color ray_color(const ray& r, const hittable& world) { hit_record rec; if (world.hit(r, interval(0, infinity), rec)) { return 0.5 * (rec.normal + color(1,1,1)); } vec3 unit_direction = unit_vector(r.direction()); auto a = 0.5*(unit_direction.y() + 1.0); return (1.0-a)*color(1.0, 1.0, 1.0) + a*color(0.5, 0.7, 1.0); } ``` -------------------------------- ### Camera Class for Ray Tracing (C++) Source: https://raytracing.github.io/books/RayTracingInOneWeekend Defines the Camera class used in ray tracing, managing image dimensions, samples per pixel, max ray bounces, and vertical field of view. It includes methods for initializing camera parameters based on aspect ratio and FOV, calculating viewport dimensions, and determining pixel locations. ```cpp class camera { public: double aspect_ratio = 1.0; // Ratio of image width over height int image_width = 100; // Rendered image width in pixel count int samples_per_pixel = 10; // Count of random samples for each pixel int max_depth = 10; // Maximum number of ray bounces into scene double vfov = 90; // Vertical view angle (field of view) void render(const hittable& world) { ... private: ... void initialize() { image_height = int(image_width / aspect_ratio); image_height = (image_height < 1) ? 1 : image_height; pixel_samples_scale = 1.0 / samples_per_pixel; center = point3(0, 0, 0); // Determine viewport dimensions. auto focal_length = 1.0; auto theta = degrees_to_radians(vfov); auto h = std::tan(theta/2); auto viewport_height = 2 * h * focal_length; auto viewport_width = viewport_height * (double(image_width)/image_height); // Calculate the vectors across the horizontal and down the vertical viewport edges. auto viewport_u = vec3(viewport_width, 0, 0); auto viewport_v = vec3(0, -viewport_height, 0); // Calculate the horizontal and vertical delta vectors from pixel to pixel. pixel_delta_u = viewport_u / image_width; pixel_delta_v = viewport_v / image_height; // Calculate the location of the upper left pixel. auto viewport_upper_left = center - vec3(0, 0, focal_length) - viewport_u/2 - viewport_v/2; pixel00_loc = viewport_upper_left + 0.5 * (pixel_delta_u + pixel_delta_v); } ... }; ``` -------------------------------- ### Implement Ray Intersection Tolerance (C++) Source: https://raytracing.github.io/books/RayTracingInOneWeekend This C++ code snippet demonstrates how to fix shadow acne by introducing a small tolerance (0.001) to the ray intersection interval. This prevents rays from self-intersecting with the surface they originated from due to floating-point errors. It's a common technique in ray tracing to ensure accurate shadow rendering. ```cpp class camera { ... private: ... color ray_color(const ray& r, int depth, const hittable& world) const { // If we've exceeded the ray bounce limit, no more light is gathered. if (depth <= 0) return color(0,0,0); hit_record rec; if (world.hit(r, interval(0.001, infinity), rec)) { vec3 direction = random_on_hemisphere(rec.normal); return 0.5 * ray_color(ray(rec.p, direction), depth-1, world); } vec3 unit_direction = unit_vector(r.direction()); auto a = 0.5*(unit_direction.y() + 1.0); return (1.0-a)*color(1.0, 1.0, 1.0) + a*color(0.5, 0.7, 1.0); } }; ``` -------------------------------- ### Metal Material with Fuzzy Reflection (C++) Source: https://raytracing.github.io/books/RayTracingInOneWeekend Implements a metal material where reflected rays can be randomized using a fuzz factor. This class inherits from a base 'material' class and defines scattering behavior for rays hitting a metal surface. It takes an albedo color and a fuzz value, normalizing the reflected vector and adding a random perturbation based on the fuzz factor. Returns true if the scattered ray's direction is away from the surface. ```cpp class metal : public material { public: metal(const color& albedo, double fuzz) : albedo(albedo), fuzz(fuzz < 1 ? fuzz : 1) {} bool scatter(const ray& r_in, const hit_record& rec, color& attenuation, ray& scattered) const override { vec3 reflected = reflect(r_in.direction(), rec.normal); reflected = unit_vector(reflected) + (fuzz * random_unit_vector()); scattered = ray(rec.p, reflected); attenuation = albedo; return (dot(scattered.direction(), rec.normal) > 0); } private: color albedo; double fuzz; }; ``` -------------------------------- ### Generate PPM Image Data in C++ Source: https://raytracing.github.io/books/RayTracingInOneWeekend This C++ code generates a 256x256 PPM image with a gradient from black to red and black to green. It outputs the PPM header and pixel data to standard output. Ensure correct formatting for image viewers. ```cpp #include int main() { // Image int image_width = 256; int image_height = 256; // Render std::cout << "P3\n" << image_width << ' ' << image_height << "\n255\n"; for (int j = 0; j < image_height; j++) { for (int i = 0; i < image_width; i++) { auto r = double(i) / (image_width-1); auto g = double(j) / (image_height-1); auto b = 0.0; int ir = int(255.999 * r); int ig = int(255.999 * g); int ib = int(255.999 * b); std::cout << ir << ' ' << ig << ' ' << ib << '\n'; } } } ``` -------------------------------- ### Dielectric Material Class with Total Internal Reflection (C++) Source: https://raytracing.github.io/books/RayTracingInOneWeekend Implements a dielectric material class in C++ that handles both refraction and reflection, including total internal reflection. The `scatter` function calculates the probability of reflection using the Fresnel equations and determines the scattered ray's direction. Attenuation is set to white, as dielectrics do not absorb light. ```cpp class dielectric : public material { public: dielectric(double refraction_index) : refraction_index(refraction_index) {} bool scatter(const ray& r_in, const hit_record& rec, color& attenuation, ray& scattered) const override { attenuation = color(1.0, 1.0, 1.0); double ri = rec.front_face ? (1.0/refraction_index) : refraction_index; vec3 unit_direction = unit_vector(r_in.direction()); double cos_theta = std::fmin(dot(-unit_direction, rec.normal), 1.0); double sin_theta = std::sqrt(1.0 - cos_theta*cos_theta); bool cannot_refract = ri * sin_theta > 1.0; vec3 direction; if (cannot_refract) direction = reflect(unit_direction, rec.normal); else direction = refract(unit_direction, rec.normal, ri); scattered = ray(rec.p, direction); return true; } private: // Refractive index in vacuum or air, or the ratio of the material's refractive index over // the refractive index of the enclosing media double refraction_index; }; ``` -------------------------------- ### Ray Color Calculation with Reflectance Adjustment (C++) Source: https://raytracing.github.io/books/RayTracingInOneWeekend This C++ code snippet demonstrates the `ray_color` function within a `camera` class. It calculates the color of a ray by recursively tracing its path and handling bounce limits. The reflectance value is adjusted to showcase the effect on perceived brightness. ```C++ class camera { ... color ray_color(const ray& r, int depth, const hittable& world) const { // If we've exceeded the ray bounce limit, no more light is gathered. if (depth <= 0) return color(0,0,0); hit_record rec; if (world.hit(r, interval(0.001, infinity), rec)) { vec3 direction = rec.normal + random_unit_vector(); return 0.1 * ray_color(ray(rec.p, direction), depth-1, world); } vec3 unit_direction = unit_vector(r.direction()); auto a = 0.5*(unit_direction.y() + 1.0); return (1.0-a)*color(1.0, 1.0, 1.0) + a*color(0.5, 0.7, 1.0); } }; ``` -------------------------------- ### Define Common Constants and Utility Functions in C++ Source: https://raytracing.github.io/books/RayTracingInOneWeekend Defines essential constants such as infinity and pi, and a utility function degrees_to_radians. It also includes common C++ standard library components and other necessary headers for ray tracing. ```C++ #ifndef RTWEEKEND_H #define RTWEEKEND_H #include #include #include #include // C++ Std Usings using std::make_shared; using std::shared_ptr; // Constants const double infinity = std::numeric_limits::infinity(); const double pi = 3.1415926535897932385; // Utility Functions inline double degrees_to_radians(double degrees) { return degrees * pi / 180.0; } // Common Headers #include "color.h" #include "ray.h" #include "vec3.h" #endif ``` -------------------------------- ### Initialize Sphere with Material Pointer (C++) Source: https://raytracing.github.io/books/RayTracingInOneWeekend Updates the `sphere` constructor to accept and store a shared pointer to a `material` object. This allows spheres to have different surface properties, such as being metallic or diffuse. The `mat` member variable is initialized with the provided material pointer. ```cpp #include "hittable.h" #include class sphere : public hittable { public: sphere(const point3& center, double radius, std::shared_ptr mat) : center(center), radius(std::fmax(0,radius)), mat(mat) {} // Other members and methods... private: point3 center; double radius; std::shared_ptr mat; }; ```