Luca Perullo
Components

Component

LiveNew

Blob Mixer

Una versione full-R3F del demo blobmixer.14islands cucita addosso a Next 16 + drei + postprocessing. La superficie è un'icosfera 128-suddivisioni dispostata in vertex shader; le normali sono ricalcolate analiticamente per frame, così trasmissione, iridescenza, clearcoat e sheen restano coerenti. Switching dei preset = lerp simultaneo di ogni proprietà PBR + shape uniform + bloom intensity.

3DShaderWebGLR3FPostprocessing
Open in ClaudeSorgente

Esempio01

scene.client.tsx
Chrome

Note Pesante ma stabile — sull'integrato Apple M-class regge 60fps anche a detail=128. In compact (catalog tile) detail scende a 64 e il post-processing è disattivato. La rail di swatch è interna alla scena: cliccare un swatch innesca il lerp di tutte le proprietà del materiale in ~250ms (half-life), stesso easing del sito originale.

Prompt LLM02

Incolla in Claude o ChatGPT per generare la tua variante. Include il contesto del brand, i token e i vincoli del progetto.

Prompt · blob-mixer
Open in Claude
Sei un senior frontend engineer. Stai lavorando su un sito Next.js 16 + React 19 + Tailwind v4 in italiano, look chanhdai-inspired: colonna stretta 672px, Geist Sans + Geist Mono, hairline 1px, divisori a stripe diagonale, palette zinc.

Token CSS disponibili: --bg, --bg-alt, --fg, --fg-muted, --fg-soft, --border, --border-strong, --accent. Usa SEMPRE queste variabili tramite le utility tailwind generate (bg-bg, text-fg-muted, border-border, ecc.). Helper "cn" da "@/lib/utils". Niente librerie UI extra: solo lucide-react e tailwind-merge.

Genera un componente <BlobMixerScene> in React Three Fiber, replica del demo blobmixer.14islands.com adattata al portfolio.

Architettura (file separati in src/components/blob-mixer/):
- shaders.ts → 3D simplex noise (Ashima/Gustavson) + funzione blobField (3 ottave + breathe pulse + chaos detail) + displacePosition con pointer dent. Esporta noiseGLSL e vertexInjection (chunk da iniettare in #include <begin_vertex>).
- presets.ts → 12 preset (Chrome, Gold, Glass, Soap Bubble, Pearl, Plasma, Lava, Jelly, Wax, Hologram, Ink, Candy). Ogni preset ha: material{color, metalness, roughness, envMapIntensity, clearcoat, clearcoatRoughness, iridescence, iridescenceIOR, iridescenceThicknessRange, sheen, sheenColor, sheenRoughness, transmission, thickness, ior, attenuationColor, attenuationDistance, specularIntensity, opacity, transparent}, shape{noiseScale, noiseSpeed, displace, roundness, pulse, chaos}, core{visible, intensity, colorA, colorB}, bloom, swatch (CSS gradient), bg, accent.
- blob.tsx → "use client", componente <Blob presetId detail/>. useMemo crea MeshPhysicalMaterial UNA volta + setta onBeforeCompile prima del primo render: Object.assign(shader.uniforms, customUniforms); injetta noiseGLSL prima di "void main() {" e vertexInjection dopo "#include <begin_vertex>". useFrame ogni frame: lerpa tutte le NUMERIC_MAT_KEYS, COLOR_MAT_KEYS via THREE.Color.lerp, iridescenceThicknessRange come tupla, e tutte le shape uniforms; k = 1 - exp(-dt * 4.5) per ottenere ~250ms half-life framerate-independent. Mesh secondaria additive-blended (core glow) per plasma/lava. Pointer pickup via raycaster su un piano facing-camera attraverso l'origine.
- env.tsx → DarkStudioEnv: bake PMREM custom con 3 area lights (warm key, cool fill, magenta rim, top stripe) + backdrop sphere a gradient. Niente HDR esterno.
- background.tsx → sfera back-side con gradient radiale che lerpa il colore del preset attivo.
- scene.client.tsx → "use client", <BlobMixerScene compact?> wrapper: Canvas (dpr [1,2], ACES, exposure 0.85, fov 32, camera Z=4.2). Bambini: <DarkStudioEnv/>, <Background/>, 3 directionalLight (warm/cool/rim), <Blob/>, <EffectComposer> con <Bloom> (intensity tweenata via useFrame), ChromaticAberration, Vignette, ToneMapping ACES. Compact mode: detail=64, no postproc, fov 28, camera Z=4.6. Overlay: rail floating verticale di swatch a sinistra (o destra in compact), HUD bottom-center con preset name.

Vincoli:
- Usa SOLO le librerie già installate: three, @react-three/fiber, @react-three/drei (PerspectiveCamera), @react-three/postprocessing (EffectComposer, Bloom, ChromaticAberration, Vignette, ToneMapping), postprocessing (BlendFunction, ToneMappingMode).
- Token CSS del progetto per la chrome (rail, HUD): bg/45 black + border-white/10 + backdrop-blur-md.
- Niente GSAP, niente zustand: lerp ogni frame con dt-aware easing, stato React solo per presetId.
- onBeforeCompile assegnato dentro useMemo che crea il materiale (non in useEffect): garantisce sia attivo prima della prima compile.
- frustumCulled={false} sul mesh: il displacement lo allarga oltre il bounding di base.

Output: 6 file completi nella struttura sopra, pronti da incollare.

Uso tipico03

tsx
import { BlobMixerScene } from "@/components/blob-mixer";

<BlobMixerScene className="h-[70vh]" initialPreset="plasma" />

Dipendenze04

npm
  • @react-three/fiber
  • @react-three/drei
  • @react-three/postprocessing
  • three
Interno
  • @/lib/utils#cn
  • src/components/blob-mixer/{shaders,presets,blob,env,background,scene.client}.{ts,tsx}

Ti è servito? Dimmelo, oppure proponi il prossimo componente.