Coursework III:

Path Tracing

COMP0027 Team

Tobias Ritschel, Michael Fischer, Pradyumna (Preddy) Reddy, David Walton

November 28, 2022

We have shown you the framework for solving the coursework at https://uclcg.github.io/uclcg/.

You should start by extending the respective example there. The programming language is WebGL

(https://www.khronos.org/registry/webgl/specs/latest/1.0/) and the OpenGL ES Shading Language

(GLSL) www.khronos.org/files/opengles_shading_language.pdf. This should run in any browser, but

we formerly experienced problems with Safari and thus recommend using a different browser such as Chrome.

Do not write any answers in any other programming language, in paper, or pseudo code. Do not write code

outside the #define blocks.

Remember to save your solution often enough to a .uclcg file. In the end, hand in that file via Moodle.

The total points for this exercise is 100.

Please refer to Moodle for the due dates.

Introduction We have prepared a simple path tracing framework you would be asked to extend. The

framework is very similar to the solution of the first coursework (ray-tracing), just that we removed cylinder

intersections and point lights.

As in the previous coursework, we proceed in an artificially-low resolution for two reasons: Slow computers

and in order to allow you to see individual pixels to notice subtle effects. The new revision of the framework

allows to change the resolutions with a new button.

The path tracer is progressive: It will permanently run when loaded and compute a new sample at each

pixel. The result already gets averaged over time by the framework. The solution will be reset every time

you change the code. To add new iterations, press the play or stop buttons in the web page. The current

solution will run for 1000 samples.

The results are also tone-mapped and gamma-corrected. Typically, you do not need to change the code in the

tab “Tonemapping” to solve the coursework. Modifying it might help for visual debugging in some cases,

though. Tone-mapping will reduce the physical light values to a range your display can actually reproduce and

that appears most plausible visually. Gamma-mapping will convert physically linear units your simulation

produces into non-linear values your display expects. If you know the gamma value of your monitor, you can

change the γ = 2.2 we assume to something better to see more details in light or shadows (some machines go

as low as γ = 1.6 these days).

1

1 Let there be light! (5 points)

In the beginning you will see only the diffuse colors.

First, extend the Material struct to hold the information that every material in path tracing has to have

to become a light source (2 points). For our example, the first sphere should become a source emitting

150.0 · (0.9, 0.9, 0.5) units of light, the second should emit 150.0 · (0.8, 0.3, 0.1) and all other object should

not be light sources. Second, use this information in getEmission (1 points). You now should now see the

direct light as seen below. Write two sentences about what the gamma is doing in our case (2 points).

COMP0027 (Computer Graphics) 2

2 Now bounce (10 points)

The current code is only able to render the first bounce of light between the object and the camera. We will

now add multiple bounces.

To do so, first implement the function randomDirection to return a random direction in 3D. Param-

eter to this function is the dimensionIndex of the bounce. The i-th bounce’s sampling dimension is

PATH SAMPLE DIMENSION+2 i. This index will later be used in advanced (e.g., Halton) sampling that proceeds

differently in different dimensions.

The lecture has explained how picking a random 3D point in the unit cube and normalizing it is not a valid

solution. Instead, you should use the formula below to compute a vector ωi = (x, y, z), where ξ0 and ξ1 are

random sample coordinates in (0, 1) provided by our function sample (2 points).

θ = arccos(2 · ξ0 − 1)

φ = ξ1 · 2pi

x = sin(θ) cos(φ)

y = sin(θ) sin(φ)

z = cos(θ)

The formula above has two logical parts, can you indentify them? Implement the formula by calling two

separate functions (1 points) instead of one go and give them proper names (1 points). What would be a

unit test of this, that was to involve a third function and what is that third function? (2 points). Implement

this test and describe how it would be ran by setting a simple flag (2 points).

Next, you need to use this function to trace a ray in the direction ωi. The function intersectScene, similar

to the one used in the first coursework, is at your disposal to do so (2 points).

Please use the constant const int maxPathLength defined on the top to control the maximal length of the

path you sample. At maxPathLength = 2, the image should look as the one below:

COMP0027 (Computer Graphics) 3

3 Throughput (30 points)

The current solution solves an alternative, non-physical equation that misses the reflectance and the geometric

term:

L(x, ωo) = Le(x, ωo) +

∫

0.1 · L(y,−ωi)dωi

What it should solve instead is an equation that include the BRDF and the geometric term:

L(x, ωo) = Le(x, ωo) +

∫

fr(x, ωi, ωo)L(y,−ωi) cos(θ)dωi

First, implement the function getGeometricTerm (5 points) and getReflectance (5 points) using the

(physically-correct) Phong BRDF. Physically-correct Phong is a variant of Phong that uses the normalization

factor n+2/2pi to preserves energy for all values of glossiness n.

fr(ωi, ωo) =

kd

pi

+ ks

n+ 2

2pi

(〈ωo, r〉+)n

Implementing both methods will not yet change something, as they are not called. Second, those functions have

to be multiplied up correctly to compute the throughput of every light path vertex to the camera (10 points).

You might want to remember how the variable weight worked in the backward ray-tracer in coursework 1.

Finally, add comments to explain your implementation of getGeometricTerm and getReflectance and how

you used them to compute the throughput (10 points).

Solving this, a converged image will look the following:

COMP0027 (Computer Graphics) 4

4 Variance reduction: Sampling patterns (20 points)

Currently, we use random numbers using a simple linear congruential generator frand for every pixel. We

have seen how quasi-random patterns, such as Halton reduce variance in the lecture. Here, we will make use

of them.

Change the implementation of sample to use Halton sampling (5 points). Note, how sample takes the

dimension as a parameter. For the frand implementation, this parameter was not relevant, for Halton it will

be. You might find using the existing function prime(int index) that returns the i-th prime number form

a table useful. We do not require you to explain Halton sequences or radical inversion or Van-der-Corput

sequences, as long as you use it correctly.

You will notice the effect by a quicker convergence, less noise, but structural patterns. As both methods

are unbiased, the end-result will be the same. Consider comparing the images with and without the change:

They should be identical.

Let si,j,k be the sample in (0, 1) which our function sample returns for dimension i, sample j and pixel k.

Using the same Halton pattern si,j,k = Hi,j might produce quicker convergence, but leads to structured

patterns you will find objectionable as all pixels k have the same value. Using a uniform random value

si,j,k = ξi,j,k avoids this, but converges slower. The lecture has mentioned Cranely-Petterson rotation to

combine both: in dimension i all pixels use the same pattern Hi,·, but shifted modulo-1 by a random per-pixel

and per-dimension (but not per-sample) offset ξi,k as in s(i, j, k) = fract(Hi,j + ξi,k). Add code for this

improvement (10 points) and explain your implementation (5 points).

5 Anti-aliasing (10 points)

We have seen that other effects such as depth of field, motion blur and anti-aliasing can be understood as

generalized sampling domains. A simple domain to tackle is the pixel domain. Add pixel sampling with

a box filter to produce anti-aliasing (5 points) and explain your implementation (5 points). After adding

anti-aliasing the edges should be nicely blurred as seen in the image below.

COMP0027 (Computer Graphics) 5

6 Importance sampling is important (20 points)

This is more open-ended and advanced questions.

Implement importance sampling for the geometric term (10 points). The below figure shows in the top row an

image with importance sampling and in the bottom row an image without at resolution 256×128 and 10 samples.

What is the most basic job you expect such an importance sampling to do? (1 points). Write a comment in

the importance sampling function.

What is the difference between an importance sampled result and one without it for infinitely many samples?

Make sure your implementation approaches said difference for many (e.g., 10,000 ) samples! (1 points). Write

a comment in the importance sampling function.

Can you demonstrate an extension to multiple light sources (emissive sphere in our case) that have very

different values of emissiveness? Please implement and describe in the way you see fit (6 points).

Can you also propose and implement in a similar way what would be to do if some of those spheres had

positions very different from the positions seen in the framebuffer (2 points)?

7 Motion Blur (5 points)

Add motion blur to the intergator (5 points).

COMP0027 (Computer Graphics) 6

If you give a motion of (−3, 0, 3) to the sphere with index 2 and a motion of (2, 4, 1) to sphere with index 3,

the image will look like this:

COMP0027 (Computer Graphics) 7

欢迎咨询51作业君