Raytracing is fun

Have you ever heard of ray tracing?
If you are a graphics enthusiastic gamer, you probably heard of it.
It's a famous method of making photorealistic CGs.

Let me show you some of CGs that I have created with ray tracing.
When I showed these images to my friends, They all said "It's completely a photo".

I used realworld images as a background lighting environment so it's partially true, but these glass balls, diamond and floors are completely artificial.

So how can we get these photorealistic CGs?
The answer is to do a physics simulation of light transportation.

I will describe the overview of how to do a simulation following pages. I don't mention about each term's mathematically strict definition, So please consult other pages if you want to understand it strictly(I will write more concrete version someday).

The basic idea is like this.
There is an eye and a screen in the world, your task is to compute the color at the screen position $p$.

Let's denote the amount of light which comes from the direction $\omega$ to the screen position $p$ as $L(p, \omega)$, then we need to calculate this $L(p, \omega)$.

Calculation of $L(p, \omega)$


If you keep drawing the line from the screen position $p$ into the world, the line intersects with a object in the world at some distance, this line is called "Ray".
Let's denote the intersection point as $p_1$ and the amount of light emittance from $p_1$ to $p$ as $L(p_1, \omega_1)$.

If the air is assumed to be a vacuum, the attenuation of light between $p$ and $p_1$ does not happen, so
$$L(p, \omega) = L(p_1, \omega_1)$$

Then our initial task is converted to calculate $L(p_1, \omega_1)$.

What determines the value of $L(p_1, \omega_1)$?

BRDF


The reflection property of the object is very important. If it absorbs the red and blue light, It should be looked like green, It it is a mirror, the incident light should be reflected in the particular direction.

The reflection property can be modeled using "Bidirectional Reflectance Distribution Function(BRDF)". BRDF represents the amount of reflected light for particular in-direction and out-direction.

Let in-direction denoted as $\omega_i$, out-direction $\omega_o$ and the position where reflection occurs $x$, BRDF is represented as $f(x, \omega_i, \omega_o)$

Using BRDF, the amout of reflected light $L(x, \omega_o)$ from particular incident light $L(x, \omega_i)$ is calculated as
$$L(x, \omega_o) = f(x, \omega_i, \omega_o)L(x, \omega_i)\cos{\theta}$$
where $\theta$ is the angle between $\omega_i$ and surface's normal.



Incident Light


Using BRDF, We can now calculate the reflected light $L(x, \omega_o)$. But It only considers one particular in-direction $\omega_i$.

The incident light comes from every direction above the surface. So we need to calculate $L(x, \omega_o)$ for each incident light and sum them up.

This operation is represented by integral.
$$L(x, \omega_o) = \int_{\Omega} f(x, \omega_i, \omega_o)L(x, \omega_i)\cos{\theta}d\omega_i$$
where $\Omega$ represents every direction above the surface.


The Rendering Equation


The object possibly emits the light at $x$. I denote it as $L_e(x, \omega_o)$.
Summing up the reflected light and emitted light, We get the famous rendering equation.
$$
L(x, \omega_o) = L_e(x, \omega_o) + \int_{\Omega} f(x, \omega_i, \omega_o)L(x, \omega_i)\cos{\theta}d\omega_i
$$

Every rendering softwares like Blender's Cycles, Arnord Renderer tries to solve this equation and get amazingly photorealistic CGs.

It's a recursive integral equation. The right term's $L(x, \omega_i)$ is another rendering equation.



1 recursion corresponds to 1 reflection, and 2 recursion corresponds to 2 reflections. So if you want to calculate $L(x, \omega_o)$ considering 100times reflected incident light, you need to calculate 100-dimensional integral.

It's a computationally difficult problem. If you are familiar with numerical integration, you probably try to integrate it using the trapezoidal rule.


But it's a 100-dimensional integral, if you divide each dimension as 10 samples, the amount of whole sample is $10^{100}$. Even if you use the fastest super computer, It takes very long time to finish the calculation.

Montecarlo Integration

So how can we solve the rendering equation in reasonable time? There are several methods to solve the rendering equation. The most popular method is "Path Tracing".

Path Tracing uses Montecarlo Integration to evaluate the integral. It randomly selects the incident direction and calculate $L(x, \omega_i)$. 


If you want to consider 100times reflected light, you need to evaluate $L(x, \omega_i)$ 100 times. It is significant reduction of computation compared to the trapezoidal rule.

If you run that calculation, you will get an very noisy image like this.


This is because the whole $\Omega$ is not searched. To reduce the noise, You need to iterate the calculation and average it, that gives you an statistically correct image.


To implement it by youself


If you want to implement path tracing by youself, reading Peter Shirley's "Ray Tracing in One Weekend" is a good start!

Most of people use C++ to implement a raytracer because it runs fast, but any languages you like can be used.

If you are interested in my implementation, there is a github repository.
https://github.com/yumcyaWiz/Photorealism

Comments