aboutsummaryrefslogtreecommitdiff
path: root/src/components.rs
blob: d22524ccaf4adde48db274566f5ade3315cb18f5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
use bevy::{
    prelude::*,
    render::{
        render_asset::RenderAssetUsages,
        render_resource::{Extent3d, TextureDimension, TextureFormat, TextureUsages}, extract_component::ExtractComponent,
    },
};

#[derive(Component, ExtractComponent, Clone)]
pub struct DitherPostProcessSettings(Handle<Image>);

impl DitherPostProcessSettings {
    pub fn new(
        level: u32,
        asset_server: &AssetServer,
    ) -> Self {
        let power = level + 1;
        let map_size: u32 = 1 << power;
        let mut buffer = Vec::<u8>::new();

        for row in 0..map_size {
            for col in 0..map_size {
                let a = row ^ col;
                // Interleave bits of `a` with bits of y coordinate in reverse order
                let mut result: u64 = 0;
                let mut bit = 0;
                let mut mask = power as i32 - 1;
                loop {
                    if bit >= 2 * power {
                        break;
                    }
                    result |= (((col >> mask) & 1) << bit) as u64;
                    bit += 1;
                    result |= (((a >> mask) & 1) << bit) as u64;
                    bit += 1;
                    mask -= 1;
                }
                let value = ((result as f32 / map_size.pow(2) as f32) * 255.0) as u8;
                buffer.push(value);
            }

        }

        let mut image = Image::new(
            Extent3d {
                width: map_size,
                height: map_size,
                depth_or_array_layers: 1,
            },
            TextureDimension::D2,
            buffer,
            TextureFormat::R8Unorm,
            RenderAssetUsages::RENDER_WORLD,
        );
        image.texture_descriptor.usage =
        TextureUsages::COPY_DST | TextureUsages::STORAGE_BINDING | TextureUsages::TEXTURE_BINDING;

        let handle = asset_server.add(image);

        Self(handle)
    }

    pub fn handle(&self) -> Handle<Image> {
        self.0.clone()
    }
}