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)]
#[derive(Copy, Clone, Pod, Zeroable)]
pub struct PrimitiveUniform {

View File

@ -105,9 +105,10 @@ pub mod tile {
}
pub mod tile_mask {
use super::{FragmentShaderState, VertexShaderState};
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(
include_str!("tile_mask.vertex.wgsl"),
@ -116,16 +117,19 @@ pub mod tile_mask {
array_stride: std::mem::size_of::<GpuVertexUniform>() as u64,
step_mode: wgpu::VertexStepMode::Vertex,
attributes: &[
// position
wgpu::VertexAttribute {
offset: 0,
format: wgpu::VertexFormat::Float32x2,
shader_location: 0,
},
// normal
wgpu::VertexAttribute {
offset: wgpu::VertexFormat::Float32x2.size(),
format: wgpu::VertexFormat::Float32x2,
shader_location: 1,
},
// ?
wgpu::VertexAttribute {
offset: 2 * wgpu::VertexFormat::Float32x2.size(),
format: wgpu::VertexFormat::Uint32,
@ -134,13 +138,36 @@ pub mod tile_mask {
],
},
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,
attributes: &[wgpu::VertexAttribute {
offset: 0,
format: wgpu::VertexFormat::Float32x2,
shader_location: 4,
}],
attributes: &[
// offset position
wgpu::VertexAttribute {
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 {
[[location(0)]] out_color: vec4<f32>;
};
[[stage(fragment)]]
fn main() -> Output {
return Output(vec4<f32>(1.0,1.0,1.0,1.0));
fn main([[location(0)]] v_color: vec4<f32>) -> Output {
return Output(v_color);
}

View File

@ -11,6 +11,7 @@ struct GlobalsUniform {
[[group(0), binding(0)]] var<uniform> globals: GlobalsUniform;
struct VertexOutput {
[[location(0)]] v_color: vec4<f32>;
[[builtin(position)]] position: vec4<f32>;
};
@ -18,19 +19,23 @@ struct VertexOutput {
fn main(
[[location(0)]] a_position: 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"
) -> VertexOutput {
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)) {
if (a_position.x == 0.0) {
world_pos.x = 0.0;
}
}
var world_pos_3d = vec3<f32>(a_position + mask_offset, z);
var world_pos = m * world_pos_3d;
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 = [
GpuVertexUniform::new([0.0, 0.0], [0.0, 0.0], 0),
GpuVertexUniform::new([4096.0, 0.0], [0.0, 0.0], 0),
// Step 1
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 {
@ -356,10 +370,6 @@ impl State {
let render_pipeline = device.create_render_pipeline(&render_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 {
usage: wgpu::TextureUsages::RENDER_ATTACHMENT,
format: COLOR_TEXTURE_FORMAT,
@ -540,7 +550,7 @@ impl State {
pass.set_bind_group(0, &self.bind_group, &[]);
{
// Increment stencil
// Draw Mask
pass.set_pipeline(&self.mask_pipeline);
pass.set_index_buffer(
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(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_stencil_reference(2);
pass.set_stencil_reference(1);
pass.set_index_buffer(self.indices_uniform_buffer.slice(..), INDEX_FORMAT);
pass.set_vertex_buffer(0, self.vertex_uniform_buffer.slice(..));
if !self.tile_fill_range.is_empty() {
@ -562,7 +572,7 @@ impl State {
}
{
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_vertex_buffer(0, self.vertex_uniform_buffer.slice(..));
if !self.tile2_fill_range.is_empty() {