Browse Source
- Implement 16x16 procedural textures using Perlin noise (RCT-style) - Each tile has unique texture based on grid position and biome - GL_NEAREST filtering for retro pixelated look - Random seeds for both heightmap and textures on regeneration (R key) - Disable lighting on top faces to show pure texture colors - Uniform brown color for side faces with shading - Update documentation (README, docs/) with texture features - Update copilot instructions with communication rulesmaster v1.1.0
9 changed files with 464 additions and 44 deletions
@ -0,0 +1,120 @@
|
||||
""" |
||||
Test script to generate and visualize procedural textures for terrain tiles |
||||
""" |
||||
import numpy as np |
||||
import noise |
||||
import matplotlib.pyplot as plt |
||||
from matplotlib.colors import ListedColormap |
||||
|
||||
# Configuration |
||||
GRID_SIZE = 20 |
||||
SEED = 42 |
||||
|
||||
# Base biome colors (RGB 0-1) |
||||
BIOME_COLORS = { |
||||
'grass': (0.25, 0.6, 0.25), |
||||
'sand': (0.76, 0.7, 0.5), |
||||
'water': (0.2, 0.4, 0.8), |
||||
} |
||||
|
||||
def generate_texture(grid_size, base_color, seed): |
||||
""" |
||||
Generate procedural texture for a tile grid |
||||
|
||||
Args: |
||||
grid_size: Size of the grid (grid_size x grid_size) |
||||
base_color: Base RGB color tuple (0-1 range) |
||||
seed: Random seed |
||||
|
||||
Returns: |
||||
numpy array of shape (grid_size, grid_size, 3) with RGB values |
||||
""" |
||||
texture = np.zeros((grid_size, grid_size, 3)) |
||||
|
||||
for i in range(grid_size): |
||||
for j in range(grid_size): |
||||
# Use grid coordinates for noise sampling |
||||
i_coord = float(i) * 0.1 |
||||
j_coord = float(j) * 0.1 |
||||
|
||||
# Fine detail noise (subtle variations) |
||||
detail_noise = noise.pnoise2( |
||||
i_coord + seed * 0.01, |
||||
j_coord + seed * 0.01, |
||||
octaves=3, |
||||
persistence=0.5, |
||||
lacunarity=2.0 |
||||
) |
||||
|
||||
# Medium pattern noise (patches/clusters) |
||||
pattern_noise = noise.pnoise2( |
||||
i_coord * 0.5 + 100, |
||||
j_coord * 0.5 + 100, |
||||
octaves=2, |
||||
persistence=0.6 |
||||
) |
||||
|
||||
# Random spots (like grass tufts or darker patches) |
||||
spots_noise = noise.pnoise2( |
||||
i_coord * 1.5 + 200, |
||||
j_coord * 1.5 + 200, |
||||
octaves=1 |
||||
) |
||||
|
||||
# Create darker spots where noise is high |
||||
spot_factor = 1.0 |
||||
if spots_noise > 0.3: # Lower threshold for more spots |
||||
spot_factor = 0.75 # Darker patch |
||||
elif spots_noise > 0.5: |
||||
spot_factor = 0.6 # Even darker |
||||
|
||||
# Combine all noise layers |
||||
variation = (detail_noise * 0.4 + pattern_noise * 0.6) * 0.25 |
||||
|
||||
# Apply to color with spot darkening |
||||
textured_color = tuple( |
||||
max(0.0, min(1.0, (c + variation) * spot_factor)) |
||||
for c in base_color |
||||
) |
||||
|
||||
texture[i, j] = textured_color |
||||
|
||||
return texture |
||||
|
||||
def main(): |
||||
"""Generate and display textures for different biomes""" |
||||
fig, axes = plt.subplots(2, 3, figsize=(15, 10)) |
||||
fig.suptitle('Procedural Texture Generation - RCT Style', fontsize=16) |
||||
|
||||
biomes = [ |
||||
('Grass', BIOME_COLORS['grass']), |
||||
('Sand', BIOME_COLORS['sand']), |
||||
('Water', BIOME_COLORS['water']), |
||||
] |
||||
|
||||
for idx, (name, base_color) in enumerate(biomes): |
||||
# Generate texture with variation |
||||
texture = generate_texture(GRID_SIZE, base_color, SEED) |
||||
|
||||
# Show textured version |
||||
ax1 = axes[0, idx] |
||||
ax1.imshow(texture) |
||||
ax1.set_title(f'{name} - Textured') |
||||
ax1.axis('off') |
||||
|
||||
# Show base color for comparison |
||||
base_texture = np.zeros((GRID_SIZE, GRID_SIZE, 3)) |
||||
base_texture[:, :] = base_color |
||||
|
||||
ax2 = axes[1, idx] |
||||
ax2.imshow(base_texture) |
||||
ax2.set_title(f'{name} - Base Color') |
||||
ax2.axis('off') |
||||
|
||||
plt.tight_layout() |
||||
plt.savefig('texture_test.png', dpi=150) |
||||
print("✓ Texture generated and saved as 'texture_test.png'") |
||||
plt.show() |
||||
|
||||
if __name__ == '__main__': |
||||
main() |
||||
Loading…
Reference in new issue