Skip to content

Commit

Permalink
adding more docs and an example
Browse files Browse the repository at this point in the history
  • Loading branch information
TornaxO7 committed Jan 2, 2025
1 parent c2d564c commit 92f7b64
Show file tree
Hide file tree
Showing 7 changed files with 241 additions and 5 deletions.
2 changes: 2 additions & 0 deletions Cargo.lock

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

3 changes: 3 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ wgpu = { version = "22.0", default-features = false, features = [
tracing = "0.1"
thiserror = "2"

pollster = "0.4.0"
winit = "0.30"

cpal = "0.15"
realfft = "3.4"
splines = "4"
Expand Down
12 changes: 9 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,14 @@ For example on my system it looks like this (after starting [pavucontrol]):

Here are some other sources/similar projects if you're interested:

- https://github.com/phip1611/spectrum-analyzer
- https://github.com/BrunoWallner/crav
- https://www.youtube.com/watch?v=Xdbk1Pr5WXU&list=PLpM-Dvs8t0Vak1rrE2NJn8XYEJ5M7-BqT
- Other music visualizers:
- https://github.com/phip1611/spectrum-analyzer
- https://github.com/BrunoWallner/crav
- https://github.com/karlstav/cava
- Tscoding implementing [musializer] https://www.youtube.com/watch?v=Xdbk1Pr5WXU&list=PLpM-Dvs8t0Vak1rrE2NJn8XYEJ5M7-BqT
- WGPU tutorials:
- https://sotrh.github.io/learn-wgpu/
- https://webgpufundamentals.org/

[shadertoy]: https://www.shadertoy.com/
[pavucontrol]: https://github.com/pulseaudio/pavucontrol
Expand All @@ -33,3 +38,4 @@ Here are some other sources/similar projects if you're interested:
[shady-cli]: https://github.com/TornaxO7/shady/tree/main/shady-cli
[glsl]: https://www.khronos.org/opengl/wiki/Core_Language_(GLSL)
[wgsl]: https://www.w3.org/TR/WGSL/
[musializer]: https://github.com/tsoding/musializer
4 changes: 4 additions & 0 deletions shady-lib/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ wgpu.workspace = true
tracing.workspace = true
thiserror.workspace = true

[dev-dependencies]
winit.workspace = true
pollster.workspace = true

[features]
default = ["time", "resolution", "audio", "mouse", "frame"]

Expand Down
22 changes: 22 additions & 0 deletions shady-lib/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# `shady-lib`

The main library which takes care of the uniform/storage buffers, vertices and templates.

The idea is that other applications who wish to include [shadertoy]-like shaders into their
application to use this library which takes care most of the data to be able to run those shaders.

# State

It's useable, however I'm a bit unsure about the architecture because I don't really know what
a good API looks like for a graphics-programmer. It may sound stupid, but the reason why I didn't
publish this yet, is:

1. It's very likely that breaking changes are going to appear ...
2. ... hence there aren't any docs yet.

However, I hope that this will change after some time.

Nevertheless, there's a "simple" example (I tried to create a very small example) in the `examples` directory if you want
to include it to your app. All relevant places, where you have to "interact" with shady are annoted with the `// SHADY` comments.

[shadertoy]: https://www.youtube.com/watch?v=Xdbk1Pr5WXU&list=PLpM-Dvs8t0Vak1rrE2NJn8XYEJ5M7-BqT
199 changes: 199 additions & 0 deletions shady-lib/examples/mini-simple.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,199 @@
/// Every relevant part is marked with the prefix `SHADY` so you can just search in this code with `SHADY`.
use std::sync::Arc;

use pollster::FutureExt;
use shady::{Shady, ShadyDescriptor, Wgsl};
use wgpu::{
Backends, Device, Instance, Queue, Surface, SurfaceConfiguration, TextureViewDescriptor,
};
use winit::{
application::ApplicationHandler,
dpi::PhysicalSize,
event::WindowEvent,
event_loop::{ActiveEventLoop, EventLoop},
window::{Window, WindowAttributes, WindowId},
};

const SHADY_BIND_GROUP_INDEX: u32 = 0;
const SHADY_VERTEX_BUFFER_INDEX: u32 = 0;

struct State<'a> {
surface: Surface<'a>,
device: Device,
queue: Queue,
config: SurfaceConfiguration,
window: Arc<Window>,
// SHADY
shady: Shady<Wgsl>,
}

impl<'a> State<'a> {
fn new(window: Window) -> Self {
let window = Arc::new(window);

let instance = Instance::new(wgpu::InstanceDescriptor {
backends: Backends::PRIMARY,
..Default::default()
});

let surface = instance.create_surface(window.clone()).unwrap();

let adapter = instance
.request_adapter(&wgpu::RequestAdapterOptions {
compatible_surface: Some(&surface),
..Default::default()
})
.block_on()
.unwrap();

let (device, queue) = adapter
.request_device(&wgpu::DeviceDescriptor::default(), None)
.block_on()
.unwrap();

let (config, shady) = {
let surface_caps = surface.get_capabilities(&adapter);
let surface_format = surface_caps
.formats
.iter()
.find(|f| f.is_srgb())
.copied()
.unwrap_or(surface_caps.formats[0]);

let size = window.clone().inner_size();

let config = wgpu::SurfaceConfiguration {
usage: wgpu::TextureUsages::RENDER_ATTACHMENT,
format: surface_format,
width: size.width,
height: size.height,
present_mode: wgpu::PresentMode::AutoVsync,
alpha_mode: surface_caps.alpha_modes[0],
view_formats: vec![],
desired_maximum_frame_latency: 2,
};

// SHADY
let fragment_shader = {
let mut fragment_code = String::new();
shady::get_template(
shady::TemplateLang::Wgsl {
bind_group_index: 0,
},
&mut fragment_code,
)
.unwrap();
fragment_code
};

// SHADY
let shady = Shady::new(&ShadyDescriptor {
device: &device,
fragment_shader: &fragment_shader,
texture_format: surface_format,
bind_group_index: SHADY_BIND_GROUP_INDEX,
vertex_buffer_index: SHADY_VERTEX_BUFFER_INDEX,
})
.unwrap();

(config, shady)
};

Self {
surface,
device,
queue,
config,
window,
shady,
}
}

pub fn prepare_next_frame(&mut self) {
// SHADY
self.shady.prepare_next_frame(&mut self.queue);

self.surface.configure(&self.device, &self.config);
}

pub fn render(&mut self) {
let output = self.surface.get_current_texture().unwrap();
let view = output
.texture
.create_view(&TextureViewDescriptor::default());

let mut encoder = self
.device
.create_command_encoder(&wgpu::CommandEncoderDescriptor {
label: Some("Render encoder"),
});

self.shady.add_render_pass(&mut encoder, &view);

self.queue.submit(std::iter::once(encoder.finish()));
output.present();
}

pub fn window(&self) -> Arc<Window> {
self.window.clone()
}

pub fn resize(&mut self, new_size: PhysicalSize<u32>) {
// SHADY
self.shady
.update_resolution(new_size.width, new_size.height);
}
}

struct App<'a> {
state: Option<State<'a>>,
}

