From ae73e626b95c732d883afa59fb7b51e422c7211f Mon Sep 17 00:00:00 2001 From: djairoh Date: Sat, 2 May 2026 13:48:27 +0200 Subject: [PATCH] wip: normal material --- scenes/scene.json | 15 ++++++++------- src/camera.rs | 2 +- src/objects/cube.rs | 1 + src/objects/hit.rs | 1 + src/objects/materials.rs | 1 + src/objects/materials/normal.rs | 17 +++++++++++++++++ src/objects/quad.rs | 3 ++- src/objects/triangle.rs | 4 +--- src/scenes/scene.rs | 3 +++ src/vec3.rs | 1 + 10 files changed, 36 insertions(+), 12 deletions(-) create mode 100644 src/objects/materials/normal.rs diff --git a/scenes/scene.json b/scenes/scene.json index 7a99474..351e763 100644 --- a/scenes/scene.json +++ b/scenes/scene.json @@ -4,9 +4,9 @@ "image_height": 1080, "anti_alias_rate": 1, "max_depth": 50, - "fov": 50.0, - "look_from": [15, 4, 10], - "look_at": [10.0, 2.0, 0.0], + "fov": 10.0, + "look_from": [0, 4, 15], + "look_at": [0.0, 0.0, 0.0], "vup": [0.0, 1.0, 0.0], "defocus_angle": 0, "focus_dist": 15.68 @@ -14,20 +14,21 @@ "materials": [ { "type": "lambertian", "albedo": [0.2, 0.2, 0.2], "prob": 0.8 }, { "type": "lambertian", "albedo": [0.9, 0.9, 0.0], "prob": 1.0, "fuzz": 0.1 }, - { "type": "dielectric", "refraction_index": 1.5} + { "type": "dielectric", "refraction_index": 1.5}, + { "type": "normal"} ], "objects": [ { "type": "sphere", "center": [0.0, 0.0, -1.2], "radius": 0.5, "material": { "type": "metal", "albedo": [0.7, 0.4, 0.2], "prob": 1.0, "fuzz": 0.1 }}, - { "type": "sphere", "center": [-1, 0, -1], "radius": 0.4, "material": 2}, + { "type": "sphere", "center": [-1, 0, -1], "radius": 0.4, "material": 3}, { "type": "sphere", "center": [1, 0, -1], "radius": 0.5, "material": { "type": "metal", "albedo": [0.8, 0.6, 0.2], "prob": 1.0, "fuzz": 1.0 }}, { "type": "triangle", "p1": [-4, 0, -4], "p2": [0, 0, -4], "p3": [-2, 2, -4], "material": 1}, { "type": "triangle", "p1": [0, 0, -4], "p2": [4, 0, -4], "p3": [2, 2, -4], "material": 1}, - { "type": "triangle", "p1": [-2, 2, -4], "p2": [2, 2, -4], "p3": [0, 4, -4], "material": 1}, + { "type": "triangle", "p1": [-2, 2, -4], "p2": [2, 2, -4], "p3": [0, 4, -4], "material": 3}, { "type": "quad", "p1": [-20, -1, -20], "p2": [20, -1, -20], "p3": [20, 20, -20], "p4": [-20, 20, -20], "material": 0}, { "type": "quad", "p1": [-20, -1, 20], "p2": [-20, -1, -20], "p3": [-20, 20, -20], "p4": [-20, 20, 20], "material": 0}, { "type": "quad", "p1": [-20, -1, 20], "p2": [20, -1, 20], "p3": [20, -1, -20], "p4": [-20, -1, -20], "material": 0}, { "type": "quad", "p1": [20, -1, 20], "p2": [20, -1, -20], "p3": [20, 20, -20], "p4": [20, 20, 20], "material": 0}, - { "type": "cube", "p1": [8, 0, 2], "p2": [12, 0, 2], "p3": [12, 4, 2], "p4": [8, 4, 2], "p5": [8, 0, -2], "p6": [12, 0, -2], "p7": [12, 4, -2], "p8": [8, 4, -2], "material": 1} + { "type": "cube", "p1": [8, 0, 2], "p2": [12, 0, 2], "p3": [12, 4, 2], "p4": [8, 4, 2], "p5": [8, 0, -2], "p6": [12, 0, -2], "p7": [12, 4, -2], "p8": [8, 4, -2], "material": 3} ] } diff --git a/src/camera.rs b/src/camera.rs index 268d635..a016ca2 100644 --- a/src/camera.rs +++ b/src/camera.rs @@ -1,6 +1,6 @@ use std::{f32::consts::PI, sync::Arc}; -use log::info; +use log::{info, warn}; use crate::{ objects::{hit::Hit, traits::Hittable}, diff --git a/src/objects/cube.rs b/src/objects/cube.rs index 9c9de0f..42b771a 100644 --- a/src/objects/cube.rs +++ b/src/objects/cube.rs @@ -44,6 +44,7 @@ impl Hittable for Cube { } fn normal_at(&self, p: &Vec3) -> Vec3 { + // TODO: normal calc for cube todo!() } } diff --git a/src/objects/hit.rs b/src/objects/hit.rs index b7fb6ff..71043fe 100644 --- a/src/objects/hit.rs +++ b/src/objects/hit.rs @@ -45,6 +45,7 @@ impl Hit { self.front_face } + // TODO: use front_face to discard back-hits for culling pub fn hit_list(hittables: &Vec>, r: &Ray) -> Option { let mut closest: Option = None; for hittable in hittables { diff --git a/src/objects/materials.rs b/src/objects/materials.rs index ba0b2cd..60d9347 100644 --- a/src/objects/materials.rs +++ b/src/objects/materials.rs @@ -1,3 +1,4 @@ pub mod dielectric; pub mod lambertian; +pub mod normal; pub mod traits; diff --git a/src/objects/materials/normal.rs b/src/objects/materials/normal.rs new file mode 100644 index 0000000..7ecb87a --- /dev/null +++ b/src/objects/materials/normal.rs @@ -0,0 +1,17 @@ +use serde::Deserialize; + +use crate::{ + objects::{hit::Hit, materials::traits::Material}, + ray::Ray, + vec3::Vec3, +}; + +#[derive(Debug, Deserialize)] +pub struct Normal {} + +impl Material for Normal { + fn scatter(&self, hit: &Hit, ray: &Ray) -> Option<(Ray, Vec3)> { + let refl = ray.dir().reflect(hit.n()).get_unit(); + Some((Ray::new(*hit.p(), refl), (hit.n() + 1.) / 2.)) + } +} diff --git a/src/objects/quad.rs b/src/objects/quad.rs index ea53fd9..9b24ef5 100644 --- a/src/objects/quad.rs +++ b/src/objects/quad.rs @@ -4,7 +4,7 @@ use crate::objects::traits::Hittable; use crate::objects::triangle::Triangle; use crate::ray::Ray; use crate::{objects::materials::traits::Material, vec3::Vec3}; -use log::info; +use log::{info, warn}; use std::fmt::Debug; use std::sync::Arc; @@ -19,6 +19,7 @@ pub struct Quad { impl Quad { pub fn new(p1: Vec3, p2: Vec3, p3: Vec3, p4: Vec3, material: Arc) -> Self { + warn!("quad normal {}", (p2 - p1).cross(&(p4 - p1)).get_unit()); Self { p1, p2, diff --git a/src/objects/triangle.rs b/src/objects/triangle.rs index 8b389bf..cfdb82c 100644 --- a/src/objects/triangle.rs +++ b/src/objects/triangle.rs @@ -1,5 +1,3 @@ -use log::{info, warn}; - use crate::objects::hit::Hit; use crate::objects::traits::Hittable; use crate::ray::Ray; @@ -56,7 +54,7 @@ impl Triangle { let diff = (a4 - a1 - a2 - a3).abs(); if diff < 0.001 { - return Some(Hit::new(t, p, normal, material, normal.dot(&-r.dir()) < 0.)); + return Some(Hit::new(t, p, normal, material, normal.dot(&-r.dir()) > 0.)); } else { return None; } diff --git a/src/scenes/scene.rs b/src/scenes/scene.rs index 0d1f8c5..97f8772 100644 --- a/src/scenes/scene.rs +++ b/src/scenes/scene.rs @@ -11,6 +11,7 @@ use crate::{ materials::{ dielectric::Dielectric, lambertian::{Lambertian, Metal}, + normal::Normal, traits::Material, }, quad::Quad, @@ -207,6 +208,7 @@ enum MaterialDef { Lambertian(Lambertian), Metal(Metal), Dielectric(Dielectric), + Normal(Normal), } impl MaterialDef { @@ -215,6 +217,7 @@ impl MaterialDef { MaterialDef::Lambertian(l) => Arc::new(l), MaterialDef::Metal(m) => Arc::new(m), MaterialDef::Dielectric(d) => Arc::new(d), + MaterialDef::Normal(n) => Arc::new(n), } } } diff --git a/src/vec3.rs b/src/vec3.rs index 582988a..4ea48fe 100644 --- a/src/vec3.rs +++ b/src/vec3.rs @@ -1,5 +1,6 @@ use core::f32::math::sqrt; use is_close::default; +use log::warn; use rand::RngExt; use serde::{Deserialize, Serialize, Serializer}; use std::{