Skip to content

Commit 18c8498

Browse files
committed
Enhance SDL GUI and CUDA renderer with scene selection controls and performance metrics
1 parent c333cae commit 18c8498

File tree

5 files changed

+224
-56
lines changed

5 files changed

+224
-56
lines changed

resources/caustics_chapel.yaml

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
camera:
2+
position: [0.0, 1.0, 5.5]
3+
look_at: [0.0, 0.7, 0.0]
4+
up: [0.0, 1.0, 0.0]
5+
fov: 42.0
6+
7+
settings:
8+
background_color: [0.0, 0.0, 0.0]
9+
ambient_light: 0.0
10+
background_intensity: 0.0
11+
use_bvh: true
12+
13+
materials:
14+
- { name: wall, type: lambertian, albedo: [0.75, 0.75, 0.75] }
15+
- { name: floor, type: lambertian, albedo: [0.65, 0.62, 0.58] }
16+
- { name: glass, type: glass, albedo: [1.0, 1.0, 1.0], refractive_index: 1.5, transmission: 1.0 }
17+
- { name: bronze, type: rough_mirror, albedo: [0.82, 0.58, 0.30], roughness: 0.06, metallic: 1.0 }
18+
- { name: light, type: light, emission: [25.0, 20.0, 16.0], albedo: [1.0, 1.0, 1.0] }
19+
20+
geometry:
21+
- { type: rectangle, material: floor, corner: [-2.5, 0.0, -3.0], u: [5.0, 0.0, 0.0], v: [0.0, 0.0, 6.0] }
22+
- { type: rectangle, material: wall, corner: [-2.5, 2.8, -3.0], u: [5.0, 0.0, 0.0], v: [0.0, 0.0, 6.0] }
23+
- { type: rectangle, material: wall, corner: [-2.5, 0.0, -3.0], u: [5.0, 0.0, 0.0], v: [0.0, 2.8, 0.0] }
24+
- { type: rectangle, material: wall, corner: [-2.5, 0.0, -3.0], u: [0.0, 0.0, 6.0], v: [0.0, 2.8, 0.0] }
25+
- { type: rectangle, material: wall, corner: [2.5, 0.0, -3.0], u: [0.0, 0.0, 6.0], v: [0.0, 2.8, 0.0] }
26+
- { type: rectangle, material: light, corner: [-0.6, 2.79, -0.4], u: [1.2, 0.0, 0.0], v: [0.0, 0.0, 0.8] }
27+
- { type: sphere, material: glass, center: [-0.8, 0.6, -0.4], radius: 0.6 }
28+
- { type: sphere, material: glass, center: [0.7, 0.45, 0.6], radius: 0.45 }
29+
- { type: sphere, material: bronze, center: [0.0, 0.35, -1.4], radius: 0.35 }

resources/displacement_garden.yaml

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
camera:
2+
position: [0.0, 1.1, 7.0]
3+
look_at: [0.0, 0.5, 0.0]
4+
up: [0.0, 1.0, 0.0]
5+
fov: 42.0
6+
7+
settings:
8+
background_color: [0.08, 0.12, 0.18]
9+
ambient_light: 0.05
10+
background_intensity: 0.25
11+
use_bvh: true
12+
13+
materials:
14+
- { name: ground, type: lambertian, albedo: [0.35, 0.38, 0.40] }
15+
- { name: matte, type: lambertian, albedo: [0.75, 0.74, 0.72] }
16+
- { name: blue_metal, type: rough_mirror, albedo: [0.45, 0.62, 0.95], roughness: 0.15, metallic: 1.0 }
17+
- { name: light, type: light, emission: [10.0, 8.0, 6.5], albedo: [1.0, 1.0, 1.0] }
18+
19+
geometry:
20+
- { type: sphere, material: ground, center: [0.0, -1000.0, 0.0], radius: 1000.0 }
21+
- { type: rectangle, material: light, corner: [-4.0, 4.0, -2.0], u: [8.0, 0.0, 0.0], v: [0.0, 0.0, 3.0], visible: false }
22+
- { type: displaced_sphere, material: matte, center: [-3.0, 0.55, -1.0], radius: 0.55, displacement_scale: 0.05, pattern_type: 0 }
23+
- { type: displaced_sphere, material: matte, center: [-1.5, 0.55, -0.6], radius: 0.55, displacement_scale: 0.10, pattern_type: 0 }
24+
- { type: displaced_sphere, material: blue_metal, center: [0.0, 0.55, -0.2], radius: 0.55, displacement_scale: 0.16, pattern_type: 0 }
25+
- { type: displaced_sphere, material: matte, center: [1.5, 0.55, 0.2], radius: 0.55, displacement_scale: 0.24, pattern_type: 0 }
26+
- { type: displaced_sphere, material: blue_metal, center: [3.0, 0.55, 0.6], radius: 0.55, displacement_scale: 0.32, pattern_type: 0 }

