30-04-2026

This commit is contained in:
Kevin Adametz 2026-04-30 14:54:39 +02:00
parent 761b1156c1
commit d054732bf5
35 changed files with 2796 additions and 505 deletions

View file

@ -0,0 +1,200 @@
# Verbesserungsvorschläge: floating-lines.js
Analyse von `floating-lines.js` (Dev-Klasse) im Vergleich zur produktiven `FloatingLines.vue`.
**Stand: April 2026 — alle wesentlichen Punkte umgesetzt.**
---
## Was der Code macht (Kurzübersicht)
Ein WebGL-Fullscreen-Shader via Three.js mit drei visuellen Schichten:
- **Top/Bottom**: Einfache Sinus-Wellen mit Rotation (`wave()`)
- **Middle**: Bézier-Kurven zwischen Kontrollpunkten mit animierten Fächer-Linien (`waveFocal()`) + Kreise an den Punkten
- **Hintergrund**: Radialer Verlauf von Mitte → Rand (oder Horizont-Split bei Modus „Trennung")
---
## Fehler / Bugs
### 1. Totes Uniform `bgColor` ✅ Umgesetzt
**Datei:** `floating-lines.js`, Zeile 508
Das tote `bgColor`-Uniform wurde entfernt. Der Shader nutzt ausschließlich `bgColorCenter` + `bgColorEdge`.
```js
// Entfernt:
bgColor: { value: new Vector3(0, 0, 0) },
```
### 2. Konstruktor-Parameter `middleWavePosition` wird ignoriert ✅ Umgesetzt
Der ungenutzte Parameter wurde aus der Konstruktorsignatur entfernt.
### 3. Kein Konstruktor-Interface für `bgColorCenter` / `bgColorEdge` ✅ Umgesetzt
Beide Uniforms sind jetzt als Konstruktor-Parameter verfügbar und werden korrekt initialisiert:
```js
constructor({ ..., bgColorCenter = '#0a0514', bgColorEdge = '#000000', ... })
```
Die Uniforms werden beim Konstruktoraufruf aus den Hex-Strings in `Vector3`-Werte konvertiert.
---
## Performance-Problem
### 4. `bezierClosestT` wird pro Linie neu berechnet (kritisch) ✅ Umgesetzt
`bezierClosestT` wird jetzt **einmal pro Segment** berechnet. Die Ergebnisse (`bt`, `bPos`, `bNorm`) werden als Parameter an `waveFocal()` übergeben:
```glsl
// Neue waveFocal()-Signatur (precomputed values):
float waveFocal(vec2 uv, float fi, float totalLines, float t, vec2 bPos, vec2 bNorm)
// Im Segment-Loop (einmal pro Segment, nicht pro Linie):
float bt = bezierClosestT(baseUv, sp, pc, ep);
vec2 bPos = bmt*bmt*sp + 2.0*bmt*bt*pc + bt*bt*ep;
vec2 bTang = normalize(2.0*bmt*(pc - sp) + 2.0*bt*(ep - pc));
vec2 bNorm = vec2(-bTang.y, bTang.x);
// → alle middleLineCount Aufrufe nutzen dieselben Werte
```
Reduktion von O(Segmente × Linien) auf O(Segmente) `bezierClosestT`-Aufrufe pro Pixel.
---
## Fehlende Features (in `.vue` vorhanden, in `.js` nicht)
### 5. `lineBrightness` Uniform fehlt ✅ Umgesetzt
`lineBrightness` ist jetzt als Konstruktor-Parameter und Uniform vorhanden. Im Shader:
```glsl
col *= lineBrightness; // vor Background-Composite
```
### 6. Kein Pause bei verstecktem Tab ✅ Umgesetzt
Der `requestAnimationFrame`-Loop pausiert jetzt bei `document.hidden`:
```js
this._handleVisibility = () => {
if (document.hidden) {
cancelAnimationFrame(this.raf)
this.raf = 0
} else if (!this.raf) {
renderLoop()
}
}
document.addEventListener('visibilitychange', this._handleVisibility)
// destroy() ruft removeEventListener auf
```
### 7. Kein adaptives DPR ⏭️ Offen / Optional
Die Vue-Version misst FPS live und reduziert `devicePixelRatio` bei schlechter Performance (vor allem Mobile). Die Dev-Klasse ist ein Test-Tool und nicht für Mobile ausgelegt — diese Komplexität lohnt sich hier nicht.
---
## Code-Qualität
### 8. Legacy-Code: `background_color()`, `BLACK`, `PINK`, `BLUE` ✅ Umgesetzt
Die Shader-Konstanten `BLACK`, `PINK`, `BLUE` und die Funktion `background_color()` wurden entfernt. Der Hintergrund wird immer über `bgColorCenter`/`bgColorEdge` gesteuert.
### 9. Redundante `enabledWaves.includes()` Checks ✅ Umgesetzt
Die doppelten Prüfungen in den Hilfsfunktionen wurden entfernt. Die äußere Prüfung im Aufrufer ist die einzige Guard.
### 10. Hardcoded `* 0.5` in `getLineColor()` ✅ Umgesetzt
Der feste `* 0.5`-Faktor wurde entfernt. `getLineColor()` gibt jetzt die volle Gradient-Farbe zurück. Die Kompensation mit `* 2.5` an den Kreisen wurde auf `* 1.5` angepasst. Die Helligkeit wird über das `lineBrightness`-Uniform gesteuert (→ Punkt 5).
---
## Optionale Verbesserungen / Ideen
### 11. Glättere Kreise bei höherem DPR ⏭️ Offen / Optional
Der AA-Radius passt sich durch `iResolution` (physische Pixel bei gesetztem DPR) bereits implizit an. Keine Änderung nötig.
### 12. `pointSpacingX` + `pointsOffsetX` vs. explizite X-Koordinaten ⏭️ Offen / Optional
Die Dev-Klasse behält das Auto-Spacing-Modell für einfache Testzwecke. Die Vue-Komponente nutzt explizite X-Koordinaten für die Lebenszeitlinie. Beide Ansätze sind intentional verschieden.
### 13. GLSL `precision highp``mediump` ✅ Umgesetzt
Fragment-Shader nutzt jetzt `precision mediump float` — ausreichend für diese Visualisierung, effizienter auf Mobile/Low-End.
---
## Neue Punkte (nachträglich ergänzt)
### 14. Resize-Bug: Kreise und Linien desynchronisieren sich ✅ Umgesetzt
**Betrifft:** `LifeWaveLayout.vue`
**Ursache:** `layoutResizeObserver` aktualisierte `layoutWidth/Height` sofort, während `TimelineView`s `@view-update` (mit den neuen CSS-Event-Positionen) erst im nächsten Frame kam — führte zu 1-Frame UV-Desync.
**Fix:** `requestAnimationFrame`-Wrapper im Callback:
```js
layoutResizeObserver = new ResizeObserver(() => {
requestAnimationFrame(() => {
if (!layoutRef.value) return
layoutWidth.value = layoutRef.value.clientWidth
layoutHeight.value = layoutRef.value.clientHeight
})
})
```
### 15. Feature: Horizont ✅ Umgesetzt (erweitert)
Statt einer einzelnen Linie wurden **drei wählbare Horizont-Modi** implementiert:
| Modus | Wert | Beschreibung |
|-------|------|--------------|
| Aus | `'off'` | Kein Horizont-Effekt |
| Nebel | `'fog'` | Leuchtender Band-Effekt auf Y=0, Farbe aus Gradient |
| Trennung | `'split'` | Hintergrund wird vertikal geteilt: `bgColorCenter` oben, `bgColorEdge` unten — mit einstellbarer Blend-Breite |
| Glow | `'glow'` | Weiches + hartes Leuchten auf dem Horizont, Farbe aus Gradient |
**Shader (alle Modi):**
```glsl
uniform int horizonMode; // 0=off 1=fog 2=split 3=glow
uniform float horizonOpacity;
uniform float horizonBlend;
if (horizonMode == 1) {
float band = exp(-baseUv.y * baseUv.y * 5.0);
vec3 fogColor = getLineColor(0.5, bg) * 2.0;
col += fogColor * band * horizonOpacity;
} else if (horizonMode == 2) {
float blendW = max(horizonBlend * 0.7, 0.001);
float t = smoothstep(-blendW, blendW, baseUv.y);
bg = mix(bgColorEdge, bgColorCenter, t);
} else if (horizonMode == 3) {
float d2 = baseUv.y * baseUv.y;
float softGlow = exp(-d2 * 10.0);
float coreGlow = exp(-d2 * 70.0) * 0.7;
vec3 glowColor = getLineColor(0.5, bg) * 3.0;
col += glowColor * (softGlow + coreGlow) * horizonOpacity;
}
```
**Umgesetzt in:**
- `floating-lines.js` — Shader + Konstruktor-Parameter + Uniforms
- `FloatingLines.vue` — Shader (mit `gradientMid()` Hilfsfunktion) + Props + Uniforms + Watches
- `settings.js``horizonMode: 'off'`, `horizonOpacity: 0.5`, `horizonBlend: 0.2`
- `LifeWaveSettings.vue` — Segmented Control + bedingte Slider (Deckkraft / Übergang)
- `LifeWaveLayout.vue` — Props weitergeleitet
- `init-fl.html` — 4 Modus-Buttons + bedingte Slider-Sichtbarkeit
---
## Zusammenfassung Prioritäten
| # | Typ | Priorität | Aufwand | Status |
|---|-----|-----------|---------|--------|
| 4 | Performance: `bezierClosestT` Hoisting | **Hoch** | Mittel | ✅ |
| 14 | Bug: Resize-Desync (LifeWaveLayout) | **Hoch** | Minimal | ✅ |
| 1 | Bug: totes `bgColor` Uniform | Mittel | Minimal | ✅ |
| 3 | Bug: `bgColorCenter/Edge` nicht setzbar | Mittel | Klein | ✅ |
| 5 | Feature: `lineBrightness` | Mittel | Klein | ✅ |
| 10 | Qualität: hardcoded `* 0.5` | Mittel | Klein | ✅ |
| 15 | Feature: Horizont (3 Modi) | Mittel | Mittel | ✅ |
| 8 | Qualität: Legacy-Code entfernen | Niedrig | Klein | ✅ |
| 6 | Feature: Tab-Pause | Niedrig | Klein | ✅ |
| 2 | Bug: ignorierter Parameter | Niedrig | Minimal | ✅ |
| 9 | Qualität: redundante Checks | Niedrig | Minimal | ✅ |
| 13 | Perf: `mediump` Precision | Optional | Minimal | ✅ |
| 7 | Feature: adaptives DPR | Optional | Groß | ⏭️ |
| 11 | Qualität: AA-Radius explizit | Optional | Minimal | ⏭️ |
| 12 | API: explizite X-Koordinaten | Optional | Mittel | ⏭️ |