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
fail_op: wgpu::StencilOperation::Keep,
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 {
wgpu::StencilFaceState {

View File

@ -40,9 +40,11 @@ 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 + instance_idx];
var prim: PrimitiveUniform = u_primitives.primitives[a_prim_id];
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);

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 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 {
device: wgpu::Device,
@ -69,6 +75,8 @@ pub struct State {
indices_uniform_buffer: wgpu::Buffer,
tile_fill_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_indices_uniform_buffer: wgpu::Buffer,
@ -98,10 +106,18 @@ impl SceneParams {
// Stroke primitive
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
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);
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,
@ -116,16 +132,25 @@ impl State {
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());
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) = (
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 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
let instance = wgpu::Instance::new(wgpu::Backends::all());
@ -177,9 +202,9 @@ impl State {
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_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 =
device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
label: None,
@ -370,12 +395,14 @@ impl State {
tile_mask_vertex_uniform_buffer,
fps_meter: FPSMeter::new(),
tile_stroke_range,
tile2_fill_range,
tile_mask_indices_uniform_buffer,
tile_mask_range,
camera,
projection,
camera_controller,
mouse_pressed: false,
tile2_stroke_range
}
}
@ -529,10 +556,10 @@ impl State {
{
// Increment stencil
pass.set_pipeline(&self.mask_pipeline);
//pass.set_stencil_reference(0);
pass.set_stencil_reference(1);
pass.set_index_buffer(
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.draw_indexed(self.tile_mask_range.clone(), 0, 0..1);
@ -542,12 +569,34 @@ impl State {
pass.set_stencil_reference(1);
pass.set_index_buffer(
self.indices_uniform_buffer.slice(..),
wgpu::IndexFormat::Uint16,
INDEX_FORMAT,
);
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_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()));
@ -568,13 +617,13 @@ impl State {
// 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].color = [
/* scene.cpu_primitives[STROKE_PRIM_ID as usize].color = [
(time_secs * 0.8 - 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,
1.0,
];
*/
self.fps_meter.update_and_print()
}
}

View File

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