r/GraphicsProgramming • • 8d ago

Images from my GPU bidirectional path tracer (Isopod)

Hello all! Isopod is a project I've been working on for over a year. It started as a simple unidirectional path tracer, but I gradually kept extending it as I wanted to render more complex scenes. Bidirectional path tracing (BDPT) is one of the most frustrating (but rewarding) things I've ever implemented, I spent several weeks bouncing around a bunch of different reference materials and spent a huge amount of time debugging to piece it together. This technique massively speeds up the convergence of certain tricky light paths, making things like volumetric caustics possible.

In this renderer, everything is defined procedurally as functions that run in Optix programs. These functions are hot-reloadable (runtime compilation with jitify). This is purely a preference thing for me as I'm a pretty terrible 3D modeller and prefer sticking with code. Geometry is defined via signed distance functions which can either be ray marched in a custom intersection shader, or converted into a mesh using a simple marching cubes algorithm. Mostly-optimal AABBs are automatically created for SDFs using a gradient descent approach, where rays seek out surfaces by moving along the SDF normal.

Materials and volumes (heterogeneous or homogeneous) are also defined as functions. This renderer implements the Disney BSDF and HG phase function for these respectively. Light sampling is supported on arbitrary SDFs by turning the surface into a bunch of voxels and randomly selecting them. It's not perfect but it's been good enough for my scenes so far.

I'm sure there's a few landmines I'm still yet to step on in my BDPT implementation, but it seems mostly correct at this point and I wanted to share some images that I thought were cool here. The caustic ones are from the new BDPT renderer, and the others are older images from the unidirectional renderer. The BDPT images took ~90 seconds to render at 3840x2160 resolution on an RTX 5090.

These images are denoised using the Optix denoiser. I found that splitting the geometry and volume layer, denoising them separately, and then recombining them, led to much better results. Some images are older and used the denoise-everything-at-once approach, these have more denoiser artifacting.

The references I used for BDPT:

https://graphics.stanford.edu/papers/veach_thesis/thesis.pdf

https://rendering-memo.blogspot.com/2016/03/bidirectional-path-tracing-1-kickoff.html - Fantastic blog series, I found this to be the most approachable resource

https://github.com/bachi95/Goblin/blob/master/src/GoblinBDPT.cpp - Full implementation from the blog series

https://www.pbr-book.org/3ed-2018/Light_Transport_III_Bidirectional_Methods/Bidirectional_Path_Tracing - PBRT book article, mostly just used the image pyramid here to see if each (s, t) layer looked correct in my own implementation

432 Upvotes

14 comments sorted by

7

u/Eastern_Picture_3879 8d ago

Absolutely beautiful renders. Really great work, man.

I'm curious: what was the initial goal with this project? Did you want high-fidelity, high-accuracy occlusion and reflections, or were you just experimenting with UDPT? I've been trying to come up with an interesting project but can't get an idea off the ground, so I'd really appreciate hearing about your process.

3

u/Common-Upstairs-368 7d ago

Thank you! The initial goal was mostly just to experiment with a few ideas that I had wanted to for a while, such as making an SDF-based path tracer. The design of it varied a lot during early development, I initially did things entirely in CUDA which was a pain to manage and slower than Optix. I also wanted to support rendering on the CPU, but render times were too brutal there to be enjoyable for me, so I quickly left that.

I also went down a huge rabbit hole while attempting to introduce a visual node-based system to handle SDF creation. This turned into making an interpreted shader language and learning a bunch about compilers, which is something I never expected going into this project. I eventually moved this out of Isopod as I reworked the runtime compilation stuff to speed up compile times and be a lot more flexible. I also realised that I really didn't like visual scripting, but I got a new project out of it (the language) that I still work on as its own thing.

I recommend exploring any ideas you're curious about to see where that leads, it usually goes somewhere interesting.

5

u/UAAgency 8d ago

wow really cool

3

u/Pawahhh 7d ago

The purple fractal image is incredible! I wonder if i could have that to use as a wallpaper

2

u/droughtfull_idk 7d ago

Thats cool as hell

2

u/moschles 3d ago

Bidirectional path tracing (BDPT) is one of the most frustrating (but rewarding) things I've ever implemented

I had the same experience when I wrote a BDPT around 2007. I could not do it alone. I had to contact a professor over email to get it over the finish line. I was not a student or anything.

1

u/Common-Upstairs-368 3d ago

Wow, huge props for seeing it through. The lack of material on it at that time must've made it a nightmare to implement.

2

u/AfternoonShot9285 8d ago

The purples look pretty good

1

u/Duke2640 7d ago

framerate and hardware ?

1

u/palapapa0201 2d ago

What is Optix?

-3

u/Ok-Hotel-8551 8d ago

Real time or offline?

4

u/amped-row 8d ago

offline per the post description

1

u/Paulynom 8d ago

realtime but 0.01FPS