summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRosyid Haryadi <rosyid_haryadi@protonmail.com>2025-03-03 00:15:55 +0700
committerRosyid Haryadi <rosyid_haryadi@protonmail.com>2025-03-03 00:15:55 +0700
commitab0b3f165788c5d79b2d159aeefda8c8947b68ae (patch)
treefc19c8105c401685f7668ed663050366338a2d27
parent7301f5af4fc7cb7bc13a9d559183f2f095de47d0 (diff)
refactor material
-rw-r--r--src/camera.rs8
-rw-r--r--src/common.rs40
-rw-r--r--src/main.rs15
-rw-r--r--src/material.rs18
-rw-r--r--src/object.rs22
5 files changed, 69 insertions, 34 deletions
diff --git a/src/camera.rs b/src/camera.rs
index 4f2469f..1f211de 100644
--- a/src/camera.rs
+++ b/src/camera.rs
@@ -86,18 +86,12 @@ impl Camera {
let mut rec = HitRecord::default();
let ray_t = Interval::new(0.001, f32::INFINITY);
if world.hit(ray, ray_t, &mut rec) {
- // let direction = Vec3::random_on_hemisphere(&rec.normal);
- let material = Material::new(
- rec.color.clone(),
- rec.material.clone(),
- rec.fuzz
- );
let mut scattered: Ray = Ray {
origin: Vec3::random_unit(),
direction: Vec3::random_unit(),
};
let mut attenuation: Color = Color::new(0.0, 0.0, 0.0);
- if material.scatter(ray, &rec, &mut attenuation, &mut scattered) {
+ if rec.material.scatter(ray, &rec, &mut attenuation, &mut scattered) {
return attenuation.elem_prod(&self.ray_color(&mut scattered, &world, depth - 1));
}
return Color::new(0.0, 0.0, 0.0);
diff --git a/src/common.rs b/src/common.rs
index 918c59c..120d8b4 100644
--- a/src/common.rs
+++ b/src/common.rs
@@ -25,11 +25,51 @@ pub struct Color {
pub b: f32,
}
+pub enum ColorName {
+ Black,
+ White,
+ Red,
+ Lime,
+ Blue,
+ Yellow,
+ Cyan,
+ Magenta,
+ Silver,
+ Gray,
+ Maroon,
+ Olive,
+ Green,
+ Purple,
+ Teal,
+ Navy,
+}
+
impl Color {
pub fn new(r: f32, g: f32, b: f32) -> Self {
Self { r, g, b }
}
+ pub fn from_name(name: ColorName) -> Self {
+ match name {
+ ColorName::Black => { Self::new(0.0, 0.0, 0.0) }
+ ColorName::White => { Self::new(1.0, 1.0, 1.0) }
+ ColorName::Red => { Self::new(1.0, 0.0, 0.0) }
+ ColorName::Lime => { Self::new(0.0, 1.0, 0.0) }
+ ColorName::Blue => { Self::new(0.0, 0.0, 1.0) }
+ ColorName::Yellow => { Self::new(1.0, 1.0, 0.0) }
+ ColorName::Cyan => { Self::new(0.0, 1.0, 1.0) }
+ ColorName::Magenta => { Self::new(1.0, 0.0, 1.0) }
+ ColorName::Silver => { Self::new(0.75, 0.75, 0.75) }
+ ColorName::Gray => { Self::new(0.5, 0.5, 0.5) }
+ ColorName::Maroon => { Self::new(0.5, 0.0, 0.0) }
+ ColorName::Olive => { Self::new(0.5, 0.5, 0.0)}
+ ColorName::Green => { Self::new(0.0, 0.5, 0.0) }
+ ColorName::Purple => { Self::new(0.5, 0.0, 0.5) }
+ ColorName::Teal => { Self::new(0.0, 0.5, 0.5) }
+ ColorName::Navy => { Self::new(0.0, 0.0, 0.5) }
+ }
+ }
+
pub fn mul_scalar(&self, scalar: f32) -> Color {
Self {
r: self.r * scalar,
diff --git a/src/main.rs b/src/main.rs
index fa6c194..cc5d6b6 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -7,8 +7,8 @@ mod interval;
mod material;
use crate::calculus::calculus::Point3;
-use crate::common::*;
use crate::camera::Camera;
+use crate::common::*;
use crate::material::{Material, MaterialType};
use crate::object::{HittableList, Sphere};
use crate::view::{render_viewer, View};
@@ -17,17 +17,22 @@ fn main() {
let mut display_buffer: DisplayBuffer = [[Pixel::default(); IMG_WIDTH]; IMG_HEIGHT];
let mut world = HittableList::new();
+ let ground = Material::new(Color::from_name(ColorName::Maroon), MaterialType::Diffuse);
+ let blue = Material::new(Color::new(0.1, 0.2, 0.5), MaterialType::Diffuse);
+ let steel = Material::new(Color::from_name(ColorName::Silver), MaterialType::Metal(0.1));
+ let gold = Material::new(Color::from_name(ColorName::Yellow), MaterialType::Metal(0.0));
+
world.push(
- Sphere::new(Point3::new(0.0, -100.5, -1.0), 100.0, MaterialType::Diffuse, Color::new(0.8, 0.8, 0.0), 0.0)
+ Sphere::new(Point3::new(0.0, -100.5, -1.0), 100.0, ground)
);
world.push(
- Sphere::new(Point3::new(0.0, 0.0, -1.2), 0.5, MaterialType::Diffuse, Color::new(0.1, 0.2, 0.5), 0.0)
+ Sphere::new(Point3::new(0.0, 0.0, -1.2), 0.5, blue)
);
world.push(
- Sphere::new(Point3::new(-1.0, 0.0, -1.0), 0.5, MaterialType::Metal, Color::new(0.8, 0.8, 0.8), 0.1)
+ Sphere::new(Point3::new(-1.0, 0.0, -1.0), 0.5, steel)
);
world.push(
- Sphere::new(Point3::new(1.0, 0.0, -1.0), 0.5, MaterialType::Metal, Color::new(0.8, 0.6, 0.2), 0.0)
+ Sphere::new(Point3::new(1.0, 0.0, -1.0), 0.5, gold)
);
let camera = Camera::new();
diff --git a/src/material.rs b/src/material.rs
index 731eb0c..a654f4d 100644
--- a/src/material.rs
+++ b/src/material.rs
@@ -5,19 +5,23 @@ use crate::object::HitRecord;
#[derive(Clone)]
pub enum MaterialType {
Diffuse,
- Metal,
+ Metal(f32), // color fuzz
}
+#[derive(Clone)]
pub struct Material {
pub material_type: MaterialType,
pub albedo: Color,
- pub fuzz: f32,
}
impl Material {
- pub fn new(albedo: Color, material_type: MaterialType, fuzz: f32) -> Self {
- let fuzz = if fuzz < 1.0 { fuzz } else { 1.0 };
- Self { albedo, material_type, fuzz }
+ pub fn new(albedo: Color, material_type: MaterialType) -> Self {
+ let mut material_type = material_type;
+ if let MaterialType::Metal(fuzz) = material_type {
+ let fuzz = if fuzz < 1.0 { fuzz } else { fuzz };
+ material_type = MaterialType::Metal(fuzz);
+ }
+ Self { albedo, material_type }
}
pub fn scatter(&self, r_in: &Ray, rec: &HitRecord, attenuation: &mut Color, scattered: &mut Ray) -> bool {
@@ -30,9 +34,9 @@ impl Material {
scatter_direction
}
}
- MaterialType::Metal => {
+ MaterialType::Metal(fuzz) => {
let mut reflected = r_in.reflect(&rec.normal);
- reflected.unit().add(&Vec3::random_unit().scalar_mul(self.fuzz))
+ reflected.unit().add(&Vec3::random_unit().scalar_mul(fuzz))
}
};
diff --git a/src/object.rs b/src/object.rs
index 2192703..0161d38 100644
--- a/src/object.rs
+++ b/src/object.rs
@@ -1,7 +1,7 @@
use crate::calculus::calculus::{Point3, Ray, Vec3};
use crate::common::Color;
use crate::interval::Interval;
-use crate::material::MaterialType;
+use crate::material::{Material, MaterialType};
#[derive(Clone)]
pub struct HitRecord {
@@ -9,9 +9,7 @@ pub struct HitRecord {
pub normal: Vec3,
pub t: f32,
pub front_face: bool,
- pub material: MaterialType,
- pub color: Color,
- pub fuzz: f32,
+ pub material: Material,
}
impl Default for HitRecord {
@@ -21,9 +19,7 @@ impl Default for HitRecord {
normal: Vec3 {x:0.0, y:0.0, z:0.0},
t: 0.0,
front_face: false,
- material: MaterialType::Diffuse,
- color:Color::new(0.0, 0.0, 0.0),
- fuzz: 1.0,
+ material: Material::new(Color::new(1.0, 1.0, 1.0), MaterialType::Diffuse),
}
}
}
@@ -42,15 +38,13 @@ pub trait Hittable {
pub struct Sphere {
center: Point3,
radius: f32,
- material: MaterialType,
- color: Color,
- fuzz: f32,
+ material: Material,
}
impl Sphere {
- pub fn new(center: Vec3, radius: f32, material: MaterialType, color: Color, fuzz: f32) -> Self {
+ pub fn new(center: Vec3, radius: f32, material: Material) -> Self {
let radius = f32::max(0.0, radius);
- Self { center, radius, material, color, fuzz }
+ Self { center, radius, material }
}
}
@@ -82,8 +76,6 @@ impl Hittable for Sphere {
.scalar_mul(1.0 / self.radius);
rec.set_face_normal(r, outward_normal);
rec.material = self.material.clone();
- rec.color = self.color.clone();
- rec.fuzz = self.fuzz;
true
}
@@ -105,7 +97,7 @@ impl HittableList {
impl Hittable for HittableList {
fn hit(&self, r: &Ray, ray_t: Interval, rec: &mut HitRecord) -> bool {
- let mut temp_rec = HitRecord::default();
+ let mut temp_rec = rec.clone();
let mut hit_anything = false;
let mut closest_so_far = ray_t.max;