summaryrefslogtreecommitdiffstats
path: root/src/texture.rs
diff options
context:
space:
mode:
authorsalmonik <raisersoft@proton.me>2026-07-09 23:27:55 +0200
committersalmonik <raisersoft@proton.me>2026-07-09 23:27:55 +0200
commit3460d889aa2e7af1a60d218a1a8589027b4e4e63 (patch)
tree89e66acd05fba086835337bfa95b36710dc8c4da /src/texture.rs
downloaddungeon-3460d889aa2e7af1a60d218a1a8589027b4e4e63.tar.gz
dungeon-3460d889aa2e7af1a60d218a1a8589027b4e4e63.zip
init
Diffstat (limited to '')
-rw-r--r--src/texture.rs102
1 files changed, 102 insertions, 0 deletions
diff --git a/src/texture.rs b/src/texture.rs
new file mode 100644
index 0000000..bdbb15c
--- /dev/null
+++ b/src/texture.rs
@@ -0,0 +1,102 @@
1use rand::Rng;
2
3pub const TEX_SIZE: usize = 64;
4
5/// Deterministic hash for coherent procedural noise.
6fn hash(x: u32, y: u32, seed: u64) -> u64 {
7 let mut h = (x as u64).wrapping_mul(0x9e3779b9);
8 h = h.wrapping_add((y as u64).wrapping_mul(0x517cc1b727220a95));
9 h = h.wrapping_add(seed);
10 h = (h ^ (h >> 33)).wrapping_mul(0xc6a4a7935bd1e995);
11 h = (h ^ (h >> 29)).wrapping_mul(0x5bd1e995);
12 h
13}
14
15/// Brown cracked wall texture — 64×64, brick pattern with mortar lines and fissures.
16pub fn generate_wall_texture(rng: &mut impl Rng) -> Vec<u32> {
17 let seed = rng.gen::<u64>();
18 let mut tex = vec![0u32; TEX_SIZE * TEX_SIZE];
19
20 for y in 0..TEX_SIZE {
21 for x in 0..TEX_SIZE {
22 let h = hash(x as u32, y as u32, seed);
23
24 let r = 105u8.wrapping_add((h % 50) as u8);
25 let g = 55u8.wrapping_add(((h >> 8) % 35) as u8);
26 let b = 22u8.wrapping_add(((h >> 16) % 25) as u8);
27
28 // Brick mortar every 16 pixels
29 let mortar = y % 16 == 0 || y % 16 == 15;
30
31 let (r, g, b) = if mortar {
32 (42, 20, 8)
33 } else {
34 let crack_hash = hash(x.wrapping_add(1000) as u32, y as u32, seed);
35 let crack_val = (crack_hash % 100) as u8;
36 if crack_val < 8 {
37 // dark crack
38 let factor = 0.30 + (crack_val as f64 / 8.0) * 0.25;
39 (
40 (r as f64 * factor) as u8,
41 (g as f64 * factor) as u8,
42 (b as f64 * factor) as u8,
43 )
44 } else if crack_val < 14 {
45 // light crack highlight
46 (
47 (r.saturating_add(25)).min(255),
48 (g.saturating_add(18)).min(255),
49 (b.saturating_add(10)).min(255),
50 )
51 } else {
52 (r, g, b)
53 }
54 };
55
56 tex[y * TEX_SIZE + x] =
57 0xFF00_0000 | ((r as u32) << 16) | ((g as u32) << 8) | (b as u32);
58 }
59 }
60 tex
61}
62
63/// Gray stone-tile floor — 64×64, checkerboard with grout and subtle colour tint.
64pub fn generate_floor_texture(rng: &mut impl Rng) -> Vec<u32> {
65 let seed = rng.gen::<u64>();
66 let mut tex = vec![0u32; TEX_SIZE * TEX_SIZE];
67
68 for y in 0..TEX_SIZE {
69 for x in 0..TEX_SIZE {
70 let h = hash(x as u32, y as u32, seed);
71 let h2 = hash(x.wrapping_add(2000) as u32, y.wrapping_add(2000) as u32, seed);
72
73 let tile_x = x / 16;
74 let tile_y = y / 16;
75 let is_light_tile = (tile_x + tile_y) % 2 == 0;
76
77 let local_x = x % 16;
78 let local_y = y % 16;
79 let is_grout = local_x == 0 || local_y == 0;
80
81 let base_gray: u8 = if is_light_tile { 115 } else { 95 };
82 let noise = (h % 15) as u8;
83
84 let tint_r = (h2 % 8) as i16 - 4i16;
85 let tint_b = ((h2 >> 8) % 8) as i16 - 4i16;
86
87 let gray = if is_grout {
88 base_gray.saturating_sub(30).saturating_add(noise / 3)
89 } else {
90 base_gray.saturating_add(noise / 2)
91 };
92
93 let r = (gray as i16 + tint_r).clamp(0, 255) as u8;
94 let g = gray;
95 let b = (gray as i16 + tint_b).clamp(0, 255) as u8;
96
97 tex[y * TEX_SIZE + x] =
98 0xFF00_0000 | ((r as u32) << 16) | ((g as u32) << 8) | (b as u32);
99 }
100 }
101 tex
102}