render2d im Browser: WASM/WebGPU-Viewport hinter ?engine=wasm
Integrations-Spike: die native 2D-Engine (src-tauri/render2d) laeuft jetzt als WASM/WebGPU-Canvas in der App-UI, mit derselben Szene (planToRenderScene) und ViewBox wie der WebGL2-Pfad; das SVG-Overlay (Text/Griffe/Auswahl) bleibt drueber. - render2d: neues Feature "web" (wasm-bindgen/web-sys), Fassade WebPlanRenderer (new/set_scene/set_view_box/set_paper_scale/resize/render) auf Canvas-Surface. Geteilte GPU-Schicht (gpu.rs), native Fensterschicht (winit) unberuehrt. - Font: cosmic-text findet auf wasm keine Systemfonts -> Inter-Bytes eingebettet (assets/Inter.ttf), Renderer.load_font + text_family aus der geladenen Familie. - Frontend: useWasmPlanRenderer (gleiche Schnittstelle wie useGlPlanRenderer); PlanView waehlt die Engine per ?engine=wasm + navigator.gpu, sonst WebGL2/SVG. - Build: npm-Script build:engine (wasm-pack, target web -> src/engine/pkg, gitignored). chromium-shell.sh mit WebGPU-Flags (--enable-unsafe-webgpu/Vulkan). - Kompat-Shim: wgpu 22 sendet das spec-entfernte Limit maxInterStageShaderComponents, das neuere Chromium ablehnen -> im Hook vor requestDevice entfernt. Verifiziert: cargo test -p render2d gruen (18), tsc gruen, wasm-Build gruen; Headless-Chromium (?engine=wasm) zeichnet den Grundriss (Waende/Schraffur/ Tuerschwenk/Treppe/Raumtext) im WASM-Viewport, Fallback ohne Flag unveraendert.
This commit is contained in:
+33
-11
@@ -18,6 +18,7 @@ import { docToLines, type SvgLine } from "../text/renderHtml";
|
||||
import type { EdgeGrip, Vec2 } from "../model/types";
|
||||
import type { DraftShape, SnapResult, ToolHandlers, ToolId, ToolMods } from "../tools/types";
|
||||
import { useGlPlanRenderer } from "./useGlPlanRenderer";
|
||||
import { useWasmPlanRenderer } from "./useWasmPlanRenderer";
|
||||
|
||||
const PX_PER_M = 90; // viewBox-Einheiten je Meter (Modell → SVG-Benutzerraum)
|
||||
const PAD = 60; // Rand in viewBox-Einheiten
|
||||
@@ -410,19 +411,40 @@ export const PlanView = forwardRef<PlanViewHandle, PlanViewProps>(
|
||||
const svgRef = useRef<SVGSVGElement | null>(null);
|
||||
const canvasRef = useRef<HTMLCanvasElement | null>(null);
|
||||
|
||||
// WebGL2-GPU-Renderer ist der STANDARD-Pfad. Der SVG-Renderer bleibt als
|
||||
// automatischer Fallback (nur falls WebGL2/Shader nicht verfügbar) — es gibt
|
||||
// KEINE User-Umschaltung mehr. `?gl=0` erzwingt zu Debug-Zwecken reines SVG.
|
||||
const wantGpu =
|
||||
// Engine-Auswahl. STANDARD-Pfad: WebGL2 (useGlPlanRenderer); der SVG-Renderer
|
||||
// bleibt automatischer Fallback (nur falls WebGL2/Shader nicht verfügbar), `?gl=0`
|
||||
// erzwingt reines SVG. INTEGRATIONS-SPIKE: Mit `?engine=wasm` UND vorhandenem
|
||||
// WebGPU (navigator.gpu) übernimmt statt WebGL2 der native render2d-Renderer als
|
||||
// WASM/WebGPU-Viewport (useWasmPlanRenderer) — dieselbe Szene, dieselbe ViewBox,
|
||||
// dasselbe SVG-Overlay (Text/Griffe/Auswahl) darüber. Fehlt WebGPU trotz Flag:
|
||||
// stiller Fallback auf WebGL2 (+ Warnung).
|
||||
const engineParam =
|
||||
typeof window === "undefined"
|
||||
? null
|
||||
: new URLSearchParams(window.location.search).get("engine");
|
||||
const hasWebGpu = typeof navigator !== "undefined" && "gpu" in navigator;
|
||||
const wantWasm = engineParam === "wasm" && hasWebGpu;
|
||||
useEffect(() => {
|
||||
if (engineParam === "wasm" && !hasWebGpu) {
|
||||
console.warn("engine=wasm angefragt, aber navigator.gpu fehlt → WebGL2-Fallback");
|
||||
}
|
||||
}, [engineParam, hasWebGpu]);
|
||||
// WebGL2 nur, wenn NICHT der WASM-Pfad aktiv ist (und `?gl!=0`).
|
||||
const wantGl =
|
||||
!wantWasm &&
|
||||
(typeof window === "undefined"
|
||||
? true
|
||||
: new URLSearchParams(window.location.search).get("gl") !== "0";
|
||||
const { render: renderGl, updateGeometry, ready: glReady } = useGlPlanRenderer(
|
||||
canvasRef,
|
||||
wantGpu,
|
||||
);
|
||||
// GL WIRKLICH aktiv? Steuert das Umschalten SVG↔GL: bei false rendert der volle
|
||||
// SVG-Pfad (Fallback), bei true übernimmt die GL-Ebene + Text-Overlay.
|
||||
: new URLSearchParams(window.location.search).get("gl") !== "0");
|
||||
// Beide Hooks unbedingt aufrufen (Hook-Regeln); je nach Flag ist genau einer aktiv.
|
||||
const glHook = useGlPlanRenderer(canvasRef, wantGl);
|
||||
const wasmHook = useWasmPlanRenderer(canvasRef, wantWasm);
|
||||
const activeEngine = wantWasm ? wasmHook : glHook;
|
||||
const { render: renderGl, updateGeometry, ready: glReady } = activeEngine;
|
||||
// „GPU-Canvas montieren?" — beide GPU-Pfade brauchen das Canvas (an der ABSICHT
|
||||
// montiert, nicht am ready, sonst könnte die Engine mangels Canvas nie starten).
|
||||
const wantGpu = wantGl || wantWasm;
|
||||
// Engine WIRKLICH aktiv? Steuert das Umschalten SVG↔GPU: bei false rendert der
|
||||
// volle SVG-Pfad (Fallback), bei true übernimmt die GPU-Ebene + Text-Overlay.
|
||||
const useGpuRenderer = wantGpu && glReady;
|
||||
|
||||
// Stabiler Papier-Massstab-Nenner N (1:N) als REFERENZ für die Print-Strich-
|
||||
|
||||
Reference in New Issue
Block a user