From 1ef0aa4639b1e19393d2fda43eba2684322b92c9 Mon Sep 17 00:00:00 2001 From: Maximilian Ammann Date: Sun, 5 Dec 2021 10:55:52 +0100 Subject: [PATCH] First successful experiment with stencil buffer --- src/render/piplines.rs | 36 +++++++++++++--------- src/render/shader.rs | 24 ++++++++++++--- src/render/state.rs | 70 ++++++++++++++++++++++++++++++++++-------- 3 files changed, 98 insertions(+), 32 deletions(-) diff --git a/src/render/piplines.rs b/src/render/piplines.rs index 119d5a44..83fa19ed 100644 --- a/src/render/piplines.rs +++ b/src/render/piplines.rs @@ -7,7 +7,23 @@ pub fn create_map_render_pipeline_description<'a>( vertex_state: VertexState<'a>, fragment_state: FragmentState<'a>, sample_count: u32, + draw_mask: bool, ) -> RenderPipelineDescriptor<'a> { + let stencil_state = if draw_mask { + wgpu::StencilFaceState { + compare: wgpu::CompareFunction::Always, + fail_op: wgpu::StencilOperation::Keep, + depth_fail_op: wgpu::StencilOperation::Keep, + pass_op: wgpu::StencilOperation::IncrementClamp, + } + } else { + wgpu::StencilFaceState { + compare: wgpu::CompareFunction::Equal, + fail_op: wgpu::StencilOperation::Keep, + depth_fail_op: wgpu::StencilOperation::Keep, + pass_op: wgpu::StencilOperation::Keep + } + }; let descriptor = wgpu::RenderPipelineDescriptor { label: None, layout: Some(&pipeline_layout), @@ -25,22 +41,12 @@ pub fn create_map_render_pipeline_description<'a>( depth_stencil: Some(wgpu::DepthStencilState { format: DEPTH_TEXTURE_FORMAT, depth_write_enabled: true, - depth_compare: wgpu::CompareFunction::Greater, + depth_compare: wgpu::CompareFunction::Always, stencil: wgpu::StencilState { - front: wgpu::StencilFaceState { - compare: wgpu::CompareFunction::Equal, - fail_op: wgpu::StencilOperation::Keep, - depth_fail_op: wgpu::StencilOperation::Keep, - pass_op: wgpu::StencilOperation::IncrementClamp, - }, - back: wgpu::StencilFaceState { - compare: wgpu::CompareFunction::Equal, - fail_op: wgpu::StencilOperation::Keep, - depth_fail_op: wgpu::StencilOperation::Keep, - pass_op: wgpu::StencilOperation::IncrementClamp, - }, - read_mask: 1, - write_mask: 0, + front: stencil_state, + back: stencil_state, + read_mask: 0xff, + write_mask: 0xff, }, bias: wgpu::DepthBiasState::default(), }), diff --git a/src/render/shader.rs b/src/render/shader.rs index 3b0c8450..14a4597b 100644 --- a/src/render/shader.rs +++ b/src/render/shader.rs @@ -1,6 +1,9 @@ -use wgpu::{ColorTargetState, FragmentState, ShaderModule, ShaderModuleDescriptor, VertexAttribute, VertexBufferLayout, VertexState}; -use super::platform_constants::COLOR_TEXTURE_FORMAT; +use wgpu::{ + ColorTargetState, FragmentState, ShaderModule, ShaderModuleDescriptor, VertexAttribute, + VertexBufferLayout, VertexState, +}; +use super::platform_constants::COLOR_TEXTURE_FORMAT; use super::shader_ffi::GpuVertex; const MAP_VERTEX_SHADER_ARGUMENTS: [VertexAttribute; 3] = [ @@ -33,6 +36,12 @@ const MAP_VERTEX_COLOR_TARGETS: [ColorTargetState; 1] = [wgpu::ColorTargetState write_mask: wgpu::ColorWrites::ALL, }]; +const MASK_MAP_VERTEX_COLOR_TARGETS: [ColorTargetState; 1] = [wgpu::ColorTargetState { + format: COLOR_TEXTURE_FORMAT, + blend: None, + write_mask: wgpu::ColorWrites::empty(), +}]; + pub fn create_vertex_module_descriptor<'a>() -> ShaderModuleDescriptor<'a> { wgpu::ShaderModuleDescriptor { label: Some("Geometry vs"), @@ -55,10 +64,17 @@ pub fn create_map_vertex_state(vertex_shader_module: &ShaderModule) -> VertexSta } } -pub fn create_map_fragment_state(fragment_shader_module: &ShaderModule) -> FragmentState { +pub fn create_map_fragment_state( + fragment_shader_module: &ShaderModule, + mask: bool, +) -> FragmentState { wgpu::FragmentState { module: fragment_shader_module, entry_point: "main", - targets: &MAP_VERTEX_COLOR_TARGETS, + targets: if mask { + &MASK_MAP_VERTEX_COLOR_TARGETS + } else { + &MAP_VERTEX_COLOR_TARGETS + }, } } diff --git a/src/render/state.rs b/src/render/state.rs index ddd45e5c..c0e2e91f 100644 --- a/src/render/state.rs +++ b/src/render/state.rs @@ -6,8 +6,8 @@ use std::ops::Range; use lyon::math::Vector; use lyon::tessellation::VertexBuffers; use vector_tile::parse_tile_reader; -use wgpu::Extent3d; use wgpu::util::DeviceExt; +use wgpu::Extent3d; use winit::event::{ElementState, KeyboardInput, VirtualKeyCode, WindowEvent}; use winit::window::Window; @@ -55,6 +55,8 @@ pub struct State { pub size: winit::dpi::PhysicalSize, render_pipeline: wgpu::RenderPipeline, + mask_pipeline: wgpu::RenderPipeline, + mask_pipeline2: wgpu::RenderPipeline, bind_group: wgpu::BindGroup, sample_count: u32, @@ -152,7 +154,6 @@ impl State { .await .unwrap(); - let limits = if cfg!(feature = "web-webgl") { wgpu::Limits::downlevel_webgl2_defaults() } else { @@ -260,11 +261,28 @@ impl State { let render_pipeline_descriptor = create_map_render_pipeline_description( &pipeline_layout, create_map_vertex_state(&vertex_module), - create_map_fragment_state(&fragment_module), + create_map_fragment_state(&fragment_module, false), sample_count, + false, + ); + + let mask_pipeline_descriptor = create_map_render_pipeline_description( + &pipeline_layout, + create_map_vertex_state(&vertex_module), + create_map_fragment_state(&fragment_module, false), + sample_count, + true, + ); let mask_pipeline_descriptor2 = create_map_render_pipeline_description( + &pipeline_layout, + create_map_vertex_state(&vertex_module), + create_map_fragment_state(&fragment_module, false), + sample_count, + true, ); let render_pipeline = device.create_render_pipeline(&render_pipeline_descriptor); + let mask_pipeline = device.create_render_pipeline(&mask_pipeline_descriptor); + let mask_pipeline2 = device.create_render_pipeline(&mask_pipeline_descriptor2); // TODO: this isn't what we want: we'd need the equivalent of VK_POLYGON_MODE_LINE, // but it doesn't seem to be exposed by wgpu? @@ -283,7 +301,7 @@ impl State { let depth_texture = Texture::create_depth_texture(&device, &surface_config, "depth_texture", sample_count); -/* + /* let data = [1; 512 * 512] ; queue.write_texture( @@ -323,6 +341,8 @@ impl State { size, surface_config, render_pipeline, + mask_pipeline, + mask_pipeline2, bind_group, multisampled_render_target, depth_texture, @@ -339,7 +359,7 @@ impl State { fps_meter: FPSMeter::new(), stroke_range, cpu_primitives, - mask_fill_range + mask_fill_range, } } @@ -445,9 +465,9 @@ impl State { &self.globals_uniform_buffer, 0, bytemuck::cast_slice(&[Globals::new( - [self.size.width as f32, self.size.height as f32], - scene.scroll.to_array(), - scene.zoom, + [self.size.width as f32, self.size.height as f32], + scene.scroll.to_array(), + scene.zoom, )]), ); @@ -496,19 +516,43 @@ impl State { }), }); - pass.set_pipeline(&self.render_pipeline); pass.set_bind_group(0, &self.bind_group, &[]); pass.set_index_buffer( self.indices_uniform_buffer.slice(..), wgpu::IndexFormat::Uint16, ); pass.set_vertex_buffer(0, self.vertex_uniform_buffer.slice(..)); + //compare: wgpu::CompareFunction::Equal + { + // Increment stencil + pass.set_pipeline(&self.mask_pipeline); + pass.set_stencil_reference(0); // Must be 0, else this does nothing? + pass.draw_indexed(self.mask_fill_range.clone(), 0, 0..1); - //pass.set_stencil_reference(1); - //pass.draw_indexed(self.fill_range.clone(), 0, 0..(self.num_instances as u32)); - pass.draw_indexed(self.stroke_range.clone(), 0, 0..1); + pass.set_pipeline(&self.mask_pipeline2); + pass.set_stencil_reference(0); // Must be 0, else this does nothing? + pass.draw_indexed(self.mask_fill_range.clone(), 0, 0..1); + + pass.set_pipeline(&self.render_pipeline); + pass.set_stencil_reference(2); + //pass.draw_indexed(self.fill_range.clone(), 0, 0..(self.num_instances as u32)); + pass.draw_indexed(self.stroke_range.clone(), 0, 0..1); + } + + //compare: wgpu::CompareFunction::Always +/* { + // Increment stencil + pass.set_pipeline(&self.mask_pipeline); + pass.set_stencil_reference(5); + pass.draw_indexed(self.mask_fill_range.clone(), 0, 0..1); + + pass.set_pipeline(&self.render_pipeline); + pass.set_stencil_reference(5); + //pass.draw_indexed(self.fill_range.clone(), 0, 0..(self.num_instances as u32)); + pass.draw_indexed(self.stroke_range.clone(), 0, 0..1); + + }*/ - pass.draw_indexed(self.mask_fill_range.clone(), 0, 0..1); } self.queue.submit(Some(encoder.finish()));