use super::*;
impl RenderCore {
pub fn new(device: wgpu::Device, queue: wgpu::Queue, format: wgpu::TextureFormat) -> Self {
let shader = device.create_shader_module(wgpu::ShaderModuleDescriptor {
label: Some("brep-render shaders"),
source: wgpu::ShaderSource::Wgsl(include_str!("../shaders.wgsl").into()),
});
let globals_layout = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
label: Some("globals"),
entries: &[wgpu::BindGroupLayoutEntry {
binding: 0,
visibility: wgpu::ShaderStages::VERTEX_FRAGMENT,
ty: wgpu::BindingType::Buffer {
ty: wgpu::BufferBindingType::Uniform,
has_dynamic_offset: false,
min_binding_size: None,
},
count: None,
}],
});
let style_layout = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
label: Some("style"),
entries: &[wgpu::BindGroupLayoutEntry {
binding: 0,
visibility: wgpu::ShaderStages::VERTEX_FRAGMENT,
ty: wgpu::BindingType::Buffer {
ty: wgpu::BufferBindingType::Uniform,
has_dynamic_offset: false,
min_binding_size: None,
},
count: None,
}],
});
let globals_buf = device.create_buffer(&wgpu::BufferDescriptor {
label: Some("globals"),
size: std::mem::size_of::<Globals>() as u64,
usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST,
mapped_at_creation: false,
});
let globals_bind = device.create_bind_group(&wgpu::BindGroupDescriptor {
label: Some("globals"),
layout: &globals_layout,
entries: &[wgpu::BindGroupEntry {
binding: 0,
resource: globals_buf.as_entire_binding(),
}],
});
let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
label: Some("brep-render"),
bind_group_layouts: &[Some(&globals_layout), Some(&style_layout)],
immediate_size: 0,
});
const ALPHA_BLEND: wgpu::BlendState = wgpu::BlendState::ALPHA_BLENDING;
let color_target = |blend: Option<wgpu::BlendState>| {
Some(wgpu::ColorTargetState {
format,
blend,
write_mask: wgpu::ColorWrites::ALL,
})
};
let multisample = wgpu::MultisampleState {
count: SAMPLES,
..Default::default()
};
let mesh_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
label: Some("mesh"),
layout: Some(&pipeline_layout),
vertex: wgpu::VertexState {
module: &shader,
entry_point: Some("vs_mesh"),
compilation_options: Default::default(),
buffers: &[wgpu::VertexBufferLayout {
array_stride: std::mem::size_of::<MeshVertex>() as u64,
step_mode: wgpu::VertexStepMode::Vertex,
attributes: &wgpu::vertex_attr_array![0 => Float32x3, 1 => Float32x3],
}],
},
fragment: Some(wgpu::FragmentState {
module: &shader,
entry_point: Some("fs_mesh"),
compilation_options: Default::default(),
targets: &[color_target(None)],
}),
primitive: wgpu::PrimitiveState {
topology: wgpu::PrimitiveTopology::TriangleList,
front_face: wgpu::FrontFace::Ccw,
cull_mode: None,
..Default::default()
},
depth_stencil: Some(wgpu::DepthStencilState {
format: DEPTH_FORMAT,
depth_write_enabled: Some(true),
depth_compare: Some(wgpu::CompareFunction::Less),
stencil: Default::default(),
bias: wgpu::DepthBiasState {
constant: 4,
slope_scale: 2.0,
clamp: 0.0,
},
}),
multisample,
multiview_mask: None,
cache: None,
});
let wire_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
label: Some("wireframe"),
layout: Some(&pipeline_layout),
vertex: wgpu::VertexState {
module: &shader,
entry_point: Some("vs_mesh"),
compilation_options: Default::default(),
buffers: &[wgpu::VertexBufferLayout {
array_stride: std::mem::size_of::<MeshVertex>() as u64,
step_mode: wgpu::VertexStepMode::Vertex,
attributes: &wgpu::vertex_attr_array![0 => Float32x3, 1 => Float32x3],
}],
},
fragment: Some(wgpu::FragmentState {
module: &shader,
entry_point: Some("fs_wire"),
compilation_options: Default::default(),
targets: &[color_target(None)],
}),
primitive: wgpu::PrimitiveState {
topology: wgpu::PrimitiveTopology::LineList,
front_face: wgpu::FrontFace::Ccw,
cull_mode: None,
..Default::default()
},
depth_stencil: Some(wgpu::DepthStencilState {
format: DEPTH_FORMAT,
depth_write_enabled: Some(true),
depth_compare: Some(wgpu::CompareFunction::Less),
stencil: Default::default(),
bias: Default::default(),
}),
multisample,
multiview_mask: None,
cache: None,
});
let edge_pipeline = |label: &str, depth_compare: wgpu::CompareFunction| {
device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
label: Some(label),
layout: Some(&pipeline_layout),
vertex: wgpu::VertexState {
module: &shader,
entry_point: Some("vs_edge"),
compilation_options: Default::default(),
buffers: &[wgpu::VertexBufferLayout {
array_stride: std::mem::size_of::<EdgeInstance>() as u64,
step_mode: wgpu::VertexStepMode::Instance,
attributes: &wgpu::vertex_attr_array![0 => Float32x3, 1 => Float32x3],
}],
},
fragment: Some(wgpu::FragmentState {
module: &shader,
entry_point: Some("fs_edge"),
compilation_options: Default::default(),
targets: &[color_target(Some(ALPHA_BLEND))],
}),
primitive: wgpu::PrimitiveState {
topology: wgpu::PrimitiveTopology::TriangleList,
front_face: wgpu::FrontFace::Ccw,
cull_mode: None,
..Default::default()
},
depth_stencil: Some(wgpu::DepthStencilState {
format: DEPTH_FORMAT,
depth_write_enabled: Some(false),
depth_compare: Some(depth_compare),
stencil: Default::default(),
bias: Default::default(),
}),
multisample,
multiview_mask: None,
cache: None,
})
};
let edge_visible_pipeline = edge_pipeline("edges", wgpu::CompareFunction::LessEqual);
let edge_hidden_pipeline = edge_pipeline("edges-hidden", wgpu::CompareFunction::Greater);
let point_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
label: Some("points"),
layout: Some(&pipeline_layout),
vertex: wgpu::VertexState {
module: &shader,
entry_point: Some("vs_point"),
compilation_options: Default::default(),
buffers: &[wgpu::VertexBufferLayout {
array_stride: std::mem::size_of::<PointInstance>() as u64,
step_mode: wgpu::VertexStepMode::Instance,
attributes: &wgpu::vertex_attr_array![0 => Float32x3],
}],
},
fragment: Some(wgpu::FragmentState {
module: &shader,
entry_point: Some("fs_point"),
compilation_options: Default::default(),
targets: &[color_target(Some(ALPHA_BLEND))],
}),
primitive: wgpu::PrimitiveState {
topology: wgpu::PrimitiveTopology::TriangleList,
front_face: wgpu::FrontFace::Ccw,
cull_mode: None,
..Default::default()
},
depth_stencil: Some(wgpu::DepthStencilState {
format: DEPTH_FORMAT,
depth_write_enabled: Some(false),
depth_compare: Some(wgpu::CompareFunction::LessEqual),
stencil: Default::default(),
bias: Default::default(),
}),
multisample,
multiview_mask: None,
cache: None,
});
let overlay_tri_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
label: Some("overlay-tri"),
layout: Some(&pipeline_layout),
vertex: wgpu::VertexState {
module: &shader,
entry_point: Some("vs_overlay_tri"),
compilation_options: Default::default(),
buffers: &[wgpu::VertexBufferLayout {
array_stride: std::mem::size_of::<OverlayTriVertex>() as u64,
step_mode: wgpu::VertexStepMode::Vertex,
attributes: &wgpu::vertex_attr_array![0 => Float32x3, 1 => Float32x3, 2 => Float32x4],
}],
},
fragment: Some(wgpu::FragmentState {
module: &shader,
entry_point: Some("fs_overlay_tri"),
compilation_options: Default::default(),
targets: &[color_target(Some(ALPHA_BLEND))],
}),
primitive: wgpu::PrimitiveState {
topology: wgpu::PrimitiveTopology::TriangleList,
front_face: wgpu::FrontFace::Ccw,
cull_mode: None,
..Default::default()
},
depth_stencil: Some(wgpu::DepthStencilState {
format: DEPTH_FORMAT,
depth_write_enabled: Some(true),
depth_compare: Some(wgpu::CompareFunction::LessEqual),
stencil: Default::default(),
bias: Default::default(),
}),
multisample,
multiview_mask: None,
cache: None,
});
let overlay_line_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
label: Some("overlay-line"),
layout: Some(&pipeline_layout),
vertex: wgpu::VertexState {
module: &shader,
entry_point: Some("vs_overlay_line"),
compilation_options: Default::default(),
buffers: &[wgpu::VertexBufferLayout {
array_stride: std::mem::size_of::<OverlayLineInstance>() as u64,
step_mode: wgpu::VertexStepMode::Instance,
attributes: &wgpu::vertex_attr_array![0 => Float32x3, 1 => Float32x3, 2 => Float32x4],
}],
},
fragment: Some(wgpu::FragmentState {
module: &shader,
entry_point: Some("fs_overlay_line"),
compilation_options: Default::default(),
targets: &[color_target(Some(ALPHA_BLEND))],
}),
primitive: wgpu::PrimitiveState {
topology: wgpu::PrimitiveTopology::TriangleList,
front_face: wgpu::FrontFace::Ccw,
cull_mode: None,
..Default::default()
},
depth_stencil: Some(wgpu::DepthStencilState {
format: DEPTH_FORMAT,
depth_write_enabled: Some(false),
depth_compare: Some(wgpu::CompareFunction::LessEqual),
stencil: Default::default(),
bias: Default::default(),
}),
multisample,
multiview_mask: None,
cache: None,
});
let vc_globals_buf = device.create_buffer(&wgpu::BufferDescriptor {
label: Some("viewcube globals"),
size: std::mem::size_of::<Globals>() as u64,
usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST,
mapped_at_creation: false,
});
let vc_globals_bind = device.create_bind_group(&wgpu::BindGroupDescriptor {
label: Some("viewcube globals"),
layout: &globals_layout,
entries: &[wgpu::BindGroupEntry {
binding: 0,
resource: vc_globals_buf.as_entire_binding(),
}],
});
let styles = GlobalStyles {
face_selected: StyleBuf::new(&device, &style_layout, "face-selected"),
face_hovered: StyleBuf::new(&device, &style_layout, "face-hovered"),
edge_base: StyleBuf::new(&device, &style_layout, "edge-base"),
edge_selected: StyleBuf::new(&device, &style_layout, "edge-selected"),
edge_hovered: StyleBuf::new(&device, &style_layout, "edge-hovered"),
edge_hidden: StyleBuf::new(&device, &style_layout, "edge-hidden"),
boundary: StyleBuf::new(&device, &style_layout, "boundary"),
point_base: StyleBuf::new(&device, &style_layout, "point-base"),
point_selected: StyleBuf::new(&device, &style_layout, "point-selected"),
point_hovered: StyleBuf::new(&device, &style_layout, "point-hovered"),
axis_x: StyleBuf::new(&device, &style_layout, "axis-x"),
axis_y: StyleBuf::new(&device, &style_layout, "axis-y"),
axis_z: StyleBuf::new(&device, &style_layout, "axis-z"),
overlay_line: StyleBuf::new(&device, &style_layout, "overlay-line"),
};
Self {
device,
queue,
format,
globals_buf,
globals_bind,
style_layout,
mesh_pipeline,
wire_pipeline,
edge_visible_pipeline,
edge_hidden_pipeline,
point_pipeline,
overlay_tri_pipeline,
overlay_line_pipeline,
vc_globals_buf,
vc_globals_bind,
styles,
targets: None,
}
}
}