From f1f0bee4cf822070af489be5964bcaf165854925 Mon Sep 17 00:00:00 2001 From: djairoh Date: Sun, 13 Sep 2026 21:01:47 +0200 Subject: [PATCH] ft: texture loading err handling now uses a default placeholder texture + colour source --- scenes/lowDef.json | 37 +++++++++++++++++++ scenes/texture.json | 37 ------------------- src/objects/materials/colour_source.rs | 12 +++---- src/objects/materials/texture.rs | 49 ++++++++++++++++++++------ src/raytracer.rs | 2 +- src/scenes/material_def.rs | 1 - 6 files changed, 83 insertions(+), 55 deletions(-) create mode 100644 scenes/lowDef.json delete mode 100644 scenes/texture.json diff --git a/scenes/lowDef.json b/scenes/lowDef.json new file mode 100644 index 0000000..a1317f1 --- /dev/null +++ b/scenes/lowDef.json @@ -0,0 +1,37 @@ +{ + "filename": "lowDef.png", + "image_width": 1920, + "image_height": 1080, + "max_depth": 50, + "camera": { + "anti_alias_rate": 7, + "fov": 20.0, + "look_from": [10, 5, 10], + "look_at": [0.0, 0.0, -1.0], + "vup": [0.0, 1.0, 0.0], + "defocus_angle": 0, + "focus_dist": 15.68 + }, + "materials": [ + { "type": "metal", "colour": "./balls", "prob": 1.0, "fuzz": 0.1}, + { "type": "metal", "colour": "./balls", "prob": 1.0, "fuzz": 0.1}, + { "type": "lambertian", "colour": "balls", "prob": 1.0}, + { "type": "metal", "colour": "./balls", "prob": 1.0, "fuzz": 0.1}, + { "type": "dielectric", "colour": "balls", "refraction_index": 1.5}, + { "type": "dielectric", "colour": "balls", "refraction_index": 1.5}, + { "type": "dielectric", "colour": "balls", "refraction_index": 1.5} + + ], + "objects": [ + { "type": "sphere", "center": [0, 0.7, -0.4], "radius": 0.2, "material": 0}, + { "type": "sphere", "center": [0.0, 0.5, -0.8], "radius": 0.1, "material": 1}, + { "type": "sphere", "center": [0.0, -100.5, -1.0], "radius": 100.0, "material": 2}, + { "type": "sphere", "center": [0.0, 0.0, -1.2], "radius": 0.5, "material": 3}, + { "type": "sphere", "center": [-1, 0, -1], "radius": 0.4, "material": 5}, + { "type": "sphere", "center": [1, 0, -1], "radius": 0.5, "material": 6}, + { "type": "sphere", "center": [20, 7, -15], "radius": 10.5, "material": 0} + ] +} + + + diff --git a/scenes/texture.json b/scenes/texture.json deleted file mode 100644 index b5c2466..0000000 --- a/scenes/texture.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "filename": "textured2.png", - "image_width": 1920, - "image_height": 1080, - "max_depth": 50, - "camera": { - "anti_alias_rate": 5, - "fov": 50.0, - "look_from": [-3, 4, 10], - "look_at": [-3, 0.0, -10.0], - "vup": [0.0, 1.0, 0.0], - "defocus_angle": 0, - "focus_dist": 15.68 - }, - "materials": [ - { "type": "lambertian", "colour": [0.2, 0.2, 0.2], "prob": 0.8 }, - { "type": "dielectric", "refraction_index": 1.5, "colour": [0.9, 0.1, 0.4]}, - { "type": "metal", "colour": "./textures/ballnold.png", "prob": 1.0, "fuzz": 0.1 }, - { "type": "dielectric", "refraction_index": 1.5} - ], - "objects": [ - { "type": "sphere", "center": [0.0, 0.0, -1.2], "radius": 0.9, "material": 2}, - { "type": "sphere", "center": [-2, 0, -1], "radius": 0.8, "material": 1}, - { "type": "sphere", "center": [-2, 4, -1], "radius": 0.9, "material": 3}, - { "type": "triangle", "p1": [0, 0, -4], "p2": [4, 0, -4], "p3": [2, 2, -4], "material": 2}, - { "type": "triangle", "p1": [-2, 2, -4], "p2": [2, 2, -4], "p3": [0, 4, -4], "material": 1}, - { "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": "quad", "p1": [-4, 3, -4], "p2": [-1, 3, -4], "p3": [-1, 6, -4], "p4": [-4, 6, -4], "material": 1}, - { "type": "quad", "p1": [-8, 3, -4], "p2": [-5, 3, -4], "p3": [-5, 6, -4], "p4": [-8, 6, -4], "material": 2} - ] -} - - - diff --git a/src/objects/materials/colour_source.rs b/src/objects/materials/colour_source.rs index 9cc6ada..32faeb1 100644 --- a/src/objects/materials/colour_source.rs +++ b/src/objects/materials/colour_source.rs @@ -11,6 +11,12 @@ pub enum ColourSource { Texture(Texture), } +impl Default for ColourSource { + fn default() -> Self { + Self::rgb(1., 1., 1.) + } +} + impl ColourSource { pub fn get_colour(&self, hit: &Hit) -> Colour { match self { @@ -24,12 +30,6 @@ impl ColourSource { } } -impl Default for ColourSource { - fn default() -> Self { - Self::rgb(1., 1., 1.) - } -} - #[derive(Deserialize)] #[serde(untagged)] enum RawColourSource { diff --git a/src/objects/materials/texture.rs b/src/objects/materials/texture.rs index 4645826..2b73f93 100644 --- a/src/objects/materials/texture.rs +++ b/src/objects/materials/texture.rs @@ -1,5 +1,8 @@ -use image::{DynamicImage, ImageReader}; -use log::trace; +use std::error::Error; + +use image::{DynamicImage, ImageReader, Rgb}; +use image::{RgbImage}; +use log::warn; use crate::{objects::hit::Hit, vec3::Vec3}; @@ -13,14 +16,26 @@ pub struct Texture { impl Texture { pub fn new(texture: &str) -> Self { - let img = ImageReader::open(texture).unwrap().decode().unwrap(); // FIXME: unwraps - trace!( - "texture '{}' is {} by {} pixels, with {} bytes total", - texture, - img.width(), - img.height(), - img.as_bytes().len() - ); + match ImageReader::open(texture) { + Ok(r) => { + match r.decode() { + Ok(img) => Self::_build(img), + Err(e) => { + // ImageError + warn!("Failed to parse image \"{}\": {}", texture, e); + Self::default() + } + } + } + Err(e) => { + // IoError + warn!("Failed to read file \"{}\": {}", texture, e); + Self::default() + } + } + } + + fn _build(img: DynamicImage) -> Self { let stride = match img.color() { // TODO: support other types of image image::ColorType::L8 => todo!(), @@ -35,6 +50,7 @@ impl Texture { image::ColorType::Rgba32F => todo!(), _ => 3, }; + Self { width: img.width(), height: img.height(), @@ -66,3 +82,16 @@ impl Texture { self._at(u, 1. - v) } } + +impl Default for Texture { + fn default() -> Self { + let mut img = RgbImage::new(1, 1); + img.put_pixel(0,0,Rgb([250,0,250])); + Self { + source: DynamicImage::ImageRgb8(img), + width: 1, + height: 1, + stride: 3, + } + } +} diff --git a/src/raytracer.rs b/src/raytracer.rs index 25d4a62..603bc0e 100644 --- a/src/raytracer.rs +++ b/src/raytracer.rs @@ -1,4 +1,4 @@ -use image::{codecs::png::PngEncoder, ExtendedColorType, ImageEncoder}; +use image::{ExtendedColorType, ImageEncoder, codecs::png::PngEncoder}; use log::{error, info, trace}; use rayon::iter::IntoParallelIterator; use rayon::prelude::*; diff --git a/src/scenes/material_def.rs b/src/scenes/material_def.rs index b8d5b07..e40f9d7 100644 --- a/src/scenes/material_def.rs +++ b/src/scenes/material_def.rs @@ -6,7 +6,6 @@ use crate::objects::materials::{ dielectric::Dielectric, lambertian::{Lambertian, Metal}, normal::Normal, - texture::Texture, traits::Material, };