2024-01-20 10:04:09 -08:00
|
|
|
use galactica_util::constants::{IMAGE_LIMIT, OBJECT_SPRITE_INSTANCE_LIMIT};
|
2024-01-04 17:18:31 -08:00
|
|
|
use wgpu;
|
|
|
|
|
2024-01-20 10:04:09 -08:00
|
|
|
use super::{object::ObjectLocationArray, AtlasArray, GlobalDataContent};
|
2024-01-04 17:18:31 -08:00
|
|
|
|
|
|
|
pub struct GlobalUniform {
|
|
|
|
pub data_buffer: wgpu::Buffer,
|
|
|
|
pub atlas_buffer: wgpu::Buffer,
|
2024-01-05 19:56:26 -08:00
|
|
|
pub object_buffer: wgpu::Buffer,
|
2024-01-04 17:18:31 -08:00
|
|
|
pub bind_group: wgpu::BindGroup,
|
|
|
|
pub bind_group_layout: wgpu::BindGroupLayout,
|
2024-01-06 14:02:50 -08:00
|
|
|
pub content: GlobalDataContent,
|
2024-01-04 17:18:31 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
impl GlobalUniform {
|
|
|
|
pub fn shader_header(&self, group: u32) -> String {
|
|
|
|
let mut out = String::new();
|
|
|
|
|
2024-01-05 19:56:26 -08:00
|
|
|
// Global game data
|
2024-01-04 17:18:31 -08:00
|
|
|
out.push_str(&format!("@group({group}) @binding(0)\n"));
|
|
|
|
out.push_str(
|
|
|
|
r#"
|
2024-01-06 14:02:50 -08:00
|
|
|
var<uniform> global_data: GlobalData;
|
|
|
|
struct GlobalData {
|
2024-01-04 17:18:31 -08:00
|
|
|
camera_position: vec2<f32>,
|
|
|
|
camera_zoom: vec2<f32>,
|
|
|
|
camera_zoom_limits: vec2<f32>,
|
|
|
|
window_size: vec2<f32>,
|
2024-01-08 15:17:20 -08:00
|
|
|
window_scale: vec2<f32>,
|
2024-01-04 17:18:31 -08:00
|
|
|
window_aspect: vec2<f32>,
|
2024-01-04 18:15:30 -08:00
|
|
|
starfield_sprite: vec2<u32>,
|
2024-01-04 17:18:31 -08:00
|
|
|
starfield_tile_size: vec2<f32>,
|
|
|
|
starfield_size_limits: vec2<f32>,
|
|
|
|
current_time: vec2<f32>,
|
|
|
|
};
|
2024-01-04 19:01:22 -08:00
|
|
|
"#,
|
2024-01-04 17:18:31 -08:00
|
|
|
);
|
|
|
|
out.push_str("\n");
|
|
|
|
|
2024-01-05 19:56:26 -08:00
|
|
|
// Atlas image locations
|
|
|
|
out.push_str(&format!(
|
|
|
|
r#"
|
|
|
|
@group({group}) @binding(1)
|
2024-01-06 14:02:50 -08:00
|
|
|
var<uniform> global_atlas: array<AtlasImageLocation, {IMAGE_LIMIT}>;
|
2024-01-05 19:56:26 -08:00
|
|
|
"#
|
|
|
|
));
|
|
|
|
out.push_str("\n");
|
2024-01-04 17:18:31 -08:00
|
|
|
out.push_str(
|
|
|
|
r#"
|
2024-01-06 14:02:50 -08:00
|
|
|
struct AtlasImageLocation {
|
2024-01-04 17:18:31 -08:00
|
|
|
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 17:18:31 -08:00
|
|
|
};
|
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
|
|
|
|
|
2024-01-05 19:56:26 -08:00
|
|
|
// Object location data
|
2024-01-04 19:01:22 -08:00
|
|
|
out.push_str(&format!(
|
|
|
|
r#"
|
2024-01-20 10:04:09 -08:00
|
|
|
@group({group}) @binding(2)
|
2024-01-06 14:02:50 -08:00
|
|
|
var<uniform> objects: array<ObjectData, {OBJECT_SPRITE_INSTANCE_LIMIT}>;
|
2024-01-05 19:56:26 -08:00
|
|
|
"#
|
2024-01-04 19:01:22 -08:00
|
|
|
));
|
2024-01-04 17:18:31 -08:00
|
|
|
out.push_str("\n");
|
2024-01-05 19:56:26 -08:00
|
|
|
out.push_str(
|
|
|
|
r#"
|
2024-01-06 14:02:50 -08:00
|
|
|
struct ObjectData {
|
2024-01-05 19:56:26 -08:00
|
|
|
xpos: f32,
|
|
|
|
ypos: f32,
|
|
|
|
zpos: f32,
|
|
|
|
angle: f32,
|
|
|
|
size: f32,
|
2024-01-06 14:02:50 -08:00
|
|
|
parent: u32,
|
|
|
|
is_child: u32,
|
2024-01-05 19:56:26 -08:00
|
|
|
|
|
|
|
padding_a: f32,
|
|
|
|
};
|
|
|
|
"#,
|
|
|
|
);
|
|
|
|
out.push_str("\n");
|
2024-01-04 17:18:31 -08:00
|
|
|
|
|
|
|
return out;
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn new(device: &wgpu::Device) -> Self {
|
|
|
|
let data_buffer = device.create_buffer(&wgpu::BufferDescriptor {
|
|
|
|
label: Some("global uniform data buffer"),
|
2024-01-06 14:02:50 -08:00
|
|
|
size: GlobalDataContent::SIZE,
|
2024-01-04 17:18:31 -08:00
|
|
|
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"),
|
2024-01-05 19:56:26 -08:00
|
|
|
size: AtlasArray::SIZE,
|
2024-01-04 17:18:31 -08:00
|
|
|
usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST,
|
|
|
|
mapped_at_creation: false,
|
|
|
|
});
|
|
|
|
|
2024-01-05 19:56:26 -08:00
|
|
|
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,
|
|
|
|
});
|
|
|
|
|
2024-01-04 17:18:31 -08:00
|
|
|
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,
|
|
|
|
},
|
2024-01-04 17:18:31 -08:00
|
|
|
],
|
|
|
|
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,
|
2024-01-05 19:56:26 -08:00
|
|
|
resource: object_buffer.as_entire_binding(),
|
|
|
|
},
|
2024-01-04 17:18:31 -08:00
|
|
|
],
|
|
|
|
label: Some("global uniform bind group"),
|
|
|
|
});
|
|
|
|
|
|
|
|
return Self {
|
|
|
|
data_buffer,
|
|
|
|
atlas_buffer,
|
2024-01-05 19:56:26 -08:00
|
|
|
object_buffer,
|
2024-01-04 17:18:31 -08:00
|
|
|
bind_group,
|
|
|
|
bind_group_layout,
|
2024-01-06 14:02:50 -08:00
|
|
|
content: GlobalDataContent::default(),
|
2024-01-04 17:18:31 -08:00
|
|
|
};
|
|
|
|
}
|
|
|
|
}
|