Skip to main content

pfx_materials/
kinds.rs

1use crate::material::{NoiseKind, NoiseLayer, PARAMS};
2
3#[derive(Clone, Copy, Debug, PartialEq, Default)]
4pub struct Fibre {
5    pub across: f32,
6    pub along: f32,
7    pub fine: f32,
8    pub mottle: f32,
9    pub ripple: f32,
10    pub swell: f32,
11    pub fibre_gain: f32,
12    pub mottle_gain: f32,
13    pub ripple_gain: f32,
14    pub swell_gain: f32,
15}
16
17impl Fibre {
18    pub const SAMPLE: Self = Self {
19        across: 2400.0,
20        along: 800.0,
21        fine: 6000.0,
22        mottle: 120.0,
23        ripple: 4800.0,
24        swell: 80.0,
25        fibre_gain: 0.06,
26        mottle_gain: 0.04,
27        ripple_gain: 0.07,
28        swell_gain: 0.01,
29    };
30
31    pub fn layer(self, amplitude: f32, seed: u32) -> NoiseLayer {
32        layer(NoiseKind::Fibre, self.params(), amplitude, seed)
33    }
34
35    pub fn params(self) -> [f32; PARAMS] {
36        fill(&[
37            self.across,
38            self.along,
39            self.fine,
40            self.mottle,
41            self.ripple,
42            self.swell,
43            self.fibre_gain,
44            self.mottle_gain,
45            self.ripple_gain,
46            self.swell_gain,
47        ])
48    }
49
50    pub fn from_params(p: &[f32; PARAMS]) -> Self {
51        Self {
52            across: p[0],
53            along: p[1],
54            fine: p[2],
55            mottle: p[3],
56            ripple: p[4],
57            swell: p[5],
58            fibre_gain: p[6],
59            mottle_gain: p[7],
60            ripple_gain: p[8],
61            swell_gain: p[9],
62        }
63    }
64}
65
66#[derive(Clone, Copy, Debug, PartialEq, Default)]
67pub struct Crinkle {
68    pub frequencies: [f32; 2],
69    pub gains: [f32; 2],
70}
71
72impl Crinkle {
73    pub const SAMPLE: Self = Self {
74        frequencies: [300.0, 650.0],
75        gains: [0.15, 0.06],
76    };
77
78    pub fn layer(self, amplitude: f32, seed: u32) -> NoiseLayer {
79        layer(NoiseKind::Crinkle, self.params(), amplitude, seed)
80    }
81
82    pub fn params(self) -> [f32; PARAMS] {
83        fill(&[
84            self.frequencies[0],
85            self.frequencies[1],
86            self.gains[0],
87            self.gains[1],
88        ])
89    }
90
91    pub fn from_params(p: &[f32; PARAMS]) -> Self {
92        Self {
93            frequencies: [p[0], p[1]],
94            gains: [p[2], p[3]],
95        }
96    }
97}
98
99#[derive(Clone, Copy, Debug, PartialEq, Default)]
100pub struct PlankWood {
101    pub width: f32,
102    pub rings: f32,
103    pub warp: f32,
104    pub figure: [f32; 2],
105    pub tone: f32,
106    pub figure_depth: f32,
107    pub seam_floor: f32,
108    pub roughness: f32,
109    pub jitter: f32,
110}
111
112impl PlankWood {
113    pub const SAMPLE: Self = Self {
114        width: 0.15,
115        rings: 60.0,
116        warp: 0.03,
117        figure: [80.0, 600.0],
118        tone: 0.3,
119        figure_depth: 0.4,
120        seam_floor: 0.4,
121        roughness: 0.45,
122        jitter: 2.5,
123    };
124
125    pub fn layer(self, amplitude: f32, seed: u32) -> NoiseLayer {
126        layer(NoiseKind::PlankWood, self.params(), amplitude, seed)
127    }
128
129    pub fn params(self) -> [f32; PARAMS] {
130        fill(&[
131            self.width,
132            self.rings,
133            self.warp,
134            self.figure[0],
135            self.figure[1],
136            self.tone,
137            self.figure_depth,
138            self.seam_floor,
139            self.roughness,
140            self.jitter,
141        ])
142    }
143
144    pub fn from_params(p: &[f32; PARAMS]) -> Self {
145        Self {
146            width: p[0],
147            rings: p[1],
148            warp: p[2],
149            figure: [p[3], p[4]],
150            tone: p[5],
151            figure_depth: p[6],
152            seam_floor: p[7],
153            roughness: p[8],
154            jitter: p[9],
155        }
156    }
157}
158
159#[derive(Clone, Copy, Debug, PartialEq, Default)]
160pub struct WallMottle {
161    pub broad: [f32; 2],
162    pub fine: [f32; 2],
163    pub swell: [f32; 2],
164    pub broad_gain: f32,
165    pub fine_gain: f32,
166    pub swell_gains: [f32; 2],
167}
168
169impl WallMottle {
170    pub const SAMPLE: Self = Self {
171        broad: [2.5, 7.0],
172        fine: [400.0, 1400.0],
173        swell: [250.0, 36.0],
174        broad_gain: 0.12,
175        fine_gain: 0.05,
176        swell_gains: [0.016, 0.006],
177    };
178
179    pub fn layer(self, amplitude: f32, seed: u32) -> NoiseLayer {
180        layer(NoiseKind::WallMottle, self.params(), amplitude, seed)
181    }
182
183    pub fn params(self) -> [f32; PARAMS] {
184        fill(&[
185            self.broad[0],
186            self.broad[1],
187            self.fine[0],
188            self.fine[1],
189            self.swell[0],
190            self.swell[1],
191            self.broad_gain,
192            self.fine_gain,
193            self.swell_gains[0],
194            self.swell_gains[1],
195        ])
196    }
197
198    pub fn from_params(p: &[f32; PARAMS]) -> Self {
199        Self {
200            broad: [p[0], p[1]],
201            fine: [p[2], p[3]],
202            swell: [p[4], p[5]],
203            broad_gain: p[6],
204            fine_gain: p[7],
205            swell_gains: [p[8], p[9]],
206        }
207    }
208}
209
210#[derive(Clone, Copy, Debug, PartialEq, Default)]
211pub struct Grime {
212    pub frequencies: [f32; 2],
213    pub dirty: [f32; 3],
214    pub clean: [f32; 3],
215    pub roughness: [f32; 2],
216}
217
218impl Grime {
219    pub const SAMPLE: Self = Self {
220        frequencies: [160.0, 800.0],
221        dirty: [0.9, 0.84, 0.76],
222        clean: [1.03, 1.02, 1.0],
223        roughness: [1.2, 0.65],
224    };
225
226    pub fn layer(self, amplitude: f32, seed: u32) -> NoiseLayer {
227        layer(NoiseKind::Grime, self.params(), amplitude, seed)
228    }
229
230    pub fn params(self) -> [f32; PARAMS] {
231        fill(&[
232            self.frequencies[0],
233            self.frequencies[1],
234            self.dirty[0],
235            self.dirty[1],
236            self.dirty[2],
237            self.clean[0],
238            self.clean[1],
239            self.clean[2],
240            self.roughness[0],
241            self.roughness[1],
242        ])
243    }
244
245    pub fn from_params(p: &[f32; PARAMS]) -> Self {
246        Self {
247            frequencies: [p[0], p[1]],
248            dirty: [p[2], p[3], p[4]],
249            clean: [p[5], p[6], p[7]],
250            roughness: [p[8], p[9]],
251        }
252    }
253}
254
255#[derive(Clone, Copy, Debug, PartialEq, Default)]
256pub struct Scratch {
257    pub line: f32,
258    pub smudge: [f32; 2],
259    pub speck: f32,
260}
261
262impl Scratch {
263    pub const SAMPLE: Self = Self {
264        line: 800.0,
265        smudge: [20.0, 55.0],
266        speck: 2400.0,
267    };
268
269    pub fn layer(self, amplitude: f32, seed: u32) -> NoiseLayer {
270        layer(NoiseKind::Scratch, self.params(), amplitude, seed)
271    }
272
273    pub fn params(self) -> [f32; PARAMS] {
274        fill(&[self.line, self.smudge[0], self.smudge[1], self.speck])
275    }
276
277    pub fn from_params(p: &[f32; PARAMS]) -> Self {
278        Self {
279            line: p[0],
280            smudge: [p[1], p[2]],
281            speck: p[3],
282        }
283    }
284}
285
286#[derive(Clone, Copy, Debug, PartialEq, Default)]
287pub struct CoatWobble {
288    pub frequencies: [f32; 3],
289    pub weights: [f32; 2],
290}
291
292impl CoatWobble {
293    pub const SAMPLE: Self = Self {
294        frequencies: [800.0, 48.0, 20.0],
295        weights: [0.5, 1.0],
296    };
297
298    pub fn layer(self, amplitude: f32, seed: u32) -> NoiseLayer {
299        layer(NoiseKind::CoatWobble, self.params(), amplitude, seed)
300    }
301
302    pub fn params(self) -> [f32; PARAMS] {
303        fill(&[
304            self.frequencies[0],
305            self.frequencies[1],
306            self.frequencies[2],
307            self.weights[0],
308            self.weights[1],
309        ])
310    }
311
312    pub fn from_params(p: &[f32; PARAMS]) -> Self {
313        Self {
314            frequencies: [p[0], p[1], p[2]],
315            weights: [p[3], p[4]],
316        }
317    }
318}
319
320fn layer(kind: NoiseKind, params: [f32; PARAMS], amplitude: f32, seed: u32) -> NoiseLayer {
321    NoiseLayer::new(kind, 1.0, amplitude, seed).with_params(params)
322}
323
324fn fill(values: &[f32]) -> [f32; PARAMS] {
325    let mut out = [0.0; PARAMS];
326    out[..values.len()].copy_from_slice(values);
327    out
328}
329
330#[cfg(test)]
331mod tests {
332    use super::*;
333
334    fn counted(values: usize) -> [f32; PARAMS] {
335        std::array::from_fn(|k| if k < values { k as f32 + 1.5 } else { 0.0 })
336    }
337
338    #[test]
339    fn every_kind_reads_back_the_params_it_writes() {
340        assert_eq!(Fibre::from_params(&counted(10)).params(), counted(10));
341        assert_eq!(Crinkle::from_params(&counted(4)).params(), counted(4));
342        assert_eq!(PlankWood::from_params(&counted(10)).params(), counted(10));
343        assert_eq!(WallMottle::from_params(&counted(10)).params(), counted(10));
344        assert_eq!(Grime::from_params(&counted(10)).params(), counted(10));
345        assert_eq!(Scratch::from_params(&counted(4)).params(), counted(4));
346        assert_eq!(CoatWobble::from_params(&counted(5)).params(), counted(5));
347    }
348
349    #[test]
350    fn a_kind_builds_its_own_layer() {
351        let coat = CoatWobble {
352            frequencies: [400.0, 30.0, 8.0],
353            weights: [0.5, 0.25],
354        };
355        let layer = coat.layer(0.02, 4);
356        assert_eq!(layer.kind, NoiseKind::CoatWobble);
357        assert_eq!(layer.amplitude, 0.02);
358        assert_eq!(layer.seed, 4);
359        assert_eq!(CoatWobble::from_params(&layer.params), coat);
360        assert!(!PlankWood::default().layer(1.0, 0).active());
361        let wood = PlankWood {
362            width: 0.2,
363            ..PlankWood::default()
364        };
365        assert!(wood.layer(1.0, 0).active());
366    }
367}