use std::sync::{ mpsc::{Receiver, Sender}, Arc, }; use rand::{rngs::SmallRng, SeedableRng}; use ray_tracing_core::{ camera::{BasicCamera, Camera}, prelude::*, renderer::ClassicalRenderer, scene::Scene, }; use ray_tracing_renderer::{ depth_renderer::DepthRenderer, mis::MIS, next_event_estimation::NextEventEstimation, path_tracer::PathTracer, path_tracer_importance::PathTracerImportance, }; use ray_tracing_scene::examples; use rayon::{ iter::{IndexedParallelIterator, ParallelIterator}, slice::ParallelSliceMut, }; use vulkano::{ buffer::{Buffer, BufferCreateInfo, BufferUsage, Subbuffer}, memory::allocator::{AllocationCreateInfo, MemoryAllocator, MemoryTypeFilter}, }; #[derive(Debug, Clone)] pub struct RenderSettings { pub width: u32, pub height: u32, pub scene: &'static str, pub renderer_id: usize, pub camera_pos: Pos3, pub camera_look_at: Pos3, pub camera_up: Dir3, pub camera_horizontal_fov: Float, } pub struct Data { pub width: u32, pub height: u32, pub samples: u32, pub buffer: Subbuffer<[f32]>, } fn render_pass< R: ClassicalRenderer + std::marker::Sync, S: Scene + std::marker::Sync, >( settings: &RenderSettings, renderer: &R, scene: &S, camera: &BasicCamera, samples: u32, buffer: &mut [Float], ) { buffer.par_chunks_mut(3).enumerate().for_each(|(i, c)| { let x = (i % settings.width as usize) as u32; let y = (i / settings.width as usize) as u32; let mut rng = SmallRng::seed_from_u64( (x + y * settings.width) as u64 + (settings.width as u64 * settings.height as u64 * samples as u64), ); let r = renderer.render_pixel(&scene, &camera, x, y, &mut rng); c[0] += r.r(); c[1] += r.g(); c[2] += r.b(); }); } #[allow(clippy::type_complexity)] pub const RENDERER: [&str; 5] = [ "Depth", "Path tracer", "Path tracer importance", "Next event estimation", "MIS", ]; fn render_pass_renderer + Sync>( settings: &RenderSettings, scene: &S, camera: &BasicCamera, samples: u32, buffer: &mut [Float], ) { match settings.renderer_id { 0 => { let r = DepthRenderer::new(settings.width, settings.height); render_pass(settings, &r, scene, camera, samples, buffer); } 1 => { let r = PathTracer::new(settings.width, settings.height); render_pass(settings, &r, scene, camera, samples, buffer); } 2 => { let r = PathTracerImportance::new(settings.width, settings.height); render_pass(settings, &r, scene, camera, samples, buffer); } 3 => { let r = NextEventEstimation::new(settings.width, settings.height); render_pass(settings, &r, scene, camera, samples, buffer); } 4 => { let r = MIS::new(settings.width, settings.height); render_pass(settings, &r, scene, camera, samples, buffer); } _ => panic!("Unknown renderer"), } } pub fn render_thread( s: RenderSettings, rx: Receiver, tx: Sender, allocator: Arc, ) { let mut settings = s; let mut buffer = vec![0.0; settings.width as usize * settings.height as usize * 3]; let example_scenes = examples::example_scenes::(); let mut scene = example_scenes[settings.scene].get_scene(); let mut camera = BasicCamera::from_look_at( settings.width, settings.height, settings.camera_pos, settings.camera_look_at, settings.camera_up, settings.camera_horizontal_fov, ); let mut samples = 0; loop { while let Ok(s) = rx.try_recv() { println!("Settings changed."); settings = s; scene = example_scenes[settings.scene].get_scene(); camera = BasicCamera::from_look_at( settings.width, settings.height, settings.camera_pos, settings.camera_look_at, settings.camera_up, settings.camera_horizontal_fov, ); buffer = vec![0.0; settings.width as usize * settings.height as usize * 3]; samples = 0; } match &scene { examples::ExampleSceneEnum::AccelerationStructureScene(s) => { render_pass_renderer(&settings, s, &camera, samples, &mut buffer) } examples::ExampleSceneEnum::TriangleBVH(s) => { render_pass_renderer(&settings, s, &camera, samples, &mut buffer) } } samples += 1; let data = Data { width: settings.width, height: settings.height, samples, buffer: Buffer::from_iter( allocator.clone(), BufferCreateInfo { usage: BufferUsage::STORAGE_BUFFER, ..Default::default() }, AllocationCreateInfo { memory_type_filter: MemoryTypeFilter::PREFER_DEVICE | MemoryTypeFilter::HOST_SEQUENTIAL_WRITE, ..Default::default() }, buffer.iter().copied(), ) .unwrap(), }; let _ = tx.send(data); } }