From a46640bfb656f34f5259006fdd16ed6ab5e61c4a Mon Sep 17 00:00:00 2001 From: Victor Giers Date: Mon, 6 Apr 2026 20:54:05 +0200 Subject: [PATCH] Add underwater effect to RunnerCanvas and update WebGL rendering check --- src/app/app.css | 16 ++++++++++++++++ src/runner-web/RunnerCanvas.tsx | 22 ++++++++++------------ 2 files changed, 26 insertions(+), 12 deletions(-) diff --git a/src/app/app.css b/src/app/app.css index a671bf3a..fbf47f65 100644 --- a/src/app/app.css +++ b/src/app/app.css @@ -1163,6 +1163,22 @@ button:disabled { border-radius: 999px; } +.runner-canvas--underwater { + box-shadow: inset 0 0 0 9999px rgba(9, 38, 62, 0.08); +} + +.runner-canvas__underwater { + position: absolute; + inset: 0; + z-index: 2; + pointer-events: none; + background: + radial-gradient(circle at 50% 18%, rgba(146, 223, 255, 0.2), transparent 42%), + linear-gradient(180deg, rgba(38, 113, 153, 0.16), rgba(8, 40, 63, 0.42)); + backdrop-filter: blur(1.5px) saturate(1.08); + mix-blend-mode: screen; +} + .runner-canvas__prompt { position: absolute; left: 50%; diff --git a/src/runner-web/RunnerCanvas.tsx b/src/runner-web/RunnerCanvas.tsx index 8e1c5ff4..e4bbdf9c 100644 --- a/src/runner-web/RunnerCanvas.tsx +++ b/src/runner-web/RunnerCanvas.tsx @@ -37,6 +37,7 @@ export function RunnerCanvas({ const hostRef = useRef(null); const [runnerMessage, setRunnerMessage] = useState(null); const [interactionPrompt, setInteractionPrompt] = useState(null); + const [firstPersonTelemetry, setFirstPersonTelemetry] = useState(null); useEffect(() => { const container = containerRef.current; @@ -45,30 +46,26 @@ export function RunnerCanvas({ return; } - const testCanvas = document.createElement("canvas"); - const hasWebGl = - testCanvas.getContext("webgl2") !== null || - testCanvas.getContext("webgl") !== null || - testCanvas.getContext("experimental-webgl") !== null; - try { const runtimeHost = new RuntimeHost({ - enableRendering: hasWebGl + enableRendering: true }); hostRef.current = runtimeHost; runtimeHost.mount(container); runtimeHost.setRuntimeMessageHandler(onRuntimeMessageChange); - runtimeHost.setFirstPersonTelemetryHandler(onFirstPersonTelemetryChange); + runtimeHost.setFirstPersonTelemetryHandler((telemetry) => { + setFirstPersonTelemetry(telemetry); + onFirstPersonTelemetryChange(telemetry); + }); runtimeHost.setInteractionPromptHandler((prompt) => { setInteractionPrompt(prompt); onInteractionPromptChange(prompt); }); - setRunnerMessage( - hasWebGl ? null : "WebGL is unavailable in this browser environment. The runner shell is visible, but runtime rendering is disabled." - ); + setRunnerMessage(null); return () => { onInteractionPromptChange(null); + setFirstPersonTelemetry(null); runtimeHost.dispose(); hostRef.current = null; }; @@ -95,7 +92,7 @@ export function RunnerCanvas({ return (
+ {navigationMode === "firstPerson" && firstPersonTelemetry?.inWaterVolume ?