From 08bc43d28087f9a51480ea26df6b5b43a4f98e10 Mon Sep 17 00:00:00 2001 From: prushton2 Date: Tue, 7 Apr 2026 10:49:05 -0400 Subject: [PATCH] More abstraction, new textures --- src/main.rs | 70 ++-------------------------------- src/wgpu_handler.rs | 81 ++++++++++++++++++++++++++++++++++++++-- textures/dirt.png | Bin 750 -> 307 bytes textures/grass_side.png | Bin 793 -> 406 bytes textures/grass_top.png | Bin 506 -> 305 bytes textures/shading.png | Bin 0 -> 286 bytes 6 files changed, 80 insertions(+), 71 deletions(-) create mode 100644 textures/shading.png 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 adda077bd136193522c5613648143efc06c753cc..564599db0222b22b487eba4a5f47d34c6c7f9fb4 100644 GIT binary patch delta 281 zcmV+!0p|Yh1+xN>BYyz;NklbTr*&6?e|vwrw8IA^z#k!?z*;8UV^5G^+_f z&T>8NM_$yp#Ku{urfb)gRRB0Wrc|zW(LaVTXvV;)X4-mp34Z{U`{g+H!@JJG%&axD ztN?5wHZW=PNkQ`m?z-8Q&X9oX(8y+rjer;cu-Mi$QUr)gaVC7HuA1lp@em=&X(LB< zVPe+p>(WFwlv;+&w&2A%%1F$SuR+2%-$c%Wj9m2KUo-wJWh1sgEVEY6fSc^=o&n@2 fyYtx}g7*b zz3q7BGqDk}Mtyv~>#{h+yr@a!KYC;|4Cy4HkE-q1Eg&09{ZSt8b4+Q1@v%d65;HsLPRF{D8R4l68G~F)SH7H zXN;mfJ#AFTqkv!@MeRV-hEXmFEYf*w6#E{(AvUz}?a{WYsR2zH=!L#!FNX<1W<|qs6#iBgx6*L1 zt+Db=(=ms;nT+sk+gZ|2n5?RC$PzQ8O;nbIiESf-1_Y;`Sk@iwlx%u{%{uk&aF;F+pzg8C?hAJ4El@Ey zDV-^J&ImLeht#9R6~~danFhQ|fYTR`oCp-s32KOY6sKe&6+uhJSTR(iKy>ISqQ||1 z&#a6n=yWB7`uu9&{hrs@n6Mi)82Nx^4g_Gr$WZ>A)kC4oFJlOJL@Q(3n-W;PKiqR2 zzvQHEIiLJ6t4!q9TEwI^m@h3y@Nq%<7uPLArI4{p!@F5z@DHUiSSkjsX5jz;002ov JPDHLkV1nMnP_F<0 diff --git a/textures/grass_side.png b/textures/grass_side.png index ffe278d09ad7fadf49b1007947c08688a0e04256..293756b3d41de72724f7af2aded4f9cb47c95b7e 100644 GIT binary patch delta 380 zcmV-?0fYXT29^VmBYy#1NklF-P_sucHWzFSHqi7 zcCq|Ez#_*-TitUlWYI#*nXYKOY2k% z5SLFA8FkKuAln7bKDvQ+b=@0_YgR8*Lg^%{#Q*`wcz?)Ay}uHyXWgj;nY~oRVzb=? zQ2aSx>tWiSaNJ>@AlJLCgp2i0jA}tiAaVeCz+7MqK!MLxNHFO|_s}Xk+crMbVDXigldK`PsXQq8(;ymVX~u*(wx(x?Idf*@m;J zVdB#!mgi65wA%$kDls0muv)a>nb8q}v!!(b=03LY=Dv3XGQF^k?+*v@=t~oCXS(~P zHGzYwgv$MP%f!kt3o1{%yLVX%GMk$E2bP|Cc(&ApV;D%J#PV$ucRq*s@HmGji#}F% zni#DV@oT%@m4C4KU_z=*6$8Z_Ku5M3J_d_<=o(;XI#&0ZsHn3nB)03F?CDH753z9f zlJqIxfI!~TQF2ZE-fA3~r5-L0m3d9z=f)n!DrK0az>mLs-3ne!k4v59ms|_~nnV^d zWAz*p1xv%913ybV?d7mu>pl;$x{Z1p=lWcT*~#UI&nhXB0Kb%G+FJ(POF1P5M#d`Wk#FI z7{;LIAV;Ic+_hmDL`tEAqwBCuJu|96ko|TDgH_c#F)F<_*c61ZI@6)<40$wh_Uf>V zS-wjHJAa{s=dyhq96wA{Ll7k?@&vUAu93VIBp@a<{?7Ij;KlTaj1q}fC(RB@E;W)R zVrTkX9fy>nG%NN}UeCaF_H2Mt8StKXJ~hHF5FkiVCi@{7(irH-lm;4T^W7uRV2@2d zA~YyR#fe^vxdeE5eN-xgY<7YkvRw}Rh}96(k9$}y=QM9AA5u=I#x{&K z9GBa*0LKetqX&6@l)BI}fC6V>eLu)9D*Z}^0(aQT9NXJVU@<>6Ce_TBSbj`>?J!2! zwovVJQ0s)KwPH#zvCHyzn-L7Mdt?cj>p2Gg0|Ns@GT{b3>i_@%07*qoM6N<$f}u@n Ao&W#< diff --git a/textures/grass_top.png b/textures/grass_top.png index dc896677013170dc8e234622f904367bb39d83e4..ece957c1769b647a6902399144973133c2160a50 100644 GIT binary patch delta 279 zcmV+y0qFkv1F-^-BYyz+NklG(&;U>bp;=7; za^~H5F1)C5j*YWW&3zggs|w)sn9{h~MgJJWppJo4jkNXd5`O^7`^%|phMzf@8MQ{1 z4S+4EK-zqg?tr^)wxzR5z;)zCGsQ+g3;lrIVVrLwWFPfgO>0>pbv|mwPpV8HDBj3Ez zekpH>--hz`7=V-0VWmH?ze#gRx*jPQ?c4!)8tXqUkZpV9-G4sMomBmcjvxilJ+R^6 z{kbvZLgQWqkcjI8VDaRv0yE$Q2K=qGB@X7jB(;iY8_Zw<2C*^_4VeBi)}F(Xvf{M8 zqeiNScmMw2zKgyp13A}Cpve%7X&!83e^aO{+Q(g)N|Nd@6Q6 zO`_v8tbi~$w12Q4RaXxVx=adM1GsLWEY`(f3td9hfLqY9lp>U^gC-Ev^Bnz@I(M7D z#mN*-4ASa*l5jH7XU9l7M)iUiNs!xSf)A3gA|Hw|P4fc_%8QfLP!RxLXKsvO`C+CJ z5!GoDxI{vdiyyj{7bkMEp^JfVBE32Xch=Yk08(=a09wy-hsS3pzRX=ZPvRF?tywl08TUjP*yT+?X_)Z{%*kRE7zN;1@abvTuwlD(F^wu#E)&$aK9>`I17b?~8+H8WtNoGQr`g+Da_B;F>5@?L8%4k+*uDDmyXl#Naq&+3;vR_ODegFUf07*qoM6N<$f-JUwD*ylh literal 0 HcmV?d00001