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
|
use rand::Rng;
pub const TEX_SIZE: usize = 64;
/// Deterministic hash for coherent procedural noise.
fn hash(x: u32, y: u32, seed: u64) -> u64 {
let mut h = (x as u64).wrapping_mul(0x9e3779b9);
h = h.wrapping_add((y as u64).wrapping_mul(0x517cc1b727220a95));
h = h.wrapping_add(seed);
h = (h ^ (h >> 33)).wrapping_mul(0xc6a4a7935bd1e995);
h = (h ^ (h >> 29)).wrapping_mul(0x5bd1e995);
h
}
/// Brown cracked wall texture — 64×64, brick pattern with mortar lines and fissures.
pub fn generate_wall_texture(rng: &mut impl Rng) -> Vec<u32> {
let seed = rng.gen::<u64>();
let mut tex = vec![0u32; TEX_SIZE * TEX_SIZE];
for y in 0..TEX_SIZE {
for x in 0..TEX_SIZE {
let h = hash(x as u32, y as u32, seed);
let r = 105u8.wrapping_add((h % 50) as u8);
let g = 55u8.wrapping_add(((h >> 8) % 35) as u8);
let b = 22u8.wrapping_add(((h >> 16) % 25) as u8);
// Brick mortar every 16 pixels
let mortar = y % 16 == 0 || y % 16 == 15;
let (r, g, b) = if mortar {
(42, 20, 8)
} else {
let crack_hash = hash(x.wrapping_add(1000) as u32, y as u32, seed);
let crack_val = (crack_hash % 100) as u8;
if crack_val < 8 {
// dark crack
let factor = 0.30 + (crack_val as f64 / 8.0) * 0.25;
(
(r as f64 * factor) as u8,
(g as f64 * factor) as u8,
(b as f64 * factor) as u8,
)
} else if crack_val < 14 {
// light crack highlight
(
(r.saturating_add(25)).min(255),
(g.saturating_add(18)).min(255),
(b.saturating_add(10)).min(255),
)
} else {
(r, g, b)
}
};
tex[y * TEX_SIZE + x] =
0xFF00_0000 | ((r as u32) << 16) | ((g as u32) << 8) | (b as u32);
}
}
tex
}
/// Gray stone-tile floor — 64×64, checkerboard with grout and subtle colour tint.
pub fn generate_floor_texture(rng: &mut impl Rng) -> Vec<u32> {
let seed = rng.gen::<u64>();
let mut tex = vec![0u32; TEX_SIZE * TEX_SIZE];
for y in 0..TEX_SIZE {
for x in 0..TEX_SIZE {
let h = hash(x as u32, y as u32, seed);
let h2 = hash(x.wrapping_add(2000) as u32, y.wrapping_add(2000) as u32, seed);
let tile_x = x / 16;
let tile_y = y / 16;
let is_light_tile = (tile_x + tile_y) % 2 == 0;
let local_x = x % 16;
let local_y = y % 16;
let is_grout = local_x == 0 || local_y == 0;
let base_gray: u8 = if is_light_tile { 115 } else { 95 };
let noise = (h % 15) as u8;
let tint_r = (h2 % 8) as i16 - 4i16;
let tint_b = ((h2 >> 8) % 8) as i16 - 4i16;
let gray = if is_grout {
base_gray.saturating_sub(30).saturating_add(noise / 3)
} else {
base_gray.saturating_add(noise / 2)
};
let r = (gray as i16 + tint_r).clamp(0, 255) as u8;
let g = gray;
let b = (gray as i16 + tint_b).clamp(0, 255) as u8;
tex[y * TEX_SIZE + x] =
0xFF00_0000 | ((r as u32) << 16) | ((g as u32) << 8) | (b as u32);
}
}
tex
}
|