Add procedural pixelated textures for tiles

- 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 rules
This commit is contained in:
John Doe
2025-10-24 17:59:39 +02:00
parent 01799256e7
commit bce3b0324f
9 changed files with 468 additions and 48 deletions
+23 -15
View File
@@ -11,8 +11,9 @@ Quando avvii il programma, vedrai:
1. **Una griglia di terreno 3D** composta da 20×20 tessere (chiamate "tile")
2. **Variazioni di altezza** che creano colline, valli e montagne
3. **Diversi colori** che rappresentano biomi (acqua, sabbia, erba, roccia, neve)
4. **Linee nere** che delimitano ogni tessera, creando un effetto griglia
5. **Una vista dall'alto** con un angolo di 45 gradi (vista isometrica)
4. **Texture procedurali pixelate** - Ogni tile ha decorazioni uniche in stile retro
5. **Linee nere** che delimitano ogni tessera, creando un effetto griglia
6. **Una vista dall'alto** con un angolo di 45 gradi (vista isometrica)
### Interattività
@@ -74,23 +75,24 @@ Altezza 70+ → Bianco (Neve) 🏔️
### 3. Rendering 3D
Il computer disegna ogni tessera come un quadrato in 3D:
Il computer disegna ogni tessera come un quadrato in 3D con texture procedurale:
```
Vista dall'alto: Vista isometrica:
Vista dall'alto: Vista isometrica con texture:
┌──┬──┐ ◇──◇
│ │ │ ╱│ ╱│
├──┼──┤ → ◇──◇ │
│ │ │ │ ╱│ ╱
┌──┬──┐ ◇──◇ (con pattern 16×16 pixel)
│ │ │ ╱│ ╱│ (macchie scure, variazioni)
├──┼──┤ → ◇──◇ │ (ogni tile unica)
│ │ │ │ ╱│ ╱ (stile retro pixelato)
└──┴──┘ ◇──◇
```
Ogni quadrato (quad) è disegnato con:
- Una **faccia superiore** (quella che vediamo)
- **Facce laterali** (per mostrare l'altezza)
- **Colore** basato sull'altezza
- **Ombreggiatura** per dare profondità
- Una **faccia superiore** con texture procedurale 16×16 pixel
- **Facce laterali** uniformi marroni per l'altezza
- **Colore base** determinato dal bioma
- **Pattern unici** generati con Perlin noise per ogni tile
- **Ombreggiatura** sulle facce laterali per profondità
## Risultati Visivi
@@ -161,7 +163,14 @@ shader/
## Caratteristiche Principali
### ✅ Generazione Procedurale
Il terreno è generato automaticamente usando algoritmi matematici. Ogni volta che premi R, ottieni un paesaggio completamente diverso!
Il terreno è generato automaticamente usando algoritmi matematici. Ogni volta che premi R, ottieni un paesaggio completamente diverso con texture uniche!
### ✅ Texture Procedurali Pixelate
Ogni tile ha una texture 16×16 pixel generata proceduralmente con:
- Pattern casuali unici per ogni tile
- Macchie scure e variazioni di colore
- Stile retro pixelato (GL_NEAREST filtering)
- Contestuali al bioma (erba, sabbia, roccia, ecc.)
### ✅ Configurabilità
Tutto è personalizzabile tramite il file `config/settings.py`:
@@ -211,10 +220,9 @@ Il progetto base ha alcune limitazioni:
- ❌ Non c'è salvataggio/caricamento delle mappe
- ❌ Non puoi modificare il terreno interattivamente
- ❌ La griglia è fissa a 20×20 (modificabile nel config)
- ❌ Non ci sono texture, solo colori solidi
- ❌ Nessun sistema di gameplay
Queste sono tutte cose che puoi aggiungere estendendo il progetto!
Le texture procedurali sono completamente implementate! ✅
## Prossimi Passi
+88 -14
View File
@@ -38,9 +38,10 @@ heightmap[i+1][j+1] = 13
### 1. Calcolo Vertici
```python
def draw_tile(self, x, z, h1, h2, h3, h4):
def draw_tile(self, x, z, h1, h2, h3, h4, grid_i, grid_j):
# x, z: posizione in griglia
# h1, h2, h3, h4: altezze dei 4 angoli
# grid_i, grid_j: indici griglia per texture unica
corners = [
(x, h1, z), # Angolo 1
@@ -50,24 +51,97 @@ def draw_tile(self, x, z, h1, h2, h3, h4):
]
```
### 2. Faccia Superiore
### 2. Generazione Texture Procedurale
Prima di disegnare, ogni tile genera una texture OpenGL unica:
```python
# Calcola colore medio
avg_height = (h1 + h2 + h3 + h4) / 4.0
color = self.get_color_for_height(avg_height)
# Disegna quad
glBegin(GL_QUADS)
glColor3f(*color) # Applica colore
for corner in corners:
glVertex3f(*corner) # Definisci vertice
glEnd()
def generate_procedural_texture(self, base_color, grid_i, grid_j, texture_size=16):
# Crea array 16×16 pixel
texture_data = np.zeros((16, 16, 3), dtype=np.uint8)
# Offset unico per questo tile
tile_offset_x = grid_i * 1000.0
tile_offset_y = grid_j * 1000.0
for i in range(16):
for j in range(16):
# Coordinate noise con offset tile
i_coord = float(i) / 16 * scale + tile_offset_x
j_coord = float(j) / 16 * scale + tile_offset_y
# 3 layer di Perlin noise
detail = noise.pnoise2(i_coord, j_coord, octaves=3)
pattern = noise.pnoise2(i_coord * 0.5, j_coord * 0.5, octaves=2)
spots = noise.pnoise2(i_coord * 1.5, j_coord * 1.5, octaves=1)
# Combina e applica al colore base
variation = (detail * 0.4 + pattern * 0.6) * 0.25
spot_factor = 0.75 if spots > 0.6 else 1.0
final_color = (base_color + variation) * spot_factor
texture_data[i, j] = final_color * 255
# Crea texture OpenGL
texture_id = glGenTextures(1)
glBindTexture(GL_TEXTURE_2D, texture_id)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST) # Pixelato!
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST)
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 16, 16, 0, GL_RGB, GL_UNSIGNED_BYTE, texture_data)
return texture_id
```
**Risultato**: Faccia superiore della tile colorata.
**Caratteristiche**:
- 16×16 pixel per effetto retro
- GL_NEAREST = nessuna interpolazione → pixel netti
- 3 layer Perlin noise per variazioni naturali
- Offset unico (grid_i, grid_j) = ogni tile diversa
- Macchie scure dove `spots > 0.6`
### 3. Facce Laterali
### 3. Faccia Superiore con Texture
```python
# Ottieni texture unica per questo tile
avg_height = (h1 + h2 + h3 + h4) / 4.0
base_color = self.get_color_for_height(avg_height)
texture_id = self.get_texture_for_tile(base_color, grid_i, grid_j)
# Abilita texturing
glEnable(GL_TEXTURE_2D)
glBindTexture(GL_TEXTURE_2D, texture_id)
glDisable(GL_LIGHTING) # Mostra colori puri texture
glColor3f(1.0, 1.0, 1.0) # Bianco = non tinta la texture
# Disegna quad con coordinate texture
glBegin(GL_QUADS)
glTexCoord2f(0.0, 0.0) # Angolo texture
glVertex3f(*corners[0])
glTexCoord2f(1.0, 0.0)
glVertex3f(*corners[1])
glTexCoord2f(1.0, 1.0)
glVertex3f(*corners[2])
glTexCoord2f(0.0, 1.0)
glVertex3f(*corners[3])
glEnd()
glDisable(GL_TEXTURE_2D)
glEnable(GL_LIGHTING) # Riabilita per facce laterali
```
**Coordinate Texture (UV)**:
```
(0,0)────(1,0)
│ 16×16 │
│ pixel │
(0,1)────(1,1)
```
Ogni angolo del quad mappa un angolo della texture 16×16.
**Risultato**: Faccia superiore con pattern procedurale pixelato unico.
### 4. Facce Laterali (Uniformi)
#### Faccia Destra (X+)