Add ConstantTexture and use it for Lambertian material.

This commit is contained in:
Bill Thiede 2018-09-22 19:53:27 -07:00
parent e1c430b9b2
commit a1d3cce4e4
10 changed files with 88 additions and 25 deletions

View File

@ -234,6 +234,7 @@ mod tests {
use material::Lambertian; use material::Lambertian;
use material::Metal; use material::Metal;
use sphere::Sphere; use sphere::Sphere;
use texture::ConstantTexture;
use vec3::Vec3; use vec3::Vec3;
use super::*; use super::*;
@ -245,7 +246,9 @@ mod tests {
Box::new(Sphere::new( Box::new(Sphere::new(
Vec3::new(0., 0., 0.), Vec3::new(0., 0., 0.),
0.5, 0.5,
Box::new(Lambertian::new(Vec3::new(0.1, 0.2, 0.5))), Box::new(Lambertian::new(Box::new(ConstantTexture::new(Vec3::new(
0.1, 0.2, 0.5,
))))),
)), )),
Box::new(Sphere::new( Box::new(Sphere::new(
Vec3::new(1., 0., 0.), Vec3::new(1., 0., 0.),
@ -271,7 +274,9 @@ mod tests {
Box::new(Sphere::new( Box::new(Sphere::new(
Vec3::new(0., 0., 0.), Vec3::new(0., 0., 0.),
0.5, 0.5,
Box::new(Lambertian::new(Vec3::new(0.1, 0.2, 0.5))), Box::new(Lambertian::new(Box::new(ConstantTexture::new(Vec3::new(
0.1, 0.2, 0.5,
))))),
)), )),
Box::new(Sphere::new( Box::new(Sphere::new(
Vec3::new(1., 0., 0.), Vec3::new(1., 0., 0.),

View File

@ -11,6 +11,7 @@ pub mod ray;
pub mod renderer; pub mod renderer;
pub mod scenes; pub mod scenes;
pub mod sphere; pub mod sphere;
pub mod texture;
pub mod vec3; pub mod vec3;
extern crate crossbeam_channel; extern crate crossbeam_channel;

View File

@ -3,6 +3,7 @@ use self::rand::Rng;
use hitable::HitRecord; use hitable::HitRecord;
use ray::Ray; use ray::Ray;
use texture::Texture;
use vec3::dot; use vec3::dot;
use vec3::Vec3; use vec3::Vec3;
@ -33,12 +34,13 @@ pub trait Material: Send + Sync {
} }
pub struct Lambertian { pub struct Lambertian {
albedo: Vec3, // TODO(wathiede): implement texture sharing via references
albedo: Box<Texture>,
} }
impl Lambertian { impl Lambertian {
pub fn new(albedo: Vec3) -> Lambertian { pub fn new(texture: Box<Texture>) -> Lambertian {
Lambertian { albedo } Lambertian { albedo: texture }
} }
} }
@ -46,7 +48,7 @@ impl Material for Lambertian {
fn scatter(&self, r_in: &Ray, rec: &HitRecord) -> ScatterResponse { fn scatter(&self, r_in: &Ray, rec: &HitRecord) -> ScatterResponse {
let target = rec.p + rec.normal + random_in_unit_sphere(); let target = rec.p + rec.normal + random_in_unit_sphere();
ScatterResponse { ScatterResponse {
attenutation: self.albedo, attenutation: self.albedo.value(0., 0., rec.p),
scattered: Ray::new(rec.p, target - rec.p, r_in.time), scattered: Ray::new(rec.p, target - rec.p, r_in.time),
reflected: true, reflected: true,
} }

View File

@ -10,6 +10,7 @@ use material::Lambertian;
use renderer::Opt; use renderer::Opt;
use renderer::Scene; use renderer::Scene;
use sphere::Sphere; use sphere::Sphere;
use texture::ConstantTexture;
use vec3::Vec3; use vec3::Vec3;
pub fn new(opt: &Opt) -> Scene { pub fn new(opt: &Opt) -> Scene {
@ -32,7 +33,7 @@ pub fn new(opt: &Opt) -> Scene {
); );
let mut rng = rand::thread_rng(); let mut rng = rand::thread_rng();
let mut grid: Vec<Box<Hit>> = Vec::new(); let mut grid: Vec<Box<Hit>> = Vec::new();
let len = 100; let len = 1000;
for x in 0..len { for x in 0..len {
for z in 0..len { for z in 0..len {
let r = rng.gen_range::<f32>(0., 1.); let r = rng.gen_range::<f32>(0., 1.);
@ -45,7 +46,9 @@ pub fn new(opt: &Opt) -> Scene {
grid.push(Box::new(Sphere::new( grid.push(Box::new(Sphere::new(
Vec3::new(x_pos, 0., z_pos), Vec3::new(x_pos, 0., z_pos),
0.5, 0.5,
Box::new(Lambertian::new(Vec3::new(r, g, b))), Box::new(Lambertian::new(Box::new(ConstantTexture::new(Vec3::new(
r, g, b,
))))),
))); )));
} }
} }

View File

@ -11,6 +11,7 @@ use material::Metal;
use renderer::Opt; use renderer::Opt;
use renderer::Scene; use renderer::Scene;
use sphere::Sphere; use sphere::Sphere;
use texture::ConstantTexture;
use vec3::Vec3; use vec3::Vec3;
pub fn new(opt: &Opt) -> Scene { pub fn new(opt: &Opt) -> Scene {
@ -55,7 +56,9 @@ fn random_scene(background_color: Vec3) -> Vec<Box<Hit>> {
let mut objects: Vec<Box<Hit>> = vec![Box::new(Sphere::new( let mut objects: Vec<Box<Hit>> = vec![Box::new(Sphere::new(
Vec3::new(0., -1000., 0.), Vec3::new(0., -1000., 0.),
1000., 1000.,
Box::new(Lambertian::new(background_color)), Box::new(Lambertian::new(Box::new(ConstantTexture::new(
background_color,
)))),
))]; ))];
let mut random = || rng.gen_range::<f32>(0., 1.); let mut random = || rng.gen_range::<f32>(0., 1.);
@ -69,11 +72,11 @@ fn random_scene(background_color: Vec3) -> Vec<Box<Hit>> {
Box::new(Sphere::new( Box::new(Sphere::new(
center, center,
0.2, 0.2,
Box::new(Lambertian::new(Vec3::new( Box::new(Lambertian::new(Box::new(ConstantTexture::new(Vec3::new(
random() * random(), random() * random(),
random() * random(), random() * random(),
random() * random(), random() * random(),
))), ))))),
)) ))
} else if choose_mat < 0.95 { } else if choose_mat < 0.95 {
// metal // metal
@ -107,7 +110,9 @@ fn random_scene(background_color: Vec3) -> Vec<Box<Hit>> {
Box::new(Sphere::new( Box::new(Sphere::new(
Vec3::new(-4., 1., 0.), Vec3::new(-4., 1., 0.),
1.0, 1.0,
Box::new(Lambertian::new(Vec3::new(0.4, 0.2, 0.1))), Box::new(Lambertian::new(Box::new(ConstantTexture::new(Vec3::new(
0.4, 0.2, 0.1,
))))),
)), )),
Box::new(Sphere::new( Box::new(Sphere::new(
Vec3::new(4., 1., 0.), Vec3::new(4., 1., 0.),

View File

@ -7,6 +7,7 @@ use moving_sphere::MovingSphere;
use renderer::Opt; use renderer::Opt;
use renderer::Scene; use renderer::Scene;
use sphere::Sphere; use sphere::Sphere;
use texture::ConstantTexture;
use vec3::Vec3; use vec3::Vec3;
pub fn new(opt: &Opt) -> Scene { pub fn new(opt: &Opt) -> Scene {
@ -32,12 +33,16 @@ pub fn new(opt: &Opt) -> Scene {
Box::new(Sphere::new( Box::new(Sphere::new(
Vec3::new(0., 0., -1.), Vec3::new(0., 0., -1.),
0.5, 0.5,
Box::new(Lambertian::new(Vec3::new(0.1, 0.2, 0.5))), Box::new(Lambertian::new(Box::new(ConstantTexture::new(Vec3::new(
0.1, 0.2, 0.5,
))))),
)), )),
Box::new(Sphere::new( Box::new(Sphere::new(
Vec3::new(0., -100.5, -1.), Vec3::new(0., -100.5, -1.),
100., 100.,
Box::new(Lambertian::new(Vec3::new(0.8, 0.8, 0.8))), Box::new(Lambertian::new(Box::new(ConstantTexture::new(Vec3::new(
0.8, 0.8, 0.8,
))))),
)), )),
Box::new(Sphere::new( Box::new(Sphere::new(
Vec3::new(1., 0., -1.), Vec3::new(1., 0., -1.),
@ -50,7 +55,9 @@ pub fn new(opt: &Opt) -> Scene {
0.5, 0.5,
time_min, time_min,
time_max, time_max,
Box::new(Lambertian::new(Vec3::new(0.2, 0.8, 0.2))), Box::new(Lambertian::new(Box::new(ConstantTexture::new(Vec3::new(
0.2, 0.8, 0.2,
))))),
)), )),
], ],
time_min, time_min,

View File

@ -6,6 +6,7 @@ use material::Lambertian;
use renderer::Opt; use renderer::Opt;
use renderer::Scene; use renderer::Scene;
use sphere::Sphere; use sphere::Sphere;
use texture::ConstantTexture;
use vec3::Vec3; use vec3::Vec3;
pub fn new(opt: &Opt) -> Scene { pub fn new(opt: &Opt) -> Scene {
@ -30,17 +31,23 @@ pub fn new(opt: &Opt) -> Scene {
Box::new(Sphere::new( Box::new(Sphere::new(
Vec3::new(0., 0., -1.), Vec3::new(0., 0., -1.),
0.5, 0.5,
Box::new(Lambertian::new(Vec3::new(0.1, 0.2, 0.5))), Box::new(Lambertian::new(Box::new(ConstantTexture::new(Vec3::new(
0.1, 0.2, 0.5,
))))),
)), )),
Box::new(Cube::new( Box::new(Cube::new(
Vec3::new(0., 0., 0.), Vec3::new(0., 0., 0.),
0.5, 0.5,
Box::new(Lambertian::new(Vec3::new(0.5, 0.2, 0.1))), Box::new(Lambertian::new(Box::new(ConstantTexture::new(Vec3::new(
0.5, 0.2, 0.1,
))))),
)), )),
Box::new(Sphere::new( Box::new(Sphere::new(
Vec3::new(0., -100.5, -1.), Vec3::new(0., -100.5, -1.),
100., 100.,
Box::new(Lambertian::new(Vec3::new(0.8, 0.8, 0.8))), Box::new(Lambertian::new(Box::new(ConstantTexture::new(Vec3::new(
0.8, 0.8, 0.8,
))))),
)), )),
])); ]));
Scene { Scene {

View File

@ -9,6 +9,7 @@ use material::Metal;
use renderer::Opt; use renderer::Opt;
use renderer::Scene; use renderer::Scene;
use sphere::Sphere; use sphere::Sphere;
use texture::ConstantTexture;
use vec3::Vec3; use vec3::Vec3;
pub fn new(opt: &Opt) -> Scene { pub fn new(opt: &Opt) -> Scene {
@ -43,19 +44,25 @@ pub fn new(opt: &Opt) -> Scene {
objects.push(Box::new(Sphere::new( objects.push(Box::new(Sphere::new(
center, center,
0.5, 0.5,
Box::new(Lambertian::new(Vec3::new(1., 0., 0.))), Box::new(Lambertian::new(Box::new(ConstantTexture::new(Vec3::new(
1., 0., 0.,
))))),
))); )));
let center = Vec3::new(c1, 0., c2); let center = Vec3::new(c1, 0., c2);
objects.push(Box::new(Sphere::new( objects.push(Box::new(Sphere::new(
center, center,
0.5, 0.5,
Box::new(Lambertian::new(Vec3::new(0., 1., 0.))), Box::new(Lambertian::new(Box::new(ConstantTexture::new(Vec3::new(
0., 1., 0.,
))))),
))); )));
let center = Vec3::new(c1, c2, 0.); let center = Vec3::new(c1, c2, 0.);
objects.push(Box::new(Sphere::new( objects.push(Box::new(Sphere::new(
center, center,
0.5, 0.5,
Box::new(Lambertian::new(Vec3::new(0., 0., 1.))), Box::new(Lambertian::new(Box::new(ConstantTexture::new(Vec3::new(
0., 0., 1.,
))))),
))); )));
} }
let world: Box<Hit> = if opt.use_accel { let world: Box<Hit> = if opt.use_accel {

View File

@ -8,6 +8,7 @@ use moving_sphere::MovingSphere;
use renderer::Opt; use renderer::Opt;
use renderer::Scene; use renderer::Scene;
use sphere::Sphere; use sphere::Sphere;
use texture::ConstantTexture;
use vec3::Vec3; use vec3::Vec3;
pub fn new(opt: &Opt) -> Scene { pub fn new(opt: &Opt) -> Scene {
@ -29,9 +30,9 @@ pub fn new(opt: &Opt) -> Scene {
time_max, time_max,
); );
let ground_color = if opt.use_accel { let ground_color = if opt.use_accel {
Vec3::new(1.0, 0.4, 0.4) Box::new(ConstantTexture::new(Vec3::new(1.0, 0.4, 0.4)))
} else { } else {
Vec3::new(0.4, 1.0, 0.4) Box::new(ConstantTexture::new(Vec3::new(0.4, 1.0, 0.4)))
}; };
let objects: Vec<Box<Hit>> = vec![ let objects: Vec<Box<Hit>> = vec![
@ -39,7 +40,9 @@ pub fn new(opt: &Opt) -> Scene {
Box::new(Sphere::new( Box::new(Sphere::new(
Vec3::new(0., 0., -1.), Vec3::new(0., 0., -1.),
0.5, 0.5,
Box::new(Lambertian::new(Vec3::new(0.1, 0.2, 0.5))), Box::new(Lambertian::new(Box::new(ConstantTexture::new(Vec3::new(
0.1, 0.2, 0.5,
))))),
)), )),
Box::new(Sphere::new( Box::new(Sphere::new(
Vec3::new(0., -100.5, -1.), Vec3::new(0., -100.5, -1.),
@ -57,7 +60,9 @@ pub fn new(opt: &Opt) -> Scene {
0.5, 0.5,
0., 0.,
1., 1.,
Box::new(Lambertian::new(Vec3::new(0.2, 0.8, 0.2))), Box::new(Lambertian::new(Box::new(ConstantTexture::new(Vec3::new(
0.2, 0.8, 0.2,
))))),
)), )),
]; ];
let world: Box<Hit> = if opt.use_accel { let world: Box<Hit> = if opt.use_accel {

21
rtiow/src/texture.rs Normal file
View File

@ -0,0 +1,21 @@
use vec3::Vec3;
pub trait Texture: Send + Sync {
fn value(&self, u: f32, v: f32, p: Vec3) -> Vec3;
}
pub struct ConstantTexture {
color: Vec3,
}
impl ConstantTexture {
pub fn new(color: Vec3) -> ConstantTexture {
ConstantTexture { color }
}
}
impl Texture for ConstantTexture {
fn value(&self, _u: f32, _v: f32, _p: Vec3) -> Vec3 {
self.color
}
}