impl<'a> App<'a> {
pub fn new() -> Self {
Self { state: None }
}
}

impl<'a> ApplicationHandler<()> for App<'a> {
fn resumed(&mut self, event_loop: &ActiveEventLoop) {
let window = event_loop
.create_window(WindowAttributes::default())
.unwrap();

self.state = Some(State::new(window));
}

fn window_event(
&mut self,
event_loop: &ActiveEventLoop,
_window_id: WindowId,
event: WindowEvent,
) {
let Some(state) = &mut self.state else { return };
let window = state.window();

match event {
WindowEvent::CloseRequested => event_loop.exit(),
WindowEvent::RedrawRequested => {
window.request_redraw();
state.prepare_next_frame();
state.render();
}
WindowEvent::Resized(new_size) => state.resize(new_size),
WindowEvent::KeyboardInput { event, .. }
if event.logical_key.to_text() == Some("q") =>
{
event_loop.exit();
}
_ => (),
}
}
}

fn main() {
let event_loop = EventLoop::new().unwrap();
let mut app = App::new();

event_loop.run_app(&mut app).unwrap();
}
4 changes: 2 additions & 2 deletions shady-toy/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,15 @@ license = "GPL-3.0-or-later"
anyhow = "1"
ariadne = "0.5"
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
pollster = "0.4.0"
notify = "7"
shady = { path = "../shady-lib" }
winit = "0.30"

winit.workspace = true
wgpu.workspace = true
tracing.workspace = true
thiserror.workspace = true
clap.workspace = true
pollster.workspace = true

[dev-dependencies]
image = "0.25"
Expand Down

0 comments on commit 92f7b64

Please sign in to comment.