Skip to content

Commit

Permalink
Changes.
Browse files Browse the repository at this point in the history
  • Loading branch information
tychedelia committed Aug 21, 2024
1 parent 435c0b2 commit ca17a79
Show file tree
Hide file tree
Showing 9 changed files with 254 additions and 38 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions bevy_nannou_isf/src/asset.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ impl AssetLoader for IsfLoader {
for (name, import) in &isf.imported {
let image = load_context.load::<Image>(import.path.clone());
imported_images.insert(name.clone(), image);

}
Ok(Isf {
isf,
Expand Down
5 changes: 0 additions & 5 deletions bevy_nannou_isf/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,8 @@ use bevy::prelude::*;
use bevy::render::extract_component::ExtractComponentPlugin;
use bevy::render::extract_resource::ExtractResourcePlugin;
use bevy::render::view;
use bevy::render::view::{NoFrustumCulling, VisibilitySystems};
use bevy::window::PrimaryWindow;
use bevy_egui::{egui, EguiContext};
use bevy_inspector_egui::inspector_egui_impls::InspectorEguiImpl;
use bevy_inspector_egui::quick::ResourceInspectorPlugin;
use bevy_inspector_egui::DefaultInspectorConfigPlugin;
use std::any::TypeId;

mod asset;
mod inputs;
Expand Down
4 changes: 4 additions & 0 deletions examples/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ walkdir = "2"
hound = "3.4.0"
ringbuf = "0.2.2"
futures = "0.3"
bytemuck = "1"

[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
tokio = { version = "1", features = ["full"]}
Expand Down Expand Up @@ -63,6 +64,9 @@ path = "communication/osc_sender.rs"
[[example]]
name = "game_of_life"
path = "compute/game_of_life.rs"
[[example]]
name = "particle_mouse"
path = "compute/particle_mouse.rs"

# Draw
[[example]]
Expand Down
88 changes: 88 additions & 0 deletions examples/assets/shaders/particle_mouse.wgsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
struct Particle {
position: vec2<f32>,
velocity: vec2<f32>,
color: vec4<f32>,
};

@group(0) @binding(0) var<storage, read_write> particles: array<Particle>;
@group(0) @binding(1) var<uniform> mouse: vec2<f32>;
@group(0) @binding(2) var<uniform> resolution: vec2<f32>;


struct VertexOutput {
@builtin(position) clip_position: vec4<f32>,
@location(0) color: vec4<f32>,
};

@vertex
fn vertex(@builtin(vertex_index) vertex_index: u32) -> VertexOutput {
let particle = particles[vertex_index];

var out: VertexOutput;
out.clip_position = vec4<f32>(particle.position, 0.0, 1.0);
out.color = particle.color;
return out;
}

@fragment
fn fragment(in: VertexOutput) -> @location(0) vec4<f32> {
return in.color;
}

fn random(seed: vec2<f32>) -> f32 {
return fract(sin(dot(seed, vec2(12.9898, 78.233))) * 43758.5453);
}

@compute @workgroup_size(64)
fn init(@builtin(global_invocation_id) global_id: vec3<u32>) {
let index = global_id.x;
var particle: Particle;

// Initialize position randomly within the window
particle.position = vec2<f32>(
(random(vec2<f32>(f32(index), 0.0)) - 0.5) * resolution.x,
(random(vec2<f32>(0.0, f32(index))) - 0.5) * resolution.y
);

// Initialize velocity randomly
particle.velocity = vec2<f32>(
(random(vec2<f32>(f32(index), 1.0)) - 0.5) * 0.1,
(random(vec2<f32>(1.0, f32(index))) - 0.5) * 0.1
);

// Initialize color randomly
particle.color = vec4<f32>(
random(vec2<f32>(f32(index), 2.0)),
random(vec2<f32>(2.0, f32(index))),
random(vec2<f32>(f32(index), 3.0)),
1.0
);

particles[index] = particle;
}

@compute @workgroup_size(64)
fn update(@builtin(global_invocation_id) global_id: vec3<u32>) {
let index = global_id.x;
var particle = particles[index];

// Update particle position
particle.position = particle.position + particle.velocity;

// Attract particles to mouse
let to_mouse = mouse - particle.position;
particle.velocity = particle.velocity + normalize(to_mouse) * 0.0001;

// Bounce off screen edges
if (particle.position.x < -1.0 || particle.position.x > 1.0) {
particle.velocity.x = -particle.velocity.x;
}
if (particle.position.y < -1.0 || particle.position.y > 1.0) {
particle.velocity.y = -particle.velocity.y;
}

// Update color based on velocity
particle.color = vec4<f32>(abs(particle.velocity), 1.0, 1.0);

particles[index] = particle;
}
7 changes: 4 additions & 3 deletions examples/compute/game_of_life.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
mod particle_mouse;

use nannou::prelude::*;

const DISPLAY_FACTOR: u32 = 4;
Expand Down Expand Up @@ -33,10 +35,10 @@ struct ComputeModel {
texture_write: Handle<Image>,
}

impl ComputeShader for ComputeModel {
impl Compute for ComputeModel {
type State = State;

fn compute_shader() -> ShaderRef {
fn shader() -> ShaderRef {
"shaders/game_of_life.wgsl".into()
}

Expand Down Expand Up @@ -119,7 +121,6 @@ fn compute(app: &App, model: &Model, state: State, view: Entity) -> (State, Comp

fn view(app: &App, model: &Model, view: Entity) {
let draw = app.draw();
draw.background().color(BLACK);
let window_rect = app.window_rect();
draw.rect()
.w_h(window_rect.w(), window_rect.h())
Expand Down
125 changes: 125 additions & 0 deletions examples/compute/particle_mouse.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
use bytemuck::{Pod, Zeroable};
use nannou::prelude::bevy_render::renderer::RenderDevice;
use nannou::prelude::*;
use std::sync::Arc;

const NUM_PARTICLES: u32 = 10000;
const WORKGROUP_SIZE: u32 = 64;

fn main() {
nannou::app(model).compute(compute).update(update).run();
}

struct Model {
particles: Buffer,
}

#[derive(Default, Clone, Copy, Pod, Zeroable)]
#[repr(C)]
struct Particle {
position: Vec2,
velocity: Vec2,
color: Vec4,
}

#[derive(Default, Debug, Eq, PartialEq, Hash, Clone)]
enum State {
#[default]
Init,
Update,
}

#[derive(AsBindGroup, Clone)]
struct ComputeModel {
#[storage(0, buffer, visibility(compute, vertex))]
particles: Buffer,
#[uniform(1)]
mouse: Vec2,
#[uniform(2)]
resolution: Vec2,
}

impl Compute for ComputeModel {
type State = State;

fn shader() -> ShaderRef {
"shaders/particle_mouse.wgsl".into()
}

fn shader_entry(state: &Self::State) -> &'static str {
match state {
State::Init => "init",
State::Update => "update",
}
}

fn workgroup_size(_state: &Self::State) -> (u32, u32, u32) {
(WORKGROUP_SIZE, 1, 1)
}
}

#[derive(AsBindGroup, Asset, TypePath, Clone)]
struct DrawMaterial {
#[storage(0, buffer, visibility(compute, vertex))]
particles: Buffer,
}



impl Material for DrawMaterial {
fn vertex_shader() -> ShaderRef {
"shaders/particle_mouse.wgsl".into()
}

fn fragment_shader() -> ShaderRef {
"shaders/particle_mouse.wgsl".into()
}
}

fn model(app: &App) -> Model {
let _window_id = app
.new_window()
.primary()
.size(1024, 768)
.view(view)
.build();
let device = app.resource_mut::<RenderDevice>();

let particles = device.create_buffer_with_data(&BufferInitDescriptor {
label: Some("ParticleBuffer"),
contents: bytemuck::cast_slice(&vec![Particle::default(); NUM_PARTICLES as usize]),
usage: BufferUsages::STORAGE | BufferUsages::VERTEX,
});

Model { particles }
}

fn update(app: &App, model: &mut Model) {}

fn compute(app: &App, model: &Model, state: State, view: Entity) -> (State, ComputeModel) {
let window = app.main_window();
let window_rect = window.rect();

let mouse_pos = app.mouse();
let compute_model = ComputeModel {
particles: model.particles.clone(),
mouse: mouse_pos,
resolution: Vec2::new(window_rect.w(), window_rect.h()),
};

match state {
State::Init => (State::Update, compute_model),
State::Update => (State::Update, compute_model),
}
}

fn view(app: &App, model: &Model) {
let draw = app.draw()
.material(DrawMaterial {
particles: model.particles.clone(),
});
draw.background()
.color(BLACK);
draw.polyline()
.points(vec![Vec2::ZERO; NUM_PARTICLES as usize]);
}
31 changes: 16 additions & 15 deletions nannou/src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,15 +49,14 @@ use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
use std::sync::Arc;
use std::time::Duration;
use std::{self};
use wgpu::naga::ShaderStage::Compute;

use crate::frame::{Frame, FramePlugin};
use crate::prelude::bevy_ecs::system::SystemState;
use crate::prelude::render::NannouMesh;
use crate::prelude::NannouMaterialPlugin;
use crate::render::{
ComputeModel, ComputePlugin, ComputeShader, ComputeShaderHandle, ComputeState,
NannouRenderNode, RenderApp, RenderPlugin,
Compute, ComputeModel, ComputePlugin, ComputeShaderHandle, ComputeState, NannouRenderNode,
RenderApp, RenderPlugin,
};
use crate::window::WindowUserFunctions;
use crate::{camera, geom, light, window};
Expand All @@ -70,9 +69,9 @@ pub type ComputeUpdateFn<Model, ComputeModel> =
fn(
&App,
&Model,
<ComputeModel as ComputeShader>::State,
<ComputeModel as Compute>::State,
Entity,
) -> (<ComputeModel as ComputeShader>::State, ComputeModel);
) -> (<ComputeModel as Compute>::State, ComputeModel);

/// The user function type for updating their model in accordance with some event.
pub type EventFn<Model, Event> = fn(&App, &mut Model, &Event);
Expand Down Expand Up @@ -168,7 +167,7 @@ struct EventFnRes<M, E>(Option<EventFn<M, E>>);
struct UpdateFnRes<M>(Option<UpdateFn<M>>);

#[derive(Resource, Deref, DerefMut)]
struct ComputeUpdateFnRes<M, CM: ComputeShader>(ComputeUpdateFn<M, CM>);
struct ComputeUpdateFnRes<M, CM: Compute>(ComputeUpdateFn<M, CM>);

#[derive(Resource, Deref, DerefMut)]
pub(crate) struct RenderFnRes<M>(Option<RenderFn<M>>);
Expand Down Expand Up @@ -252,12 +251,14 @@ where
pub fn new(model: ModelFn<M>) -> Self {
let mut app = bevy::app::App::new();
app.add_plugins((
DefaultPlugins.set(WindowPlugin {
// Don't spawn a window by default, we'll handle this ourselves
primary_window: None,
exit_condition: ExitCondition::OnAllClosed,
..default()
}),
DefaultPlugins
.set(WindowPlugin {
// Don't spawn a window by default, we'll handle this ourselves
primary_window: None,
exit_condition: ExitCondition::OnAllClosed,
..default()
})
.set(ImagePlugin::default_nearest()),
#[cfg(feature = "egui")]
bevy_egui::EguiPlugin,
NannouPlugin,
Expand Down Expand Up @@ -370,9 +371,9 @@ where
self
}

pub fn compute<CM: ComputeShader>(mut self, compute_fn: ComputeUpdateFn<M, CM>) -> Self {
pub fn compute<CM: Compute>(mut self, compute_fn: ComputeUpdateFn<M, CM>) -> Self {
let render_app = self.app.sub_app_mut(bevy::render::RenderApp);
render_app.insert_resource(ComputeShaderHandle(CM::compute_shader()));
render_app.insert_resource(ComputeShaderHandle(CM::shader()));
self.app
.add_systems(
First,
Expand Down Expand Up @@ -1145,7 +1146,7 @@ fn compute<M, CM>(
)>,
) where
M: 'static + Send + Sync,
CM: ComputeShader,
CM: Compute,
{
let (mut app, (mut model, compute, mut views_q)) = get_app_and_state(world, state);
let compute = compute.0;
Expand Down
Loading

0 comments on commit ca17a79

Please sign in to comment.