Another year, another Hacktoberfest. Hacktoberfest is an event meant to promote open source involvement. This year, I created a basic ray tracer and also contributed to a Prometheus exporter.

Ray tracer

My ray tracer is implemented in Golang without any dependencies and is heavily inspired by the C++ code from the book "Ray Tracing in One Weekend". It was satisfying to work on something that produces a visual result for a change.

The ray tracer uses unbiased monte-carlo sampling. It supports different materials with tunable properties. They mainly differ in light color absorbtion (albedo) and scatter behaviour (diffuse, metalic, reflective, glass). The available shapes are spheres, triangles and infinite planes (useful for the ground).

Rendering is multithreaded. The number of samples per pixel (rays simulated for each pixel) is configurable. To divide the work across workers, the total samples per pixel number is divided by the number of workers. Every worker renders a separate image with the same number of samples per pixel. The images are combined afterwards, yielding an image with the requested number of samples per pixel in total.

Ray tracer example image with different materials
Ray tracer example image with different materials

I implemented a minimal object file format loader that supports vertices and faces, making it possible to load arbitrary models. The cube below was loaded from an object file. It consists of two triangles for each face.

Ray tracer example image with different shapes (triangles, sphere and infinite plane)
Ray tracer example image with different shapes (triangles, sphere and infinite plane)

However, rendering complex models is infeasible because rendering takes too long. I started implementing an acceleration structure, an axis-aligned bounding volume hierarchy, as described in Ray Tracing: The Next Week to improve performance. Without an acceleration structure, each light ray has to be checked for intersections with every single object in the scene. This brute force approach is too slow for complex models that consist of a large number of triangles. I didn't manage to finish the acceleration data structure in October.

Harbor Prometheus exporter bugfix

Aside from implementing the ray tracer, I also fixed a socket leak in a Prometheus exporter. The exporter provides metrics for the container registry Harbor. The socket leak was caused by instantiation of a new HTTP client in each scrape request. The dangling connections used up memory in kernel space causing the OOM killer to terminate the exporter process after some time. There were multiple issues complaining about the nearly unbounded growth of memory usage and my employer was affected also.

Hacktoberfest projects are now opt-in

Sadly, there were problems with people spamming repositories with unsubstantive pull requests to get a Hacktoberfest t-shirt without real contributions. The Hacktoberfest organizators reacted by making Hacktoberfest opt-in only for projects and maintainers. I feel this is a very effective measure.

Conclusion

Hacktoberfest was a lot of fun once again. As always, I learned a lot. Working on something that produces a visual result made the progress tangible. I was amazed how simple a basic ray tracer is conceptually. However, implementing a performant ray tracer is a different challenge. There is a huge number of techniques and approaches with different trade offs. For example, rays can be biased towards light sources to reduce the number of rays required for a render without grainy shadows.