use galactica_util::constants::{IMAGE_LIMIT, OBJECT_SPRITE_INSTANCE_LIMIT}; use wgpu; use super::{object::ObjectLocationArray, AtlasArray, GlobalDataContent}; pub struct GlobalUniform { pub data_buffer: wgpu::Buffer, pub atlas_buffer: wgpu::Buffer, pub object_buffer: wgpu::Buffer, pub bind_group: wgpu::BindGroup, pub bind_group_layout: wgpu::BindGroupLayout, pub content: GlobalDataContent, } impl GlobalUniform { pub fn shader_header(&self, group: u32) -> String { let mut out = String::new(); // Global game data out.push_str(&format!("@group({group}) @binding(0)\n")); out.push_str( r#" var global_data: GlobalData; struct GlobalData { camera_position_x: f32, camera_position_y: f32, camera_zoom: f32, camera_zoom_min: f32, camera_zoom_max: f32, window_size_w: f32, window_size_h: f32, window_scale: f32, window_aspect: f32, starfield_sprite: u32, starfield_tile_size: f32, starfield_size_min: f32, starfield_size_max: f32, }; "#, ); out.push_str("\n"); // Atlas image locations out.push_str(&format!( r#" @group({group}) @binding(1) var global_atlas: array; "# )); out.push_str("\n"); out.push_str( r#" struct AtlasImageLocation { xpos: f32, ypos: f32, width: f32, height: f32, atlas_texture: u32, padding_a: f32, padding_b: f32, padding_c: f32, }; "#, ); out.push_str("\n"); // TODO: document // wgpu uniforms require constant item sizes. // if you get an error like the following,check! // `Buffer is bound with size 3456 where the shader expects 5184 in group[1] compact index 2` // More notes are in datacontent // Object location data out.push_str(&format!( r#" @group({group}) @binding(2) var objects: array; "# )); out.push_str("\n"); out.push_str( r#" struct ObjectData { xpos: f32, ypos: f32, zpos: f32, angle: f32, size: f32, parent: u32, is_child: u32, padding_a: f32, }; "#, ); out.push_str("\n"); return out; } pub fn new(device: &wgpu::Device) -> Self { let data_buffer = device.create_buffer(&wgpu::BufferDescriptor { label: Some("global uniform data buffer"), size: GlobalDataContent::SIZE, usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST, mapped_at_creation: false, }); let atlas_buffer = device.create_buffer(&wgpu::BufferDescriptor { label: Some("global uniform atlas buffer"), size: AtlasArray::SIZE, usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST, mapped_at_creation: false, }); let object_buffer = device.create_buffer(&wgpu::BufferDescriptor { label: Some("global uniform object buffer"), size: ObjectLocationArray::SIZE, usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST, mapped_at_creation: false, }); let bind_group_layout = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { entries: &[ wgpu::BindGroupLayoutEntry { binding: 0, visibility: wgpu::ShaderStages::VERTEX_FRAGMENT, ty: wgpu::BindingType::Buffer { ty: wgpu::BufferBindingType::Uniform, has_dynamic_offset: false, min_binding_size: None, }, count: None, }, wgpu::BindGroupLayoutEntry { binding: 1, visibility: wgpu::ShaderStages::VERTEX_FRAGMENT, ty: wgpu::BindingType::Buffer { ty: wgpu::BufferBindingType::Uniform, has_dynamic_offset: false, min_binding_size: None, }, count: None, }, wgpu::BindGroupLayoutEntry { binding: 2, visibility: wgpu::ShaderStages::VERTEX_FRAGMENT, ty: wgpu::BindingType::Buffer { ty: wgpu::BufferBindingType::Uniform, has_dynamic_offset: false, min_binding_size: None, }, count: None, }, ], label: Some("global uniform bind group layout"), }); let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor { layout: &bind_group_layout, entries: &[ wgpu::BindGroupEntry { binding: 0, resource: data_buffer.as_entire_binding(), }, wgpu::BindGroupEntry { binding: 1, resource: atlas_buffer.as_entire_binding(), }, wgpu::BindGroupEntry { binding: 2, resource: object_buffer.as_entire_binding(), }, ], label: Some("global uniform bind group"), }); return Self { data_buffer, atlas_buffer, object_buffer, bind_group, bind_group_layout, content: GlobalDataContent::default(), }; } }