@@ -136,6 +136,7 @@ class RendererCUDAProgressive : public IRenderer
136136 // Rendering buffers
137137 SDL_Event event;
138138 vector<unsigned char > display_image (image_width * image_height * image_channels);
139+ vector<unsigned char > base_display_image (image_width * image_height * image_channels);
139140 RenderTargetView display_view{&display_image, image_width, image_height, image_channels};
140141
141142 void *d_rand_states = nullptr ;
@@ -310,6 +311,52 @@ class RendererCUDAProgressive : public IRenderer
310311 // Build initial GPU scene
311312 CudaScene::Scene *gpu_scene = Scene::CudaSceneBuilder::buildGPUScene (active_scene);
312313
314+ auto applySceneSelectionChange = [&]() {
315+ std::cout << " Switching to scene: " << scene_names[current_scene_index] << std::endl;
316+ switch (current_scene_index)
317+ {
318+ case 0 :
319+ active_scene = Scene::SceneFactory::createDefaultScene ();
320+ break ;
321+ case 1 :
322+ active_scene = Scene::SceneFactory::singleObjectScene ();
323+ break ;
324+ case 2 :
325+ active_scene = Scene::SceneFactory::fromYAML (" ../resources/cornell_box.yaml" );
326+ break ;
327+ case 3 :
328+ active_scene = Scene::SceneFactory::fromYAML (" ../resources/simple_scene.yaml" );
329+ break ;
330+ case 4 :
331+ active_scene = Scene::SceneFactory::fromYAML (" ../resources/bvh_test_scene.yaml" );
332+ break ;
333+ }
334+
335+ // Update original_scene as well, then re-apply visualization mode.
336+ original_scene = active_scene;
337+ cpu_scene_for_arrows = Scene::CPUSceneBuilder::buildCPUScene (original_scene);
338+ applyVisualizationToActiveScene ();
339+
340+ // Apply scene camera
341+ look_from = active_scene.camera_position ;
342+ look_at = active_scene.camera_look_at ;
343+ camera.vup = active_scene.camera_up ;
344+ camera.vfov = active_scene.camera_fov ;
345+ cam_fov_ui = static_cast <float >(camera.vfov );
346+ camera_control.initializeCameraControls (look_from, look_at);
347+
348+ // Apply scene-specific rendering settings
349+ background_intensity = active_scene.background_intensity ;
350+
351+ // Rebuild GPU scene
352+ Scene::CudaSceneBuilder::freeGPUScene (gpu_scene);
353+ gpu_scene = Scene::CudaSceneBuilder::buildGPUScene (active_scene);
354+
355+ // Reset rendering state
356+ camera_changed = true ;
357+ applySceneSettings ();
358+ };
359+
313360 // Timing for auto-orbit
314361 auto last_frame_time = std::chrono::high_resolution_clock::now ();
315362
@@ -319,6 +366,7 @@ class RendererCUDAProgressive : public IRenderer
319366 while (running)
320367 {
321368 bool visualization_toggled_by_key = false ;
369+ bool scene_switched_by_key = false ;
322370
323371 // Handle events
324372 while (SDLGuiHandler::pollEvent (event))
@@ -383,6 +431,16 @@ class RendererCUDAProgressive : public IRenderer
383431 : static_cast <int >(VisualizationMode::SHOW_NORMALS);
384432 visualization_toggled_by_key = true ;
385433 }
434+ else if (event.key .keysym .sym == SDLK_LEFT)
435+ {
436+ current_scene_index = (current_scene_index - 1 + scene_count) % scene_count;
437+ scene_switched_by_key = true ;
438+ }
439+ else if (event.key .keysym .sym == SDLK_RIGHT)
440+ {
441+ current_scene_index = (current_scene_index + 1 ) % scene_count;
442+ scene_switched_by_key = true ;
443+ }
386444 else if (camera_control.handleKeyDown (event, accumulation_enabled, samples_per_batch_float,
387445 light_intensity, background_intensity, needs_rerender,
388446 camera_changed))
@@ -417,6 +475,11 @@ class RendererCUDAProgressive : public IRenderer
417475 }
418476 }
419477
478+ if (scene_switched_by_key)
479+ {
480+ applySceneSelectionChange ();
481+ }
482+
420483 if (visualization_toggled_by_key)
421484 {
422485 applyVisualizationToActiveScene ();
@@ -479,6 +542,9 @@ class RendererCUDAProgressive : public IRenderer
479542 display_view.height, display_view.channels, current_samples);
480543 }
481544
545+ // Keep a clean, overlay-free base image for deterministic per-frame compositing.
546+ base_display_image = display_image;
547+
482548 if (target.pixels )
483549 *target.pixels = display_image;
484550 needs_rerender = false ;
@@ -551,6 +617,9 @@ class RendererCUDAProgressive : public IRenderer
551617 image_channels, current_samples);
552618 }
553619
620+ // Keep a clean, overlay-free base image for deterministic per-frame compositing.
621+ base_display_image = display_image;
622+
554623 if (target.pixels )
555624 *target.pixels = display_image;
556625 }
@@ -584,6 +653,8 @@ class RendererCUDAProgressive : public IRenderer
584653 float cam_pos[3 ] = {(float )look_from.x (), (float )look_from.y (), (float )look_from.z ()};
585654 float cam_lookat[3 ] = {(float )look_at.x (), (float )look_at.y (), (float )look_at.z ()};
586655
656+ // Recompose from a stable base every frame so overlays don't stack over time.
657+ display_image = base_display_image;
587658 drawCPUArrowOverlay (display_image);
588659
589660 gui.updateDisplay (display_image, image_channels, current_sps, current_ms_per_sample, current_samples,
@@ -606,49 +677,7 @@ class RendererCUDAProgressive : public IRenderer
606677 // Handle scene change from UI
607678 if (current_scene_index != old_scene_index)
608679 {
609- std::cout << " Switching to scene: " << scene_names[current_scene_index] << std::endl;
610- switch (current_scene_index)
611- {
612- case 0 :
613- active_scene = Scene::SceneFactory::createDefaultScene ();
614- break ;
615- case 1 :
616- active_scene = Scene::SceneFactory::singleObjectScene ();
617- break ;
618- case 2 :
619- active_scene = Scene::SceneFactory::fromYAML (" ../resources/cornell_box.yaml" );
620- break ;
621- case 3 :
622- active_scene = Scene::SceneFactory::fromYAML (" ../resources/simple_scene.yaml" );
623- break ;
624- case 4 :
625- active_scene = Scene::SceneFactory::fromYAML (" ../resources/bvh_test_scene.yaml" );
626- break ;
627- }
628-
629- // Update original_scene as well, then re-apply visualization mode.
630- original_scene = active_scene;
631- cpu_scene_for_arrows = Scene::CPUSceneBuilder::buildCPUScene (original_scene);
632- applyVisualizationToActiveScene ();
633-
634- // Apply scene camera
635- look_from = active_scene.camera_position ;
636- look_at = active_scene.camera_look_at ;
637- camera.vup = active_scene.camera_up ;
638- camera.vfov = active_scene.camera_fov ;
639- cam_fov_ui = static_cast <float >(camera.vfov );
640- camera_control.initializeCameraControls (look_from, look_at);
641-
642- // Apply scene-specific rendering settings
643- background_intensity = active_scene.background_intensity ;
644-
645- // Rebuild GPU scene
646- Scene::CudaSceneBuilder::freeGPUScene (gpu_scene);
647- gpu_scene = Scene::CudaSceneBuilder::buildGPUScene (active_scene);
648-
649- // Reset rendering state
650- camera_changed = true ;
651- applySceneSettings ();
680+ applySceneSelectionChange ();
652681 }
653682
654683 // Handle visualization mode change
0 commit comments