diff --git a/include/neural-graphics-primitives/common_device.cuh b/include/neural-graphics-primitives/common_device.cuh
index 361c62bafd81b58ce3eabcbe79f02b472f7767d1..3ca1af0b440468f46a39ec6a8aba8b87c81b75f7 100644
--- a/include/neural-graphics-primitives/common_device.cuh
+++ b/include/neural-graphics-primitives/common_device.cuh
@@ -613,15 +613,15 @@ inline NGP_HOST_DEVICE Eigen::Vector2f motion_vector(
 	const Foveation& prev_foveation = {},
 	const Lens& lens = {}
 ) {
-	Ray ray = pixel_to_ray(
+	Eigen::Vector2f pxf = pixel.cast<float>() + ld_random_pixel_offset(snap_to_pixel_centers ? 0 : sample_index);
+	Ray ray = uv_to_ray(
 		sample_index,
-		pixel,
+		pxf.cwiseQuotient(resolution.cast<float>()),
 		resolution,
 		focal_length,
 		camera,
 		screen_center,
 		parallax_shift,
-		snap_to_pixel_centers,
 		0.0f,
 		1.0f,
 		0.0f,
@@ -630,7 +630,7 @@ inline NGP_HOST_DEVICE Eigen::Vector2f motion_vector(
 		lens
 	);
 
-	Eigen::Vector2f prev_pixel = pos_to_pixel(
+	Eigen::Vector2f prev_pxf = pos_to_pixel(
 		ray(depth),
 		resolution,
 		focal_length,
@@ -641,7 +641,7 @@ inline NGP_HOST_DEVICE Eigen::Vector2f motion_vector(
 		lens
 	);
 
-	return prev_pixel - (pixel.cast<float>() + ld_random_pixel_offset(sample_index));
+	return prev_pxf - pxf;
 }
 
 // Maps view-space depth (physical units) in the range [znear, zfar] hyperbolically to
diff --git a/include/neural-graphics-primitives/render_buffer.h b/include/neural-graphics-primitives/render_buffer.h
index 0e51364f36f228209b125f6f507c41dc0e2f43fb..a9b3bce4553297b2234da772929d204bd29e9e12 100644
--- a/include/neural-graphics-primitives/render_buffer.h
+++ b/include/neural-graphics-primitives/render_buffer.h
@@ -231,7 +231,7 @@ public:
 
 	void accumulate(float exposure, cudaStream_t stream);
 
-	void tonemap(float exposure, const Eigen::Array4f& background_color, EColorSpace output_color_space, float znear, float zfar, cudaStream_t stream);
+	void tonemap(float exposure, const Eigen::Array4f& background_color, EColorSpace output_color_space, float znear, float zfar, bool snap_to_pixel_centers, cudaStream_t stream);
 
 	void overlay_image(
 		float alpha,
diff --git a/src/render_buffer.cu b/src/render_buffer.cu
index ab01d4d66c1172152f87aa72abf1eadc35f552f6..f52eb6c71f14429c72b075380c650ac22ed04fa0 100644
--- a/src/render_buffer.cu
+++ b/src/render_buffer.cu
@@ -659,7 +659,7 @@ void CudaRenderBuffer::accumulate(float exposure, cudaStream_t stream) {
 	++m_spp;
 }
 
-void CudaRenderBuffer::tonemap(float exposure, const Array4f& background_color, EColorSpace output_color_space, float znear, float zfar, cudaStream_t stream) {
+void CudaRenderBuffer::tonemap(float exposure, const Array4f& background_color, EColorSpace output_color_space, float znear, float zfar, bool snap_to_pixel_centers, cudaStream_t stream) {
 	assert(m_dlss || out_resolution() == in_resolution());
 
 	auto res = in_resolution();
@@ -688,7 +688,7 @@ void CudaRenderBuffer::tonemap(float exposure, const Array4f& background_color,
 			res,
 			output_color_space == EColorSpace::Linear, /* HDR mode */
 			m_dlss_sharpening,
-			Vector2f::Constant(0.5f) - ld_random_pixel_offset(sample_index), /* jitter offset in [-0.5, 0.5] */
+			Vector2f::Constant(0.5f) - ld_random_pixel_offset(snap_to_pixel_centers ? 0 : sample_index), /* jitter offset in [-0.5, 0.5] */
 			sample_index == 0 /* reset history */
 		);
 
diff --git a/src/testbed.cu b/src/testbed.cu
index e442bd01ea5f8572193415df2ad8a7f36a6d7fd9..b30526aca5f86a144188836958da5a738d57c01b 100644
--- a/src/testbed.cu
+++ b/src/testbed.cu
@@ -4317,7 +4317,7 @@ void Testbed::render_frame_epilogue(
 	}
 
 	render_buffer.accumulate(m_exposure, stream);
-	render_buffer.tonemap(m_exposure, m_background_color, output_color_space, m_ndc_znear, m_ndc_zfar, stream);
+	render_buffer.tonemap(m_exposure, m_background_color, output_color_space, m_ndc_znear, m_ndc_zfar, m_snap_to_pixel_centers, stream);
 
 	if (m_testbed_mode == ETestbedMode::Nerf) {
 		// Overlay the ground truth image if requested