use std::f32; mod camera; use crate::camera::PerspectiveCamera; mod renderer; use crate::renderer::cast_ray; //use crate::materials::{Material,SurfaceType}; mod elements; use crate::elements::*; #[macro_use] extern crate bmp; extern crate rand; extern crate nalgebra; use std::fs::File; use std::path::*; use rand::Rng; use nalgebra::*; use bmp::Image; use bmp::Pixel; use std::io::{Write,stdout}; use crossterm::{QueueableCommand,cursor,terminal,ExecutableCommand}; fn initialize_scene(camera: &mut PerspectiveCamera) { camera.lights.push(LightSrc::new(Vec3::new(200.0, 800.0, 300.0), 5.0)); camera.lights.push(LightSrc::new(Vec3::new(1200.0, 800.0, 300.0), 5.0)); for i in 0..15 { let mut rng = rand::thread_rng(); let x: f64 = rng.gen::() * 250.0 * 10.0; let y: f64 = rng.gen::() * 250.0 * 10.0; let z: f64 = rng.gen::() * 250.0 * 10.0; let radius: f64 = rng.gen::() * 40.0 * 10.0; let red: f32 = rng.gen::() * 100.0; let green: f32 = rng.gen::() * 100.0; let blue: f32 = rng.gen::() * 100.0; let color = Color { red, green, blue }; let sphere = Sphere { pos: Vec3::new(x, y, 100.0), radius: radius, material: Material::new(Coloration::Color(color), 2.0, SurfaceType::Reflective { reflectivity: rng.gen::() }), }; //camera.elements.push(Element::Sphere(sphere)); } let color = Color { red: 30.0, green: 30.0, blue: 30.0 }; let back_plane = Plane { //pos: Vec3::new(0.0, 0.0, 100.0), pos: Vec3::new(0.0, 0.0, 1500.0), //color: Color::new(20.0, 20.0, 255.0), material: Material::new(Coloration::Color(color), 2.0, SurfaceType::Diffuse), normal: Vec3::new(0.0, 0.0, 1.0), }; camera.elements.push(Element::Plane(back_plane)); // let bottom_plane = Plane { // pos: Vec3::new(2500.0, 0.0, 1500.0), // //color: Coloration::Texture(texture), // //material: Material::new(Coloration::Texture(dummy_texture.clone()), 2.0, SurfaceType::Diffuse), // normal: Vec3::new(0.0, 0.2, 1.0), // }; //camera.elements.push(Element::Plane(bottom_plane)); let path = Path::new("texture/granite_base.png"); let texture_image = image::open(&path).unwrap(); let base_texture = Texture { texture: texture_image }; let center_sphere = Sphere { pos: Vec3::new(1280.0, 1290.0, 1000.0), radius: 300.0, material: Material::new(Coloration::Texture(base_texture.clone()), 2.0, SurfaceType::Reflective { reflectivity: 0.1 }), }; camera.elements.push(Element::Sphere(center_sphere)); let left_sphere = Sphere { pos: Vec3::new(200.0, 1800.0, 500.0), radius: 200.0, material: Material::new(Coloration::Texture(base_texture.clone()), 2.0, SurfaceType::Reflective { reflectivity: 0.1 }), }; camera.elements.push(Element::Sphere(left_sphere)); let top_sphere = Sphere { pos: Vec3::new(1080.0, 700.0, 500.0), radius: 200.0, material: Material::new(Coloration::Texture(base_texture.clone()), 2.0, SurfaceType::Diffuse), }; camera.elements.push(Element::Sphere(top_sphere)); } fn main() { let mut camera = PerspectiveCamera { pos: Vec3::new(1280.0, 1280.0, -1000.0), output_img: Image::new(2560,2560), elements: Vec::new(), lights: Vec::new(), shadow_bias: 1e-3, max_recursion_depth: 5, fov: 90.0, scene_width: 2560, scene_height: 2560, }; initialize_scene(&mut camera); println!("Rusty Rays v1.0 Alpha\n"); println!("Raytracing...\n"); let mut stdout = stdout(); stdout.execute(cursor::Hide).unwrap(); stdout.write_all(format!("Progress: ").as_bytes()).unwrap(); for (x, y) in camera.output_img.coordinates() { stdout.queue(cursor::SavePosition).unwrap(); stdout.write_all(format!("{:.1}%", camera.percent_complete(y)).as_bytes()).unwrap(); //stdout.write_all(format!("Raytracing.. {} : {}", x, y).as_bytes()).unwrap(); stdout.queue(cursor::RestorePosition).unwrap(); stdout.flush().unwrap(); //thread::sleep(time::Duration::from_millis(100)); stdout.queue(cursor::RestorePosition).unwrap(); stdout.queue(terminal::Clear(terminal::ClearType::FromCursorDown)).unwrap(); camera.output_img.set_pixel(x, y, px!(20, 20, 20)); let prime_ray = camera.create_prime(x, y); let pixel = cast_ray(&camera, &prime_ray, 0); camera.output_img.set_pixel(x, y, px!(pixel.red, pixel.green, pixel.blue)); } stdout.queue(cursor::RestorePosition).unwrap(); println!("Render complete! 🎉"); let _ = camera.output_img.save("img.bmp"); }