Implement DiffuseLight material.
Allow Scenes to define global_illumination so scenes without lighting can continue to work.
This commit is contained in:
parent
34ce373269
commit
9c5233e057
@ -8,6 +8,7 @@ pub mod material;
|
|||||||
pub mod moving_sphere;
|
pub mod moving_sphere;
|
||||||
pub mod perlin;
|
pub mod perlin;
|
||||||
pub mod ray;
|
pub mod ray;
|
||||||
|
pub mod rect;
|
||||||
pub mod renderer;
|
pub mod renderer;
|
||||||
pub mod scenes;
|
pub mod scenes;
|
||||||
pub mod sphere;
|
pub mod sphere;
|
||||||
|
|||||||
@ -31,6 +31,9 @@ pub struct ScatterResponse {
|
|||||||
|
|
||||||
pub trait Material: Send + Sync {
|
pub trait Material: Send + Sync {
|
||||||
fn scatter(&self, r_in: &Ray, rec: &HitRecord) -> ScatterResponse;
|
fn scatter(&self, r_in: &Ray, rec: &HitRecord) -> ScatterResponse;
|
||||||
|
fn emitted(&self, _u: f32, _v: f32, _p: Vec3) -> Vec3 {
|
||||||
|
Vec3::new(0., 0., 0.)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Lambertian {
|
pub struct Lambertian {
|
||||||
@ -149,3 +152,27 @@ impl Material for Dielectric {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct DiffuseLight {
|
||||||
|
emit: Box<Texture>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DiffuseLight {
|
||||||
|
pub fn new(emit: Box<Texture>) -> DiffuseLight {
|
||||||
|
DiffuseLight { emit }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Material for DiffuseLight {
|
||||||
|
fn scatter(&self, _r_in: &Ray, _rec: &HitRecord) -> ScatterResponse {
|
||||||
|
ScatterResponse {
|
||||||
|
scattered: Default::default(),
|
||||||
|
attenutation: Default::default(),
|
||||||
|
reflected: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn emitted(&self, u: f32, v: f32, p: Vec3) -> Vec3 {
|
||||||
|
self.emit.value(u, v, p)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
58
rtiow/src/rect.rs
Normal file
58
rtiow/src/rect.rs
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
use aabb::AABB;
|
||||||
|
use hitable::Hit;
|
||||||
|
use hitable::HitRecord;
|
||||||
|
use material::Material;
|
||||||
|
use ray::Ray;
|
||||||
|
use vec3::Vec3;
|
||||||
|
|
||||||
|
pub struct XYRect {
|
||||||
|
x0: f32,
|
||||||
|
x1: f32,
|
||||||
|
y0: f32,
|
||||||
|
y1: f32,
|
||||||
|
k: f32,
|
||||||
|
material: Box<Material>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl XYRect {
|
||||||
|
pub fn new(x0: f32, x1: f32, y0: f32, y1: f32, k: f32, material: Box<Material>) -> XYRect {
|
||||||
|
XYRect {
|
||||||
|
x0,
|
||||||
|
x1,
|
||||||
|
y0,
|
||||||
|
y1,
|
||||||
|
k,
|
||||||
|
material,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Hit for XYRect {
|
||||||
|
fn hit(&self, r: Ray, t_min: f32, t_max: f32) -> Option<HitRecord> {
|
||||||
|
let t = (self.k - r.origin.z) / r.direction.z;
|
||||||
|
if t < t_min || t > t_max {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
let x = r.origin.x + t * r.direction.x;
|
||||||
|
let y = r.origin.y + t * r.direction.y;
|
||||||
|
if x < self.x0 || x > self.x1 || y < self.y0 || y > self.y1 {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
let u = (x - self.x0) / (self.x1 - self.x0);
|
||||||
|
let v = (y - self.y0) / (self.y1 - self.y0);
|
||||||
|
Some(HitRecord {
|
||||||
|
t,
|
||||||
|
uv: (u, v),
|
||||||
|
p: r.point_at_parameter(t),
|
||||||
|
normal: Vec3::new(0., 0., 1.),
|
||||||
|
material: &*self.material,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn bounding_box(&self, _t_min: f32, _t_max: f32) -> Option<AABB> {
|
||||||
|
Some(AABB::new(
|
||||||
|
Vec3::new(self.x0, self.y0, self.k - 0.0001),
|
||||||
|
Vec3::new(self.x1, self.y1, self.k + 0.0001),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -96,21 +96,36 @@ pub struct Scene {
|
|||||||
pub subsamples: usize,
|
pub subsamples: usize,
|
||||||
pub width: usize,
|
pub width: usize,
|
||||||
pub height: usize,
|
pub height: usize,
|
||||||
|
pub global_illumination: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn color(r: Ray, world: &Hit, depth: usize) -> Vec3 {
|
// color will trace ray up to 50 bounces deep accumulating color as it goes. If
|
||||||
|
// global_illumination is true, a default light background color is assumed and will light the
|
||||||
|
// world. If false, it is expected the scene has emissive light sources.
|
||||||
|
fn color(r: Ray, world: &Hit, depth: usize, global_illumination: bool) -> Vec3 {
|
||||||
if let Some(rec) = world.hit(r, 0.001, std::f32::MAX) {
|
if let Some(rec) = world.hit(r, 0.001, std::f32::MAX) {
|
||||||
|
let (u, v) = rec.uv;
|
||||||
|
let emitted = rec.material.emitted(u, v, rec.p);
|
||||||
let scatter_response = rec.material.scatter(&r, &rec);
|
let scatter_response = rec.material.scatter(&r, &rec);
|
||||||
if depth < 50 && scatter_response.reflected {
|
if depth < 50 && scatter_response.reflected {
|
||||||
return scatter_response.attenutation
|
return emitted + scatter_response.attenutation * color(
|
||||||
* color(scatter_response.scattered, world, depth + 1);
|
scatter_response.scattered,
|
||||||
|
world,
|
||||||
|
depth + 1,
|
||||||
|
global_illumination,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return emitted;
|
||||||
}
|
}
|
||||||
return Default::default();
|
|
||||||
}
|
}
|
||||||
|
if global_illumination {
|
||||||
// No hit, choose color from background.
|
// No hit, choose color from background.
|
||||||
let unit_direction = r.direction.unit_vector();
|
let unit_direction = r.direction.unit_vector();
|
||||||
let t = 0.5 * (unit_direction.y + 1.);
|
let t = 0.5 * (unit_direction.y + 1.);
|
||||||
Vec3::new(1., 1., 1.) * (1. - t) + Vec3::new(0.5, 0.7, 1.) * t
|
return Vec3::new(1., 1., 1.) * (1. - t) + Vec3::new(0.5, 0.7, 1.) * t;
|
||||||
|
}
|
||||||
|
// No global illumination, so background is black.
|
||||||
|
Vec3::new(0., 0., 0.)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn trace_pixel(x: usize, y: usize, scene: &Scene) -> Vec3 {
|
fn trace_pixel(x: usize, y: usize, scene: &Scene) -> Vec3 {
|
||||||
@ -118,7 +133,7 @@ fn trace_pixel(x: usize, y: usize, scene: &Scene) -> Vec3 {
|
|||||||
let u = (rng.gen_range::<f32>(0., 1.) + x as f32) / scene.width as f32;
|
let u = (rng.gen_range::<f32>(0., 1.) + x as f32) / scene.width as f32;
|
||||||
let v = (rng.gen_range::<f32>(0., 1.) + y as f32) / scene.height as f32;
|
let v = (rng.gen_range::<f32>(0., 1.) + y as f32) / scene.height as f32;
|
||||||
let ray = scene.camera.get_ray(u, v);
|
let ray = scene.camera.get_ray(u, v);
|
||||||
color(ray, scene.world.as_ref(), 0)
|
color(ray, scene.world.as_ref(), 0, scene.global_illumination)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render_worker(
|
fn render_worker(
|
||||||
|
|||||||
@ -73,5 +73,6 @@ pub fn new(opt: &Opt) -> Scene {
|
|||||||
subsamples: opt.subsamples,
|
subsamples: opt.subsamples,
|
||||||
width: opt.width,
|
width: opt.width,
|
||||||
height: opt.height,
|
height: opt.height,
|
||||||
|
global_illumination: true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -50,6 +50,7 @@ pub fn new(opt: &Opt) -> Scene {
|
|||||||
subsamples: opt.subsamples,
|
subsamples: opt.subsamples,
|
||||||
width: opt.width,
|
width: opt.width,
|
||||||
height: opt.height,
|
height: opt.height,
|
||||||
|
global_illumination: true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -71,5 +71,6 @@ pub fn new(opt: &Opt) -> Scene {
|
|||||||
subsamples: opt.subsamples,
|
subsamples: opt.subsamples,
|
||||||
width: opt.width,
|
width: opt.width,
|
||||||
height: opt.height,
|
height: opt.height,
|
||||||
|
global_illumination: true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,7 +4,9 @@ use camera::Camera;
|
|||||||
use hitable::Hit;
|
use hitable::Hit;
|
||||||
use hitable_list::HitableList;
|
use hitable_list::HitableList;
|
||||||
use kdtree::KDTree;
|
use kdtree::KDTree;
|
||||||
|
use material::DiffuseLight;
|
||||||
use material::Lambertian;
|
use material::Lambertian;
|
||||||
|
use rect::XYRect;
|
||||||
use renderer::Opt;
|
use renderer::Opt;
|
||||||
use renderer::Scene;
|
use renderer::Scene;
|
||||||
use sphere::Sphere;
|
use sphere::Sphere;
|
||||||
@ -14,7 +16,7 @@ use texture::NoiseTexture;
|
|||||||
use vec3::Vec3;
|
use vec3::Vec3;
|
||||||
|
|
||||||
pub fn new(opt: &Opt) -> Scene {
|
pub fn new(opt: &Opt) -> Scene {
|
||||||
let lookfrom = Vec3::new(0., 5., 20.);
|
let lookfrom = Vec3::new(30., 2., 0.);
|
||||||
let lookat = Vec3::new(0., 1., 0.);
|
let lookat = Vec3::new(0., 1., 0.);
|
||||||
let dist_to_focus = 10.0;
|
let dist_to_focus = 10.0;
|
||||||
let aperture = 0.0;
|
let aperture = 0.0;
|
||||||
@ -53,6 +55,26 @@ pub fn new(opt: &Opt) -> Scene {
|
|||||||
// Box::new(Lambertian::new(ground_color)),
|
// Box::new(Lambertian::new(ground_color)),
|
||||||
Box::new(Lambertian::new(Box::new(NoiseTexture::with_scale(10.)))),
|
Box::new(Lambertian::new(Box::new(NoiseTexture::with_scale(10.)))),
|
||||||
)),
|
)),
|
||||||
|
Box::new(XYRect::new(
|
||||||
|
0.,
|
||||||
|
4.,
|
||||||
|
0.,
|
||||||
|
4.,
|
||||||
|
-4.,
|
||||||
|
Box::new(DiffuseLight::new(Box::new(ConstantTexture::new(
|
||||||
|
Vec3::new(4., 4., 4.),
|
||||||
|
)))),
|
||||||
|
)),
|
||||||
|
Box::new(XYRect::new(
|
||||||
|
0.,
|
||||||
|
4.,
|
||||||
|
0.,
|
||||||
|
4.,
|
||||||
|
4.,
|
||||||
|
Box::new(DiffuseLight::new(Box::new(ConstantTexture::new(
|
||||||
|
Vec3::new(0., 4., 4.),
|
||||||
|
)))),
|
||||||
|
)),
|
||||||
/*
|
/*
|
||||||
Box::new(Sphere::new(
|
Box::new(Sphere::new(
|
||||||
Vec3::new(0., 0., 0.),
|
Vec3::new(0., 0., 0.),
|
||||||
@ -90,5 +112,6 @@ pub fn new(opt: &Opt) -> Scene {
|
|||||||
subsamples: opt.subsamples,
|
subsamples: opt.subsamples,
|
||||||
width: opt.width,
|
width: opt.width,
|
||||||
height: opt.height,
|
height: opt.height,
|
||||||
|
global_illumination: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -76,5 +76,6 @@ pub fn new(opt: &Opt) -> Scene {
|
|||||||
subsamples: opt.subsamples,
|
subsamples: opt.subsamples,
|
||||||
width: opt.width,
|
width: opt.width,
|
||||||
height: opt.height,
|
height: opt.height,
|
||||||
|
global_illumination: true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,7 +1,6 @@
|
|||||||
use image::RgbImage;
|
use image::RgbImage;
|
||||||
|
|
||||||
use perlin::turb;
|
use perlin::turb;
|
||||||
use perlin::GENERATOR;
|
|
||||||
use vec3::Vec3;
|
use vec3::Vec3;
|
||||||
|
|
||||||
pub trait Texture: Send + Sync {
|
pub trait Texture: Send + Sync {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user