mirror of
https://github.com/maplibre/maplibre-rs.git
synced 2025-12-08 19:05:57 +00:00
Add a perfect masking stencil
This commit is contained in:
parent
1e66a8ee36
commit
35e18937a0
File diff suppressed because one or more lines are too long
|
Before Width: | Height: | Size: 27 KiB After Width: | Height: | Size: 106 KiB |
@ -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 {
|
||||
|
||||
@ -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,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
);
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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() {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user