GPU Adjoint Particle Tracing

Posted by Chang on March 22, 2022 · 1 min read

I spent only one day and a half implementing this adjoint particle tracer in ZillumGL. However, since ZillumGL was originally intended to be a path tracer only, it took me five days to adjust my code framework prior to this implementation. This included creating abstract integrator classes, as in a CPU renderer. Moreover, I separated some common modules in order to reuse among shaders of different integrators, such as ray intersection test, light/camera sampling and BSDF calculation.

Even though the work was generally pretty easy, a problem I met nearly made me give up halfway: native GLSL doesn't support atomic float operation, which is critical for random (and async) radiance accumulation on the film buffer. Luckily, I found a GLSL extension,

GL_NV_shader_atomic_float with
imageAtomicAdd(IMAGE_PARAMS, float data)

making such operation possible (note this extension is only compatible with r32f format images, meaning you have to change your [w, h, rgba32f] buffer image to [w * 3, h, r32f] format to use that function).

It is delightful adjoint particle tracing can be implemented with GLSL. Because this has proved the following goal, a naive GPU bidirectional path tracer, has virtually no other technical obstacle than random buffer accumulation.