veloren_voxygen/render/pipelines/
rope.rs1use super::super::{AaMode, Bound, Consts, GlobalsLayouts, Vertex as VertexTrait};
2use bytemuck::{Pod, Zeroable};
3use std::mem;
4use vek::*;
5
6#[repr(C)]
7#[derive(Copy, Clone, Debug, Zeroable, Pod)]
8pub struct Locals {
9 pos_a: [f32; 4],
10 pos_b: [f32; 4],
11 rope_length: f32,
12 _padding: [f32; 3],
13}
14
15impl Locals {
16 pub fn new(pos_a: Vec3<f32>, pos_b: Vec3<f32>, rope_length: f32) -> Self {
17 Self {
18 pos_a: pos_a.with_w(0.0).into_array(),
19 pos_b: pos_b.with_w(0.0).into_array(),
20 rope_length,
21 _padding: [0.0; 3],
22 }
23 }
24}
25
26impl Default for Locals {
27 fn default() -> Self { Self::new(Vec3::zero(), Vec3::zero(), 0.0) }
28}
29
30pub type BoundLocals = Bound<Consts<Locals>>;
31
32#[repr(C)]
33#[derive(Copy, Clone, Debug, Zeroable, Pod)]
34pub struct Vertex {
35 pub pos: [f32; 3],
36 pub norm: [f32; 3],
37}
38
39impl Vertex {
40 pub fn new(pos: Vec3<f32>, norm: Vec3<f32>) -> Self {
41 Self {
42 pos: pos.into_array(),
43 norm: norm.into_array(),
44 }
45 }
46
47 fn desc<'a>() -> wgpu::VertexBufferLayout<'a> {
48 const ATTRIBUTES: [wgpu::VertexAttribute; 2] =
49 wgpu::vertex_attr_array![0 => Float32x3, 1 => Float32x3];
50 wgpu::VertexBufferLayout {
51 array_stride: Self::STRIDE,
52 step_mode: wgpu::VertexStepMode::Vertex,
53 attributes: &ATTRIBUTES,
54 }
55 }
56}
57
58impl VertexTrait for Vertex {
59 const QUADS_INDEX: Option<wgpu::IndexFormat> = Some(wgpu::IndexFormat::Uint16);
60 const STRIDE: wgpu::BufferAddress = mem::size_of::<Self>() as wgpu::BufferAddress;
61}
62
63pub struct RopeLayout {
64 pub locals: wgpu::BindGroupLayout,
65}
66
67impl RopeLayout {
68 pub fn new(device: &wgpu::Device) -> Self {
69 Self {
70 locals: device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
71 label: None,
72 entries: &[
73 wgpu::BindGroupLayoutEntry {
75 binding: 0,
76 visibility: wgpu::ShaderStages::VERTEX_FRAGMENT,
77 ty: wgpu::BindingType::Buffer {
78 ty: wgpu::BufferBindingType::Uniform,
79 has_dynamic_offset: false,
80 min_binding_size: None,
81 },
82 count: None,
83 },
84 ],
85 }),
86 }
87 }
88
89 pub fn bind_locals(&self, device: &wgpu::Device, locals: Consts<Locals>) -> BoundLocals {
90 let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor {
91 label: None,
92 layout: &self.locals,
93 entries: &[wgpu::BindGroupEntry {
94 binding: 0,
95 resource: locals.buf().as_entire_binding(),
96 }],
97 });
98
99 BoundLocals {
100 bind_group,
101 with: locals,
102 }
103 }
104}
105
106pub struct RopePipeline {
107 pub pipeline: wgpu::RenderPipeline,
108}
109
110impl RopePipeline {
111 pub fn new(
112 device: &wgpu::Device,
113 vs_module: &wgpu::ShaderModule,
114 fs_module: &wgpu::ShaderModule,
115 global_layout: &GlobalsLayouts,
116 layout: &RopeLayout,
117 aa_mode: AaMode,
118 format: wgpu::TextureFormat,
119 ) -> Self {
120 common_base::span!(_guard, "RopePipeline::new");
121 let render_pipeline_layout =
122 device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
123 label: Some("Rope pipeline layout"),
124 push_constant_ranges: &[],
125 bind_group_layouts: &[
126 &global_layout.globals,
127 &global_layout.shadow_textures,
128 &layout.locals,
129 ],
130 });
131
132 let samples = aa_mode.samples();
133
134 let render_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
135 label: Some("Rope pipeline"),
136 layout: Some(&render_pipeline_layout),
137 vertex: wgpu::VertexState {
138 module: vs_module,
139 entry_point: "main",
140 buffers: &[Vertex::desc()],
141 },
142 primitive: wgpu::PrimitiveState {
143 topology: wgpu::PrimitiveTopology::TriangleList,
144 strip_index_format: None,
145 front_face: wgpu::FrontFace::Ccw,
146 cull_mode: Some(wgpu::Face::Back),
147 unclipped_depth: false,
148 polygon_mode: wgpu::PolygonMode::Fill,
149 conservative: false,
150 },
151 depth_stencil: Some(wgpu::DepthStencilState {
152 format: wgpu::TextureFormat::Depth32Float,
153 depth_write_enabled: true,
154 depth_compare: wgpu::CompareFunction::GreaterEqual,
155 stencil: wgpu::StencilState {
156 front: wgpu::StencilFaceState::IGNORE,
157 back: wgpu::StencilFaceState::IGNORE,
158 read_mask: !0,
159 write_mask: !0,
160 },
161 bias: wgpu::DepthBiasState {
162 constant: 0,
163 slope_scale: 0.0,
164 clamp: 0.0,
165 },
166 }),
167 multisample: wgpu::MultisampleState {
168 count: samples,
169 mask: !0,
170 alpha_to_coverage_enabled: false,
171 },
172 fragment: Some(wgpu::FragmentState {
173 module: fs_module,
174 entry_point: "main",
175 targets: &[
176 Some(wgpu::ColorTargetState {
177 format,
178 blend: Some(wgpu::BlendState {
179 color: wgpu::BlendComponent {
180 src_factor: wgpu::BlendFactor::SrcAlpha,
181 dst_factor: wgpu::BlendFactor::OneMinusSrcAlpha,
182 operation: wgpu::BlendOperation::Add,
183 },
184 alpha: wgpu::BlendComponent {
185 src_factor: wgpu::BlendFactor::One,
186 dst_factor: wgpu::BlendFactor::One,
187 operation: wgpu::BlendOperation::Add,
188 },
189 }),
190 write_mask: wgpu::ColorWrites::ALL,
191 }),
192 Some(wgpu::ColorTargetState {
193 format: wgpu::TextureFormat::Rgba8Uint,
194 blend: None,
195 write_mask: wgpu::ColorWrites::ALL,
196 }),
197 ],
198 }),
199 multiview: None,
200 });
201
202 Self {
203 pipeline: render_pipeline,
204 }
205 }
206}