Encode mask directly in shader

This commit is contained in:
Maximilian Ammann 2021-12-29 22:00:18 +01:00
parent 45fa50962e
commit a5fc17a2e6
4 changed files with 73 additions and 106 deletions

View File

@ -112,64 +112,38 @@ pub mod tile_mask {
pub const VERTEX: VertexShaderState = VertexShaderState::new(
include_str!("tile_mask.vertex.wgsl"),
&[
wgpu::VertexBufferLayout {
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,
shader_location: 2,
},
],
},
wgpu::VertexBufferLayout {
array_stride: std::mem::size_of::<MaskInstanceUniform>() as u64,
step_mode: wgpu::VertexStepMode::Instance,
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,
},
],
},
],
&[wgpu::VertexBufferLayout {
array_stride: std::mem::size_of::<MaskInstanceUniform>() as u64,
step_mode: wgpu::VertexStepMode::Instance,
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,
},
],
}],
);
pub const FRAGMENT: FragmentShaderState = FragmentShaderState::new(

View File

@ -38,12 +38,12 @@ fn main(
[[location(2)]] a_prim_id: u32,
[[builtin(instance_index)]] instance_idx: u32 // instance_index is used when we have multiple instances of the same "object"
) -> VertexOutput {
var prim: PrimitiveUniform = u_primitives.primitives[a_prim_id];
var z = 0.0;
let prim: PrimitiveUniform = u_primitives.primitives[a_prim_id];
let z = 0.0;
var world_pos = a_position + prim.translate + a_normal * prim.width;
let world_pos = a_position + prim.translate + a_normal * prim.width;
var position = globals.camera.view_proj * vec4<f32>(world_pos, z, 1.0);
let position = globals.camera.view_proj * vec4<f32>(world_pos, z, 1.0);
return VertexOutput(prim.color, position);
}

View File

@ -15,27 +15,54 @@ struct VertexOutput {
[[builtin(position)]] position: vec4<f32>;
};
let EXTENT = 4096.0;
[[stage(vertex)]]
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(vertex_index)]] vertex_idx: u32,
[[builtin(instance_index)]] instance_idx: u32 // instance_index is used when we have multiple instances of the same "object"
) -> VertexOutput {
let z = 0.0;
var a_position: vec2<f32>;
var m: mat3x3<f32> = mat3x3<f32>(
// Encode a square within the shader
switch (vertex_idx) {
case 0: {
a_position = vec2<f32>(0.0, 0.0);
}
case 1: {
a_position = vec2<f32>(0.0, EXTENT);
}
case 2: {
a_position = vec2<f32>(EXTENT, 0.0);
}
case 3: {
a_position = vec2<f32>(EXTENT, 0.0);
}
case 4: {
a_position = vec2<f32>(0.0, EXTENT);
}
case 5: {
a_position = vec2<f32>(EXTENT, EXTENT);
}
default: { }
}
let scaling: mat3x3<f32> = mat3x3<f32>(
vec3<f32>(target_width, 0.0, 0.0),
vec3<f32>(0.0, target_height, 0.0),
vec3<f32>(0.0, 0.0, 1.0)
);
var world_pos_3d = vec3<f32>(a_position + mask_offset, z);
var world_pos = m * world_pos_3d;
let z = 0.0;
var position = globals.camera.view_proj * vec4<f32>(world_pos, 1.0);
let world_pos_3d = vec3<f32>(a_position + mask_offset, z);
let world_pos = scaling * world_pos_3d;
let position = globals.camera.view_proj * vec4<f32>(world_pos, 1.0);
return VertexOutput(debug_color, position);
}

View File

@ -42,13 +42,10 @@ impl Default for SceneParams {
const INDEX_FORMAT: wgpu::IndexFormat = wgpu::IndexFormat::Uint32;
type IndexDataType = u32; // Must match INDEX_FORMAT
const PRIM_BUFFER_LEN: usize = 256;
const STROKE_PRIM_ID: u32 = 0;
const FILL_PRIM_ID: u32 = 1;
const SECOND_TILE_FILL_PRIM_ID: u32 = 2;
const MASK_FILL_PRIM_ID: u32 = 3;
const SECOND_TILE_STROKE_PRIM_ID: u32 = 5;
pub struct State {
@ -84,9 +81,6 @@ pub struct State {
tile2_fill_range: Range<u32>,
tile2_stroke_range: Range<u32>,
tile_mask_vertex_uniform_buffer: wgpu::Buffer,
tile_mask_indices_uniform_buffer: wgpu::Buffer,
tile_mask_range: Range<u32>,
tile_mask_instances: wgpu::Buffer,
pub camera: camera::Camera,
@ -120,9 +114,6 @@ impl SceneParams {
cpu_primitives[SECOND_TILE_FILL_PRIM_ID as usize] =
PrimitiveUniform::new([0.0, 1.0, 1.0, 1.0], [4096.0, 0.0], 0, 1.0, 0.0, 1.0);
cpu_primitives[MASK_FILL_PRIM_ID as usize] =
PrimitiveUniform::new([0.0, 0.0, 1.0, 1.0], [0.0, 0.0], 0, 1.0, 0.0, 1.0);
Self {
cpu_primitives,
..SceneParams::default()
@ -243,24 +234,6 @@ impl State {
usage: wgpu::BufferUsages::INDEX,
});
let mut tile_mask_geometry: VertexBuffers<GpuVertexUniform, IndexDataType> =
VertexBuffers::new();
let tile_mask = TileMask();
let tile_mask_range = tile_mask.tesselate_fill(&mut tile_mask_geometry, MASK_FILL_PRIM_ID);
let tile_mask_vertex_uniform_buffer =
device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
label: None,
contents: bytemuck::cast_slice(&tile_mask_geometry.vertices),
usage: wgpu::BufferUsages::VERTEX,
});
let tile_mask_indices_uniform_buffer =
device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
label: None,
contents: bytemuck::cast_slice(&tile_mask_geometry.indices),
usage: wgpu::BufferUsages::INDEX,
});
let instances = [
// Step 1
MaskInstanceUniform::new([0.0, 0.0], 4.0, 4.0, [1.0, 0.0, 0.0, 1.0]), // horizontal
@ -439,12 +412,9 @@ impl State {
globals_uniform_buffer,
prims_uniform_buffer,
indices_uniform_buffer,
tile_mask_vertex_uniform_buffer,
fps_meter: FPSMeter::new(),
tile_stroke_range,
tile2_fill_range,
tile_mask_indices_uniform_buffer,
tile_mask_range,
tile_mask_instances,
camera,
projection,
@ -567,15 +537,11 @@ impl State {
pass.set_bind_group(0, &self.bind_group, &[]);
{
// Draw Mask
// Draw masks
pass.set_pipeline(&self.mask_pipeline);
pass.set_index_buffer(
self.tile_mask_indices_uniform_buffer.slice(..),
INDEX_FORMAT,
);
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..11);
pass.set_vertex_buffer(0, self.tile_mask_instances.slice(..));
// Draw 11 squares each out of 6 vertices
pass.draw(0..6, 0..11);
}
{
pass.set_pipeline(&self.render_pipeline);