Raytracing - Diffuse Materials

Finish reading Ray Tracing in One Weekend (RTIOW) Chapter 7. Worked through the algorithm of simulating diffuse material with raytracing. Breakdown topics of diffuse reflection, random reflecting ray generation and rejection sampling in unit sphere.

Diffuse Material and Diffuse Reflection

Object with a diffuse material doesn’t emit light but take on the colors from the surroundings(background/sky light), and modulate (alter the amplitude or frequency of an electromagnetic wave or other oscillation in accordance with the variations of a second signal, typically one of a lower frequency) the colors with its own intrinsic color.

The visibility of objects, excluding light-emitting ones, is primarily caused by diffuse reflection of light: it is diffusely-scattered light that forms the image of the object in the observer’s eye. Another term commonly used for this type of reflection is “light scattering”.

The light that reflects off a diffuse surface has its direction randomized.

Diffuse reflection is the reflection of light from a surface such that a ray incident on the surface is scattered at many angles rather than at just one angle as in the case of specular reflection.

An ideal diffuse reflecting surface is said to exhibit Lambertian reflection, meaning that there is equal luminance when viewed from all directions lying in the half-space adjacent to the surface. More technically, the surface’s luminance is isotropic, and the luminous intensity obeys Lambert’s cosine law.

In RTIOW we are using a simple algorithm to approximate mathematically ideal Lambertian reflection.

Figure: The rays represent luminous intensity, which varies according to Lambert’s cosine law for an ideal diffuse reflector.

Also the light got absorbed a lot rather than reflected, and this is called attenuation that caused by light scattering. The darker the surface is the more light-absorption (eg. Vantablack is the darkest artificial substance known, absorbing up to 99.965% of radiation in the visible spectrum).

Simulating Diffuse Material With Raytracing

Now with all the rays that are generated from the origin shooting onto the object, how can we calculate the reflected rays? Since the reflected light direction on diffuse surface is randomized, now we need to generate this random direction to build the reflecting ray.

The solution is to add a small random vector onto the normal vector.

Algorithm Breakdown

Build Random Reflecting Ray

From the point $P$ where ray hit on the sphere, we form a unit sphere that is tangent to this hitpoint. $\vec{N}$ is the surface normal at $P$.

Next we need to form another unit sphere centered at ray/view origin (simple on calculation, also will prevent reflecting direction from pointing into the sphere), and pick a random point $S$ in this unit sphere to build the small random vector $\vec{E}$. With all of them we can calculate the point $R$ (vec3 target) which is on the random reflecting direction:

Then from $P$, we build another ray with the reflecting direction to shoot to next object, and repeat this process again and again, until it has nothing to hit on. At this moment we return the color of the background.

vec3 color(const ray& r, hitable *world){
    hit_record rec;
    if(world->hit(r, 0.001, MAXFLOAT, rec)){
        vec3 target = rec.p + rec.normal + random_in_unit_sphere();
        /* for random_in_unit_sphere() see next section */
        return 0.5 * color(ray(rec.p, target-rec.p), world); // * 0.5
        // return background color

Light Attenuation

Note that every time the ray reflect, we multiply a value 0.5 (light bouncing rate) to the color to simulate the absorption of the light (light attenuation) when it bounces around diffuse materials.

bouncing rate 10%

bouncing rate 50%

bouncing rate 90%

Rejection Sampling In Unit Sphere

To find this random point $S$ in a unit sphere, we are using the easiest algorithm rejection method.

An example in 2D case:

As a simple geometric example, suppose it is desired to generate a random point within the unit circle. Generate a candidate point $(x,y)$ where $x$ and $y$ are independent uniformly distributed between −1 and 1. If it happens that $x^{2}+y^{2}\leq 1$ then the point is within the unit circle and should be accepted. If not then this point should be rejected and another candidate should be generated.

For each x, y, z coordinates, choose a random value of a uniform distribution between [-1, 1]. If the length of the resulting vector is greater than one, reject it and try again.

vec3 random_in_unit_sphere(){
    vec3 p;
        p = 2.0 * vec3(drand48(), drand48(), drand48()) - vec3(1,1,1);
    } while (p.squared_length() >= 1.0);
    return p;