use crate::gpu_types::{FillInstance, StrokeInstance};
use crate::vertex::{FillVertex, StrokeVertex};
use astrelis_render::{Renderer, wgpu};
pub const FILL_SHADER: &str = include_str!("shaders/fill.wgsl");
pub const STROKE_SHADER: &str = include_str!("shaders/stroke.wgsl");
pub fn create_fill_pipeline(
renderer: &Renderer,
projection_bind_group_layout: &wgpu::BindGroupLayout,
surface_format: wgpu::TextureFormat,
depth_format: Option<wgpu::TextureFormat>,
name: &str,
) -> wgpu::RenderPipeline {
let shader = renderer.create_shader(Some(&format!("{} Fill Shader", name)), FILL_SHADER);
let layout = renderer.create_pipeline_layout(
Some(&format!("{} Fill Pipeline Layout", name)),
&[projection_bind_group_layout],
&[],
);
let depth_stencil = depth_format.map(|format| wgpu::DepthStencilState {
format,
depth_write_enabled: true,
depth_compare: wgpu::CompareFunction::GreaterEqual, stencil: wgpu::StencilState::default(),
bias: wgpu::DepthBiasState::default(),
});
renderer.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
label: Some(&format!("{} Fill Pipeline", name)),
layout: Some(&layout),
vertex: wgpu::VertexState {
module: &shader,
entry_point: Some("vs_main"),
buffers: &[FillVertex::vertex_layout(), FillInstance::vertex_layout()],
compilation_options: wgpu::PipelineCompilationOptions::default(),
},
fragment: Some(wgpu::FragmentState {
module: &shader,
entry_point: Some("fs_main"),
targets: &[Some(wgpu::ColorTargetState {
format: surface_format,
blend: Some(wgpu::BlendState::ALPHA_BLENDING),
write_mask: wgpu::ColorWrites::ALL,
})],
compilation_options: wgpu::PipelineCompilationOptions::default(),
}),
primitive: wgpu::PrimitiveState {
topology: wgpu::PrimitiveTopology::TriangleList,
strip_index_format: None,
front_face: wgpu::FrontFace::Ccw,
cull_mode: None,
polygon_mode: wgpu::PolygonMode::Fill,
unclipped_depth: false,
conservative: false,
},
depth_stencil,
multisample: wgpu::MultisampleState {
count: 1,
mask: !0,
alpha_to_coverage_enabled: false,
},
multiview: None,
cache: None,
})
}
pub fn create_stroke_pipeline(
renderer: &Renderer,
projection_bind_group_layout: &wgpu::BindGroupLayout,
surface_format: wgpu::TextureFormat,
depth_format: Option<wgpu::TextureFormat>,
name: &str,
) -> wgpu::RenderPipeline {
let shader = renderer.create_shader(Some(&format!("{} Stroke Shader", name)), STROKE_SHADER);
let layout = renderer.create_pipeline_layout(
Some(&format!("{} Stroke Pipeline Layout", name)),
&[projection_bind_group_layout],
&[],
);
let depth_stencil = depth_format.map(|format| wgpu::DepthStencilState {
format,
depth_write_enabled: true,
depth_compare: wgpu::CompareFunction::GreaterEqual, stencil: wgpu::StencilState::default(),
bias: wgpu::DepthBiasState::default(),
});
renderer.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
label: Some(&format!("{} Stroke Pipeline", name)),
layout: Some(&layout),
vertex: wgpu::VertexState {
module: &shader,
entry_point: Some("vs_main"),
buffers: &[
StrokeVertex::vertex_layout(),
StrokeInstance::vertex_layout(),
],
compilation_options: wgpu::PipelineCompilationOptions::default(),
},
fragment: Some(wgpu::FragmentState {
module: &shader,
entry_point: Some("fs_main"),
targets: &[Some(wgpu::ColorTargetState {
format: surface_format,
blend: Some(wgpu::BlendState::ALPHA_BLENDING),
write_mask: wgpu::ColorWrites::ALL,
})],
compilation_options: wgpu::PipelineCompilationOptions::default(),
}),
primitive: wgpu::PrimitiveState {
topology: wgpu::PrimitiveTopology::TriangleList,
strip_index_format: None,
front_face: wgpu::FrontFace::Ccw,
cull_mode: None,
polygon_mode: wgpu::PolygonMode::Fill,
unclipped_depth: false,
conservative: false,
},
depth_stencil,
multisample: wgpu::MultisampleState {
count: 1,
mask: !0,
alpha_to_coverage_enabled: false,
},
multiview: None,
cache: None,
})
}
pub fn create_projection_bind_group_layout(renderer: &Renderer) -> wgpu::BindGroupLayout {
renderer.create_bind_group_layout(
Some("Geometry Projection Bind Group Layout"),
&[wgpu::BindGroupLayoutEntry {
binding: 0,
visibility: wgpu::ShaderStages::VERTEX,
ty: wgpu::BindingType::Buffer {
ty: wgpu::BufferBindingType::Uniform,
has_dynamic_offset: false,
min_binding_size: None,
},
count: None,
}],
)
}