resources/material_laboratory.yaml

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
camera:
2+
position: [0.0, 1.2, 6.5]
3+
look_at: [0.0, 0.7, 0.0]
4+
up: [0.0, 1.0, 0.0]
5+
fov: 45.0
6+
7+
settings:
8+
background_color: [0.02, 0.02, 0.03]
9+
ambient_light: 0.01
10+
background_intensity: 0.0
11+
use_bvh: true
12+
13+
materials:
14+
- name: ground
15+
type: lambertian
16+
albedo: [0.45, 0.45, 0.48]
17+
- name: light
18+
type: light
19+
emission: [14.0, 12.0, 10.0]
20+
albedo: [1.0, 1.0, 1.0]
21+
- name: metal_0
22+
type: rough_mirror
23+
albedo: [0.90, 0.85, 0.78]
24+
roughness: 0.01
25+
metallic: 1.0
26+
- name: metal_1
27+
type: rough_mirror
28+
albedo: [0.90, 0.85, 0.78]
29+
roughness: 0.08
30+
metallic: 1.0
31+
- name: metal_2
32+
type: rough_mirror
33+
albedo: [0.90, 0.85, 0.78]
34+
roughness: 0.2
35+
metallic: 1.0
36+
- name: glass
37+
type: glass
38+
albedo: [1.0, 1.0, 1.0]
39+
refractive_index: 1.52
40+
transmission: 1.0
41+
42+
geometry:
43+
- type: sphere
44+
material: ground
45+
center: [0.0, -1000.0, 0.0]
46+
radius: 1000.0
47+
- type: rectangle
48+
material: light
49+
corner: [-2.0, 4.0, -1.5]
50+
u: [4.0, 0.0, 0.0]
51+
v: [0.0, 0.0, 3.0]
52+
visible: false
53+
- { type: sphere, material: metal_0, center: [-2.2, 0.7, 0.0], radius: 0.7 }
54+
- { type: sphere, material: metal_1, center: [0.0, 0.7, 0.0], radius: 0.7 }
55+
- { type: sphere, material: metal_2, center: [2.2, 0.7, 0.0], radius: 0.7 }
56+
- { type: sphere, material: glass, center: [0.0, 0.7, -2.0], radius: 0.7 }

src/rayon/camera/sdl/sdl_gui_handler.hpp

Lines changed: 41 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
#define STB_IMAGE_RESIZE_IMPLEMENTATION
2727
#include "external/stb_image_resize2.h"
2828

29+
#include <chrono>
2930
#include <cmath>
3031
#include <iostream>
3132
#include <string>
@@ -66,7 +67,8 @@ class SDLGuiHandler
6667
SDLGuiHandler(int image_width, int image_height, GuiTheme initial_theme = GuiTheme::NORD)
6768
: image_width(image_width), image_height(image_height), show_controls(true), collapse_headers(false),
6869
reset_headers(false), window_collapse_requested(false), window_collapsed(false), current_theme(initial_theme), initialized(false), window(nullptr), renderer(nullptr),
69-
texture(nullptr), logo_texture(nullptr)
70+
texture(nullptr), logo_texture(nullptr), last_perf_sample_time_ms(0),
71+
perf_sample_interval_ms(50), perf_time_window_ms(20000)
7072
{
7173
}
7274

