diff --git a/Cargo.lock b/Cargo.lock index 096e69c..f85c83b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1025,9 +1025,9 @@ checksum = "a3e2c3daef883ecc1b5d58c15adae93470a91d425f3532ba1695849656af3fc1" [[package]] name = "bytemuck" -version = "1.13.1" +version = "1.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17febce684fd15d89027105661fec94afb475cb995fbc59d2865198446ba2eea" +checksum = "374d28ec25809ee0e23827c2ab573d729e293f281dfe393500e7ad618baa61c6" dependencies = [ "bytemuck_derive", ] @@ -2701,6 +2701,7 @@ dependencies = [ "bevy", "bevy_asset_loader", "bevy_kira_audio", + "bytemuck", "embed-resource", "image", "rand", diff --git a/Cargo.toml b/Cargo.toml index ffae847..ab22994 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -56,6 +56,8 @@ rand = { version = "0.8.3" } winit = { version = "0.28", default-features = false } image = { version = "0.24", default-features = false } +bytemuck = "1.14.0" + [build-dependencies] embed-resource = "2.3.0" diff --git a/src/actions/mod.rs b/src/actions/mod.rs index a518414..c29e0bf 100644 --- a/src/actions/mod.rs +++ b/src/actions/mod.rs @@ -1,10 +1,5 @@ -use bevy::math::Vec3Swizzles; use bevy::prelude::*; -use crate::actions::game_control::{get_movement, GameControl}; -use crate::player::Player; -use crate::GameState; - mod game_control; pub const FOLLOW_EPSILON: f32 = 5.; @@ -14,47 +9,7 @@ pub struct ActionsPlugin; // This plugin listens for keyboard input and converts the input into Actions // Actions can then be used as a resource in other systems to act on the player input. impl Plugin for ActionsPlugin { - fn build(&self, app: &mut App) { - app.init_resource::().add_systems( - Update, - set_movement_actions.run_if(in_state(GameState::Playing)), - ); - } -} - -#[derive(Default, Resource)] -pub struct Actions { - pub player_movement: Option, -} - -pub fn set_movement_actions( - mut actions: ResMut, - keyboard_input: Res>, - touch_input: Res, - player: Query<&Transform, With>, - camera: Query<(&Camera, &GlobalTransform), With>, -) { - let mut player_movement = Vec2::new( - get_movement(GameControl::Right, &keyboard_input) - - get_movement(GameControl::Left, &keyboard_input), - get_movement(GameControl::Up, &keyboard_input) - - get_movement(GameControl::Down, &keyboard_input), - ); - - if let Some(touch_position) = touch_input.first_pressed_position() { - let (camera, camera_transform) = camera.single(); - if let Some(touch_position) = camera.viewport_to_world_2d(camera_transform, touch_position) - { - let diff = touch_position - player.single().translation.xy(); - if diff.length() > FOLLOW_EPSILON { - player_movement = diff.normalize(); - } - } - } + fn build(&self, _app: &mut App) { - if player_movement != Vec2::ZERO { - actions.player_movement = Some(player_movement.normalize()); - } else { - actions.player_movement = None; } } diff --git a/src/audio.rs b/src/audio.rs index 1be8133..30321e3 100644 --- a/src/audio.rs +++ b/src/audio.rs @@ -1,4 +1,3 @@ -use crate::actions::{set_movement_actions, Actions}; use crate::loading::AudioAssets; use crate::GameState; use bevy::prelude::*; @@ -11,13 +10,7 @@ pub struct InternalAudioPlugin; impl Plugin for InternalAudioPlugin { fn build(&self, app: &mut App) { app.add_plugins(AudioPlugin) - .add_systems(OnEnter(GameState::Playing), start_audio) - .add_systems( - Update, - control_flying_sound - .after(set_movement_actions) - .run_if(in_state(GameState::Playing)), - ); + .add_systems(OnEnter(GameState::Playing), start_audio); } } @@ -33,25 +26,3 @@ fn start_audio(mut commands: Commands, audio_assets: Res, audio: Re .handle(); commands.insert_resource(FlyingAudio(handle)); } - -fn control_flying_sound( - actions: Res, - audio: Res, - mut audio_instances: ResMut>, -) { - if let Some(instance) = audio_instances.get_mut(&audio.0) { - match instance.state() { - PlaybackState::Paused { .. } => { - if actions.player_movement.is_some() { - instance.resume(AudioTween::default()); - } - } - PlaybackState::Playing { .. } => { - if actions.player_movement.is_none() { - instance.pause(AudioTween::default()); - } - } - _ => {} - } - } -} diff --git a/src/engine/buffers.rs b/src/engine/buffers.rs new file mode 100644 index 0000000..720c85d --- /dev/null +++ b/src/engine/buffers.rs @@ -0,0 +1,96 @@ +use bevy::{ + prelude::{Res, Resource}, + render::{ + extract_resource::ExtractResource, + render_resource::{Buffer, BufferInitDescriptor, BufferUsages}, + renderer::RenderDevice, + }, +}; + +use super::{SIM_SIZE, SIM_VOXELS}; + +#[derive(Resource, Clone, ExtractResource, Debug)] +pub struct VoxelPipelineBuffers { + /// uniform, used for constants + pub dimentions: Buffer, + /// storage + pub in_out_double_buffers: Vec, + pub(in crate::engine) double_indices: DoubleBufferIndices, +} + +impl VoxelPipelineBuffers { + pub fn new(device: Res) -> Self { + // Initialize constants (configuration, parameters... etc) + let dimentions = create_uniform_buffer( + &device, + &[SIM_SIZE.0, SIM_SIZE.1], + Some("Voxels image dimensions Uniform"), + ); + + // Initialize double buffers for the simulation data + let initial_life_data = vec![0u32; 2 * SIM_VOXELS]; + let in_out_double_buffers = (0..2) + .map(|i| { + create_storage_buffer_with_data( + &device, + &initial_life_data, + Some(&format!("Voxel Engine Storage Buffer {i}")), + ) + }) + .collect::>(); + + VoxelPipelineBuffers { + dimentions, + in_out_double_buffers, + double_indices: DoubleBufferIndices::default(), + } + } +} + +/// To help us maintain the current and next buffer indices +#[derive(Clone, Debug)] +pub(in crate::engine) struct DoubleBufferIndices { + pub current: usize, + pub next: usize, +} + +impl Default for DoubleBufferIndices { + fn default() -> Self { + Self { + current: 0, + next: 1, + } + } +} + +impl DoubleBufferIndices { + // Sould only ever be called once per rendering tick + pub fn swap(&mut self) { + self.current = self.next; + self.next = (self.next + 1) % 2; + } +} + +pub(in crate::engine) fn create_uniform_buffer( + device: &RenderDevice, + data: &[T], + label: Option<&str>, +) -> Buffer { + device.create_buffer_with_data(&BufferInitDescriptor { + label, + contents: bytemuck::cast_slice(data), + usage: BufferUsages::UNIFORM | BufferUsages::COPY_DST, + }) +} + +pub(in crate::engine) fn create_storage_buffer_with_data( + device: &RenderDevice, + data: &[T], + label: Option<&str>, +) -> Buffer { + device.create_buffer_with_data(&BufferInitDescriptor { + label, + contents: bytemuck::cast_slice(data), + usage: BufferUsages::STORAGE | BufferUsages::COPY_DST, + }) +} diff --git a/src/engine/image.rs b/src/engine/image.rs index 7b2720c..6a39a75 100644 --- a/src/engine/image.rs +++ b/src/engine/image.rs @@ -3,7 +3,7 @@ use bevy::{ render::{extract_resource::*, render_resource::*}, }; -#[derive(Resource, Clone, Deref, ExtractResource)] +#[derive(Resource, Clone, Deref, ExtractResource, Debug)] pub struct VoxelsRenderImage(pub Handle); impl VoxelsRenderImage { diff --git a/src/engine/mod.rs b/src/engine/mod.rs index 415dacc..8cf5ce3 100644 --- a/src/engine/mod.rs +++ b/src/engine/mod.rs @@ -1,16 +1,20 @@ +mod buffers; pub mod image; mod pipeline; use bevy::{ diagnostic::*, prelude::*, - render::{extract_resource::ExtractResourcePlugin, Render, RenderApp, RenderSet, render_graph::RenderGraph}, + render::{extract_resource::ExtractResourcePlugin, Render, RenderApp, RenderSet, render_graph::RenderGraph, renderer::RenderDevice}, window::*, }; +use crate::{GameState, engine::buffers::VoxelPipelineBuffers}; + use self::{image::VoxelsRenderImage, pipeline::{VoxelShadersPipeline, VoxelSandboxNode}}; -const SIM_SIZE: (u32, u32) = (1280, 720); +const SIM_SIZE: (u32, u32) = (800, 600); +const SIM_VOXELS: usize = 800 * 600; const WORKGROUP_SIZE: u32 = 8; pub struct EnginePlugin; @@ -48,7 +52,11 @@ fn window_fps( } } -fn setup(mut commands: Commands, images: ResMut>) { +fn setup( + mut commands: Commands, + images: ResMut>, + device: Res, +) { let render_image_res = VoxelsRenderImage::new(SIM_SIZE.0, SIM_SIZE.1, images); commands.spawn(SpriteBundle { @@ -60,5 +68,10 @@ fn setup(mut commands: Commands, images: ResMut>) { ..default() }); + let buffers = VoxelPipelineBuffers::new(device); + + debug!("[Resource inserted]{:?}", render_image_res); commands.insert_resource(render_image_res); -} + debug!("[Resource inserted]{:?}", buffers); + commands.insert_resource(buffers); +} \ No newline at end of file diff --git a/src/lib.rs b/src/lib.rs index ef53cd2..7f798ea 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -5,13 +5,11 @@ mod audio; mod engine; mod loading; mod menu; -mod player; use crate::actions::ActionsPlugin; use crate::audio::InternalAudioPlugin; use crate::loading::LoadingPlugin; use crate::menu::MenuPlugin; -use crate::player::PlayerPlugin; #[cfg(debug_assertions)] use bevy::diagnostic::{FrameTimeDiagnosticsPlugin, LogDiagnosticsPlugin}; @@ -55,7 +53,6 @@ impl Plugin for GamePlugin { MenuPlugin, ActionsPlugin, InternalAudioPlugin, - PlayerPlugin, EnginePlugin, ExtractResourcePlugin::::default(), )) @@ -72,7 +69,7 @@ impl Plugin for GamePlugin { { app.add_plugins(LogPlugin { level: bevy::log::Level::DEBUG, - filter: "debug,wgpu_core=warn,wgpu_hal=warn,sandboxed=debug".into(), + filter: "debug,wgpu_core=warn,wgpu_hal=warn,naga=warn,sandboxed=debug".into(), }); app.add_plugins((FrameTimeDiagnosticsPlugin, LogDiagnosticsPlugin::default())); } diff --git a/src/player.rs b/src/player.rs deleted file mode 100644 index ad627af..0000000 --- a/src/player.rs +++ /dev/null @@ -1,47 +0,0 @@ -use crate::actions::Actions; -use crate::loading::TextureAssets; -use crate::GameState; -use bevy::prelude::*; - -pub struct PlayerPlugin; - -#[derive(Component)] -pub struct Player; - -/// This plugin handles player related stuff like movement -/// Player logic is only active during the State `GameState::Playing` -impl Plugin for PlayerPlugin { - fn build(&self, app: &mut App) { - app.add_systems(OnEnter(GameState::Playing), spawn_player) - .add_systems(Update, move_player.run_if(in_state(GameState::Playing))); - } -} - -fn spawn_player(mut commands: Commands, textures: Res) { - commands - .spawn(SpriteBundle { - texture: textures.texture_bevy.clone(), - transform: Transform::from_translation(Vec3::new(0., 0., 1.)), - ..Default::default() - }) - .insert(Player); -} - -fn move_player( - time: Res