From d7e821d45f7b1113cdd5f5806f4d7c7aea67777c Mon Sep 17 00:00:00 2001 From: Fabian Lippold Date: Thu, 26 Oct 2023 05:45:22 +0200 Subject: [PATCH] TRY-27 set up for raytracing --- .gitignore | 4 +- src/main.rs | 173 ++++++++++++------------------------------ src/scene/triangle.rs | 141 ++++++++++++++++++++++++++++++++++ 3 files changed, 194 insertions(+), 124 deletions(-) create mode 100644 src/scene/triangle.rs diff --git a/.gitignore b/.gitignore index d1c5dc3..0563889 100644 --- a/.gitignore +++ b/.gitignore @@ -153,4 +153,6 @@ fabric.properties .idea/httpRequests # Android studio 3.1+ serialized cache file -.idea/caches/build_file_checksums.ser \ No newline at end of file +.idea/caches/build_file_checksums.ser + +.vscode/* diff --git a/src/main.rs b/src/main.rs index 225f26e..a0ef54e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,3 +1,5 @@ +use std::borrow::Cow; + use glium::{ glutin::{ dpi::PhysicalSize, @@ -6,21 +8,16 @@ use glium::{ window::WindowBuilder, ContextBuilder, }, - implement_vertex, uniform, Surface, + texture::{ClientFormat, MipmapsOption, RawImage2d, UncompressedFloatFormat}, + uniforms::MagnifySamplerFilter, + BlitTarget, Rect, Surface, Texture2d, }; -#[derive(Copy, Clone)] -struct Vertex { - position: [f32; 2], -} - -implement_vertex!(Vertex, position); - pub fn main() { let window_builder = WindowBuilder::new() .with_title("TrayRacer!") .with_resizable(true) - .with_min_inner_size(PhysicalSize::new(800, 600)); + .with_inner_size(PhysicalSize::new(1200, 800)); let context_builder = ContextBuilder::new(); let event_loop = EventLoop::new(); @@ -33,123 +30,53 @@ pub fn main() { } => { *c = ControlFlow::Exit; } - Event::WindowEvent { .. } => {} - Event::RedrawRequested(_) => { + Event::WindowEvent { + event: WindowEvent::Resized(PhysicalSize { width, height }), + .. + } => { + let texture = Texture2d::with_format( + &display, + RawImage2d { + data: Cow::Owned( + (0..height) + .flat_map(|y| { + (0..width).flat_map(move |x| { + [x as f32 / width as f32, y as f32 / height as f32, 0.5, 1.0] + }) + }) + .collect::>(), + ), + width, + height, + format: ClientFormat::F32F32F32F32, + }, + UncompressedFloatFormat::F32F32F32F32, + MipmapsOption::NoMipmap, + ) + .unwrap(); + let mut frame = display.draw(); - draw_gradient_background(&display, &mut frame); + texture.as_surface().blit_color( + &Rect { + left: 0, + bottom: 0, + width: texture.width(), + height: texture.height(), + }, + &mut frame, + &BlitTarget { + left: 0, + bottom: 0, + width: width as i32, + height: height as i32, + }, + MagnifySamplerFilter::Linear, + ); + frame.finish().unwrap(); } + Event::WindowEvent { .. } => {} + Event::RedrawRequested(_) => {} _ => {} }); } - -fn draw_gradient_background(display: &glium::Display, target: &mut glium::Frame) { - let vertex_buffer = glium::VertexBuffer::new( - display, - &[ - Vertex { - position: [-1.0, -1.0], - }, - Vertex { - position: [-1.0, 1.0], - }, - Vertex { - position: [1.0, -1.0], - }, - Vertex { - position: [1.0, 1.0], - }, - ], - ) - .unwrap(); - - let indices = glium::index::NoIndices(glium::index::PrimitiveType::TriangleStrip); - - let shader_program = create_shader(display); - - target - .draw( - &vertex_buffer, - &indices, - &shader_program, - &uniform! {}, - &Default::default(), - ) - .unwrap(); -} - -fn create_shader(display: &glium::Display) -> glium::Program { - let vertex_shader_source = r#" - #version 330 core - - in vec2 position; - - void main() { - gl_Position = vec4(position, 0.0, 1.0); - } - "#; - - let _shader_vertical = r#" - #version 330 core - out vec4 color; - - void main() { - float t = (gl_FragCoord.x / 600.0); - color = vec4(1.0, t, 1.0 - t, 1.0); - } - "#; - - let _shader_horizontal = r#" - #version 330 core - out vec4 color; - - void main() { - float t = (gl_FragCoord.y / 600.0); - color = vec4(1.0, t, 1.0 - t, 1.0); - } - "#; - - let _shader_rainbow = r#" - #version 330 core - out vec4 color; - - void main() { - float t = gl_FragCoord.x / 800.0; // Adjust the divisor for the gradient width - vec3 rainbowColor; - - if (t < 0.14) { - rainbowColor = vec3(1.0, 0.0, 0.0); // Red - } else if (t < 0.28) { - rainbowColor = mix(vec3(1.0, 0.0, 0.0), vec3(1.0, 0.5, 0.0), smoothstep(0.14, 0.28, t)); - } else if (t < 0.43) { - rainbowColor = mix(vec3(1.0, 0.5, 0.0), vec3(1.0, 1.0, 0.0), smoothstep(0.28, 0.43, t)); - } else if (t < 0.57) { - rainbowColor = mix(vec3(1.0, 1.0, 0.0), vec3(0.0, 1.0, 0.0), smoothstep(0.43, 0.57, t)); - } else if (t < 0.71) { - rainbowColor = mix(vec3(0.0, 1.0, 0.0), vec3(0.0, 0.0, 1.0), smoothstep(0.57, 0.71, t)); - } else if (t < 0.85) { - rainbowColor = mix(vec3(0.0, 0.0, 1.0), vec3(0.29, 0.0, 0.51), smoothstep(0.71, 0.85, t)); - } else { - rainbowColor = mix(vec3(0.29, 0.0, 0.51), vec3(0.5, 0.0, 0.5), smoothstep(0.85, 1.0, t)); - } - - color = vec4(rainbowColor, 1.0); - } - "#; - - let shader_radial = r#" - #version 330 core - out vec4 color; - - void main() { - // Calculate the distance from the center of the screen - vec2 center = vec2(400.0, 300.0); // Center of the screen (adjust as needed) - float distance = length(gl_FragCoord.xy - center) / 400.0; // Adjust divisor for gradient size - - // The gradient will be from the center (0.0) to the edge (1.0) - color = vec4(0.0, distance, 1.0 - distance, 1.0); - } - "#; - - glium::Program::from_source(display, vertex_shader_source, shader_radial, None).unwrap() -} diff --git a/src/scene/triangle.rs b/src/scene/triangle.rs new file mode 100644 index 0000000..589f8af --- /dev/null +++ b/src/scene/triangle.rs @@ -0,0 +1,141 @@ +use bvh::aabb::AABB; +use nalgebra::{Matrix4, Point3, Vector3}; + +#[derive(Debug, Clone, Copy)] +pub struct Triangle { + pub a: Point3, + pub b: Point3, + pub c: Point3, + pub a_normal: Vector3, + pub b_normal: Vector3, + pub c_normal: Vector3, + pub material_index: usize, + bh_node_index: usize, +} + +impl Triangle { + pub fn new( + a: Point3, + b: Point3, + c: Point3, + a_normal: Vector3, + b_normal: Vector3, + c_normal: Vector3, + material_index: usize, + ) -> Self { + Self { + a, + b, + c, + a_normal, + b_normal, + c_normal, + material_index, + bh_node_index: 0, + } + } + + pub fn transform(&mut self, matrix: &Matrix4) -> &mut Triangle { + self.a = matrix.transform_point(&self.a); + self.b = matrix.transform_point(&self.b); + self.c = matrix.transform_point(&self.c); + + self.a_normal = matrix.transform_vector(&self.a_normal); + self.b_normal = matrix.transform_vector(&self.b_normal); + self.c_normal = matrix.transform_vector(&self.c_normal); + + self + } + + pub fn intersect( + &self, + ray_dir: &Vector3, + ray_origin: &Point3, + ) -> Option> { + let edge1 = self.b - self.a; + let edge2 = self.c - self.a; + + let h = ray_dir.cross(&edge2); + let a = edge1.dot(&h); + + if a.abs() < f32::EPSILON { + return None; + } + + let f = 1.0 / a; + + let s = ray_origin - self.a; + let u = f * s.dot(&h); + + if u < 0.0 || u > 1.0 { + return None; + } + + let q = s.cross(&edge1); + let v = f * ray_dir.dot(&q); + + if v < 0.0 || u + v > 1.0 { + return None; + } + + let t = f * edge2.dot(&q); + + if t > f32::EPSILON { + Some(ray_origin + ray_dir * t) + } else { + None + } + } + + pub fn barycentric(&self, point: Point3) -> (f32, f32, f32) { + let v0 = self.b - self.a; + let v1 = self.c - self.a; + let v2 = point - self.a; + + let d00 = v0.dot(&v0); + let d01 = v0.dot(&v1); + let d11 = v1.dot(&v1); + let d20 = v2.dot(&v0); + let d21 = v2.dot(&v1); + + let denom = d00 * d11 - d01 * d01; + + let v = (d11 * d20 - d01 * d21) / denom; + let w = (d00 * d21 - d01 * d20) / denom; + let u = 1.0 - v - w; + + (u, v, w) + } +} + +impl bvh::aabb::Bounded for Triangle { + fn aabb(&self) -> bvh::aabb::AABB { + AABB::default() + .grow(&bvh::Point3::new(self.a.x, self.a.y, self.a.z)) + .grow(&bvh::Point3::new(self.b.x, self.b.y, self.b.z)) + .grow(&bvh::Point3::new(self.c.x, self.c.y, self.c.z)) + } +} + +impl bvh::bounding_hierarchy::BHShape for Triangle { + fn set_bh_node_index(&mut self, index: usize) { + self.bh_node_index = index; + } + + fn bh_node_index(&self) -> usize { + self.bh_node_index + } +} + +impl PartialEq for Triangle { + fn eq(&self, other: &Self) -> bool { + self.a == other.a + && self.b == other.b + && self.c == other.c + && self.a_normal == other.a_normal + && self.b_normal == other.b_normal + && self.c_normal == other.c_normal + && self.material_index == other.material_index + && self.bh_node_index == other.bh_node_index + } +}