Compare commits
3 Commits
a4ca62e1dc
...
1f154c1a58
Author | SHA1 | Date |
---|---|---|
Mark | 1f154c1a58 | |
Mark | 7593be18ee | |
Mark | 83857d4d0d |
2
assets
2
assets
|
@ -1 +1 @@
|
||||||
Subproject commit 05e5272f3789b44192d0bf2bd253641e76659a2a
|
Subproject commit 38fd6766762ce90bb699f98e30e46b17c4eda50c
|
|
@ -1,5 +1,5 @@
|
||||||
[ship."Gypsum"]
|
[ship."Gypsum"]
|
||||||
sprite = "ship::gypsum"
|
sprite = "ship::peregrine"
|
||||||
size = 100
|
size = 100
|
||||||
mass = 1
|
mass = 1
|
||||||
hull = 200
|
hull = 200
|
||||||
|
|
|
@ -19,6 +19,23 @@ file = "projectile/blaster.png"
|
||||||
[sprite."ship::gypsum"]
|
[sprite."ship::gypsum"]
|
||||||
file = "ship/gypsum.png"
|
file = "ship/gypsum.png"
|
||||||
|
|
||||||
|
[sprite."ship::peregrine"]
|
||||||
|
duration = 1
|
||||||
|
repeat = "repeat"
|
||||||
|
frames = [
|
||||||
|
"ship/peregrine/01.png",
|
||||||
|
"ship/peregrine/02.png",
|
||||||
|
"ship/peregrine/03.png",
|
||||||
|
"ship/peregrine/04.png",
|
||||||
|
"ship/peregrine/05.png",
|
||||||
|
"ship/peregrine/06.png",
|
||||||
|
"ship/peregrine/07.png",
|
||||||
|
"ship/peregrine/08.png",
|
||||||
|
"ship/peregrine/09.png",
|
||||||
|
"ship/peregrine/10.png",
|
||||||
|
"ship/peregrine/11.png",
|
||||||
|
]
|
||||||
|
|
||||||
[sprite."ui::radar"]
|
[sprite."ui::radar"]
|
||||||
file = "ui/radar.png"
|
file = "ui/radar.png"
|
||||||
|
|
||||||
|
|
|
@ -55,3 +55,9 @@ pub const PARTICLE_SPRITE_INSTANCE_LIMIT: u64 = 1000;
|
||||||
|
|
||||||
/// Must be small enough to fit in an i32
|
/// Must be small enough to fit in an i32
|
||||||
pub const STARFIELD_SPRITE_INSTANCE_LIMIT: u64 = STARFIELD_COUNT * 24;
|
pub const STARFIELD_SPRITE_INSTANCE_LIMIT: u64 = STARFIELD_COUNT * 24;
|
||||||
|
|
||||||
|
/// The maximum number of sprites we can define
|
||||||
|
pub const SPRITE_LIMIT: u32 = 1024;
|
||||||
|
|
||||||
|
/// The maximum number of images we can load
|
||||||
|
pub const IMAGE_LIMIT: u32 = 1024;
|
||||||
|
|
|
@ -208,6 +208,8 @@ impl Content {
|
||||||
part::sprite::Sprite::build(root.sprite.take().unwrap(), &mut content)?;
|
part::sprite::Sprite::build(root.sprite.take().unwrap(), &mut content)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: enforce sprite and image limits
|
||||||
|
|
||||||
if root.ship.is_some() {
|
if root.ship.is_some() {
|
||||||
part::ship::Ship::build(root.ship.take().unwrap(), &mut content)?;
|
part::ship::Ship::build(root.ship.take().unwrap(), &mut content)?;
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,7 +26,39 @@ var texture_array: binding_array<texture_2d<f32>>;
|
||||||
var sampler_array: binding_array<sampler>;
|
var sampler_array: binding_array<sampler>;
|
||||||
|
|
||||||
|
|
||||||
|
fn fmod(x: f32, m: f32) -> f32 {
|
||||||
|
return x - floor(x / m) * m;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns texture index
|
||||||
|
// TODO: random age
|
||||||
|
// TODO: preprocessor include function
|
||||||
|
// TODO: packed location config, better error
|
||||||
|
// TODO: bounce animations
|
||||||
|
// TODO: animation randomness?
|
||||||
|
fn animate(instance: InstanceInput) -> u32 {
|
||||||
|
// Age doesn't make sense here, so arbitrarily pick zero.
|
||||||
|
let age = global.current_time.x;
|
||||||
|
let len = sprites.data[instance.texture_index].frame_count;
|
||||||
|
let rep = sprites.data[instance.texture_index].repeatmode;
|
||||||
|
let fps = sprites.data[instance.texture_index].fps;
|
||||||
|
var frame: u32 = u32(0);
|
||||||
|
if rep == u32(1) {
|
||||||
|
// Repeat
|
||||||
|
frame = u32(fmod(
|
||||||
|
(age / fps),
|
||||||
|
f32(len)
|
||||||
|
));
|
||||||
|
} else {
|
||||||
|
// Once
|
||||||
|
frame = u32(min(
|
||||||
|
(age / fps),
|
||||||
|
f32(len) - 1.0
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
return frame + sprites.data[instance.texture_index].first_frame;
|
||||||
|
}
|
||||||
|
|
||||||
@vertex
|
@vertex
|
||||||
fn vertex_main(
|
fn vertex_main(
|
||||||
|
@ -44,8 +76,7 @@ fn vertex_main(
|
||||||
var out: VertexOutput;
|
var out: VertexOutput;
|
||||||
out.position = transform * vec4<f32>(vertex.position, 1.0);
|
out.position = transform * vec4<f32>(vertex.position, 1.0);
|
||||||
|
|
||||||
let i = sprites.data[instance.texture_index].first_frame;
|
let t = atlas.data[animate(instance)];
|
||||||
let t = atlas.data[i];
|
|
||||||
out.texture_index = u32(0);
|
out.texture_index = u32(0);
|
||||||
out.texture_coords = vec2(t.xpos, t.ypos);
|
out.texture_coords = vec2(t.xpos, t.ypos);
|
||||||
if vertex.texture_coords.x == 1.0 {
|
if vertex.texture_coords.x == 1.0 {
|
||||||
|
|
|
@ -29,6 +29,30 @@ var texture_array: binding_array<texture_2d<f32>>;
|
||||||
var sampler_array: binding_array<sampler>;
|
var sampler_array: binding_array<sampler>;
|
||||||
|
|
||||||
|
|
||||||
|
// Returns texture index
|
||||||
|
fn animate(instance: InstanceInput) -> u32 {
|
||||||
|
let age = global.current_time.x - instance.created;
|
||||||
|
let len = sprites.data[instance.texture_index].frame_count;
|
||||||
|
let rep = sprites.data[instance.texture_index].repeatmode;
|
||||||
|
let fps = sprites.data[instance.texture_index].fps;
|
||||||
|
var frame: u32 = u32(0);
|
||||||
|
if rep == u32(1) {
|
||||||
|
// Repeat
|
||||||
|
frame = u32(fmod(
|
||||||
|
(age / fps),
|
||||||
|
f32(len)
|
||||||
|
));
|
||||||
|
} else {
|
||||||
|
// Once
|
||||||
|
frame = u32(min(
|
||||||
|
(age / fps),
|
||||||
|
f32(len) - 1.0
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
return frame + sprites.data[instance.texture_index].first_frame;
|
||||||
|
}
|
||||||
|
|
||||||
fn fmod(x: f32, m: f32) -> f32 {
|
fn fmod(x: f32, m: f32) -> f32 {
|
||||||
return x - floor(x / m) * m;
|
return x - floor(x / m) * m;
|
||||||
}
|
}
|
||||||
|
@ -68,10 +92,7 @@ fn vertex_main(
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let t = atlas.data[animate(instance)];
|
||||||
// Pick image
|
|
||||||
frame = frame + sprites.data[instance.texture_index].first_frame;
|
|
||||||
let t = atlas.data[frame];
|
|
||||||
out.texture_index = u32(0);
|
out.texture_index = u32(0);
|
||||||
out.texture_coords = vec2(t.xpos, t.ypos);
|
out.texture_coords = vec2(t.xpos, t.ypos);
|
||||||
if vertex.texture_coords.x == 1.0 {
|
if vertex.texture_coords.x == 1.0 {
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
use bytemuck::{Pod, Zeroable};
|
use bytemuck::{Pod, Zeroable};
|
||||||
|
use galactica_constants::IMAGE_LIMIT;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use wgpu;
|
use wgpu;
|
||||||
|
|
||||||
|
@ -14,14 +15,14 @@ pub struct ImageLocation {
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
pub struct ImageLocationArray {
|
pub struct ImageLocationArray {
|
||||||
pub data: [ImageLocation; 108],
|
pub data: [ImageLocation; IMAGE_LIMIT as usize],
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe impl Pod for ImageLocationArray {}
|
unsafe impl Pod for ImageLocationArray {}
|
||||||
unsafe impl Zeroable for ImageLocationArray {
|
unsafe impl Zeroable for ImageLocationArray {
|
||||||
fn zeroed() -> Self {
|
fn zeroed() -> Self {
|
||||||
Self {
|
Self {
|
||||||
data: [ImageLocation::zeroed(); 108],
|
data: [ImageLocation::zeroed(); IMAGE_LIMIT as usize],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
use galactica_constants::{IMAGE_LIMIT, SPRITE_LIMIT};
|
||||||
use wgpu;
|
use wgpu;
|
||||||
|
|
||||||
use super::{AtlasContent, DataContent, SpriteContent};
|
use super::{AtlasContent, DataContent, SpriteContent};
|
||||||
|
@ -30,7 +31,7 @@ impl GlobalUniform {
|
||||||
starfield_size_limits: vec2<f32>,
|
starfield_size_limits: vec2<f32>,
|
||||||
current_time: vec2<f32>,
|
current_time: vec2<f32>,
|
||||||
};
|
};
|
||||||
"#,
|
"#,
|
||||||
);
|
);
|
||||||
out.push_str("\n");
|
out.push_str("\n");
|
||||||
|
|
||||||
|
@ -44,11 +45,16 @@ impl GlobalUniform {
|
||||||
width: f32,
|
width: f32,
|
||||||
height: f32,
|
height: f32,
|
||||||
};
|
};
|
||||||
struct AtlasUniform {
|
"#,
|
||||||
data: array<ImageLocation, 108>,
|
|
||||||
};
|
|
||||||
"#,
|
|
||||||
);
|
);
|
||||||
|
out.push_str(&format!(
|
||||||
|
r#"
|
||||||
|
struct AtlasUniform {{
|
||||||
|
data: array<ImageLocation, {}>,
|
||||||
|
}};
|
||||||
|
"#,
|
||||||
|
IMAGE_LIMIT,
|
||||||
|
));
|
||||||
out.push_str("\n");
|
out.push_str("\n");
|
||||||
|
|
||||||
// TODO: document
|
// TODO: document
|
||||||
|
@ -72,11 +78,16 @@ impl GlobalUniform {
|
||||||
padding_b: f32,
|
padding_b: f32,
|
||||||
padding_c: f32,
|
padding_c: f32,
|
||||||
};
|
};
|
||||||
struct SpriteUniform {
|
"#,
|
||||||
data: array<SpriteData, 108>,
|
|
||||||
};
|
|
||||||
"#,
|
|
||||||
);
|
);
|
||||||
|
out.push_str(&format!(
|
||||||
|
r#"
|
||||||
|
struct SpriteUniform {{
|
||||||
|
data: array<SpriteData, {}>,
|
||||||
|
}};
|
||||||
|
"#,
|
||||||
|
SPRITE_LIMIT,
|
||||||
|
));
|
||||||
out.push_str("\n");
|
out.push_str("\n");
|
||||||
|
|
||||||
return out;
|
return out;
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
use bytemuck::{Pod, Zeroable};
|
use bytemuck::{Pod, Zeroable};
|
||||||
|
use galactica_constants::SPRITE_LIMIT;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use wgpu;
|
use wgpu;
|
||||||
|
|
||||||
|
@ -19,14 +20,14 @@ pub struct SpriteData {
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
pub struct SpriteDataArray {
|
pub struct SpriteDataArray {
|
||||||
pub data: [SpriteData; 108],
|
pub data: [SpriteData; SPRITE_LIMIT as usize],
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe impl Pod for SpriteDataArray {}
|
unsafe impl Pod for SpriteDataArray {}
|
||||||
unsafe impl Zeroable for SpriteDataArray {
|
unsafe impl Zeroable for SpriteDataArray {
|
||||||
fn zeroed() -> Self {
|
fn zeroed() -> Self {
|
||||||
Self {
|
Self {
|
||||||
data: [SpriteData::zeroed(); 108],
|
data: [SpriteData::zeroed(); SPRITE_LIMIT as usize],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -105,8 +105,9 @@ impl TextureArray {
|
||||||
|
|
||||||
println!("sending to gpu");
|
println!("sending to gpu");
|
||||||
let mut image_counter = 0;
|
let mut image_counter = 0;
|
||||||
|
let mut sprite_counter = 0;
|
||||||
for t in &ct.sprites {
|
for t in &ct.sprites {
|
||||||
sprite_data.data[image_counter as usize] = SpriteData {
|
sprite_data.data[sprite_counter] = SpriteData {
|
||||||
frame_count: t.frames.len() as u32,
|
frame_count: t.frames.len() as u32,
|
||||||
repeatmode: t.repeat.as_int(),
|
repeatmode: t.repeat.as_int(),
|
||||||
aspect: t.aspect,
|
aspect: t.aspect,
|
||||||
|
@ -114,6 +115,7 @@ impl TextureArray {
|
||||||
first_frame: image_counter,
|
first_frame: image_counter,
|
||||||
_padding: Default::default(),
|
_padding: Default::default(),
|
||||||
};
|
};
|
||||||
|
sprite_counter += 1;
|
||||||
|
|
||||||
// Insert texture location data
|
// Insert texture location data
|
||||||
for path in &t.frames {
|
for path in &t.frames {
|
||||||
|
|
Loading…
Reference in New Issue