feat(scene): make render loop parallelized
This commit is contained in:
parent
587471f36a
commit
aab1fa0a5e
1
Cargo.lock
generated
1
Cargo.lock
generated
@ -513,6 +513,7 @@ dependencies = [
|
|||||||
"image",
|
"image",
|
||||||
"nalgebra",
|
"nalgebra",
|
||||||
"nix",
|
"nix",
|
||||||
|
"rayon",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|||||||
@ -24,3 +24,4 @@ futures = "0.3.30"
|
|||||||
image = "0.25.5"
|
image = "0.25.5"
|
||||||
nalgebra = "0.33.2"
|
nalgebra = "0.33.2"
|
||||||
nix = "0.29.0"
|
nix = "0.29.0"
|
||||||
|
rayon = "1.10.0"
|
||||||
|
|||||||
@ -1,3 +1,3 @@
|
|||||||
[toolchain]
|
[toolchain]
|
||||||
channel = "nightly"
|
channel = "1.80.1"
|
||||||
components = [ "rustfmt", "rustc-dev", "rust-analyzer", "rust-src"]
|
components = [ "rustfmt", "rustc-dev", "rust-analyzer", "rust-src"]
|
||||||
|
|||||||
@ -6,6 +6,7 @@ use lispers::raytracer::{
|
|||||||
types::{Color, Light, Material, Point3, Vector3},
|
types::{Color, Light, Material, Point3, Vector3},
|
||||||
};
|
};
|
||||||
extern crate nalgebra as na;
|
extern crate nalgebra as na;
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let mut scene = Scene::new();
|
let mut scene = Scene::new();
|
||||||
@ -21,7 +22,7 @@ fn main() {
|
|||||||
color: Color::new(1.0, 1.0, 1.0),
|
color: Color::new(1.0, 1.0, 1.0),
|
||||||
});
|
});
|
||||||
|
|
||||||
scene.add_object(Box::new(Plane::new(
|
scene.add_object(Arc::new(Plane::new(
|
||||||
Point3::new(0.0, -1.0, 0.0),
|
Point3::new(0.0, -1.0, 0.0),
|
||||||
Vector3::new(0.0, 1.0, 0.0),
|
Vector3::new(0.0, 1.0, 0.0),
|
||||||
Material::new(
|
Material::new(
|
||||||
@ -33,7 +34,7 @@ fn main() {
|
|||||||
),
|
),
|
||||||
)));
|
)));
|
||||||
|
|
||||||
scene.add_object(Box::new(Sphere::new(
|
scene.add_object(Arc::new(Sphere::new(
|
||||||
Point3::new(-2.0, 0.0, 1.0),
|
Point3::new(-2.0, 0.0, 1.0),
|
||||||
1.0,
|
1.0,
|
||||||
Material::new(
|
Material::new(
|
||||||
@ -45,7 +46,7 @@ fn main() {
|
|||||||
),
|
),
|
||||||
)));
|
)));
|
||||||
|
|
||||||
scene.add_object(Box::new(Sphere::new(
|
scene.add_object(Arc::new(Sphere::new(
|
||||||
Point3::new(0.2, -0.5, -0.2),
|
Point3::new(0.2, -0.5, -0.2),
|
||||||
0.5,
|
0.5,
|
||||||
Material::new(
|
Material::new(
|
||||||
@ -57,7 +58,7 @@ fn main() {
|
|||||||
),
|
),
|
||||||
)));
|
)));
|
||||||
|
|
||||||
scene.add_object(Box::new(Sphere::new(
|
scene.add_object(Arc::new(Sphere::new(
|
||||||
Point3::new(-0.5, 0.5, -2.0),
|
Point3::new(-0.5, 0.5, -2.0),
|
||||||
1.5,
|
1.5,
|
||||||
Material::new(
|
Material::new(
|
||||||
|
|||||||
@ -3,6 +3,7 @@ use super::{
|
|||||||
types::{Color, Point3, Ray, Scalar, Vector3},
|
types::{Color, Point3, Ray, Scalar, Vector3},
|
||||||
};
|
};
|
||||||
use image::RgbImage;
|
use image::RgbImage;
|
||||||
|
use rayon::prelude::*;
|
||||||
|
|
||||||
/// A camera that can render a scene.
|
/// A camera that can render a scene.
|
||||||
pub struct Camera {
|
pub struct Camera {
|
||||||
@ -77,12 +78,15 @@ impl Camera {
|
|||||||
/// - `subp` is the number of subpixels to use for antialiasing.
|
/// - `subp` is the number of subpixels to use for antialiasing.
|
||||||
pub fn render(&self, scene: &Scene, depth: u32, subp: u32) -> RgbImage {
|
pub fn render(&self, scene: &Scene, depth: u32, subp: u32) -> RgbImage {
|
||||||
let dx = 1.0 / self.width as Scalar;
|
let dx = 1.0 / self.width as Scalar;
|
||||||
let dy = 1.0 / self.width as Scalar;
|
let dy = 1.0 / self.height as Scalar;
|
||||||
let dsx = dx / subp as Scalar;
|
let dsx = dx / subp as Scalar;
|
||||||
let dsy = dy / subp as Scalar;
|
let dsy = dy / subp as Scalar;
|
||||||
RgbImage::from_fn(self.width as u32, self.height as u32, |x, y| {
|
let mut img = RgbImage::new(self.width as u32, self.height as u32);
|
||||||
let x = x as Scalar * dx;
|
|
||||||
|
img.enumerate_rows_mut().par_bridge().for_each(|(_, row)| {
|
||||||
|
for (x, y, pixel) in row {
|
||||||
let y = y as Scalar * dy;
|
let y = y as Scalar * dy;
|
||||||
|
let x = x as Scalar * dx;
|
||||||
let mut color = Color::new(0.0, 0.0, 0.0);
|
let mut color = Color::new(0.0, 0.0, 0.0);
|
||||||
for sx in 0..subp {
|
for sx in 0..subp {
|
||||||
for sy in 0..subp {
|
for sy in 0..subp {
|
||||||
@ -96,7 +100,9 @@ impl Camera {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
color *= 255.0 / (subp * subp) as Scalar;
|
color *= 255.0 / (subp * subp) as Scalar;
|
||||||
[color.x as u8, color.y as u8, color.z as u8].into()
|
*pixel = [color.x as u8, color.y as u8, color.z as u8].into();
|
||||||
})
|
}
|
||||||
|
});
|
||||||
|
img
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -7,6 +7,7 @@ use super::types::Ray;
|
|||||||
use super::types::Vector3;
|
use super::types::Vector3;
|
||||||
use super::vec::mirror;
|
use super::vec::mirror;
|
||||||
use super::vec::reflect;
|
use super::vec::reflect;
|
||||||
|
use std::sync::Arc;
|
||||||
extern crate nalgebra as na;
|
extern crate nalgebra as na;
|
||||||
|
|
||||||
/// A scene is a collection of objects and lights, and provides a method to trace a ray through the scene.
|
/// A scene is a collection of objects and lights, and provides a method to trace a ray through the scene.
|
||||||
@ -14,7 +15,7 @@ pub struct Scene {
|
|||||||
/// The ambient light of the scene
|
/// The ambient light of the scene
|
||||||
ambient: Color,
|
ambient: Color,
|
||||||
/// The objects in the scene
|
/// The objects in the scene
|
||||||
objects: Vec<Box<dyn Intersect>>,
|
objects: Vec<Arc<dyn Intersect + Send + Sync>>,
|
||||||
/// The lights in the scene
|
/// The lights in the scene
|
||||||
lights: Vec<Light>,
|
lights: Vec<Light>,
|
||||||
}
|
}
|
||||||
@ -35,7 +36,7 @@ impl Scene {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Add an object to the scene
|
/// Add an object to the scene
|
||||||
pub fn add_object(&mut self, obj: Box<dyn Intersect>) {
|
pub fn add_object(&mut self, obj: Arc<dyn Intersect + Send + Sync>) {
|
||||||
self.objects.push(obj);
|
self.objects.push(obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user