# SPIKE — Bild-Texturen in `render3d` (`RenderStyle::Textured` real machen)

Stand: 2026-07-05. **Auftrag/Übergabe für einen Agenten. Kleinster ehrlicher
Durchstich — kein Produktfeature, keine Integration.**

Ziel: Beweisen, dass der bestehende wgpu-3D-Renderer echte **Bild-Texturen** auf
Wandflächen darstellen kann, sichtbar im `spike3d`-Fenster. Am Ende steht eine
belastbare Aussage, wie viel Arbeit „richtig gutes texturiertes 3D" wirklich ist —
statt Spekulation.

---

## 0. Ausgangslage (verifiziert am 2026-07-05)

- `render3d` ist **kein** Three.js-Wrapper, sondern ein eigenständiger wgpu-Renderer
  (~6400 LOC): echte GPU-Pipeline (wgpu 29), Tiefenpuffer, MSAA, WGSL-Shader.
  Läuft nativ (winit-Spike), headless (naga-validiert) und im Browser (WebGPU).
- **`RenderStyle::Textured` existiert bereits als Stub** (`gpu.rs:34` Enum-Variante,
  `gpu.rs:47` Parse aus `"textured"`) — es gibt aber **kein echtes Texturing**:
  kein Sampler, keine Textur-Bind-Group, keine Bilddaten.
- Die `cap_pipeline` mit Layout `[pos vec3, uv vec2]` + `CAP_WGSL` ist **nicht** für
  Bildtexturen, sondern für die **Schnittflächen-Kappen** (prozedurale Schraffur);
  die UVs steuern dort den Schraffur-Abstand. **Nicht damit verwechseln.**
- **Günstig für uns:** Die Muster, die der Spike braucht, existieren schon —
  ein UV-tragendes Vertex-Layout und eine zweite/dritte Pipeline, die sich die
  `Globals`-Bind-Group teilt (`grid`, `cap`). Der texturierte Mesh-Pfad reiht sich
  1:1 in dieses Muster ein.

---

## 1. Echte Symbole — vor dem Coding lesen

| Was | Ort |
|---|---|
| Vertex heute interleaved `[pos.xyz, normal.xyz, color.rgb]`, `FLOATS_PER_VERTEX`, `Mesh`-Struct | `src-tauri/render3d/src/types.rs:322` ff. |
| Quad-Emitter (Normale + Farbe je Vertex, Reihenfolge `(0,1,2)+(0,2,3)`) | `src-tauri/render3d/src/mesh.rs:886` |
| Wand-Extrusion / Mesh-Bau | `src-tauri/render3d/src/mesh.rs` — `extrude_wall` (`:91`), `build_walls_mesh` (`:911`) |
| Haupt-Pipeline + `Globals`-Bind-Group (group 0) | `src-tauri/render3d/src/gpu.rs:232`–`:320` |
| Vorlage „zweite Pipeline teilt sich Globals" — Grid | `src-tauri/render3d/src/gpu.rs:329` |
| Vorlage „Pipeline mit UV-Layout `[pos vec3, uv vec2]`" — Cap | `src-tauri/render3d/src/gpu.rs:408` |
| `RenderStyle`-Enum + Stub `Textured` | `src-tauri/render3d/src/gpu.rs:34`, `:47` |
| Pipeline-Bindung im Render-Pass (Muster für Stil-Umschaltung) | `src-tauri/render3d/src/gpu.rs:847` |
| Shader als WGSL-Konstanten (`MESH_WGSL`, `CAP_WGSL`) | `src-tauri/render3d/src/shaders.rs` |
| Beleuchtungsmodell (hemisphärisch + Directional + Fill) — Doku | `src-tauri/render3d/src/shaders.rs:1`–`40` |
| naga-WGSL-Validierung headless (Test-Vorlage) | `src-tauri/render3d/src/lib.rs:924` (`cap_module`) |
| Fenster-Spike mit Orbit-Kamera | `src-tauri/render3d/src/bin/spike3d.rs` |

---

## 2. Umfang — exakt das, nicht mehr

### 2.1 UVs auf Wandflächen
- In der Quad-Emitter-Funktion (`mesh.rs:886`) je Vertex eine **UV** berechnen:
  planare Projektion in **Metern** — `u` = Distanz entlang der Wandachse,
  `v` = Höhe (z). Textur-Raster damit weltmassstäblich (z. B. 1 Kachel = 1 m).
- Den bestehenden `[pos, normal, color]`-Pfad **bitgleich unangetastet** lassen.
  Zwei zulässige Wege (Agent wählt begründet):
  1. **Separates additives UV-Array** in `Mesh` (Default leer/None), oder
  2. **Paralleler `build_walls_mesh_textured`** → interleaved
     `[pos.xyz, normal.xyz, uv.xy]`.
