From 45ee436b0c66552922ddfea36dfe31b0668e6da8 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Thomas=20M=C3=BCller?= <tmueller@nvidia.com>
Date: Wed, 14 Sep 2022 11:00:55 +0200
Subject: [PATCH] Fix blurred first frame in rendered videos

---
 scripts/run.py    |  2 +-
 src/python_api.cu | 21 ++++++++++++++++-----
 2 files changed, 17 insertions(+), 6 deletions(-)

diff --git a/scripts/run.py b/scripts/run.py
index 151e924..b7d68e4 100644
--- a/scripts/run.py
+++ b/scripts/run.py
@@ -347,7 +347,7 @@ if __name__ == "__main__":
 		os.makedirs("tmp")
 
 		for i in tqdm(list(range(min(n_frames, n_frames+1))), unit="frames", desc=f"Rendering video"):
-			testbed.camera_smoothing = args.video_camera_smoothing and i > 0
+			testbed.camera_smoothing = args.video_camera_smoothing
 			frame = testbed.render(resolution[0], resolution[1], args.video_spp, True, float(i)/n_frames, float(i + 1)/n_frames, args.video_fps, shutter_fraction=0.5)
 			write_image(f"tmp/{i:04d}.jpg", np.clip(frame * 2**args.exposure, 0.0, 1.0), quality=100)
 
diff --git a/src/python_api.cu b/src/python_api.cu
index cc2e891..a1830e7 100644
--- a/src/python_api.cu
+++ b/src/python_api.cu
@@ -131,16 +131,27 @@ py::array_t<float> Testbed::render_to_cpu(int width, int height, int spp, bool l
 	if (end_time < 0.f) {
 		end_time = start_time;
 	}
+	bool path_animation_enabled = start_time >= 0.f;
+	if (!path_animation_enabled) { // the old code disabled camera smoothing for non-path renders; so we preserve that behaviour
+		m_smoothed_camera = m_camera;
+	}
 
+	// this rendering code assumes that the intra-frame camera motion starts from m_smoothed_camera (ie where we left off) to allow for EMA camera smoothing.
+	// in the case of a camera path animation, at the very start of the animation, we have yet to initialize smoothed_camera to something sensible
+	// - it will just be the default boot position. oops!
+	// that led to the first frame having a crazy streak from the default camera position to the start of the path.
+	// so we detect that case and explicitly force the current matrix to the start of the path
+	if (start_time == 0.f) {
+		set_camera_from_time(start_time);
+		m_smoothed_camera = m_camera;
+	}
 	auto start_cam_matrix = m_smoothed_camera;
 
-	if (start_time >= 0.f) {
+	// now set up the end-of-frame camera matrix if we are moving along a path
+	if (path_animation_enabled) {
 		set_camera_from_time(end_time);
 		apply_camera_smoothing(1000.f / fps);
-	} else {
-		start_cam_matrix = m_smoothed_camera = m_camera;
 	}
-
 	auto end_cam_matrix = m_smoothed_camera;
 
 	for (int i = 0; i < spp; ++i) {
@@ -150,7 +161,7 @@ py::array_t<float> Testbed::render_to_cpu(int width, int height, int spp, bool l
 		auto sample_start_cam_matrix = log_space_lerp(start_cam_matrix, end_cam_matrix, start_alpha);
 		auto sample_end_cam_matrix = log_space_lerp(start_cam_matrix, end_cam_matrix, end_alpha);
 
-		if (start_time >= 0.f) {
+		if (path_animation_enabled) {
 			set_camera_from_time(start_time + (end_time-start_time) * (start_alpha + end_alpha) / 2.0f);
 			m_smoothed_camera = m_camera;
 		}
-- 
GitLab