Search code examples
rustwgpu-rs

Triangles not drawing in wgpu with lyon


I am making a system for line drawing in wgpu with lyon. My problem is when I call draw_indexed() with the VertexBuffers from lyon nothing shows up.

Sorry about the huge amount of code, wgpu takes a lot to get running

impl LineDrawer {
fn build(self, device: &Device) -> Vec<Buffer> {
    let mut buffers = Vec::new();

    for i in self.lines {
        let buffer = i.build();
        let vertex = device.create_buffer_init(&BufferInitDescriptor { 
            label: None, 
            contents: bytemuck::cast_slice(&buffer.vertices),
            usage: wgpu::BufferUsages::VERTEX,
        });
        let index_len = buffer.indices.len();
        let index = device.create_buffer_init(&BufferInitDescriptor { 
            label: None, 
            contents: bytemuck::cast_slice(&buffer.indices),
            usage: wgpu::BufferUsages::INDEX,
        });
        buffers.push(Buffer { index, vertex, index_len });
    }

    buffers
}

pub fn render(
    self,
    device: &Device,
    encoder: &mut wgpu::CommandEncoder,
    view: &wgpu::TextureView,
    camera_bind_group: &wgpu::BindGroup,
) {
    let shader = device.create_shader_module(wgpu::include_wgsl!("line_drawer.wgsl"));
    let render_pipeline_layout =
        device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
            label: Some("Line Drawer Pipeline Layout"),
            bind_group_layouts: &[camera_bind_group_layout],
            push_constant_ranges: &[],
        });

    let pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
        label: Some("Line Drawer Pipeline"),
        layout: Some(&render_pipeline_layout),
        vertex: wgpu::VertexState {
            module: &shader,
            entry_point: "vs_main",
            buffers: &[ColorVertex::desc()],
        },
        fragment: Some(wgpu::FragmentState {
            module: &shader,
            entry_point: "fs_main",
            targets: &[Some(wgpu::ColorTargetState {
                format: config.format,
                blend: Some(wgpu::BlendState::ALPHA_BLENDING),
                write_mask: wgpu::ColorWrites::ALL,
            })],
        }),
        primitive: wgpu::PrimitiveState {
            topology: wgpu::PrimitiveTopology::TriangleList,
            polygon_mode: wgpu::PolygonMode::Fill,
            front_face: wgpu::FrontFace::Ccw,
            strip_index_format: None,
            cull_mode: Some(wgpu::Face::Back),
            conservative: false,
            unclipped_depth: false,
        },
        depth_stencil: None,
        multisample: wgpu::MultisampleState {
            count: 1,
            mask: !0,
            alpha_to_coverage_enabled: false,
        },
        multiview: None,
    });

    let buffers = self.build(device);
    {
        let mut render_pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
            label: Some("Render Pass"),
            color_attachments: &[Some(wgpu::RenderPassColorAttachment {
                view,
                resolve_target: None,
                ops: wgpu::Operations {
                    load: wgpu::LoadOp::Load,
                    store: true,
                },
            })],
            depth_stencil_attachment: None,
        });

        render_pass.set_pipeline(pipeline);
        render_pass.set_bind_group(0, camera_bind_group, &[]);

        for i in 0..buffers.len() {
            render_pass.set_index_buffer(buffers[i].index.slice(..), wgpu::IndexFormat::Uint16);
            render_pass.set_vertex_buffer(0, buffers[i].vertex.slice(..));

            render_pass.draw_indexed(0..buffers[i].index_len as u32, 0, 0..1)
        }
    }
}

pub struct Line {
    buffer: VertexBuffers<ColorVertex, u32>,
}

struct Buffer {
    index: wgpu::Buffer,
    vertex: wgpu::Buffer,
    index_len: usize,
}


impl Line {
pub fn rectangle(mut self, bounds: Rect, color: Color) -> Self {
    {
        let buffers = &mut self.buffer;
        let rect = lyon::math::Box2D::from_origin_and_size(
            lyon::math::point(bounds.x, bounds.y),
            lyon::math::size(bounds.width, bounds.height),
        );
        let vb = VertexBuilder {
            color: LinearColor::from(color),
        };
        let builder = &mut lyon::tessellation::BuffersBuilder::new(buffers, vb);
        let mut tessellator = lyon::tessellation::FillTessellator::new();
        tessellator.tessellate_rectangle(
             &rect, 
             &lyon::lyon_tessellation::FillOptions::default(), 
             builder
        )
        .expect("could not create rectangle");
    }
    self
}


pub fn build(self) -> VertexBuffers<ColorVertex, u32> {
    dbg!(&self.buffer);
    self.buffer
}

and here is the output

&self.buffer = VertexBuffers {
    vertices: [
        ColorVertex {
            position: [
                0.0,
                0.0,
                0.0,
            ],
            color: [
                1.0,
                1.0,
                1.0,
                1.0,
            ],
        },
        ColorVertex {
            position: [
                0.0,
                100.0,
                0.0,
            ],
            color: [
                1.0,
                1.0,
                1.0,
                1.0,
            ],
        },
        ColorVertex {
            position: [
                100.0,
                100.0,
                0.0,
            ],
            color: [
                1.0,
                1.0,
                1.0,
                1.0,
            ],
        },
        ColorVertex {
            position: [
                100.0,
                0.0,
                0.0,
            ],
            color: [
                1.0,
                1.0,
                1.0,
                1.0,
            ],
        },
    ],
    indices: [
        0,
        1,
        2,
        0,
        2,
        3,
    ],
    }

Solution

  • The fix was that lyon uses u32s as indices so I changed the pipelines index format to wgpu::IndexFormat::Uint16 and also the cull mode to Some(wgpu::Face::Front)