Add a perfect masking stencil

This commit is contained in:
Maximilian Ammann 2021-12-28 18:13:39 +01:00
parent 1e66a8ee36
commit 35e18937a0
6 changed files with 92 additions and 30 deletions

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 27 KiB

After

Width:  |  Height:  |  Size: 106 KiB

View File

@ -65,6 +65,27 @@ impl GpuVertexUniform {
} }
} }
#[repr(C)]
#[derive(Copy, Clone, Pod, Zeroable)]
pub struct MaskInstanceUniform {
pub position: Vec2f32,
pub target_width: f32,
pub target_height: f32,
pub debug_color: Vec4f32,
}
impl MaskInstanceUniform {
pub fn new(position: Vec2f32, target_width: f32, target_height: f32, debug_color: Vec4f32) -> Self {
Self {
position,
target_width,
target_height,
debug_color
}
}
}
#[repr(C)] #[repr(C)]
#[derive(Copy, Clone, Pod, Zeroable)] #[derive(Copy, Clone, Pod, Zeroable)]
pub struct PrimitiveUniform { pub struct PrimitiveUniform {

View File

@ -105,9 +105,10 @@ pub mod tile {
} }
pub mod tile_mask { pub mod tile_mask {
use super::{FragmentShaderState, VertexShaderState};
use crate::platform::COLOR_TEXTURE_FORMAT; use crate::platform::COLOR_TEXTURE_FORMAT;
use crate::render::shader_ffi::GpuVertexUniform; use crate::render::shader_ffi::{GpuVertexUniform, MaskInstanceUniform};
use super::{FragmentShaderState, VertexShaderState};
pub const VERTEX: VertexShaderState = VertexShaderState::new( pub const VERTEX: VertexShaderState = VertexShaderState::new(
include_str!("tile_mask.vertex.wgsl"), include_str!("tile_mask.vertex.wgsl"),
@ -116,16 +117,19 @@ pub mod tile_mask {
array_stride: std::mem::size_of::<GpuVertexUniform>() as u64, array_stride: std::mem::size_of::<GpuVertexUniform>() as u64,
step_mode: wgpu::VertexStepMode::Vertex, step_mode: wgpu::VertexStepMode::Vertex,
attributes: &[ attributes: &[
// position
wgpu::VertexAttribute { wgpu::VertexAttribute {
offset: 0, offset: 0,
format: wgpu::VertexFormat::Float32x2, format: wgpu::VertexFormat::Float32x2,
shader_location: 0, shader_location: 0,
}, },
// normal
wgpu::VertexAttribute { wgpu::VertexAttribute {
offset: wgpu::VertexFormat::Float32x2.size(), offset: wgpu::VertexFormat::Float32x2.size(),
format: wgpu::VertexFormat::Float32x2, format: wgpu::VertexFormat::Float32x2,
shader_location: 1, shader_location: 1,
}, },
// ?
wgpu::VertexAttribute { wgpu::VertexAttribute {
offset: 2 * wgpu::VertexFormat::Float32x2.size(), offset: 2 * wgpu::VertexFormat::Float32x2.size(),
format: wgpu::VertexFormat::Uint32, format: wgpu::VertexFormat::Uint32,
@ -134,13 +138,36 @@ pub mod tile_mask {
], ],
}, },
wgpu::VertexBufferLayout { wgpu::VertexBufferLayout {
array_stride: std::mem::size_of::<GpuVertexUniform>() as u64, array_stride: std::mem::size_of::<MaskInstanceUniform>() as u64,
step_mode: wgpu::VertexStepMode::Instance, step_mode: wgpu::VertexStepMode::Instance,
attributes: &[wgpu::VertexAttribute { attributes: &[
offset: 0, // offset position
format: wgpu::VertexFormat::Float32x2, wgpu::VertexAttribute {
shader_location: 4, offset: 0,
}], format: wgpu::VertexFormat::Float32x2,
shader_location: 4,
},
// target_width
wgpu::VertexAttribute {
offset: 1 * wgpu::VertexFormat::Float32x2.size(),
format: wgpu::VertexFormat::Float32,
shader_location: 5,
},
// target_height
wgpu::VertexAttribute {
offset: 1 * wgpu::VertexFormat::Float32x2.size()
+ wgpu::VertexFormat::Float32.size(),
format: wgpu::VertexFormat::Float32,
shader_location: 6,
},
// debug_color
wgpu::VertexAttribute {
offset: 1 * wgpu::VertexFormat::Float32x2.size()
+ 2* wgpu::VertexFormat::Float32.size(),
format: wgpu::VertexFormat::Float32x4,
shader_location: 7,
},
],
}, },
], ],
); );

View File

@ -1,9 +1,8 @@
struct Output { struct Output {
[[location(0)]] out_color: vec4<f32>; [[location(0)]] out_color: vec4<f32>;
}; };
[[stage(fragment)]] [[stage(fragment)]]
fn main() -> Output { fn main([[location(0)]] v_color: vec4<f32>) -> Output {
return Output(vec4<f32>(1.0,1.0,1.0,1.0)); return Output(v_color);
} }

View File

@ -11,6 +11,7 @@ struct GlobalsUniform {
[[group(0), binding(0)]] var<uniform> globals: GlobalsUniform; [[group(0), binding(0)]] var<uniform> globals: GlobalsUniform;
struct VertexOutput { struct VertexOutput {
[[location(0)]] v_color: vec4<f32>;
[[builtin(position)]] position: vec4<f32>; [[builtin(position)]] position: vec4<f32>;
}; };
@ -18,19 +19,23 @@ struct VertexOutput {
fn main( fn main(
[[location(0)]] a_position: vec2<f32>, [[location(0)]] a_position: vec2<f32>,
[[location(4)]] mask_offset: vec2<f32>, [[location(4)]] mask_offset: vec2<f32>,
[[location(5)]] target_width: f32,
[[location(6)]] target_height: f32,
[[location(7)]] debug_color: vec4<f32>,
[[builtin(instance_index)]] instance_idx: u32 // instance_index is used when we have multiple instances of the same "object" [[builtin(instance_index)]] instance_idx: u32 // instance_index is used when we have multiple instances of the same "object"
) -> VertexOutput { ) -> VertexOutput {
var z = 0.0; var z = 0.0;
var world_pos = a_position + mask_offset; var m: mat3x3<f32> = mat3x3<f32>(
target_width, 0.0, 0.0,
0.0, target_height, 0.0,
0.0, 0.0, 1.0
);
if (instance_idx == u32(1)) { var world_pos_3d = vec3<f32>(a_position + mask_offset, z);
if (a_position.x == 0.0) { var world_pos = m * world_pos_3d;
world_pos.x = 0.0;
}
}
var position = globals.camera.view_proj * vec4<f32>(world_pos, z, 1.0); var position = globals.camera.view_proj * vec4<f32>(world_pos, 1.0);
return VertexOutput(position); return VertexOutput(debug_color, position);
} }

View File

@ -247,8 +247,22 @@ impl State {
}); });
let instances = [ let instances = [
GpuVertexUniform::new([0.0, 0.0], [0.0, 0.0], 0), // Step 1
GpuVertexUniform::new([4096.0, 0.0], [0.0, 0.0], 0), MaskInstanceUniform::new([0.0, 0.0], 4.0, 1.0, [1.0, 0.0, 0.0, 1.0]), // horizontal
MaskInstanceUniform::new([0.0, 2.0 * 4096.0], 4.0, 1.0, [1.0, 0.0, 0.0, 1.0]), // vertical
// Step 2
MaskInstanceUniform::new([1.0 * 4096.0, 0.0], 1.0, 4.0, [0.0, 0.0, 1.0, 1.0]), // vertical
MaskInstanceUniform::new([0.0, 1.0 * 4096.0], 4.0, 1.0, [0.0, 0.0, 1.0, 1.0]), // horizontal
MaskInstanceUniform::new([3.0 * 4096.0, 0.0], 1.0, 4.0, [0.0, 0.0, 1.0, 1.0]), // vertical
MaskInstanceUniform::new([0.0, 3.0 * 4096.0], 4.0, 1.0, [0.0, 0.0, 1.0, 1.0]), // horizontal
// Step 3
MaskInstanceUniform::new([0.0, 1.0 * 4096.0], 4.0, 1.0, [0.0, 1.0, 0.0, 1.0]), // horizontal
MaskInstanceUniform::new([0.0, 3.0 * 4096.0], 4.0, 1.0, [0.0, 1.0, 0.0, 1.0]), // horizontal
// Step 4
MaskInstanceUniform::new([0.0, 1.0 * 4096.0], 1.0, 1.0, [0.0, 1.0, 1.0, 1.0]), // horizontal
MaskInstanceUniform::new([0.0, 3.0 * 4096.0], 1.0, 1.0, [0.0, 1.0, 1.0, 1.0]), // horizontal
MaskInstanceUniform::new([2.0 * 4096.0, 1.0 * 4096.0], 1.0, 1.0, [0.0, 1.0, 1.0, 1.0]), // horizontal
MaskInstanceUniform::new([2.0 * 4096.0, 3.0 * 4096.0], 1.0, 1.0, [0.0, 1.0, 1.0, 1.0]), // horizontal
]; ];
let tile_mask_instances = device.create_buffer_init(&wgpu::util::BufferInitDescriptor { let tile_mask_instances = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
@ -356,10 +370,6 @@ impl State {
let render_pipeline = device.create_render_pipeline(&render_pipeline_descriptor); let render_pipeline = device.create_render_pipeline(&render_pipeline_descriptor);
let mask_pipeline = device.create_render_pipeline(&mask_pipeline_descriptor); let mask_pipeline = device.create_render_pipeline(&mask_pipeline_descriptor);
// 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?
//render_pipeline_descriptor.primitive.topology = wgpu::PrimitiveTopology::LineList;
let surface_config = wgpu::SurfaceConfiguration { let surface_config = wgpu::SurfaceConfiguration {
usage: wgpu::TextureUsages::RENDER_ATTACHMENT, usage: wgpu::TextureUsages::RENDER_ATTACHMENT,
format: COLOR_TEXTURE_FORMAT, format: COLOR_TEXTURE_FORMAT,
@ -540,7 +550,7 @@ impl State {
pass.set_bind_group(0, &self.bind_group, &[]); pass.set_bind_group(0, &self.bind_group, &[]);
{ {
// Increment stencil // Draw Mask
pass.set_pipeline(&self.mask_pipeline); pass.set_pipeline(&self.mask_pipeline);
pass.set_index_buffer( pass.set_index_buffer(
self.tile_mask_indices_uniform_buffer.slice(..), self.tile_mask_indices_uniform_buffer.slice(..),
@ -548,11 +558,11 @@ impl State {
); );
pass.set_vertex_buffer(0, self.tile_mask_vertex_uniform_buffer.slice(..)); pass.set_vertex_buffer(0, self.tile_mask_vertex_uniform_buffer.slice(..));
pass.set_vertex_buffer(1, self.tile_mask_instances.slice(..)); pass.set_vertex_buffer(1, self.tile_mask_instances.slice(..));
pass.draw_indexed(self.tile_mask_range.clone(), 0, 0..2); pass.draw_indexed(self.tile_mask_range.clone(), 0, 0..12);
} }
{ {
pass.set_pipeline(&self.render_pipeline); pass.set_pipeline(&self.render_pipeline);
pass.set_stencil_reference(2); pass.set_stencil_reference(1);
pass.set_index_buffer(self.indices_uniform_buffer.slice(..), INDEX_FORMAT); pass.set_index_buffer(self.indices_uniform_buffer.slice(..), INDEX_FORMAT);
pass.set_vertex_buffer(0, self.vertex_uniform_buffer.slice(..)); pass.set_vertex_buffer(0, self.vertex_uniform_buffer.slice(..));
if !self.tile_fill_range.is_empty() { if !self.tile_fill_range.is_empty() {
@ -562,7 +572,7 @@ impl State {
} }
{ {
pass.set_pipeline(&self.render_pipeline); pass.set_pipeline(&self.render_pipeline);
pass.set_stencil_reference(1); pass.set_stencil_reference(2);
pass.set_index_buffer(self.indices_uniform_buffer.slice(..), INDEX_FORMAT); pass.set_index_buffer(self.indices_uniform_buffer.slice(..), INDEX_FORMAT);
pass.set_vertex_buffer(0, self.vertex_uniform_buffer.slice(..)); pass.set_vertex_buffer(0, self.vertex_uniform_buffer.slice(..));
if !self.tile2_fill_range.is_empty() { if !self.tile2_fill_range.is_empty() {