RSSAmplifier

Blog

My thought repository

Recent content on My thought repository

nelari.usRSS feed ↗19 posts

Latest posts

Voxel Raytracer Devlog

Performance interlude 2 2026-08-16 This update doesn’t contain changes to vxray. While the spatially cached RTAO both looks better and improves performance, the performance on the Macbook Air (M2) is still not amazing when moving around the interiors of the Sponza scene compared to before. A look at the Metal profiler timeline reveals that the RTAO hashmap update pass takes the most time…

Projects

Here is an overview of some of the bigger software projects I’ve worked on in my free time. Polycube A small, simple, voxel editor written from scratch in C. Posting intermittent updates about the project at https://bsky.app/profile/nelarius.bsky.social. Features: voxel editing with single voxel, box, and face extrusion brushes. a UI written using the Clay box layout library resulting in…

Experiments with wavefront ray tracing on Apple silicon

Books, articles, and blog posts present the wavefront renderer architecture as a way to improve ray tracing performance on GPUs. In practice, it’s difficult to find information on whether I should expect performance improvements for my monolithic kernel hobby renderer on Apple’s M1, M2, or M3 chips—the latter having hardware-accelerated ray tracing. On Apple hardware, would switching…

Pathtracing tidbits: integrating animated blue noise

Alan Wolfe’s paper, “Using Blue Noise for Ray Traced Soft Shadows”, presents a great method for reducing the perceived noise in soft shadows. It can be readily adapted to a path tracer as well, where it will yield images with better clarity, even with only a few samples. Take a look at an image rendered with regular RNG white noise in the left half, and blue noise in the right…

Embed data into C byte arrays at build time

Not having to deal with loading data from a bunch of small files makes it easier to work with your executable. You can forget about the working directory, just run your app or tests or benchmarks! Alternatively, if you need to ship a library which needs to access stored data, this is also one way of distributing the data with the library. This post contains notes about embedding arbitrary data,…

A quick look at Apple Silicon's hardware accelerated ray tracing performance

To develop my main ray tracing renderer project, I have been working on a Macbook Air with an M2 chip. The renderer’s performance on the laptop has not been great, with frame rates in the decimals at fullscreen resolutions. The M3 chip was introduced fairly recently (half a year ago at the time of writing) with support for ray tracing in the hardware. Anectodally, I have seen reports of 100…

Notes on C++ initialization

After getting back into hands-on programming with C++ after a long break, I reached for the shiny new way of doing aggregate initialization, called designated initializers. In two short weeks of writing code, I managed to shoot myself in the foot due to incorrect assumptions about the ways that initialization work. I reviewed some of the details of initialization, and developed some guidelines…

GPU Pathtracer Devlog

This post is a devlog for my rayfinder project. Follow along to see the progress, starting from scratch by opening a simple window. First step towards temporal filtering: simple accumulation 2024-06-24 Commit: 29eebc8 The first step towards temporal accumulation with a moving camera is implemented. The reference path tracer previously implemented temporal accumulation, but only when the camera was…

Weekend raytracing with wgpu, part 2

The first part of “Weekend raytracing with wgpu” left us with a basic implementation of Peter Shirley’s first book in the series of “Ray Tracing In One Weekend " books. “Ray Tracing: The Next Week” introduces additional features, such as texture support. This post takes a look at adding a physically based sky model, in addition to adding textured material…

Weekend raytracing with wgpu, part 1

Peter Shirley’s book Raytracing In One Weekend is a great way to kickstart your own path tracer. The book gives just enough information to get spheres rendered to your screen, minimizing the amount of time spent studying theory. I wrote a straightforward implementation of the book’s renderer using Rust many years ago. Recently, I decided to go the extra mile and port the code to the GPU,…

Using inverse transform sampling to generate random numbers in a given distribution

In inverse transform sampling, we use the inverse cumulative distribution function (CDF) to generate random numbers in a given distribution. But why does this work? This post attempts to demystify inverse transform sampling works by plugging samples from a distribution into the same distribution’s CDF and verifying that we get numbers with a uniform distribution in \([0, 1]\). Let’s…

Quick and dirty image dithering

Introduction Dithering is a fascinating and seemingly counter-intuitive technique. In order to demonstrate the technique, take a look at the following image. How many different shades of gray do you see in the picture? How many did you guess? The answer is 2. Taking a closer look, we begin to see the pixels. The original image is quantized to just two colors, fully black and white. How can an…

Generating 3d buildings using node graphs

There are many different ways to generate 3d models. Software like Blender gives you a pile of tools and modifiers with which you can model almost any object. Then you have your sculpting editors with which you can model complex organic shapes, as if you were modeling with clay. Finally, you have procedural modeling tools with which you can generative repetitive 3d geometry using simple rules. I…

Writing a small ray tracer in Rust and Zig

I spend most of my programming time writing C++. And like many other C++ programmers, I’ve shot myself in the foot countless times with a feature I didn’t fully grok. And I’ve spent enormous amounts of time trying to understand the language. Like many other C++ developers in this position, I find myself frequently daydreaming about switching to another more modern and easily…

imnodes: writing an immediate mode node editor library

Node editors are one of the more discussed use cases for the dear imgui UI library, and there are lots of gists as well as fully-fledged implementations for them on Github. If you want to implement your own node editor, you can get cracking! However, my pet peeve with the available samples and implementations is that they often aren’t immediate mode and don’t obey dear imgui’s…

About me

Hi there! I’m a software engineer based in Helsinki, Finland. I’m currently working on map rendering topics at Mapbox. I’ve previously worked on courier routing algorithms at Wolt, as well as computer graphics middleware at Umbra. I’m currently interested in ray tracing and C programming. Checkout some of my projects here or on Github!

Embedding Wren in C++, part 2

You can read part 1 here. Writing you own Wren bindings gives you full control over how your code interfaces with Wren. However, manually implementing the binding code for a large C++-Wren interface can be somewhat time consuming, especially when changes are made to the interface over time. Wren++ is a small C++ library that aims to automate most code binding tasks with a minimal runtime overhead.…

Embedding Wren in C++, part 1

Wren is a small, fast, class-based scripting language designed to be easily embeddable in a host application. As such, it fills very much the same niche as Lua. Why would you choose Wren over Lua in your application? It boils mostly down to stylistic preferences. Wren is very class oriented, and adheres to the curly-brace style tradition, in contrast to Lua’s begin...end blocks. If one of…

Placing an arbitrary number of function calls into a function argument list using templates

While I was trying to generate code to bind C++ to a scripting language, I discovered that C++ templates, in their current modern form, are not as scary as I used to think they were. Here are a few useful things that I discovered. First, in toy form, the problem that I was trying to solve. Suppose I have a free function that I want to bind to a virtual machine.