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