diff --git a/Cargo.lock b/Cargo.lock index a67d7d8..75b01df 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -96,6 +96,26 @@ version = "3.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "37ccbd214614c6783386c1af30caf03192f17891059cecc394b4fb119e363de3" +[[package]] +name = "bytemuck" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c53dfa917ec274df8ed3c572698f381a24eef2efba9492d797301b72b6db408a" +dependencies = [ + "bytemuck_derive", +] + +[[package]] +name = "bytemuck_derive" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "562e382481975bc61d11275ac5e62a19abd00b0547d99516a415336f183dcd0e" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "byteorder" version = "1.4.3" @@ -117,6 +137,7 @@ name = "canvas" version = "0.1.0" dependencies = [ "bitflags", + "bytemuck", "cgmath", "chrono", "fern", diff --git a/Cargo.toml b/Cargo.toml index 6303069..0b70a6d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,6 +6,7 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +# general dependencies log = "^0.4.17" chrono = "^0.4.19" fern = { version = "^0.6.1", features = ["colored"] } @@ -13,7 +14,11 @@ bitflags = "^1.3.2" cgmath = "^0.18.0" pollster = "^0.2.5" +# surface creation winit = "^0.26.1" raw-window-handle = "^0.4.3" +# gpu API wgpu = "^0.13.0" +bytemuck = { version = "1.4", features = [ "derive" ] } + diff --git a/src/renderer.rs b/src/renderer.rs index 58da394..938c29f 100644 --- a/src/renderer.rs +++ b/src/renderer.rs @@ -17,6 +17,7 @@ pub struct WgpuRenderer { config: wgpu::SurfaceConfiguration, size: Size, render_pipeline: wgpu::RenderPipeline, + quad_mesh: GpuMesh, } impl WgpuRenderer { @@ -62,24 +63,26 @@ impl WgpuRenderer { let render_pipeline = { let shader = device.create_shader_module(wgpu::ShaderModuleDescriptor { - label: Some("test shader"), - source: wgpu::ShaderSource::Wgsl(include_str!("shaders/test_shader.wgsl").into()), + label: Some("shape shader"), + source: wgpu::ShaderSource::Wgsl(include_str!("shaders/shape.wgsl").into()), }); let render_pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { - label: Some("test render pipeline layout"), + label: Some("shape render pipeline layout"), bind_group_layouts: &[], push_constant_ranges: &[], }); device.create_render_pipeline(&wgpu::RenderPipelineDescriptor { - label: Some("test render pipeline"), + label: Some("shape render pipeline"), layout: Some(&render_pipeline_layout), vertex: wgpu::VertexState { module: &shader, entry_point: "vs_main", - buffers: &[], + buffers: &[ + Vertex::desc(), + ], }, fragment: Some(wgpu::FragmentState { module: &shader, @@ -114,6 +117,8 @@ impl WgpuRenderer { }) }; + let quad_mesh = GpuMesh::create(&device, &QUAD); + Ok(Self { surface, device, @@ -121,6 +126,7 @@ impl WgpuRenderer { config, size, render_pipeline, + quad_mesh, }) } @@ -174,7 +180,10 @@ impl WgpuRenderer { }); render_pass.set_pipeline(&self.render_pipeline); - render_pass.draw(0..3, 0..1); + render_pass.set_vertex_buffer(0, self.quad_mesh.vertex_buffer.slice(..)); + render_pass.set_index_buffer(self.quad_mesh.index_buffer.slice(..), + wgpu::IndexFormat::Uint16); + render_pass.draw_indexed(0..self.quad_mesh.index_number, 0, 0..1); } self.queue.submit(std::iter::once(encoder.finish())); @@ -182,3 +191,78 @@ impl WgpuRenderer { } } +struct GpuMesh { + vertex_buffer: wgpu::Buffer, + index_buffer: wgpu::Buffer, + index_number: u32, +} + +impl GpuMesh { + + pub fn create(device: &wgpu::Device, mesh: &Mesh) -> Self { + use wgpu::util::DeviceExt; + + let vertex_buffer = device.create_buffer_init( + &wgpu::util::BufferInitDescriptor { + label: Some("Vertex Buffer"), + contents: bytemuck::cast_slice(mesh.vertices), + usage: wgpu::BufferUsages::VERTEX, + } + ); + + let index_buffer = device.create_buffer_init( + &wgpu::util::BufferInitDescriptor { + label: Some("Index Buffer"), + contents: bytemuck::cast_slice(mesh.indices), + usage: wgpu::BufferUsages::INDEX, + } + ); + + Self { + vertex_buffer, + index_buffer, + index_number: mesh.indices.len() as u32, + } + } +} + +//--Renderer struct utils--------------------------------------------------------------------------- +#[repr(C)] +#[derive(Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)] +struct Vertex { + pub position: [f32; 2], + pub color: [f32; 3], +} + +// lib.rs +impl Vertex { + + const ATTRIBS: [wgpu::VertexAttribute; 2] = + wgpu::vertex_attr_array![0 => Float32x2, 1 => Float32x3]; + + fn desc<'a>() -> wgpu::VertexBufferLayout<'a> { + wgpu::VertexBufferLayout { + array_stride: std::mem::size_of::() as wgpu::BufferAddress, + step_mode: wgpu::VertexStepMode::Vertex, + attributes: &Self::ATTRIBS, + } + } +} + +struct Mesh<'a> { + pub vertices: &'a[Vertex], + pub indices: &'a[u16], +} + +const QUAD: Mesh<'static> = Mesh { + vertices: &[ + Vertex { position: [0.0, 0.0], color: [1.0, 0.0, 0.0] }, + Vertex { position: [1.0, 0.0], color: [0.0, 1.0, 0.0] }, + Vertex { position: [1.0, 1.0], color: [0.0, 0.0, 1.0] }, + Vertex { position: [0.0, 1.0], color: [0.5, 0.5, 0.5] }, + ], + indices: &[ + 0, 1, 2, + 0, 2, 3, + ], +}; diff --git a/src/shaders/shape.wgsl b/src/shaders/shape.wgsl new file mode 100644 index 0000000..c0f99ea --- /dev/null +++ b/src/shaders/shape.wgsl @@ -0,0 +1,28 @@ +// Vertex shader + +struct VertexInput { + @location(0) position: vec2, + @location(1) color: vec3, +}; + +struct VertexOutput { + @builtin(position) clip_position: vec4, + @location(0) color: vec3, +}; + +@vertex +fn vs_main(model: VertexInput) -> VertexOutput { + + var out: VertexOutput; + out.color = model.color; + out.clip_position = vec4(model.position, 0.0, 1.0); + return out; +} + +// Fragment shader + +@fragment +fn fs_main(in: VertexOutput) -> @location(0) vec4 { + return vec4(in.color, 1.0); +} +