Project Scrapbook

This page serves as a scrapbook of a selection of the various software project I have worked on over the years. Some of these are hobby projects while others were made in an academic or professional context.

1. Realtime GI Using Surface Cache + Final Gather (2021)

In this project I maintain a temporally integrated surface cache encoded as UV-mapped lightmaps. The fact that the cache can resample itself over time means that I can approximate infinite bounces using relatively few rays per frame. Inspired by Epic's Lumen, I do a screenspace final gather on top of the surface cache which is filtered temporally and spatially. The final gather affords camera-dependent resolution of secondary rays, something that would not have been possible using the surface cache alone.

The renderer supports dynamic lights and dynamic geometry. It is written in Rust and Apple Metal, and it runs smoothly on a Macbook Air M1 (without a discrete GPU).

Fig 1: The UV-mapped surface cache works particularly well with low-poly scenes.
Fig 2: A somewhat challenging scene with a small non-analytical light source.

2. Realtime Constructive Solid Geometry Pathtracer (2021)

A Constructive Solid Geometry realtime pathtracer that utilizes temporal and spatial filtering techniques to eliminate noise. In each frame each pixel samples the rendering equation integral (several bounces) and accumulates the results via a Moving Exponential Average. The output is then denoised via my adaption of SVGF.

The pathtracer supports realtime changes to geometry and lighting. In addition to diffusely bounced light, I added support for volumetric fog (extinction + in-scattering), day/night cycle, simple color grading, and a subtle vignette effect. It runs at 60fps on a Macbook Air.

Fig 3: Constructive Solid Geometry affords manipulations that are not trivial to do with polygons.
Fig 4: A minimalistic CSG remake of Sponza that showcases day/night cycle and volumetric fog.

3. Realtime Sky Occlusion Using Voxel Tracing (2020)

At a Unity hackweek our team made a Minecraft clone. Inspired by Teardown I implemented realtime voxel traced sky occlusion on the GPU and integrated it into Unity's Universal Render Pipeline.

We adopted a sparse data layout that significantly reduced memory usage by not storing anything in empty regions of the world.

Fig 5: Demonstration of the effect. I did not have time to do denoising.
Fig 6: Comparison of Unity's screen space ambient occlusion (SSAO) and our effect.

4. Realtime GI Probes Using SDF Textures (2020)

In this hobby project I used Monte Carlo integration to calculate irradiance probes across several frames. I automatically generated a 3D SDF texture to enable fast raytracing on the GPU. The probe data was encoded using a sphere-to-square octahedral projection to ensure efficient per pixel sampling during shading.

The renderer was written from scratch in Rust and Metal. It was heavily inspired by SDFGI (Linietsky) and DDGI (Majercik, Guertin, Nowrouzezahrai, McGuire).

Fig 7: As the directional light moves, the irradiance probes update accordingly in realtime.

5. Realtime Occlusion Probes Using SDF Textures (2020)

At Unity Hackweek 2020 my group and I implemented GPU raymarching of signed distance fields stored as 3D textures. We used this to generate directional occlusion probes in realtime.

Fig 8: Occlusion probes are updated in realtime by raymarching a SDF 3D texture.

6. Hobby CPU Pathtracer (2020)

I started this project to solidify my understanding of pathtracing, BRDFs, and importance sampling. A few highlights:

Fig 9: Cornell box with dielectric, diffuse, and specular materials.

7. Bachelor Thesis: Evaluation of Spherical Function Bases (2019)

In realtime computer graphics we are often interested in compressing sets of spherical functions such as an irradiance field. In my thesis I evaluated and compared several known spherical function bases such as Spherical Harmonics, Spherical Gaussians and Ambient Cubes. The result was a set of recommendations about which encoding techniques to use for particular types of signals (irradiance, radiance, occlusion/visibility, etc.).

I received the maximum grade for my report and defence. You can read the thesis here.

Fig 10: A graph from the report's analysis section that shows RMAE vs space requirements for various bases.
Fig 11: SH illustrations from the report's theory section.

8. Lightmap Denoising Using Machine Learning (2019)

A machine learning-based denoiser can smooth out variance in lightmaps caused by low sample counts. This allows you to generate good-looking lightmaps much faster since you do not need to wait for convergence.

At Unity Hackweek 2019 my group and I ported the Intel Open Image Denoiser to Unity's Barracuda platform which enabled it to run on the GPU. Our primary goal was to learn about machine learning denoising.

Fig 12: A lightmapped scene before (top) and after (bottom) denoising.

9. GPU (CUDA) Pathtracer With Adaptive Sampling (2018)

For our final assignment in a course about parallel computation at university, my group and I wrote an adaptive GPU pathtracer written in C++/CUDA. The pathtracer detects converged pixels and removes them from the working set. Our primary focus was to make this detection and reduction logic as efficient as possible on modern GPUs.

Fig 13: Rendering of animated directional light in GPU pathtracer.
Fig 14: Visualization of per-pixel convergence.

10. Spatially Coherent Lightmaps in Unity (2018)

Lightmap baking involves packing all lightmapped object into a set of lightmaps. I devised and implemented a stable packing algorithm that bundled object that were nearby in world space into the same lightmaps. The benefit of this is that it makes it possible to batch draw calls more efficiently at runtime.

Due to other priorities at Unity, this feature unfortunately never shipped.

Fig 15: Before and after enabling spatially coherent packing (color denotes lightmap index).

11. Explicit Shape Sampling in Unity's Progressive Lightmapper (2018)

For Unity Hackweek 2018 my group and I added explicit sampling of disk/sphere/line lights in Unity's progressive lightmapper.

Fig 16: Unity's progressive lightmapper with explicit sphere sampling.

12. Lightmap Seam Stitching (2017)

A known problem with lightmapping is seam artifacts along the borders of the UV islands that are neighbours in object space but separated in lightmap space. To solve this problem in Unity, I implemented a technique that "stitches" together the seams by performing a least square error minization over the border texels of the UV islands. My solution to this was heavily inspired by Naughty Dog and Sebastian Sylvan.

Fig 17: Seam stitching on lightmapped sphere.
Fig 18: Seam stitching on lightmapped terrain.

13. Networked Lockstep Synchronization (2016)

An implementation of the lockstep synchronization algorithm used in some types of networked games. By making the simulation (collision detection etc.) fully deterministic on the client, you only need to transmit player actions across the network (as opposed to continuously transmitting the full server state).

Fig 19: Deterministic simulation synchronized over TCP (original is 60fps).

14. Hobby Engine (2015)

For fun and educational purposes I wrote a game engine from scratch in C++/OpenGL. A few highlights:

Source code is available on Github.

Fig 20: Sped-up day/night cycle in my hobby engine.