Bumpmapping
This commit is contained in:
@@ -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 {
|
||||
|
||||
63
src/main.rs
63
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::<f64>() * 250.0 * 10.0;
|
||||
let y: f64 = rng.gen::<f64>() * 250.0 * 10.0;
|
||||
let z: f64 = rng.gen::<f64>() * 250.0 * 10.0;
|
||||
let radius: f64 = rng.gen::<f64>() * 40.0 * 10.0;
|
||||
let red: f32 = rng.gen::<f32>() * 100.0;
|
||||
let green: f32 = rng.gen::<f32>() * 100.0;
|
||||
let blue: f32 = rng.gen::<f32>() * 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::<f32>() }),
|
||||
};
|
||||
//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(),
|
||||
|
||||
@@ -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<f64>, incident: Vec3<f64>, hit_point: Vec3<f64
|
||||
|
||||
fn get_color(camera: &PerspectiveCamera, ray: &Ray, intersection: &Intersection, depth: u32) -> 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<f
|
||||
// https://github.com/bheisler/raytracer/blob/7130556181de7fc59eaa29346f5d4134db3e720e/src/rendering.rs#L195
|
||||
let texture_coords = object.texture_coords(&hit_point);
|
||||
|
||||
let heightmap = material.coloration.height(&texture_coords);
|
||||
|
||||
// Shadow stuff
|
||||
let shadow_ray = Ray {
|
||||
pos: hit_point + surface_normal.normalize(),
|
||||
// Can be used for actual bumpy light calculations
|
||||
//pos: bump_point,
|
||||
dir: direction_to_light.normalize(),
|
||||
};
|
||||
|
||||
@@ -93,7 +106,7 @@ fn shade_diffuse(camera: &PerspectiveCamera, object: &Element, hit_point: Vec3<f
|
||||
|| shadow_intersection.unwrap().distance > 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;
|
||||
|
||||
Reference in New Issue
Block a user