veloren_voxygen/render/pipelines/
fluid.rs

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