Regular path tracing struggles with “hidden” light sources located behind corners, walls, or ceilings because rays emitted from the camera are unlikely to reach these sources within a limited number of samples and bounces.
Bidirectional Path Tracing (BDPT) addresses this issue by combining forward and backward path tracing. While traditional path tracing traces rays from the camera to the scene, BDPT also traces rays from light sources into the scene. This approach creates paths that connect light sources to the camera through multiple bounces and interactions with surfaces.
By integrating these paths, BDPT enhances the simulation of complex lighting effects such as caustics, indirect lighting, and glossy reflections, resulting in more accurate and visually appealing images compared to standard path tracing techniques.
As the figure shows, a light source illuminates only a small area on the ceiling, and the rest of the room is lit only by indirect light bounced from the ceiling. In this case, a traditional path tracer will find it challenging to successfully find a path to the light source. Most paths will contribute nothing to the final image and will be a performance waste.
However, in the theory land, if we construct two light paths, one starts from the camera, the other starts from the light source, and then connect the two paths in between, we would handle this situation more effectively. This technique is called Bidirectional Path Tracing.
For implementation, we will utilize the Dartmouth Introductory Ray Tracer as our code base. It would be a good starting point to start playing around with graphics concepts.
Implementing the BDPT into an existing code base could be risky and hard to debug. So, we initially start by restricting ourselves to a full path with only one bounce on the camera side and one bounce on the light side.
To start with, in order to test the whole procedure, we built a simplified version of the scene without blocking the light source. In this scene, we will only allow our eyeRay and lightRay to each have only one intersection with the scene. Then, we connect the intersection points of both ends. After that, we calculate the throughput of the whole path and get the final result, which should be relatively straightforward.
This will be a more "hard code" style version, but we think it would be a good starting point to keep all the behaviors more predictable.
After the previous steps, we would have a single scatter version of BDPT working. Now, we add variations to our code base to allow the rays to scatter multiple times in our scene.
After doing so, our path tracer will already gain the ability to allow rays to “escape“ from behind corners, which would be a significant improvement over the traditional path tracer.
Once again, we keep it relatively simple by not counting all the shadow rays between two paths and only considering the direct connection between two ends. This end-to-end version could help us focus on both directions' recursive hits and observe the difference between this and the single scatter version.
To improve BDPT's efficiency and accuracy, we can introduce the concept of shadow rays. Shadow rays are additional rays cast between the eye path nodes and the light path nodes to determine their visibility. By connecting these nodes with shadow rays, we can explicitly check if any occluders are blocking the light transport between them.
With the previous end-to-end version, we can now consider each node in the path as a new end, and connect it to other ends. After all, shadow rays are just more end-to-end connections.
As the figure shows, the shadow rays shoot from every node in the eyePath to every node in the lightPath. Unlike the previous solution, which only had one connection between the ends of both paths, this new method does not waste the whole path when some connections are blocked.
At this point, the ray is already tracing "bidirectionally." So, let's take a typical scene that BDPT can most likely handle well and compare the results to some traditional solutions to see the differences.
For instance, in rendering a scene illuminated solely by indirect light from a hidden light source, BDPT, even without shadow rays, clearly outperforms traditional Path Tracing and Direct Next Event Estimation (NEE). It enhances performance in such scenarios, highlighting its ability to handle complex lighting interactions that traditional methods struggle with effectively.
However, when compared to Path Tracing with Multiple Importance Sampling (MIS), our current BDPT results exhibit more noise, particularly high-frequency noise. This type of noise is challenging to mitigate during the post-rendering stage and can significantly affect the overall quality of the rendered image.
Now, when we connect the shadow rays between every node in the eyePath and every node in the lightPath and calculate their total contribution, we observe a significant improvement. The results are much better, and in some areas, it even outperforms Path Tracing with Multiple Importance Sampling (MIS).
Incorporating shadow rays into BDPT captures more accurate lighting information, effectively handling complex occlusion and indirect illumination. Shadow rays determine visibility between the eye path and light path nodes, ensuring only unoccluded connections contribute to the final image.
Without shadow rays, noise occurs because the algorithm can't accurately determine visibility between nodes, leading to incorrect lighting calculations. Shadow rays solve this by validating connections between paths, reducing the likelihood of incorrect lighting contributions, and improving overall render quality. By incorporating shadow rays, BDPT not only handles complex lighting better but also reduces noise, resulting in cleaner, more accurate renders.
Playing around with eyePathLength and lightPathLength is important in BDPT because these parameters control the trade-off between rendering quality and computational efficiency. Adjusting these lengths affects the following aspects:
When the light path length is short, it performs poorly because it does not give the light enough chance to "escape" from a hidden place. On the other hand, when the path length increases from 2-3 to 2-4 or 3-3, the results do not differ much, while the rendering time is almost twice as long. So, we know this particular scene has reached an edge where the additional computational cost may outweigh the quality improvement.
Daaa is a junior developer specializing in game dev, computer graphics, and machine learning. He is currently involved in projects integrating ML into games and graphics, aiming to push the boundaries of interactive experiences. With a solid foundation in programming and hands-on experience in Unity, Daaa is eager to expand his skills and contribute to innovative projects. His passion for learning combined with his growing expertise in ML, makes him a promising talent in the evolving landscape of digital media and immersive technologies.
Interdisciplinary is precisely what I am good at. Every time the inspiration burst, in order to set the idea free from limits, I would learn some new skills to counter the challenge. Over time, I have broadened my skillset widely open, from art to tech, from reality to virtuality. Below is an axis graph to explain the Art-Tech/Digital-Physical coordinate of the skillsets used in my projects.
Thanks to Matthew P Munger who created and shared this open source MattOS. This is really a powerful and enjoyable tool to use. I also learned a lot from how he manages this front-end system. Welcome to check out and support his work!
Maybe it's not a good idea to shut my website down without a hardware reset button. Proceed?
Just kidding. Nothing was actually shutdown. It wouldn't have been a good idea. Do it again?
Permission denied. Please reconsider your actions.