# 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`). - `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.