Added scene, raytracer, pixel display and lights
This commit is contained in:
79
src/display.rs
Normal file
79
src/display.rs
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
use pixels::{Error, Pixels, SurfaceTexture};
|
||||||
|
|
||||||
|
use std::time::Instant;
|
||||||
|
|
||||||
|
use winit::{
|
||||||
|
event::{Event, WindowEvent},
|
||||||
|
event_loop::{ControlFlow, EventLoop},
|
||||||
|
window::WindowBuilder,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub fn run() -> Result<(), Error> {
|
||||||
|
// Create an event loop and window using winit
|
||||||
|
let event_loop = EventLoop::new();
|
||||||
|
let window = WindowBuilder::new().build(&event_loop).unwrap();
|
||||||
|
|
||||||
|
// Create a Pixels instance for drawing
|
||||||
|
let mut pixels = {
|
||||||
|
let window_size = window.inner_size();
|
||||||
|
let surface_texture = SurfaceTexture::new(window_size.width, window_size.height, &window);
|
||||||
|
Pixels::new(800, 600, surface_texture).unwrap()
|
||||||
|
};
|
||||||
|
|
||||||
|
event_loop.run(move |event, _, control_flow| {
|
||||||
|
*control_flow = ControlFlow::Poll;
|
||||||
|
match event {
|
||||||
|
Event::WindowEvent {
|
||||||
|
ref event,
|
||||||
|
window_id,
|
||||||
|
} if window_id == window.id() => {
|
||||||
|
match event {
|
||||||
|
WindowEvent::CloseRequested => *control_flow = ControlFlow::Exit,
|
||||||
|
WindowEvent::Resized(physical_size) => {
|
||||||
|
//We want to change the size of the pixel display
|
||||||
|
pixels
|
||||||
|
.resize_surface(physical_size.width, physical_size.height)
|
||||||
|
.expect("Could not resize");
|
||||||
|
pixels
|
||||||
|
.resize_buffer(physical_size.width, physical_size.height)
|
||||||
|
.expect("Could not resize");
|
||||||
|
}
|
||||||
|
WindowEvent::ScaleFactorChanged { new_inner_size, .. } => {
|
||||||
|
//We want to change the size of the pixel display
|
||||||
|
// new_inner_size is &mut so w have to dereference it twice
|
||||||
|
pixels
|
||||||
|
.resize_surface(new_inner_size.width, new_inner_size.height)
|
||||||
|
.expect("Could not resize!");
|
||||||
|
pixels
|
||||||
|
.resize_buffer(new_inner_size.width, new_inner_size.height)
|
||||||
|
.expect("Could not resize");
|
||||||
|
}
|
||||||
|
WindowEvent::KeyboardInput { input, .. } => {
|
||||||
|
println!("Key input: {}", input.scancode);
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Event::RedrawRequested(_) => {
|
||||||
|
// Draw a pixel at every coordinate
|
||||||
|
for (i, pixel) in pixels.frame_mut().chunks_exact_mut(4).enumerate() {
|
||||||
|
let r = (i as u8).wrapping_mul(50);
|
||||||
|
let g = 43;
|
||||||
|
let b = 3;
|
||||||
|
let a = 255;
|
||||||
|
pixel.copy_from_slice(&[r, g, b, a]);
|
||||||
|
}
|
||||||
|
// Render the frame
|
||||||
|
if pixels.render().is_err() {
|
||||||
|
eprintln!("Failed to render frame");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Event::MainEventsCleared => {
|
||||||
|
// RedrawRequested will only trigger once, unless we manually
|
||||||
|
// request it.
|
||||||
|
window.request_redraw();
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
23
src/light.rs
Normal file
23
src/light.rs
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
use nalgebra::{Point3, Vector3};
|
||||||
|
|
||||||
|
pub struct Light {
|
||||||
|
pub colour: Vector3<f32>,
|
||||||
|
pub position: Point3<f32>,
|
||||||
|
pub falloff: [f32; 3],
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Light {
|
||||||
|
pub fn new(colour: Vector3<f32>, position: Point3<f32>, falloff: [f32; 3]) -> Self {
|
||||||
|
Light {
|
||||||
|
colour,
|
||||||
|
position,
|
||||||
|
falloff,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn white() -> Self {
|
||||||
|
let colour = Vector3::new(1.0, 1.0, 1.0);
|
||||||
|
let position = Point3::new(0.0, 0.0, 0.0);
|
||||||
|
let falloff = [1.0, 0.0, 0.0];
|
||||||
|
Light::new(colour, position, falloff)
|
||||||
|
}
|
||||||
|
}
|
||||||
52
src/raytracer.rs
Normal file
52
src/raytracer.rs
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
use crate::{
|
||||||
|
primitive::{Intersection, Primitive},
|
||||||
|
ray::Ray,
|
||||||
|
scene::Scene,
|
||||||
|
INFINITY,
|
||||||
|
};
|
||||||
|
use nalgebra::{distance, Matrix4, Point3, Vector3, Vector4};
|
||||||
|
|
||||||
|
// Find the closest intersection, given a ray in world coordinates
|
||||||
|
fn get_closest_intersection<'a>(scene: &'a Scene, ray: &Ray) -> Option<Intersection<'a>> {
|
||||||
|
let mut closest_distance = INFINITY;
|
||||||
|
let mut closest_intersect: Option<Intersection> = None;
|
||||||
|
for primitive in &scene.primitives {
|
||||||
|
if primitive.intersect_bounding_box(ray) == None {
|
||||||
|
continue;
|
||||||
|
};
|
||||||
|
|
||||||
|
let intersect = primitive.intersect_ray(ray);
|
||||||
|
if intersect.is_none() {
|
||||||
|
continue;
|
||||||
|
};
|
||||||
|
|
||||||
|
let intersect = intersect.unwrap();
|
||||||
|
if intersect.distance < closest_distance {
|
||||||
|
closest_distance = intersect.distance;
|
||||||
|
closest_intersect = Some(intersect);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
closest_intersect
|
||||||
|
}
|
||||||
|
|
||||||
|
// We want to shade a point placed in our scene
|
||||||
|
fn phong_shade_point(scene: &Scene, intersect: &Intersection) -> Option<Vector4<f32>> {
|
||||||
|
//Unpack the intersection data
|
||||||
|
let Intersection {
|
||||||
|
primitive,
|
||||||
|
point,
|
||||||
|
normal,
|
||||||
|
incidence,
|
||||||
|
distance,
|
||||||
|
} = intersect;
|
||||||
|
let ambient_light = scene.ambient_light;
|
||||||
|
let material = primitive.get_material();
|
||||||
|
let kd = material.kd;
|
||||||
|
let ks = material.kd;
|
||||||
|
let shininess = material.shininess;
|
||||||
|
// We should now have all the information for our ray-tracer
|
||||||
|
|
||||||
|
// Let us first compute the ambient light component
|
||||||
|
let ambient = ambient_light * kd;
|
||||||
|
None
|
||||||
|
}
|
||||||
13
src/scene.rs
Normal file
13
src/scene.rs
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
use crate::camera::Camera;
|
||||||
|
use crate::light::Light;
|
||||||
|
use crate::primitive::Primitive;
|
||||||
|
use nalgebra::Vector3;
|
||||||
|
|
||||||
|
pub struct Scene<'a> {
|
||||||
|
pub primitives: Vec<Box<dyn Primitive<'a>>>,
|
||||||
|
lights: Vec<Light>,
|
||||||
|
camera: Camera,
|
||||||
|
pub ambient_light: Vector3<f32>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Scene<'a> {}
|
||||||
Reference in New Issue
Block a user