From add96bbf91d9654eb503add42a5de007ef0a478d Mon Sep 17 00:00:00 2001 From: Maximilian Ammann Date: Sat, 4 Dec 2021 16:20:12 +0100 Subject: [PATCH] Enable stencil and render rust logo into map --- Cargo.toml | 1 - src/main.rs | 3 ++ src/render/piplines.rs | 19 ++++++-- src/render/platform_constants.rs | 2 +- src/render/state.rs | 79 ++++++++++++++++++++++++-------- src/render/tesselation.rs | 12 +++-- src/render/texture.rs | 5 +- 7 files changed, 92 insertions(+), 29 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index f4d7b119..2b6610e9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,7 +6,6 @@ edition = "2021" resolver = "2" [features] - web-webgl = [ "wgpu/webgl" ] [target.'cfg(target_arch = "wasm32")'.dependencies] diff --git a/src/main.rs b/src/main.rs index 18447058..638787dd 100644 --- a/src/main.rs +++ b/src/main.rs @@ -20,6 +20,9 @@ async fn setup(window: Window, event_loop: EventLoop<()>) { let mut state = State::new(&window).await; + // Important: This kick-starts the rendering loop + // window.request_redraw(); + event_loop.run(move |event, _, control_flow| { match event { Event::WindowEvent { diff --git a/src/render/piplines.rs b/src/render/piplines.rs index 088b27bb..119d5a44 100644 --- a/src/render/piplines.rs +++ b/src/render/piplines.rs @@ -1,5 +1,6 @@ use wgpu::{FragmentState, PipelineLayout, RenderPipelineDescriptor, VertexState}; +use super::texture::DEPTH_TEXTURE_FORMAT; pub fn create_map_render_pipeline_description<'a>( pipeline_layout: &'a PipelineLayout, @@ -22,13 +23,23 @@ pub fn create_map_render_pipeline_description<'a>( conservative: false, }, depth_stencil: Some(wgpu::DepthStencilState { - format: wgpu::TextureFormat::Depth32Float, + format: DEPTH_TEXTURE_FORMAT, depth_write_enabled: true, depth_compare: wgpu::CompareFunction::Greater, stencil: wgpu::StencilState { - front: wgpu::StencilFaceState::IGNORE, - back: wgpu::StencilFaceState::IGNORE, - read_mask: 0, + 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, }, bias: wgpu::DepthBiasState::default(), diff --git a/src/render/platform_constants.rs b/src/render/platform_constants.rs index eaa61aa7..4fac3310 100644 --- a/src/render/platform_constants.rs +++ b/src/render/platform_constants.rs @@ -9,5 +9,5 @@ pub const COLOR_TEXTURE_FORMAT: wgpu::TextureFormat = wgpu::TextureFormat::Rgba8 pub const COLOR_TEXTURE_FORMAT: wgpu::TextureFormat = wgpu::TextureFormat::Bgra8UnormSrgb; // FIXME: This limit is enforced by WebGL. Actually this makes sense! -// This is usually achieved by _pad attributes in shader_ffi.rs +// FIXME: This can also be achieved by _pad attributes in shader_ffi.rs pub const MIN_BUFFER_SIZE: u64 = 32; diff --git a/src/render/state.rs b/src/render/state.rs index 19549e15..ddd45e5c 100644 --- a/src/render/state.rs +++ b/src/render/state.rs @@ -1,17 +1,18 @@ use std::cmp; use std::io::Cursor; +use std::num::NonZeroU32; use std::ops::Range; use lyon::math::Vector; use lyon::tessellation::VertexBuffers; -use vector_tile::{parse_tile_reader}; +use vector_tile::parse_tile_reader; +use wgpu::Extent3d; use wgpu::util::DeviceExt; - use winit::event::{ElementState, KeyboardInput, VirtualKeyCode, WindowEvent}; - use winit::window::Window; use crate::fps_meter::FPSMeter; + use super::multisampling::create_multisampled_framebuffer; use super::piplines::*; use super::platform_constants::{COLOR_TEXTURE_FORMAT, MIN_BUFFER_SIZE}; @@ -71,6 +72,7 @@ pub struct State { cpu_primitives: Vec, fill_range: Range, stroke_range: Range, + mask_fill_range: Range, scene: SceneParams, } @@ -87,19 +89,31 @@ impl State { let mut geometry: VertexBuffers = VertexBuffers::new(); - let (stroke_range, fill_range) = if true { + let (stroke_range, fill_range) = { //let tile = parse_tile("test-data/12-2176-1425.pbf").expect("failed loading tile"); let tile = parse_tile_reader(&mut Cursor::new(TEST_TILES)); + let count_stroke = tile.tesselate_stroke(&mut geometry, stroke_prim_id); + let count_fill = 0; + + let start_stroke = 0; + let start_fill = start_stroke + count_stroke; ( - 0..tile.tesselate_stroke(&mut geometry, stroke_prim_id), - 0..0, + start_stroke..start_fill, + start_fill..start_fill + count_fill, ) - } else { + }; + + let (_, mask_fill_range) = { let logo = RustLogo(); - let max_index = logo.tesselate_stroke(&mut geometry, stroke_prim_id); + //let count_stroke = logo.tesselate_stroke(&mut geometry, stroke_prim_id); + //let start_stroke = fill_range.end; + let count_stroke = 0; + let start_stroke = fill_range.end; + let start_fill = start_stroke + count_stroke; + let count_fill = logo.tesselate_fill(&mut geometry, fill_prim_id); ( - 0..max_index, - max_index..max_index + logo.tesselate_fill(&mut geometry, fill_prim_id), + start_stroke..start_fill, + start_fill..start_fill + count_fill, ) }; @@ -120,7 +134,7 @@ impl State { Primitive::new([0.0, 0.0, 0.0, 1.0], [0.0, 0.0], 3, 1.0, 0.0, 1.0); // Main fill primitive cpu_primitives[fill_prim_id as usize] = - Primitive::new([1.0, 1.0, 1.0, 1.0], [0.0, 0.0], 1, 0.0, 0.0, 1.0); + Primitive::new([0.0, 0.0, 0.0, 1.0], [0.0, 0.0], 1, 0.0, 0.0, 1.0); // create an instance let instance = wgpu::Instance::new(wgpu::Backends::all()); @@ -138,12 +152,14 @@ impl State { .await .unwrap(); - // create a device and a queue - #[cfg(feature = "web-webgl")] - let limits = wgpu::Limits::downlevel_webgl2_defaults(); - #[cfg(not(feature = "web-webgl"))] - let limits = wgpu::Limits::default(); + let limits = if cfg!(feature = "web-webgl") { + wgpu::Limits::downlevel_webgl2_defaults() + } else { + wgpu::Limits::default() + }; + + // create a device and a queue let (device, queue) = adapter .request_device( &wgpu::DeviceDescriptor { @@ -259,13 +275,36 @@ impl State { format: COLOR_TEXTURE_FORMAT, width: size.width, height: size.height, - present_mode: wgpu::PresentMode::Mailbox, + // present_mode: wgpu::PresentMode::Mailbox, + present_mode: wgpu::PresentMode::Fifo, // VSync }; surface.configure(&device, &surface_config); let depth_texture = Texture::create_depth_texture(&device, &surface_config, "depth_texture", sample_count); +/* + let data = [1; 512 * 512] ; + + queue.write_texture( + wgpu::ImageCopyTexture { + aspect: wgpu::TextureAspect::StencilOnly, + texture: &depth_texture.texture, + mip_level: 0, + origin: wgpu::Origin3d::ZERO, + }, + &data, + wgpu::ImageDataLayout { + offset: 0, + bytes_per_row: NonZeroU32::new(512), + rows_per_image: None, + }, + Extent3d { + width: 10, + height: 10, + depth_or_array_layers: 1, + } + );*/ let multisampled_render_target = if sample_count > 1 { Some(create_multisampled_framebuffer( @@ -300,6 +339,7 @@ impl State { fps_meter: FPSMeter::new(), stroke_range, cpu_primitives, + mask_fill_range } } @@ -464,8 +504,11 @@ impl State { ); pass.set_vertex_buffer(0, self.vertex_uniform_buffer.slice(..)); - pass.draw_indexed(self.fill_range.clone(), 0, 0..(self.num_instances as u32)); + //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.draw_indexed(self.mask_fill_range.clone(), 0, 0..1); } self.queue.submit(Some(encoder.finish())); diff --git a/src/render/tesselation.rs b/src/render/tesselation.rs index 610cf53e..ea3f1269 100644 --- a/src/render/tesselation.rs +++ b/src/render/tesselation.rs @@ -44,6 +44,8 @@ impl Tesselated for Tile { let mut stroke_tess = StrokeTessellator::new(); let mut tile_builder = Path::builder().with_svg(); + let initial_indices_count = buffer.indices.len(); + for layer in self.layers() { if layer.name() != "water" { continue; @@ -112,7 +114,7 @@ impl Tesselated for Tile { ) .unwrap(); - buffer.indices.len() as u32 + (buffer.indices.len() - initial_indices_count) as u32 } fn tesselate_fill(&self, _buffer: &mut VertexBuffers, _prim_id: u32) -> u32 { @@ -126,6 +128,8 @@ impl Tesselated for RustLogo { fn tesselate_stroke(&self, buffer: &mut VertexBuffers, prim_id: u32) -> u32 { let mut stroke_tess = StrokeTessellator::new(); + let initial_indices_count = buffer.indices.len(); + // Build a Path for the rust logo. let mut rust_logo_builder = Path::builder().with_svg(); build_logo_path(&mut rust_logo_builder); @@ -139,12 +143,14 @@ impl Tesselated for RustLogo { ) .unwrap(); - buffer.indices.len() as u32 + (buffer.indices.len() - initial_indices_count) as u32 } fn tesselate_fill(&self, buffer: &mut VertexBuffers, prim_id: u32) -> u32 { let mut fill_tess = FillTessellator::new(); + let initial_indices_count = buffer.indices.len(); + // Build a Path for the rust logo. let mut rust_logo_builder = Path::builder().with_svg(); build_logo_path(&mut rust_logo_builder); @@ -159,6 +165,6 @@ impl Tesselated for RustLogo { ) .unwrap(); - buffer.indices.len() as u32 + (buffer.indices.len() - initial_indices_count) as u32 } } diff --git a/src/render/texture.rs b/src/render/texture.rs index d6f34773..50fa70d7 100644 --- a/src/render/texture.rs +++ b/src/render/texture.rs @@ -3,8 +3,9 @@ pub struct Texture { pub view: wgpu::TextureView, } +pub const DEPTH_TEXTURE_FORMAT: wgpu::TextureFormat = wgpu::TextureFormat::Depth24PlusStencil8; + impl Texture { - pub const DEPTH_FORMAT: wgpu::TextureFormat = wgpu::TextureFormat::Depth32Float; pub fn create_depth_texture( device: &wgpu::Device, @@ -23,7 +24,7 @@ impl Texture { mip_level_count: 1, sample_count, dimension: wgpu::TextureDimension::D2, - format: wgpu::TextureFormat::Depth32Float, + format: DEPTH_TEXTURE_FORMAT, usage: wgpu::TextureUsages::RENDER_ATTACHMENT, }); let view = depth_texture.create_view(&wgpu::TextureViewDescriptor::default());