diff --git a/src/.bin/shader.vert.spv b/src/.bin/shader.vert.spv index dd48e11..8179875 100644 Binary files a/src/.bin/shader.vert.spv and b/src/.bin/shader.vert.spv differ diff --git a/src/app.rs b/src/app.rs index 69e4dc7..bc10574 100644 --- a/src/app.rs +++ b/src/app.rs @@ -5,6 +5,7 @@ use futures::executor::block_on; use crate::vertex::Vertex; use crate::texture::Texture; use crate::camera::Camera; +use crate::uniforms::Uniforms; const VERTICES: &[Vertex] = &[ Vertex { position: [-1.0, 1.0, 0.0], uv: [0.0, 0.0] }, @@ -28,6 +29,9 @@ pub struct App { // Buffers vertex_buffer: wgpu::Buffer, index_buffer: wgpu::Buffer, + uniform_buffer: wgpu::Buffer, + // Uniform bind group + uniform_bind_group: wgpu::BindGroup, // Texture bind_group: wgpu::BindGroup, // Camera @@ -143,6 +147,37 @@ impl App { (bind_group_layout, bind_group) } + fn create_uniform_bind_group(device: &wgpu::Device, buf: &wgpu::Buffer) -> (wgpu::BindGroupLayout, wgpu::BindGroup) { + let uniform_bind_group_layout = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { + entries: &[ + wgpu::BindGroupLayoutEntry { + binding: 0, + visibility: wgpu::ShaderStage::VERTEX, + ty: wgpu::BindingType::Buffer { + ty: wgpu::BufferBindingType::Uniform, + has_dynamic_offset: false, + min_binding_size: None, + }, + count: None, + } + ], + label: Some("uniform_bind_group_layout"), + }); + + let uniform_bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor { + layout: &uniform_bind_group_layout, + entries: &[ + wgpu::BindGroupEntry { + binding: 0, + resource: buf.as_entire_binding(), + } + ], + label: Some("uniform_bind_group"), + }); + + (uniform_bind_group_layout, uniform_bind_group) + } + fn create_buffer(device: &wgpu::Device, usage: wgpu::BufferUsage, content: &[u8]) -> wgpu::Buffer { device.create_buffer_init( &wgpu::util::BufferInitDescriptor { @@ -153,6 +188,7 @@ impl App { ) } + pub async fn new(window: &Window) -> Self { // Create surface and pick device @@ -171,24 +207,29 @@ impl App { // Create swapchain let (swapchain_desc, swapchain) = Self::create_swapchain(&adapter, &device, &surface, window.inner_size()); - // Load image - let tex = Texture::from_file(&device, &queue, "./assets/rick.png"); - let (bind_group_layout, bind_group) = Self::create_bind_group(&device, &tex); - - // Pipeline - let pipeline = Self::create_pipeline(&device, &swapchain_desc, &[&bind_group_layout]); + // Cam + let aspect = swapchain_desc.width as f32 / swapchain_desc.height as f32; + let camera = Camera::new((0.0, 1.0, 2.0).into(), (0.0, 0.0, 0.0).into(), aspect); + let mut uniforms = Uniforms::new(); + uniforms.update_projection_matrix(&camera); // Buffers let vertex_buffer = Self::create_buffer(&device, wgpu::BufferUsage::VERTEX, bytemuck::cast_slice(VERTICES)); let index_buffer = Self::create_buffer(&device, wgpu::BufferUsage::INDEX, bytemuck::cast_slice(INDICES)); + let uniform_buffer = Self::create_buffer(&device, wgpu::BufferUsage::UNIFORM | wgpu::BufferUsage::COPY_DST, bytemuck::cast_slice(&[uniforms])); - // Cam - let aspect = swapchain_desc.width as f32 / swapchain_desc.height as f32; - let camera = Camera::new((0.0, 1.0, 2.0).into(), (0.0, 0.0, 0.0).into(), aspect); + // Load image + let tex = Texture::from_file(&device, &queue, "./assets/rick.png"); + let (bind_group_layout, bind_group) = Self::create_bind_group(&device, &tex); + let (uniform_bind_group_layout, uniform_bind_group) = Self::create_uniform_bind_group(&device, &uniform_buffer); + + // Pipeline + let bind_groups = [&bind_group_layout, &uniform_bind_group_layout]; + let pipeline = Self::create_pipeline(&device, &swapchain_desc, &bind_groups); // Save values in app println!("Initialized"); - Self { surface, device, queue, swapchain_desc, swapchain, pipeline, vertex_buffer, index_buffer, bind_group, camera } + Self { surface, device, queue, swapchain_desc, swapchain, pipeline, vertex_buffer, index_buffer, uniform_buffer, bind_group, uniform_bind_group, camera, } } pub fn resize(&mut self, new_size: Option>) { @@ -240,6 +281,7 @@ impl App { render_pass.set_pipeline(&self.pipeline); render_pass.set_bind_group(0, &self.bind_group, &[]); + render_pass.set_bind_group(1, &self.uniform_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/main.rs b/src/main.rs index 7414768..2807281 100644 --- a/src/main.rs +++ b/src/main.rs @@ -7,6 +7,7 @@ use winit::{ mod vertex; mod texture; +mod uniforms; mod camera; mod app; use app::App; diff --git a/src/shader.vert b/src/shader.vert index 3731eb2..9e6efef 100644 --- a/src/shader.vert +++ b/src/shader.vert @@ -4,9 +4,13 @@ layout(location=0) in vec3 in_position; layout(location=1) in vec2 in_uv; layout(location=0) out vec2 vert_uv; +layout(set=1, binding=0) uniform Uniforms +{ + mat4 view_projection; +}; void main() { vert_uv = in_uv; - gl_Position = vec4(in_position, 1.0); + gl_Position = view_projection * vec4(in_position, 1.0); } \ No newline at end of file diff --git a/src/uniforms.rs b/src/uniforms.rs index e07deb0..6dbd372 100644 --- a/src/uniforms.rs +++ b/src/uniforms.rs @@ -1,22 +1,23 @@ -// We need this for Rust to store our data correctly for the shaders +use cgmath::SquareMatrix; + +use crate::camera::Camera; + + #[repr(C)] -// This is so we can store this in a buffer #[derive(Debug, Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)] -struct Uniforms { - // We can't use cgmath with bytemuck directly so we'll have - // to convert the Matrix4 into a 4x4 f32 array +pub struct Uniforms { view_proj: [[f32; 4]; 4], } impl Uniforms { - fn new() -> Self { - use cgmath::SquareMatrix; + + pub fn new() -> Self { Self { view_proj: cgmath::Matrix4::identity().into(), } } - fn update_view_proj(&mut self, camera: &Camera) { - self.view_proj = camera.build_view_projection_matrix().into(); + pub fn update_projection_matrix(&mut self, camera: &Camera) { + self.view_proj = camera.projection_matrix().into(); } }