Skip to content

Commit

Permalink
Video material example.
Browse files Browse the repository at this point in the history
  • Loading branch information
tychedelia committed Jul 8, 2024
1 parent 84d62f8 commit f821270
Show file tree
Hide file tree
Showing 6 changed files with 104 additions and 18 deletions.
7 changes: 2 additions & 5 deletions bevy_nannou_video/src/asset.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,21 +25,18 @@ impl Plugin for VideoAssetPlugin {
}

fn load_next_frame(
video_q: Query<&Handle<Video>>,
mut videos: ResMut<Assets<Video>>,
mut images: ResMut<Assets<Image>>,
time: Res<Time>,
) {
for handle in video_q.iter() {
let video = videos.get_mut(handle).unwrap();
for (_, video) in videos.iter_mut() {
let current_time = time.elapsed_seconds_f64();
if current_time - video.last_update < video.frame_duration {
continue; // Not time for next frame yet
}
video.last_update = current_time;
if let Some(next_texture) = video.next_texture() {
let texture = images.get_mut(&video.texture).unwrap();
*texture = next_texture;
video.texture = images.add(next_texture);
}
}
}
Expand Down
4 changes: 4 additions & 0 deletions examples/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -226,4 +226,8 @@ required-features = ["egui"]
[[example]]
name = "simple_video"
path = "video/simple_video.rs"
required-features = ["video"]
[[example]]
name = "video_material"
path = "video/video_material.rs"
required-features = ["video"]
23 changes: 23 additions & 0 deletions examples/assets/draw_video_material.wgsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#import bevy_pbr::{
mesh_view_bindings::view,
mesh_view_bindings::globals,
forward_io::VertexOutput,
}

@group(2) @binding(0) var texture: texture_2d<f32>;
@group(2) @binding(1) var texture_sampler: sampler;

@fragment
fn fragment(
mesh: VertexOutput,
) -> @location(0) vec4<f32> {
let resolution = view.viewport.zw;
let time = globals.time;
var uv = mesh.uv * resolution;
let cp = -1.0 + 2.0 * uv / resolution;
let cl = length(cp);
uv = uv / resolution + (cp / cl) * cos(cl * 12.0 - time * 1.0) * 0.02;
let clamped_uv = clamp(uv, vec2<f32>(0.0), vec2<f32>(1.0));
let col = textureSample(texture, texture_sampler, clamped_uv).xyz;
return vec4<f32>(col, 1.0);
}
Binary file modified examples/assets/video/file_example_MP4_640_3MG.mp4
Binary file not shown.
19 changes: 6 additions & 13 deletions examples/video/simple_video.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use nannou::noise::NoiseFn;
use nannou::prelude::*;

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

#[derive(Reflect)]
Expand All @@ -22,28 +22,21 @@ fn model(app: &App) -> Model {
.view(view)
.build();

let video = app.asset_server().load_with_settings(
"video/file_example_MP4_640_3MG.mp4",
|settings: &mut VideoLoaderSettings| {
settings
.options
.insert("sws_flags".to_string(), "fast_bilinear".to_string());
},
);
let video = app
.asset_server()
.load("video/file_example_MP4_640_3MG.mp4");
Model {
window,
camera,
video,
}
}

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

fn view(app: &App, model: &Model) {
let Some(video) = app.assets().get(&model.video) else {
return;
};

let draw = app.draw();
draw.rect().w_h(100.0, 100.0).texture(&video.texture);
draw.rect()
.w_h(640.0, 400.0).texture(&video.texture);
}
69 changes: 69 additions & 0 deletions examples/video/video_material.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
use nannou::noise::NoiseFn;
use nannou::prelude::*;

fn main() {
nannou::app(model)
// Register our custom material to make it available for use in our drawing
.init_custom_material::<VideoMaterial>()
.run();
}

#[derive(Reflect)]
struct Model {
window: Entity,
camera: Entity,
video: Handle<Video>,
}

// This struct defines the data that will be passed to your shader
#[derive(Asset, TypePath, AsBindGroup, Debug, Clone, Default)]
struct VideoMaterial {
#[texture(0)]
#[sampler(1)]
texture: Handle<Image>,
}

impl Material for VideoMaterial {
fn fragment_shader() -> ShaderRef {
"draw_video_material.wgsl".into()
}
}

fn model(app: &App) -> Model {
let camera = app.new_camera().build();
let window = app
.new_window()
.camera(camera)
.primary()
.size_pixels(1024, 512)
.view(view)
.build();

let video = app.asset_server().load_with_settings(
"video/file_example_MP4_640_3MG.mp4",
|settings: &mut VideoLoaderSettings| {
settings
.options
.insert("hwaccel".to_string(), "sasfd".to_string());
},
);
Model {
window,
camera,
video,
}
}

fn view(app: &App, model: &Model) {
let Some(video) = app.assets().get(&model.video) else {
return;
};

let draw = app
.draw()
// Initialize our draw instance with our custom material
.material(VideoMaterial { texture: video.texture.clone() });

draw.rect()
.w_h(640.0, 400.0);
}

0 comments on commit f821270

Please sign in to comment.