diff --git a/Cargo.lock b/Cargo.lock index abd5c29..6dbb96b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -148,12 +148,22 @@ dependencies = [ "bytemuck", "byteorder", "color_quant", + "jpeg-decoder", "num-iter", "num-rational", "num-traits", "png", ] +[[package]] +name = "jpeg-decoder" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9478aa10f73e7528198d75109c8be5cd7d15fb530238040148d5f9a22d4c5b3b" +dependencies = [ + "rayon", +] + [[package]] name = "libc" version = "0.2.126" diff --git a/Cargo.toml b/Cargo.toml index 6c46686..73f9150 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,7 +7,7 @@ include = ["/src"] # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -image = { version = "0.24.2", default-features = false, features=["png"] } +image = { version = "0.24.2", default-features = false, features=["png", "jpeg", "jpeg_rayon"] } rand = "0.8.5" rayon = "1.5.3" diff --git a/src/image_texture.rs b/src/image_texture.rs new file mode 100644 index 0000000..6e3bc21 --- /dev/null +++ b/src/image_texture.rs @@ -0,0 +1,55 @@ +/* + let img = image::open("tests/images/jpg/progressive/cat.jpg").unwrap(); + let rgnbi = img.into_rgb8(); + rgnbi.get_pixel(0, 0); + rgnbi. + + */ +use image::{Pixel, RgbImage}; +use crate::{Color, Point3}; +use crate::texture::Texture; + +pub struct ImageTexture { + image: Option +} + +impl ImageTexture { + pub fn new(path: &str) -> Self { + let image = image::open(path) + .map(|i|i.into_rgb8()) + .ok(); + Self { + image + } + } + fn value_from_image(image: &RgbImage, u: f64, v: f64) -> Color { + // Clamp input texture coordinates to [0,1] x [1,0] + let u = u.clamp(0.0, 1.0); + let v = v.abs().clamp(0.0, 1.0); // Flip V to image coordinates + + let i = match (u * image.width() as f64) as i32 { + i if i >= image.width() as i32 => image.width() as i32 - 1, + i => i + }; + let j = match (v * image.height() as f64) as i32 { + j if j >= image.height() as i32 => image.height() as i32 - 1, + j => j + }; + let color_scale = 1.0 / 255.0; + let pixel = image.get_pixel(i as u32, j as u32); + let x = pixel.0[0] as f64 * color_scale; + let y = pixel.0[1] as f64 * color_scale; + let z = pixel.0[2] as f64 * color_scale; + Color::new(x, y, z) + } +} + +impl Texture for ImageTexture { + fn value(&self, u: f64, v: f64, _point: &Point3) -> Color { + match &self.image { + Some(i) => ImageTexture::value_from_image(i, u, v), + // If we have no texture data, then return solid cyan as a debugging aid. + _ => Color::new(0.0, 1.0, 1.0) + } + } +} diff --git a/src/main.rs b/src/main.rs index 6108429..ebe59b9 100644 --- a/src/main.rs +++ b/src/main.rs @@ -12,6 +12,7 @@ use rand::distributions::{Distribution, Uniform}; use rayon::iter::{IntoParallelIterator, ParallelIterator}; use crate::material::{Dielectric, Lambertian, Material, Metal}; use crate::aabb::Aabb; +use crate::image_texture::ImageTexture; use crate::noise::NoiseTexture; use crate::perlin::Perlin; use crate::texture::CheckerTexture; @@ -27,6 +28,20 @@ mod bvh; mod texture; mod perlin; mod noise; +mod image_texture; + +fn earth() -> HittableList { + let mut world:HittableList = Vec::new(); + let earth_texture = ImageTexture::new("textures/earthmap.jpg"); + let earth_material = Arc::new( + Material::Lambertian(Lambertian::textured(Arc::new(earth_texture)))); + world.push(Arc::new(Sphere { + center: Point3::new(0.0, 0.0, 0.0), + radius: 2.0, + material: earth_material + })); + world +} fn two_spheres() -> HittableList { let mut world:HittableList = Vec::new(); @@ -148,7 +163,7 @@ fn main() { const ASPECT_RATIO: f64 = 3.0 / 2.0; const IMAGE_WIDTH: usize = 400; const IMAGE_HEIGHT: usize = (IMAGE_WIDTH as f64 / ASPECT_RATIO) as usize; - const SAMPLES_PER_PIXEL: i32 = 50; + const SAMPLES_PER_PIXEL: i32 = 1; const MAX_DEPTH: i32 = 50; let look_from = Point3::new(13.0, 2.0, 3.0); @@ -168,10 +183,11 @@ fn main() { 1.0); // World - let scene: u8 = 1; + let scene: u8 = 2; let world = match scene { 0 => two_spheres(), 1 => two_perlin_spheres(), + 2 => earth(), _ => random_scene() }; diff --git a/src/output.rs b/src/output.rs index e95f14a..36606fd 100644 --- a/src/output.rs +++ b/src/output.rs @@ -34,4 +34,4 @@ impl Output for PNG { ImageOutputFormat::Png) .map_err(|e| Error::new(ErrorKind::Other, e)) } -} \ No newline at end of file +} diff --git a/textures/earthmap.jpg b/textures/earthmap.jpg new file mode 100644 index 0000000..908c160 Binary files /dev/null and b/textures/earthmap.jpg differ