Compare commits
No commits in common. "381dd4a38359bb178a0b918aa6bf9bf0a6cdedeb" and "a85a0f818873b9968a863a6f849d35deccf6b37e" have entirely different histories.
381dd4a383
...
a85a0f8188
2
TODO.md
2
TODO.md
|
@ -4,7 +4,7 @@
|
||||||
- Sound system
|
- Sound system
|
||||||
- Particles, impact effects
|
- Particles, impact effects
|
||||||
- Debris on ship death
|
- Debris on ship death
|
||||||
- Radar: ship size, planets and suns
|
- Radar: dynamic colors, size, planets and suns
|
||||||
|
|
||||||
----------------------------------
|
----------------------------------
|
||||||
|
|
||||||
|
|
2
assets
2
assets
|
@ -1 +1 @@
|
||||||
Subproject commit 62fd7fc297a2631691b588b898694e220d58cf78
|
Subproject commit 91377416617d049acec68bb5a17647dcac7acd0e
|
|
@ -1,9 +1,7 @@
|
||||||
[faction."player"]
|
[faction."player"]
|
||||||
display_name = "Player"
|
display_name = "Player"
|
||||||
relationship.enemy = "hostile"
|
relationship.enemy = "hostile"
|
||||||
color = [0.0, 1.0, 0.0]
|
|
||||||
|
|
||||||
[faction."enemy"]
|
[faction."enemy"]
|
||||||
display_name = "Enemy"
|
display_name = "Enemy"
|
||||||
relationship.player = "hostile"
|
relationship.player = "hostile"
|
||||||
color = [1.0, 0.0, 0.0]
|
|
||||||
|
|
|
@ -44,11 +44,8 @@ pub const CONTENT_ROOT: &'static str = "./content";
|
||||||
/// Root directory of game textures
|
/// Root directory of game textures
|
||||||
pub const TEXTURE_ROOT: &'static str = "./assets/render";
|
pub const TEXTURE_ROOT: &'static str = "./assets/render";
|
||||||
|
|
||||||
/// We can draw at most this many object sprites on the screen.
|
/// We can draw at most this many sprites on the screen.
|
||||||
pub const OBJECT_SPRITE_INSTANCE_LIMIT: u64 = 500;
|
pub const SPRITE_INSTANCE_LIMIT: u64 = 500;
|
||||||
|
|
||||||
/// We can draw at most this many ui sprites on the screen.
|
|
||||||
pub const UI_SPRITE_INSTANCE_LIMIT: u64 = 100;
|
|
||||||
|
|
||||||
/// 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_INSTANCE_LIMIT: u64 = STARFIELD_COUNT * 24;
|
||||||
|
|
|
@ -14,7 +14,6 @@ pub(crate) mod syntax {
|
||||||
#[derive(Debug, Deserialize)]
|
#[derive(Debug, Deserialize)]
|
||||||
pub struct Faction {
|
pub struct Faction {
|
||||||
pub display_name: String,
|
pub display_name: String,
|
||||||
pub color: [f32; 3],
|
|
||||||
pub relationship: HashMap<String, super::Relationship>,
|
pub relationship: HashMap<String, super::Relationship>,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -46,10 +45,6 @@ pub struct Faction {
|
||||||
/// The name of this faction
|
/// The name of this faction
|
||||||
pub name: String,
|
pub name: String,
|
||||||
|
|
||||||
/// This faction's color.
|
|
||||||
/// Format is RGB, with each color between 0 and 1.
|
|
||||||
pub color: [f32; 3],
|
|
||||||
|
|
||||||
/// This faction's handle
|
/// This faction's handle
|
||||||
pub handle: FactionHandle,
|
pub handle: FactionHandle,
|
||||||
|
|
||||||
|
@ -103,7 +98,6 @@ impl crate::Build for Faction {
|
||||||
name: faction_name.to_owned(),
|
name: faction_name.to_owned(),
|
||||||
handle: h,
|
handle: h,
|
||||||
relationships,
|
relationships,
|
||||||
color: faction.color,
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,75 +0,0 @@
|
||||||
struct InstanceInput {
|
|
||||||
@location(2) transform_matrix_0: vec4<f32>,
|
|
||||||
@location(3) transform_matrix_1: vec4<f32>,
|
|
||||||
@location(4) transform_matrix_2: vec4<f32>,
|
|
||||||
@location(5) transform_matrix_3: vec4<f32>,
|
|
||||||
@location(6) color_transform: vec4<f32>,
|
|
||||||
@location(7) texture_idx: u32,
|
|
||||||
};
|
|
||||||
|
|
||||||
struct VertexInput {
|
|
||||||
@location(0) position: vec3<f32>,
|
|
||||||
@location(1) texture_coords: vec2<f32>,
|
|
||||||
}
|
|
||||||
|
|
||||||
struct VertexOutput {
|
|
||||||
@builtin(position) position: vec4<f32>,
|
|
||||||
@location(0) texture_coords: vec2<f32>,
|
|
||||||
@location(1) index: u32,
|
|
||||||
@location(2) color_transform: vec4<f32>,
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@group(1) @binding(0)
|
|
||||||
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_texture: vec2<u32>,
|
|
||||||
starfield_tile_size: vec2<f32>,
|
|
||||||
starfield_size_limits: vec2<f32>,
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
@group(0) @binding(0)
|
|
||||||
var texture_array: binding_array<texture_2d<f32>>;
|
|
||||||
@group(0) @binding(1)
|
|
||||||
var sampler_array: binding_array<sampler>;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@vertex
|
|
||||||
fn vertex_main(
|
|
||||||
vertex: VertexInput,
|
|
||||||
instance: InstanceInput,
|
|
||||||
) -> VertexOutput {
|
|
||||||
|
|
||||||
let transform = mat4x4<f32>(
|
|
||||||
instance.transform_matrix_0,
|
|
||||||
instance.transform_matrix_1,
|
|
||||||
instance.transform_matrix_2,
|
|
||||||
instance.transform_matrix_3,
|
|
||||||
);
|
|
||||||
|
|
||||||
var out: VertexOutput;
|
|
||||||
out.position = transform * vec4<f32>(vertex.position, 1.0);
|
|
||||||
out.texture_coords = vertex.texture_coords;
|
|
||||||
out.index = instance.texture_idx;
|
|
||||||
out.color_transform = instance.color_transform;
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@fragment
|
|
||||||
fn fragment_main(in: VertexOutput) -> @location(0) vec4<f32> {
|
|
||||||
return textureSampleLevel(
|
|
||||||
texture_array[in.index],
|
|
||||||
sampler_array[0],
|
|
||||||
in.texture_coords,
|
|
||||||
0.0
|
|
||||||
).rgba * in.color_transform;
|
|
||||||
}
|
|
|
@ -15,7 +15,7 @@ use crate::{
|
||||||
texturearray::TextureArray,
|
texturearray::TextureArray,
|
||||||
vertexbuffer::{
|
vertexbuffer::{
|
||||||
consts::{SPRITE_INDICES, SPRITE_VERTICES},
|
consts::{SPRITE_INDICES, SPRITE_VERTICES},
|
||||||
types::{ObjectInstance, StarfieldInstance, TexturedVertex, UiInstance},
|
types::{SpriteInstance, StarfieldInstance, TexturedVertex},
|
||||||
VertexBuffer,
|
VertexBuffer,
|
||||||
},
|
},
|
||||||
ObjectSprite, UiSprite, OPENGL_TO_WGPU_MATRIX,
|
ObjectSprite, UiSprite, OPENGL_TO_WGPU_MATRIX,
|
||||||
|
@ -37,9 +37,8 @@ pub struct GPUState {
|
||||||
|
|
||||||
window_aspect: f32,
|
window_aspect: f32,
|
||||||
|
|
||||||
object_pipeline: wgpu::RenderPipeline,
|
sprite_pipeline: wgpu::RenderPipeline,
|
||||||
starfield_pipeline: wgpu::RenderPipeline,
|
starfield_pipeline: wgpu::RenderPipeline,
|
||||||
ui_pipeline: wgpu::RenderPipeline,
|
|
||||||
|
|
||||||
starfield: Starfield,
|
starfield: Starfield,
|
||||||
texture_array: TextureArray,
|
texture_array: TextureArray,
|
||||||
|
@ -48,9 +47,8 @@ pub struct GPUState {
|
||||||
}
|
}
|
||||||
|
|
||||||
struct VertexBuffers {
|
struct VertexBuffers {
|
||||||
object: Rc<VertexBuffer>,
|
sprite: Rc<VertexBuffer>,
|
||||||
starfield: Rc<VertexBuffer>,
|
starfield: Rc<VertexBuffer>,
|
||||||
ui: Rc<VertexBuffer>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl GPUState {
|
impl GPUState {
|
||||||
|
@ -119,12 +117,12 @@ impl GPUState {
|
||||||
}
|
}
|
||||||
|
|
||||||
let vertex_buffers = VertexBuffers {
|
let vertex_buffers = VertexBuffers {
|
||||||
object: Rc::new(VertexBuffer::new::<TexturedVertex, ObjectInstance>(
|
sprite: Rc::new(VertexBuffer::new::<TexturedVertex, SpriteInstance>(
|
||||||
"objecte",
|
"sprite",
|
||||||
&device,
|
&device,
|
||||||
Some(SPRITE_VERTICES),
|
Some(SPRITE_VERTICES),
|
||||||
Some(SPRITE_INDICES),
|
Some(SPRITE_INDICES),
|
||||||
galactica_constants::OBJECT_SPRITE_INSTANCE_LIMIT,
|
galactica_constants::SPRITE_INSTANCE_LIMIT,
|
||||||
)),
|
)),
|
||||||
|
|
||||||
starfield: Rc::new(VertexBuffer::new::<TexturedVertex, StarfieldInstance>(
|
starfield: Rc::new(VertexBuffer::new::<TexturedVertex, StarfieldInstance>(
|
||||||
|
@ -132,15 +130,7 @@ impl GPUState {
|
||||||
&device,
|
&device,
|
||||||
Some(SPRITE_VERTICES),
|
Some(SPRITE_VERTICES),
|
||||||
Some(SPRITE_INDICES),
|
Some(SPRITE_INDICES),
|
||||||
galactica_constants::STARFIELD_SPRITE_INSTANCE_LIMIT,
|
galactica_constants::STARFIELD_INSTANCE_LIMIT,
|
||||||
)),
|
|
||||||
|
|
||||||
ui: Rc::new(VertexBuffer::new::<TexturedVertex, UiInstance>(
|
|
||||||
"ui",
|
|
||||||
&device,
|
|
||||||
Some(SPRITE_VERTICES),
|
|
||||||
Some(SPRITE_INDICES),
|
|
||||||
galactica_constants::UI_SPRITE_INSTANCE_LIMIT,
|
|
||||||
)),
|
)),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -155,15 +145,15 @@ impl GPUState {
|
||||||
];
|
];
|
||||||
|
|
||||||
// Create render pipelines
|
// Create render pipelines
|
||||||
let object_pipeline = PipelineBuilder::new("object", &device)
|
let sprite_pipeline = PipelineBuilder::new("sprite", &device)
|
||||||
.set_shader(include_str!(concat!(
|
.set_shader(include_str!(concat!(
|
||||||
env!("CARGO_MANIFEST_DIR"),
|
env!("CARGO_MANIFEST_DIR"),
|
||||||
"/shaders/",
|
"/shaders/",
|
||||||
"object.wgsl"
|
"sprite.wgsl"
|
||||||
)))
|
)))
|
||||||
.set_format(config.format)
|
.set_format(config.format)
|
||||||
.set_triangle(true)
|
.set_triangle(true)
|
||||||
.set_vertex_buffer(&vertex_buffers.object)
|
.set_vertex_buffer(&vertex_buffers.sprite)
|
||||||
.set_bind_group_layouts(bind_group_layouts)
|
.set_bind_group_layouts(bind_group_layouts)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
|
@ -179,18 +169,6 @@ impl GPUState {
|
||||||
.set_bind_group_layouts(bind_group_layouts)
|
.set_bind_group_layouts(bind_group_layouts)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
let ui_pipeline = PipelineBuilder::new("ui", &device)
|
|
||||||
.set_shader(include_str!(concat!(
|
|
||||||
env!("CARGO_MANIFEST_DIR"),
|
|
||||||
"/shaders/",
|
|
||||||
"ui.wgsl"
|
|
||||||
)))
|
|
||||||
.set_format(config.format)
|
|
||||||
.set_triangle(true)
|
|
||||||
.set_vertex_buffer(&vertex_buffers.ui)
|
|
||||||
.set_bind_group_layouts(bind_group_layouts)
|
|
||||||
.build();
|
|
||||||
|
|
||||||
let mut starfield = Starfield::new();
|
let mut starfield = Starfield::new();
|
||||||
starfield.regenerate();
|
starfield.regenerate();
|
||||||
|
|
||||||
|
@ -204,9 +182,8 @@ impl GPUState {
|
||||||
window_size,
|
window_size,
|
||||||
window_aspect,
|
window_aspect,
|
||||||
|
|
||||||
object_pipeline,
|
sprite_pipeline,
|
||||||
starfield_pipeline,
|
starfield_pipeline,
|
||||||
ui_pipeline,
|
|
||||||
|
|
||||||
starfield,
|
starfield,
|
||||||
texture_array,
|
texture_array,
|
||||||
|
@ -234,13 +211,13 @@ impl GPUState {
|
||||||
self.update_starfield_buffer()
|
self.update_starfield_buffer()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a ObjectInstance for an object and add it to `instances`.
|
/// Create a SpriteInstance for an object and add it to `instances`.
|
||||||
/// Also handles child sprites.
|
/// Also handles child sprites.
|
||||||
fn push_object_sprite(
|
fn push_object_sprite(
|
||||||
&self,
|
&self,
|
||||||
camera_zoom: f32,
|
camera_zoom: f32,
|
||||||
camera_pos: Point2<f32>,
|
camera_pos: Point2<f32>,
|
||||||
instances: &mut Vec<ObjectInstance>,
|
instances: &mut Vec<SpriteInstance>,
|
||||||
clip_ne: Point2<f32>,
|
clip_ne: Point2<f32>,
|
||||||
clip_sw: Point2<f32>,
|
clip_sw: Point2<f32>,
|
||||||
s: &ObjectSprite,
|
s: &ObjectSprite,
|
||||||
|
@ -314,7 +291,7 @@ impl GPUState {
|
||||||
let t =
|
let t =
|
||||||
OPENGL_TO_WGPU_MATRIX * translate * screen_aspect * rotate * sprite_aspect_and_scale;
|
OPENGL_TO_WGPU_MATRIX * translate * screen_aspect * rotate * sprite_aspect_and_scale;
|
||||||
|
|
||||||
instances.push(ObjectInstance {
|
instances.push(SpriteInstance {
|
||||||
transform: t.into(),
|
transform: t.into(),
|
||||||
texture_index: texture.index,
|
texture_index: texture.index,
|
||||||
});
|
});
|
||||||
|
@ -332,7 +309,7 @@ impl GPUState {
|
||||||
fn push_object_subsprite(
|
fn push_object_subsprite(
|
||||||
&self,
|
&self,
|
||||||
camera_zoom: f32,
|
camera_zoom: f32,
|
||||||
instances: &mut Vec<ObjectInstance>,
|
instances: &mut Vec<SpriteInstance>,
|
||||||
s: &ObjectSubSprite,
|
s: &ObjectSubSprite,
|
||||||
parent_pos: Point2<f32>,
|
parent_pos: Point2<f32>,
|
||||||
parent_angle: Deg<f32>,
|
parent_angle: Deg<f32>,
|
||||||
|
@ -364,14 +341,14 @@ impl GPUState {
|
||||||
* protate * translate
|
* protate * translate
|
||||||
* rotate * sprite_aspect_and_scale;
|
* rotate * sprite_aspect_and_scale;
|
||||||
|
|
||||||
instances.push(ObjectInstance {
|
instances.push(SpriteInstance {
|
||||||
transform: t.into(),
|
transform: t.into(),
|
||||||
texture_index: texture.index,
|
texture_index: texture.index,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a ObjectInstance for a ui sprite and add it to `instances`
|
/// Create a SpriteInstance for a ui sprite and add it to `instances`
|
||||||
fn push_ui_sprite(&self, instances: &mut Vec<UiInstance>, s: &UiSprite) {
|
fn push_ui_sprite(&self, instances: &mut Vec<SpriteInstance>, s: &UiSprite) {
|
||||||
let logical_size: LogicalSize<f32> =
|
let logical_size: LogicalSize<f32> =
|
||||||
self.window_size.to_logical(self.window.scale_factor());
|
self.window_size.to_logical(self.window.scale_factor());
|
||||||
|
|
||||||
|
@ -417,24 +394,24 @@ impl GPUState {
|
||||||
});
|
});
|
||||||
let screen_aspect = Matrix4::from_nonuniform_scale(1.0 / self.window_aspect, 1.0, 1.0);
|
let screen_aspect = Matrix4::from_nonuniform_scale(1.0 / self.window_aspect, 1.0, 1.0);
|
||||||
|
|
||||||
instances.push(UiInstance {
|
instances.push(SpriteInstance {
|
||||||
transform: (OPENGL_TO_WGPU_MATRIX * translate * screen_aspect * rotate * scale).into(),
|
transform: (OPENGL_TO_WGPU_MATRIX * translate * screen_aspect * rotate * scale).into(),
|
||||||
texture_index: texture.index,
|
texture_index: texture.index,
|
||||||
color: s.color.unwrap_or([1.0, 1.0, 1.0, 1.0]),
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Make an instance for all the game's sprites
|
/// Make a SpriteInstance for each of the game's visible sprites.
|
||||||
/// (Objects and UI)
|
/// Will panic if SPRITE_INSTANCE_LIMIT is exceeded.
|
||||||
/// This will Will panic if any X_SPRITE_INSTANCE_LIMIT is exceeded.
|
///
|
||||||
fn update_sprite_instances(
|
/// This is only called inside self.render()
|
||||||
|
fn make_sprite_instances(
|
||||||
&self,
|
&self,
|
||||||
camera_zoom: f32,
|
camera_zoom: f32,
|
||||||
camera_pos: Point2<f32>,
|
camera_pos: Point2<f32>,
|
||||||
objects: &Vec<ObjectSprite>,
|
objects: &Vec<ObjectSprite>,
|
||||||
ui: &Vec<UiSprite>,
|
ui: &Vec<UiSprite>,
|
||||||
) -> (usize, usize) {
|
) -> Vec<SpriteInstance> {
|
||||||
let mut object_instances: Vec<ObjectInstance> = Vec::new();
|
let mut instances: Vec<SpriteInstance> = Vec::new();
|
||||||
|
|
||||||
// Game coordinates (relative to camera) of ne and sw corners of screen.
|
// Game coordinates (relative to camera) of ne and sw corners of screen.
|
||||||
// Used to skip off-screen sprites.
|
// Used to skip off-screen sprites.
|
||||||
|
@ -442,45 +419,20 @@ impl GPUState {
|
||||||
let clip_sw = Point2::from((self.window_aspect, -1.0)) * camera_zoom;
|
let clip_sw = Point2::from((self.window_aspect, -1.0)) * camera_zoom;
|
||||||
|
|
||||||
for s in objects {
|
for s in objects {
|
||||||
self.push_object_sprite(
|
self.push_object_sprite(camera_zoom, camera_pos, &mut instances, clip_ne, clip_sw, s);
|
||||||
camera_zoom,
|
}
|
||||||
camera_pos,
|
|
||||||
&mut object_instances,
|
for s in ui {
|
||||||
clip_ne,
|
self.push_ui_sprite(&mut instances, s);
|
||||||
clip_sw,
|
|
||||||
s,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Enforce sprite limit
|
// Enforce sprite limit
|
||||||
if object_instances.len() as u64 > galactica_constants::OBJECT_SPRITE_INSTANCE_LIMIT {
|
if instances.len() as u64 > galactica_constants::SPRITE_INSTANCE_LIMIT {
|
||||||
// TODO: no panic, handle this better.
|
// TODO: no panic, handle this better.
|
||||||
panic!("Sprite limit exceeded!")
|
panic!("Sprite limit exceeded!")
|
||||||
}
|
}
|
||||||
|
|
||||||
self.queue.write_buffer(
|
return instances;
|
||||||
&self.vertex_buffers.object.instances,
|
|
||||||
0,
|
|
||||||
bytemuck::cast_slice(&object_instances),
|
|
||||||
);
|
|
||||||
|
|
||||||
let mut ui_instances: Vec<UiInstance> = Vec::new();
|
|
||||||
|
|
||||||
for s in ui {
|
|
||||||
self.push_ui_sprite(&mut ui_instances, s);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ui_instances.len() as u64 > galactica_constants::UI_SPRITE_INSTANCE_LIMIT {
|
|
||||||
panic!("Ui sprite limit exceeded!")
|
|
||||||
}
|
|
||||||
|
|
||||||
self.queue.write_buffer(
|
|
||||||
&self.vertex_buffers.ui.instances,
|
|
||||||
0,
|
|
||||||
bytemuck::cast_slice(&ui_instances),
|
|
||||||
);
|
|
||||||
|
|
||||||
return (object_instances.len(), ui_instances.len());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Make a StarfieldInstance for each star that needs to be drawn.
|
/// Make a StarfieldInstance for each star that needs to be drawn.
|
||||||
|
@ -558,8 +510,13 @@ impl GPUState {
|
||||||
);
|
);
|
||||||
|
|
||||||
// Create sprite instances
|
// Create sprite instances
|
||||||
let (n_object, n_ui) =
|
let sprite_instances =
|
||||||
self.update_sprite_instances(camera_zoom, camera_pos, object_sprites, ui_sprites);
|
self.make_sprite_instances(camera_zoom, camera_pos, object_sprites, ui_sprites);
|
||||||
|
self.queue.write_buffer(
|
||||||
|
&self.vertex_buffers.sprite.instances,
|
||||||
|
0,
|
||||||
|
bytemuck::cast_slice(&sprite_instances),
|
||||||
|
);
|
||||||
|
|
||||||
// These should match the indices in each shader,
|
// These should match the indices in each shader,
|
||||||
// and should each have a corresponding bind group layout.
|
// and should each have a corresponding bind group layout.
|
||||||
|
@ -576,14 +533,13 @@ impl GPUState {
|
||||||
);
|
);
|
||||||
|
|
||||||
// Sprite pipeline
|
// Sprite pipeline
|
||||||
self.vertex_buffers.object.set_in_pass(&mut render_pass);
|
self.vertex_buffers.sprite.set_in_pass(&mut render_pass);
|
||||||
render_pass.set_pipeline(&self.object_pipeline);
|
render_pass.set_pipeline(&self.sprite_pipeline);
|
||||||
render_pass.draw_indexed(0..SPRITE_INDICES.len() as u32, 0, 0..n_object as _);
|
render_pass.draw_indexed(
|
||||||
|
0..SPRITE_INDICES.len() as u32,
|
||||||
// Ui pipeline
|
0,
|
||||||
self.vertex_buffers.ui.set_in_pass(&mut render_pass);
|
0..sprite_instances.len() as _,
|
||||||
render_pass.set_pipeline(&self.ui_pipeline);
|
);
|
||||||
render_pass.draw_indexed(0..SPRITE_INDICES.len() as u32, 0, 0..n_ui as _);
|
|
||||||
|
|
||||||
// begin_render_pass borrows encoder mutably, so we can't call finish()
|
// begin_render_pass borrows encoder mutably, so we can't call finish()
|
||||||
// without dropping this variable.
|
// without dropping this variable.
|
||||||
|
|
|
@ -38,10 +38,6 @@ pub struct UiSprite {
|
||||||
/// This object's position, in logical (dpi-adjusted) pixels
|
/// This object's position, in logical (dpi-adjusted) pixels
|
||||||
pub pos: AnchoredUiPosition,
|
pub pos: AnchoredUiPosition,
|
||||||
|
|
||||||
/// This sprite's color will be multiplied by this value.
|
|
||||||
/// If this is None, color will not be changed.
|
|
||||||
pub color: Option<[f32; 4]>,
|
|
||||||
|
|
||||||
/// The size of this sprite, in logical (dpi-adjusted) pixels
|
/// The size of this sprite, in logical (dpi-adjusted) pixels
|
||||||
pub dimensions: Point2<f32>,
|
pub dimensions: Point2<f32>,
|
||||||
|
|
||||||
|
|
|
@ -94,7 +94,7 @@ impl Starfield {
|
||||||
while ((nw_tile.x * 2 + 1)
|
while ((nw_tile.x * 2 + 1)
|
||||||
* (nw_tile.y * 2 + 1)
|
* (nw_tile.y * 2 + 1)
|
||||||
* galactica_constants::STARFIELD_COUNT as i32)
|
* galactica_constants::STARFIELD_COUNT as i32)
|
||||||
> galactica_constants::STARFIELD_SPRITE_INSTANCE_LIMIT as i32
|
> galactica_constants::STARFIELD_INSTANCE_LIMIT as i32
|
||||||
{
|
{
|
||||||
nw_tile -= Vector2::from((1, 1));
|
nw_tile -= Vector2::from((1, 1));
|
||||||
}
|
}
|
||||||
|
@ -119,7 +119,7 @@ impl Starfield {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Enforce starfield limit
|
// Enforce starfield limit
|
||||||
if instances.len() as u64 > galactica_constants::STARFIELD_SPRITE_INSTANCE_LIMIT {
|
if instances.len() as u64 > galactica_constants::STARFIELD_INSTANCE_LIMIT {
|
||||||
unreachable!("Starfield limit exceeded!")
|
unreachable!("Starfield limit exceeded!")
|
||||||
}
|
}
|
||||||
self.instance_count = instances.len() as u32;
|
self.instance_count = instances.len() as u32;
|
||||||
|
|
|
@ -81,18 +81,19 @@ impl BufferObject for StarfieldInstance {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Represents a sprite instance in WGSL
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)]
|
#[derive(Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)]
|
||||||
pub struct ObjectInstance {
|
pub struct SpriteInstance {
|
||||||
/// Extra transformations this sprite
|
/// Extra transformations this sprite
|
||||||
/// (rotation, etc)
|
/// (rotation, etc)
|
||||||
pub transform: [[f32; 4]; 4],
|
pub transform: [[f32; 4]; 4],
|
||||||
|
|
||||||
/// What texture to use for this sprite
|
// What texture to use for this sprite
|
||||||
pub texture_index: u32,
|
pub texture_index: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BufferObject for ObjectInstance {
|
impl BufferObject for SpriteInstance {
|
||||||
fn layout() -> wgpu::VertexBufferLayout<'static> {
|
fn layout() -> wgpu::VertexBufferLayout<'static> {
|
||||||
wgpu::VertexBufferLayout {
|
wgpu::VertexBufferLayout {
|
||||||
array_stride: Self::SIZE,
|
array_stride: Self::SIZE,
|
||||||
|
@ -132,66 +133,3 @@ impl BufferObject for ObjectInstance {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[repr(C)]
|
|
||||||
#[derive(Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)]
|
|
||||||
pub struct UiInstance {
|
|
||||||
/// Extra transformations this sprite
|
|
||||||
/// (rotation, etc)
|
|
||||||
pub transform: [[f32; 4]; 4],
|
|
||||||
|
|
||||||
/// This lets us color ui sprites dynamically.
|
|
||||||
/// Each fragment's color is multiplied by this value.
|
|
||||||
/// Fill this array with ones if no recoloring should be done.
|
|
||||||
pub color: [f32; 4],
|
|
||||||
|
|
||||||
/// What texture to use for this sprite
|
|
||||||
pub texture_index: u32,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl BufferObject for UiInstance {
|
|
||||||
fn layout() -> wgpu::VertexBufferLayout<'static> {
|
|
||||||
wgpu::VertexBufferLayout {
|
|
||||||
array_stride: Self::SIZE,
|
|
||||||
// Switch to a step mode of Vertex to Instance.
|
|
||||||
// This means that our shaders will only change to use the next
|
|
||||||
// instance when the shader starts processing a new instance
|
|
||||||
step_mode: wgpu::VertexStepMode::Instance,
|
|
||||||
attributes: &[
|
|
||||||
// 4 arrays = 1 4x4 matrix
|
|
||||||
wgpu::VertexAttribute {
|
|
||||||
offset: 0,
|
|
||||||
shader_location: 2,
|
|
||||||
format: wgpu::VertexFormat::Float32x4,
|
|
||||||
},
|
|
||||||
wgpu::VertexAttribute {
|
|
||||||
offset: mem::size_of::<[f32; 4]>() as wgpu::BufferAddress,
|
|
||||||
shader_location: 3,
|
|
||||||
format: wgpu::VertexFormat::Float32x4,
|
|
||||||
},
|
|
||||||
wgpu::VertexAttribute {
|
|
||||||
offset: mem::size_of::<[f32; 8]>() as wgpu::BufferAddress,
|
|
||||||
shader_location: 4,
|
|
||||||
format: wgpu::VertexFormat::Float32x4,
|
|
||||||
},
|
|
||||||
wgpu::VertexAttribute {
|
|
||||||
offset: mem::size_of::<[f32; 12]>() as wgpu::BufferAddress,
|
|
||||||
shader_location: 5,
|
|
||||||
format: wgpu::VertexFormat::Float32x4,
|
|
||||||
},
|
|
||||||
// Color
|
|
||||||
wgpu::VertexAttribute {
|
|
||||||
offset: mem::size_of::<[f32; 16]>() as wgpu::BufferAddress,
|
|
||||||
shader_location: 6,
|
|
||||||
format: wgpu::VertexFormat::Float32x4,
|
|
||||||
},
|
|
||||||
// Texture
|
|
||||||
wgpu::VertexAttribute {
|
|
||||||
offset: mem::size_of::<[f32; 20]>() as wgpu::BufferAddress,
|
|
||||||
shader_location: 7,
|
|
||||||
format: wgpu::VertexFormat::Uint32,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -24,7 +24,6 @@ pub fn build_radar(
|
||||||
y: radar_size,
|
y: radar_size,
|
||||||
},
|
},
|
||||||
angle: Deg(0.0),
|
angle: Deg(0.0),
|
||||||
color: None,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// Draw viewport frame
|
// Draw viewport frame
|
||||||
|
@ -34,7 +33,7 @@ pub fn build_radar(
|
||||||
};
|
};
|
||||||
let m = d.magnitude() / radar_range;
|
let m = d.magnitude() / radar_range;
|
||||||
let d = d / radar_range * (radar_size / 2.0);
|
let d = d / radar_range * (radar_size / 2.0);
|
||||||
let color = Some([0.5, 0.5, 0.5, 1.0]);
|
println!("{:?}", d);
|
||||||
if m < 0.8 {
|
if m < 0.8 {
|
||||||
let texture = ct.get_texture_handle("ui::radarframe");
|
let texture = ct.get_texture_handle("ui::radarframe");
|
||||||
let dimensions = Point2 {
|
let dimensions = Point2 {
|
||||||
|
@ -49,7 +48,6 @@ pub fn build_radar(
|
||||||
}),
|
}),
|
||||||
dimensions,
|
dimensions,
|
||||||
angle: Deg(0.0),
|
angle: Deg(0.0),
|
||||||
color,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
out.push(UiSprite {
|
out.push(UiSprite {
|
||||||
|
@ -60,7 +58,6 @@ pub fn build_radar(
|
||||||
}),
|
}),
|
||||||
dimensions,
|
dimensions,
|
||||||
angle: Deg(90.0),
|
angle: Deg(90.0),
|
||||||
color,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
out.push(UiSprite {
|
out.push(UiSprite {
|
||||||
|
@ -71,7 +68,6 @@ pub fn build_radar(
|
||||||
}),
|
}),
|
||||||
dimensions,
|
dimensions,
|
||||||
angle: Deg(180.0),
|
angle: Deg(180.0),
|
||||||
color,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
out.push(UiSprite {
|
out.push(UiSprite {
|
||||||
|
@ -82,7 +78,6 @@ pub fn build_radar(
|
||||||
}),
|
}),
|
||||||
dimensions,
|
dimensions,
|
||||||
angle: Deg(270.0),
|
angle: Deg(270.0),
|
||||||
color,
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -93,13 +88,23 @@ pub fn build_radar(
|
||||||
let p = util::rigidbody_position(r);
|
let p = util::rigidbody_position(r);
|
||||||
let d = p - pr;
|
let d = p - pr;
|
||||||
let m = d.magnitude() / radar_range;
|
let m = d.magnitude() / radar_range;
|
||||||
if m < 0.8 {
|
let angle: Deg<f32> = util::rigidbody_rotation(r)
|
||||||
let angle: Deg<f32> = util::rigidbody_rotation(r)
|
.angle(Vector2 { x: 0.0, y: 1.0 })
|
||||||
.angle(Vector2 { x: 0.0, y: 1.0 })
|
.into();
|
||||||
.into();
|
if s.physics_handle == *player {
|
||||||
let f = ct.get_faction(s.ship.faction).color;
|
out.push(UiSprite {
|
||||||
let f = [f[0], f[1], f[2], 1.0];
|
texture,
|
||||||
|
pos: AnchoredUiPosition::NwC(Point2 {
|
||||||
|
x: radar_size / 2.0 + 10.0,
|
||||||
|
y: radar_size / -2.0 - 10.0,
|
||||||
|
}),
|
||||||
|
dimensions: Point2 {
|
||||||
|
x: texture.aspect,
|
||||||
|
y: 1.0,
|
||||||
|
} * 5.0f32.min((0.8 - m) * 50.0),
|
||||||
|
angle: -angle,
|
||||||
|
});
|
||||||
|
} else if m < 0.8 {
|
||||||
out.push(UiSprite {
|
out.push(UiSprite {
|
||||||
texture,
|
texture,
|
||||||
pos: AnchoredUiPosition::NwC(
|
pos: AnchoredUiPosition::NwC(
|
||||||
|
@ -113,7 +118,6 @@ pub fn build_radar(
|
||||||
y: 1.0,
|
y: 1.0,
|
||||||
} * 5.0f32.min((0.8 - m) * 50.0),
|
} * 5.0f32.min((0.8 - m) * 50.0),
|
||||||
angle: -angle,
|
angle: -angle,
|
||||||
color: Some(f),
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,9 +49,6 @@ impl Game {
|
||||||
let s = object::Ship::new(
|
let s = object::Ship::new(
|
||||||
&ct,
|
&ct,
|
||||||
content::ShipHandle { index: 0 },
|
content::ShipHandle { index: 0 },
|
||||||
// This method of specifying factions is non-deterministic,
|
|
||||||
// but that's ok since this is for debug.
|
|
||||||
// TODO: fix
|
|
||||||
content::FactionHandle { index: 0 },
|
content::FactionHandle { index: 0 },
|
||||||
object::OutfitSet::new(ss),
|
object::OutfitSet::new(ss),
|
||||||
);
|
);
|
||||||
|
|
Loading…
Reference in New Issue