Enable stencil and render rust logo into map

This commit is contained in:
Maximilian Ammann 2021-12-04 16:20:12 +01:00
parent 3f4beab87f
commit add96bbf91
7 changed files with 92 additions and 29 deletions

View File

@ -6,7 +6,6 @@ edition = "2021"
resolver = "2"
[features]
web-webgl = [ "wgpu/webgl" ]
[target.'cfg(target_arch = "wasm32")'.dependencies]

View File

@ -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 {

View File

@ -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(),

View File

@ -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;

View File

@ -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<Primitive>,
fill_range: Range<u32>,
stroke_range: Range<u32>,
mask_fill_range: Range<u32>,
scene: SceneParams,
}
@ -87,19 +89,31 @@ impl State {
let mut geometry: VertexBuffers<GpuVertex, u16> = 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()));

View File

@ -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<GpuVertex, u16>, _prim_id: u32) -> u32 {
@ -126,6 +128,8 @@ impl Tesselated for RustLogo {
fn tesselate_stroke(&self, buffer: &mut VertexBuffers<GpuVertex, u16>, 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<GpuVertex, u16>, 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
}
}

View File

@ -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());