Added support for OpenEXR output.
This commit is contained in:
parent
0d189f763d
commit
bb4e57795f
48
Cargo.lock
generated
48
Cargo.lock
generated
|
@ -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)" = "<none>"
|
||||
"checksum openexr-sys 0.1.0 (git+https://github.com/cessen/openexr-rs?rev=612fc6c81c031970ffddcab15509236711613de8)" = "<none>"
|
||||
"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"
|
||||
|
|
|
@ -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 }
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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
|
||||
};
|
||||
|
|
|
@ -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))
|
||||
}
|
||||
|
||||
|
|
|
@ -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")]
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
30
src/image.rs
30
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)]
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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::<u32, f32>(&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 }
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
5
todo.txt
5
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.
|
||||
|
|
Loading…
Reference in New Issue
Block a user