- Regressionstests für den Alt-Pfad müssen grün bleiben (siehe §4).

### 2.2 Test-Textur prozedural (kein Asset, keine `image`-Crate)
- Ein **256×256 RGBA-Schachbrett/Grid im Code** generieren (`Vec<u8>`).
- `device.create_texture` + `queue.write_texture` + `Sampler`
  (`FilterMode::Linear`, `AddressMode::Repeat`). Mipmaps optional (nice-to-have für
  flache Blickwinkel; kein Muss für den Spike).
- Selbstständig, damit der Spike ohne Dateipfade/Asset-Pipeline läuft.

### 2.3 Textur-Bind-Group (group 1)
- Neue Bind-Group-Layout mit `texture_view` (`TextureSampleType::Float`) +
  `sampler`. **`Globals` bleibt group 0** und unverändert.

### 2.4 Textured-Pipeline + WGSL (`MESH_TEXTURED_WGSL`)
- Vertex-Layout `[pos vec3, normal vec3, uv vec2]`, `TriangleList`.
- **Dieselbe Beleuchtung wie `MESH_WGSL`** (hemisphärisches Ambient + Directional +
  Fill) — nur **Albedo = `textureSample(tex, samp, uv)`** statt Vertex-Farbe.
- Depth-Format, MSAA (`SAMPLE_COUNT`) und Color-Target **identisch** zur
  Haupt-Pipeline (sonst inkompatibler Render-Pass).
- Pipeline-Layout bindet group 0 (Globals) **und** group 1 (Textur).

### 2.5 Verdrahten
- Bei `RenderStyle::Textured` im Render-Pass die neue Pipeline + beide Bind-Groups
  setzen (Muster: `cap_pipeline`-Bindung bei `gpu.rs:847`).

### 2.6 Spike sichtbar machen
- `spike3d.rs` so erweitern, dass der Stil auf `Textured` schaltbar ist
  (Tastendruck, z. B. `T`, **oder** Startkonstante). Die Demo-Wände sollen
  texturiert im Orbit erscheinen.

---

## 3. Randbedingungen (hart)

- **Nur** die `render3d`-Crate. `src/web.rs` und die Tauri-/`native3d`-Oberfläche
  **nicht** anfassen.
- Feature-gegatet unter dem bestehenden `render`/`window`-Feature.
  **Default-Build und Default-Darstellung bleiben unverändert.**
- **Keine neuen Dependencies** (insbesondere **kein `image`-Crate**) für den Spike.
- Term-/Reihenfolge-sensible Geometrie (Parität) wird **nicht** berührt — es kommt
  nur additiv ein UV-Kanal + ein zweiter Render-Pfad dazu.
- Kommentar-Stil und Sprache (Deutsch, ausführliche Begründungs-Kommentare) wie im
  umgebenden Code beibehalten.

---

## 4. Akzeptanz / Verifikation

1. `cargo test` (im Crate-Verzeichnis `src-tauri/render3d`) **grün**, inklusive:
   - bestehende Mesh-Regression (Alt-Pfad `[pos,normal,color]` unverändert),
   - **neuer naga-Validierungstest** für `MESH_TEXTURED_WGSL` (Vorlage:
     `lib.rs:924`).
2. `cargo run --features window --bin spike3d` zeigt die Demo-Wände mit
   **erkennbarer, korrekt gemappter** Schachbrett-Textur:
   - Raster weltmassstäblich (in Metern), keine Verzerrung an Gehrungen/Ecken,
   - beleuchtet wie im Shaded-Modus (Volumen bleibt ablesbar).
3. Umschalten Shaded ↔ Textured zur Laufzeit (oder per Startkonstante) funktioniert
   ohne Re-Meshing-Crash.

---

## 5. Abschlussbericht (vom Agenten am Ende zu liefern)

- Welche Dateien geändert/hinzugefügt wurden und warum.
- Wie die UVs projiziert werden (Achswahl, Massstab, Verhalten an Gehrungen).
- Welcher der beiden UV-Wege (§2.1) gewählt wurde und weshalb.
- **Ehrliche Lückenliste für „richtig gutes" Texturing:** Asset-/Bild-Datei-Laden,
  Material→Textur-Zuordnung (Wandtyp/Layer → Material), Normal-/Roughness-Maps
  (PBR), anisotropes Filtern + Mipmaps, Web-Pfad (`web.rs`/WebGPU), UI zum
  Zuweisen. Grobschätzung Aufwand je Punkt.

---

## 6. Nicht im Scope

Asset-/Bild-Datei-Laden · Material-System · mehrere Texturen gleichzeitig ·
PBR/Normal-Maps · Web-Pfad (`web.rs`) · jegliche UI · Anbindung unter die Webview.
