First successful experiment with stencil buffer

This commit is contained in:
Maximilian Ammann 2021-12-05 10:55:52 +01:00
parent add96bbf91
commit 1ef0aa4639
3 changed files with 98 additions and 32 deletions

View File

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

View File

@ -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
},
}
}

View File

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