diff --git a/src/main.rs b/src/main.rs index 6eb66a9..acd1690 100644 --- a/src/main.rs +++ b/src/main.rs @@ -89,15 +89,11 @@ impl App { } pub fn render(&self) -> Option { - let gpu = match self.gpu.get_state() { - Some(t) => t, - None => return None - }; let player = self.player.read().unwrap(); - // upload uniforms - let mut uniforms = player.get_camera().to_gpu(); + // downcast objects + let mut uniform = player.get_camera().to_gpu(); let gpu_spheres: Vec = self.objects.iter() .filter_map(|o| o.as_any().downcast_ref::()) @@ -109,67 +105,7 @@ impl App { .map(|s| s.to_gpu()) .collect(); - uniforms.sphere_count = gpu_spheres.len() as u32; - uniforms.quad_count = gpu_quads.len() as u32; - - gpu.queue.write_buffer(gpu.uniform_buf, 0, bytemuck::bytes_of(&uniforms)); - gpu.queue.write_buffer(gpu.spheres_buf, 0, bytemuck::cast_slice(&gpu_spheres)); - gpu.queue.write_buffer(gpu.quads_buf, 0, bytemuck::cast_slice(&gpu_quads)); - - let frame = match gpu.surface.get_current_texture() { - Ok(f) => f, - Err(_) => { - gpu.surface.configure(gpu.device, gpu.surface_config); - return None; - } - }; - - let view = frame.texture.create_view(&wgpu::TextureViewDescriptor::default()); - - let mut encoder = gpu.device.create_command_encoder(&wgpu::CommandEncoderDescriptor { - label: Some("frame") - }); - - // step 1 — compute pass, ray traces into output[] - { - let mut pass = encoder.begin_compute_pass(&wgpu::ComputePassDescriptor { - label: Some("raytrace"), - timestamp_writes: None - }); - pass.set_pipeline(gpu.compute_pipeline); - pass.set_bind_group(0, gpu.bind_group, &[]); - pass.dispatch_workgroups( - (gpu.surface_config.width + 7) / 8, - (gpu.surface_config.height + 7) / 8, - 1 - ); - } - - // step 2 — render pass, copies output[] to screen - { - let mut pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor { - label: Some("blit"), - color_attachments: &[Some(wgpu::RenderPassColorAttachment { - view: &view, - resolve_target: None, - ops: wgpu::Operations { - load: wgpu::LoadOp::Clear(wgpu::Color::BLACK), - store: wgpu::StoreOp::Store, - }, - })], - depth_stencil_attachment: None, - timestamp_writes: None, - occlusion_query_set: None, - }); - pass.set_pipeline(gpu.render_pipeline); - pass.set_bind_group(0, gpu.bind_group, &[]); - pass.draw(0..3, 0..1); - } - - // submit the frame and return it for the caller to present it - gpu.queue.submit(std::iter::once(encoder.finish())); - - return Some(frame) + return self.gpu.draw_frame(&gpu_spheres, &gpu_quads, &mut uniform); } } diff --git a/src/wgpu_handler.rs b/src/wgpu_handler.rs index d55f5f5..d0b3bde 100644 --- a/src/wgpu_handler.rs +++ b/src/wgpu_handler.rs @@ -1,10 +1,10 @@ use std::sync::Arc; use image::ImageReader; -use wgpu::{Texture, TextureView}; +use wgpu::{SurfaceTexture, Texture, TextureView}; use winit::window::{Window}; -use crate::object; +use crate::object::{self, camera::GpuUniform, quad::GpuQuad, sphere::GpuSphere}; pub struct GpuHandler { pub device: Option, @@ -135,6 +135,79 @@ impl GpuHandler { } } + pub fn draw_frame(&self, spheres: &Vec, quads: &Vec, uniform: &mut GpuUniform) -> Option { + let gpu = match self.get_state() { + Some(t) => t, + None => return None + }; + + // ensure these are correct + uniform.sphere_count = spheres.len() as u32; + uniform.quad_count = quads.len() as u32; + + // upload to buffer + gpu.queue.write_buffer(gpu.uniform_buf, 0, bytemuck::bytes_of(uniform)); + gpu.queue.write_buffer(gpu.spheres_buf, 0, bytemuck::cast_slice(spheres)); + gpu.queue.write_buffer(gpu.quads_buf, 0, bytemuck::cast_slice(quads)); + + // surface that we draw to + let frame = match gpu.surface.get_current_texture() { + Ok(f) => f, + Err(_) => { + gpu.surface.configure(gpu.device, gpu.surface_config); + return None; + } + }; + + let view = frame.texture.create_view(&wgpu::TextureViewDescriptor::default()); + + let mut encoder = gpu.device.create_command_encoder(&wgpu::CommandEncoderDescriptor { + label: Some("frame") + }); + + // step 1 — compute pass, ray traces into output[] + { + let mut pass = encoder.begin_compute_pass(&wgpu::ComputePassDescriptor { + label: Some("raytrace"), + timestamp_writes: None + }); + pass.set_pipeline(gpu.compute_pipeline); + pass.set_bind_group(0, gpu.bind_group, &[]); + pass.dispatch_workgroups( + (gpu.surface_config.width + 7) / 8, + (gpu.surface_config.height + 7) / 8, + 1 + ); + } + + // step 2 — render pass, copies output[] to screen + { + let mut pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor { + label: Some("blit"), + color_attachments: &[Some(wgpu::RenderPassColorAttachment { + view: &view, + resolve_target: None, + ops: wgpu::Operations { + load: wgpu::LoadOp::Clear(wgpu::Color::BLACK), + store: wgpu::StoreOp::Store, + }, + })], + depth_stencil_attachment: None, + timestamp_writes: None, + occlusion_query_set: None, + }); + pass.set_pipeline(gpu.render_pipeline); + pass.set_bind_group(0, gpu.bind_group, &[]); + pass.draw(0..3, 0..1); + } + + // submit the frame and return it for the caller to present it + gpu.queue.submit(std::iter::once(encoder.finish())); + + return Some(frame) + + } + // vibecoded but man thats a lot pub async fn init(&mut self, window: Arc, width: u32, height: u32, texture_paths: Vec<&str>) { // --- get a handle to the graphics card --- @@ -408,8 +481,8 @@ impl Default for GpuHandler { spheres_buf: None, quads_buf: None, output_buf_size: None, - texture: None, - view: None + texture: None, + view: None } } } diff --git a/textures/dirt.png b/textures/dirt.png index adda077..564599d 100644 Binary files a/textures/dirt.png and b/textures/dirt.png differ diff --git a/textures/grass_side.png b/textures/grass_side.png index ffe278d..293756b 100644 Binary files a/textures/grass_side.png and b/textures/grass_side.png differ diff --git a/textures/grass_top.png b/textures/grass_top.png index dc89667..ece957c 100644 Binary files a/textures/grass_top.png and b/textures/grass_top.png differ diff --git a/textures/shading.png b/textures/shading.png new file mode 100644 index 0000000..ee2908c Binary files /dev/null and b/textures/shading.png differ