# T3 Reflection (Milestone 1)

### T3.1 Calculating the reflection vector in vec3.h

We have introduced how to calculate the reflection vector when introducing the Phong model. The difference here is that we are calculating the reflection vector of the viewing direction.&#x20;

<figure><img src="https://3464970502-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F3JUKGJZ67JX02QZdPhsy%2Fuploads%2FlTLaT3hQWrDGD4tSIKAT%2Fimage.png?alt=media&#x26;token=efd69124-ffd6-43ea-9492-c95ea974cca6" alt="" width="188"><figcaption></figcaption></figure>

Add a function reflect in vec3.h outside the vec3 class

```cpp
// in vec3.h
// calculate the reflection vector of the viewing direction
inline vec3 reflect(const vec3& v, const vec3& n) {
    return v - 2*dot(v,n)*n;
}
```

### T3.2 Add a metal material in material.h

Similar to the lambertian material, it inherits from class material and needs to implement its own scatter() method.

The difference is that it is using the reflected direction instead of a random direction to calculate secondary rays.

```cpp
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
class metal : public material {
  private:
    color albedo;
  public:
    metal(const color& albedo) : albedo(albedo) {}

    bool scatter(const ray& r_in, const hit_record& rec, color& attenuation, ray& scattered)
    const override {
        vec3 reflected = reflect(r_in.direction(), rec.normal);
        scattered = ray(rec.p, reflected);
        attenuation = albedo;
        return true;
    }
};
//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
```

### T3.3 Modify Camera's ray\_color() method for our changes

#### Add a material.h in the header section of camera.h

```cpp
#include "hittable.h"
#include "material.h" // <<<<<<<<<<<<<<<<<<<<<<<<<<<<

class camera {
// ...
};
```

#### Modify the ray\_color() method of class camera in camera.h

```cpp
    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;

        // choose a random direction to perform recursive ray tracing
        if (world.hit(r, interval(0.001, infinity), rec)) {
            //vec3 direction = rec.normal + random_unit_vector();
            //return 0.5 * ray_color(ray(rec.p, direction), depth-1, world);

            // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
            ray scattered;
            color attenuation;
            if (rec.mat->scatter(r, rec, attenuation, scattered))
                return attenuation * ray_color(scattered, depth-1, world);
            return color(0,0,0);
            // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
        }

        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);
    }
```

### Build Your Scene of Spheres in main.cpp

Add material.h before sphere.h.

Adding spheres to your world as suggested.

```cpp
#include "rtweekend.h"

#include "camera.h"
#include "hittable.h"
#include "hittable_list.h"
#include "material.h" // <<<<<<<<<<<<<<<<<<<<<<<<<<
#include "sphere.h"


int main() {

    // =====================================================
    // World

    hittable_list world;

    // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
    auto material_ground = make_shared<lambertian>(color(0.8, 0.8, 0.0));
    auto material_center = make_shared<lambertian>(color(0.1, 0.2, 0.5));
    auto material_left   = make_shared<metal>(color(0.8, 0.8, 0.8));
    auto material_right  = make_shared<metal>(color(0.8, 0.6, 0.2));

    world.add(make_shared<sphere>(point3( 0.0, -100.5, -1.0), 100.0, material_ground));
    world.add(make_shared<sphere>(point3( 0.0,    0.0, -1.2),   0.5, material_center));
    world.add(make_shared<sphere>(point3(-1.0,    0.0, -1.0),   0.5, material_left));
    world.add(make_shared<sphere>(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);

}
```

### Build and Run Your Program

If building is successful, run your program in the terminal as follows using your executable name

```
 ./ray01.exe > image10.ppm
```

You are going to see a lovely photo like the following

You can hardly achieve that mirror reflection with raster graphics.

<figure><img src="https://3464970502-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F3JUKGJZ67JX02QZdPhsy%2Fuploads%2F38tT8aJWZjEeUgjkoChe%2Ff05ce9df-6c94-4027-98bd-bcd5db3a758d.png?alt=media&#x26;token=656972ea-492c-4c3a-ac0e-0d6118484ee7" alt="" width="375"><figcaption></figcaption></figure>

### T3.4 Fuzz reflection (glossy)

Fuzzy reflection is a reflection which is not fullly mirror reflective, it is also calleed glossy. To achieve that we can add noise to the reflection vector.

Add a fuzz parameter to the metal material (material.h)

```cpp
class metal : public material {
  private:
    color albedo;
    double fuzz; // <<<<<<<<<<<<<<<<<<<<<<
  public:
    // metal(const color& albedo) : albedo(albedo) {}
    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 true;
        return (dot(scattered.direction(), rec.normal) > 0); //<<<<<<<<<<<<<<
    }
};
```

Add fuzz parameters in main()

```cpp
    auto material_ground = make_shared<lambertian>(color(0.8, 0.8, 0.0));
    auto material_center = make_shared<lambertian>(color(0.1, 0.2, 0.5));
    auto material_left   = make_shared<metal>(color(0.8, 0.8, 0.8), 0.3); // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
    auto material_right  = make_shared<metal>(color(0.8, 0.6, 0.2), 1.0); // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
```

If successful, you are going to see the following output

<figure><img src="https://3464970502-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F3JUKGJZ67JX02QZdPhsy%2Fuploads%2Fi1S1bGaEwJ3GJoclMqb8%2F171d58b0-21e5-42fd-b89d-b858ed2f941a.png?alt=media&#x26;token=340a4114-6b55-4954-ac57-d98f03f18b30" alt="" width="375"><figcaption></figcaption></figure>
