From 7d38e87f6a4066b90f7b3ef13de64a1d8c51685c Mon Sep 17 00:00:00 2001 From: hal8174 Date: Fri, 4 Oct 2024 18:12:00 +0200 Subject: [PATCH] Refactor Renderer trait --- ray-tracing-core/src/renderer.rs | 6 +- ray-tracing-image/src/main.rs | 38 ++++--- ray-tracing-renderer/src/depth_renderer.rs | 30 +++--- ray-tracing-renderer/src/path_tracer.rs | 30 +++--- .../src/path_tracer_importance.rs | 30 +++--- ray-tracing-scene/src/examples.rs | 100 ++++++++++++++++++ ray-tracing-scene/src/lib.rs | 1 + ray-tracing-scene/src/triangle_bvh.rs | 85 +-------------- ray-tracing-tev/src/main.rs | 80 +++++++++----- 9 files changed, 228 insertions(+), 172 deletions(-) create mode 100644 ray-tracing-scene/src/examples.rs diff --git a/ray-tracing-core/src/renderer.rs b/ray-tracing-core/src/renderer.rs index fba048f..d85a73b 100644 --- a/ray-tracing-core/src/renderer.rs +++ b/ray-tracing-core/src/renderer.rs @@ -1,7 +1,7 @@ -use crate::prelude::*; +use crate::{camera::Camera, prelude::*, scene::Scene}; -pub trait ClassicalRenderer { - fn render_pixel(&self, x: u32, y: u32, rng: &mut R) -> Color; +pub trait ClassicalRenderer, C: Camera> { + fn render_pixel(&self, scene: &S, camera: &C, x: u32, y: u32, rng: &mut R) -> Color; fn width(&self) -> u32; fn height(&self) -> u32; } diff --git a/ray-tracing-image/src/main.rs b/ray-tracing-image/src/main.rs index e139532..22b8283 100644 --- a/ray-tracing-image/src/main.rs +++ b/ray-tracing-image/src/main.rs @@ -1,13 +1,24 @@ use image::{ImageBuffer, ImageResult, Rgb}; use rand::{rngs::SmallRng, SeedableRng}; -use ray_tracing_core::{camera::BasicCamera, prelude::*, renderer::ClassicalRenderer}; -use ray_tracing_renderer::{path_tracer::PathTracer, path_tracer_importance::PathTracerImportance}; -use ray_tracing_scene::{basic_scene::BasicScene, triangle_bvh::examples::cornel}; +use ray_tracing_core::{ + camera::{BasicCamera, Camera}, + prelude::*, + renderer::ClassicalRenderer, + scene::Scene, +}; +use ray_tracing_renderer::path_tracer_importance::PathTracerImportance; +use ray_tracing_scene::examples::basic_cornel; use rayon::prelude::*; use std::path::Path; -fn render_image + Sync>( - renderer: C, +fn render_image< + R: ClassicalRenderer + Sync, + S: Scene + Sync, + C: Camera + Sync, +>( + renderer: &R, + scene: &S, + camera: &C, outputfilename: impl AsRef, samples_per_pixel: usize, ) -> ImageResult<()> { @@ -19,7 +30,8 @@ fn render_image + Sync>( let mut rng = SmallRng::seed_from_u64((x + y * renderer.width()) as u64); for _ in 0..samples_per_pixel { - *c += renderer.render_pixel(x, y, &mut rng) / (samples_per_pixel as Float); + *c += + renderer.render_pixel(scene, camera, x, y, &mut rng) / (samples_per_pixel as Float); } }); @@ -33,18 +45,18 @@ fn render_image + Sync>( fn main() -> ImageResult<()> { // let s = BasicScene::new(); - let s = cornel(); + let s = basic_cornel(); let c = BasicCamera::new( 400, 400, - Pos3::new(-6.0, 0.0, 0.0), - Dir3::new(1.0, 0.0, 0.0), - Dir3::up(), - Float::to_radians(90.0), + s.camera_pos, + s.camera_dir, + s.camera_up, + s.horizontal_fov, ); - let r = PathTracerImportance::new(s, c); + let r = PathTracerImportance::new(400, 400); - render_image(r, "test.exr", 1048) + render_image(&r, &s.scene, &c, "test.exr", 1048) } diff --git a/ray-tracing-renderer/src/depth_renderer.rs b/ray-tracing-renderer/src/depth_renderer.rs index 49db54f..7342f7c 100644 --- a/ray-tracing-renderer/src/depth_renderer.rs +++ b/ray-tracing-renderer/src/depth_renderer.rs @@ -1,42 +1,38 @@ use ray_tracing_core::{camera::Camera, prelude::*, renderer::ClassicalRenderer, scene::Scene}; use std::marker::PhantomData; -pub struct DepthRenderer +pub struct DepthRenderer where - S: Scene, - C: Camera, R: Rng, { - scene: S, - camera: C, + width: u32, + height: u32, rng: PhantomData, } -impl DepthRenderer +impl DepthRenderer where - S: Scene, - C: Camera, R: Rng, { - pub fn new(scene: S, camera: C) -> Self { + pub fn new(width: u32, height: u32) -> Self { Self { - scene, - camera, rng: PhantomData {}, + width, + height, } } } -impl ClassicalRenderer for DepthRenderer +impl ClassicalRenderer for DepthRenderer where S: Scene, C: Camera, R: Rng, { - fn render_pixel(&self, x: u32, y: u32, rng: &mut R) -> Color { - let r = self.camera.forward(x, y, rng); + fn render_pixel(&self, scene: &S, camera: &C, x: u32, y: u32, rng: &mut R) -> Color { + let r = camera.forward(x, y, rng); - if let Some(i) = self.scene.intersect(r, 0.0, Float::INFINITY) { + if let Some(i) = scene.intersect(r, 0.0, Float::INFINITY) { Color::gray(1.0 / i.t()) // let c = 0.5 * (i.normal() + Dir3::new(1.0, 1.0, 1.0)); // let c = i.normal(); @@ -47,10 +43,10 @@ where } fn width(&self) -> u32 { - self.camera.width() + self.width } fn height(&self) -> u32 { - self.camera.height() + self.height } } diff --git a/ray-tracing-renderer/src/path_tracer.rs b/ray-tracing-renderer/src/path_tracer.rs index 2d89fdc..dafe454 100644 --- a/ray-tracing-renderer/src/path_tracer.rs +++ b/ray-tracing-renderer/src/path_tracer.rs @@ -1,47 +1,43 @@ use ray_tracing_core::{camera::Camera, prelude::*, renderer::ClassicalRenderer, scene::Scene}; use std::marker::PhantomData; -pub struct PathTracer +pub struct PathTracer where - S: Scene, - C: Camera, R: Rng, { - scene: S, - camera: C, + width: u32, + height: u32, rng: PhantomData, } -impl PathTracer +impl PathTracer where - S: Scene, - C: Camera, R: Rng, { - pub fn new(scene: S, camera: C) -> Self { + pub fn new(width: u32, height: u32) -> Self { Self { - scene, - camera, + width, + height, rng: PhantomData {}, } } } -impl ClassicalRenderer for PathTracer +impl ClassicalRenderer for PathTracer where S: Scene, C: Camera, R: Rng, { - fn render_pixel(&self, x: u32, y: u32, rng: &mut R) -> Color { + fn render_pixel(&self, scene: &S, camera: &C, x: u32, y: u32, rng: &mut R) -> Color { let mut sum = Color::black(); let mut alpha = Color::white(); - let mut r = self.camera.forward(x, y, rng); + let mut r = camera.forward(x, y, rng); let mut count = 0; - while let Some(i) = self.scene.intersect(r, 0.001, Float::INFINITY) { + while let Some(i) = scene.intersect(r, 0.001, Float::INFINITY) { let frame = i.tangent_frame(); let w_in = frame.to_frame(-r.dir()); let w_out = Dir3::sample_uniform_hemisphere(rng); @@ -67,10 +63,10 @@ where } fn width(&self) -> u32 { - self.camera.width() + self.width } fn height(&self) -> u32 { - self.camera.height() + self.height } } diff --git a/ray-tracing-renderer/src/path_tracer_importance.rs b/ray-tracing-renderer/src/path_tracer_importance.rs index 15fd75d..e7dae5a 100644 --- a/ray-tracing-renderer/src/path_tracer_importance.rs +++ b/ray-tracing-renderer/src/path_tracer_importance.rs @@ -1,47 +1,43 @@ use ray_tracing_core::{camera::Camera, prelude::*, renderer::ClassicalRenderer, scene::Scene}; use std::marker::PhantomData; -pub struct PathTracerImportance +pub struct PathTracerImportance where - S: Scene, - C: Camera, R: Rng, { - scene: S, - camera: C, + width: u32, + height: u32, rng: PhantomData, } -impl PathTracerImportance +impl PathTracerImportance where - S: Scene, - C: Camera, R: Rng, { - pub fn new(scene: S, camera: C) -> Self { + pub fn new(width: u32, height: u32) -> Self { Self { - scene, - camera, + width, + height, rng: PhantomData {}, } } } -impl ClassicalRenderer for PathTracerImportance +impl ClassicalRenderer for PathTracerImportance where S: Scene, C: Camera, R: Rng, { - fn render_pixel(&self, x: u32, y: u32, rng: &mut R) -> Color { + fn render_pixel(&self, scene: &S, camera: &C, x: u32, y: u32, rng: &mut R) -> Color { let mut sum = Color::black(); let mut alpha = Color::white(); - let mut r = self.camera.forward(x, y, rng); + let mut r = camera.forward(x, y, rng); let mut count = 0; - while let Some(i) = self.scene.intersect(r, 0.001, Float::INFINITY) { + while let Some(i) = scene.intersect(r, 0.001, Float::INFINITY) { let frame = i.tangent_frame(); let w_in = frame.to_frame(-r.dir()); @@ -68,10 +64,10 @@ where } fn width(&self) -> u32 { - self.camera.width() + self.width } fn height(&self) -> u32 { - self.camera.height() + self.height } } diff --git a/ray-tracing-scene/src/examples.rs b/ray-tracing-scene/src/examples.rs new file mode 100644 index 0000000..a5036fc --- /dev/null +++ b/ray-tracing-scene/src/examples.rs @@ -0,0 +1,100 @@ +use ray_tracing_core::{light::AreaLight, prelude::*}; +use ray_tracing_material::{diffuse::DiffuseMaterial, mirror::Mirror}; +use std::collections::HashMap; + +use crate::triangle_bvh::{BVHMaterial, Triangle, TriangleBVH}; + +pub struct ExampleScene { + pub scene: TriangleBVH, + pub camera_pos: Pos3, + pub camera_dir: Dir3, + pub camera_up: Dir3, + pub horizontal_fov: Float, +} + +pub fn example_scenes() -> HashMap<&'static str, fn() -> ExampleScene> { + let mut map: HashMap<&str, fn() -> ExampleScene> = HashMap::new(); + map.insert("basic_cornel", basic_cornel::); + // map.insert("cornel2", cornel2::); + map +} + +pub fn cornel2() -> ExampleScene { + todo!() +} + +pub fn basic_cornel() -> ExampleScene { + let side_length = 1.5; + let light_size = 0.5; + let light_offset = 0.01; + let box_size = 0.3; + let scene = TriangleBVH::new( + vec![ + Pos3::new(side_length, side_length, side_length), + Pos3::new(side_length, side_length, -side_length), + Pos3::new(side_length, -side_length, side_length), + Pos3::new(side_length, -side_length, -side_length), + Pos3::new(-side_length, side_length, side_length), + Pos3::new(-side_length, side_length, -side_length), + Pos3::new(-side_length, -side_length, side_length), + Pos3::new(-side_length, -side_length, -side_length), + Pos3::new(light_size, side_length - light_offset, light_size), + Pos3::new(light_size, side_length - light_offset, -light_size), + Pos3::new(-light_size, side_length - light_offset, light_size), + Pos3::new(-light_size, side_length - light_offset, -light_size), + Pos3::new(box_size, -side_length, 0.0), + Pos3::new(0.0, -side_length, -box_size), + Pos3::new(-box_size, -side_length, 0.0), + Pos3::new(0.0, -side_length, box_size), + Pos3::new(0.0, box_size - side_length, 0.0), + ], + vec![ + Triangle::new([0, 1, 2], 0), + Triangle::new([1, 3, 2], 0), + Triangle::new([0, 4, 1], 0), + Triangle::new([1, 4, 5], 0), + Triangle::new([2, 3, 6], 0), + Triangle::new([3, 7, 6], 0), + Triangle::new([0, 2, 4], 1), + Triangle::new([6, 4, 2], 1), + Triangle::new([1, 5, 3], 2), + Triangle::new([7, 3, 5], 2), + Triangle::new([8, 10, 9], 3), + Triangle::new([11, 9, 10], 3), + Triangle::new([12, 13, 16], 4), + Triangle::new([13, 14, 16], 4), + Triangle::new([14, 15, 16], 4), + Triangle::new([15, 12, 16], 4), + ], + vec![ + BVHMaterial { + material: Some(Box::new(DiffuseMaterial::new(Color::new(0.8, 0.8, 0.8)))), + light: None, + }, + BVHMaterial { + material: Some(Box::new(DiffuseMaterial::new(Color::new(0.9, 0.0, 0.0)))), + light: None, + }, + BVHMaterial { + material: Some(Box::new(DiffuseMaterial::new(Color::new(0.0, 0.9, 0.0)))), + light: None, + }, + BVHMaterial { + material: None, + light: Some(Box::new(AreaLight::new(Color::white() * 30.0))), + }, + BVHMaterial { + material: Some(Box::new(Mirror::new(Color::new(1.0, 1.0, 1.0)))), + light: None, + }, + ], + ); + + ExampleScene { + scene, + camera_pos: Pos3::new(-6.0, 0.0, 0.0), + camera_dir: Dir3::new(1.0, 0.0, 0.0), + camera_up: Dir3::up(), + horizontal_fov: Float::to_radians(90.0), + } +} diff --git a/ray-tracing-scene/src/lib.rs b/ray-tracing-scene/src/lib.rs index 052ab74..87fb664 100644 --- a/ray-tracing-scene/src/lib.rs +++ b/ray-tracing-scene/src/lib.rs @@ -1,3 +1,4 @@ pub mod basic_scene; +pub mod examples; pub mod parse_obj; pub mod triangle_bvh; diff --git a/ray-tracing-scene/src/triangle_bvh.rs b/ray-tracing-scene/src/triangle_bvh.rs index 4858f4d..e70129d 100644 --- a/ray-tracing-scene/src/triangle_bvh.rs +++ b/ray-tracing-scene/src/triangle_bvh.rs @@ -14,9 +14,9 @@ pub struct TriangleBVH { } #[derive(Debug)] -struct BVHMaterial { - material: Option>>, - light: Option>>, +pub struct BVHMaterial { + pub material: Option>>, + pub light: Option>>, } #[derive(Debug, Clone, Copy)] @@ -40,7 +40,7 @@ pub struct Triangle { } impl Triangle { - fn new(vertices: [Index; 3], material: Index) -> Self { + pub fn new(vertices: [Index; 3], material: Index) -> Self { Triangle { vertices, material } } } @@ -167,7 +167,7 @@ fn build_bvh( } impl TriangleBVH { - fn new( + pub fn new( vertices: Vec, mut triangles: Vec, materials: Vec>, @@ -281,78 +281,3 @@ impl Scene for TriangleBVH { )) } } - -pub mod examples { - use super::{BVHMaterial, Triangle, TriangleBVH}; - use ray_tracing_core::{light::AreaLight, prelude::*}; - use ray_tracing_material::{diffuse::DiffuseMaterial, mirror::Mirror}; - use std::fmt::Debug; - - pub fn cornel() -> TriangleBVH { - let side_length = 1.5; - let light_size = 0.5; - let light_offset = 0.01; - let box_size = 0.3; - dbg!(TriangleBVH::new( - vec![ - Pos3::new(side_length, side_length, side_length), - Pos3::new(side_length, side_length, -side_length), - Pos3::new(side_length, -side_length, side_length), - Pos3::new(side_length, -side_length, -side_length), - Pos3::new(-side_length, side_length, side_length), - Pos3::new(-side_length, side_length, -side_length), - Pos3::new(-side_length, -side_length, side_length), - Pos3::new(-side_length, -side_length, -side_length), - Pos3::new(light_size, side_length - light_offset, light_size), - Pos3::new(light_size, side_length - light_offset, -light_size), - Pos3::new(-light_size, side_length - light_offset, light_size), - Pos3::new(-light_size, side_length - light_offset, -light_size), - Pos3::new(box_size, -side_length, 0.0), - Pos3::new(0.0, -side_length, -box_size), - Pos3::new(-box_size, -side_length, 0.0), - Pos3::new(0.0, -side_length, box_size), - Pos3::new(0.0, box_size - side_length, 0.0), - ], - vec![ - Triangle::new([0, 1, 2], 0), - Triangle::new([1, 3, 2], 0), - Triangle::new([0, 4, 1], 0), - Triangle::new([1, 4, 5], 0), - Triangle::new([2, 3, 6], 0), - Triangle::new([3, 7, 6], 0), - Triangle::new([0, 2, 4], 1), - Triangle::new([6, 4, 2], 1), - Triangle::new([1, 5, 3], 2), - Triangle::new([7, 3, 5], 2), - Triangle::new([8, 10, 9], 3), - Triangle::new([11, 9, 10], 3), - Triangle::new([12, 13, 16], 4), - Triangle::new([13, 14, 16], 4), - Triangle::new([14, 15, 16], 4), - Triangle::new([15, 12, 16], 4), - ], - vec![ - BVHMaterial { - material: Some(Box::new(DiffuseMaterial::new(Color::new(0.8, 0.8, 0.8)))), - light: None, - }, - BVHMaterial { - material: Some(Box::new(DiffuseMaterial::new(Color::new(0.9, 0.0, 0.0)))), - light: None, - }, - BVHMaterial { - material: Some(Box::new(DiffuseMaterial::new(Color::new(0.0, 0.9, 0.0)))), - light: None, - }, - BVHMaterial { - material: None, - light: Some(Box::new(AreaLight::new(Color::white() * 30.0))), - }, - BVHMaterial { - material: Some(Box::new(Mirror::new(Color::new(1.0, 1.0, 1.0)))), - light: None, - }, - ], - )) - } -} diff --git a/ray-tracing-tev/src/main.rs b/ray-tracing-tev/src/main.rs index 151191b..57fec0e 100644 --- a/ray-tracing-tev/src/main.rs +++ b/ray-tracing-tev/src/main.rs @@ -1,17 +1,28 @@ use rand::{rngs::SmallRng, SeedableRng}; -use ray_tracing_core::{camera::BasicCamera, prelude::*, renderer::ClassicalRenderer}; +use ray_tracing_core::{ + camera::{BasicCamera, Camera}, + prelude::*, + renderer::ClassicalRenderer, + scene::Scene, +}; use ray_tracing_renderer::{ depth_renderer::DepthRenderer, path_tracer::PathTracer, path_tracer_importance::PathTracerImportance, }; -use ray_tracing_scene::triangle_bvh::{examples::cornel, TriangleBVH}; +use ray_tracing_scene::{examples::basic_cornel, triangle_bvh::TriangleBVH}; use rayon::prelude::*; -use std::{net::TcpStream, path::Path}; +use std::net::TcpStream; use tev_client::{PacketCreateImage, PacketUpdateImage, TevClient, TevError}; -fn render_image + Sync>( - renderer: C, +fn render_image< + R: ClassicalRenderer + Sync, + S: Scene + Sync, + C: Camera + Sync, +>( name: impl AsRef, + renderer: &R, + scene: &S, + camera: &C, samples_per_pixel: usize, tev: &mut TevClient, ) -> Result<(), TevError> { @@ -23,7 +34,8 @@ fn render_image + Sync>( let mut rng = SmallRng::seed_from_u64((x + y * renderer.width()) as u64); for _ in 0..samples_per_pixel { - let r = renderer.render_pixel(x, y, &mut rng) / (samples_per_pixel as Float); + let r = + renderer.render_pixel(scene, camera, x, y, &mut rng) / (samples_per_pixel as Float); c[0] += r.r(); c[1] += r.g(); c[2] += r.b(); @@ -57,44 +69,62 @@ fn render_image + Sync>( } fn get_scene() -> (TriangleBVH, BasicCamera) { - let s = cornel(); + let s = basic_cornel(); let c = BasicCamera::new( 400, 400, - Pos3::new(-6.0, 0.0, 0.0), - Dir3::new(1.0, 0.0, 0.0), - Dir3::up(), - Float::to_radians(90.0), + s.camera_pos, + s.camera_dir, + s.camera_up, + s.horizontal_fov, ); - (s, c) + (s.scene, c) } fn main() { let mut client = TevClient::wrap(TcpStream::connect("127.0.0.1:14158").unwrap()); let (s, c) = get_scene(); - let r = DepthRenderer::new(s, c); - render_image(r, "depth renderer", 128, &mut client).unwrap(); + let width = 400; + let height = 400; + + let r = DepthRenderer::new(width, height); + render_image("depth renderer", &r, &s, &c, 128, &mut client).unwrap(); let samples_per_pixel = 1024; - let (s, c) = get_scene(); - let r = PathTracer::new(s, c); - render_image(r, "example path tracer", samples_per_pixel, &mut client).unwrap(); - - let (s, c) = get_scene(); - let r = PathTracerImportance::new(s, c); + let r = PathTracer::new(width, height); render_image( - r, - "example path tracer importance 1024", + "example path tracer", + &r, + &s, + &c, samples_per_pixel, &mut client, ) .unwrap(); - let (s, c) = get_scene(); - let r = PathTracerImportance::new(s, c); - render_image(r, "example path tracer importance 2048", 2048, &mut client).unwrap(); + let r = PathTracerImportance::new(width, height); + render_image( + "example path tracer importance 1024", + &r, + &s, + &c, + samples_per_pixel, + &mut client, + ) + .unwrap(); + + let r = PathTracerImportance::new(width, height); + render_image( + "example path tracer importance 2048", + &r, + &s, + &c, + 2048, + &mut client, + ) + .unwrap(); }