From 972aee716a0a0dce520f799da1ad382583ebee7a Mon Sep 17 00:00:00 2001 From: numzero Date: Mon, 19 Oct 2026 02:28:00 +0300 Subject: [PATCH] separate uniforms from the pipeline --- src/lib.rs | 47 ++++++++++++++++++++++++++++++++--------- src/render/mesh.rs | 52 +++++++++++++++++++++++++--------------------- 2 files changed, 65 insertions(+), 34 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 2312f8f..9eee8b2 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -2,6 +2,8 @@ use std::error::Error; use glam::{Mat4, UVec2, Vec3, Vec4, vec3, vec4}; +use crate::render::mesh::GpuParams; + mod bevel_gear; mod camera; mod crown_gear; @@ -56,10 +58,15 @@ pub struct Core { device: wgpu::Device, queue: wgpu::Queue, surface: wgpu::Surface<'static>, + depth: wgpu::Texture, mesh_pipeline: render::mesh::Pipeline, - mesh_gray: render::mesh::GpuMeshIndexed, - depth: wgpu::Texture, + + mesh_gear: render::mesh::GpuMeshIndexed, + mesh_cutter: render::mesh::GpuMeshIndexed, + + params_gear: render::mesh::GpuParams, + params_cutter: render::mesh::GpuParams, } fn srgb_to_linear(color: Vec3) -> Vec3 { @@ -131,7 +138,11 @@ impl Core { .to_standard_mesh() .into_indexed(); - let mesh_gray = render::mesh::GpuMeshIndexed::new(&device, &bevel_gear_mesh); + let mesh_cutter = render::mesh::GpuMeshIndexed::new(&device, &crown_gear_mesh); + let mesh_gear = render::mesh::GpuMeshIndexed::new(&device, &bevel_gear_mesh); + + let params_gear = GpuParams::new(&device, &mesh_pipeline); + let params_cutter = GpuParams::new(&device, &mesh_pipeline); Self::configure_surface(&surface, &device, pixel_size); @@ -139,9 +150,12 @@ impl Core { device, queue, surface, - mesh_pipeline, - mesh_gray, depth, + mesh_pipeline, + mesh_gear, + mesh_cutter, + params_gear, + params_cutter, } } @@ -162,16 +176,26 @@ impl Core { .clamp_z_min(0.01 * args.cam_view_y) .to_mat4(); let view = Mat4::from_mat3(camera::rotation(-args.cam_yaw, -args.cam_pitch)); - self.mesh_pipeline.set_params( + let light = vec3(0.7, 0.5, 1.0).normalize(); + + self.params_gear.set( &self.queue, render::mesh::Params { mvp: proj * view, - light: vec3(0.7, 0.5, 1.0).normalize(), + light, _zero: 0., - color: vec4(0.5, 0.5, 0.5, 1.0), + color: srgba_to_linear(vec4(0.2, 0.8, 0.1, 1.0)), + }, + ); + self.params_cutter.set( + &self.queue, + render::mesh::Params { + mvp: proj * view, + light, + _zero: 0., + color: srgba_to_linear(vec4(0.8, 0.2, 0.1, 1.0)), }, ); - self.queue.submit([]); // flush buffer updates let view = output.create_view(&wgpu::TextureViewDescriptor::default()); let depth_view = self @@ -200,7 +224,10 @@ impl Core { }), ..Default::default() }); - self.mesh_gray.render(&self.mesh_pipeline, &mut pass); + self.mesh_cutter + .render(&mut pass, &self.mesh_pipeline, &self.params_cutter); + self.mesh_gear + .render(&mut pass, &self.mesh_pipeline, &self.params_gear); drop(pass); self.queue.submit(std::iter::once(encoder.finish())); } diff --git a/src/render/mesh.rs b/src/render/mesh.rs index 28446a8..9620fc9 100644 --- a/src/render/mesh.rs +++ b/src/render/mesh.rs @@ -26,6 +26,10 @@ pub struct Params { pub color: Vec4, } +pub struct Pipeline { + pipeline: wgpu::RenderPipeline, +} + pub struct GpuMesh { vertices: wgpu::Buffer, vertex_count: u32, @@ -37,6 +41,11 @@ pub struct GpuMeshIndexed { index_count: u32, } +pub struct GpuParams { + params: wgpu::Buffer, + bindings: wgpu::BindGroup, +} + impl GpuMesh { pub fn new(device: &wgpu::Device, data: &CpuMesh) -> Self { let vertices = cast_slice::<_, Vertex>(&data.faces); @@ -84,21 +93,8 @@ impl GpuMeshIndexed { } } -pub struct Pipeline { - params: wgpu::Buffer, - bindings: wgpu::BindGroup, - pipeline: wgpu::RenderPipeline, -} - impl Pipeline { pub fn new(device: &wgpu::Device) -> Self { - let params = device.create_buffer(&wgpu::BufferDescriptor { - label: None, - size: size_of::() as u64, - usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST, - mapped_at_creation: false, - }); - let shader = device.create_shader_module(wgpu::ShaderModuleDescriptor { label: None, source: wgpu::ShaderSource::Wgsl(SHADER.into()), @@ -157,39 +153,47 @@ impl Pipeline { multiview: None, cache: None, }); + Self { pipeline } + } +} + +impl GpuParams { + pub fn new(device: &wgpu::Device, pipeline: &Pipeline) -> Self { + let params = device.create_buffer(&wgpu::BufferDescriptor { + label: None, + size: size_of::() as u64, + usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST, + mapped_at_creation: false, + }); let bindings = device.create_bind_group(&wgpu::BindGroupDescriptor { label: None, - layout: &pipeline.get_bind_group_layout(0), + layout: &pipeline.pipeline.get_bind_group_layout(0), entries: &[wgpu::BindGroupEntry { binding: 0, resource: params.as_entire_binding(), }], }); - Self { - params, - bindings, - pipeline, - } + Self { params, bindings } } - pub fn set_params(&self, queue: &wgpu::Queue, params: Params) { + pub fn set(&self, queue: &wgpu::Queue, params: Params) { queue.write_buffer(&self.params, 0, bytes_of(¶ms)); } } impl GpuMesh { - pub fn render(&self, pipeline: &Pipeline, pass: &mut wgpu::RenderPass) { + pub fn render(&self, pass: &mut wgpu::RenderPass, pipeline: &Pipeline, params: &GpuParams) { pass.set_pipeline(&pipeline.pipeline); - pass.set_bind_group(0, &pipeline.bindings, &[]); + pass.set_bind_group(0, ¶ms.bindings, &[]); pass.set_vertex_buffer(0, self.vertices.slice(..)); pass.draw(0..self.vertex_count, 0..1); } } impl GpuMeshIndexed { - pub fn render(&self, pipeline: &Pipeline, pass: &mut wgpu::RenderPass) { + pub fn render(&self, pass: &mut wgpu::RenderPass, pipeline: &Pipeline, params: &GpuParams) { pass.set_pipeline(&pipeline.pipeline); - pass.set_bind_group(0, &pipeline.bindings, &[]); + pass.set_bind_group(0, ¶ms.bindings, &[]); pass.set_vertex_buffer(0, self.vertices.slice(..)); pass.set_index_buffer(self.indices.slice(..), wgpu::IndexFormat::Uint16); pass.draw_indexed(0..self.index_count, 0, 0..1);