In this project, I continued implementing the ray tracer to make the rendered image closer to real scene. Specifically, I first implemented the reflection and refraction property of BSDF so that the image is able to represent mirror and glass materials (see Part 1). Then I added the reflection property of the conductors, which is to implement the microfacet materials’ BRDF. To make the sampling suitable for Beckmann distribution, I also implemented the importance sampling (see Part 2). Another useful scheme is to use environment lighting, where I implemented texture mapping by uniform sampling, and to reduce the render variance, I also implemented the 2D texture map importance sampling (see Part 3). In Part 4, I move forward from the pinhole mask model by using a thin lens as the camera, and thus we have the focus effect.
In this article, I use s to denote the sample rate per pixel, l to denote the sample rate per light, m to denote the max depth, d to denote the focus length, and b to denote the radius of the lens.
Part 1: Mirror and Glass Materials
The main purposes in this part are to implement the reflection and refraction function of BSDF, and “combine” them for material like glass that has a combination of both properties.
Because we do ray tracing and we generate ray from camera to the scene as before, all the input and out put ray is opposite to the mark of the variables. The reflect funtion takes wo as input and reflect by normal (0, 0, 1) and save the reflection result to wi.
As for refraction, what we need to do is to implement using Snell’s Law. As shown in the figure, we use this geometry relationship to map the refract ray’s values from the input ray. One to pay attention here is to calculate the eta value based on the entering or existing direction because eta is related to the n value of the material. We separate the two situation by checking the sign of the z coordiante value. The other thing to pay attention is the situation of whole reflection where no refraction takes place, and we check is by the sign of 1 – eta * eta * (1 – wo.z * wo.z).
When combining the two, we use the Schlick’s approximation to decide whether to use the sample point for reflection or fraction based on the Schlick’s reflection coefficient R. For either case, we need to assign the pdf to the correspoding probability R or 1-R.
2: Result (s = 64, l = 4)
The bounce condition of the following images:
On the whole, the scene becomes brighter and more light noises. m = 0: we can see only the first bounced light, which is the diffuse bounce light from the walls. m = 1: we can see the scene of two bounces, where we can see the diffused light from the walls reflected by the ball and hit the camera. Specifically, the ball in the back (because it’s a mirror ball) we can see the reflected scene, but for the ball in the front, we can only see the small part of reflected scene, because this glass ball has much refraction but we haven’t allow that depth so we couldn’t see, which is the reason why it is so dim. m = 2: we can see the refraction of the front ball, because we let the scene behind it first (bounce) enter the ball and then second (bounce) exit the ball and captured by the camera. Fraction takes one more bounce to flection of a same ball because for refraction it need to hit the ball and then exit the ball, but reflection only need to hit the ball. m = 3: last time, we also allow the delta light ray enter the ball and exit the ball, and hit the ground. This time, we add another bounce, the the light hit the ground and then reflect to the camera, and we can see. m = 4: this time we can also see the light on the right wall, which is first enter the ball, second exit the ball, third reflect from ground, and fouth relfect from wall, altogether four bounces to eye. m = 5: there is less different we can notice here, just a little bright. m = 100: not much different than m = 5, which means the light rays contains less and less power after 5 bounces and we can hardly notice.
|m = 0||m = 1|
|m = 2||m = 3|
|m = 4||m = 5|
|m = 100|
Part 2: Microfacet Material
Microfacet material is something related to micro scale observation of the surface. In the former parts, we treated a surface as smooth because we only observe it as wavelength scale which is relatively large. In this part, we use micro scale and we can see the rough surfaces and should do the reflection / shadowing by the local property.
In this part, we use the BRDF evaluation function to implement the microfacet properties which includes the Fresnel term, the shadowing-masking term, and the normal distribution function.
Instead of just use cosine hemisphere sampling to get wi and apply it to the evaluation function above, we can also use importance sampling. As for the importance sampling, it is used to fit the Beckmann distribution. What we need to do sample is to find by sampling is the half vector h which is the middle of wi and wo. We do this by sampling theta_h and Phi_h according to their pdfs, and calculate the h. Also, we need to calculate the pdf for wi by the pdf of h, and we calculate the pdf for h by the pdfs we used to generate theta_h and phi_h.
2: Results for different alpha
alpha is the parameter to tune the smoothness of the surface as we discribed before. When alpha is small, the surface is relatively smooth, and when alpha becomes larger, the surface becomes rougher.
|alpha = 0.005||alpha = 0.05|
|alpha = 0.25||alpha = 0.5|
3: Results for importance sampling and cosine hemisphere sampling
Since the distribution here is not a diffuse one, the reflected light is not evenly distributed in all direction. Even if we use importance sampling, we are following a wrong pdf. If we continue with a cosine hemisphere sampling, we can sample many parts again and agin but for some other directions with high propability to happen, we just sample them rarely. In this way, more sample points will be needed to cover these directions and generate a good image. What we want is to modify is to use the correct pdf funtion to do the importance sampling, which is dicribed above. From the results below, we can see is: given same sampling rate, the importance sampling Beckmann distribution have a better image with less noise, which shows it is more efficient and takes less to converge.
|Importance sampling Beckmann distribution||Default cosine hemisphere sampling|
4: Results for other materials
In this following I show a result using the silver material. To get the k and eta value, we need to query with different wavelengthes of R, G, and B.
Part 3: Environment Light
The uniform sampling just do bilinear mapping to the texture image of the environment, which is straightforward.
The importace sampling generate the 2D pdf which we use to get the coordination (x, y) to do the same mapping as uniform of the texture map. To implement the importance sampling in 2D, what we need to pay attention is to generate the marginal distribution to find the y value and the conditional distribution to find the x value after we get the y value. To calculate the probability distribution, we use the default formula.
To get the sample value from the pdfs, we use the inversion method as taught in lecture. We implement this method by using the upper_bound function. The marginal distribution and the conditional distribution already give the accumulated probability function and what we need to find is the sample value that gives the value of the input which we sample uniformly. Because the distribution is descrete, we use the upper_bound function to find the index. But the function does not return the index, so we need to subtract the beginning index. Since the distribution array is not a vector and we cannot use the begin() and end() funtion, so we need to calculate by the pointer to the array, especially for the conditional distribution where each line is accumulated from 0 to 1.
2: Probability image
The probability image helps us to debug.
3: Results for environment light (s=4, l=64, m=5)
Since there is no glossy BSDF for the top two models, they will not reflect the environment. The copper one can reflect the environment and the base of the rabbit. The difference between uniform sampling and importance sampling is not obvious.
|Uniform sampling||Importance sampling|
|Uniform sampling||Importance sampling|
Part 4: Depth of Field
Use s=128, l=4, m=5, and b=1.23 to render. Set different focus distance. As can be seen, the clear part is moving backward from image to image.
|d = 4.56||d = 4.68|
|d = 4.80||d = 4.92|
Use s=128, l=4, m=5, and d=4.56 to render. Set different diameter of lens. As can be seen, as the aperture size going large, the image is more blurry.
|b = 0.23||b = 1.23|
|b = 2.23||b = 3.23|