Reworked renderer for new sprite system
parent
73f540d30a
commit
fdd481e8f0
|
@ -1,41 +0,0 @@
|
|||
// Pick a frame of a sprite animation from an instance.
|
||||
fn animate(sprite_index: u32, age: f32, offset: f32) -> f32 {
|
||||
|
||||
let len = global_sprites[sprite_index].frame_count;
|
||||
let rep = global_sprites[sprite_index].repeatmode;
|
||||
let frame_duration = global_sprites[sprite_index].frame_duration;
|
||||
var frame: f32 = 0.0;
|
||||
|
||||
// Once
|
||||
if rep == u32(1) {
|
||||
|
||||
frame = min(
|
||||
age / frame_duration + offset,
|
||||
f32(len) - 1.0
|
||||
);
|
||||
|
||||
// Reverse
|
||||
} else if rep == u32(2) {
|
||||
let x = age / frame_duration + offset;
|
||||
let m = f32(len) * 2.0 - 1.0;
|
||||
// x fmod m
|
||||
frame = x - floor(x / m) * m;
|
||||
|
||||
if frame >= f32(len) {
|
||||
frame = (
|
||||
f32(len) + f32(len) - 1.0
|
||||
// Split integer and fractional part so tweening works properly
|
||||
- floor(frame)
|
||||
+ fract(frame)
|
||||
);
|
||||
}
|
||||
|
||||
// Repeat (default)
|
||||
} else {
|
||||
let x = age / frame_duration + offset;
|
||||
let m = f32(len);
|
||||
frame = x - floor(x / m) * m;
|
||||
}
|
||||
|
||||
return frame + f32(global_sprites[sprite_index].first_frame);
|
||||
}
|
|
@ -1,8 +1,9 @@
|
|||
// INCLUDE: global uniform header
|
||||
|
||||
struct InstanceInput {
|
||||
@location(2) sprite_index: u32,
|
||||
@location(3) object_index: u32,
|
||||
@location(2) texture_index: vec2<u32>,
|
||||
@location(3) texture_fade: f32,
|
||||
@location(4) object_index: u32,
|
||||
};
|
||||
|
||||
struct VertexInput {
|
||||
|
@ -25,20 +26,19 @@ var texture_array: binding_array<texture_2d<f32>>;
|
|||
@group(0) @binding(1)
|
||||
var sampler_array: binding_array<sampler>;
|
||||
|
||||
|
||||
// INCLUDE: animate.wgsl
|
||||
|
||||
fn transform_vertex(obj: ObjectData, vertex_position: vec2<f32>, sprite_index: u32) -> vec4<f32> {
|
||||
fn transform_vertex(obj: ObjectData, vertex_position: vec2<f32>, texture_index: u32) -> vec4<f32> {
|
||||
// Object scale
|
||||
var scale: f32 = obj.size / (global_data.camera_zoom.x * obj.zpos);
|
||||
if obj.is_child == 1u {
|
||||
scale /= objects[obj.parent].zpos;
|
||||
}
|
||||
|
||||
let texture = global_atlas[texture_index];
|
||||
|
||||
// Apply scale and sprite aspect
|
||||
// Note that our mesh starts centered at (0, 0). This is important!
|
||||
var pos: vec2<f32> = vec2(
|
||||
vertex_position.x * scale * global_sprites[sprite_index].aspect,
|
||||
vertex_position.x * scale * (texture.width / texture.height),
|
||||
vertex_position.y * scale
|
||||
);
|
||||
|
||||
|
@ -113,18 +113,18 @@ fn vertex_main(
|
|||
) -> VertexOutput {
|
||||
var out: VertexOutput;
|
||||
|
||||
|
||||
|
||||
out.position = transform_vertex(objects[instance.object_index], vertex.position.xy, instance.sprite_index);
|
||||
out.position = transform_vertex(
|
||||
objects[instance.object_index],
|
||||
vertex.position.xy,
|
||||
instance.texture_index.x
|
||||
);
|
||||
|
||||
|
||||
// Compute texture coordinates
|
||||
|
||||
let age = global_data.current_time.x;
|
||||
let frame = animate(instance.sprite_index, age, 0.0);
|
||||
out.tween = fract(frame);
|
||||
out.tween = instance.texture_fade;
|
||||
|
||||
let t = global_atlas[u32(floor(frame))];
|
||||
let t = global_atlas[instance.texture_index.x];
|
||||
out.texture_index_a = u32(t.atlas_texture);
|
||||
out.texture_coords_a = vec2(t.xpos, t.ypos);
|
||||
if vertex.texture_coords.x == 1.0 {
|
||||
|
@ -134,7 +134,7 @@ fn vertex_main(
|
|||
out.texture_coords_a = out.texture_coords_a + vec2(0.0, t.height);
|
||||
}
|
||||
|
||||
let b = global_atlas[u32(floor(animate(instance.sprite_index, age, 1.0)))];
|
||||
let b = global_atlas[instance.texture_index.y];
|
||||
out.texture_index_b = u32(b.atlas_texture);
|
||||
out.texture_coords_b = vec2(b.xpos, b.ypos);
|
||||
if vertex.texture_coords.x == 1.0 {
|
||||
|
|
|
@ -9,7 +9,8 @@ struct InstanceInput {
|
|||
@location(7) created: f32,
|
||||
@location(8) expires: f32,
|
||||
@location(9) fade: f32,
|
||||
@location(10) sprite_index: u32,
|
||||
@location(10) texture_index: vec2<u32>,
|
||||
@location(11) texture_fade: f32,
|
||||
};
|
||||
|
||||
struct VertexInput {
|
||||
|
@ -33,9 +34,6 @@ var texture_array: binding_array<texture_2d<f32>>;
|
|||
@group(0) @binding(1)
|
||||
var sampler_array: binding_array<sampler>;
|
||||
|
||||
|
||||
// INCLUDE: animate.wgsl
|
||||
|
||||
@vertex
|
||||
fn vertex_main(
|
||||
vertex: VertexInput,
|
||||
|
@ -96,9 +94,9 @@ fn vertex_main(
|
|||
|
||||
// Compute texture coordinates
|
||||
let frame = animate(instance.sprite_index, age, 0.0);
|
||||
out.tween = fract(frame);
|
||||
out.tween = instance.texture_fade;
|
||||
|
||||
let t = global_atlas[u32(floor(frame))];
|
||||
let t = global_atlas[instance.texture_index.x];
|
||||
out.texture_index_a = u32(t.atlas_texture);
|
||||
out.texture_coords_a = vec2(t.xpos, t.ypos);
|
||||
if vertex.texture_coords.x == 1.0 {
|
||||
|
@ -108,7 +106,7 @@ fn vertex_main(
|
|||
out.texture_coords_a = out.texture_coords_a + vec2(0.0, t.height);
|
||||
}
|
||||
|
||||
let b = global_atlas[u32(floor(animate(instance.sprite_index, age, 1.0)))];
|
||||
let b = global_atlas[instance.texture_index.y];
|
||||
out.texture_index_b = u32(b.atlas_texture);
|
||||
out.texture_coords_b = vec2(b.xpos, b.ypos);
|
||||
if vertex.texture_coords.x == 1.0 {
|
||||
|
@ -118,7 +116,6 @@ fn vertex_main(
|
|||
out.texture_coords_b = out.texture_coords_b + vec2(0.0, b.height);
|
||||
}
|
||||
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
|
|
|
@ -109,8 +109,7 @@ fn vertex_main(
|
|||
|
||||
|
||||
// Starfield sprites may not be animated
|
||||
let i = global_sprites[global_data.starfield_sprite.x].first_frame;
|
||||
let t = global_atlas[i];
|
||||
let t = global_atlas[global_data.starfield_sprite.x];
|
||||
out.texture_index = u32(t.atlas_texture);
|
||||
out.texture_coords = vec2(t.xpos, t.ypos);
|
||||
if vertex.texture_coords.x == 1.0 {
|
||||
|
|
|
@ -6,8 +6,9 @@ struct InstanceInput {
|
|||
@location(4) angle: f32,
|
||||
@location(5) size: f32,
|
||||
@location(6) color_transform: vec4<f32>,
|
||||
@location(7) sprite_index: u32,
|
||||
@location(8) mask_index: vec2<u32>,
|
||||
@location(7) texture_index: vec2<u32>,
|
||||
@location(8) texture_fade: f32,
|
||||
@location(9) mask_index: vec2<u32>,
|
||||
};
|
||||
|
||||
struct VertexInput {
|
||||
|
@ -30,7 +31,6 @@ var texture_array: binding_array<texture_2d<f32>>;
|
|||
var sampler_array: binding_array<sampler>;
|
||||
|
||||
|
||||
// INCLUDE: animate.wgsl
|
||||
// INCLUDE: anchor.wgsl
|
||||
|
||||
@vertex
|
||||
|
@ -42,12 +42,15 @@ fn vertex_main(
|
|||
|
||||
let window_dim = global_data.window_size / global_data.window_scale.x;
|
||||
let scale = instance.size / window_dim.y;
|
||||
let sprite_aspect = global_sprites[instance.sprite_index].aspect;
|
||||
let aspect = (
|
||||
global_atlas[instance.texture_index.x].width /
|
||||
global_atlas[instance.texture_index.x].height
|
||||
);
|
||||
|
||||
// Apply scale and sprite aspect
|
||||
// Note that our mesh starts centered at (0, 0). This is important!
|
||||
var pos: vec2<f32> = vec2(
|
||||
vertex.position.x * scale * sprite_aspect,
|
||||
vertex.position.x * scale * aspect,
|
||||
vertex.position.y * scale
|
||||
);
|
||||
|
||||
|
@ -66,7 +69,7 @@ fn vertex_main(
|
|||
pos = pos + anchor(
|
||||
instance.anchor,
|
||||
instance.position,
|
||||
vec2(instance.size * sprite_aspect, instance.size)
|
||||
vec2(instance.size * aspect, instance.size)
|
||||
);
|
||||
|
||||
var out: VertexOutput;
|
||||
|
@ -77,7 +80,7 @@ fn vertex_main(
|
|||
|
||||
// TODO: function to get texture from sprite
|
||||
// Pick texture frame
|
||||
let t = global_atlas[u32(animate(instance.sprite_index, global_data.current_time.x, 0.0))];
|
||||
let t = global_atlas[instance.texture_index.x];
|
||||
out.texture_index = u32(t.atlas_texture);
|
||||
out.texture_coords = vec2(t.xpos, t.ypos);
|
||||
if vertex.texture_coords.x == 1.0 {
|
||||
|
@ -91,8 +94,7 @@ fn vertex_main(
|
|||
// x coordinate of mask index is either 0 or 1, telling us whether or not to use a mask.
|
||||
// y coordinate is mask sprite index
|
||||
if instance.mask_index.x == 1u {
|
||||
let ms = global_sprites[instance.mask_index.y].first_frame;
|
||||
let m = global_atlas[ms];
|
||||
let m = global_atlas[instance.mask_index.y];
|
||||
out.mask_index = vec2(1u, u32(m.atlas_texture));
|
||||
out.mask_coords = vec2(m.xpos, m.ypos);
|
||||
if vertex.texture_coords.x == 1.0 {
|
||||
|
|
|
@ -1,12 +1,11 @@
|
|||
use galactica_util::constants::{IMAGE_LIMIT, OBJECT_SPRITE_INSTANCE_LIMIT, SPRITE_LIMIT};
|
||||
use galactica_util::constants::{IMAGE_LIMIT, OBJECT_SPRITE_INSTANCE_LIMIT};
|
||||
use wgpu;
|
||||
|
||||
use super::{object::ObjectLocationArray, AtlasArray, GlobalDataContent, SpriteDataArray};
|
||||
use super::{object::ObjectLocationArray, AtlasArray, GlobalDataContent};
|
||||
|
||||
pub struct GlobalUniform {
|
||||
pub data_buffer: wgpu::Buffer,
|
||||
pub atlas_buffer: wgpu::Buffer,
|
||||
pub sprite_buffer: wgpu::Buffer,
|
||||
pub object_buffer: wgpu::Buffer,
|
||||
pub bind_group: wgpu::BindGroup,
|
||||
pub bind_group_layout: wgpu::BindGroupLayout,
|
||||
|
@ -70,35 +69,10 @@ impl GlobalUniform {
|
|||
// `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> global_sprites: array<SpriteData, {SPRITE_LIMIT}>;
|
||||
"#
|
||||
));
|
||||
out.push_str("\n");
|
||||
out.push_str(
|
||||
r#"
|
||||
struct SpriteData {
|
||||
frame_count: u32,
|
||||
repeatmode: u32,
|
||||
aspect: f32,
|
||||
frame_duration: f32,
|
||||
first_frame: u32,
|
||||
|
||||
padding_a: f32,
|
||||
padding_b: f32,
|
||||
padding_c: f32,
|
||||
};
|
||||
"#,
|
||||
);
|
||||
out.push_str("\n");
|
||||
|
||||
// Object location data
|
||||
out.push_str(&format!(
|
||||
r#"
|
||||
@group({group}) @binding(3)
|
||||
@group({group}) @binding(2)
|
||||
var<uniform> objects: array<ObjectData, {OBJECT_SPRITE_INSTANCE_LIMIT}>;
|
||||
"#
|
||||
));
|
||||
|
@ -138,13 +112,6 @@ impl GlobalUniform {
|
|||
mapped_at_creation: false,
|
||||
});
|
||||
|
||||
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,
|
||||
|
@ -184,16 +151,6 @@ impl GlobalUniform {
|
|||
},
|
||||
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"),
|
||||
});
|
||||
|
@ -211,10 +168,6 @@ impl GlobalUniform {
|
|||
},
|
||||
wgpu::BindGroupEntry {
|
||||
binding: 2,
|
||||
resource: sprite_buffer.as_entire_binding(),
|
||||
},
|
||||
wgpu::BindGroupEntry {
|
||||
binding: 3,
|
||||
resource: object_buffer.as_entire_binding(),
|
||||
},
|
||||
],
|
||||
|
@ -224,7 +177,6 @@ impl GlobalUniform {
|
|||
return Self {
|
||||
data_buffer,
|
||||
atlas_buffer,
|
||||
sprite_buffer,
|
||||
object_buffer,
|
||||
bind_group,
|
||||
bind_group_layout,
|
||||
|
|
|
@ -2,10 +2,8 @@ mod atlas;
|
|||
mod data;
|
||||
mod globaluniform;
|
||||
mod object;
|
||||
mod sprite;
|
||||
|
||||
pub use atlas::{AtlasArray, AtlasImageLocation};
|
||||
pub use data::GlobalDataContent;
|
||||
pub use globaluniform::GlobalUniform;
|
||||
pub use object::ObjectData;
|
||||
pub use sprite::{SpriteData, SpriteDataArray};
|
||||
|
|
|
@ -1,43 +0,0 @@
|
|||
use bytemuck::{Pod, Zeroable};
|
||||
use galactica_util::constants::SPRITE_LIMIT;
|
||||
use std::mem;
|
||||
use wgpu;
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Copy, Clone, Pod, Zeroable, Default)]
|
||||
pub struct SpriteData {
|
||||
// Animation parameters
|
||||
pub frame_count: u32,
|
||||
pub repeatmode: u32,
|
||||
pub aspect: f32,
|
||||
pub frame_duration: f32,
|
||||
|
||||
// Index of first frame in ImageLocationArray
|
||||
pub first_frame: u32,
|
||||
// stride must be a multiple of 16
|
||||
pub _padding: [f32; 3],
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub struct SpriteDataArray {
|
||||
pub data: [SpriteData; SPRITE_LIMIT as usize],
|
||||
}
|
||||
|
||||
unsafe impl Pod for SpriteDataArray {}
|
||||
unsafe impl Zeroable for SpriteDataArray {
|
||||
fn zeroed() -> Self {
|
||||
Self {
|
||||
data: [SpriteData::zeroed(); SPRITE_LIMIT as usize],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for SpriteDataArray {
|
||||
fn default() -> Self {
|
||||
Self::zeroed()
|
||||
}
|
||||
}
|
||||
|
||||
impl SpriteDataArray {
|
||||
pub const SIZE: u64 = mem::size_of::<Self>() as wgpu::BufferAddress;
|
||||
}
|
|
@ -20,7 +20,7 @@ pub struct GPUState {
|
|||
|
||||
object_pipeline: wgpu::RenderPipeline,
|
||||
starfield_pipeline: wgpu::RenderPipeline,
|
||||
particle_pipeline: wgpu::RenderPipeline,
|
||||
//particle_pipeline: wgpu::RenderPipeline,
|
||||
ui_pipeline: wgpu::RenderPipeline,
|
||||
radialbar_pipeline: wgpu::RenderPipeline,
|
||||
|
||||
|
@ -57,12 +57,7 @@ impl GPUState {
|
|||
self.state.queue.write_buffer(
|
||||
&self.state.global_uniform.atlas_buffer,
|
||||
0,
|
||||
bytemuck::cast_slice(&[self.texture_array.image_locations]),
|
||||
);
|
||||
self.state.queue.write_buffer(
|
||||
&self.state.global_uniform.sprite_buffer,
|
||||
0,
|
||||
bytemuck::cast_slice(&[self.texture_array.sprite_data]),
|
||||
bytemuck::cast_slice(&[self.texture_array.texture_atlas]),
|
||||
);
|
||||
|
||||
self.starfield.update_buffer(ct, &mut self.state);
|
||||
|
|
|
@ -167,6 +167,7 @@ impl GPUState {
|
|||
.set_bind_group_layouts(bind_group_layouts)
|
||||
.build();
|
||||
|
||||
/*
|
||||
let particle_pipeline = PipelineBuilder::new("particle", &device)
|
||||
.set_shader(&preprocess_shader(
|
||||
&include_str!(concat!(
|
||||
|
@ -181,7 +182,7 @@ impl GPUState {
|
|||
.set_triangle(true)
|
||||
.set_vertex_buffer(vertex_buffers.get_particle())
|
||||
.set_bind_group_layouts(bind_group_layouts)
|
||||
.build();
|
||||
.build();*/
|
||||
|
||||
let radialbar_pipeline = PipelineBuilder::new("radialbar", &device)
|
||||
.set_shader(&preprocess_shader(
|
||||
|
@ -228,7 +229,7 @@ impl GPUState {
|
|||
object_pipeline,
|
||||
starfield_pipeline,
|
||||
ui_pipeline,
|
||||
particle_pipeline,
|
||||
//particle_pipeline,
|
||||
radialbar_pipeline,
|
||||
|
||||
state,
|
||||
|
|
|
@ -22,7 +22,7 @@ impl GPUState {
|
|||
let ship_pos;
|
||||
let ship_ang;
|
||||
let ship_cnt;
|
||||
match ship.data.get_state() {
|
||||
match ship.get_data().get_state() {
|
||||
ShipState::Dead | ShipState::Landed { .. } => continue,
|
||||
|
||||
ShipState::Collapsing { .. } | ShipState::Flying { .. } => {
|
||||
|
@ -31,7 +31,7 @@ impl GPUState {
|
|||
ship_pos = Point3::new(pos.x, pos.y, 1.0);
|
||||
let ship_rot = r.rotation();
|
||||
ship_ang = ship_rot.angle();
|
||||
ship_cnt = state.ct.get_ship(ship.data.get_content());
|
||||
ship_cnt = state.ct.get_ship(ship.get_data().get_content());
|
||||
}
|
||||
|
||||
ShipState::UnLanding { current_z, .. } | ShipState::Landing { current_z, .. } => {
|
||||
|
@ -40,7 +40,7 @@ impl GPUState {
|
|||
ship_pos = Point3::new(pos.x, pos.y, *current_z);
|
||||
let ship_rot = r.rotation();
|
||||
ship_ang = ship_rot.angle();
|
||||
ship_cnt = state.ct.get_ship(ship.data.get_content());
|
||||
ship_cnt = state.ct.get_ship(ship.get_data().get_content());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -84,22 +84,23 @@ impl GPUState {
|
|||
);
|
||||
|
||||
// Push this object's instance
|
||||
let anim_state = ship.get_anim_state();
|
||||
self.state.push_object_buffer(ObjectInstance {
|
||||
sprite_index: ship_cnt.sprite.get_index(),
|
||||
texture_index: anim_state.texture_index(),
|
||||
texture_fade: anim_state.fade,
|
||||
object_index: idx as u32,
|
||||
});
|
||||
|
||||
let flare = ship.data.get_outfits().get_flare_sprite(state.ct);
|
||||
if {
|
||||
let is_flying = match ship.data.get_state() {
|
||||
let is_flying = match ship.get_data().get_state() {
|
||||
ShipState::Flying { .. }
|
||||
| ShipState::UnLanding { .. }
|
||||
| ShipState::Landing { .. } => true,
|
||||
_ => false,
|
||||
};
|
||||
ship.get_controls().thrust && flare.is_some() && is_flying
|
||||
ship.get_controls().thrust && is_flying
|
||||
} {
|
||||
for engine_point in &ship_cnt.engines {
|
||||
for (engine_point, anim) in ship.iter_engine_anim() {
|
||||
self.state.queue.write_buffer(
|
||||
&self.state.global_uniform.object_buffer,
|
||||
ObjectData::SIZE * self.state.get_object_counter() as u64,
|
||||
|
@ -122,8 +123,10 @@ impl GPUState {
|
|||
}]),
|
||||
);
|
||||
|
||||
let anim_state = anim.get_texture_idx();
|
||||
self.state.push_object_buffer(ObjectInstance {
|
||||
sprite_index: flare.unwrap().get_index(),
|
||||
texture_index: anim_state.texture_index(),
|
||||
texture_fade: anim_state.fade,
|
||||
object_index: self.state.get_object_counter() as u32,
|
||||
});
|
||||
}
|
||||
|
@ -182,9 +185,10 @@ impl GPUState {
|
|||
}]),
|
||||
);
|
||||
|
||||
// Push this object's instance
|
||||
let anim_state = p.get_anim_state();
|
||||
self.state.push_object_buffer(ObjectInstance {
|
||||
sprite_index: proj_cnt.sprite.get_index(),
|
||||
texture_index: anim_state.texture_index(),
|
||||
texture_fade: anim_state.fade,
|
||||
object_index: idx as u32,
|
||||
});
|
||||
}
|
||||
|
@ -235,9 +239,13 @@ impl GPUState {
|
|||
}]),
|
||||
);
|
||||
|
||||
let sprite = state.ct.get_sprite(o.sprite);
|
||||
let texture_a = sprite.get_section(sprite.default_section).frames[0]; // ANIMATE
|
||||
|
||||
// Push this object's instance
|
||||
self.state.push_object_buffer(ObjectInstance {
|
||||
sprite_index: o.sprite.get_index(),
|
||||
texture_index: [texture_a, texture_a],
|
||||
texture_fade: 1.0,
|
||||
object_index: idx as u32,
|
||||
});
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
use anyhow::Result;
|
||||
use bytemuck;
|
||||
use galactica_system::{data::ShipState, phys::PhysSimShipHandle};
|
||||
use galactica_util::constants::PARTICLE_SPRITE_INSTANCE_LIMIT;
|
||||
use glyphon::Resolution;
|
||||
use nalgebra::Point2;
|
||||
|
@ -12,9 +13,9 @@ use crate::{
|
|||
RenderInput,
|
||||
};
|
||||
|
||||
impl super::GPUState {
|
||||
/// Main render function. Draws sprites on a window.
|
||||
pub fn render(&mut self, input: RenderInput) -> Result<(), wgpu::SurfaceError> {
|
||||
impl<'a> super::GPUState {
|
||||
/// Render routines while player is flying
|
||||
fn render_flying(&'a mut self, input: &RenderInput) -> Result<()> {
|
||||
let output = self.surface.get_current_texture()?;
|
||||
let view = output.texture.create_view(&Default::default());
|
||||
|
||||
|
@ -45,45 +46,19 @@ impl super::GPUState {
|
|||
timestamp_writes: None,
|
||||
});
|
||||
|
||||
self.state.frame_reset();
|
||||
let s = input.ct.get_starfield_handle();
|
||||
|
||||
// Update global values
|
||||
self.state.queue.write_buffer(
|
||||
&self.state.global_uniform.data_buffer,
|
||||
0,
|
||||
bytemuck::cast_slice(&[GlobalDataContent {
|
||||
camera_position: input.camera_pos.into(),
|
||||
camera_zoom: [input.camera_zoom, 0.0],
|
||||
camera_zoom_limits: [
|
||||
input.ct.get_config().zoom_min,
|
||||
input.ct.get_config().zoom_max,
|
||||
],
|
||||
window_size: [
|
||||
self.state.window_size.width as f32,
|
||||
self.state.window_size.height as f32,
|
||||
],
|
||||
window_scale: [self.state.window.scale_factor() as f32, 0.0],
|
||||
window_aspect: [self.state.window_aspect, 0.0],
|
||||
starfield_sprite: [s.get_index(), 0],
|
||||
starfield_tile_size: [input.ct.get_config().starfield_size, 0.0],
|
||||
starfield_size_limits: [
|
||||
input.ct.get_config().starfield_min_size,
|
||||
input.ct.get_config().starfield_max_size,
|
||||
],
|
||||
current_time: [input.current_time, 0.0],
|
||||
}]),
|
||||
);
|
||||
|
||||
// Write all new particles to GPU buffer
|
||||
for i in input.particles.iter() {
|
||||
let sprite = input.ct.get_sprite(i.sprite);
|
||||
let texture_a = sprite.get_section(sprite.default_section).frames[0]; // ANIMATE
|
||||
|
||||
self.state.push_particle_buffer(ParticleInstance {
|
||||
position: [i.pos.x, i.pos.y],
|
||||
velocity: i.velocity.into(),
|
||||
angle: i.angle,
|
||||
angvel: i.angvel,
|
||||
size: i.size,
|
||||
sprite_index: i.sprite.get_index(),
|
||||
texture_index: [texture_a, texture_a],
|
||||
texture_fade: 1.0,
|
||||
created: input.current_time,
|
||||
expires: input.current_time + i.lifetime,
|
||||
fade: i.fade,
|
||||
|
@ -134,6 +109,7 @@ impl super::GPUState {
|
|||
0..self.state.get_object_counter(),
|
||||
);
|
||||
|
||||
/*
|
||||
// Particle pipeline
|
||||
self.state
|
||||
.vertex_buffers
|
||||
|
@ -144,7 +120,7 @@ impl super::GPUState {
|
|||
0..SPRITE_INDICES.len() as u32,
|
||||
0,
|
||||
0..PARTICLE_SPRITE_INSTANCE_LIMIT as _,
|
||||
);
|
||||
); */
|
||||
|
||||
// Ui pipeline
|
||||
self.state
|
||||
|
@ -171,7 +147,7 @@ impl super::GPUState {
|
|||
0..self.state.get_radialbar_counter(),
|
||||
);
|
||||
|
||||
let textareas = self.ui.get_textareas(&input, &self.state);
|
||||
let textareas = self.ui.get_textareas_flying(input, &self.state);
|
||||
self.state
|
||||
.text_renderer
|
||||
.prepare(
|
||||
|
@ -193,13 +169,175 @@ impl super::GPUState {
|
|||
.render(&self.state.text_atlas, &mut render_pass)
|
||||
.unwrap();
|
||||
|
||||
// begin_render_pass borrows encoder mutably, so we can't call finish()
|
||||
// without dropping this variable.
|
||||
// begin_render_pass borrows encoder mutably,
|
||||
// so we need to drop it before calling finish.
|
||||
drop(render_pass);
|
||||
|
||||
self.state.queue.submit(iter::once(encoder.finish()));
|
||||
output.present();
|
||||
|
||||
Ok(())
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
/// Render routines while player is landed
|
||||
fn render_landed(&'a mut self, input: &RenderInput) -> Result<()> {
|
||||
let output = self.surface.get_current_texture()?;
|
||||
let view = output.texture.create_view(&Default::default());
|
||||
|
||||
let mut encoder = self
|
||||
.device
|
||||
.create_command_encoder(&wgpu::CommandEncoderDescriptor {
|
||||
label: Some("render encoder"),
|
||||
});
|
||||
|
||||
let mut render_pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
|
||||
label: Some("render pass"),
|
||||
|
||||
color_attachments: &[Some(wgpu::RenderPassColorAttachment {
|
||||
view: &view,
|
||||
resolve_target: None,
|
||||
ops: wgpu::Operations {
|
||||
load: wgpu::LoadOp::Clear(wgpu::Color {
|
||||
r: 0.0,
|
||||
g: 0.0,
|
||||
b: 0.0,
|
||||
a: 1.0,
|
||||
}),
|
||||
store: wgpu::StoreOp::Store,
|
||||
},
|
||||
})],
|
||||
depth_stencil_attachment: None,
|
||||
occlusion_query_set: None,
|
||||
timestamp_writes: None,
|
||||
});
|
||||
|
||||
// Create sprite instances
|
||||
self.ui.draw(&input, &mut self.state);
|
||||
|
||||
// These should match the indices in each shader,
|
||||
// and should each have a corresponding bind group layout.
|
||||
render_pass.set_bind_group(0, &self.texture_array.bind_group, &[]);
|
||||
render_pass.set_bind_group(1, &self.state.global_uniform.bind_group, &[]);
|
||||
|
||||
// Starfield pipeline
|
||||
self.state
|
||||
.vertex_buffers
|
||||
.get_starfield()
|
||||
.set_in_pass(&mut render_pass);
|
||||
render_pass.set_pipeline(&self.starfield_pipeline);
|
||||
render_pass.draw_indexed(
|
||||
0..SPRITE_INDICES.len() as u32,
|
||||
0,
|
||||
0..self.state.get_starfield_counter(),
|
||||
);
|
||||
|
||||
// Ui pipeline
|
||||
self.state
|
||||
.vertex_buffers
|
||||
.get_ui()
|
||||
.set_in_pass(&mut render_pass);
|
||||
render_pass.set_pipeline(&self.ui_pipeline);
|
||||
render_pass.draw_indexed(
|
||||
0..SPRITE_INDICES.len() as u32,
|
||||
0,
|
||||
0..self.state.get_ui_counter(),
|
||||
);
|
||||
|
||||
// Radial progress bars
|
||||
self.state
|
||||
.vertex_buffers
|
||||
.get_radialbar()
|
||||
.set_in_pass(&mut render_pass);
|
||||
render_pass.set_pipeline(&self.radialbar_pipeline);
|
||||
render_pass.draw_indexed(
|
||||
0..SPRITE_INDICES.len() as u32,
|
||||
0,
|
||||
0..self.state.get_radialbar_counter(),
|
||||
);
|
||||
|
||||
let textareas = self.ui.get_textareas_landed(input, &self.state);
|
||||
self.state
|
||||
.text_renderer
|
||||
.prepare(
|
||||
&self.device,
|
||||
&self.state.queue,
|
||||
&mut self.state.text_font_system,
|
||||
&mut self.state.text_atlas,
|
||||
Resolution {
|
||||
width: self.state.window_size.width,
|
||||
height: self.state.window_size.height,
|
||||
},
|
||||
textareas,
|
||||
&mut self.state.text_cache,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
self.state
|
||||
.text_renderer
|
||||
.render(&self.state.text_atlas, &mut render_pass)
|
||||
.unwrap();
|
||||
|
||||
// begin_render_pass borrows encoder mutably,
|
||||
// so we need to drop it before calling finish.
|
||||
drop(render_pass);
|
||||
|
||||
self.state.queue.submit(iter::once(encoder.finish()));
|
||||
output.present();
|
||||
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
/// Main render function. Draws sprites on a window.
|
||||
pub fn render(&mut self, input: RenderInput) -> Result<(), wgpu::SurfaceError> {
|
||||
// Update global values
|
||||
self.state.queue.write_buffer(
|
||||
&self.state.global_uniform.data_buffer,
|
||||
0,
|
||||
bytemuck::cast_slice(&[GlobalDataContent {
|
||||
camera_position: input.camera_pos.into(),
|
||||
camera_zoom: [input.camera_zoom, 0.0],
|
||||
camera_zoom_limits: [
|
||||
input.ct.get_config().zoom_min,
|
||||
input.ct.get_config().zoom_max,
|
||||
],
|
||||
window_size: [
|
||||
self.state.window_size.width as f32,
|
||||
self.state.window_size.height as f32,
|
||||
],
|
||||
window_scale: [self.state.window.scale_factor() as f32, 0.0],
|
||||
window_aspect: [self.state.window_aspect, 0.0],
|
||||
starfield_sprite: [input.ct.get_starfield_texture(), 0],
|
||||
starfield_tile_size: [input.ct.get_config().starfield_size, 0.0],
|
||||
starfield_size_limits: [
|
||||
input.ct.get_config().starfield_min_size,
|
||||
input.ct.get_config().starfield_max_size,
|
||||
],
|
||||
current_time: [input.current_time, 0.0],
|
||||
}]),
|
||||
);
|
||||
|
||||
self.state.frame_reset();
|
||||
|
||||
match input
|
||||
.systemsim
|
||||
.get_ship(&PhysSimShipHandle(input.player.ship.unwrap()))
|
||||
.unwrap()
|
||||
.get_data()
|
||||
.get_state()
|
||||
{
|
||||
ShipState::Collapsing
|
||||
| ShipState::Dead
|
||||
| ShipState::Landing { .. }
|
||||
| ShipState::UnLanding { .. }
|
||||
| ShipState::Flying { .. } => {
|
||||
self.render_flying(&input).unwrap();
|
||||
}
|
||||
|
||||
ShipState::Landed { .. } => {
|
||||
self.render_landed(&input).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,15 +13,6 @@ pub(crate) fn preprocess_shader(
|
|||
);
|
||||
|
||||
// Insert common functions
|
||||
let shader = shader.replace(
|
||||
"// INCLUDE: animate.wgsl",
|
||||
&include_str!(concat!(
|
||||
env!("CARGO_MANIFEST_DIR"),
|
||||
"/shaders/include/",
|
||||
"animate.wgsl"
|
||||
)),
|
||||
);
|
||||
|
||||
let shader = shader.replace(
|
||||
"// INCLUDE: anchor.wgsl",
|
||||
&include_str!(concat!(
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use crate::globaluniform::{AtlasArray, AtlasImageLocation, SpriteData, SpriteDataArray};
|
||||
use crate::globaluniform::{AtlasArray, AtlasImageLocation};
|
||||
use anyhow::Result;
|
||||
use bytemuck::Zeroable;
|
||||
use galactica_content::Content;
|
||||
|
@ -84,8 +84,7 @@ pub struct Texture {
|
|||
pub struct TextureArray {
|
||||
pub bind_group: wgpu::BindGroup,
|
||||
pub bind_group_layout: BindGroupLayout,
|
||||
pub image_locations: AtlasArray,
|
||||
pub sprite_data: SpriteDataArray,
|
||||
pub texture_atlas: AtlasArray,
|
||||
}
|
||||
|
||||
impl TextureArray {
|
||||
|
@ -93,49 +92,36 @@ impl TextureArray {
|
|||
// Load all textures
|
||||
let mut texture_data = Vec::new();
|
||||
|
||||
for a in ct.atlas_files() {
|
||||
println!("opening {a}");
|
||||
for file in ct.atlas_files() {
|
||||
println!("opening {file}");
|
||||
let p = Path::new(ASSET_CACHE);
|
||||
let mut f = File::open(p.join(a))?;
|
||||
let mut f = File::open(p.join(file))?;
|
||||
let mut bytes = Vec::new();
|
||||
f.read_to_end(&mut bytes)?;
|
||||
texture_data.push(RawTexture::from_bytes(
|
||||
&device,
|
||||
&queue,
|
||||
&bytes,
|
||||
&format!("Atlas `{a}`"),
|
||||
&format!("Atlas `{file}`"),
|
||||
)?);
|
||||
}
|
||||
|
||||
let mut image_locations = AtlasArray::zeroed();
|
||||
let mut sprite_data = SpriteDataArray::zeroed();
|
||||
|
||||
println!("sending to gpu");
|
||||
let mut image_counter = 0;
|
||||
let mut sprite_counter = 0;
|
||||
for t in &ct.sprites {
|
||||
sprite_data.data[sprite_counter] = SpriteData {
|
||||
frame_count: t.frames.len() as u32,
|
||||
repeatmode: t.repeat.as_int(),
|
||||
aspect: t.aspect,
|
||||
frame_duration: t.frame_duration,
|
||||
first_frame: image_counter,
|
||||
_padding: Default::default(),
|
||||
};
|
||||
sprite_counter += 1;
|
||||
|
||||
// Insert texture location data
|
||||
for path in &t.frames {
|
||||
let image = ct.get_image(&path);
|
||||
image_locations.data[image_counter as usize] = AtlasImageLocation {
|
||||
xpos: image.x,
|
||||
ypos: image.y,
|
||||
width: image.w,
|
||||
height: image.h,
|
||||
atlas_texture: image.atlas,
|
||||
_padding: Default::default(),
|
||||
};
|
||||
image_counter += 1;
|
||||
for sprite in &ct.sprites {
|
||||
for section in sprite.iter_sections() {
|
||||
for idx in §ion.frames {
|
||||
let image = ct.get_image(*idx);
|
||||
image_locations.data[*idx as usize] = AtlasImageLocation {
|
||||
xpos: image.x,
|
||||
ypos: image.y,
|
||||
width: image.w,
|
||||
height: image.h,
|
||||
atlas_texture: image.atlas,
|
||||
_padding: Default::default(),
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -192,8 +178,7 @@ impl TextureArray {
|
|||
return Ok(Self {
|
||||
bind_group,
|
||||
bind_group_layout,
|
||||
image_locations,
|
||||
sprite_data,
|
||||
texture_atlas: image_locations,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,7 +32,7 @@ impl UiManager {
|
|||
|
||||
self.fps.update(input, state);
|
||||
|
||||
match ship.data.get_state() {
|
||||
match ship.get_data().get_state() {
|
||||
ShipState::Collapsing
|
||||
| ShipState::Dead
|
||||
| ShipState::Flying { .. }
|
||||
|
@ -48,23 +48,22 @@ impl UiManager {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn get_textareas(&self, input: &RenderInput, state: &RenderState) -> Vec<TextArea> {
|
||||
/// Textareas to show while player is flying
|
||||
pub fn get_textareas_flying(
|
||||
&self,
|
||||
_input: &RenderInput,
|
||||
_state: &RenderState,
|
||||
) -> Vec<TextArea> {
|
||||
let mut v = Vec::with_capacity(5);
|
||||
v.push(self.fps.get_textarea());
|
||||
|
||||
let ship_handle = input.player.ship.unwrap();
|
||||
let ship = input
|
||||
.systemsim
|
||||
.get_ship(&PhysSimShipHandle(ship_handle))
|
||||
.unwrap();
|
||||
match ship.data.get_state() {
|
||||
ShipState::Collapsing
|
||||
| ShipState::Dead
|
||||
| ShipState::Flying { .. }
|
||||
| ShipState::Landing { .. }
|
||||
| ShipState::UnLanding { .. } => v.push(self.fps.get_textarea()),
|
||||
return v;
|
||||
}
|
||||
|
||||
ShipState::Landed { .. } => v.extend(self.planet.get_textarea(input, state)),
|
||||
};
|
||||
/// Textareas to show when player is landed
|
||||
pub fn get_textareas_landed(&self, input: &RenderInput, state: &RenderState) -> Vec<TextArea> {
|
||||
let mut v = Vec::with_capacity(5);
|
||||
v.extend(self.planet.get_textarea(input, state));
|
||||
|
||||
return v;
|
||||
}
|
||||
|
|
|
@ -34,7 +34,7 @@ impl Radar {
|
|||
))
|
||||
.unwrap();
|
||||
|
||||
match player_ship.data.get_state() {
|
||||
match player_ship.get_data().get_state() {
|
||||
ShipState::Dead => {}
|
||||
|
||||
ShipState::Landed { target } => {
|
||||
|
@ -60,6 +60,9 @@ impl Radar {
|
|||
let ship_sprite = input.ct.get_sprite_handle("ui::shipblip");
|
||||
let arrow_sprite = input.ct.get_sprite_handle("ui::centerarrow");
|
||||
|
||||
let sprite = input.ct.get_sprite(input.ct.get_sprite_handle("ui::radar"));
|
||||
let texture_a = sprite.get_section(sprite.default_section).frames[0]; // ANIMATE
|
||||
|
||||
// Push this object's instance
|
||||
state.push_ui_buffer(UiInstance {
|
||||
anchor: PositionAnchor::NwNw.to_int(),
|
||||
|
@ -67,7 +70,8 @@ impl Radar {
|
|||
angle: 0.0,
|
||||
size: radar_size,
|
||||
color: [1.0, 1.0, 1.0, 1.0],
|
||||
sprite_index: input.ct.get_sprite_handle("ui::radar").get_index(),
|
||||
texture_index: [texture_a, texture_a],
|
||||
texture_fade: 1.0,
|
||||
mask_index: [0, 0],
|
||||
});
|
||||
|
||||
|
@ -87,6 +91,9 @@ impl Radar {
|
|||
continue;
|
||||
}
|
||||
|
||||
let sprite = input.ct.get_sprite(planet_sprite);
|
||||
let texture_a = sprite.get_section(sprite.default_section).frames[0]; // ANIMATE
|
||||
|
||||
// Push this object's instance
|
||||
state.push_ui_buffer(UiInstance {
|
||||
anchor: PositionAnchor::NwC.to_int(),
|
||||
|
@ -96,7 +103,8 @@ impl Radar {
|
|||
angle: o.angle,
|
||||
size,
|
||||
color: [0.5, 0.5, 0.5, 1.0],
|
||||
sprite_index: planet_sprite.get_index(),
|
||||
texture_index: [texture_a, texture_a],
|
||||
texture_fade: 1.0,
|
||||
mask_index: [0, 0],
|
||||
})
|
||||
};
|
||||
|
@ -104,8 +112,8 @@ impl Radar {
|
|||
|
||||
// Draw ships
|
||||
for (s, r) in input.systemsim.iter_ship_body() {
|
||||
let ship = input.ct.get_ship(s.data.get_content());
|
||||
let (color, z_scale) = match s.data.get_state() {
|
||||
let ship = input.ct.get_ship(s.get_data().get_content());
|
||||
let (color, z_scale) = match s.get_data().get_state() {
|
||||
ShipState::Dead | ShipState::Landed { .. } => {
|
||||
continue;
|
||||
}
|
||||
|
@ -121,7 +129,7 @@ impl Radar {
|
|||
([0.2, 0.2, 0.2, 1.0], 1.0)
|
||||
}
|
||||
ShipState::Flying { .. } => {
|
||||
let c = input.ct.get_faction(s.data.get_faction()).color;
|
||||
let c = input.ct.get_faction(s.get_data().get_faction()).color;
|
||||
([c[0], c[1], c[2], 1.0], 1.0)
|
||||
}
|
||||
};
|
||||
|
@ -144,13 +152,17 @@ impl Radar {
|
|||
let position = Point2::new(radar_size / 2.0 + 10.0, radar_size / -2.0 - 10.0)
|
||||
+ (d * (radar_size / 2.0));
|
||||
|
||||
let sprite = input.ct.get_sprite(ship_sprite);
|
||||
let texture_a = sprite.get_section(sprite.default_section).frames[0]; // ANIMATE
|
||||
|
||||
state.push_ui_buffer(UiInstance {
|
||||
anchor: PositionAnchor::NwC.to_int(),
|
||||
position: position.into(),
|
||||
angle: r.rotation().angle(),
|
||||
size,
|
||||
color,
|
||||
sprite_index: ship_sprite.get_index(),
|
||||
texture_index: [texture_a, texture_a],
|
||||
texture_fade: 1.0,
|
||||
mask_index: [0, 0],
|
||||
});
|
||||
}
|
||||
|
@ -168,6 +180,9 @@ impl Radar {
|
|||
let sprite = input.ct.get_sprite_handle("ui::radarframe");
|
||||
let size = 7.0f32.min((0.8 - m) * 70.0);
|
||||
|
||||
let sprite = input.ct.get_sprite(sprite);
|
||||
let texture_a = sprite.get_section(sprite.default_section).frames[0]; // ANIMATE
|
||||
|
||||
state.push_ui_buffer(UiInstance {
|
||||
anchor: PositionAnchor::NwNw.to_int(),
|
||||
position: Point2::new(
|
||||
|
@ -178,7 +193,8 @@ impl Radar {
|
|||
angle: to_radians(90.0),
|
||||
size,
|
||||
color,
|
||||
sprite_index: sprite.get_index(),
|
||||
texture_index: [texture_a, texture_a],
|
||||
texture_fade: 1.0,
|
||||
mask_index: [0, 0],
|
||||
});
|
||||
|
||||
|
@ -192,7 +208,8 @@ impl Radar {
|
|||
angle: to_radians(180.0),
|
||||
size,
|
||||
color,
|
||||
sprite_index: sprite.get_index(),
|
||||
texture_index: [texture_a, texture_a],
|
||||
texture_fade: 1.0,
|
||||
mask_index: [0, 0],
|
||||
});
|
||||
|
||||
|
@ -206,7 +223,8 @@ impl Radar {
|
|||
angle: to_radians(270.0),
|
||||
size,
|
||||
color,
|
||||
sprite_index: sprite.get_index(),
|
||||
texture_index: [texture_a, texture_a],
|
||||
texture_fade: 1.0,
|
||||
mask_index: [0, 0],
|
||||
});
|
||||
|
||||
|
@ -220,7 +238,8 @@ impl Radar {
|
|||
angle: to_radians(0.0),
|
||||
size,
|
||||
color,
|
||||
sprite_index: sprite.get_index(),
|
||||
texture_index: [texture_a, texture_a],
|
||||
texture_fade: 1.0,
|
||||
mask_index: [0, 0],
|
||||
});
|
||||
}
|
||||
|
@ -233,13 +252,17 @@ impl Radar {
|
|||
let position = Point2::new(10.0 + (radar_size / 2.0), -10.0 - (radar_size / 2.0))
|
||||
+ Rotation2::new(angle) * Vector2::new(0.915 * (radar_size / 2.0), 0.0);
|
||||
|
||||
let sprite = input.ct.get_sprite(arrow_sprite);
|
||||
let texture_a = sprite.get_section(sprite.default_section).frames[0]; // ANIMATE
|
||||
|
||||
state.push_ui_buffer(UiInstance {
|
||||
anchor: PositionAnchor::NwC.to_int(),
|
||||
position: position.into(),
|
||||
angle,
|
||||
size: 10.0,
|
||||
color: [1.0, 1.0, 1.0, 1f32.min((m - 200.0) / 400.0)],
|
||||
sprite_index: arrow_sprite.get_index(),
|
||||
texture_index: [texture_a, texture_a],
|
||||
texture_fade: 1.0,
|
||||
mask_index: [0, 0],
|
||||
});
|
||||
}
|
||||
|
|
|
@ -26,32 +26,38 @@ impl Status {
|
|||
))
|
||||
.unwrap();
|
||||
|
||||
match player_ship.data.get_state() {
|
||||
match player_ship.get_data().get_state() {
|
||||
ShipState::Dead => {
|
||||
current_shields = 0.0;
|
||||
current_hull = 0.0;
|
||||
max_shields = player_ship.data.get_outfits().get_shield_strength();
|
||||
max_hull = input.ct.get_ship(player_ship.data.get_content()).hull;
|
||||
max_shields = player_ship.get_data().get_outfits().get_shield_strength();
|
||||
max_hull = input.ct.get_ship(player_ship.get_data().get_content()).hull;
|
||||
}
|
||||
ShipState::UnLanding { .. }
|
||||
| ShipState::Landing { .. }
|
||||
| ShipState::Landed { .. }
|
||||
| ShipState::Collapsing { .. }
|
||||
| ShipState::Flying { .. } => {
|
||||
current_shields = player_ship.data.get_shields();
|
||||
current_hull = player_ship.data.get_hull();
|
||||
max_shields = player_ship.data.get_outfits().get_shield_strength();
|
||||
max_hull = input.ct.get_ship(player_ship.data.get_content()).hull;
|
||||
current_shields = player_ship.get_data().get_shields();
|
||||
current_hull = player_ship.get_data().get_hull();
|
||||
max_shields = player_ship.get_data().get_outfits().get_shield_strength();
|
||||
max_hull = input.ct.get_ship(player_ship.get_data().get_content()).hull;
|
||||
}
|
||||
}
|
||||
|
||||
let sprite = input
|
||||
.ct
|
||||
.get_sprite(input.ct.get_sprite_handle("ui::status"));
|
||||
let texture_a = sprite.get_section(sprite.default_section).frames[0]; // ANIMATE
|
||||
|
||||
state.push_ui_buffer(UiInstance {
|
||||
anchor: PositionAnchor::NeNe.to_int(),
|
||||
position: [-10.0, -10.0],
|
||||
angle: 0.0,
|
||||
size: 200.0,
|
||||
color: [1.0, 1.0, 1.0, 1.0],
|
||||
sprite_index: input.ct.get_sprite_handle("ui::status").get_index(),
|
||||
texture_index: [texture_a, texture_a],
|
||||
texture_fade: 1.0,
|
||||
mask_index: [0, 0],
|
||||
});
|
||||
|
||||
|
|
|
@ -85,7 +85,13 @@ impl BufferObject for StarfieldInstance {
|
|||
#[derive(Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)]
|
||||
pub struct ObjectInstance {
|
||||
/// What texture to use for this instance
|
||||
pub sprite_index: u32,
|
||||
/// Result will be a faded mix of the two textures
|
||||
/// given here. Only the first will be shown if fade = 0.0,
|
||||
/// and only the second if fade = 1.0
|
||||
pub texture_index: [u32; 2],
|
||||
/// Fade parameter for texture index
|
||||
/// Must be between 0 and 1.
|
||||
pub texture_fade: f32,
|
||||
|
||||
/// Which object this instance is for
|
||||
pub object_index: u32,
|
||||
|
@ -100,16 +106,22 @@ impl BufferObject for ObjectInstance {
|
|||
// instance when the shader starts processing a new instance
|
||||
step_mode: wgpu::VertexStepMode::Instance,
|
||||
attributes: &[
|
||||
// Sprite
|
||||
// Texture
|
||||
wgpu::VertexAttribute {
|
||||
offset: 0,
|
||||
shader_location: 2,
|
||||
format: wgpu::VertexFormat::Uint32,
|
||||
format: wgpu::VertexFormat::Uint32x2,
|
||||
},
|
||||
// Texture fade
|
||||
wgpu::VertexAttribute {
|
||||
offset: mem::size_of::<[f32; 2]>() as wgpu::BufferAddress,
|
||||
shader_location: 3,
|
||||
format: wgpu::VertexFormat::Float32,
|
||||
},
|
||||
// Object
|
||||
wgpu::VertexAttribute {
|
||||
offset: mem::size_of::<[f32; 1]>() as wgpu::BufferAddress,
|
||||
shader_location: 3,
|
||||
offset: mem::size_of::<[f32; 3]>() as wgpu::BufferAddress,
|
||||
shader_location: 4,
|
||||
format: wgpu::VertexFormat::Uint32,
|
||||
},
|
||||
],
|
||||
|
@ -138,12 +150,14 @@ pub struct UiInstance {
|
|||
/// Fill this array with ones if no recoloring should be done.
|
||||
pub color: [f32; 4],
|
||||
|
||||
/// What texture to use for this sprite
|
||||
pub sprite_index: u32,
|
||||
/// What texture to use for this instance
|
||||
pub texture_index: [u32; 2],
|
||||
/// Fade parameter between textures
|
||||
pub texture_fade: f32,
|
||||
|
||||
/// What mask to use for this sprite
|
||||
/// What texture to use to mask this instance
|
||||
/// If the first element is not 1, no mask is used.
|
||||
/// Second element is sprite index of mask.
|
||||
/// Second element is a texture index
|
||||
pub mask_index: [u32; 2],
|
||||
}
|
||||
|
||||
|
@ -186,16 +200,22 @@ impl BufferObject for UiInstance {
|
|||
shader_location: 6,
|
||||
format: wgpu::VertexFormat::Float32x4,
|
||||
},
|
||||
// Sprite
|
||||
// Texture
|
||||
wgpu::VertexAttribute {
|
||||
offset: mem::size_of::<[f32; 9]>() as wgpu::BufferAddress,
|
||||
shader_location: 7,
|
||||
format: wgpu::VertexFormat::Uint32,
|
||||
format: wgpu::VertexFormat::Uint32x2,
|
||||
},
|
||||
// Texture fade
|
||||
wgpu::VertexAttribute {
|
||||
offset: mem::size_of::<[f32; 11]>() as wgpu::BufferAddress,
|
||||
shader_location: 8,
|
||||
format: wgpu::VertexFormat::Float32,
|
||||
},
|
||||
// Mask
|
||||
wgpu::VertexAttribute {
|
||||
offset: mem::size_of::<[f32; 10]>() as wgpu::BufferAddress,
|
||||
shader_location: 8,
|
||||
offset: mem::size_of::<[f32; 12]>() as wgpu::BufferAddress,
|
||||
shader_location: 9,
|
||||
format: wgpu::VertexFormat::Uint32x2,
|
||||
},
|
||||
],
|
||||
|
@ -232,8 +252,10 @@ pub struct ParticleInstance {
|
|||
/// Fade this particle out over this many seconds as it expires
|
||||
pub fade: f32,
|
||||
|
||||
/// What sprite to use for this particle
|
||||
pub sprite_index: u32,
|
||||
/// What texture to use for this particle
|
||||
pub texture_index: [u32; 2],
|
||||
/// Fade parameter for texture index
|
||||
pub texture_fade: f32,
|
||||
}
|
||||
|
||||
impl BufferObject for ParticleInstance {
|
||||
|
@ -290,11 +312,17 @@ impl BufferObject for ParticleInstance {
|
|||
shader_location: 9,
|
||||
format: wgpu::VertexFormat::Float32,
|
||||
},
|
||||
// Sprite
|
||||
// Texture
|
||||
wgpu::VertexAttribute {
|
||||
offset: mem::size_of::<[f32; 10]>() as wgpu::BufferAddress,
|
||||
shader_location: 10,
|
||||
format: wgpu::VertexFormat::Uint32,
|
||||
format: wgpu::VertexFormat::Uint32x2,
|
||||
},
|
||||
// Texture fade
|
||||
wgpu::VertexAttribute {
|
||||
offset: mem::size_of::<[f32; 12]>() as wgpu::BufferAddress,
|
||||
shader_location: 11,
|
||||
format: wgpu::VertexFormat::Float32,
|
||||
},
|
||||
],
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue