diff --git a/Cargo.lock b/Cargo.lock index 0e7dd8175..f56d29472 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2576,7 +2576,7 @@ version = "0.1.0" dependencies = [ "audrey", "futures 0.3.30", - "hotglsl", + "hotglsl 0.2.0 (git+https://github.com/nannou-org/hotglsl?branch=master)", "hound", "hrtf", "nannou", @@ -3328,6 +3328,16 @@ dependencies = [ "thiserror", ] +[[package]] +name = "hotglsl" +version = "0.2.0" +source = "git+https://github.com/nannou-org/hotglsl?branch=master#534b2288809f4ada29089d27425a2064f8cacdcd" +dependencies = [ + "naga 0.14.2", + "notify", + "thiserror", +] + [[package]] name = "hound" version = "3.5.1" @@ -4406,7 +4416,7 @@ dependencies = [ name = "nannou_isf" version = "0.1.0" dependencies = [ - "hotglsl", + "hotglsl 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "isf", "nannou", "thiserror", diff --git a/bevy_nannou/assets/images/img.png b/bevy_nannou/assets/images/img.png new file mode 100644 index 000000000..c02067d32 Binary files /dev/null and b/bevy_nannou/assets/images/img.png differ diff --git a/bevy_nannou/src/lib.rs b/bevy_nannou/src/lib.rs index 20934fae5..5d0b5fb44 100644 --- a/bevy_nannou/src/lib.rs +++ b/bevy_nannou/src/lib.rs @@ -1,5 +1,7 @@ use bevy::prelude::*; -use bevy_nannou_render::mesh::{Vertex, ViewMesh}; +use bevy::prelude::shape::Cube; + +use bevy_nannou_render::mesh::ViewMesh; pub struct NannouPlugin; @@ -12,22 +14,36 @@ impl Plugin for NannouPlugin { } } -fn setup(mut commands: Commands) { +fn setup( + mut commands: Commands, + assets: Res, + mut meshes: ResMut>, + mut materials: ResMut>, +) { let mut mesh = ViewMesh::default(); + let image = assets.load("images/img.png"); + mesh.texture = Some(image); mesh.extend_from_slices( &[ - Vec3::new(-512.0, -384.0, 0.0), - Vec3::new(-512.0, 384.0, 0.0), - Vec3::new(512.0, 384.0, 0.0), + Vec3::new(-512.0, -512.0, 0.0), + Vec3::new(512.0, -512.0, 0.0), + Vec3::new(-512.0, 512.0, 0.0), + Vec3::new(512.0, 512.0, 0.0), + ], + &[1, 0, 2, 1, 2, 3], + &[Vec4::new(1.0, 0.0, 0.0, 1.0); 4], + &[ + Vec2::new(0.0, 1.0), + Vec2::new(1.0, 1.0), + Vec2::new(0.0, 0.0), + Vec2::new(1.0, 0.0), ], - &[0, 1, 2], - &[Vec4::new(1.0, 0.0, 0.0, 1.0); 3], - &[Vec2::new(0.0, 0.0); 3], ); commands.spawn(( Camera3dBundle { transform: Transform::from_xyz(0.0, 0.0, -10.0).looking_at(Vec3::ZERO, Vec3::Z), projection: OrthographicProjection { + scale: 1.0, ..Default::default() } .into(), @@ -35,6 +51,16 @@ fn setup(mut commands: Commands) { }, mesh, )); + commands.insert_resource(AmbientLight { + color: Color::WHITE, + brightness: 1.0, + }); + commands.spawn(PbrBundle { + mesh: meshes.add(Mesh::from(Cube::new(10.0))), + material: materials.add(Color::rgb(1.0, 1.0, 1.0).into()), + transform: Transform::from_xyz(0.0, 0.0, 0.0), + ..Default::default() + }); } #[cfg(test)] diff --git a/bevy_nannou_render/src/mesh/mod.rs b/bevy_nannou_render/src/mesh/mod.rs index f526414dd..711511816 100644 --- a/bevy_nannou_render/src/mesh/mod.rs +++ b/bevy_nannou_render/src/mesh/mod.rs @@ -27,6 +27,7 @@ pub type MeshType = #[derive(Component, Debug, Clone, ExtractComponent)] pub struct ViewMesh { mesh: MeshType, + pub texture: Option>, } impl ViewMesh { @@ -183,7 +184,7 @@ impl ViewMesh { impl Default for ViewMesh { fn default() -> Self { let mesh = Default::default(); - ViewMesh { mesh } + ViewMesh { mesh, texture: None } } } diff --git a/bevy_nannou_render/src/pipeline.rs b/bevy_nannou_render/src/pipeline.rs index ac7f7380c..9bf0bb9bd 100644 --- a/bevy_nannou_render/src/pipeline.rs +++ b/bevy_nannou_render/src/pipeline.rs @@ -5,6 +5,7 @@ use std::hash::{Hash, Hasher}; use bevy::ecs::query::QueryItem; use bevy::prelude::*; use bevy::render::camera::ExtractedCamera; +use bevy::render::render_asset::RenderAssets; use bevy::render::render_graph::{NodeRunError, RenderGraphContext, ViewNode}; use bevy::render::render_resource as wgpu; use bevy::render::render_resource::{ @@ -19,7 +20,7 @@ use bevy::utils; use crate::mesh::vertex::Point; use crate::mesh::{TexCoords, ViewMesh}; -use crate::{GlyphCache, NANNOU_SHADER_HANDLE, VertexMode, ViewUniformBindGroup}; +use crate::{GlyphCache, mesh, NANNOU_SHADER_HANDLE, VertexMode, ViewUniformBindGroup}; #[derive(Resource)] pub struct NannouPipeline { @@ -28,7 +29,6 @@ pub struct NannouPipeline { text_bind_group_layout: wgpu::BindGroupLayout, text_bind_group: wgpu::BindGroup, texture_samplers: HashMap, - // TODO: move to resource and support multiple textures. texture_bind_group_layout: wgpu::BindGroupLayout, texture_bind_group: wgpu::BindGroup, output_color_format: wgpu::TextureFormat, @@ -96,13 +96,13 @@ impl NannouPipeline { offset: 0, shader_location: 0, }]) - .add_vertex_buffer::(&[wgpu::VertexAttribute { - format: wgpu::VertexFormat::Float32x3, + .add_vertex_buffer::(&[wgpu::VertexAttribute { + format: wgpu::VertexFormat::Float32x4, offset: 0, shader_location: 1, }]) - .add_vertex_buffer::(&[wgpu::VertexAttribute { - format: wgpu::VertexFormat::Float32x3, + .add_vertex_buffer::(&[wgpu::VertexAttribute { + format: wgpu::VertexFormat::Float32x2, offset: 0, shader_location: 2, }]) @@ -148,7 +148,7 @@ impl NannouPipeline { .build(device, layout) } - fn create_texture_bind_group( + pub fn create_texture_bind_group( device: &RenderDevice, layout: &wgpu::BindGroupLayout, sampler: &wgpu::Sampler, @@ -364,7 +364,9 @@ impl ViewNode for NannouViewNode { // Create render pass builder. let render_pass_builder = bevy_nannou_wgpu::RenderPassBuilder::new() - .color_attachment(target.main_texture_view(), |color| color); + .color_attachment(target.main_texture_view(), |color| + color.load_op(wgpu::LoadOp::Load) // TODO: bg color + ); let render_device = render_context.render_device(); @@ -372,7 +374,7 @@ impl ViewNode for NannouViewNode { let points_bytes = cast_slice(&mesh.points()[..]); let colors_bytes = cast_slice(mesh.colors()); let tex_coords_bytes = cast_slice(mesh.tex_coords()); - // let modes_bytes = vertex_modes_as_bytes(vertex_mode_buffer); + let modes_bytes = cast_slice(&[VertexMode::Texture as u32; 4]); let indices_bytes = cast_slice(mesh.indices()); let point_buffer = render_device.create_buffer_with_data(&BufferInitDescriptor { label: Some("nannou Renderer point_buffer"), @@ -391,7 +393,7 @@ impl ViewNode for NannouViewNode { }); let mode_buffer = render_device.create_buffer_with_data(&BufferInitDescriptor { label: Some("nannou Renderer mode_buffer"), - contents: &[], + contents: modes_bytes, usage: vertex_usage, }); let index_buffer = render_device.create_buffer_with_data(&BufferInitDescriptor { @@ -400,6 +402,30 @@ impl ViewNode for NannouViewNode { usage: wgpu::BufferUsages::INDEX, }); + let texture_bind_group = match &mesh.texture { + Some(texture) => { + let images = world.resource::>(); + if let Some(gpu_image) = images.get(texture) { + let texture_bind_group_layout = NannouPipeline::create_texture_bind_group_layout( + render_device, + true, + wgpu::TextureSampleType::Float { filterable: true }, + ); + NannouPipeline::create_texture_bind_group( + render_device, + &texture_bind_group_layout, + &gpu_image.sampler, + &gpu_image.texture_view, + ) + } else { + nannou_pipeline.texture_bind_group.clone() + } + } + None => { + nannou_pipeline.texture_bind_group.clone() + } + }; + let mut render_pass = render_pass_builder.begin(render_context); render_pass.set_render_pipeline(pipeline); @@ -414,7 +440,7 @@ impl ViewNode for NannouViewNode { let uniform_bind_group = world.resource::(); render_pass.set_bind_group(0, &uniform_bind_group.bind_group, &[]); render_pass.set_bind_group(1, &nannou_pipeline.text_bind_group, &[]); - render_pass.set_bind_group(2, &nannou_pipeline.texture_bind_group, &[]); + render_pass.set_bind_group(2, &texture_bind_group, &[]); // Draw the mesh. let indices = 0..mesh.indices().len() as u32; diff --git a/bevy_nannou_render/src/shaders/nannou.wgsl b/bevy_nannou_render/src/shaders/nannou.wgsl index a05536253..2d8e9be7a 100644 --- a/bevy_nannou_render/src/shaders/nannou.wgsl +++ b/bevy_nannou_render/src/shaders/nannou.wgsl @@ -22,9 +22,8 @@ struct VertexOutput { fn vertex( input: VertexInput, ) -> VertexOutput { - let out_pos: vec4 = view.projection * vec4(input.position, 1.0); + let out_pos: vec4 = view.view_proj * vec4(input.position, 1.0); return VertexOutput(input.color, input.tex_coords, input.mode, out_pos); - } // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ FRAGMENT ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // diff --git a/examples/Cargo.toml b/examples/Cargo.toml index 149c6589c..f205b2613 100644 --- a/examples/Cargo.toml +++ b/examples/Cargo.toml @@ -15,7 +15,7 @@ edition = "2018" [dev-dependencies] audrey = "0.3" -hotglsl = "0.2" +hotglsl = { git = "https://github.com/nannou-org/hotglsl", branch = "master" } hrtf = "0.2" nannou = { version ="0.19.0", path = "../nannou" } nannou_audio = { version ="0.19.0", path = "../nannou_audio" } diff --git a/examples/draw/draw_textured_polygon.rs b/examples/draw/draw_textured_polygon.rs index 1dde60c63..51bc7e9f8 100644 --- a/examples/draw/draw_textured_polygon.rs +++ b/examples/draw/draw_textured_polygon.rs @@ -6,8 +6,7 @@ fn main() { struct Model { window_id: window::Id, - texture_a: wgpu::Texture, - texture_b: wgpu::Texture, + texture: wgpu::Texture, } fn model(app: &App) -> Model { @@ -16,11 +15,9 @@ fn model(app: &App) -> Model { // Load the image from disk and upload it to a GPU texture. let assets = app.assets_path().unwrap(); let img_path = assets.join("images").join("nature").join("nature_1.jpg"); - let texture_a = wgpu::Texture::from_path(app, img_path).unwrap(); - let img_path = assets.join("images").join("nature").join("nature_2.jpg"); - let texture_b = wgpu::Texture::from_path(app, img_path).unwrap(); + let texture = wgpu::Texture::from_path(app, img_path).unwrap(); - Model { window_id, texture_a, texture_b } + Model { window_id, texture } } // Draw the state of your `Model` into the given `Frame` here. @@ -58,17 +55,9 @@ fn view(app: &App, model: &Model, frame: Frame) { let ellipse_side = win_rect.w().min(win_rect.h()) * 0.75; draw.scale(ellipse_side) .polygon() - .points_textured(&model.texture_a, points.clone()) + .points_textured(&model.texture, points) .rotate(app.time * 0.25); - // Scale the points up to half the window size. - let ellipse_side = win_rect.w().min(win_rect.h()) * 0.75; - draw.scale(ellipse_side) - .polygon() - .points_textured(&model.texture_b, points) - .rotate(app.time * 0.11); - - // Draw to the frame! draw.to_frame(app, &frame).unwrap(); }