First time rendering two tiles

This commit is contained in:
Maximilian Ammann 2021-12-18 18:00:03 +01:00
parent 62e29042a7
commit aeba8afc31
4 changed files with 106 additions and 46 deletions

View File

@ -33,7 +33,7 @@ pub fn create_map_render_pipeline_description<'a>(
compare: wgpu::CompareFunction::Always, // Allow ALL values to update the stencil compare: wgpu::CompareFunction::Always, // Allow ALL values to update the stencil
fail_op: wgpu::StencilOperation::Keep, fail_op: wgpu::StencilOperation::Keep,
depth_fail_op: wgpu::StencilOperation::Keep, // This is used when the depth test already failed depth_fail_op: wgpu::StencilOperation::Keep, // This is used when the depth test already failed
pass_op: wgpu::StencilOperation::IncrementClamp, pass_op: wgpu::StencilOperation::Replace,
} }
} else { } else {
wgpu::StencilFaceState { wgpu::StencilFaceState {

View File

@ -40,9 +40,11 @@ fn main(
[[location(2)]] a_prim_id: u32, [[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" [[builtin(instance_index)]] instance_idx: u32 // instance_index is used when we have multiple instances of the same "object"
) -> VertexOutput { ) -> VertexOutput {
var prim: PrimitiveUniform = u_primitives.primitives[a_prim_id + instance_idx]; var prim: PrimitiveUniform = u_primitives.primitives[a_prim_id];
var z = 0.0; var z = 0.0;
var world_pos = a_position + a_normal * prim.width;
var mask_offset = vec2<f32>(f32(instance_idx) * 4096.0, 0.0);
var world_pos = a_position + mask_offset + prim.translate + a_normal * prim.width;
var position = globals.camera.view_proj * vec4<f32>(world_pos, z, 1.0); var position = globals.camera.view_proj * vec4<f32>(world_pos, z, 1.0);

View File

@ -38,9 +38,15 @@ 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 PRIM_BUFFER_LEN: usize = 256;
const STROKE_PRIM_ID: u32 = 0; const STROKE_PRIM_ID: u32 = 0;
const FILL_PRIM_ID: u32 = 1; 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 { pub struct State {
device: wgpu::Device, device: wgpu::Device,
@ -69,6 +75,8 @@ pub struct State {
indices_uniform_buffer: wgpu::Buffer, indices_uniform_buffer: wgpu::Buffer,
tile_fill_range: Range<u32>, tile_fill_range: Range<u32>,
tile_stroke_range: Range<u32>, tile_stroke_range: Range<u32>,
tile2_fill_range: Range<u32>,
tile2_stroke_range: Range<u32>,
tile_mask_vertex_uniform_buffer: wgpu::Buffer, tile_mask_vertex_uniform_buffer: wgpu::Buffer,
tile_mask_indices_uniform_buffer: wgpu::Buffer, tile_mask_indices_uniform_buffer: wgpu::Buffer,
@ -98,10 +106,18 @@ impl SceneParams {
// Stroke primitive // Stroke primitive
cpu_primitives[STROKE_PRIM_ID as usize] = cpu_primitives[STROKE_PRIM_ID as usize] =
PrimitiveUniform::new([0.0, 0.0, 0.0, 1.0], [0.0, 0.0], 0, 1.0, 0.0, 1.0); PrimitiveUniform::new([1.0, 0.0, 1.0, 1.0], [0.0, 0.0], 0, 1.0, 0.0, 1.0);
cpu_primitives[SECOND_TILE_STROKE_PRIM_ID as usize] =
PrimitiveUniform::new([0.5, 0.8, 0.1, 1.0], [4096.0, 0.0], 0, 1.0, 0.0, 1.0);
// Main fill primitive // Main fill primitive
cpu_primitives[FILL_PRIM_ID as usize] = cpu_primitives[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); PrimitiveUniform::new([0.0, 0.0, 1.0, 1.0], [0.0, 0.0], 0, 1.0, 0.0, 1.0);
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 { Self {
cpu_primitives, cpu_primitives,
@ -116,16 +132,25 @@ impl State {
let size = window.inner_size(); let size = window.inner_size();
let mut geometry: VertexBuffers<GpuVertexUniform, u16> = VertexBuffers::new(); let mut geometry: VertexBuffers<GpuVertexUniform, IndexDataType> = VertexBuffers::new();
println!("Using static database from {}", static_database::get_source_path()); println!("Using static database from {}", static_database::get_source_path());
let tile = parse_tile_reader(&mut Cursor::new(static_database::get_tile(2179, 1421,12).unwrap().contents())).expect("failed to load tile"); let tile = parse_tile_reader(&mut Cursor::new(static_database::get_tile(2179, 1421,12).unwrap().contents())).expect("failed to load tile");
let (tile_stroke_range, tile_fill_range) = ( let (tile_stroke_range, tile_fill_range) = (
tile.tesselate_stroke(&mut geometry, STROKE_PRIM_ID), tile.tesselate_stroke(&mut geometry, STROKE_PRIM_ID),
//tile.empty_range(&mut geometry, STROKE_PRIM_ID),
tile.tesselate_fill(&mut geometry, FILL_PRIM_ID), tile.tesselate_fill(&mut geometry, FILL_PRIM_ID),
); );
// tile right to it
let tile = parse_tile_reader(&mut Cursor::new(static_database::get_tile(2180, 1421,12).unwrap().contents())).expect("failed to load tile");
let (tile2_stroke_range, tile2_fill_range) = (
tile.tesselate_stroke(&mut geometry, SECOND_TILE_STROKE_PRIM_ID),
//tile.empty_range(&mut geometry, STROKE_PRIM_ID),
tile.tesselate_fill(&mut geometry, SECOND_TILE_FILL_PRIM_ID),
);
// create an instance // create an instance
let instance = wgpu::Instance::new(wgpu::Backends::all()); let instance = wgpu::Instance::new(wgpu::Backends::all());
@ -177,9 +202,9 @@ impl State {
usage: wgpu::BufferUsages::INDEX, usage: wgpu::BufferUsages::INDEX,
}); });
let mut tile_mask_geometry: VertexBuffers<GpuVertexUniform, u16> = VertexBuffers::new(); let mut tile_mask_geometry: VertexBuffers<GpuVertexUniform, IndexDataType> = VertexBuffers::new();
let tile_mask = TileMask(); let tile_mask = TileMask();
let tile_mask_range = tile_mask.tesselate_fill(&mut tile_mask_geometry, FILL_PRIM_ID); let tile_mask_range = tile_mask.tesselate_fill(&mut tile_mask_geometry, MASK_FILL_PRIM_ID);
let tile_mask_vertex_uniform_buffer = let tile_mask_vertex_uniform_buffer =
device.create_buffer_init(&wgpu::util::BufferInitDescriptor { device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
label: None, label: None,
@ -370,12 +395,14 @@ impl State {
tile_mask_vertex_uniform_buffer, tile_mask_vertex_uniform_buffer,
fps_meter: FPSMeter::new(), fps_meter: FPSMeter::new(),
tile_stroke_range, tile_stroke_range,
tile2_fill_range,
tile_mask_indices_uniform_buffer, tile_mask_indices_uniform_buffer,
tile_mask_range, tile_mask_range,
camera, camera,
projection, projection,
camera_controller, camera_controller,
mouse_pressed: false, mouse_pressed: false,
tile2_stroke_range
} }
} }
@ -529,10 +556,10 @@ impl State {
{ {
// Increment stencil // Increment stencil
pass.set_pipeline(&self.mask_pipeline); pass.set_pipeline(&self.mask_pipeline);
//pass.set_stencil_reference(0); pass.set_stencil_reference(1);
pass.set_index_buffer( pass.set_index_buffer(
self.tile_mask_indices_uniform_buffer.slice(..), self.tile_mask_indices_uniform_buffer.slice(..),
wgpu::IndexFormat::Uint16, INDEX_FORMAT,
); );
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.draw_indexed(self.tile_mask_range.clone(), 0, 0..1); pass.draw_indexed(self.tile_mask_range.clone(), 0, 0..1);
@ -542,12 +569,34 @@ impl State {
pass.set_stencil_reference(1); pass.set_stencil_reference(1);
pass.set_index_buffer( pass.set_index_buffer(
self.indices_uniform_buffer.slice(..), self.indices_uniform_buffer.slice(..),
wgpu::IndexFormat::Uint16, INDEX_FORMAT,
); );
pass.set_vertex_buffer(0, self.vertex_uniform_buffer.slice(..)); pass.set_vertex_buffer(0, self.vertex_uniform_buffer.slice(..));
pass.draw_indexed(self.tile_fill_range.clone(), 0, 0..1); pass.draw_indexed(self.tile_fill_range.clone(), 0, 0..1);
pass.draw_indexed(self.tile_stroke_range.clone(), 0, 0..1); pass.draw_indexed(self.tile_stroke_range.clone(), 0, 0..1);
} }
{
// Increment stencil
pass.set_pipeline(&self.mask_pipeline);
pass.set_stencil_reference(2);
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.draw_indexed(self.tile_mask_range.clone(), 0, 1..2);
}
{
pass.set_pipeline(&self.render_pipeline);
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(..));
pass.draw_indexed(self.tile2_fill_range.clone(), 0, 0..1);
pass.draw_indexed(self.tile2_stroke_range.clone(), 0, 0..1);
}
} }
self.queue.submit(Some(encoder.finish())); self.queue.submit(Some(encoder.finish()));
@ -568,13 +617,13 @@ impl State {
// Animate the strokes of primitive // Animate the strokes of primitive
scene.cpu_primitives[STROKE_PRIM_ID as usize].width = scene.stroke_width; scene.cpu_primitives[STROKE_PRIM_ID as usize].width = scene.stroke_width;
scene.cpu_primitives[STROKE_PRIM_ID as usize].color = [ /* scene.cpu_primitives[STROKE_PRIM_ID as usize].color = [
(time_secs * 0.8 - 1.6).sin() * 0.1 + 0.1, (time_secs * 0.8 - 1.6).sin() * 0.1 + 0.1,
(time_secs * 0.5 - 1.6).sin() * 0.1 + 0.1, (time_secs * 0.5 - 1.6).sin() * 0.1 + 0.1,
(time_secs - 1.6).sin() * 0.1 + 0.1, (time_secs - 1.6).sin() * 0.1 + 0.1,
1.0, 1.0,
]; ];
*/
self.fps_meter.update_and_print() self.fps_meter.update_and_print()
} }
} }

View File

@ -7,6 +7,7 @@ use lyon::tessellation::{
BuffersBuilder, FillOptions, FillVertexConstructor, StrokeOptions, StrokeVertexConstructor, BuffersBuilder, FillOptions, FillVertexConstructor, StrokeOptions, StrokeVertexConstructor,
VertexBuffers, VertexBuffers,
}; };
use lyon::tessellation::geometry_builder::MaxIndex;
use lyon_path::builder::SvgPathBuilder; use lyon_path::builder::SvgPathBuilder;
use lyon_path::Path; use lyon_path::Path;
@ -17,9 +18,15 @@ use super::shader_ffi::GpuVertexUniform;
const DEFAULT_TOLERANCE: f32 = 0.02; const DEFAULT_TOLERANCE: f32 = 0.02;
pub trait Tesselated { pub trait Tesselated<OutputIndex: std::ops::Add> {
fn tesselate_stroke(&self, buffer: &mut VertexBuffers<GpuVertexUniform, u16>, prim_id: u32) -> Range<u32>; fn tesselate_stroke(&self, buffer: &mut VertexBuffers<GpuVertexUniform, OutputIndex>, prim_id: u32) -> Range<u32>;
fn tesselate_fill(&self, buffer: &mut VertexBuffers<GpuVertexUniform, u16>, prim_id: u32) -> Range<u32>; fn tesselate_fill(&self, buffer: &mut VertexBuffers<GpuVertexUniform, OutputIndex>, prim_id: u32) -> Range<u32>;
fn empty_range(&self, buffer: &mut VertexBuffers<GpuVertexUniform, OutputIndex>,
_prim_id: u32) -> Range<u32> {
let initial_indices_count = buffer.indices.len() as u32;
(initial_indices_count..initial_indices_count)
}
} }
/// This vertex constructor forwards the positions and normals provided by the /// This vertex constructor forwards the positions and normals provided by the
@ -45,11 +52,12 @@ impl StrokeVertexConstructor<GpuVertexUniform> for WithId {
fn build_path( fn build_path(
tile: &Tile, tile: &Tile,
fill: bool
) -> Path { ) -> Path {
let mut tile_builder = Path::builder().with_svg(); let mut tile_builder = Path::builder().with_svg();
for layer in tile.layers() { for layer in tile.layers() {
if layer.name() != "water" { if layer.name() != "transportation" {
continue; continue;
} }
@ -79,24 +87,26 @@ fn build_path(
} }
} }
Geometry::GeometryLineString(polygon) => { Geometry::GeometryLineString(polygon) => {
for command in &polygon.commands { if !fill {
match command { for command in &polygon.commands {
Command::MoveTo(cmd) => { match command {
tile_builder.relative_move_to(lyon_path::math::vector( Command::MoveTo(cmd) => {
cmd.x as f32, tile_builder.relative_move_to(lyon_path::math::vector(
cmd.y as f32, cmd.x as f32,
)); cmd.y as f32,
} ));
Command::LineTo(cmd) => { }
tile_builder.relative_line_to(lyon_path::math::vector( Command::LineTo(cmd) => {
cmd.x as f32, tile_builder.relative_line_to(lyon_path::math::vector(
cmd.y as f32, cmd.x as f32,
)); cmd.y as f32,
} ));
Command::Close => { }
panic!("error") Command::Close => {
} panic!("error")
}; }
};
}
} }
} }
_ => {} _ => {}
@ -108,18 +118,17 @@ fn build_path(
tile_builder.build() tile_builder.build()
} }
impl<OutputIndex: std::ops::Add + std::convert::From<lyon::lyon_tessellation::VertexId> + MaxIndex> Tesselated<OutputIndex> for Tile {
impl Tesselated for Tile {
fn tesselate_stroke( fn tesselate_stroke(
&self, &self,
buffer: &mut VertexBuffers<GpuVertexUniform, u16>, buffer: &mut VertexBuffers<GpuVertexUniform, OutputIndex>,
prim_id: u32, prim_id: u32,
) -> Range<u32> { ) -> Range<u32> {
let mut tesselator = StrokeTessellator::new(); let mut tesselator = StrokeTessellator::new();
let initial_indices_count = buffer.indices.len(); let initial_indices_count = buffer.indices.len();
let tile_path = build_path(self); let tile_path = build_path(self, false);
tesselator tesselator
.tessellate_path( .tessellate_path(
@ -132,12 +141,12 @@ impl Tesselated for Tile {
initial_indices_count as u32..buffer.indices.len() as u32 initial_indices_count as u32..buffer.indices.len() as u32
} }
fn tesselate_fill(&self, buffer: &mut VertexBuffers<GpuVertexUniform, u16>, prim_id: u32) -> Range<u32> { fn tesselate_fill(&self, buffer: &mut VertexBuffers<GpuVertexUniform, OutputIndex>, prim_id: u32) -> Range<u32> {
let mut tesselator = FillTessellator::new(); let mut tesselator = FillTessellator::new();
let initial_indices_count = buffer.indices.len(); let initial_indices_count = buffer.indices.len();
let tile_path = build_path(self); let tile_path = build_path(self, true);
tesselator tesselator
.tessellate_path( .tessellate_path(
@ -153,8 +162,8 @@ impl Tesselated for Tile {
pub struct RustLogo(); pub struct RustLogo();
impl Tesselated for RustLogo { impl<OutputIndex: std::ops::Add + std::convert::From<lyon::lyon_tessellation::VertexId> + MaxIndex> Tesselated<OutputIndex> for RustLogo {
fn tesselate_stroke(&self, buffer: &mut VertexBuffers<GpuVertexUniform, u16>, prim_id: u32) -> Range<u32> { fn tesselate_stroke(&self, buffer: &mut VertexBuffers<GpuVertexUniform, OutputIndex>, prim_id: u32) -> Range<u32> {
let mut stroke_tess = StrokeTessellator::new(); let mut stroke_tess = StrokeTessellator::new();
let initial_indices_count = buffer.indices.len(); let initial_indices_count = buffer.indices.len();
@ -175,7 +184,7 @@ impl Tesselated for RustLogo {
initial_indices_count as u32..buffer.indices.len() as u32 initial_indices_count as u32..buffer.indices.len() as u32
} }
fn tesselate_fill(&self, buffer: &mut VertexBuffers<GpuVertexUniform, u16>, prim_id: u32) -> Range<u32> { fn tesselate_fill(&self, buffer: &mut VertexBuffers<GpuVertexUniform, OutputIndex>, prim_id: u32) -> Range<u32> {
let mut fill_tess = FillTessellator::new(); let mut fill_tess = FillTessellator::new();
let initial_indices_count = buffer.indices.len(); let initial_indices_count = buffer.indices.len();
@ -203,12 +212,12 @@ const EXTENT: f32 = 4096.0;
pub struct TileMask(); pub struct TileMask();
impl Tesselated for TileMask { impl Tesselated<u32> for TileMask {
fn tesselate_stroke(&self, _buffer: &mut VertexBuffers<GpuVertexUniform, u16>, _prim_id: u32) -> Range<u32> { fn tesselate_stroke(&self, _buffer: &mut VertexBuffers<GpuVertexUniform, u32>, _prim_id: u32) -> Range<u32> {
0..0 0..0
} }
fn tesselate_fill(&self, buffer: &mut VertexBuffers<GpuVertexUniform, u16>, prim_id: u32) -> Range<u32> { fn tesselate_fill(&self, buffer: &mut VertexBuffers<GpuVertexUniform, u32>, prim_id: u32) -> Range<u32> {
let initial_indices_count = buffer.indices.len(); let initial_indices_count = buffer.indices.len();
buffer.vertices = vec![ buffer.vertices = vec![