From 04b166ac720fb15cfb7c2852b1f9e75dbc325885 Mon Sep 17 00:00:00 2001 From: maddiebaka Date: Sat, 17 Jun 2023 01:19:13 -0400 Subject: [PATCH] Bumpmapping --- src/elements.rs | 36 ++++++++++++++++++++++++++++ src/main.rs | 63 ++++++++++++++++++------------------------------- src/renderer.rs | 15 +++++++++++- 3 files changed, 73 insertions(+), 41 deletions(-) diff --git a/src/elements.rs b/src/elements.rs index 2f1060c..d8d6a7b 100644 --- a/src/elements.rs +++ b/src/elements.rs @@ -117,12 +117,48 @@ impl Coloration { } } } + + pub fn height(&self, coords: &TextureCoords) -> f32 { + match *self { + Coloration::Color(ref c) => { + 1.0 + }, + Coloration::Texture(ref texture) => { + let delta_u = (1.0 / texture.heightmap.width() as f32) * 0.5; + + let delta_height = texture.get_height(coords.x + delta_u, coords.y); + let height = texture.get_height(coords.x, coords.y); + + //println!("delta_height : height : {} : {}", delta_height, height); + + let result = (delta_height - height) / delta_u; + + //result + + (height - 100.0) / 60.0 + //(delta_height - height) + 1.0 + + //Color::from_rgba(texture.heightmap.get_pixel(tex_x, tex_y)) + } + } + } } // T)extures #[derive(Clone)] pub struct Texture { pub texture: DynamicImage, + pub heightmap: DynamicImage, +} + +impl Texture { + // TODO: Might need to take more channels into account + pub fn get_height(&self, x: f32, y: f32) -> f32 { + let tex_x = wrap(x, self.heightmap.width()); + let tex_y = wrap(y, self.heightmap.height()); + + self.heightmap.get_pixel(tex_x, tex_y).0[0] as f32 + } } pub fn dummy_texture() -> DynamicImage { diff --git a/src/main.rs b/src/main.rs index 03e8a93..607722c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -28,31 +28,11 @@ 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)); + camera.lights.push(LightSrc::new(Vec3::new(180000.0, 900.0, 300.0), 2.0)); + camera.lights.push(LightSrc::new(Vec3::new(1100.0, 800.0, 300.0), 2.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), @@ -62,38 +42,41 @@ fn initialize_scene(camera: &mut PerspectiveCamera) { }; camera.elements.push(Element::Plane(back_plane)); - let path = Path::new("texture/granite_base.png"); + let texture_path = Path::new("texture/granite_base.png"); + let height_path = Path::new("texture/granite_height.png"); + let normal_path = Path::new("texture/granite_normal.png"); - let texture_image = image::open(&path).unwrap(); + let texture_image = image::open(&texture_path).unwrap(); + let height_image = image::open(&height_path).unwrap(); + let normal_image = image::open(&normal_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 base_texture = Texture { texture: texture_image.clone(), heightmap: height_image }; 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 }), + pos: Vec3::new(800.0, 1290.0, 1000.0), + radius: 300.0, + material: Material::new(Coloration::Texture(base_texture.clone()), 2.0, SurfaceType::Diffuse), }; camera.elements.push(Element::Sphere(left_sphere)); - let top_sphere = Sphere { - pos: Vec3::new(1080.0, 700.0, 500.0), - radius: 200.0, + let right_sphere = Sphere { + pos: Vec3::new(1480.0, 1290.0, 1000.0), + radius: 300.0, material: Material::new(Coloration::Texture(base_texture.clone()), 2.0, SurfaceType::Diffuse), }; - camera.elements.push(Element::Sphere(top_sphere)); + camera.elements.push(Element::Sphere(right_sphere)); + let center_sphere = Sphere { + pos: Vec3::new(1280.0, 690.0, 1100.0), + radius: 300.0, + material: Material::new(Coloration::Texture(base_texture.clone()), 2.0, SurfaceType::Reflective { reflectivity: 0.2 }), + }; + camera.elements.push(Element::Sphere(center_sphere)); } fn main() { let mut camera = PerspectiveCamera { - pos: Vec3::new(1280.0, 1280.0, -1000.0), + pos: Vec3::new(1280.0, 1280.0, -200.0), output_img: Image::new(2560,2560), elements: Vec::new(), lights: Vec::new(), diff --git a/src/renderer.rs b/src/renderer.rs index 113aa9b..7f939b5 100644 --- a/src/renderer.rs +++ b/src/renderer.rs @@ -7,6 +7,8 @@ use crate::camera::*; use crate::elements::*; +const BUMPMAP_SCALE: f64 = 1.0; + const BLACK: Color = Color { red: 0.0, green: 0.0, @@ -55,7 +57,14 @@ fn create_reflection(normal: Vec3, incident: Vec3, hit_point: Vec3 Color { let hit_point = ray.pos + (ray.dir * intersection.distance); + let texture_coords = intersection.object.texture_coords(&hit_point); + //let material = intersection.object.material(); + //let heightmap_value = material.coloration.height(&texture_coords); + + //let surface_normal = intersection.object.normal(hit_point) * heightmap_value as f64; + //let bump_hit_point = hit_point + surface_normal; let surface_normal = intersection.object.normal(hit_point); + //println!("heightmap_value: {}", heightmap_value); let material = intersection.object.material(); @@ -82,9 +91,13 @@ fn shade_diffuse(camera: &PerspectiveCamera, object: &Element, hit_point: Vec3 light.distance(hit_point); let light_intensity = if in_light { light.intensity } else { 0.0 }; - let light_power = (surface_normal.normalize().dot(&direction_to_light.normalize()) as f32).max(0.0); + let light_power = heightmap * (surface_normal.normalize().dot(&direction_to_light.normalize()) as f32).max(0.0); let light_reflected = material.albedo / f32::consts::PI; let light_color = light_intensity * light_power * light_reflected;