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_line_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
278 label: Some("overlay-line"),
279 layout: Some(&pipeline_layout),
280 vertex: wgpu::VertexState {
281 module: &shader,
282 entry_point: Some("vs_overlay_line"),
283 compilation_options: Default::default(),
284 buffers: &[wgpu::VertexBufferLayout {
285 array_stride: std::mem::size_of::<OverlayLineInstance>() as u64,
286 step_mode: wgpu::VertexStepMode::Instance,
287 attributes: &wgpu::vertex_attr_array![0 => Float32x3, 1 => Float32x3, 2 => Float32x4],
288 }],
289 },
290 fragment: Some(wgpu::FragmentState {
291 module: &shader,
292 entry_point: Some("fs_overlay_line"),
293 compilation_options: Default::default(),
294 targets: &[color_target(Some(ALPHA_BLEND))],
295 }),
296 primitive: wgpu::PrimitiveState {
297 topology: wgpu::PrimitiveTopology::TriangleList,
298 front_face: wgpu::FrontFace::Ccw,
299 cull_mode: None,
300 ..Default::default()
301 },
302 depth_stencil: Some(wgpu::DepthStencilState {
303 format: DEPTH_FORMAT,
304 depth_write_enabled: Some(false),
305 depth_compare: Some(wgpu::CompareFunction::LessEqual),
306 stencil: Default::default(),
307 bias: Default::default(),
308 }),
309 multisample,
310 multiview_mask: None,
311 cache: None,
312 });
313
314 let vc_globals_buf = device.create_buffer(&wgpu::BufferDescriptor {
316 label: Some("viewcube globals"),
317 size: std::mem::size_of::<Globals>() as u64,
318 usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST,
319 mapped_at_creation: false,
320 });
321 let vc_globals_bind = device.create_bind_group(&wgpu::BindGroupDescriptor {
322 label: Some("viewcube globals"),
323 layout: &globals_layout,
324 entries: &[wgpu::BindGroupEntry {
325 binding: 0,
326 resource: vc_globals_buf.as_entire_binding(),
327 }],
328 });
329
330 let styles = GlobalStyles {
331 face_selected: StyleBuf::new(&device, &style_layout, "face-selected"),
332 face_hovered: StyleBuf::new(&device, &style_layout, "face-hovered"),
333 edge_base: StyleBuf::new(&device, &style_layout, "edge-base"),
334 edge_selected: StyleBuf::new(&device, &style_layout, "edge-selected"),
335 edge_hovered: StyleBuf::new(&device, &style_layout, "edge-hovered"),
336 edge_hidden: StyleBuf::new(&device, &style_layout, "edge-hidden"),
337 boundary: StyleBuf::new(&device, &style_layout, "boundary"),
338 point_base: StyleBuf::new(&device, &style_layout, "point-base"),
339 point_selected: StyleBuf::new(&device, &style_layout, "point-selected"),
340 point_hovered: StyleBuf::new(&device, &style_layout, "point-hovered"),
341 axis_x: StyleBuf::new(&device, &style_layout, "axis-x"),
342 axis_y: StyleBuf::new(&device, &style_layout, "axis-y"),
343 axis_z: StyleBuf::new(&device, &style_layout, "axis-z"),
344 overlay_line: StyleBuf::new(&device, &style_layout, "overlay-line"),
345 };
346
347 Self {
348 device,
349 queue,
350 format,
351 globals_buf,
352 globals_bind,
353 style_layout,
354 mesh_pipeline,
355 wire_pipeline,
356 edge_visible_pipeline,
357 edge_hidden_pipeline,
358 point_pipeline,
359 overlay_tri_pipeline,
360 overlay_line_pipeline,
361 vc_globals_buf,
362 vc_globals_bind,
363 styles,
364 targets: None,
365 }
366 }
367}