aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorlamp2024-01-21 16:40:16 +0000
committerlamp2024-01-21 16:40:16 +0000
commit89a5c9a8a0cdf627cda0e31da454f83ca21315ce (patch)
tree8da94d4b9bf1cd61353f278a94312719d60b306e /src
parentc0fc3926e06acddcc02ef086fbda688d4709e5ba (diff)
implement beer's law for colourful dielectrics
Diffstat (limited to 'src')
-rw-r--r--src/hittable/constant_medium.rs2
-rw-r--r--src/main.rs6
-rw-r--r--src/material/dielectric.rs25
-rw-r--r--src/material/mod.rs1
-rw-r--r--src/scenes.rs16
5 files changed, 37 insertions, 13 deletions
diff --git a/src/hittable/constant_medium.rs b/src/hittable/constant_medium.rs
index b047c23..36ac2ff 100644
--- a/src/hittable/constant_medium.rs
+++ b/src/hittable/constant_medium.rs
@@ -1,6 +1,6 @@
use std::sync::Arc;
-use crate::{hittable::{HitRecord, Hittable, AABB}, material::{Isotropic, Material}, ray::Ray, texture::Texture, vec3::Vec3};
+use crate::{hittable::{HitRecord, Hittable, AABB}, material::{Isotropic, Material}, ray::Ray, texture::Texture, vec3::{Vec3, Point3}};
pub struct ConstantMedium {
boundary: Arc<dyn Hittable>,
diff --git a/src/main.rs b/src/main.rs
index c99ca58..0fe2df9 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -14,7 +14,7 @@ use camera::Camera;
use hittable::Hittable;
use display::{Display, Image, Pixelflut};
use ray::Ray;
-use vec3::{Vec3, Color};
+use vec3::{Vec3, Color, Point3};
use scenes::get_scene;
struct PixelUpdate {
@@ -33,7 +33,7 @@ fn ray_color(ray: &Ray, background: &Color, world: &dyn Hittable, depth: u32) ->
}
match world.hit(ray, 0.001, f64::INFINITY) {
None => background.clone(),
- Some(rec) => {
+ Some(mut rec) => {
let mut scattered = Ray::new();
let mut attenuation = Color::new();
if let Some(material) = &rec.material {
@@ -70,7 +70,7 @@ fn main() {
//const ASPECT_RATIO: f64 = 1.0;
const IMAGE_WIDTH: u32 = 600;
const IMAGE_HEIGHT: u32 = (IMAGE_WIDTH as f64 / ASPECT_RATIO) as u32;
- const SAMPLES_PER_PIXEL: u32 = 500;
+ const SAMPLES_PER_PIXEL: u32 = 30;
const MAX_DEPTH: u32 = 50;
const THREAD_COUNT: u32 = 8;
const TIME_START: f64 = 0.0;
diff --git a/src/material/dielectric.rs b/src/material/dielectric.rs
index bcacb78..1a49f73 100644
--- a/src/material/dielectric.rs
+++ b/src/material/dielectric.rs
@@ -1,10 +1,18 @@
+use std::ops::Neg;
+
use super::Material;
use crate::{hittable::HitRecord, vec3::Vec3};
use crate::vec3::Color;
use crate::ray::Ray;
+pub struct DielectricAttenuation {
+ pub albedo: Color,
+ pub constant: f64,
+}
+
pub struct Dielectric {
pub index_of_refraction: f64,
+ pub attenuation: Option<DielectricAttenuation>,
}
impl Dielectric {
@@ -18,7 +26,22 @@ impl Dielectric {
impl Material for Dielectric {
fn scatter(&self, ray_in: &Ray, hit_record: &HitRecord, attenuation: &mut Color, scattered: &mut Ray) -> bool {
- *attenuation = Color { x: 1.0, y: 1.0, z: 1.0 };
+ if let Some(props) = &self.attenuation {
+ let outward_normal = if hit_record.front_face {
+ hit_record.normal.clone()
+ } else {
+ -&hit_record.normal
+ };
+ if outward_normal.dot(&ray_in.direction) > 0.0 {
+ let distance = (&ray_in.origin - &hit_record.p).length();
+ let falloff_ratio = (props.constant * distance).neg().exp();
+ *attenuation = &props.albedo * falloff_ratio;
+ } else {
+ *attenuation = props.albedo.clone();
+ }
+ } else {
+ *attenuation = Color { x: 1.0, y: 1.0, z: 1.0 };
+ }
let refraction_ratio = if hit_record.front_face { 1.0 / self.index_of_refraction } else { self.index_of_refraction };
let unit_direction = ray_in.direction.unit_vector();
let cos_theta = hit_record.normal.dot(&-&unit_direction).min(1.0);
diff --git a/src/material/mod.rs b/src/material/mod.rs
index bf1eb24..c292ea1 100644
--- a/src/material/mod.rs
+++ b/src/material/mod.rs
@@ -4,6 +4,7 @@ mod metal;
pub use metal::Metal;
mod dielectric;
pub use dielectric::Dielectric;
+pub use dielectric::DielectricAttenuation;
mod diffuse_light;
pub use diffuse_light::DiffuseLight;
mod isotropic;
diff --git a/src/scenes.rs b/src/scenes.rs
index 7cdce86..54f6eb3 100644
--- a/src/scenes.rs
+++ b/src/scenes.rs
@@ -3,7 +3,7 @@ use std::sync::Arc;
use crate::hittable::{ConstantMedium, Hittable};
use crate::hittable::HittableBox;
use crate::hittable::HittableList;
-use crate::material::{Dielectric, DiffuseLight, Lambertian, Material, Metal};
+use crate::material::{Dielectric, DielectricAttenuation, DiffuseLight, Lambertian, Material, Metal};
use crate::hittable::instance::RotateY;
use crate::hittable::instance::RotateX;
use crate::hittable::instance::RotateZ;
@@ -59,14 +59,14 @@ fn random_scene() -> (Arc<dyn Hittable>, Point3, Point3, f64, f64, Color) {
sphere_material = Arc::new(Metal { albedo, fuzz });
world.add(Arc::new(Sphere { center, radius: 0.2, material: sphere_material }));
} else {
- sphere_material = Arc::new(Dielectric { index_of_refraction: 1.5 });
+ sphere_material = Arc::new(Dielectric { index_of_refraction: 1.5, attenuation: Some(DielectricAttenuation { albedo: Color { x: 0.5, y: 0.5, z: 0.8 }, constant: 0.8 } ) });
world.add(Arc::new(Sphere { center, radius: 0.2, material: sphere_material }));
}
}
}
}
- let material1 = Arc::new(Dielectric { index_of_refraction: 1.5 });
+ let material1 = Arc::new(Dielectric { index_of_refraction: 1.5, attenuation: Some(DielectricAttenuation { albedo: Color { x: 0.5, y: 0.5, z: 0.8 }, constant: 0.8 } ) });
world.add(Arc::new(Sphere { center: Point3 { x: 0.0, y: 1.0, z: 0.0 }, radius: 1.0, material: material1 }));
let material2 = Arc::new(Lambertian { albedo: Arc::new(SolidColor::from_color(Color { x: 0.4, y: 0.2, z: 0.1 })) });
@@ -199,13 +199,13 @@ fn final_scene() -> (Arc<dyn Hittable>, Point3, Point3, f64, f64, Color) {
let moving_sphere_material = Arc::new(Lambertian::from_color(Color { x: 0.7, y: 0.3, z: 0.1 }));
objects.add(Arc::new(Moving { hittable: Arc::new(Sphere { center: Point3::new(), radius: 50.0, material: moving_sphere_material }), offset_start: center_1, offset_end: center_2, time_start: 0.0, time_end: 1.0, }));
- objects.add(Arc::new(Sphere { center: Point3 { x: 260.0, y: 150.0, z: 45.0 }, radius: 50.0, material: Arc::new(Dielectric { index_of_refraction: 1.5 }) }));
+ objects.add(Arc::new(Sphere { center: Point3 { x: 260.0, y: 150.0, z: 45.0 }, radius: 50.0, material: Arc::new(Dielectric { index_of_refraction: 1.5, attenuation: None }) }));
objects.add(Arc::new(Sphere { center: Point3 { x: 0.0, y: 150.0, z: 145.0 }, radius: 50.0, material: Arc::new(Metal { albedo: Color { x: 0.8, y: 0.8, z: 0.9 }, fuzz: 1.0 }) }));
- let boundary = Arc::new(Sphere { center: Point3 { x: 360.0, y: 150.0, z: 145.0 }, radius: 70.0, material: Arc::new(Dielectric { index_of_refraction: 1.5 }) });
+ let boundary = Arc::new(Sphere { center: Point3 { x: 360.0, y: 150.0, z: 145.0 }, radius: 70.0, material: Arc::new(Dielectric { index_of_refraction: 1.5, attenuation: None }) });
objects.add(boundary.clone());
objects.add(Arc::new(ConstantMedium::new(boundary.clone(), 0.2, Arc::new(SolidColor::from_color(Color { x: 0.2, y: 0.4, z: 0.9 })))));
- let boundary = Arc::new(Sphere { center: Point3 { x: 0.0, y: 0.0, z: 0.0 }, radius: 5000.0, material: Arc::new(Dielectric { index_of_refraction: 1.5 }) });
+ let boundary = Arc::new(Sphere { center: Point3 { x: 0.0, y: 0.0, z: 0.0 }, radius: 5000.0, material: Arc::new(Dielectric { index_of_refraction: 1.5, attenuation: None }) });
objects.add(Arc::new(ConstantMedium::new(boundary.clone(), 0.0001, Arc::new(SolidColor::from_color(Color { x: 1.0, y: 1.0, z: 1.0 })))));
let emat = Arc::new(Lambertian { albedo: Arc::new(ImageTexture::from_bmp_data(&include_bytes!("../res/earthmap.bmp").to_vec())) });
@@ -242,8 +242,8 @@ fn triangle_scene() -> (Arc<dyn Hittable>, Point3, Point3, f64, f64, Color) {
//let pertext = Arc::new(Lambertian { albedo: Arc::new(NoiseTexture::new(4.0)) });
//let pertext = Arc::new(Lambertian { albedo: Arc::new(SolidColor::from_color(Color {x: 0.0, y: 0.0, z: 0.0}) ) });
//objects.add(Arc::new(Triangle { material: Arc::new(Metal { albedo: Color { x: 0.7, y: 0.6, z: 0.5 }, fuzz: 0.0 }), v0 : Vec3::new(), v1: Vec3 { x: 0.0, y: 0.0, z: 1.0 }, v2: Vec3 { x: 0.0, y: 1.0, z: 0.5 } }));
- //let monkey = Arc::new(Model::from_obj(include_str!("../res/monkey.obj"), Arc::new(Dielectric { index_of_refraction: 1.5 })));
- let monkey = Arc::new(Model::from_obj(include_str!("../res/monkey.obj"), Arc::new(Metal { albedo: Color { x: 0.7, y: 0.6, z: 0.5 }, fuzz: 0.5 })));
+ let monkey = Arc::new(Model::from_obj(include_str!("../res/monkey.obj"), Arc::new(Dielectric { index_of_refraction: 1.5, attenuation: Some(DielectricAttenuation { albedo: Color { x: 0.5, y: 0.5, z: 0.8 }, constant: 0.8 } ) })));
+ // let monkey = Arc::new(Model::from_obj(include_str!("../res/monkey.obj"), Arc::new(Metal { albedo: Color { x: 0.7, y: 0.6, z: 0.5 }, fuzz: 0.5 })));
let monkey = Arc::new(RotateX::new(monkey, 45.0));
let monkey = Arc::new(RotateZ::new(monkey, 45.0));
objects.add(monkey);