Refactoring
This commit is contained in:
parent
226ff88874
commit
3226e9c965
10 changed files with 316 additions and 95 deletions
|
|
@ -8,6 +8,7 @@ use core::ops::{
|
||||||
Add, AddAssign, Div, DivAssign, Index, IndexMut, Mul, MulAssign, Neg, Sub, SubAssign,
|
Add, AddAssign, Div, DivAssign, Index, IndexMut, Mul, MulAssign, Neg, Sub, SubAssign,
|
||||||
};
|
};
|
||||||
use num_traits::{AsPrimitive, FloatConst, Num, Signed, Zero};
|
use num_traits::{AsPrimitive, FloatConst, Num, Signed, Zero};
|
||||||
|
use core::fmt;
|
||||||
|
|
||||||
pub trait MulAdd<M = Self, A = Self> {
|
pub trait MulAdd<M = Self, A = Self> {
|
||||||
type Output;
|
type Output;
|
||||||
|
|
@ -35,6 +36,45 @@ pub struct Point<T, const N: usize>(pub [T; N]);
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||||
pub struct Normal<T, const N: usize>(pub [T; N]);
|
pub struct Normal<T, const N: usize>(pub [T; N]);
|
||||||
|
|
||||||
|
impl<T: fmt::Display, const N: usize> fmt::Display for Vector<T, N> {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
write!(f, "Vector(")?;
|
||||||
|
for (i, item) in (&self.0).into_iter().enumerate() {
|
||||||
|
if i > 0 {
|
||||||
|
write!(f, ", ")?;
|
||||||
|
}
|
||||||
|
write!(f, "{}", item)?;
|
||||||
|
}
|
||||||
|
write!(f, ")")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: fmt::Display, const N: usize> fmt::Display for Point<T, N> {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
write!(f, "Point(")?;
|
||||||
|
for (i, item) in (&self.0).into_iter().enumerate() {
|
||||||
|
if i > 0 {
|
||||||
|
write!(f, ", ")?;
|
||||||
|
}
|
||||||
|
write!(f, "{}", item)?;
|
||||||
|
}
|
||||||
|
write!(f, ")")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: fmt::Display, const N: usize> fmt::Display for Normal<T, N> {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
write!(f, "Normal(")?;
|
||||||
|
for (i, item) in (&self.0).into_iter().enumerate() {
|
||||||
|
if i > 0 {
|
||||||
|
write!(f, ", ")?;
|
||||||
|
}
|
||||||
|
write!(f, "{}", item)?;
|
||||||
|
}
|
||||||
|
write!(f, ")")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! impl_tuple_core {
|
macro_rules! impl_tuple_core {
|
||||||
($Struct:ident) => {
|
($Struct:ident) => {
|
||||||
|
|
|
||||||
|
|
@ -194,3 +194,10 @@ pub enum Material {
|
||||||
Mix(MixMaterial),
|
Mix(MixMaterial),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// TODO: THIS IS A HACK JUST FOR TESTING
|
||||||
|
impl PartialEq for Material {
|
||||||
|
fn eq(&self, other: &Self) -> bool {
|
||||||
|
core::mem::discriminant(self) == core::mem::discriminant(other)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,22 @@
|
||||||
use crate::core::scene::BasicScene;
|
use crate::core::scene::BasicScene;
|
||||||
|
use crate::globals::get_options;
|
||||||
|
use crate::integrators::pipeline::render;
|
||||||
use crate::Arena;
|
use crate::Arena;
|
||||||
use anyhow::Result;
|
use anyhow::{bail, Result};
|
||||||
use log::warn;
|
use log::warn;
|
||||||
use shared::core::camera::CameraTrait;
|
use shared::core::camera::CameraTrait;
|
||||||
|
use shared::core::geometry::{Point2f, Vector2f};
|
||||||
|
use shared::core::interaction::InteractionTrait;
|
||||||
|
use shared::core::primitive::PrimitiveTrait;
|
||||||
|
use shared::core::sampler::CameraSample;
|
||||||
|
use shared::spectra::{SampledWavelengths, LAMBDA_MAX, LAMBDA_MIN};
|
||||||
|
use shared::Float;
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
fn render_scene(scene: &BasicScene, arena: &Arena) -> Result<()> {
|
fn render_scene(scene: &BasicScene, arena: &Arena) -> Result<()> {
|
||||||
let media = scene.create_media();
|
let media = scene.create_media();
|
||||||
let textures = scene.create_textures(arena);
|
let textures = scene.create_textures(arena);
|
||||||
let lights = scene.create_lights()
|
let (lights, _) = scene.create_lights(&textures, arena);
|
||||||
let (named_materials, materials) = scene.create_materials(&textures, arena)?;
|
let (named_materials, materials) = scene.create_materials(&textures, arena)?;
|
||||||
let (aggregate, area_lights) =
|
let (aggregate, area_lights) =
|
||||||
scene.create_aggregate(&textures, &named_materials, &materials, arena);
|
scene.create_aggregate(&textures, &named_materials, &materials, arena);
|
||||||
|
|
@ -15,6 +24,90 @@ fn render_scene(scene: &BasicScene, arena: &Arena) -> Result<()> {
|
||||||
let film = camera.get_film();
|
let film = camera.get_film();
|
||||||
warn!("Creating integrator");
|
warn!("Creating integrator");
|
||||||
let sampler = scene.get_sampler()?;
|
let sampler = scene.get_sampler()?;
|
||||||
let integrator = scene.create_integrator(camera, sampler, aggregate, lights, arena);
|
let integrator = scene.create_integrator(camera.clone(), sampler.clone(), aggregate.clone(), lights, arena);
|
||||||
|
let mut have_scattering = false;
|
||||||
|
for sh in scene.shapes.lock().iter() {
|
||||||
|
if !sh.inside_medium.is_empty() || !sh.outside_medium.is_empty() {
|
||||||
|
have_scattering = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for sh in scene.animated_shapes.lock().iter() {
|
||||||
|
if !sh.inside_medium.is_empty() || !sh.outside_medium.is_empty() {
|
||||||
|
have_scattering = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if get_options().pixel_material.is_some() {
|
||||||
|
let lambda =
|
||||||
|
SampledWavelengths::sample_uniform(0.5, LAMBDA_MIN as Float, LAMBDA_MAX as Float);
|
||||||
|
let cs = CameraSample {
|
||||||
|
p_film: Point2f::from(get_options().pixel_material.unwrap()) + Vector2f::new(0.5, 0.5),
|
||||||
|
time: 0.5,
|
||||||
|
p_lens: Point2f::new(0.5, 0.5),
|
||||||
|
filter_weight: 1.,
|
||||||
|
};
|
||||||
|
|
||||||
|
let Some(cr) = camera.generate_ray_differential(cs, &lambda) else {
|
||||||
|
bail!("Unable to generate ray for pixel")
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut depth = 1;
|
||||||
|
let mut ray = cr.ray;
|
||||||
|
loop {
|
||||||
|
if let Some(isect) = aggregate.intersect(&ray, Some(Float::INFINITY)) {
|
||||||
|
let intr = isect.intr;
|
||||||
|
if intr.material.is_null() {
|
||||||
|
log::warn!("Ignoring material")
|
||||||
|
} else {
|
||||||
|
let world_from_render = camera.base().camera_transform.world_from_render;
|
||||||
|
log::debug!("Intersection depth {}\n", depth);
|
||||||
|
log::debug!(
|
||||||
|
"World-space p: {}\n",
|
||||||
|
world_from_render.apply_to_point(intr.p())
|
||||||
|
);
|
||||||
|
log::debug!(
|
||||||
|
"World-space n: {}\n",
|
||||||
|
world_from_render.apply_to_normal(intr.n())
|
||||||
|
);
|
||||||
|
log::debug!(
|
||||||
|
"World-space ns: {}\n",
|
||||||
|
world_from_render.apply_to_normal(intr.shading.n)
|
||||||
|
);
|
||||||
|
log::debug!("Distance from camera: {}\n", intr.p().distance(cr.ray.o));
|
||||||
|
|
||||||
|
let mut is_named = false;
|
||||||
|
for (name, mtl) in &named_materials {
|
||||||
|
if *mtl == unsafe { *intr.material.as_ref() } {
|
||||||
|
log::debug!("Named material: {}\n\n", name);
|
||||||
|
is_named = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// if !is_named {
|
||||||
|
// log::warn!("{}\n\n", intr.material.as_ref().to_str());
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
|
||||||
|
depth += 1;
|
||||||
|
ray = intr.spawn_ray(ray.d);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if depth == 1 {
|
||||||
|
bail!("No geometry visible from pixel")
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
render(
|
||||||
|
&integrator,
|
||||||
|
&integrator.base,
|
||||||
|
&camera,
|
||||||
|
sampler.as_ref(),
|
||||||
|
arena,
|
||||||
|
);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,6 @@ use super::entities::*;
|
||||||
use super::BasicScene;
|
use super::BasicScene;
|
||||||
use crate::spectra::get_colorspace_device;
|
use crate::spectra::get_colorspace_device;
|
||||||
use crate::utils::error::FileLoc;
|
use crate::utils::error::FileLoc;
|
||||||
use crate::utils::normalize_utf8;
|
|
||||||
use crate::utils::parameters::{ParameterDictionary, ParsedParameterVector};
|
use crate::utils::parameters::{ParameterDictionary, ParsedParameterVector};
|
||||||
use crate::utils::parser::{ParserError, ParserTarget};
|
use crate::utils::parser::{ParserError, ParserTarget};
|
||||||
use crate::Arena;
|
use crate::Arena;
|
||||||
|
|
@ -17,9 +16,14 @@ use shared::Float;
|
||||||
use std::collections::{HashMap, HashSet};
|
use std::collections::{HashMap, HashSet};
|
||||||
use std::ops::{Index, IndexMut};
|
use std::ops::{Index, IndexMut};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
use unicode_normalization::UnicodeNormalization;
|
||||||
|
|
||||||
const MAX_TRANSFORMS: usize = 2;
|
const MAX_TRANSFORMS: usize = 2;
|
||||||
|
|
||||||
|
fn normalize_utf8(input: &str) -> String {
|
||||||
|
input.nfc().collect::<String>()
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Default, Clone, Copy)]
|
#[derive(Debug, Default, Clone, Copy)]
|
||||||
struct TransformSet {
|
struct TransformSet {
|
||||||
t: [Transform; MAX_TRANSFORMS],
|
t: [Transform; MAX_TRANSFORMS],
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,7 @@ use shared::core::shape::Shape;
|
||||||
use shared::core::texture::{GPUFloatTexture, SpectrumType};
|
use shared::core::texture::{GPUFloatTexture, SpectrumType};
|
||||||
use shared::lights::sampler::LightSampler;
|
use shared::lights::sampler::LightSampler;
|
||||||
use shared::spectra::RGBColorSpace;
|
use shared::spectra::RGBColorSpace;
|
||||||
|
use shared::textures::FloatConstantTexture;
|
||||||
use shared::{Ptr, Transform};
|
use shared::{Ptr, Transform};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
@ -508,52 +509,165 @@ impl BasicScene {
|
||||||
Ok((named_materials, materials))
|
Ok((named_materials, materials))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn create_lights(&self, camera_transform: &CameraTransform, arena: &Arena) -> Vec<Light> {
|
pub fn create_lights(
|
||||||
let state = self.light_state.lock();
|
&self,
|
||||||
|
textures: &NamedTextures,
|
||||||
|
arena: &Arena,
|
||||||
|
) -> (Vec<Arc<Light>>, HashMap<usize, Vec<Arc<Light>>>) {
|
||||||
|
let shape_entities = self.shapes.lock();
|
||||||
|
let light_state = self.light_state.lock();
|
||||||
|
let material_state = self.material_state.lock();
|
||||||
|
|
||||||
state
|
let mut all_lights: Vec<Arc<Light>> = Vec::new();
|
||||||
.lights
|
let mut shape_index_to_area_lights: HashMap<usize, Vec<Arc<Light>>> = HashMap::new();
|
||||||
.iter()
|
|
||||||
.filter_map(|entity| {
|
|
||||||
let render_from_light = entity.transformed_base.render_from_object.start_transform;
|
|
||||||
|
|
||||||
let medium = self
|
for (i, entity) in shape_entities.iter().enumerate() {
|
||||||
.get_medium(&entity.medium, &entity.transformed_base.base.loc)
|
let light_idx = match entity.light_index {
|
||||||
.map(|m| *m);
|
Some(idx) => idx,
|
||||||
|
None => continue,
|
||||||
|
};
|
||||||
|
|
||||||
match crate::core::light::create_light(
|
let material_name = match &entity.material {
|
||||||
&entity.transformed_base.base.name,
|
MaterialRef::Name(name) => {
|
||||||
render_from_light,
|
match material_state
|
||||||
medium,
|
.named_materials
|
||||||
&entity.transformed_base.base.parameters,
|
.iter()
|
||||||
&entity.transformed_base.base.loc,
|
.find(|(n, _)| n == name)
|
||||||
camera_transform.clone(),
|
{
|
||||||
arena,
|
Some((_, mtl_entity)) => {
|
||||||
) {
|
match mtl_entity.parameters.get_one_string("type", "") {
|
||||||
Ok(light) => Some(light),
|
Ok(t) if !t.is_empty() => t,
|
||||||
Err(e) => {
|
_ => {
|
||||||
log::error!(
|
log::error!(
|
||||||
"{}: failed to create light: {}",
|
"{}: named material '{}' missing type",
|
||||||
entity.transformed_base.base.loc,
|
entity.base.loc,
|
||||||
e
|
name
|
||||||
);
|
);
|
||||||
None
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
log::error!(
|
||||||
|
"{}: no named material '{}' defined.",
|
||||||
|
entity.base.loc,
|
||||||
|
name
|
||||||
|
);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
MaterialRef::Index(idx) => match material_state.materials.get(*idx) {
|
||||||
.collect()
|
Some(mtl_entity) => mtl_entity.name.clone(),
|
||||||
|
None => {
|
||||||
|
log::error!("{}: material index {} out of bounds", entity.base.loc, idx);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
MaterialRef::None => String::new(),
|
||||||
|
};
|
||||||
|
|
||||||
|
if material_name == "interface" || material_name == "none" || material_name.is_empty() {
|
||||||
|
log::warn!(
|
||||||
|
"{}: Ignoring area light specification for shape with \"interface\" material.",
|
||||||
|
entity.base.loc
|
||||||
|
);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
let shape_objects = match Shape::create(
|
||||||
|
&entity.base.name,
|
||||||
|
*entity.render_from_object,
|
||||||
|
*entity.object_from_render,
|
||||||
|
entity.reverse_orientation,
|
||||||
|
entity.base.parameters.clone(),
|
||||||
|
&textures.float_textures,
|
||||||
|
entity.base.loc.clone(),
|
||||||
|
arena,
|
||||||
|
) {
|
||||||
|
Ok(shapes) => shapes,
|
||||||
|
Err(e) => {
|
||||||
|
log::error!("{}: failed to create shape: {}", entity.base.loc, e);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if shape_objects.is_empty() {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
let alpha_tex = Self::get_alpha_texture(
|
||||||
|
&entity.base.parameters,
|
||||||
|
&entity.base.loc,
|
||||||
|
&textures.float_textures,
|
||||||
|
);
|
||||||
|
let default_alpha = Arc::new(FloatTexture::default());
|
||||||
|
let alpha_ref = alpha_tex.as_ref().unwrap_or(&default_alpha);
|
||||||
|
|
||||||
|
let inside = self.get_medium(&entity.inside_medium, &entity.base.loc);
|
||||||
|
let outside = self.get_medium(&entity.outside_medium, &entity.base.loc);
|
||||||
|
let medium_interface = MediumInterface {
|
||||||
|
inside: inside
|
||||||
|
.as_ref()
|
||||||
|
.map(|m| Ptr::from(m.as_ref()))
|
||||||
|
.unwrap_or(Ptr::null()),
|
||||||
|
outside: outside
|
||||||
|
.as_ref()
|
||||||
|
.map(|m| Ptr::from(m.as_ref()))
|
||||||
|
.unwrap_or(Ptr::null()),
|
||||||
|
};
|
||||||
|
|
||||||
|
let al_entity = &light_state.area_lights[light_idx];
|
||||||
|
|
||||||
|
let film_cs = self.film_colorspace.lock();
|
||||||
|
let colorspace_ref = al_entity
|
||||||
|
.parameters
|
||||||
|
.color_space
|
||||||
|
.as_ref()
|
||||||
|
.or(film_cs.as_ref());
|
||||||
|
|
||||||
|
let mut shape_lights: Vec<Arc<Light>> = Vec::new();
|
||||||
|
|
||||||
|
for shape in &shape_objects {
|
||||||
|
let cs = colorspace_ref.map(|cs| cs.as_ref());
|
||||||
|
match crate::core::light::create_area_light(
|
||||||
|
*entity.render_from_object,
|
||||||
|
None,
|
||||||
|
&al_entity.parameters,
|
||||||
|
&al_entity.loc,
|
||||||
|
shape,
|
||||||
|
alpha_ref,
|
||||||
|
cs,
|
||||||
|
arena,
|
||||||
|
) {
|
||||||
|
Ok(light) => {
|
||||||
|
let light_arc = Arc::new(light);
|
||||||
|
all_lights.push(Arc::clone(&light_arc));
|
||||||
|
shape_lights.push(light_arc);
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
log::error!("{}: failed to create area light: {}", al_entity.loc, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !shape_lights.is_empty() {
|
||||||
|
shape_index_to_area_lights.insert(i, shape_lights);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
log::debug!("Finished area lights");
|
||||||
|
|
||||||
|
(all_lights, shape_index_to_area_lights)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create area lights for shapes that reference one. Produces a map from
|
|
||||||
/// shape index to a vec of lights.
|
|
||||||
/// Must be called after shapes are loaded but before upload_shapes.
|
|
||||||
pub fn create_area_lights(
|
pub fn create_area_lights(
|
||||||
&self,
|
&self,
|
||||||
loaded_shapes: &[Vec<Shape>],
|
loaded_shapes: &[Vec<Shape>],
|
||||||
shape_entities: &[ShapeSceneEntity],
|
|
||||||
textures: &NamedTextures,
|
textures: &NamedTextures,
|
||||||
arena: &Arena,
|
arena: &Arena,
|
||||||
) -> HashMap<usize, Vec<Light>> {
|
) -> HashMap<usize, Vec<Light>> {
|
||||||
|
let shape_entities = &self.shapes.lock();
|
||||||
let light_state = self.light_state.lock();
|
let light_state = self.light_state.lock();
|
||||||
let mut shape_lights: HashMap<usize, Vec<Light>> = HashMap::new();
|
let mut shape_lights: HashMap<usize, Vec<Light>> = HashMap::new();
|
||||||
|
|
||||||
|
|
@ -681,7 +795,7 @@ impl BasicScene {
|
||||||
sampler: Arc<Sampler>,
|
sampler: Arc<Sampler>,
|
||||||
aggregate: Arc<Primitive>,
|
aggregate: Arc<Primitive>,
|
||||||
lights: Vec<Arc<Light>>,
|
lights: Vec<Arc<Light>>,
|
||||||
arena: &Arena
|
arena: &Arena,
|
||||||
) -> PathIntegrator {
|
) -> PathIntegrator {
|
||||||
let integrator = &self.integrator.lock().clone().unwrap();
|
let integrator = &self.integrator.lock().clone().unwrap();
|
||||||
PathIntegrator::create(
|
PathIntegrator::create(
|
||||||
|
|
@ -691,7 +805,7 @@ impl BasicScene {
|
||||||
aggregate,
|
aggregate,
|
||||||
lights,
|
lights,
|
||||||
PathConfig::SIMPLE,
|
PathConfig::SIMPLE,
|
||||||
arena
|
arena,
|
||||||
)
|
)
|
||||||
.expect("Integrator creation has failed")
|
.expect("Integrator creation has failed")
|
||||||
}
|
}
|
||||||
|
|
@ -1114,12 +1228,23 @@ impl BasicScene {
|
||||||
textures: &HashMap<String, Arc<FloatTexture>>,
|
textures: &HashMap<String, Arc<FloatTexture>>,
|
||||||
) -> Option<Arc<FloatTexture>> {
|
) -> Option<Arc<FloatTexture>> {
|
||||||
let name = params.get_texture("alpha");
|
let name = params.get_texture("alpha");
|
||||||
if name.is_empty() {
|
if !name.is_empty() {
|
||||||
return None;
|
match textures.get(&name) {
|
||||||
}
|
Some(tex) => Some(tex.clone()),
|
||||||
match textures.get(&name) {
|
None => panic!(
|
||||||
Some(tex) => Some(tex.clone()),
|
"{}: couldn't find float texture '{}' for \"alpha\" parameter.",
|
||||||
None => panic!("{:?}: Alpha texture '{}' not found", loc, name),
|
loc, name
|
||||||
|
),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let alpha = params.get_one_float("alpha", 1.0).unwrap();
|
||||||
|
if alpha < 1.0 {
|
||||||
|
Some(Arc::new(FloatTexture::Constant(FloatConstantTexture::new(
|
||||||
|
alpha,
|
||||||
|
))))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -66,7 +66,7 @@ impl CreateIntegrator for PathIntegrator {
|
||||||
) -> Result<PathIntegrator> {
|
) -> Result<PathIntegrator> {
|
||||||
let _max_depth = parameters.get_one_int("maxdepth", 5)?;
|
let _max_depth = parameters.get_one_int("maxdepth", 5)?;
|
||||||
let _regularize = parameters.get_one_bool("regularize", false)?;
|
let _regularize = parameters.get_one_bool("regularize", false)?;
|
||||||
let light_sampler = create_light_sampler("bvh", &lights, arena);
|
let light_sampler = create_light_sampler("power", &lights, arena);
|
||||||
let integrator = PathIntegrator::new(aggregate, lights, camera, light_sampler, config);
|
let integrator = PathIntegrator::new(aggregate, lights, camera, light_sampler, config);
|
||||||
Ok(integrator)
|
Ok(integrator)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -78,7 +78,7 @@ pub fn render<T>(
|
||||||
_base: &IntegratorBase,
|
_base: &IntegratorBase,
|
||||||
camera: &Camera,
|
camera: &Camera,
|
||||||
sampler_prototype: &Sampler,
|
sampler_prototype: &Sampler,
|
||||||
arena: Arc<Arena>,
|
arena: &Arena,
|
||||||
) where
|
) where
|
||||||
T: RayIntegratorTrait + Sync,
|
T: RayIntegratorTrait + Sync,
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,6 @@ pub mod mipmap;
|
||||||
pub mod parallel;
|
pub mod parallel;
|
||||||
pub mod parameters;
|
pub mod parameters;
|
||||||
pub mod parser;
|
pub mod parser;
|
||||||
pub mod strings;
|
|
||||||
pub mod upload;
|
pub mod upload;
|
||||||
|
|
||||||
pub use error::FileLoc;
|
pub use error::FileLoc;
|
||||||
|
|
@ -16,7 +15,6 @@ pub use file::{read_float_file, resolve_filename};
|
||||||
pub use parameters::{
|
pub use parameters::{
|
||||||
ParameterDictionary, ParsedParameter, ParsedParameterVector, TextureParameterDictionary,
|
ParameterDictionary, ParsedParameter, ParsedParameterVector, TextureParameterDictionary,
|
||||||
};
|
};
|
||||||
pub use strings::*;
|
|
||||||
pub use mipmap::{MIPMap, MIPMapFilterOptions};
|
pub use mipmap::{MIPMap, MIPMapFilterOptions};
|
||||||
pub use upload::{Upload, ArenaUpload};
|
pub use upload::{Upload, ArenaUpload};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,47 +1,6 @@
|
||||||
use crossbeam_channel::{Receiver, bounded};
|
use crossbeam_channel::{Receiver, bounded};
|
||||||
use rayon::prelude::*;
|
use rayon::prelude::*;
|
||||||
|
|
||||||
pub fn init_parallel(n_threads: usize) {
|
|
||||||
let threads = if n_threads == 0 {
|
|
||||||
num_cpus::get()
|
|
||||||
} else {
|
|
||||||
n_threads
|
|
||||||
};
|
|
||||||
|
|
||||||
if let Err(e) = rayon::ThreadPoolBuilder::new()
|
|
||||||
.num_threads(threads)
|
|
||||||
.build_global()
|
|
||||||
{
|
|
||||||
eprintln!("Warning: Rayon thread pool already initialized: {}", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn num_system_cores() -> usize {
|
|
||||||
num_cpus::get()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn max_concurrency() -> usize {
|
|
||||||
rayon::current_num_threads()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn parallel_for<F>(start: i64, end: i64, func: F)
|
|
||||||
where
|
|
||||||
F: Fn(i64) + Sync + Send,
|
|
||||||
{
|
|
||||||
(start..end).into_par_iter().for_each(|i| func(i));
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn parallel_for_2d<F>(start_x: i64, end_x: i64, start_y: i64, end_y: i64, func: F)
|
|
||||||
where
|
|
||||||
F: Fn(i64, i64) + Sync + Send,
|
|
||||||
{
|
|
||||||
(start_y..end_y).into_par_iter().for_each(|y| {
|
|
||||||
(start_x..end_x).into_par_iter().for_each(|x| {
|
|
||||||
func(x, y);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct AsyncJob<T> {
|
pub struct AsyncJob<T> {
|
||||||
receiver: Receiver<T>,
|
receiver: Receiver<T>,
|
||||||
|
|
|
||||||
|
|
@ -1,5 +0,0 @@
|
||||||
use unicode_normalization::UnicodeNormalization;
|
|
||||||
|
|
||||||
pub fn normalize_utf8(input: &str) -> String {
|
|
||||||
input.nfc().collect::<String>()
|
|
||||||
}
|
|
||||||
Loading…
Reference in a new issue