diff --git a/Cargo.lock b/Cargo.lock index 9d8a78b..dea9cf6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7,6 +7,7 @@ dependencies = [ "lodepng 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", "nom 1.2.4 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "openexr 0.1.0 (git+https://github.com/cessen/openexr-rs?rev=612fc6c81c031970ffddcab15509236711613de8)", "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", "scoped_threadpool 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "simd 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -26,6 +27,14 @@ name = "c_vec" version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "cmake" +version = "0.1.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "gcc 0.3.35 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "crossbeam" version = "0.2.9" @@ -41,6 +50,11 @@ dependencies = [ "strsim 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "gcc" +version = "0.3.35" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "kernel32-sys" version = "0.2.2" @@ -86,6 +100,31 @@ dependencies = [ "libc 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "openexr" +version = "0.1.0" +source = "git+https://github.com/cessen/openexr-rs?rev=612fc6c81c031970ffddcab15509236711613de8#612fc6c81c031970ffddcab15509236711613de8" +dependencies = [ + "libc 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", + "openexr-sys 0.1.0 (git+https://github.com/cessen/openexr-rs?rev=612fc6c81c031970ffddcab15509236711613de8)", +] + +[[package]] +name = "openexr-sys" +version = "0.1.0" +source = "git+https://github.com/cessen/openexr-rs?rev=612fc6c81c031970ffddcab15509236711613de8#612fc6c81c031970ffddcab15509236711613de8" +dependencies = [ + "cmake 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", + "gcc 0.3.35 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", + "pkg-config 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "pkg-config" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "regex" version = "0.1.73" @@ -173,16 +212,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [metadata] "checksum aho-corasick 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2b3fb52b09c1710b961acb35390d514be82e4ac96a9969a8e38565a29b878dc9" "checksum c_vec 1.0.12 (registry+https://github.com/rust-lang/crates.io-index)" = "aa9e1d9f7d49e289f36f19effbf3d5a5e30163ecf9c7a3c9be94d5374dec5b9a" +"checksum cmake 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)" = "dfcf5bcece56ef953b8ea042509e9dcbdfe97820b7e20d86beb53df30ed94978" "checksum crossbeam 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)" = "fb974f835e90390c5f9dfac00f05b06dc117299f5ea4e85fbc7bb443af4911cc" "checksum docopt 0.6.81 (registry+https://github.com/rust-lang/crates.io-index)" = "323b5c50646d8d3f26c826eb62c15659b2bc031831d56bcdb02e0e49c5b73829" +"checksum gcc 0.3.35 (registry+https://github.com/rust-lang/crates.io-index)" = "91ecd03771effb0c968fd6950b37e89476a578aaf1c70297d8e92b6516ec3312" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" "checksum libc 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "39dfaaa0f4da0f1a06876c5d94329d739ad0150868069cc235f1ddf80a0480e7" "checksum lodepng 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2949340106c6ddacb872a8bceb940e39e332739873d56c1315917778527f8779" "checksum memchr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d8b629fb514376c675b98c1421e80b151d3817ac42d7c667717d282761418d20" "checksum nom 1.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "a5b8c256fd9471521bcb84c3cdba98921497f1a331cbc15b8030fc63b82050ce" -"checksum num-traits 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)" = "95e58eac34596aac30ab134c8a8da9aa2dc99caa4b4b4838e6fc6e298016278f" "checksum num_cpus 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a859041cbf7a70ea1ece4b87d1a2c6ef364dcb68749c88db1f97304b9ec09d5f" -"checksum quickersort 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5950b7cb98904f6f7856bdff5b0987821f8a4ec4a67f4be892ddc8ed244ce89d" +"checksum openexr 0.1.0 (git+https://github.com/cessen/openexr-rs?rev=612fc6c81c031970ffddcab15509236711613de8)" = "" +"checksum openexr-sys 0.1.0 (git+https://github.com/cessen/openexr-rs?rev=612fc6c81c031970ffddcab15509236711613de8)" = "" +"checksum pkg-config 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "8cee804ecc7eaf201a4a207241472cc870e825206f6c031e3ee2a72fa425f2fa" "checksum regex 0.1.73 (registry+https://github.com/rust-lang/crates.io-index)" = "56b7ee9f764ecf412c6e2fff779bca4b22980517ae335a21aeaf4e32625a5df2" "checksum regex-syntax 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "31040aad7470ad9d8c46302dcffba337bb4289ca5da2e3cd6e37b64109a85199" "checksum rgb 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8b5b3c2c5af3cafb6dad34a02c7a5b8818f71992663f5a8b1e1d1e27c5e782dd" @@ -193,8 +235,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum thread-id 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a9539db560102d1cef46b8b78ce737ff0bb64e7e18d35b2a5688f7d097d0ff03" "checksum thread_local 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "55dd963dbaeadc08aa7266bf7f91c3154a7805e32bb94b820b769d2ef3b4744d" "checksum time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)" = "3c7ec6d62a20df54e07ab3b78b9a3932972f4b7981de295563686849eb3989af" -"checksum unreachable 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1f2ae5ddb18e1c92664717616dd9549dde73f539f01bd7b77c2edb2446bdff91" "checksum utf8-ranges 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a1ca13c08c41c9c3e04224ed9ff80461d97e121589ff27c753a16cb10830ae0f" -"checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" "checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" "checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" diff --git a/Cargo.toml b/Cargo.toml index 6202de4..55080c7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,5 +18,6 @@ scoped_threadpool = "0.1" crossbeam = "0.2" num_cpus = "1.0" lodepng = "0.8" +openexr = { git = "https://github.com/cessen/openexr-rs", rev = "612fc6c81c031970ffddcab15509236711613de8" } simd = { version = "0.1.1", optional = true } diff --git a/psychoblend/render.py b/psychoblend/render.py index d887b5a..72f31b3 100644 --- a/psychoblend/render.py +++ b/psychoblend/render.py @@ -99,7 +99,7 @@ class PsychopathRender(bpy.types.RenderEngine): export_path = get_temp_filename('.psy') # Create a temporary file to render into - render_image_path = get_temp_filename('.png') + render_image_path = get_temp_filename('.exr') # start export self.update_stats("", "Psychopath: Exporting data from Blender") diff --git a/src/assembly.rs b/src/assembly.rs index 7d8d659..c9c44d9 100644 --- a/src/assembly.rs +++ b/src/assembly.rs @@ -184,11 +184,7 @@ impl AssemblyBuilder { // Map zero-length transforms to None let xforms = if let Some(xf) = xforms { - if xf.len() > 0 { - Some(xf) - } else { - None - } + if xf.len() > 0 { Some(xf) } else { None } } else { None }; diff --git a/src/color/mod.rs b/src/color/mod.rs index 224bec2..b17b425 100644 --- a/src/color/mod.rs +++ b/src/color/mod.rs @@ -36,11 +36,7 @@ pub trait Color { fn nth_wavelength(hero_wavelength: f32, n: usize) -> f32 { let wl = hero_wavelength + (WL_RANGE_Q * n as f32); - if wl > WL_MAX { - wl - WL_RANGE - } else { - wl - } + if wl > WL_MAX { wl - WL_RANGE } else { wl } } @@ -70,11 +66,7 @@ impl SpectralSample { /// Returns the nth wavelength fn wl_n(&self, n: usize) -> f32 { let wl = self.hero_wavelength + (WL_RANGE_Q * n as f32); - if wl > WL_MAX { - wl - WL_RANGE - } else { - wl - } + if wl > WL_MAX { wl - WL_RANGE } else { wl } } } @@ -308,59 +300,24 @@ fn xyz_to_spectrum(xyz: (f32, f32, f32), wavelength: f32) -> f32 { /// Functions" by Wyman et al. #[allow(dead_code)] fn x_1931(wavelength: f32) -> f32 { - let t1 = (wavelength - 442.0) * - (if wavelength < 442.0 { - 0.0624 - } else { - 0.0374 - }); - let t2 = (wavelength - 599.8) * - (if wavelength < 599.8 { - 0.0264 - } else { - 0.0323 - }); - let t3 = (wavelength - 501.1) * - (if wavelength < 501.1 { - 0.0490 - } else { - 0.0382 - }); + let t1 = (wavelength - 442.0) * (if wavelength < 442.0 { 0.0624 } else { 0.0374 }); + let t2 = (wavelength - 599.8) * (if wavelength < 599.8 { 0.0264 } else { 0.0323 }); + let t3 = (wavelength - 501.1) * (if wavelength < 501.1 { 0.0490 } else { 0.0382 }); (0.362 * faster_exp(-0.5 * t1 * t1)) + (1.056 * faster_exp(-0.5 * t2 * t2)) - (0.065 * faster_exp(-0.5 * t3 * t3)) } #[allow(dead_code)] fn y_1931(wavelength: f32) -> f32 { - let t1 = (wavelength - 568.8) * - (if wavelength < 568.8 { - 0.0213 - } else { - 0.0247 - }); - let t2 = (wavelength - 530.9) * - (if wavelength < 530.9 { - 0.0613 - } else { - 0.0322 - }); + let t1 = (wavelength - 568.8) * (if wavelength < 568.8 { 0.0213 } else { 0.0247 }); + let t2 = (wavelength - 530.9) * (if wavelength < 530.9 { 0.0613 } else { 0.0322 }); (0.821 * faster_exp(-0.5 * t1 * t1)) + (0.286 * faster_exp(-0.5 * t2 * t2)) } #[allow(dead_code)] fn z_1931(wavelength: f32) -> f32 { - let t1 = (wavelength - 437.0) * - (if wavelength < 437.0 { - 0.0845 - } else { - 0.0278 - }); - let t2 = (wavelength - 459.0) * - (if wavelength < 459.0 { - 0.0385 - } else { - 0.0725 - }); + let t1 = (wavelength - 437.0) * (if wavelength < 437.0 { 0.0845 } else { 0.0278 }); + let t2 = (wavelength - 459.0) * (if wavelength < 459.0 { 0.0385 } else { 0.0725 }); (1.217 * faster_exp(-0.5 * t1 * t1)) + (0.681 * faster_exp(-0.5 * t2 * t2)) } diff --git a/src/float4.rs b/src/float4.rs index 3c991f2..de7c1e7 100644 --- a/src/float4.rs +++ b/src/float4.rs @@ -59,11 +59,7 @@ impl Float4 { } else { self.get_3() }; - if n1 < n2 { - n1 - } else { - n2 - } + if n1 < n2 { n1 } else { n2 } } pub fn h_max(&self) -> f32 { @@ -77,11 +73,7 @@ impl Float4 { } else { self.get_3() }; - if n1 > n2 { - n1 - } else { - n2 - } + if n1 > n2 { n1 } else { n2 } } #[cfg(feature = "simd_perf")] diff --git a/src/hilbert.rs b/src/hilbert.rs index d590364..86f2055 100644 --- a/src/hilbert.rs +++ b/src/hilbert.rs @@ -29,16 +29,8 @@ pub fn xy2d(x: u32, y: u32) -> u32 { let mut d = 0; let mut s = N >> 1; while s > 0 { - let rx = if (x & s) > 0 { - 1 - } else { - 0 - }; - let ry = if (y & s) > 0 { - 1 - } else { - 0 - }; + let rx = if (x & s) > 0 { 1 } else { 0 }; + let ry = if (y & s) > 0 { 1 } else { 0 }; d += s * s * ((3 * rx) ^ ry); hil_rot(s, rx, ry, &mut x, &mut y); diff --git a/src/image.rs b/src/image.rs index 4d00640..b2dd28a 100644 --- a/src/image.rs +++ b/src/image.rs @@ -11,6 +11,7 @@ use std::path::Path; use std::sync::Mutex; use lodepng; +use openexr; use color::{XYZ, xyz_to_rec709e}; @@ -153,6 +154,35 @@ impl Image { // Done Ok(()) } + + pub fn write_exr(&mut self, path: &Path) { + let mut image = Vec::new(); + + // Convert pixels + for y in 0..self.res.1 { + for x in 0..self.res.0 { + let (r, g, b) = xyz_to_rec709e(self.get(x, y).to_tuple()); + image.push((r, g, b)); + } + } + + let mut wr = openexr::ExrWriterBuilder::new(path) + .display_window((0, 0), ((self.res.0 - 1) as i32, (self.res.1 - 1) as i32)) + .data_window((0, 0), ((self.res.0 - 1) as i32, (self.res.1 - 1) as i32)) + .insert_channel("R", openexr::Channel::with_type(openexr::PixelType::F32)) + .insert_channel("G", openexr::Channel::with_type(openexr::PixelType::F32)) + .insert_channel("B", openexr::Channel::with_type(openexr::PixelType::F32)) + .open(); + + let mut fb = { + // Create the frame buffer + let mut fb = openexr::FrameBuffer::new(self.res.0, self.res.1); + fb.add_structured_slice(&mut image, &[("R", 0.0), ("G", 0.0), ("B", 0.0)]); + fb + }; + + wr.write_pixels(&mut fb); + } } #[derive(Debug)] diff --git a/src/main.rs b/src/main.rs index e126247..06145d1 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,6 +2,7 @@ extern crate crossbeam; extern crate docopt; extern crate lodepng; extern crate num_cpus; +extern crate openexr; extern crate rustc_serialize; extern crate scoped_threadpool; extern crate time; @@ -153,7 +154,13 @@ fn main() { println!("\tRendered scene in {:.3}s", t.tick()); println!("Writing image to disk..."); - let _ = image.write_png(Path::new(&r.output_file)); + if r.output_file.ends_with(".png") { + let _ = image.write_png(Path::new(&r.output_file)); + } else if r.output_file.ends_with(".exr") { + image.write_exr(Path::new(&r.output_file)); + } else { + panic!("Unknown output file extension."); + } println!("\tWrote image in {:.3}s", t.tick()); } } diff --git a/src/math/mod.rs b/src/math/mod.rs index 77cf8b6..1eec137 100644 --- a/src/math/mod.rs +++ b/src/math/mod.rs @@ -42,16 +42,8 @@ pub fn fast_ln(x: f32) -> f32 { pub fn fast_pow2(p: f32) -> f32 { use std::mem::transmute_copy; - let offset: f32 = if p < 0.0 { - 1.0 - } else { - 0.0 - }; - let clipp: f32 = if p < -126.0 { - -126.0 - } else { - p - }; + let offset: f32 = if p < 0.0 { 1.0 } else { 0.0 }; + let clipp: f32 = if p < -126.0 { -126.0 } else { p }; let w: i32 = clipp as i32; let z: f32 = clipp - w as f32 + offset; @@ -69,11 +61,7 @@ pub fn fast_exp(p: f32) -> f32 { pub fn faster_pow2(p: f32) -> f32 { use std::mem::transmute_copy; - let clipp: f32 = if p < -126.0 { - -126.0 - } else { - p - }; + let clipp: f32 = if p < -126.0 { -126.0 } else { p }; let i: u32 = ((1 << 23) as f32 * (clipp + 126.94269504)) as u32; unsafe { transmute_copy::(&i) } @@ -85,20 +73,12 @@ pub fn faster_exp(p: f32) -> f32 { // The stdlib min function is slower than a simple if statement for some reason. pub fn fast_minf32(a: f32, b: f32) -> f32 { - if a < b { - a - } else { - b - } + if a < b { a } else { b } } // The stdlib max function is slower than a simple if statement for some reason. pub fn fast_maxf32(a: f32, b: f32) -> f32 { - if a > b { - a - } else { - b - } + if a > b { a } else { b } } diff --git a/src/objects_split.rs b/src/objects_split.rs index d1af31b..2915e40 100644 --- a/src/objects_split.rs +++ b/src/objects_split.rs @@ -314,11 +314,7 @@ pub fn median_split<'a, T, F>(objects: &mut [T], bounder: &F) -> (usize, usize) let place = { let place = objects.len() / 2; - if place > 0 { - place - } else { - 1 - } + if place > 0 { place } else { 1 } }; quick_select(objects, place, |a, b| { let tb_a = lerp_slice(bounder(a), 0.5); diff --git a/todo.txt b/todo.txt index 64461b3..aa01da4 100644 --- a/todo.txt +++ b/todo.txt @@ -1,7 +1,6 @@ -//- Implement support for multiple light sources in a scene. -//- Implement light tree. -//- Implement proper light source selection for hierarchical instancing. - Implement shader parsing, and use in rendering. +- Implement sun light sources - Implement floating point accuracy stuff. +// Add OpenEXR support. - Add gui display of rendering in progress. - Unit tests for scene parsing.