Galactica/crates/render/src/globaluniform/globaluniform.rs

234 lines
5.6 KiB
Rust
Raw Normal View History

use galactica_constants::{IMAGE_LIMIT, OBJECT_SPRITE_INSTANCE_LIMIT, SPRITE_LIMIT};
use wgpu;
use super::{object::ObjectLocationArray, AtlasArray, DataContent, SpriteDataArray};
pub struct GlobalUniform {
pub data_buffer: wgpu::Buffer,
pub atlas_buffer: wgpu::Buffer,
2024-01-04 18:15:30 -08:00
pub sprite_buffer: wgpu::Buffer,
pub object_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();
// Global game data
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>,
2024-01-04 18:15:30 -08:00
starfield_sprite: vec2<u32>,
starfield_tile_size: vec2<f32>,
starfield_size_limits: vec2<f32>,
current_time: vec2<f32>,
};
2024-01-04 19:01:22 -08:00
"#,
);
out.push_str("\n");
// Atlas image locations
out.push_str(&format!(
r#"
@group({group}) @binding(1)
var<uniform> atlas: array<ImageLocation, {IMAGE_LIMIT}>;
"#
));
out.push_str("\n");
out.push_str(
r#"
2024-01-04 18:15:30 -08:00
struct ImageLocation {
xpos: f32,
ypos: f32,
width: f32,
height: f32,
2024-01-04 22:17:34 -08:00
atlas_texture: u32,
padding_a: f32,
padding_b: f32,
padding_c: f32,
};
2024-01-04 19:01:22 -08:00
"#,
2024-01-04 18:15:30 -08:00
);
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
// Sprite data
out.push_str(&format!(
r#"
@group({group}) @binding(2)
var<uniform> sprites: array<SpriteData, {SPRITE_LIMIT}>;
"#
));
out.push_str("\n");
2024-01-04 18:15:30 -08:00
out.push_str(
r#"
struct SpriteData {
frame_count: u32,
repeatmode: u32,
aspect: f32,
fps: f32,
first_frame: u32,
padding_a: f32,
padding_b: f32,
padding_c: f32,
};
2024-01-04 19:01:22 -08:00
"#,
);
out.push_str("\n");
// Object location data
2024-01-04 19:01:22 -08:00
out.push_str(&format!(
r#"
@group({group}) @binding(3)
var<uniform> objects: array<ObjectLocation, {OBJECT_SPRITE_INSTANCE_LIMIT}>;
"#
2024-01-04 19:01:22 -08:00
));
out.push_str("\n");
out.push_str(
r#"
struct ObjectLocation {
xpos: f32,
ypos: f32,
zpos: f32,
angle: f32,
size: f32,
padding_a: f32,
padding_b: f32,
padding_c: 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: 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: AtlasArray::SIZE,
usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST,
mapped_at_creation: false,
});
2024-01-04 18:15:30 -08:00
let sprite_buffer = device.create_buffer(&wgpu::BufferDescriptor {
label: Some("global uniform sprite buffer"),
size: SpriteDataArray::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,
2024-01-04 18:15:30 -08:00
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,
},
2024-01-04 18:15:30 -08:00
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,
},
wgpu::BindGroupLayoutEntry {
binding: 3,
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(),
},
2024-01-04 18:15:30 -08:00
wgpu::BindGroupEntry {
binding: 2,
resource: sprite_buffer.as_entire_binding(),
},
wgpu::BindGroupEntry {
binding: 3,
resource: object_buffer.as_entire_binding(),
},
],
label: Some("global uniform bind group"),
});
return Self {
data_buffer,
atlas_buffer,
2024-01-04 18:15:30 -08:00
sprite_buffer,
object_buffer,
bind_group,
bind_group_layout,
content: DataContent::default(),
};
}
}