use image::{DynamicImage, ImageReader}; use log::trace; use crate::{objects::hit::Hit, vec3::Vec3}; #[derive(Debug)] pub struct Texture { source: DynamicImage, width: u32, height: u32, stride: usize, } 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() ); let stride = match img.color() { // TODO: support other types of image image::ColorType::L8 => todo!(), image::ColorType::La8 => todo!(), image::ColorType::Rgb8 => 3, image::ColorType::Rgba8 => 4, image::ColorType::L16 => todo!(), image::ColorType::La16 => todo!(), image::ColorType::Rgb16 => todo!(), image::ColorType::Rgba16 => todo!(), image::ColorType::Rgb32F => todo!(), image::ColorType::Rgba32F => todo!(), _ => 3, }; Self { width: img.width(), height: img.height(), source: img, stride, } } fn _idx(&self, u: f32, v: f32) -> usize { let x: usize = (u * ((self.width - 1) as f32)) as usize; let y: usize = (v * ((self.height - 1) as f32)) as usize; y * self.width as usize + x } fn _at(&self, u: f32, v: f32) -> Vec3 { let b = self.source.as_bytes(); let idx = self._idx(u, v); Vec3::from_u8( b[self.stride * idx], b[self.stride * idx + 2], b[self.stride * idx + 1], ) } pub fn colour_at(&self, hit: &Hit) -> Vec3 { let (u, v) = hit.uv(); self._at(u, 1. - v) } }