import '../../../../src/styles.css' import { ACESFilmicToneMapping, Color, PerspectiveCamera, Scene, SRGBColorSpace, Timer, } from 'three' import { RenderPipeline, WebGPURenderer } from 'three/webgpu' import { pass, uniform } from 'three/tsl' import { attachPointerSplats, FluidSimulation, fluidOverlay, simpleDistortion, } from 'three-fluid-fx/tsl' import { DomTextPlane } from '../../../extras/text/DomTextPlane' import { asNode, asTsl, setPipelineOutput, type UniformValue } from '../../shared/nodeInterop' const stage = document.getElementById('stage') if (!(stage instanceof HTMLElement)) throw new Error('Missing #stage') if (typeof navigator === 'undefined' || !('gpu' in navigator)) { stage.textContent = 'WebGPU is not available in this browser. The TSL example needs a WebGPU-capable browser.' throw new Error('WebGPU unavailable') } const CAMERA_FOV = 45 const CAMERA_Z = 6.4 const FIXED_FLUID_DT = 1 / 60 const MAX_FLUID_SUBSTEPS = 4 const styleElement = document.createElement('style') styleElement.textContent = ` .minimal-fluid-text-copy { position: absolute; inset: 0; z-index: 1; box-sizing: border-box; display: grid; align-content: center; justify-items: center; gap: 14px; padding: 80px 28px; text-align: center; color: #f3f0e8; pointer-events: none; } .minimal-fluid-text-copy p { margin: 0; } .minimal-fluid-text-kicker { color: #ff7a5f; font-size: 11px; font-weight: 800; line-height: 1; letter-spacing: 0; text-transform: uppercase; } .minimal-fluid-text-copy h2 { width: min(760px, 86vw); margin: 0; color: #f3f0e8; font-size: clamp(52px, 10vw, 116px); font-weight: 820; line-height: 0.88; letter-spacing: 0; text-wrap: balance; } .minimal-fluid-text-lead { width: min(560px, 76vw); color: rgba(243, 240, 232, 0.72); font-size: clamp(16px, 2vw, 22px); line-height: 1.42; letter-spacing: 0; } .minimal-fluid-text-copy.is-synced .minimal-fluid-text-kicker, .minimal-fluid-text-copy.is-synced h2, .minimal-fluid-text-copy.is-synced .minimal-fluid-text-lead { color: transparent; -webkit-text-fill-color: transparent; } @media (max-width: 720px) { .minimal-fluid-text-copy { gap: 12px; padding-inline: 22px; } .minimal-fluid-text-copy h2 { width: min(520px, 92vw); font-size: clamp(48px, 16vw, 82px); } .minimal-fluid-text-lead { width: min(520px, 86vw); } } ` document.head.appendChild(styleElement) const renderer = new WebGPURenderer({ antialias: true, forceWebGL: false }) renderer.outputColorSpace = SRGBColorSpace renderer.toneMapping = ACESFilmicToneMapping renderer.toneMappingExposure = 1 renderer.setClearColor(new Color('#07080b'), 1) renderer.domElement.style.position = 'absolute' renderer.domElement.style.inset = '0' stage.appendChild(renderer.domElement) const textRoot = document.createElement('div') textRoot.className = 'minimal-fluid-text-copy' textRoot.innerHTML = `
THREE-FLUID-FX
Live type, bent by fluid.
` stage.appendChild(textRoot) await renderer.init() if ('fonts' in document) { await document.fonts.ready } const scene = new Scene() const camera = new PerspectiveCamera(CAMERA_FOV, 1, 0.1, 100) camera.position.set(0, 0, CAMERA_Z) camera.updateMatrixWorld(true) const textElements = Array.from( textRoot.querySelectorAll