library: document render module

This commit is contained in:
Antoine Martin 2020-03-22 01:51:04 +01:00
parent a9fd726a0d
commit 64125dbc43
4 changed files with 127 additions and 0 deletions

View file

@ -1,8 +1,11 @@
//! Utility module to compute overall illumination
use crate::light::*; use crate::light::*;
use serde::Deserialize; use serde::Deserialize;
use std::iter::Iterator; use std::iter::Iterator;
#[derive(Debug, PartialEq, Deserialize)] #[derive(Debug, PartialEq, Deserialize)]
/// A struct centralizing the light computation logic.
pub struct LightAggregate { pub struct LightAggregate {
#[serde(default)] #[serde(default)]
ambients: Vec<AmbientLight>, ambients: Vec<AmbientLight>,
@ -15,10 +18,39 @@ pub struct LightAggregate {
} }
impl LightAggregate { impl LightAggregate {
/// Creates a new empty `LightAggregate`.
///
/// # Examples
///
/// ```
/// # use pathtracer::render::LightAggregate;
/// #
/// let la = LightAggregate::empty();
/// assert_eq!(la.ambient_lights_iter().count(), 0);
/// assert_eq!(la.spatial_lights_iter().count(), 0);
/// ```
pub fn empty() -> Self { pub fn empty() -> Self {
LightAggregate::new(vec![], vec![], vec![], vec![]) LightAggregate::new(vec![], vec![], vec![], vec![])
} }
/// Creates a new `LightAggregate` from `Vec`s of [`Light`]s.
///
/// [`Light`]: ../../light/trait.Light.html
///
/// # Examples
///
/// ```
/// # use pathtracer::render::LightAggregate;
/// #
/// let la = LightAggregate::new(
/// Vec::new(),
/// Vec::new(),
/// Vec::new(),
/// Vec::new(),
/// );
/// assert_eq!(la.ambient_lights_iter().count(), 0);
/// assert_eq!(la.spatial_lights_iter().count(), 0);
/// ```
pub fn new( pub fn new(
ambients: Vec<AmbientLight>, ambients: Vec<AmbientLight>,
directionals: Vec<DirectionalLight>, directionals: Vec<DirectionalLight>,
@ -33,10 +65,21 @@ impl LightAggregate {
} }
} }
/// Returns an iterator over the aggregate's [`AmbientLight`]s.
///
/// [`AmbientLight`]: ../../light/ambient_light/struct.AmbientLight.html
pub fn ambient_lights_iter(&self) -> impl Iterator<Item = &'_ dyn Light> { pub fn ambient_lights_iter(&self) -> impl Iterator<Item = &'_ dyn Light> {
self.ambients.iter().map(|l| l as &dyn Light) self.ambients.iter().map(|l| l as &dyn Light)
} }
/// Returns an iterator over the aggregate's [`SpatialLight`]s.
///
/// This simply merges iterators over [`DirectionalLight`], [`PointLight`] and [`SpotLight`].
///
/// [`SpatialLight`]: ../../light/trait.SpatialLight.html
/// [`DirectionalLight`]: ../../light/directional_light/struct.DirectionalLight.html
/// [`PointLight`]: ../../light/point_light/struct.PointLight.html
/// [`Spotight`]: ../../light/spot_light/struct.Spotight.html
pub fn spatial_lights_iter(&self) -> impl Iterator<Item = &'_ dyn SpatialLight> { pub fn spatial_lights_iter(&self) -> impl Iterator<Item = &'_ dyn SpatialLight> {
self.directionals self.directionals
.iter() .iter()

View file

@ -1,3 +1,5 @@
//! Rendering logic
pub mod light_aggregate; pub mod light_aggregate;
pub use light_aggregate::*; pub use light_aggregate::*;

View file

@ -1,3 +1,5 @@
//! Logic for the scene objects
use crate::material::MaterialEnum; use crate::material::MaterialEnum;
use crate::shape::{Shape, ShapeEnum}; use crate::shape::{Shape, ShapeEnum};
use crate::texture::TextureEnum; use crate::texture::TextureEnum;
@ -8,14 +10,42 @@ use serde::Deserialize;
/// An object being rendered in the scene. /// An object being rendered in the scene.
#[derive(Debug, PartialEq, Deserialize)] #[derive(Debug, PartialEq, Deserialize)]
pub struct Object { pub struct Object {
/// The `Object`'s physical shape
pub shape: ShapeEnum, pub shape: ShapeEnum,
/// The `Object`'s material
pub material: MaterialEnum, pub material: MaterialEnum,
/// The `Object`'s texture
pub texture: TextureEnum, pub texture: TextureEnum,
#[serde(skip_deserializing)] #[serde(skip_deserializing)]
/// Index inside the `BVH`
index: usize, index: usize,
} }
impl Object { impl Object {
/// Creates a new `Object`.
///
/// # Examples
///
/// ```
/// # use pathtracer::core::{LightProperties, LinearColor};
/// # use pathtracer::material::UniformMaterial;
/// # use pathtracer::render::Object;
/// # use pathtracer::shape::Sphere;
/// # use pathtracer::texture::UniformTexture;
/// # use pathtracer::Point;
/// #
/// let obj = Object::new(
/// Sphere::new(Point::origin(), 1.0).into(),
/// UniformMaterial::new(
/// LightProperties::new(
/// LinearColor::new(1.0, 0.0, 0.0), // diffuse component
/// LinearColor::new(0.0, 0.0, 0.0), // specular component
/// None,
/// ),
/// ).into(),
/// UniformTexture::new(LinearColor::new(0.5, 0.5, 0.5)).into(),
/// );
/// ```
pub fn new(shape: ShapeEnum, material: MaterialEnum, texture: TextureEnum) -> Self { pub fn new(shape: ShapeEnum, material: MaterialEnum, texture: TextureEnum) -> Self {
Object { Object {
shape, shape,

View file

@ -1,3 +1,5 @@
//! Scene rendering logic
use std::cmp::Ordering; use std::cmp::Ordering;
use super::{light_aggregate::LightAggregate, object::Object}; use super::{light_aggregate::LightAggregate, object::Object};
@ -26,6 +28,39 @@ pub struct Scene {
} }
impl Scene { impl Scene {
/// Creates a new `Scene`.
///
/// # Examples
///
/// ```
/// # use pathtracer::core::{Camera, LightProperties, LinearColor};
/// # use pathtracer::material::UniformMaterial;
/// # use pathtracer::render::{LightAggregate, Object, Scene};
/// # use pathtracer::shape::Sphere;
/// # use pathtracer::texture::UniformTexture;
/// # use pathtracer::Point;
/// #
/// let scene = Scene::new(
/// Camera::default(),
/// LightAggregate::empty(),
/// vec![
/// Object::new(
/// Sphere::new(Point::origin(), 1.0).into(),
/// UniformMaterial::new(
/// LightProperties::new(
/// LinearColor::new(1.0, 0.0, 0.0), // diffuse component
/// LinearColor::new(0.0, 0.0, 0.0), // specular component
/// None,
/// ),
/// ).into(),
/// UniformTexture::new(LinearColor::new(0.5, 0.5, 0.5)).into(),
/// ),
/// ],
/// 5, // aliasing limit
/// 3, // reflection recursion limit
/// 0.0, // diffraction index
/// );
/// ```
pub fn new( pub fn new(
camera: Camera, camera: Camera,
lights: LightAggregate, lights: LightAggregate,
@ -34,6 +69,7 @@ impl Scene {
reflection_limit: u32, reflection_limit: u32,
diffraction_index: f32, diffraction_index: f32,
) -> Self { ) -> Self {
// NOTE(Antoine): fun fact: BVH::build stack overflows when given an empty slice :)
let bvh = BVH::build(&mut objects); let bvh = BVH::build(&mut objects);
Scene { Scene {
camera, camera,
@ -338,4 +374,20 @@ mod test {
let _: Scene = serde_yaml::from_str(yaml).unwrap(); let _: Scene = serde_yaml::from_str(yaml).unwrap();
// FIXME: actually test the equality ? // FIXME: actually test the equality ?
} }
#[test]
#[ignore] // stack overflow because of BVH :(
fn bvh_fails() {
use crate::core::Camera;
use crate::render::{LightAggregate, Scene};
let _scene = Scene::new(
Camera::default(),
LightAggregate::empty(),
Vec::new(), // Objects list
5, // aliasing limit
3, // reflection recursion limit
0.0, // diffraction index
);
}
} }