From 3a444d6e3a2d5dfb733845d194db35247888e0ba Mon Sep 17 00:00:00 2001 From: Piotrek Date: Mon, 26 Apr 2021 19:07:02 +0200 Subject: [PATCH] postprocess render pass --- build.rs | 2 +- src/renderer/mod.rs | 26 +++- src/renderer/passes/mod.rs | 5 +- src/renderer/passes/postprocess.rs | 120 +++++++++++++++++- src/renderer/passes/raytrace.rs | 13 +- .../fullscreen.vert.spv} | Bin 1360 -> 1360 bytes src/shaders/{shader.vert => fullscreen.vert} | 4 +- src/shaders/postprocess/.bin/main.frag.spv | Bin 0 -> 1572 bytes src/shaders/postprocess/main.frag | 22 ++++ .../.bin/main.frag.spv} | Bin 14488 -> 14488 bytes .../{shader.frag => raytrace/main.frag} | 11 +- src/shaders/{ => raytrace}/raycasting.cginc | 0 src/shaders/{ => raytrace}/shading.cginc | 0 src/shaders/{ => raytrace}/structs.cginc | 0 14 files changed, 179 insertions(+), 24 deletions(-) rename src/shaders/{bin/shader.vert.spv => .bin/fullscreen.vert.spv} (95%) rename src/shaders/{shader.vert => fullscreen.vert} (76%) create mode 100644 src/shaders/postprocess/.bin/main.frag.spv create mode 100644 src/shaders/postprocess/main.frag rename src/shaders/{bin/shader.frag.spv => raytrace/.bin/main.frag.spv} (99%) rename src/shaders/{shader.frag => raytrace/main.frag} (89%) rename src/shaders/{ => raytrace}/raycasting.cginc (100%) rename src/shaders/{ => raytrace}/shading.cginc (100%) rename src/shaders/{ => raytrace}/structs.cginc (100%) diff --git a/build.rs b/build.rs index e3c2f29..feceb3d 100644 --- a/build.rs +++ b/build.rs @@ -19,7 +19,7 @@ impl ShaderData { let extension = src_path.extension().expect("File has no extension").to_str().unwrap(); // Create output path - let directory = src_path.parent().unwrap().join("bin"); + let directory = src_path.parent().unwrap().join(".bin"); create_dir_all(directory.clone()).expect("Failed to create output directory"); let spv_path = directory.join(filename).with_extension(format!("{}.spv", extension)); diff --git a/src/renderer/mod.rs b/src/renderer/mod.rs index 43e1131..5921456 100644 --- a/src/renderer/mod.rs +++ b/src/renderer/mod.rs @@ -5,7 +5,7 @@ pub mod buffers; use buffers::Buffers; mod passes; -use passes::RaytracePass; +use passes::{RaytracePass, PostprocessPass}; pub mod camera; use camera::Camera; @@ -17,7 +17,10 @@ pub struct Renderer { queue: wgpu::Queue, swapchain_desc: wgpu::SwapChainDescriptor, swapchain: wgpu::SwapChain, + // Passes + texture: wgpu::TextureView, raytrace_pass: RaytracePass, + postprocess_pass: PostprocessPass, // Buffers buffers: Buffers, // Other @@ -58,16 +61,32 @@ impl Renderer { let aspect = swapchain_desc.width as f32 / swapchain_desc.height as f32; let camera = Camera::new(aspect, 60.0); + // Middleman texture + let mut texture_descriptor = wgpu::TextureDescriptor { + label: Some("glow_post_process_texture1"), + size: wgpu::Extent3d { width: swapchain_desc.width, + height: swapchain_desc.height, + depth: 1, + }, + mip_level_count: 1, + sample_count: 1, + dimension: wgpu::TextureDimension::D2, + format: swapchain_desc.format, + usage: wgpu::TextureUsage::SAMPLED | wgpu::TextureUsage::RENDER_ATTACHMENT, + }; + let texture = device.create_texture(&texture_descriptor).create_view(&wgpu::TextureViewDescriptor::default()); + // Pipeline let buffers = Buffers::new(&device); let raytrace_pass = RaytracePass::new(&device, &swapchain_desc, &buffers); + let postprocess_pass = PostprocessPass::new(&device, &swapchain_desc, &texture); // Other let start = std::time::Instant::now(); let changed_bricks: Vec = Vec::new(); println!("Initialized"); - Self { surface, device, queue, swapchain_desc, swapchain, raytrace_pass, buffers, camera, start, changed_bricks } + Self { surface, device, queue, swapchain_desc, swapchain, texture, raytrace_pass, postprocess_pass, buffers, camera, start, changed_bricks } } /* @@ -117,7 +136,8 @@ impl Renderer { // Create encoder that will build command buffer for us let mut encoder = self.device.create_command_encoder(&wgpu::CommandEncoderDescriptor { label: Some("Render Encoder"),}); - self.raytrace_pass.render(&mut encoder, &mut self.buffers, &frame.view); + self.raytrace_pass.render(&mut encoder, &mut self.buffers, &self.texture);//&frame.view); + self.postprocess_pass.render(&mut encoder, &frame.view); // Submit encoder (command buffer) self.queue.submit(std::iter::once(encoder.finish())); diff --git a/src/renderer/passes/mod.rs b/src/renderer/passes/mod.rs index 21eb545..8597fb8 100644 --- a/src/renderer/passes/mod.rs +++ b/src/renderer/passes/mod.rs @@ -1,3 +1,6 @@ mod raytrace; -pub use raytrace::RaytracePass; \ No newline at end of file +pub use raytrace::RaytracePass; + +mod postprocess; +pub use postprocess::PostprocessPass; \ No newline at end of file diff --git a/src/renderer/passes/postprocess.rs b/src/renderer/passes/postprocess.rs index 0605dd1..9726713 100644 --- a/src/renderer/passes/postprocess.rs +++ b/src/renderer/passes/postprocess.rs @@ -1,9 +1,123 @@ pub struct PostprocessPass { - pub pipeline: wgpu::RenderPipeline + pipeline: wgpu::RenderPipeline, + bind_group: wgpu::BindGroup } impl PostprocessPass { - pub fn new(device: &wgpu::Device, swapchain_desc: &wgpu::SwapChainDescriptor) -> Self { - + pub fn new(device: &wgpu::Device, swapchain_desc: &wgpu::SwapChainDescriptor, texture_view: &wgpu::TextureView) -> Self { + + // Vertex shader + let vert_state = wgpu::VertexState { + module: &device.create_shader_module(&wgpu::include_spirv!("..\\..\\shaders\\.bin\\fullscreen.vert.spv")), + entry_point: "main", + buffers: &[], + }; + + // Fragment shader + let frag_state = wgpu::FragmentState { + module: &device.create_shader_module(&wgpu::include_spirv!("..\\..\\shaders\\postprocess\\.bin\\main.frag.spv")), + entry_point: "main", + targets: &[wgpu::ColorTargetState { + format: swapchain_desc.format, + alpha_blend: wgpu::BlendState::REPLACE, //TODO: Change to correct + color_blend: wgpu::BlendState::REPLACE, + write_mask: wgpu::ColorWrite::ALL, + }], + }; + + // Create bind layout + let bind_layout = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { + label: Some("Post process bind layout"), + entries: &[ + wgpu::BindGroupLayoutEntry { + binding: 0, + visibility: wgpu::ShaderStage::FRAGMENT, + ty: wgpu::BindingType::Texture { + sample_type: wgpu::TextureSampleType::Float { filterable: true }, + view_dimension: wgpu::TextureViewDimension::D2, + multisampled: false, + }, + count: None, + }, + wgpu::BindGroupLayoutEntry { + binding: 1, + visibility: wgpu::ShaderStage::FRAGMENT, + ty: wgpu::BindingType::Sampler { + filtering: true, + comparison: false, + }, + count: None, + } + ], + }); + + // Craete texture sampler + let sampler = device.create_sampler(&wgpu::SamplerDescriptor { + label: Some("Post procecss sampler"), + address_mode_u: wgpu::AddressMode::ClampToEdge, + address_mode_v: wgpu::AddressMode::ClampToEdge, + address_mode_w: wgpu::AddressMode::ClampToEdge, + mag_filter: wgpu::FilterMode::Nearest, + min_filter: wgpu::FilterMode::Nearest, + mipmap_filter: wgpu::FilterMode::Nearest, + lod_min_clamp: 0.0, + lod_max_clamp: 100.0, + compare: None, + anisotropy_clamp: None, + border_color: None, + }); + + let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor { + layout: &bind_layout, + entries: &[ + wgpu::BindGroupEntry {binding: 0, resource: wgpu::BindingResource::TextureView(&texture_view),}, + wgpu::BindGroupEntry {binding: 1, resource: wgpu::BindingResource::Sampler(&sampler),}, + ], + label: Some("Uniform buffer group"), + }); + + // Pipeline layout + let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { + label: Some("Render Pipeline Layout"), + bind_group_layouts: &[&bind_layout], + push_constant_ranges: &[], + }); + + // Create pipeline + let pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor { + label: Some("Render Pipeline"), + layout: Some(&pipeline_layout), + vertex: vert_state, + fragment: Some(frag_state), + primitive: wgpu::PrimitiveState { + topology: wgpu::PrimitiveTopology::TriangleList, + strip_index_format: None, + front_face: wgpu::FrontFace::Cw, + cull_mode: wgpu::CullMode::Back, + polygon_mode: wgpu::PolygonMode::Fill, + }, + depth_stencil: None, + multisample: wgpu::MultisampleState { count: 1, mask: !0, alpha_to_coverage_enabled: false } + }); + + Self { pipeline, bind_group } + } + + pub fn render(&mut self, encoder: &mut wgpu::CommandEncoder, attachment: &wgpu::TextureView) { + let mut pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor { + label: Some("Postprocess pass"), + color_attachments: &[wgpu::RenderPassColorAttachmentDescriptor { + attachment: &attachment, + resolve_target: None, + ops: wgpu::Operations { + load: wgpu::LoadOp::Clear(wgpu::Color::BLACK), + store: true, + }, + }], + depth_stencil_attachment: None, + }); + pass.set_pipeline(&self.pipeline); + pass.set_bind_group(0, &self.bind_group, &[]); + pass.draw(0..6, 0..1); } } \ No newline at end of file diff --git a/src/renderer/passes/raytrace.rs b/src/renderer/passes/raytrace.rs index 6284e56..b0be4aa 100644 --- a/src/renderer/passes/raytrace.rs +++ b/src/renderer/passes/raytrace.rs @@ -9,14 +9,14 @@ impl RaytracePass { // Vertex shader let vert_state = wgpu::VertexState { - module: &device.create_shader_module(&wgpu::include_spirv!("..\\..\\shaders\\bin\\shader.vert.spv")), + module: &device.create_shader_module(&wgpu::include_spirv!("..\\..\\shaders\\.bin\\fullscreen.vert.spv")), entry_point: "main", buffers: &[], }; // Fragment shader let frag_state = wgpu::FragmentState { - module: &device.create_shader_module(&wgpu::include_spirv!("..\\..\\shaders\\bin\\shader.frag.spv")), + module: &device.create_shader_module(&wgpu::include_spirv!("..\\..\\shaders\\raytrace\\.bin\\main.frag.spv")), entry_point: "main", targets: &[wgpu::ColorTargetState { format: swapchain_desc.format, @@ -63,7 +63,7 @@ impl RaytracePass { pub fn render(&mut self, encoder: &mut wgpu::CommandEncoder, buffers: &mut Buffers, attachment: &wgpu::TextureView) { let mut render_pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor { - label: Some("Render Pass"), + label: Some("Raytrace Pass"), color_attachments: &[ wgpu::RenderPassColorAttachmentDescriptor { attachment: attachment, @@ -86,10 +86,7 @@ impl RaytracePass { render_pass.set_bind_group(2, &buffers.brick_buffer.bind_group, &[]); render_pass.set_bind_group(3, &buffers.material_buffer.bind_group, &[]); - // Vertices and indices - render_pass.draw(0..6, 0..1); // 3. - // render_pass.set_vertex_buffer(0, buffers.raster_buffer.vertex_buffer.slice(..)); - // render_pass.set_index_buffer(buffers.raster_buffer.index_buffer.slice(..), wgpu::IndexFormat::Uint16); - // render_pass.draw_indexed(0..buffers.raster_buffer.index_len, 0, 0..1); + // Draw 2 triangles + render_pass.draw(0..6, 0..1); } } \ No newline at end of file diff --git a/src/shaders/bin/shader.vert.spv b/src/shaders/.bin/fullscreen.vert.spv similarity index 95% rename from src/shaders/bin/shader.vert.spv rename to src/shaders/.bin/fullscreen.vert.spv index 9bb3ef291d571e60838fcce4084544a92318b362..14a8aa1b32fbe6d6476380706f4b2a0efd598188 100644 GIT binary patch delta 18 Zcmcb>b%ATb8TNS3ywETPhK-kNSpY?h2HpSw delta 18 Zcmcb>b%ATb8TPW&qLTR1vW=H(SpZH52q*vm diff --git a/src/shaders/shader.vert b/src/shaders/fullscreen.vert similarity index 76% rename from src/shaders/shader.vert rename to src/shaders/fullscreen.vert index 5138c8b..e41d165 100644 --- a/src/shaders/shader.vert +++ b/src/shaders/fullscreen.vert @@ -1,6 +1,6 @@ #version 450 -layout(location=0) out vec2 vert_uv; +layout(location=0) out vec2 _InUV; const vec2 positions[6] = vec2[6]( vec2(-1.0, 1.0), @@ -14,6 +14,6 @@ const vec2 positions[6] = vec2[6]( void main() { - vert_uv = positions[gl_VertexIndex]; + _InUV = positions[gl_VertexIndex]; gl_Position = vec4(positions[gl_VertexIndex], 0.0, 1.0); } \ No newline at end of file diff --git a/src/shaders/postprocess/.bin/main.frag.spv b/src/shaders/postprocess/.bin/main.frag.spv new file mode 100644 index 0000000000000000000000000000000000000000..28bc812102f5650bfe472d0d57534358501d114d GIT binary patch literal 1572 zcmY+ETTc^F6oq$b3kc;V0s>y9;vK9vKon`C#xy3A6oca9gtYT8NhwWfi9V_E-QQ$< z*8k&+iR+u5lZ+?XIeV|Y&c042Ke9Gvma_?)vYHLgoQ()Eo3zpNu7?L<<+R_bY;HY( zF>U#j2xrE|te_h?K1w<`CM8cLv*Lj(fwa7$n*G$Hg0j`asNQJQ!`D%>+l@~9pW1QM zPC9YaN_ug#pPa?;#xuO6(`*k~Swc~aY~G@BoKud$nHfInh~9MGAL_=wth;&AKIx@) z(E{D_zl%Ti2R-F0s?zKKVFyRY-FEEx^b|D){Z}qV-Q~C9R!*m9slF(ER9GNc5}(;(!wY1O>jp!xCv+1Vd)L{_1#CffNp~RO ztUG&ZXr}L{rNbo$e(pJm*_WE<&&z`2{mZz`YSgzXg*SXL)N@HUwSX^cTl9*b_u1oZ z-duGKxb%P>IBZ3oGf#MH4#S3r&3rkls^F$>Vo=u|-Q+DuHl$I{hJ@a{_g`9V_eYHycBIoQ@u>luoq}!a3u8~@bNK&KECe` zTX8shuc|A003#3cE=vMuvzr?d_HwBA?BtdN4mfYfb6Y~358^P(yApWd4NZ!DtxLcW zPENvnse!rS_d2`vvF}S~79~xKdGS-@?Mn&1Z^{Y&P(ttcOR5U&u>>yt;b-?H)q`(S zf)AW;hVKNvpXZizILwJ!=wVwzt;`bpiNoOf+QB^knRNJXU5&fa!8jg!E**?oJhtaB a=CiL}m}ynQd-(Y2m7IL9`2H%wj^rQv24Rf= literal 0 HcmV?d00001 diff --git a/src/shaders/postprocess/main.frag b/src/shaders/postprocess/main.frag new file mode 100644 index 0000000..1533dd1 --- /dev/null +++ b/src/shaders/postprocess/main.frag @@ -0,0 +1,22 @@ +#version 450 + +layout(set=0, binding=0) uniform texture2D _InTexture; +layout(set=0, binding=1) uniform sampler _InTextureSampler; +layout(location=0) in vec2 _InUV; +layout(location=0) out vec4 _OutColor; + + +void main() +{ + // Get color + vec2 uv = vec2(_InUV.x+1.0, -_InUV.y+1.0) * 0.5; + vec3 color = texture(sampler2D(_InTexture, _InTextureSampler), uv).rgb; + + // Viniette + color = vec3(1,1,1); + + color *= smoothstep(0.0, 0.2, pow(1.0-length(_InUV), 1.5)) + 0.5; + + // Return + _OutColor = vec4(color, 1.0); +} \ No newline at end of file diff --git a/src/shaders/bin/shader.frag.spv b/src/shaders/raytrace/.bin/main.frag.spv similarity index 99% rename from src/shaders/bin/shader.frag.spv rename to src/shaders/raytrace/.bin/main.frag.spv index 4447e7defca1707e2501a330bb9b981739e63533..5ad0da7672a301731c955e7a20fe23096378f7c5 100644 GIT binary patch delta 31 ncmbPHIHPbw1si+3XI^L+1HmH8=gkY*zZ(Dmt^5kW delta 31 ncmbPHIHPbw1si)=YEemiY1!s_Hd#j2{L+&6