183 lines
4.4 KiB
Rust
183 lines
4.4 KiB
Rust
use galactica_constants::{IMAGE_LIMIT, SPRITE_LIMIT};
|
|
use wgpu;
|
|
|
|
use super::{AtlasContent, DataContent, SpriteContent};
|
|
|
|
pub struct GlobalUniform {
|
|
pub data_buffer: wgpu::Buffer,
|
|
pub atlas_buffer: wgpu::Buffer,
|
|
pub sprite_buffer: wgpu::Buffer,
|
|
pub bind_group: wgpu::BindGroup,
|
|
pub bind_group_layout: wgpu::BindGroupLayout,
|
|
pub content: DataContent,
|
|
}
|
|
|
|
impl GlobalUniform {
|
|
pub fn shader_header(&self, group: u32) -> String {
|
|
let mut out = String::new();
|
|
|
|
out.push_str(&format!("@group({group}) @binding(0)\n"));
|
|
out.push_str(
|
|
r#"
|
|
var<uniform> global: GlobalUniform;
|
|
struct GlobalUniform {
|
|
camera_position: vec2<f32>,
|
|
camera_zoom: vec2<f32>,
|
|
camera_zoom_limits: vec2<f32>,
|
|
window_size: vec2<f32>,
|
|
window_aspect: vec2<f32>,
|
|
starfield_sprite: vec2<u32>,
|
|
starfield_tile_size: vec2<f32>,
|
|
starfield_size_limits: vec2<f32>,
|
|
current_time: vec2<f32>,
|
|
};
|
|
"#,
|
|
);
|
|
out.push_str("\n");
|
|
|
|
out.push_str(&format!("@group({group}) @binding(1)\n"));
|
|
out.push_str(
|
|
r#"
|
|
var<uniform> atlas: AtlasUniform;
|
|
struct ImageLocation {
|
|
xpos: f32,
|
|
ypos: f32,
|
|
width: f32,
|
|
height: f32,
|
|
};
|
|
"#,
|
|
);
|
|
out.push_str(&format!(
|
|
r#"
|
|
struct AtlasUniform {{
|
|
data: array<ImageLocation, {}>,
|
|
}};
|
|
"#,
|
|
IMAGE_LIMIT,
|
|
));
|
|
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
|
|
|
|
out.push_str(&format!("@group({group}) @binding(2)\n"));
|
|
out.push_str(
|
|
r#"
|
|
var<uniform> sprites: SpriteUniform;
|
|
struct SpriteData {
|
|
frame_count: u32,
|
|
repeatmode: u32,
|
|
aspect: f32,
|
|
fps: f32,
|
|
first_frame: u32,
|
|
|
|
padding_a: f32,
|
|
padding_b: f32,
|
|
padding_c: f32,
|
|
};
|
|
"#,
|
|
);
|
|
out.push_str(&format!(
|
|
r#"
|
|
struct SpriteUniform {{
|
|
data: array<SpriteData, {}>,
|
|
}};
|
|
"#,
|
|
SPRITE_LIMIT,
|
|
));
|
|
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: DataContent::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: AtlasContent::SIZE,
|
|
usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST,
|
|
mapped_at_creation: false,
|
|
});
|
|
|
|
let sprite_buffer = device.create_buffer(&wgpu::BufferDescriptor {
|
|
label: Some("global uniform sprite buffer"),
|
|
size: SpriteContent::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: sprite_buffer.as_entire_binding(),
|
|
},
|
|
],
|
|
label: Some("global uniform bind group"),
|
|
});
|
|
|
|
return Self {
|
|
data_buffer,
|
|
atlas_buffer,
|
|
sprite_buffer,
|
|
bind_group,
|
|
bind_group_layout,
|
|
content: DataContent::default(),
|
|
};
|
|
}
|
|
}
|