From 65952214fe289636f3357b9f2a68c3ab2f265673 Mon Sep 17 00:00:00 2001
From: Wentao Liu <wentao.liu.zero@outlook.com>
Date: Thu, 9 Jan 2025 14:32:02 +0800
Subject: [PATCH] Fix NAN bug when MLT propose a path with 0 radiance

---
 src/pbrt/cpu/integrators.cpp | 31 ++++++++++++++++++++++++++-----
 1 file changed, 26 insertions(+), 5 deletions(-)

diff --git a/src/pbrt/cpu/integrators.cpp b/src/pbrt/cpu/integrators.cpp
index a8c541f85..2913d49aa 100644
--- a/src/pbrt/cpu/integrators.cpp
+++ b/src/pbrt/cpu/integrators.cpp
@@ -2679,12 +2679,33 @@ void MLTIntegrator::Render() {
             // Compute acceptance probability for proposed sample
             Float cProposed = c(LProposed, lambdaProposed);
             Float cCurrent = c(LCurrent, lambdaCurrent);
-            Float accept = std::min<Float>(1, cProposed / cCurrent);
 
-            // Splat both current and proposed samples to _film_
-            if (accept > 0)
-                film.AddSplat(pProposed, LProposed * accept / cProposed, lambdaProposed);
-            film.AddSplat(pCurrent, LCurrent * (1 - accept) / cCurrent, lambdaCurrent);
+            Float accept = NAN;
+            if (cProposed == 0 && cCurrent == 0) {
+                // neither current path or the proposed found a light source
+                accept = 0.5;
+
+            } else if (cProposed == 0) {
+                // current path found a light source but the proposed didn't
+                accept = 0;
+                film.AddSplat(pCurrent, LCurrent / cCurrent, lambdaCurrent);
+
+            } else if (cCurrent == 0) {
+                // current path didn't find a light source but the proposed did
+                accept = 1;
+                film.AddSplat(pProposed, LProposed / cProposed, lambdaProposed);
+
+            } else {
+                // both paths found a light source
+                 accept = std::min<Float>(1, cProposed / cCurrent);
+                // Splat both current and proposed samples to _film_
+                if (accept > 0) {
+                    film.AddSplat(pProposed, LProposed * accept / cProposed, lambdaProposed);
+                }
+                if (accept < 1) {
+                    film.AddSplat(pCurrent, LCurrent * (1 - accept) / cCurrent, lambdaCurrent);
+                }
+            }
 
             // Accept or reject the proposal
             if (rng.Uniform<Float>() < accept) {