1use super::*;
2
3impl RenderCore {
4 pub fn new(device: wgpu::Device, queue: wgpu::Queue, format: wgpu::TextureFormat) -> Self {
5 let shader = device.create_shader_module(wgpu::ShaderModuleDescriptor {
6 label: Some("brep-render shaders"),
7 source: wgpu::ShaderSource::Wgsl(include_str!("../shaders.wgsl").into()),
8 });
9
10 let globals_layout = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
11 label: Some("globals"),
12 entries: &[wgpu::BindGroupLayoutEntry {
13 binding: 0,
14 visibility: wgpu::ShaderStages::VERTEX_FRAGMENT,
15 ty: wgpu::BindingType::Buffer {
16 ty: wgpu::BufferBindingType::Uniform,
17 has_dynamic_offset: false,
18 min_binding_size: None,
19 },
20 count: None,
21 }],
22 });
23 let style_layout = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
24 label: Some("style"),
25 entries: &[wgpu::BindGroupLayoutEntry {
26 binding: 0,
27 visibility: wgpu::ShaderStages::VERTEX_FRAGMENT,
28 ty: wgpu::BindingType::Buffer {
29 ty: wgpu::BufferBindingType::Uniform,
30 has_dynamic_offset: false,
31 min_binding_size: None,
32 },
33 count: None,
34 }],
35 });
36 let globals_buf = device.create_buffer(&wgpu::BufferDescriptor {
37 label: Some("globals"),
38 size: std::mem::size_of::<Globals>() as u64,
39 usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST,
40 mapped_at_creation: false,
41 });
42 let globals_bind = device.create_bind_group(&wgpu::BindGroupDescriptor {
43 label: Some("globals"),
44 layout: &globals_layout,
45 entries: &[wgpu::BindGroupEntry {
46 binding: 0,
47 resource: globals_buf.as_entire_binding(),
48 }],
49 });
50
51 let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
52 label: Some("brep-render"),
53 bind_group_layouts: &[Some(&globals_layout), Some(&style_layout)],
54 immediate_size: 0,
55 });
56
57 const ALPHA_BLEND: wgpu::BlendState = wgpu::BlendState::ALPHA_BLENDING;
58 let color_target = |blend: Option<wgpu::BlendState>| {
59 Some(wgpu::ColorTargetState {
60 format,
61 blend,
62 write_mask: wgpu::ColorWrites::ALL,
63 })
64 };
65 let multisample = wgpu::MultisampleState {
66 count: SAMPLES,
67 ..Default::default()
68 };
69
70 let mesh_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
71 label: Some("mesh"),
72 layout: Some(&pipeline_layout),
73 vertex: wgpu::VertexState {
74 module: &shader,
75 entry_point: Some("vs_mesh"),
76 compilation_options: Default::default(),
77 buffers: &[wgpu::VertexBufferLayout {
78 array_stride: std::mem::size_of::<MeshVertex>() as u64,
79 step_mode: wgpu::VertexStepMode::Vertex,
80 attributes: &wgpu::vertex_attr_array![0 => Float32x3, 1 => Float32x3],
81 }],
82 },
83 fragment: Some(wgpu::FragmentState {
84 module: &shader,
85 entry_point: Some("fs_mesh"),
86 compilation_options: Default::default(),
87 targets: &[color_target(None)],
88 }),
89 primitive: wgpu::PrimitiveState {
90 topology: wgpu::PrimitiveTopology::TriangleList,
91 front_face: wgpu::FrontFace::Ccw,
92 cull_mode: None,
95 ..Default::default()
96 },
97 depth_stencil: Some(wgpu::DepthStencilState {
98 format: DEPTH_FORMAT,
99 depth_write_enabled: Some(true),
100 depth_compare: Some(wgpu::CompareFunction::Less),
101 stencil: Default::default(),
102 bias: wgpu::DepthBiasState {
105 constant: 4,
106 slope_scale: 2.0,
107 clamp: 0.0,
108 },
109 }),
110 multisample,
111 multiview_mask: None,
112 cache: None,
113 });
114
115 let wire_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
119 label: Some("wireframe"),
120 layout: Some(&pipeline_layout),
121 vertex: wgpu::VertexState {
122 module: &shader,
123 entry_point: Some("vs_mesh"),
124 compilation_options: Default::default(),
125 buffers: &[wgpu::VertexBufferLayout {
126 array_stride: std::mem::size_of::<MeshVertex>() as u64,
127 step_mode: wgpu::VertexStepMode::Vertex,
128 attributes: &wgpu::vertex_attr_array![0 => Float32x3, 1 => Float32x3],
129 }],
130 },
131 fragment: Some(wgpu::FragmentState {
132 module: &shader,
133 entry_point: Some("fs_wire"),
134 compilation_options: Default::default(),
135 targets: &[color_target(None)],
136 }),
137 primitive: wgpu::PrimitiveState {
138 topology: wgpu::PrimitiveTopology::LineList,
139 front_face: wgpu::FrontFace::Ccw,
140 cull_mode: None,
141 ..Default::default()
142 },
143 depth_stencil: Some(wgpu::DepthStencilState {
144 format: DEPTH_FORMAT,
145 depth_write_enabled: Some(true),
146 depth_compare: Some(wgpu::CompareFunction::Less),
147 stencil: Default::default(),
148 bias: Default::default(),
149 }),
150 multisample,
151 multiview_mask: None,
152 cache: None,
153 });
154
155 let edge_pipeline = |label: &str, depth_compare: wgpu::CompareFunction| {
156 device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
157 label: Some(label),
158 layout: Some(&pipeline_layout),
159 vertex: wgpu::VertexState {
160 module: &shader,
161 entry_point: Some("vs_edge"),
162 compilation_options: Default::default(),
163 buffers: &[wgpu::VertexBufferLayout {
164 array_stride: std::mem::size_of::<EdgeInstance>() as u64,
165 step_mode: wgpu::VertexStepMode::Instance,
166 attributes: &wgpu::vertex_attr_array![0 => Float32x3, 1 => Float32x3],
167 }],
168 },
169 fragment: Some(wgpu::FragmentState {
170 module: &shader,
171 entry_point: Some("fs_edge"),
172 compilation_options: Default::default(),
173 targets: &[color_target(Some(ALPHA_BLEND))],
174 }),
175 primitive: wgpu::PrimitiveState {
176 topology: wgpu::PrimitiveTopology::TriangleList,
177 front_face: wgpu::FrontFace::Ccw,
178 cull_mode: None,
179 ..Default::default()
180 },
181 depth_stencil: Some(wgpu::DepthStencilState {
182 format: DEPTH_FORMAT,
183 depth_write_enabled: Some(false),
186 depth_compare: Some(depth_compare),
187 stencil: Default::default(),
188 bias: Default::default(),
189 }),
190 multisample,
191 multiview_mask: None,
192 cache: None,
193 })
194 };
195 let edge_visible_pipeline = edge_pipeline("edges", wgpu::CompareFunction::LessEqual);
198 let edge_hidden_pipeline = edge_pipeline("edges-hidden", wgpu::CompareFunction::Greater);
199
200 let point_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
201 label: Some("points"),
202 layout: Some(&pipeline_layout),
203 vertex: wgpu::VertexState {
204 module: &shader,
205 entry_point: Some("vs_point"),
206 compilation_options: Default::default(),
207 buffers: &[wgpu::VertexBufferLayout {
208 array_stride: std::mem::size_of::<PointInstance>() as u64,
209 step_mode: wgpu::VertexStepMode::Instance,
210 attributes: &wgpu::vertex_attr_array![0 => Float32x3],
211 }],
212 },
213 fragment: Some(wgpu::FragmentState {
214 module: &shader,
215 entry_point: Some("fs_point"),
216 compilation_options: Default::default(),
217 targets: &[color_target(Some(ALPHA_BLEND))],
218 }),
219 primitive: wgpu::PrimitiveState {
220 topology: wgpu::PrimitiveTopology::TriangleList,
221 front_face: wgpu::FrontFace::Ccw,
222 cull_mode: None,
223 ..Default::default()
224 },
225 depth_stencil: Some(wgpu::DepthStencilState {
226 format: DEPTH_FORMAT,
227 depth_write_enabled: Some(false),
228 depth_compare: Some(wgpu::CompareFunction::LessEqual),
229 stencil: Default::default(),
230 bias: Default::default(),
231 }),
232 multisample,
233 multiview_mask: None,
234 cache: None,
235 });
236
237 let overlay_tri_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
242 label: Some("overlay-tri"),
243 layout: Some(&pipeline_layout),
244 vertex: wgpu::VertexState {
245 module: &shader,
246 entry_point: Some("vs_overlay_tri"),
247 compilation_options: Default::default(),
248 buffers: &[wgpu::VertexBufferLayout {
249 array_stride: std::mem::size_of::<OverlayTriVertex>() as u64,
250 step_mode: wgpu::VertexStepMode::Vertex,
251 attributes: &wgpu::vertex_attr_array![0 => Float32x3, 1 => Float32x3, 2 => Float32x4],
252 }],
253 },
254 fragment: Some(wgpu::FragmentState {
255 module: &shader,
256 entry_point: Some("fs_overlay_tri"),
257 compilation_options: Default::default(),
258 targets: &[color_target(Some(ALPHA_BLEND))],
259 }),
260 primitive: wgpu::PrimitiveState {
261 topology: wgpu::PrimitiveTopology::TriangleList,
262 front_face: wgpu::FrontFace::Ccw,
263 cull_mode: None,
264 ..Default::default()
265 },
266 depth_stencil: Some(wgpu::DepthStencilState {
267 format: DEPTH_FORMAT,
268 depth_write_enabled: Some(true),
269 depth_compare: Some(wgpu::CompareFunction::LessEqual),
270 stencil: Default::default(),
271 bias: Default::default(),
272 }),
273 multisample,
274 multiview_mask: None,
275 cache: None,
276 });
277 let overlay_tri_nodepth_pipeline =
281 device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
282 label: Some("overlay-tri-nodepth"),
283 layout: Some(&pipeline_layout),
284 vertex: wgpu::VertexState {
285 module: &shader,
286 entry_point: Some("vs_overlay_tri"),
287 compilation_options: Default::default(),
288 buffers: &[wgpu::VertexBufferLayout {
289 array_stride: std::mem::size_of::<OverlayTriVertex>() as u64,
290 step_mode: wgpu::VertexStepMode::Vertex,
291 attributes: &wgpu::vertex_attr_array![0 => Float32x3, 1 => Float32x3, 2 => Float32x4],
292 }],
293 },
294 fragment: Some(wgpu::FragmentState {
295 module: &shader,
296 entry_point: Some("fs_overlay_tri"),
297 compilation_options: Default::default(),
298 targets: &[color_target(Some(ALPHA_BLEND))],
299 }),
300 primitive: wgpu::PrimitiveState {
301 topology: wgpu::PrimitiveTopology::TriangleList,
302 front_face: wgpu::FrontFace::Ccw,
303 cull_mode: None,
304 ..Default::default()
305 },
306 depth_stencil: Some(wgpu::DepthStencilState {
307 format: DEPTH_FORMAT,
308 depth_write_enabled: Some(false),
309 depth_compare: Some(wgpu::CompareFunction::LessEqual),
310 stencil: Default::default(),
311 bias: Default::default(),
312 }),
313 multisample,
314 multiview_mask: None,
315 cache: None,
316 });
317 let overlay_line_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
318 label: Some("overlay-line"),
319 layout: Some(&pipeline_layout),
320 vertex: wgpu::VertexState {
321 module: &shader,
322 entry_point: Some("vs_overlay_line"),
323 compilation_options: Default::default(),
324 buffers: &[wgpu::VertexBufferLayout {
325 array_stride: std::mem::size_of::<OverlayLineInstance>() as u64,
326 step_mode: wgpu::VertexStepMode::Instance,
327 attributes: &wgpu::vertex_attr_array![0 => Float32x3, 1 => Float32x3, 2 => Float32x4],
328 }],
329 },
330 fragment: Some(wgpu::FragmentState {
331 module: &shader,
332 entry_point: Some("fs_overlay_line"),
333 compilation_options: Default::default(),
334 targets: &[color_target(Some(ALPHA_BLEND))],
335 }),
336 primitive: wgpu::PrimitiveState {
337 topology: wgpu::PrimitiveTopology::TriangleList,
338 front_face: wgpu::FrontFace::Ccw,
339 cull_mode: None,
340 ..Default::default()
341 },
342 depth_stencil: Some(wgpu::DepthStencilState {
343 format: DEPTH_FORMAT,
344 depth_write_enabled: Some(false),
345 depth_compare: Some(wgpu::CompareFunction::LessEqual),
346 stencil: Default::default(),
347 bias: Default::default(),
348 }),
349 multisample,
350 multiview_mask: None,
351 cache: None,
352 });
353
354 let vc_globals_buf = device.create_buffer(&wgpu::BufferDescriptor {
356 label: Some("viewcube globals"),
357 size: std::mem::size_of::<Globals>() as u64,
358 usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST,
359 mapped_at_creation: false,
360 });
361 let vc_globals_bind = device.create_bind_group(&wgpu::BindGroupDescriptor {
362 label: Some("viewcube globals"),
363 layout: &globals_layout,
364 entries: &[wgpu::BindGroupEntry {
365 binding: 0,
366 resource: vc_globals_buf.as_entire_binding(),
367 }],
368 });
369
370 let styles = GlobalStyles {
371 face_selected: StyleBuf::new(&device, &style_layout, "face-selected"),
372 face_hovered: StyleBuf::new(&device, &style_layout, "face-hovered"),
373 edge_base: StyleBuf::new(&device, &style_layout, "edge-base"),
374 edge_selected: StyleBuf::new(&device, &style_layout, "edge-selected"),
375 edge_hovered: StyleBuf::new(&device, &style_layout, "edge-hovered"),
376 edge_hidden: StyleBuf::new(&device, &style_layout, "edge-hidden"),
377 boundary: StyleBuf::new(&device, &style_layout, "boundary"),
378 point_base: StyleBuf::new(&device, &style_layout, "point-base"),
379 point_selected: StyleBuf::new(&device, &style_layout, "point-selected"),
380 point_hovered: StyleBuf::new(&device, &style_layout, "point-hovered"),
381 axis_x: StyleBuf::new(&device, &style_layout, "axis-x"),
382 axis_y: StyleBuf::new(&device, &style_layout, "axis-y"),
383 axis_z: StyleBuf::new(&device, &style_layout, "axis-z"),
384 overlay_line: StyleBuf::new(&device, &style_layout, "overlay-line"),
385 };
386
387 Self {
388 device,
389 queue,
390 format,
391 globals_buf,
392 globals_bind,
393 style_layout,
394 mesh_pipeline,
395 wire_pipeline,
396 edge_visible_pipeline,
397 edge_hidden_pipeline,
398 point_pipeline,
399 overlay_tri_pipeline,
400 overlay_tri_nodepth_pipeline,
401 overlay_line_pipeline,
402 vc_globals_buf,
403 vc_globals_bind,
404 styles,
405 targets: None,
406 }
407 }
408}