Skip to main content

rustial_renderer_wgpu/pipeline/
line_pattern_pipeline.rs

1//! Dedicated line-pattern render pipeline with repeating texture sampling.
2
3use crate::gpu::depth::DEPTH_FORMAT;
4use crate::gpu::line_pattern_vertex::LinePatternVertex;
5use crate::pipeline::uniforms::ViewProjUniform;
6
7/// The line-pattern rendering pipeline.
8///
9/// Uses a two-group bind layout:
10/// - Group 0: view-projection + line-style uniform (binding 0)
11/// - Group 1: pattern texture (binding 0) + sampler (binding 1)
12pub struct LinePatternPipeline {
13    /// Render pipeline configured for patterned line rendering.
14    pub pipeline: wgpu::RenderPipeline,
15    /// Bind group layout (group 0) for view-projection + line-style uniforms.
16    pub uniform_bind_group_layout: wgpu::BindGroupLayout,
17    /// Bind group layout (group 1) for per-batch pattern texture + sampler.
18    pub texture_bind_group_layout: wgpu::BindGroupLayout,
19}
20
21impl LinePatternPipeline {
22    /// Create the line-pattern pipeline.
23    pub fn new(device: &wgpu::Device, surface_format: wgpu::TextureFormat) -> Self {
24        let shader = device.create_shader_module(wgpu::ShaderModuleDescriptor {
25            label: Some("line_pattern_shader"),
26            source: wgpu::ShaderSource::Wgsl(include_str!("../shaders/line_pattern.wgsl").into()),
27        });
28
29        // Group 0: uniforms (same layout as solid line — ViewProjUniform
30        // which contains the line_style vec4).
31        let uniform_bind_group_layout =
32            device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
33                label: Some("line_pattern_uniform_bgl"),
34                entries: &[wgpu::BindGroupLayoutEntry {
35                    binding: 0,
36                    visibility: wgpu::ShaderStages::VERTEX_FRAGMENT,
37                    ty: wgpu::BindingType::Buffer {
38                        ty: wgpu::BufferBindingType::Uniform,
39                        has_dynamic_offset: false,
40                        min_binding_size: wgpu::BufferSize::new(
41                            std::mem::size_of::<ViewProjUniform>() as u64,
42                        ),
43                    },
44                    count: None,
45                }],
46            });
47
48        // Group 1: pattern texture + sampler.
49        let texture_bind_group_layout =
50            device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
51                label: Some("line_pattern_texture_bgl"),
52                entries: &[
53                    wgpu::BindGroupLayoutEntry {
54                        binding: 0,
55                        visibility: wgpu::ShaderStages::FRAGMENT,
56                        ty: wgpu::BindingType::Texture {
57                            multisampled: false,
58                            view_dimension: wgpu::TextureViewDimension::D2,
59                            sample_type: wgpu::TextureSampleType::Float { filterable: true },
60                        },
61                        count: None,
62                    },
63                    wgpu::BindGroupLayoutEntry {
64                        binding: 1,
65                        visibility: wgpu::ShaderStages::FRAGMENT,
66                        ty: wgpu::BindingType::Sampler(wgpu::SamplerBindingType::Filtering),
67                        count: None,
68                    },
69                ],
70            });
71
72        let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
73            label: Some("line_pattern_pipeline_layout"),
74            bind_group_layouts: &[&uniform_bind_group_layout, &texture_bind_group_layout],
75            push_constant_ranges: &[],
76        });
77
78        let pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
79            label: Some("line_pattern_pipeline"),
80            layout: Some(&pipeline_layout),
81            vertex: wgpu::VertexState {
82                module: &shader,
83                entry_point: Some("vs_main"),
84                buffers: &[LinePatternVertex::layout()],
85                compilation_options: wgpu::PipelineCompilationOptions::default(),
86            },
87            fragment: Some(wgpu::FragmentState {
88                module: &shader,
89                entry_point: Some("fs_main"),
90                targets: &[Some(wgpu::ColorTargetState {
91                    format: surface_format,
92                    blend: Some(wgpu::BlendState::ALPHA_BLENDING),
93                    write_mask: wgpu::ColorWrites::ALL,
94                })],
95                compilation_options: wgpu::PipelineCompilationOptions::default(),
96            }),
97            primitive: wgpu::PrimitiveState {
98                topology: wgpu::PrimitiveTopology::TriangleList,
99                front_face: wgpu::FrontFace::Ccw,
100                cull_mode: None,
101                ..Default::default()
102            },
103            depth_stencil: Some(wgpu::DepthStencilState {
104                format: DEPTH_FORMAT,
105                depth_write_enabled: true,
106                depth_compare: wgpu::CompareFunction::Less,
107                stencil: wgpu::StencilState::default(),
108                bias: wgpu::DepthBiasState::default(),
109            }),
110            multisample: wgpu::MultisampleState::default(),
111            multiview: None,
112            cache: None,
113        });
114
115        Self {
116            pipeline,
117            uniform_bind_group_layout,
118            texture_bind_group_layout,
119        }
120    }
121}