veloren_voxygen/render/pipelines/
fluid.rs1use super::super::{
2 ExperimentalShader, GlobalsLayouts, PipelineModes, TerrainLayout, Vertex as VertexTrait,
3};
4use bytemuck::{Pod, Zeroable};
5use std::mem;
6use vek::*;
7
8#[repr(C)]
9#[derive(Copy, Clone, Debug, Zeroable, Pod)]
10pub struct Vertex {
11 pos_norm: u32,
12 vel: u32,
13}
14
15impl Vertex {
16 pub fn new(pos: Vec3<f32>, norm: Vec3<f32>, river_velocity: Vec2<f32>) -> Self {
17 let (norm_axis, norm_dir) = norm
18 .as_slice()
19 .iter()
20 .enumerate()
21 .find(|(_i, e)| **e != 0.0)
22 .unwrap_or((0, &1.0));
23 let norm_bits = ((norm_axis << 1) | usize::from(*norm_dir > 0.0)) as u32;
24
25 const EXTRA_NEG_Z: f32 = 65536.0;
26
27 Self {
28 pos_norm: 0
29 | (((pos.x as u32) & 0x003F) << 0)
30 | (((pos.y as u32) & 0x003F) << 6)
31 | ((((pos.z + EXTRA_NEG_Z).clamp(0.0, (1 << 17) as f32) as u32) & 0x1FFFF) << 12)
32 | ((norm_bits & 0x7) << 29),
33 vel: river_velocity
34 .map2(Vec2::new(0, 16), |e, off| {
35 ((e * 1000.0 + 32768.9) as u16 as u32) << off
36 })
37 .reduce_bitor(),
38 }
39 }
40
41 fn desc<'a>() -> wgpu::VertexBufferLayout<'a> {
42 const ATTRIBUTES: [wgpu::VertexAttribute; 2] = wgpu::vertex_attr_array![
43 0 => Uint32,
44 1 => Uint32,
45 ];
46 wgpu::VertexBufferLayout {
47 array_stride: Self::STRIDE,
48 step_mode: wgpu::VertexStepMode::Vertex,
49 attributes: &ATTRIBUTES,
50 }
51 }
52}
53
54impl VertexTrait for Vertex {
55 const QUADS_INDEX: Option<wgpu::IndexFormat> = Some(wgpu::IndexFormat::Uint16);
56 const STRIDE: wgpu::BufferAddress = mem::size_of::<Self>() as wgpu::BufferAddress;
57}
58
59pub struct FluidPipeline {
60 pub pipeline: wgpu::RenderPipeline,
61}
62
63impl FluidPipeline {
64 pub fn new(
65 device: &wgpu::Device,
66 vs_module: &wgpu::ShaderModule,
67 fs_module: &wgpu::ShaderModule,
68 global_layout: &GlobalsLayouts,
69 terrain_layout: &TerrainLayout,
70 format: wgpu::TextureFormat,
71 pipeline_modes: &PipelineModes,
72 ) -> Self {
73 common_base::span!(_guard, "FluidPipeline::new");
74 let render_pipeline_layout =
75 device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
76 label: Some("Fluid pipeline layout"),
77 push_constant_ranges: &[],
78 bind_group_layouts: &[
79 &global_layout.globals,
80 &global_layout.shadow_textures,
81 &terrain_layout.locals,
82 ],
83 });
84
85 let samples = pipeline_modes.aa.samples();
86
87 let render_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
88 label: Some("Fluid pipeline"),
89 layout: Some(&render_pipeline_layout),
90 vertex: wgpu::VertexState {
91 module: vs_module,
92 entry_point: Some("main"),
93 buffers: &[Vertex::desc()],
94 compilation_options: Default::default(),
95 },
96 primitive: wgpu::PrimitiveState {
97 topology: wgpu::PrimitiveTopology::TriangleList,
98 strip_index_format: None,
99 front_face: wgpu::FrontFace::Ccw,
100 cull_mode: None,
101 unclipped_depth: false,
102 polygon_mode: if pipeline_modes
103 .experimental_shaders
104 .contains(&ExperimentalShader::Wireframe)
105 {
106 wgpu::PolygonMode::Line
107 } else {
108 wgpu::PolygonMode::Fill
109 },
110 conservative: false,
111 },
112 depth_stencil: Some(wgpu::DepthStencilState {
113 format: wgpu::TextureFormat::Depth32Float,
114 depth_write_enabled: true,
115 depth_compare: wgpu::CompareFunction::GreaterEqual,
116 stencil: wgpu::StencilState {
117 front: wgpu::StencilFaceState::IGNORE,
118 back: wgpu::StencilFaceState::IGNORE,
119 read_mask: !0,
120 write_mask: 0,
121 },
122 bias: wgpu::DepthBiasState {
123 constant: 0,
124 slope_scale: 0.0,
125 clamp: 0.0,
126 },
127 }),
128 multisample: wgpu::MultisampleState {
129 count: samples,
130 mask: !0,
131 alpha_to_coverage_enabled: false,
132 },
133 fragment: Some(wgpu::FragmentState {
134 module: fs_module,
135 entry_point: Some("main"),
136 targets: &[
137 Some(wgpu::ColorTargetState {
138 format,
139 blend: Some(wgpu::BlendState {
140 color: wgpu::BlendComponent {
141 src_factor: wgpu::BlendFactor::SrcAlpha,
142 dst_factor: wgpu::BlendFactor::OneMinusSrcAlpha,
143 operation: wgpu::BlendOperation::Add,
144 },
145 alpha: wgpu::BlendComponent {
146 src_factor: wgpu::BlendFactor::One,
147 dst_factor: wgpu::BlendFactor::One,
148 operation: wgpu::BlendOperation::Min,
149 },
150 }),
151 write_mask: wgpu::ColorWrites::ALL,
152 }),
153 Some(wgpu::ColorTargetState {
154 format: wgpu::TextureFormat::Rgba8Uint,
155 blend: None,
156 write_mask: wgpu::ColorWrites::ALL,
157 }),
158 ],
159 compilation_options: Default::default(),
160 }),
161 multiview: None,
162 cache: None,
163 });
164
165 Self {
166 pipeline: render_pipeline,
167 }
168 }
169}