Added scene, raytracer, pixel display and lights

This commit is contained in:
STP
2023-11-13 00:42:23 -05:00
parent 29e22a0afa
commit 2c65a48cb2
4 changed files with 167 additions and 0 deletions

79
src/display.rs Normal file
View 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
View 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
View 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
View 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> {}