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 { let seed = rng.gen::(); 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 { let seed = rng.gen::(); 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 }