@@ -217,15 +219,36 @@ class SDLGuiHandler
217219
ImGui::Text("Throughput: %.0f S/s", sps);
218220
ImGui::Text("Time/Pass: %.3f ms", ms_per_sample);
219221

220-
if (sps > 0.0f)
222+
ImGui::Text("Graph dt: %u ms", perf_sample_interval_ms);
223+
ImGui::SameLine();
224+
if (ImGui::SmallButton("-##graph_dt"))
225+
{
226+
perf_sample_interval_ms = (perf_sample_interval_ms > 20) ? perf_sample_interval_ms - 20 : 20;
227+
last_perf_sample_time_ms = 0;
228+
}
229+
ImGui::SameLine();
230+
if (ImGui::SmallButton("+##graph_dt"))
221231
{
222-
sps_history.push_back(sps);
223-
ms_history.push_back(ms_per_sample);
232+
perf_sample_interval_ms = (perf_sample_interval_ms < 1000) ? perf_sample_interval_ms + 20 : 1000;
233+
last_perf_sample_time_ms = 0;
234+
}
224235

225-
if (sps_history.size() > 500)
236+
if (sps > 0.0f)
237+
{
238+
const Uint32 now_ms = SDL_GetTicks();
239+
if (last_perf_sample_time_ms == 0 || now_ms - last_perf_sample_time_ms >= perf_sample_interval_ms)
226240
{
227-
sps_history.erase(sps_history.begin());
228-
ms_history.erase(ms_history.begin());
241+
sps_history.push_back(sps);
242+
ms_history.push_back(ms_per_sample);
243+
last_perf_sample_time_ms = now_ms;
244+
245+
// Fixed x-axis time range: keep only the last N seconds worth of samples.
246+
const size_t max_points = std::max<size_t>(10, perf_time_window_ms / perf_sample_interval_ms);
247+
if (sps_history.size() > max_points)
248+
{
249+
sps_history.erase(sps_history.begin());
250+
ms_history.erase(ms_history.begin());
251+
}
229252
}
230253
}
231254

@@ -250,11 +273,6 @@ class SDLGuiHandler
250273
ImGui::PopStyleColor();
251274
}
252275

253-
if (auto_accumulate)
254-
{
255-
ImGui::Separator();
256-
ImGui::Checkbox("Auto-Accumulate (Space)", auto_accumulate);
257-
}
258276
}
259277

260278
// --- Adaptive Sampling ---
@@ -264,7 +282,13 @@ class SDLGuiHandler
264282
ImGui::SetNextItemOpen(!collapse_headers);
265283
if (ImGui::CollapsingHeader("Adaptive Sampling"))
266284
{
267-
ImGui::Checkbox("Enable Adaptive Sampling", adaptive_sampling);
285+
if (auto_accumulate)
286+
{
287+
ImGui::Checkbox("Accumulate", auto_accumulate);
288+
ImGui::SameLine();
289+
}
290+
291+
ImGui::Checkbox("Adaptive Sampling##adaptive_toggle", adaptive_sampling);
268292

269293
if (*adaptive_sampling)
270294
{
@@ -415,6 +439,7 @@ class SDLGuiHandler
415439
ImGui::BulletText("SPACE: Toggle Accumulation");
416440
ImGui::BulletText("A: Toggle Normal Arrows");
417441
ImGui::BulletText("N: Toggle Show Normals");
442+
ImGui::BulletText("Left/Right: Previous/Next Scene");
418443
ImGui::BulletText("O: Auto-Orbit");
419444
ImGui::BulletText("Enter: Collapse/Expand Window");
420445
ImGui::BulletText("H: Hide/Show UI");
@@ -484,6 +509,9 @@ class SDLGuiHandler
484509
SDL_Rect logo_rect;
485510
std::vector<float> sps_history;
486511
std::vector<float> ms_history;
512+
Uint32 last_perf_sample_time_ms;
513+
Uint32 perf_sample_interval_ms;
514+
Uint32 perf_time_window_ms;
487515

488516
static void cleanupSDL() { SDL_Quit(); }
489517

src/rayon/gpu_renderers/renderer_cuda_progressive_host.hpp

Lines changed: 72 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)