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
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
//! Texture related options.

use derive_builder::Builder;
pub use image::ImageFormat;
pub use vulkano::sampler::BorderColor;
use vulkano::sampler::{
    Filter as vkFilter, SamplerAddressMode, SamplerCreateInfo, SamplerMipmapMode,
};

/// Formats for the texture from raw data.
#[derive(Clone, Copy, Debug)]
pub enum Format {
    /// 8 bits red
    R8,
    /// 8 bits red green blue alpha
    RGBA8,
    /// 16 bits red green blue alpha
    RGBA16,
}

/// Filtering mode
#[derive(Clone, Copy, Debug)]
pub enum Filter {
    Nearest,
    Linear,
}

/// Handling of pixels outside the position range of the texture.
#[derive(Clone, Copy, Debug)]
pub enum AddressMode {
    /// Repeats the texture.
    Repeat,
    /// Repeats the texture mirrored.
    Mirrored,
    /// Coordinates outside 0 - 1 are clamped to 0 - 1.
    ClampToEdge,
    /// Coordinates outside 0 - 1 are colored to the border color settable in the Sampler struct.
    ClampToBorder,
}

/// The sampler of the texture that determines how the shader should handle textures.
#[derive(Debug, Builder, Clone)]
#[builder(setter(into))]
pub struct Sampler {
    /// Way to filter the texture when the texture is bigger than it's actual resolution.
    #[builder(setter(into), default = "Filter::Nearest")]
    pub mag_filter: Filter,
    /// Way to filter the texture when it's smaller than the actual texture.
    #[builder(setter(into), default = "Filter::Linear")]
    pub min_filter: Filter,
    /// How the final sampled value should be calculated from the samples of individual mipmaps.
    #[builder(setter(into), default = "Filter::Nearest")]
    pub mipmap_mode: Filter,
    /// How out of range texture coordinates should be handled.
    #[builder(setter(into), default = "[AddressMode::ClampToBorder; 3]")]
    pub address_mode: [AddressMode; 3],
    /// Color for the border when the address mode is on ClampToBorder.
    #[builder(setter(into), default = "BorderColor::FloatTransparentBlack")]
    pub border_color: BorderColor,
}

/// The main texture settings.
#[derive(Clone, Debug)]
pub struct TextureSettings {
    /// SRGB mode.
    pub srgb: bool,
    /// Image sampler
    pub sampler: Sampler,
}

impl Default for Sampler {
    fn default() -> Self {
        Self {
            mag_filter: Filter::Nearest,
            min_filter: Filter::Linear,
            mipmap_mode: Filter::Nearest,
            address_mode: [AddressMode::ClampToBorder; 3],
            border_color: BorderColor::FloatTransparentBlack,
        }
    }
}

impl Sampler {
    pub fn to_vulkano(&self) -> SamplerCreateInfo {
        SamplerCreateInfo {
            mag_filter: match self.mag_filter {
                Filter::Nearest => vkFilter::Nearest,
                Filter::Linear => vkFilter::Linear,
            },
            min_filter: match self.mag_filter {
                Filter::Nearest => vkFilter::Nearest,
                Filter::Linear => vkFilter::Linear,
            },
            mipmap_mode: match self.mag_filter {
                Filter::Nearest => SamplerMipmapMode::Nearest,
                Filter::Linear => SamplerMipmapMode::Linear,
            },
            // improvable.
            address_mode: [
                match self.address_mode[0] {
                    AddressMode::Repeat => SamplerAddressMode::Repeat,
                    AddressMode::Mirrored => SamplerAddressMode::MirroredRepeat,
                    AddressMode::ClampToEdge => SamplerAddressMode::ClampToEdge,
                    AddressMode::ClampToBorder => SamplerAddressMode::ClampToBorder,
                },
                match self.address_mode[1] {
                    AddressMode::Repeat => SamplerAddressMode::Repeat,
                    AddressMode::Mirrored => SamplerAddressMode::MirroredRepeat,
                    AddressMode::ClampToEdge => SamplerAddressMode::ClampToEdge,
                    AddressMode::ClampToBorder => SamplerAddressMode::ClampToBorder,
                },
                match self.address_mode[2] {
                    AddressMode::Repeat => SamplerAddressMode::Repeat,
                    AddressMode::Mirrored => SamplerAddressMode::MirroredRepeat,
                    AddressMode::ClampToEdge => SamplerAddressMode::ClampToEdge,
                    AddressMode::ClampToBorder => SamplerAddressMode::ClampToBorder,
                },
            ],
            border_color: self.border_color,
            ..Default::default()
        }
    }
}

impl Default for TextureSettings {
    fn default() -> Self {
        Self {
            srgb: true,
            sampler: Sampler::default(),
        }
    }
}

impl TextureSettings {
    pub fn srgb(mut self, srgb: bool) -> Self {
        self.srgb = srgb;
        self
    }
    pub fn sampler(mut self, sampler: Sampler) -> Self {
        self.sampler = sampler;
        self
    }
}