diff --git a/assets/rick.png b/assets/rick.png new file mode 100644 index 0000000..f31af78 Binary files /dev/null and b/assets/rick.png differ diff --git a/src/.bin/shader.frag.spv b/src/.bin/shader.frag.spv index 226a1d5..bc8ab0f 100644 Binary files a/src/.bin/shader.frag.spv and b/src/.bin/shader.frag.spv differ diff --git a/src/app.rs b/src/app.rs index e557417..e96d201 100644 --- a/src/app.rs +++ b/src/app.rs @@ -1,12 +1,15 @@ use winit::{window::Window, dpi::PhysicalSize, event::WindowEvent}; use wgpu::util::DeviceExt; +use std::path::Path; +use image::GenericImageView; + use crate::vertex::Vertex; const VERTICES: &[Vertex] = &[ - Vertex { position: [-0.5, 0.5, 0.0], uv: [0.0, 1.0] }, - Vertex { position: [ 0.5, 0.5, 0.0], uv: [1.0, 1.0] }, - Vertex { position: [ 0.5,-0.5, 0.0], uv: [1.0, 0.0] }, - Vertex { position: [-0.5,-0.5, 0.0], uv: [0.0, 0.0] }, + Vertex { position: [-1.0, 1.0, 0.0], uv: [0.0, 0.0] }, + Vertex { position: [ 1.0, 1.0, 0.0], uv: [1.0, 0.0] }, + Vertex { position: [ 1.0,-1.0, 0.0], uv: [1.0, 1.0] }, + Vertex { position: [-1.0,-1.0, 0.0], uv: [0.0, 1.0] }, ]; const INDICES: &[u16] = &[ @@ -24,6 +27,8 @@ pub struct App { // Buffers vertex_buffer: wgpu::Buffer, index_buffer: wgpu::Buffer, + // Texture + diffuse_bind_group: wgpu::BindGroup } impl App { @@ -65,10 +70,103 @@ impl App { }; let swapchain = device.create_swap_chain(&surface, &swapchain_desc); + // Load image + let img_path = Path::new("./assets/rick.png"); + let img = image::open(img_path).unwrap(); + let img_dim = img.dimensions(); + let img_data = img.as_rgba8().unwrap(); + + let texture_size = wgpu::Extent3d { width: img_dim.0, height: img_dim.1, depth: 1, }; + let texture_desc = wgpu::TextureDescriptor { + size: texture_size, + mip_level_count: 1, + sample_count: 1, + dimension: wgpu::TextureDimension::D2, + format: wgpu::TextureFormat::Rgba8UnormSrgb, + usage: wgpu::TextureUsage::SAMPLED | wgpu::TextureUsage::COPY_DST, + label: Some("diffuse_texture"), + }; + let texture = device.create_texture(&texture_desc); + + queue.write_texture( + // Tells wgpu where to copy the pixel data + wgpu::TextureCopyView { + texture: &texture, + mip_level: 0, + origin: wgpu::Origin3d::ZERO, + }, + // The actual pixel data + img_data, + // The layout of the texture + wgpu::TextureDataLayout { + offset: 0, + bytes_per_row: 4 * img_dim.0, + rows_per_image: img_dim.1, + }, + texture_size, + ); + + let diffuse_texture_view = texture.create_view(&wgpu::TextureViewDescriptor::default()); + let diffuse_sampler = device.create_sampler(&wgpu::SamplerDescriptor { + address_mode_u: wgpu::AddressMode::ClampToEdge, + address_mode_v: wgpu::AddressMode::ClampToEdge, + address_mode_w: wgpu::AddressMode::ClampToEdge, + mag_filter: wgpu::FilterMode::Linear, + min_filter: wgpu::FilterMode::Nearest, + mipmap_filter: wgpu::FilterMode::Nearest, + ..Default::default() + }); + + let texture_bind_group_layout = device.create_bind_group_layout( + &wgpu::BindGroupLayoutDescriptor { + entries: &[ + wgpu::BindGroupLayoutEntry { + binding: 0, + visibility: wgpu::ShaderStage::FRAGMENT, + ty: wgpu::BindingType::Texture { + multisampled: false, + view_dimension: wgpu::TextureViewDimension::D2, + sample_type: wgpu::TextureSampleType::Float { filterable: false }, + }, + count: None, + }, + wgpu::BindGroupLayoutEntry { + binding: 1, + visibility: wgpu::ShaderStage::FRAGMENT, + ty: wgpu::BindingType::Sampler { + comparison: false, + filtering: true, + }, + count: None, + }, + ], + label: Some("texture_bind_group_layout"), + } + ); + + let diffuse_bind_group = device.create_bind_group( + &wgpu::BindGroupDescriptor { + layout: &texture_bind_group_layout, + entries: &[ + wgpu::BindGroupEntry { + binding: 0, + resource: wgpu::BindingResource::TextureView(&diffuse_texture_view), + }, + wgpu::BindGroupEntry { + binding: 1, + resource: wgpu::BindingResource::Sampler(&diffuse_sampler), + } + ], + label: Some("diffuse_bind_group"), + } + ); + + + // Pipeline stuff let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { label: Some("Render Pipeline Layout"), - bind_group_layouts: &[], + bind_group_layouts: &[&texture_bind_group_layout], push_constant_ranges: &[], }); let vert_state = wgpu::VertexState { //vert @@ -130,7 +228,7 @@ impl App { // Save values in app println!("Initialized"); - Self { surface, device, queue, swapchain_desc, swapchain, pipeline, vertex_buffer, index_buffer } + Self { surface, device, queue, swapchain_desc, swapchain, pipeline, vertex_buffer, index_buffer, diffuse_bind_group } } pub fn resize(&mut self, new_size: Option>) { @@ -181,6 +279,7 @@ impl App { }); render_pass.set_pipeline(&self.pipeline); + render_pass.set_bind_group(0, &self.diffuse_bind_group, &[]); render_pass.set_vertex_buffer(0, self.vertex_buffer.slice(..)); render_pass.set_index_buffer(self.index_buffer.slice(..), wgpu::IndexFormat::Uint16); render_pass.draw_indexed(0..(INDICES.len() as u32), 0, 0..1); diff --git a/src/shader.frag b/src/shader.frag index b4ca97f..d971b97 100644 --- a/src/shader.frag +++ b/src/shader.frag @@ -4,7 +4,10 @@ layout(location=0) in vec2 vert_uv; layout(location=0) out vec4 frag_color; +layout(set=0, binding=0) uniform texture2D tex; +layout(set=0, binding=1) uniform sampler tex_smp; + void main() { - frag_color = vec4(vert_uv, 0.0, 1.0); + frag_color = texture(sampler2D(tex, tex_smp), vert_uv); } \ No newline at end of file