1use crate::material_graph::{GraphMode, MaterialGraph};
13
14pub struct Preset {
16 pub category: &'static str,
18 pub name: &'static str,
20 pub graph: MaterialGraph,
22}
23
24const BASE: usize = 0;
26const ROUGH: usize = 1;
27const METAL: usize = 2;
28const EMIT: usize = 3;
29const ALPHA: usize = 4;
30const NORMAL: usize = 6;
31
32struct B {
33 g: MaterialGraph,
34 out: u32,
35 col: [f32; 8],
36}
37
38impl B {
39 fn new() -> Self {
40 let mut g = MaterialGraph { nodes: Vec::new(), textures: Default::default(), next_id: 1, mode: GraphMode::Material };
41 let out = g.add_node("Output", [1100.0, 120.0]);
42 B { g, out, col: [0.0; 8] }
43 }
44
45 fn node(&mut self, kind: &str, column: usize) -> u32 {
47 let y = self.col[column.min(7)];
48 self.col[column.min(7)] += 190.0;
49 self.g.add_node(kind, [40.0 + column as f32 * 250.0, 30.0 + y])
50 }
51
52 fn set(&mut self, id: u32, params: &[f32]) -> u32 {
53 let n = self.g.nodes.iter_mut().find(|n| n.id == id).unwrap();
54 for (i, v) in params.iter().enumerate() {
55 n.params[i] = *v;
56 }
57 id
58 }
59
60 fn value(&mut self, id: u32, input: usize, v: [f32; 3]) {
61 let n = self.g.nodes.iter_mut().find(|n| n.id == id).unwrap();
62 n.inputs[input].value = v;
63 n.inputs[input].override_default = true;
64 }
65
66 fn link(&mut self, from: u32, to: u32, input: usize) {
67 assert!(self.g.connect(from, to, input), "link {from} -> {to}.{input}");
68 }
69
70 fn out(&mut self, from: u32, input: usize) {
71 self.link(from, self.out, input);
72 }
73
74 fn out_value(&mut self, input: usize, v: f32) {
75 let out = self.out;
76 self.value(out, input, [v; 3]);
77 }
78
79 fn ramp(&mut self, source: u32, stops: [[f32; 3]; 4], pos: [f32; 4], column: usize) -> u32 {
81 let r = self.node("Color ramp", column);
82 self.set(r, &pos);
83 for (i, s) in stops.iter().enumerate() {
84 self.value(r, i + 1, *s);
85 }
86 self.link(source, r, 0);
87 r
88 }
89
90 fn map_range(&mut self, source: u32, lo: f32, hi: f32, column: usize) -> u32 {
91 let m = self.node("Map range", column);
92 self.set(m, &[0.0, 1.0, lo, hi]);
93 self.link(source, m, 0);
94 m
95 }
96
97 fn bump(&mut self, height: u32, strength: f32, column: usize) -> u32 {
98 let b = self.node("Bump from height", column);
99 self.set(b, &[strength]);
100 self.link(height, b, 0);
101 self.out(b, NORMAL);
102 b
103 }
104
105 fn fractal(&mut self, scale: f32, octaves: f32, kind: f32, column: usize) -> u32 {
106 let n = self.node("Fractal noise", column);
107 self.set(n, &[scale, octaves, 2.0, 0.5, kind]);
108 n
109 }
110}
111
112#[allow(clippy::too_many_arguments)]
114fn natural(stops: [[f32; 3]; 4], pos: [f32; 4], scale: f32, kind: f32, rough: (f32, f32), metal: f32, bump: f32) -> MaterialGraph {
115 let mut b = B::new();
116 let big = b.fractal(scale, 5.0, kind, 0);
117 let fine = b.fractal(scale * 7.0, 3.0, 0.0, 0);
118 let ramp = b.ramp(big, stops, pos, 1);
119 let detail = b.node("Blend colours", 2);
120 b.set(detail, &[1.0]);
121 b.link(ramp, detail, 0);
122 let grain = b.map_range(fine, 0.8, 1.15, 1);
123 b.link(grain, detail, 1);
124 b.out(detail, BASE);
125 let r = b.map_range(big, rough.0, rough.1, 2);
126 b.out(r, ROUGH);
127 b.out_value(METAL, metal);
128 b.bump(big, bump * 0.5, 3);
130 b.g
131}
132
133fn metal_brushed(color: [f32; 3], dark: [f32; 3], rough: f32, scratch: f32) -> MaterialGraph {
134 let mut b = B::new();
135 let s = b.node("Scratches", 0);
136 b.set(s, &[scratch, 0.0]);
137 let n = b.fractal(3.0, 4.0, 0.0, 0);
138 let mix = b.node("Mix", 1);
139 b.value(mix, 0, color);
140 b.value(mix, 1, dark);
141 let soft = b.map_range(s, 0.0, 0.45, 1);
142 b.link(soft, mix, 2);
143 b.out(mix, BASE);
144 let r = b.map_range(n, rough * 0.7, rough * 1.3, 1);
145 b.out(r, ROUGH);
146 b.out_value(METAL, 1.0);
147 b.g
148}
149
150fn emissive(name_ramp: [[f32; 3]; 4], pos: [f32; 4], scale: f32, kind: f32, intensity: f32, base: [f32; 3], rough: f32) -> MaterialGraph {
151 let mut b = B::new();
152 let n = b.fractal(scale, 5.0, kind, 0);
153 let ramp = b.ramp(n, name_ramp, pos, 1);
154 let glow = b.node("Multiply", 2);
155 b.link(ramp, glow, 0);
156 b.value(glow, 1, [intensity; 3]);
157 b.out(glow, EMIT);
158 let dark = b.node("Mix", 2);
159 b.value(dark, 0, base);
160 b.value(dark, 1, [0.01; 3]);
161 b.link(n, dark, 2);
162 b.out(dark, BASE);
163 b.out_value(ROUGH, rough);
164 b.bump(n, 1.5, 3);
165 b.g
166}
167
168fn tiles(color_a: [f32; 3], color_b: [f32; 3], count: f32, gap: f32, rough: f32, metal: f32) -> MaterialGraph {
169 let mut b = B::new();
170 let grid = b.node("Grid lines", 0);
171 b.set(grid, &[count, gap]);
172 let checker = b.node("Checker", 0);
173 b.set(checker, &[count]);
174 let mix = b.node("Mix", 1);
175 b.value(mix, 0, color_a);
176 b.value(mix, 1, color_b);
177 b.link(checker, mix, 2);
178 let grout = b.node("Mix", 2);
179 b.link(mix, grout, 0);
180 b.value(grout, 1, [0.08, 0.08, 0.08]);
181 b.link(grid, grout, 2);
182 b.out(grout, BASE);
183 b.out_value(ROUGH, rough);
184 b.out_value(METAL, metal);
185 let inv = b.node("One minus", 1);
186 b.link(grid, inv, 0);
187 b.bump(inv, 2.0, 2);
188 b.g
189}
190
191fn wood(light: [f32; 3], dark: [f32; 3], planks: bool) -> MaterialGraph {
192 let mut b = B::new();
193 let rings = b.node("Wood rings", 0);
194 b.set(rings, &[4.0, 0.35]);
195 let fine = b.fractal(40.0, 3.0, 0.0, 0);
196 let grain = b.node("Blend colours", 1);
197 b.set(grain, &[1.0]);
198 b.link(rings, grain, 0);
199 b.link(fine, grain, 1);
200 let ramp = b.ramp(grain, [dark, [dark[0] * 1.5, dark[1] * 1.4, dark[2] * 1.3], light, [light[0] * 1.1, light[1] * 1.1, light[2] * 1.05]], [0.0, 0.35, 0.7, 1.0], 2);
201 if planks {
202 let pl = b.node("Planks", 0);
203 b.set(pl, &[6.0, 3.0, 0.02]);
204 let shade = b.node("Multiply", 3);
205 b.link(ramp, shade, 0);
206 b.link(pl, shade, 1);
207 b.out(shade, BASE);
208 b.bump(pl, 1.0, 3);
209 } else {
210 b.out(ramp, BASE);
211 b.bump(fine, 0.6, 3);
212 }
213 b.out_value(ROUGH, 0.55);
214 b.g
215}
216
217fn marble(base: [f32; 3], vein: [f32; 3], warp: f32) -> MaterialGraph {
219 crate::material_presets_v4::marble(base, vein, warp * 0.75, 1.6)
220}
221
222fn bricks(brick: [f32; 3], mortar: [f32; 3]) -> MaterialGraph {
223 let mut b = B::new();
224 let br = b.node("Bricks", 0);
225 b.set(br, &[6.0, 0.05]);
226 let n = b.fractal(12.0, 4.0, 0.0, 0);
227 let cells = b.node("Voronoi cells", 0);
228 b.set(cells, &[8.0, 1.0, 2.0]);
229 let tone = b.ramp(cells, [[brick[0] * 0.6, brick[1] * 0.6, brick[2] * 0.6], brick, [brick[0] * 1.25, brick[1] * 1.15, brick[2] * 1.1], brick], [0.0, 0.4, 0.8, 1.0], 1);
230 let mix = b.node("Mix", 2);
231 b.value(mix, 0, mortar);
232 b.link(tone, mix, 1);
233 b.link(br, mix, 2);
234 let dirt = b.node("Blend colours", 3);
235 b.set(dirt, &[1.0]);
236 b.link(mix, dirt, 0);
237 let grime = b.map_range(n, 0.7, 1.1, 1);
238 b.link(grime, dirt, 1);
239 b.out(dirt, BASE);
240 b.out_value(ROUGH, 0.85);
241 b.bump(br, 3.0, 2);
242 b.g
243}
244
245fn weave(a: [f32; 3], bcol: [f32; 3], threads: f32, metal: f32, rough: f32) -> MaterialGraph {
246 let mut b = B::new();
247 let w = b.node("Weave", 0);
248 b.set(w, &[threads]);
249 let mix = b.node("Mix", 1);
250 b.value(mix, 0, a);
251 b.value(mix, 1, bcol);
252 b.link(w, mix, 2);
253 let shade = b.node("Multiply", 2);
254 b.link(mix, shade, 0);
255 b.link(w, shade, 1);
256 b.out(shade, BASE);
257 b.out_value(ROUGH, rough);
258 b.out_value(METAL, metal);
259 b.bump(w, 2.5, 1);
260 b.g
261}
262
263fn hex_metal(base: [f32; 3], edge: [f32; 3], scale: f32) -> MaterialGraph {
264 let mut b = B::new();
265 let h = b.node("Hexagons", 0);
266 b.set(h, &[scale, 0.08]);
267 let mix = b.node("Mix", 1);
268 b.value(mix, 0, edge);
269 b.value(mix, 1, base);
270 b.link(h, mix, 2);
271 b.out(mix, BASE);
272 b.out_value(ROUGH, 0.35);
273 b.out_value(METAL, 1.0);
274 b.bump(h, 2.0, 1);
275 b.g
276}
277
278fn cracked(base: [f32; 3], crack: [f32; 3], scale: f32, rough: f32) -> MaterialGraph {
279 let mut b = B::new();
280 let c = b.node("Cracks", 0);
281 b.set(c, &[scale, 0.07]);
282 let n = b.fractal(6.0, 5.0, 0.0, 0);
283 let mix = b.node("Mix", 1);
284 b.value(mix, 0, base);
285 b.value(mix, 1, crack);
286 b.link(c, mix, 2);
287 let shade = b.node("Blend colours", 2);
288 b.set(shade, &[1.0]);
289 b.link(mix, shade, 0);
290 let m = b.map_range(n, 0.75, 1.1, 1);
291 b.link(m, shade, 1);
292 b.out(shade, BASE);
293 b.out_value(ROUGH, rough);
294 let inv = b.node("One minus", 1);
295 b.link(c, inv, 0);
296 b.bump(inv, 2.5, 2);
297 b.g
298}
299
300fn neon_grid(line: [f32; 3], intensity: f32) -> MaterialGraph {
301 let mut b = B::new();
302 let g = b.node("Grid lines", 0);
303 b.set(g, &[10.0, 0.03]);
304 let glow = b.node("Multiply", 1);
305 b.value(glow, 0, line);
306 b.link(g, glow, 1);
307 let boost = b.node("Multiply", 2);
308 b.link(glow, boost, 0);
309 b.value(boost, 1, [intensity; 3]);
310 let pulse = b.node("Pulse", 0);
311 b.set(pulse, &[0.5]);
312 let mixed = b.node("Mix", 3);
313 b.link(boost, mixed, 1);
314 b.value(mixed, 0, [0.0; 3]);
315 b.link(pulse, mixed, 2);
316 b.out(boost, EMIT);
317 b.value(b.out, BASE, [0.02, 0.02, 0.03]);
318 b.out_value(ROUGH, 0.3);
319 b.g
320}
321
322fn glass(tint: [f32; 3], alpha: f32, rough: f32) -> MaterialGraph {
323 let mut b = B::new();
324 let f = b.node("Fresnel", 0);
325 b.value(f, 0, [3.0; 3]);
326 let a = b.map_range(f, alpha, 1.0, 1);
327 b.out(a, ALPHA);
328 b.value(b.out, BASE, tint);
329 b.out_value(ROUGH, rough);
330 b.out_value(METAL, 0.0);
331 b.g
332}
333
334fn plain(color: [f32; 3], rough: f32, metal: f32) -> MaterialGraph {
335 let mut b = B::new();
336 b.value(b.out, BASE, color);
337 b.out_value(ROUGH, rough);
338 b.out_value(METAL, metal);
339 b.g
340}
341
342fn stylized(stops: [[f32; 3]; 4], scale: f32, steps: f32, kind: f32) -> MaterialGraph {
344 let mut b = B::new();
345 let n = b.fractal(scale, 4.0, kind, 0);
346 let post = b.node("Posterize", 1);
347 b.set(post, &[steps]);
348 b.link(n, post, 0);
349 let ramp = b.ramp(post, stops, [0.0, 0.34, 0.67, 1.0], 2);
350 b.out(ramp, BASE);
351 b.out_value(ROUGH, 0.85);
352 b.g
353}
354
355fn pattern(kind: &str, params: &[f32], a: [f32; 3], bcol: [f32; 3], rough: f32) -> MaterialGraph {
357 let mut b = B::new();
358 let pat = b.node(kind, 0);
359 b.set(pat, params);
360 let mix = b.node("Mix", 1);
361 b.value(mix, 0, a);
362 b.value(mix, 1, bcol);
363 b.link(pat, mix, 2);
364 b.out(mix, BASE);
365 b.out_value(ROUGH, rough);
366 b.g
367}
368
369fn gradient(kind: &str, stops: [[f32; 3]; 4], emission: f32) -> MaterialGraph {
371 let mut b = B::new();
372 let g = b.node(kind, 0);
373 let ramp = b.ramp(g, stops, [0.0, 0.34, 0.67, 1.0], 1);
374 if emission > 0.0 {
375 let glow = b.node("Multiply", 2);
376 b.link(ramp, glow, 0);
377 b.value(glow, 1, [emission; 3]);
378 b.out(glow, EMIT);
379 b.value(b.out, BASE, [0.02; 3]);
380 } else {
381 b.out(ramp, BASE);
382 }
383 b.out_value(ROUGH, 0.7);
384 b.g
385}
386
387fn rainbow(from_view: bool, scale: f32) -> MaterialGraph {
389 let mut b = B::new();
390 let src = if from_view {
391 let f = b.node("Fresnel", 0);
392 b.value(f, 0, [1.5; 3]);
393 f
394 } else {
395 let w = b.node("Warped noise", 0);
396 b.set(w, &[scale, 2.5]);
397 w
398 };
399 let hsv = b.node("HSV to RGB", 1);
400 b.link(src, hsv, 0);
401 b.value(hsv, 1, [0.75; 3]);
402 b.value(hsv, 2, [1.0; 3]);
403 b.out(hsv, BASE);
404 if from_view {
405 let glow = b.node("Multiply", 2);
406 b.link(hsv, glow, 0);
407 b.value(glow, 1, [0.6; 3]);
408 b.out(glow, EMIT);
409 b.out_value(METAL, 0.8);
410 b.out_value(ROUGH, 0.2);
411 } else {
412 b.out_value(ROUGH, 0.8);
413 }
414 b.g
415}
416
417fn galaxy(a: [f32; 3], bcol: [f32; 3]) -> MaterialGraph {
419 let mut b = B::new();
420 let n = b.node("Clouds", 0);
421 b.set(n, &[2.0, 0.3, 0.6]);
422 let ramp = b.ramp(n, [[0.01, 0.01, 0.05], a, bcol, [1.0, 0.9, 1.0]], [0.0, 0.4, 0.75, 1.0], 1);
423 let stars = b.node("Sparkle", 0);
424 b.set(stars, &[90.0, 0.04]);
425 let sum = b.node("Add", 2);
426 b.link(ramp, sum, 0);
427 b.link(stars, sum, 1);
428 b.out(sum, EMIT);
429 b.value(b.out, BASE, [0.0; 3]);
430 b.g
431}
432
433fn water(deep: [f32; 3], shallow: [f32; 3], speed: f32, scale: f32, stylized: bool, alpha: f32) -> MaterialGraph {
436 let mut b = B::new();
437 let uv = b.node("UV", 0);
438 let s1 = b.node("Scroll coords", 1);
439 b.set(s1, &[speed, speed * 0.4]);
440 b.link(uv, s1, 0);
441 let s2 = b.node("Scroll coords", 1);
442 b.set(s2, &[-speed * 0.7, speed * 0.9]);
443 b.link(uv, s2, 0);
444 let n1 = b.fractal(scale, 4.0, 0.0, 2);
445 let n2 = b.fractal(scale * 2.3, 3.0, 2.0, 2);
446 b.link(s1, n1, 0);
447 b.link(s2, n2, 0);
448 let waves = b.node("Average", 3);
449 b.link(n1, waves, 0);
450 b.link(n2, waves, 1);
451 let source = if stylized {
452 let post = b.node("Posterize", 3);
453 b.set(post, &[4.0]);
454 b.link(waves, post, 0);
455 post
456 } else {
457 waves
458 };
459 let mid = [(deep[0] + shallow[0]) * 0.5, (deep[1] + shallow[1]) * 0.5, (deep[2] + shallow[2]) * 0.5];
460 let ramp = b.ramp(source, [deep, mid, shallow, [shallow[0] * 1.2 + 0.1, shallow[1] * 1.2 + 0.1, shallow[2] * 1.2 + 0.1]], [0.15, 0.45, 0.7, 0.95], 4);
461 if stylized {
462 let foam = b.node("Greater than", 4);
464 b.link(waves, foam, 0);
465 b.value(foam, 1, [0.78; 3]);
466 let mixed = b.node("Mix", 5);
467 b.link(ramp, mixed, 0);
468 b.value(mixed, 1, [1.0; 3]);
469 b.link(foam, mixed, 2);
470 b.out(mixed, BASE);
471 b.out_value(ROUGH, 0.35);
472 } else {
473 b.out(ramp, BASE);
474 b.out_value(ROUGH, 0.04);
475 b.bump(waves, 2.5, 5);
476 let caustics = b.node("Caustics", 4);
478 let glow = b.node("Multiply", 5);
479 b.link(caustics, glow, 0);
480 b.value(glow, 1, [0.12; 3]);
481 b.out(glow, EMIT);
482 }
483 let fres = b.node("Fresnel", 4);
484 b.value(fres, 0, [3.0; 3]);
485 let a = b.map_range(fres, alpha, 1.0, 5);
486 b.out(a, ALPHA);
487 b.g
488}
489
490fn deep_layers(pal: [[f32; 3]; 3], speed: f32, stars: f32, scales: [f32; 3]) -> MaterialGraph {
493 let mut b = B::new();
494 let uv = b.node("UV", 0);
495 let view = b.node("View direction", 0);
496 let mut sum: Option<u32> = None;
497 for (i, (depth, scale)) in [(0.0f32, scales[0]), (0.18, scales[1]), (0.45, scales[2])].into_iter().enumerate() {
498 let off = b.node("Multiply", 1);
499 b.link(view, off, 0);
500 b.value(off, 1, [depth; 3]);
501 let shifted = b.node("Add", 1);
502 b.link(uv, shifted, 0);
503 b.link(off, shifted, 1);
504 let scroll = b.node("Scroll coords", 2);
505 b.set(scroll, &[speed * (i as f32 + 1.0) * 0.02, speed * 0.01]);
506 b.link(shifted, scroll, 0);
507 let noise = b.fractal(scale, 4.0, if i == 1 { 1.0 } else { 0.0 }, 3);
508 b.link(scroll, noise, 0);
509 let ramp = b.ramp(noise, [[0.0; 3], tint(pal[i % 3], [0.5; 3]), tint(pal[(i + 1) % 3], [0.8; 3]), [0.75, 0.72, 0.8]], [0.25, 0.5, 0.75, 1.0], 4);
510 let mask = b.node("Smoothstep", 4);
511 b.set(mask, &[0.3, 0.8]);
512 b.link(noise, mask, 0);
513 let layer = b.node("Multiply", 5);
514 b.link(ramp, layer, 0);
515 b.link(mask, layer, 1);
516 sum = Some(match sum {
517 None => layer,
518 Some(prev) => {
519 let add = b.node("Add", 6);
520 b.link(prev, add, 0);
521 b.link(layer, add, 1);
522 add
523 }
524 });
525 }
526 let star_shift = b.node("Multiply", 1);
527 b.link(view, star_shift, 0);
528 b.value(star_shift, 1, [0.6; 3]);
529 let star_uv = b.node("Add", 2);
530 b.link(uv, star_uv, 0);
531 b.link(star_shift, star_uv, 1);
532 let sparkle = b.node("Sparkle", 3);
533 b.set(sparkle, &[70.0, stars]);
534 b.link(star_uv, sparkle, 0);
535 let boost = b.node("Multiply", 5);
536 b.link(sparkle, boost, 0);
537 b.value(boost, 1, [2.0; 3]);
538 let total = b.node("Add", 7);
539 b.link(sum.unwrap(), total, 0);
540 b.link(boost, total, 1);
541 b.out(total, EMIT);
542 b.value(b.out, BASE, [0.0; 3]);
543 b.out_value(ROUGH, 0.5);
544 b.g
545}
546
547fn leak(s: String) -> &'static str {
548 Box::leak(s.into_boxed_str())
549}
550
551fn tint(c: [f32; 3], t: [f32; 3]) -> [f32; 3] {
552 [c[0] * t[0], c[1] * t[1], c[2] * t[2]]
553}
554
555fn tint4(c: [[f32; 3]; 4], t: [f32; 3]) -> [[f32; 3]; 4] {
556 [tint(c[0], t), tint(c[1], t), tint(c[2], t), tint(c[3], t)]
557}
558
559fn extra(v: &mut Vec<Preset>) {
561 const TINTS: [(&str, [f32; 3]); 6] = [
562 ("Red", [1.3, 0.7, 0.65]),
563 ("Blue", [0.7, 0.85, 1.3]),
564 ("Green", [0.75, 1.15, 0.8]),
565 ("Brown", [1.15, 0.9, 0.7]),
566 ("Pink", [1.25, 0.85, 1.0]),
567 ("Dark", [0.45, 0.45, 0.48]),
568 ];
569 let stones: [(&str, [[f32; 3]; 4], f32, f32, (f32, f32), f32); 5] = [
571 ("Granite", [[0.18, 0.18, 0.19], [0.42, 0.41, 0.42], [0.62, 0.6, 0.6], [0.8, 0.78, 0.78]], 6.0, 0.0, (0.4, 0.7), 1.0),
572 ("Rock", [[0.12, 0.11, 0.1], [0.28, 0.25, 0.22], [0.45, 0.4, 0.35], [0.62, 0.57, 0.5]], 2.5, 1.0, (0.75, 1.0), 4.0),
573 ("Sandstone", [[0.5, 0.36, 0.2], [0.68, 0.5, 0.3], [0.8, 0.62, 0.4], [0.88, 0.72, 0.5]], 3.5, 2.0, (0.8, 1.0), 2.0),
574 ("Slate", [[0.06, 0.07, 0.09], [0.14, 0.16, 0.2], [0.22, 0.25, 0.3], [0.32, 0.35, 0.4]], 4.0, 1.0, (0.45, 0.8), 1.5),
575 ("Concrete", [[0.3, 0.3, 0.3], [0.42, 0.42, 0.41], [0.52, 0.52, 0.5], [0.6, 0.6, 0.58]], 5.0, 0.0, (0.85, 1.0), 0.8),
576 ];
577 for (name, stops, scale, kind, rough, bump) in stones {
578 for (tname, t) in TINTS {
579 v.push(p("Stone Variants", leak(format!("{name} {tname}")), natural(tint4(stops, t), [0.0, 0.35, 0.65, 1.0], scale, kind, rough, 0.0, bump)));
580 }
581 }
582 let metals = [("Silver", [0.8, 0.8, 0.82]), ("Steel Blue", [0.5, 0.6, 0.75]), ("Bronze", [0.8, 0.5, 0.2]), ("Brass", [0.85, 0.7, 0.3]), ("Rose Gold", [0.95, 0.62, 0.55]), ("Gunmetal", [0.25, 0.27, 0.3]),
584 ("Black Steel", [0.08, 0.08, 0.09]), ("Platinum", [0.85, 0.84, 0.82]), ("Cobalt", [0.2, 0.35, 0.65]), ("Emerald Metal", [0.1, 0.55, 0.35]), ("Ruby Metal", [0.65, 0.07, 0.1]), ("Violet Metal", [0.45, 0.25, 0.7])];
585 for (name, c) in metals {
586 v.push(p("Metal Variants", leak(format!("{name} Brushed")), metal_brushed(c, tint(c, [0.65; 3]), 0.32, 160.0)));
587 v.push(p("Metal Variants", leak(format!("{name} Polished")), plain(c, 0.08, 1.0)));
588 }
589 let woods = [("Birch", [0.85, 0.75, 0.55], [0.6, 0.48, 0.3]), ("Cherry", [0.55, 0.25, 0.15], [0.35, 0.14, 0.08]), ("Ebony", [0.12, 0.09, 0.07], [0.04, 0.03, 0.025]), ("Maple", [0.8, 0.62, 0.4], [0.58, 0.42, 0.25]),
591 ("Mahogany", [0.45, 0.2, 0.12], [0.25, 0.1, 0.06]), ("Ash", [0.75, 0.68, 0.55], [0.5, 0.42, 0.32]), ("Teak", [0.6, 0.42, 0.2], [0.38, 0.24, 0.1]), ("Bamboo", [0.8, 0.72, 0.4], [0.55, 0.5, 0.25])];
592 for (name, light, dark) in woods {
593 v.push(p("Wood Variants", leak(format!("{name}")), wood(light, dark, false)));
594 v.push(p("Wood Variants", leak(format!("{name} Planks")), wood(light, dark, true)));
595 }
596 let colours = [("Red", [0.7, 0.05, 0.05]), ("Orange", [0.9, 0.4, 0.05]), ("Yellow", [0.95, 0.8, 0.1]), ("Green", [0.1, 0.55, 0.15]), ("Teal", [0.05, 0.5, 0.5]), ("Blue", [0.08, 0.2, 0.75]),
598 ("Purple", [0.4, 0.12, 0.6]), ("Pink", [0.95, 0.4, 0.6]), ("White", [0.9, 0.9, 0.88]), ("Grey", [0.35, 0.35, 0.37]), ("Black", [0.03, 0.03, 0.035]), ("Brown", [0.3, 0.17, 0.09])];
599 for (name, c) in colours {
600 v.push(p("Fabric Variants", leak(format!("{name} Cloth")), weave(c, tint(c, [0.8; 3]), 44.0, 0.0, 0.9)));
601 v.push(p("Tile Variants", leak(format!("{name} Tiles")), tiles(c, tint(c, [0.7; 3]), 10.0, 0.04, 0.25, 0.0)));
602 v.push(p("Plastic", leak(format!("{name} Gloss")), plain(c, 0.18, 0.0)));
603 v.push(p("Plastic", leak(format!("{name} Matte")), plain(c, 0.75, 0.0)));
604 }
605 for (name, c) in [("Red", [0.7, 0.2, 0.15]), ("Brown", [0.5, 0.3, 0.2]), ("Grey", [0.5, 0.5, 0.5]), ("Yellow", [0.75, 0.6, 0.3]), ("Dark", [0.25, 0.2, 0.2]), ("White", [0.8, 0.78, 0.74])] {
606 v.push(p("Building Variants", leak(format!("{name} Bricks")), bricks(c, [0.55, 0.53, 0.5])));
607 }
608 for (name, tintc, alpha) in [("Blue", [0.55, 0.75, 1.0], 0.2), ("Green", [0.4, 0.9, 0.55], 0.25), ("Amber", [1.0, 0.7, 0.25], 0.3), ("Red", [1.0, 0.3, 0.3], 0.3), ("Smoke", [0.3, 0.3, 0.32], 0.5), ("Frosted", [0.9, 0.95, 1.0], 0.6), ("Purple", [0.6, 0.3, 0.9], 0.3), ("Pink", [1.0, 0.6, 0.8], 0.3)] {
609 v.push(p("Glass", leak(format!("{name} Glass")), glass(tintc, alpha, if name == "Frosted" { 0.5 } else { 0.04 })));
610 }
611 let waters: [(&str, [f32; 3], [f32; 3], f32, f32, f32); 10] = [
613 ("Ocean", [0.0, 0.1, 0.28], [0.1, 0.5, 0.65], 0.03, 2.0, 0.55), ("Lake", [0.02, 0.16, 0.22], [0.15, 0.55, 0.55], 0.015, 2.5, 0.5), ("Pool", [0.1, 0.55, 0.8], [0.5, 0.95, 1.0], 0.02, 4.0, 0.25),
614 ("Tropical", [0.0, 0.45, 0.55], [0.3, 1.0, 0.85], 0.03, 3.0, 0.35), ("Swamp", [0.05, 0.12, 0.04], [0.25, 0.4, 0.15], 0.008, 3.0, 0.85), ("River", [0.05, 0.2, 0.25], [0.35, 0.6, 0.6], 0.06, 3.5, 0.5),
615 ("Toxic", [0.1, 0.3, 0.0], [0.6, 1.0, 0.1], 0.025, 2.5, 0.7), ("Ink", [0.0, 0.0, 0.04], [0.12, 0.12, 0.3], 0.02, 2.0, 0.9), ("Milk", [0.85, 0.85, 0.8], [1.0, 1.0, 0.95], 0.01, 2.0, 0.9), ("Lava River", [0.35, 0.03, 0.0], [1.0, 0.55, 0.05], 0.02, 2.0, 1.0),
616 ];
617 for (name, deep, shallow, speed, scale, alpha) in waters {
618 v.push(p("Water", leak(format!("{name} Realistic")), water(deep, shallow, speed, scale, false, alpha)));
619 v.push(p("Water", leak(format!("{name} Stylized")), water(deep, shallow, speed * 1.5, scale * 0.7, true, alpha.max(0.7))));
620 }
621 let cosmos: [(&str, [[f32; 3]; 3], f32, f32); 16] = [
623 ("Galaxy Purple", [[0.3, 0.1, 0.7], [0.8, 0.3, 0.8], [0.2, 0.4, 1.0]], 1.0, 0.02), ("Nebula Teal", [[0.05, 0.4, 0.6], [0.2, 0.8, 0.7], [0.6, 0.3, 0.9]], 1.0, 0.025), ("Deep Space", [[0.02, 0.03, 0.15], [0.1, 0.1, 0.4], [0.3, 0.2, 0.6]], 0.5, 0.04),
624 ("Crimson Nebula", [[0.5, 0.05, 0.1], [1.0, 0.3, 0.2], [1.0, 0.7, 0.4]], 1.0, 0.02), ("Aurora", [[0.1, 0.8, 0.4], [0.2, 0.5, 0.9], [0.6, 0.2, 0.8]], 1.5, 0.015), ("Wormhole", [[0.0, 0.2, 0.6], [0.5, 0.8, 1.0], [1.0, 1.0, 1.0]], 2.0, 0.03),
625 ("Energy Core", [[1.0, 0.4, 0.0], [1.0, 0.8, 0.2], [1.0, 1.0, 0.8]], 3.0, 0.0), ("Crystal Depth", [[0.2, 0.7, 0.9], [0.5, 0.9, 1.0], [0.9, 0.5, 1.0]], 0.6, 0.01), ("Abyss", [[0.0, 0.1, 0.2], [0.0, 0.3, 0.4], [0.2, 0.6, 0.6]], 0.5, 0.0),
626 ("Magic Portal", [[0.6, 0.1, 0.9], [0.2, 0.9, 0.9], [1.0, 0.9, 0.3]], 2.5, 0.02), ("Cosmic Dust", [[0.4, 0.3, 0.2], [0.8, 0.6, 0.4], [1.0, 0.9, 0.7]], 1.0, 0.03), ("Pulsar", [[0.1, 0.1, 0.6], [0.3, 0.6, 1.0], [1.0, 1.0, 1.0]], 3.0, 0.04),
627 ("Stardust", [[0.8, 0.7, 0.3], [1.0, 0.9, 0.6], [1.0, 1.0, 1.0]], 0.8, 0.06), ("Supernova", [[1.0, 0.2, 0.0], [1.0, 0.6, 0.1], [0.9, 0.9, 1.0]], 2.0, 0.03), ("Eclipse", [[0.02, 0.0, 0.05], [0.4, 0.1, 0.0], [1.0, 0.6, 0.2]], 0.6, 0.01), ("Quasar", [[0.4, 0.2, 1.0], [0.1, 0.9, 1.0], [1.0, 1.0, 1.0]], 2.5, 0.03),
628 ];
629 for (name, pal, speed, stars) in cosmos {
630 v.push(p("Deep Space", name, deep_layers(pal, speed, stars + 0.02, [2.0, 4.0, 8.0])));
631 }
632 let palettes: [(&str, [[f32; 3]; 4]); 8] = [
634 ("Meadow", [[0.1, 0.4, 0.15], [0.25, 0.65, 0.2], [0.5, 0.85, 0.3], [0.8, 0.95, 0.5]]), ("Candy", [[0.9, 0.3, 0.6], [1.0, 0.55, 0.75], [1.0, 0.8, 0.85], [1.0, 0.95, 0.95]]),
635 ("Ocean", [[0.0, 0.2, 0.5], [0.0, 0.45, 0.75], [0.2, 0.7, 0.9], [0.8, 0.95, 1.0]]), ("Autumn", [[0.4, 0.1, 0.05], [0.8, 0.3, 0.1], [1.0, 0.6, 0.15], [1.0, 0.85, 0.4]]),
636 ("Frost", [[0.3, 0.45, 0.7], [0.55, 0.75, 0.95], [0.8, 0.92, 1.0], [1.0, 1.0, 1.0]]), ("Shadow", [[0.03, 0.02, 0.08], [0.12, 0.08, 0.25], [0.3, 0.2, 0.5], [0.55, 0.4, 0.8]]),
637 ("Mint", [[0.2, 0.6, 0.5], [0.4, 0.85, 0.7], [0.7, 1.0, 0.85], [0.95, 1.0, 0.95]]), ("Sunrise", [[0.5, 0.15, 0.4], [0.9, 0.35, 0.35], [1.0, 0.65, 0.3], [1.0, 0.92, 0.55]]),
638 ];
639 for (name, stops) in palettes {
640 v.push(p("Stylized Painted", leak(format!("Painted {name}")), stylized(stops, 3.0, 4.0, 0.0)));
641 v.push(p("Stylized Painted", leak(format!("Blobs {name}")), stylized(stops, 1.8, 3.0, 1.0)));
642 v.push(p("Stylized Painted", leak(format!("Clouds {name}")), stylized(stops, 1.2, 5.0, 2.0)));
643 v.push(p("Stylized Painted", leak(format!("Speckle {name}")), stylized(stops, 9.0, 3.0, 0.0)));
644 v.push(p("Stylized Painted", leak(format!("Gradient {name}")), gradient("Linear gradient", stops, 0.0)));
645 v.push(p("Stylized Painted", leak(format!("Radial {name}")), gradient("Radial gradient", stops, 0.0)));
646 v.push(p("Stylized Painted", leak(format!("Stripes {name}")), pattern("Stripes", &[8.0, 0.85], stops[0], stops[2], 0.6)));
647 v.push(p("Stylized Painted", leak(format!("Dots {name}")), pattern("Dots", &[10.0, 0.3], stops[3], stops[1], 0.6)));
648 }
649 for (name, c) in [("Red", [1.0, 0.1, 0.1]), ("Orange", [1.0, 0.5, 0.0]), ("Yellow", [1.0, 0.9, 0.1]), ("Green", [0.1, 1.0, 0.3]), ("Blue", [0.15, 0.4, 1.0]), ("Violet", [0.55, 0.2, 1.0]), ("White", [1.0, 1.0, 1.0])] {
651 v.push(p("Emissive", leak(format!("Neon Grid {name}")), neon_grid(c, 6.0)));
652 v.push(p("Emissive", leak(format!("Plasma {name}")), emissive([[c[0] * 0.05, c[1] * 0.05, c[2] * 0.05], tint(c, [0.4; 3]), c, [1.0, 1.0, 1.0]], [0.1, 0.4, 0.7, 1.0], 4.0, 2.0, 3.0, tint(c, [0.05; 3]), 0.3)));
653 }
654}
655
656fn p(category: &'static str, name: &'static str, graph: MaterialGraph) -> Preset {
657 Preset { category, name, graph }
658}
659
660pub fn library() -> Vec<Preset> {
662 let sand = [[0.55, 0.45, 0.28], [0.72, 0.6, 0.38], [0.82, 0.72, 0.5], [0.9, 0.82, 0.62]];
663 let mut v = vec![
664 p("Stone", "Granite", natural([[0.18, 0.18, 0.19], [0.42, 0.41, 0.42], [0.62, 0.6, 0.6], [0.8, 0.78, 0.78]], [0.0, 0.35, 0.65, 1.0], 6.0, 0.0, (0.4, 0.7), 0.0, 1.0)),
666 p("Stone", "Rock", natural([[0.12, 0.11, 0.1], [0.28, 0.25, 0.22], [0.45, 0.4, 0.35], [0.62, 0.57, 0.5]], [0.0, 0.3, 0.65, 1.0], 2.5, 1.0, (0.75, 1.0), 0.0, 4.0)),
667 p("Stone", "Sandstone", natural([[0.5, 0.36, 0.2], [0.68, 0.5, 0.3], [0.8, 0.62, 0.4], [0.88, 0.72, 0.5]], [0.0, 0.3, 0.7, 1.0], 3.5, 2.0, (0.8, 1.0), 0.0, 2.0)),
668 p("Stone", "Slate", natural([[0.06, 0.07, 0.09], [0.14, 0.16, 0.2], [0.22, 0.25, 0.3], [0.32, 0.35, 0.4]], [0.0, 0.4, 0.7, 1.0], 4.0, 1.0, (0.45, 0.8), 0.0, 1.5)),
669 p("Stone", "Concrete", natural([[0.3, 0.3, 0.3], [0.42, 0.42, 0.41], [0.52, 0.52, 0.5], [0.6, 0.6, 0.58]], [0.0, 0.4, 0.7, 1.0], 5.0, 0.0, (0.85, 1.0), 0.0, 0.8)),
670 p("Stone", "Asphalt", natural([[0.04, 0.04, 0.045], [0.08, 0.08, 0.09], [0.14, 0.14, 0.15], [0.22, 0.22, 0.23]], [0.0, 0.4, 0.75, 1.0], 12.0, 0.0, (0.8, 1.0), 0.0, 1.5)),
671 p("Stone", "Cobblestone", cracked([0.32, 0.3, 0.28], [0.05, 0.05, 0.05], 5.0, 0.9)),
672 p("Stone", "Marble White", marble([0.92, 0.92, 0.9], [0.35, 0.37, 0.42], 4.0)),
673 p("Stone", "Marble Black", marble([0.04, 0.04, 0.05], [0.8, 0.75, 0.55], 5.0)),
674 p("Stone", "Marble Green", marble([0.08, 0.3, 0.2], [0.85, 0.92, 0.85], 3.0)),
675 p("Ground", "Dirt", natural([[0.1, 0.07, 0.04], [0.2, 0.14, 0.08], [0.32, 0.23, 0.14], [0.42, 0.32, 0.2]], [0.0, 0.35, 0.7, 1.0], 3.0, 0.0, (0.9, 1.0), 0.0, 2.5)),
676 p("Ground", "Mud", natural([[0.06, 0.04, 0.025], [0.13, 0.09, 0.05], [0.2, 0.14, 0.08], [0.28, 0.2, 0.12]], [0.0, 0.4, 0.75, 1.0], 2.0, 2.0, (0.3, 0.7), 0.0, 3.0)),
677 p("Ground", "Sand", natural(sand, [0.0, 0.35, 0.7, 1.0], 8.0, 0.0, (0.85, 1.0), 0.0, 1.0)),
678 p("Ground", "Grass", natural([[0.04, 0.12, 0.03], [0.08, 0.25, 0.05], [0.16, 0.38, 0.08], [0.3, 0.5, 0.14]], [0.0, 0.35, 0.7, 1.0], 9.0, 0.0, (0.8, 1.0), 0.0, 1.2)),
679 p("Ground", "Moss", natural([[0.03, 0.1, 0.03], [0.1, 0.25, 0.06], [0.2, 0.4, 0.1], [0.35, 0.55, 0.2]], [0.0, 0.3, 0.65, 1.0], 14.0, 2.0, (0.9, 1.0), 0.0, 2.5)),
680 p("Ground", "Snow", natural([[0.7, 0.75, 0.82], [0.85, 0.9, 0.96], [0.95, 0.97, 1.0], [1.0, 1.0, 1.0]], [0.0, 0.3, 0.7, 1.0], 4.0, 0.0, (0.55, 0.8), 0.0, 0.6)),
681 p("Ground", "Ice", natural([[0.45, 0.65, 0.8], [0.62, 0.8, 0.92], [0.8, 0.92, 0.98], [0.95, 1.0, 1.0]], [0.0, 0.35, 0.7, 1.0], 3.0, 1.0, (0.05, 0.25), 0.0, 0.5)),
682 p("Ground", "Dry Earth Cracks", cracked([0.5, 0.38, 0.24], [0.06, 0.04, 0.02], 4.0, 0.95)),
683 p("Metal", "Brushed Steel", metal_brushed([0.75, 0.77, 0.8], [0.5, 0.52, 0.55], 0.35, 180.0)),
685 p("Metal", "Brushed Aluminium", metal_brushed([0.88, 0.89, 0.9], [0.65, 0.66, 0.68], 0.3, 220.0)),
686 p("Metal", "Copper", metal_brushed([0.95, 0.52, 0.38], [0.6, 0.3, 0.2], 0.3, 120.0)),
687 p("Metal", "Gold", metal_brushed([1.0, 0.78, 0.34], [0.75, 0.55, 0.2], 0.2, 90.0)),
688 p("Metal", "Titanium", metal_brushed([0.55, 0.52, 0.5], [0.38, 0.36, 0.35], 0.38, 160.0)),
689 p("Metal", "Rusty Iron", natural([[0.1, 0.1, 0.1], [0.4, 0.17, 0.07], [0.6, 0.28, 0.1], [0.35, 0.33, 0.32]], [0.0, 0.35, 0.65, 1.0], 4.0, 1.0, (0.55, 0.95), 0.6, 3.0)),
690 p("Metal", "Hexagon Plate", hex_metal([0.5, 0.52, 0.56], [0.12, 0.12, 0.14], 7.0)),
691 p("Metal", "Carbon Fiber", weave([0.02, 0.02, 0.025], [0.07, 0.07, 0.08], 24.0, 0.3, 0.3)),
692 p("Metal", "Chain Mail", hex_metal([0.4, 0.42, 0.45], [0.05, 0.05, 0.06], 18.0)),
693 p("Wood", "Oak", wood([0.55, 0.38, 0.2], [0.3, 0.19, 0.09], false)),
695 p("Wood", "Dark Walnut", wood([0.25, 0.14, 0.08], [0.1, 0.055, 0.03], false)),
696 p("Wood", "Pine Planks", wood([0.78, 0.6, 0.36], [0.55, 0.38, 0.2], true)),
697 p("Wood", "Floor Boards", wood([0.45, 0.3, 0.17], [0.22, 0.13, 0.07], true)),
698 p("Organic", "Leather", cracked([0.22, 0.1, 0.05], [0.08, 0.035, 0.02], 22.0, 0.55)),
699 p("Organic", "Skin", natural([[0.55, 0.32, 0.25], [0.72, 0.46, 0.36], [0.85, 0.6, 0.48], [0.9, 0.68, 0.56]], [0.0, 0.35, 0.7, 1.0], 18.0, 0.0, (0.45, 0.6), 0.0, 0.4)),
700 p("Organic", "Bark", natural([[0.06, 0.045, 0.035], [0.15, 0.11, 0.08], [0.26, 0.19, 0.13], [0.36, 0.28, 0.2]], [0.0, 0.35, 0.7, 1.0], 3.0, 1.0, (0.9, 1.0), 0.0, 5.0)),
701 p("Fabric", "Linen", weave([0.72, 0.68, 0.58], [0.6, 0.56, 0.47], 40.0, 0.0, 0.95)),
703 p("Fabric", "Denim", weave([0.08, 0.14, 0.3], [0.12, 0.2, 0.4], 60.0, 0.0, 0.95)),
704 p("Fabric", "Red Cloth", weave([0.5, 0.04, 0.04], [0.65, 0.07, 0.06], 50.0, 0.0, 0.85)),
705 p("Building", "Red Bricks", bricks([0.55, 0.2, 0.12], [0.55, 0.53, 0.5])),
706 p("Building", "Old Bricks", bricks([0.4, 0.22, 0.16], [0.3, 0.29, 0.28])),
707 p("Building", "Checker Tiles", tiles([0.9, 0.9, 0.88], [0.1, 0.1, 0.12], 8.0, 0.04, 0.2, 0.0)),
708 p("Building", "Bathroom Tiles", tiles([0.85, 0.9, 0.92], [0.78, 0.84, 0.88], 12.0, 0.05, 0.12, 0.0)),
709 p("Building", "Plaster", natural([[0.7, 0.68, 0.64], [0.78, 0.76, 0.72], [0.85, 0.83, 0.79], [0.9, 0.88, 0.85]], [0.0, 0.4, 0.7, 1.0], 7.0, 0.0, (0.85, 1.0), 0.0, 0.5)),
710 p("Emissive", "Lava", emissive([[0.04, 0.0, 0.0], [0.6, 0.06, 0.0], [1.0, 0.45, 0.05], [1.0, 0.9, 0.4]], [0.2, 0.45, 0.7, 1.0], 2.5, 1.0, 4.0, [0.04, 0.03, 0.03], 0.9)),
712 p("Emissive", "Toxic Slime", emissive([[0.0, 0.05, 0.0], [0.05, 0.4, 0.0], [0.3, 0.9, 0.05], [0.8, 1.0, 0.4]], [0.2, 0.5, 0.75, 1.0], 3.0, 2.0, 2.5, [0.04, 0.12, 0.03], 0.15)),
713 p("Emissive", "Plasma", emissive([[0.05, 0.0, 0.2], [0.4, 0.0, 0.9], [0.9, 0.3, 1.0], [1.0, 0.9, 1.0]], [0.1, 0.4, 0.7, 1.0], 4.0, 2.0, 3.0, [0.02, 0.0, 0.05], 0.3)),
714 p("Emissive", "Neon Grid Cyan", neon_grid([0.0, 0.9, 1.0], 6.0)),
715 p("Emissive", "Neon Grid Magenta", neon_grid([1.0, 0.1, 0.8], 6.0)),
716 p("Plain", "Glass Clear", glass([0.9, 0.95, 1.0], 0.12, 0.03)),
718 p("Plain", "Glass Green", glass([0.3, 0.7, 0.45], 0.25, 0.05)),
719 p("Plain", "Rubber Black", plain([0.02, 0.02, 0.022], 0.85, 0.0)),
720 p("Plain", "Plastic White", plain([0.9, 0.9, 0.9], 0.35, 0.0)),
721 p("Plain", "Plastic Red", plain([0.8, 0.04, 0.03], 0.3, 0.0)),
722 p("Plain", "Plastic Blue", plain([0.05, 0.2, 0.8], 0.3, 0.0)),
723 p("Plain", "Chrome", plain([0.9, 0.9, 0.92], 0.04, 1.0)),
724 p("Plain", "Clay", plain([0.55, 0.3, 0.2], 0.9, 0.0)),
725 p("Stylized", "Toon Grass", stylized([[0.1, 0.4, 0.15], [0.2, 0.6, 0.2], [0.4, 0.8, 0.25], [0.65, 0.92, 0.35]], 3.0, 4.0, 0.0)),
727 p("Stylized", "Toon Stone", stylized([[0.32, 0.33, 0.4], [0.5, 0.52, 0.6], [0.66, 0.68, 0.76], [0.82, 0.84, 0.9]], 2.5, 4.0, 1.0)),
728 p("Stylized", "Toon Sand", stylized([[0.82, 0.62, 0.35], [0.92, 0.75, 0.45], [0.98, 0.86, 0.58], [1.0, 0.94, 0.75]], 4.0, 4.0, 0.0)),
729 p("Stylized", "Toon Snow", stylized([[0.6, 0.72, 0.9], [0.78, 0.88, 1.0], [0.92, 0.96, 1.0], [1.0, 1.0, 1.0]], 3.0, 3.0, 0.0)),
730 p("Stylized", "Toon Dirt", stylized([[0.25, 0.15, 0.1], [0.38, 0.24, 0.15], [0.5, 0.33, 0.2], [0.62, 0.42, 0.26]], 3.5, 4.0, 2.0)),
731 p("Stylized", "Toon Wood", wood([0.8, 0.55, 0.3], [0.5, 0.3, 0.15], false)),
732 p("Stylized", "Toon Water Foam", stylized([[0.1, 0.4, 0.75], [0.2, 0.6, 0.9], [0.55, 0.85, 1.0], [0.95, 1.0, 1.0]], 2.0, 5.0, 2.0)),
733 p("Stylized", "Toon Lava", stylized([[0.3, 0.02, 0.02], [0.8, 0.15, 0.05], [1.0, 0.55, 0.1], [1.0, 0.9, 0.35]], 2.5, 4.0, 1.0)),
734 p("Stylized", "Candy Stripes", pattern("Stripes", &[10.0, 0.9], [0.95, 0.2, 0.3], [1.0, 0.95, 0.95], 0.35)),
735 p("Stylized", "Polka Dots", pattern("Dots", &[8.0, 0.28], [1.0, 0.85, 0.9], [0.9, 0.2, 0.5], 0.5)),
736 p("Stylized", "Pastel Checker", pattern("Checker", &[10.0], [1.0, 0.85, 0.9], [0.8, 0.9, 1.0], 0.6)),
737 p("Stylized", "Comic Halftone", pattern("Dots", &[40.0, 0.35], [1.0, 0.96, 0.85], [0.1, 0.12, 0.3], 0.9)),
738 p("Stylized", "Zebra", pattern("Stripes", &[14.0, 0.95], [0.03, 0.03, 0.03], [0.96, 0.96, 0.96], 0.6)),
739 p("Stylized", "Honeycomb", pattern("Hexagons", &[9.0, 0.12], [0.35, 0.2, 0.02], [1.0, 0.72, 0.1], 0.3)),
740 p("Stylized", "Pixel Camo", stylized([[0.2, 0.25, 0.12], [0.35, 0.4, 0.2], [0.5, 0.42, 0.28], [0.15, 0.17, 0.1]], 5.0, 3.0, 0.0)),
741 p("Stylized", "Tie Dye", rainbow(false, 2.0)),
742 p("Stylized", "Holographic Foil", rainbow(true, 1.0)),
743 p("Stylized", "Sunset Gradient", gradient("Linear gradient", [[0.15, 0.05, 0.35], [0.75, 0.15, 0.4], [1.0, 0.55, 0.2], [1.0, 0.9, 0.5]], 0.0)),
744 p("Stylized", "Ocean Gradient", gradient("Radial gradient", [[0.0, 0.05, 0.2], [0.0, 0.3, 0.6], [0.1, 0.6, 0.8], [0.7, 0.95, 1.0]], 0.0)),
745 p("Stylized", "Neon Gradient", gradient("Angular gradient", [[1.0, 0.1, 0.6], [0.5, 0.1, 1.0], [0.1, 0.8, 1.0], [1.0, 0.1, 0.6]], 2.5)),
746 p("Stylized", "Galaxy", galaxy([0.25, 0.1, 0.6], [0.8, 0.3, 0.7])),
747 p("Stylized", "Nebula", galaxy([0.05, 0.35, 0.6], [0.2, 0.8, 0.7])),
748 p("Stylized", "Watercolor", stylized([[0.85, 0.9, 0.95], [0.7, 0.82, 0.92], [0.95, 0.85, 0.8], [0.98, 0.95, 0.9]], 1.5, 8.0, 0.0)),
749 p("Stylized", "Paper", natural([[0.86, 0.84, 0.78], [0.9, 0.88, 0.82], [0.93, 0.91, 0.86], [0.96, 0.95, 0.9]], [0.0, 0.4, 0.7, 1.0], 18.0, 0.0, (0.9, 1.0), 0.0, 0.2)),
750 p("Stylized", "Cardboard", natural([[0.5, 0.36, 0.22], [0.6, 0.45, 0.28], [0.68, 0.52, 0.34], [0.74, 0.58, 0.4]], [0.0, 0.4, 0.7, 1.0], 20.0, 1.0, (0.9, 1.0), 0.0, 0.5)),
751 ];
752 extra(&mut v);
753 v.extend(crate::material_presets_v4::library());
754 for preset in &mut v {
755 preset.graph.next_id = preset.graph.nodes.iter().map(|n| n.id + 1).max().unwrap_or(1);
756 for n in &mut preset.graph.nodes {
757 n.preview = false;
758 }
759 }
760 v
761}
762
763#[cfg(test)]
764mod tests {
765 use super::*;
766
767 #[test]
768 fn names_are_unique_and_every_preset_round_trips() {
769 let all = library();
770 let mut seen = std::collections::HashSet::new();
771 for p in &all {
772 assert!(seen.insert((p.category, p.name)), "duplicate {} / {}", p.category, p.name);
773 let again = MaterialGraph::from_json(&p.graph.to_json()).unwrap();
774 assert_eq!(again, p.graph, "{}", p.name);
775 again.validate().unwrap_or_else(|e| panic!("{}: {e}", p.name));
776 }
777 }
778}