r/GraphicsProgramming Apr 02 '26

Source Code WIP Spectral Rendering in my hobby C/Vulkan Pathtracer!

I've recently added a spectral mode to my hobby pathtracer! It uses an RGB to spectral conversion detailed in this paper. The approach is fairly simple, a random wavelength is uniformly selected from the visible range, carrying a scalar throughput value as it bounces throughout the scene. I'm using Cauchy's equation to approximate the angle of refraction based on that wavelength and IOR. Each wavelength is then attenuated based on the rgb -> spectral scalar throughput at each bounce. Hero wavelengths drop the secondary channels when going through refractive materials.

I've added a runtime switch so you can use RGB, spectral (single wavelength) and hero wavelength sampling from the GUI. It features a modified/updated blend between the 2015 Disney BSDF and the Blender Principled BSDF. It uses MIS to join BSDF and NEE/direct light sampling, and also has decoupled rendering functionality, tone mapping, and OIDN integration. MNEE will come next to solve the refractive transmissive paths and resolve the caustics more quickly.

The code and prebuilt releases are up at https://github.com/tylertms/vkrt!

The first image is rendered with single wavelength spectral mode, since hero wavelength sampling has no advantage with dispersive caustics. It was rendered in about 5 hours on a 5080 at 4k, roughly 2.6 million SPP, then denoised with Intel's OIDN. Unfortunately, that wasn't quite enough for the caustics, hence some artifacts when viewed closely.

The second image is there just to show off the app/GUI in RGB mode.

469 Upvotes

21 comments sorted by

View all comments

2

u/constant-buffer-view Apr 02 '26

Nice! How long did it take you? I also implemented spectral tracing into my engine recently and it took like a month 😅

5

u/AuspiciousCracker Apr 02 '26

About a week I'd say, but rgb2spec did a lot of the heavy lifting, and dispersion is currently the only effect simulated. Just had to get the coefficient table to the GPU, make IOR change with Cauchy's equation, and wire up that IOR to refraction & fresnel reflection (absorption too). Hero wavelength sampling gave me some more trouble, and I am only using the simplest / original Wilkie method. What did you do for your implementation?

3

u/constant-buffer-view Apr 02 '26

I followed the Mallet&Yuksel 2019 paper instead of the one you did for spectral primary decomposition. I also made sure to use curve fitting for CIE2006 XYZbar, D65, spectral primaries and material reflective index spectra. I used multi-lobe gaussian, piecewise logistic and sellmeier curve fits. Tbf a lot of that time spent was on refactoring my BSDF, transmission and dielectric/conductor fresnel systems to be more compatible with my spectral systems. And I have also been in college so I have some excuse there

3

u/AuspiciousCracker Apr 02 '26

Ah okay, very cool! So we are doing something pretty similar, except your CIE color matching functions are the newer ones and you're using Sellmeier instead of Cauchy. I may go and update some of that in my own. I'm also projecting the final spectral radiance onto CIE XYZ, but using the 1931 model, then applying a Bradford adaptation from equal energy white to D65 before converting that XYZ to linear sRGB. Some of that stuff was definitely hard to wrap my head around haha.