1+ /**
2+ * Fluid Waterfall preset — spiral/fluid text effect with iridescence and distortion.
3+ */
14import React , { useRef , useMemo , useEffect } from "react" ;
25import tgpu from "typegpu" ;
36import * as d from "typegpu/data" ;
@@ -20,7 +23,11 @@ import { collectUniformControls, type PresetMeta } from "./types";
2023// Everything is packed into ONE WGSL struct → ONE GPU buffer → no WebGPU limit issues.
2124const U = defineUniforms ( {
2225 // --- interaction ---
23- mouseUV : { schema : d . vec2f , value : d . vec2f ( - 2 , - 2 ) , control : { editable : false } } ,
26+ mouseUV : {
27+ schema : d . vec2f ,
28+ value : d . vec2f ( - 2 , - 2 ) ,
29+ control : { editable : false } ,
30+ } ,
2431 time : { schema : d . f32 , value : 0 , control : { editable : false } } ,
2532
2633 // --- SPIRAL_* controls global swirl shape, speed, and micro-perturbation ---
@@ -168,9 +175,9 @@ const U = defineUniforms({
168175 // --- SDF_* and AA_* control edge extraction and antialias softening ---
169176 SDF_ALPHA_EDGE_MAX : { schema : d . f32 , value : 100.0 } ,
170177 SDF_ALPHA_EDGE_OFFSET : { schema : d . f32 , value : 40.0 } ,
171- AA_FWIDTH_SCALE : { schema : d . f32 , value : 1.5 } ,
178+ AA_FWIDTH_SCALE : { schema : d . f32 , value : 1.0 } ,
172179
173- // --- COLOR_* defines the waterfall palette ---
180+ // --- COLOR_* defines the fluid waterfall palette ---
174181 COLOR_PRIMARY : { schema : d . vec4f , value : d . vec4f ( 0.871 , 0.267 , 0.231 , 1.0 ) } ,
175182 COLOR_SECONDARY : { schema : d . vec4f , value : d . vec4f ( 0.4 , 0.0 , 0.706 , 1.0 ) } ,
176183 COLOR_TERTIARY : {
@@ -179,7 +186,7 @@ const U = defineUniforms({
179186 } ,
180187} ) ;
181188
182- const waterFragment = tgpu [ "~unstable" ] . fragmentFn ( {
189+ const fluidWaterfallFragment = tgpu [ "~unstable" ] . fragmentFn ( {
183190 in : { uv : d . vec2f } ,
184191 out : d . vec4f ,
185192} ) ( ( { uv } ) => {
@@ -237,10 +244,7 @@ const waterFragment = tgpu["~unstable"].fragmentFn({
237244 u . PAINT_CONTRAST_OFFSET ;
238245 const paintRes = std . min (
239246 u . PAINT_MAX_RES ,
240- std . max (
241- d . f32 ( 0.0 ) ,
242- std . length ( uvSpiral ) * u . PAINT_RES_SCALE * contrastMod ,
243- ) ,
247+ std . max ( d . f32 ( 0.0 ) , std . length ( uvSpiral ) * u . PAINT_RES_SCALE * contrastMod ) ,
244248 ) ;
245249 const circleSharpness = u . PAINT_CIRCLE_SHARPNESS ;
246250 const c1p = std . max (
@@ -282,12 +286,20 @@ const waterFragment = tgpu["~unstable"].fragmentFn({
282286 u . IRIDESCENCE_BLEND23_END ,
283287 tSmooth ,
284288 ) ;
285- const blend31 = std . smoothstep ( u . IRIDESCENCE_BLEND31_START , d . f32 ( 1.0 ) , tSmooth ) ;
289+ const blend31 = std . smoothstep (
290+ u . IRIDESCENCE_BLEND31_START ,
291+ d . f32 ( 1.0 ) ,
292+ tSmooth ,
293+ ) ;
286294 const colorPrimary = u . COLOR_PRIMARY ;
287295 const colorSecondary = u . COLOR_SECONDARY ;
288296 const colorTertiary = u . COLOR_TERTIARY ;
289297 const iridescent = std . mix (
290- std . mix ( std . mix ( colorPrimary , colorSecondary , blend12 ) , colorTertiary , blend23 ) ,
298+ std . mix (
299+ std . mix ( colorPrimary , colorSecondary , blend12 ) ,
300+ colorTertiary ,
301+ blend23 ,
302+ ) ,
291303 colorPrimary ,
292304 blend31 ,
293305 ) ;
@@ -298,10 +310,7 @@ const waterFragment = tgpu["~unstable"].fragmentFn({
298310 const c3pVec = d
299311 . vec4f ( colorTertiary . x , colorTertiary . y , colorTertiary . z , colorPrimary . w )
300312 . mul ( c3p ) ;
301- const blend = colorPrimary
302- . mul ( c1p )
303- . add ( colorSecondary . mul ( c2p ) )
304- . add ( c3pVec ) ;
313+ const blend = colorPrimary . mul ( c1p ) . add ( colorSecondary . mul ( c2p ) ) . add ( c3pVec ) ;
305314 const baseColor = colorPrimary
306315 . mul ( contrastFactor )
307316 . add ( blend . mul ( oneMinusCf ) )
@@ -313,7 +322,10 @@ const waterFragment = tgpu["~unstable"].fragmentFn({
313322 const noiseScale = u . DISTORTION_NOISE_SCALE ;
314323 const noisePos = uv . mul ( noiseScale ) ;
315324
316- const timeOffset = d . vec2f ( d . f32 ( 0.0 ) , time * u . DISTORTION_TIME_OFFSET_Y_SPEED ) ;
325+ const timeOffset = d . vec2f (
326+ d . f32 ( 0.0 ) ,
327+ time * u . DISTORTION_TIME_OFFSET_Y_SPEED ,
328+ ) ;
317329 const noiseVal = perlin2d . sample ( noisePos . add ( timeOffset ) ) ;
318330
319331 const distFromCenter =
@@ -332,7 +344,8 @@ const waterFragment = tgpu["~unstable"].fragmentFn({
332344
333345 const pullStrength = u . DISTORTION_PULL_STRENGTH ;
334346
335- const yDisplacement = dirToCenter * distortionMask * streakNoise * pullStrength ;
347+ const yDisplacement =
348+ dirToCenter * distortionMask * streakNoise * pullStrength ;
336349
337350 const noiseValX = perlin2d . sample ( uv . add ( timeOffset ) ) ;
338351 const distortionMaskX = std . smoothstep (
@@ -341,7 +354,8 @@ const waterFragment = tgpu["~unstable"].fragmentFn({
341354 distFromCenter ,
342355 ) ;
343356
344- const xDisplacement = noiseValX * distortionMaskX * u . DISTORTION_X_DISPLACEMENT_SCALE ;
357+ const xDisplacement =
358+ noiseValX * distortionMaskX * u . DISTORTION_X_DISPLACEMENT_SCALE ;
345359
346360 const flareMask = std . pow ( distFromCenter , u . FLARE_MASK_POW ) ;
347361
@@ -398,7 +412,7 @@ const DEFAULT_PADDING = {
398412 paddingLeft : 150 ,
399413} satisfies Padding ;
400414
401- export interface WaterfallProps {
415+ export interface FluidWaterfallProps {
402416 text : string ;
403417 font : FontConfig ;
404418 padding ?: Partial < Padding > ;
@@ -412,7 +426,7 @@ export interface WaterfallProps {
412426 className ?: string ;
413427}
414428
415- function WaterfallCanvas ( {
429+ function FluidWaterfallCanvas ( {
416430 text,
417431 font,
418432 padding = DEFAULT_PADDING ,
@@ -424,7 +438,7 @@ function WaterfallCanvas({
424438 FLARE_STRENGTH = 0.5 ,
425439 style,
426440 className,
427- } : WaterfallProps ) {
441+ } : FluidWaterfallProps ) {
428442 const interactionUniforms = useShaderInteractionUniforms ( ) ;
429443 const timeRef = useRef ( 0 ) ;
430444 const spiralSpeedRef = useRef ( SPIRAL_SPEED ) ;
@@ -472,7 +486,7 @@ function WaterfallCanvas({
472486 return (
473487 < ShaderCanvas
474488 source = { source }
475- fragment = { waterFragment }
489+ fragment = { fluidWaterfallFragment }
476490 uniformBindingsRef = { uniformBindings }
477491 padding = { padding }
478492 style = { style }
@@ -481,10 +495,10 @@ function WaterfallCanvas({
481495 ) ;
482496}
483497
484- export function Waterfall ( props : WaterfallProps ) {
498+ export function FluidWaterfall ( props : FluidWaterfallProps ) {
485499 return (
486500 < InteractionArea style = { { display : "inline-block" } } >
487- < WaterfallCanvas { ...props } />
501+ < FluidWaterfallCanvas { ...props } />
488502 </ InteractionArea >
489503 ) ;
490504}
@@ -496,18 +510,18 @@ const DEFAULT_FONT: FontConfig = {
496510} ;
497511
498512export const presetMeta = {
499- id : "waterfall" ,
500- name : "Waterfall" ,
501- component : Waterfall ,
513+ id : "fluid- waterfall" ,
514+ name : "Fluid Waterfall" ,
515+ component : FluidWaterfall ,
502516 defaultProps : {
503- text : "Hello " ,
504- font : DEFAULT_FONT ,
505- SPIRAL_SPEED : 7.0 ,
506- SPIRAL_AMOUNT : 3 .0,
507- PAINT_CONTRAST : 28 .0,
508- IRIDESCENCE_MIX_FACTOR : 0.6 ,
509- DISTORTION_PULL_STRENGTH : 2.0 ,
510- FLARE_STRENGTH : 0.5 ,
517+ text : "Waterfall " ,
518+ font : { family : "Cormorant Garamond" , size : 120 , weight : 700 } ,
519+ SPIRAL_SPEED : 17.5 ,
520+ SPIRAL_AMOUNT : 0 .0,
521+ PAINT_CONTRAST : 9 .0,
522+ IRIDESCENCE_MIX_FACTOR : 0.0 ,
523+ DISTORTION_PULL_STRENGTH : 0.9 ,
524+ FLARE_STRENGTH : 0.0 ,
511525 } ,
512526 uniformControls : collectUniformControls ( U . specs ) ,
513- } satisfies PresetMeta < WaterfallProps > ;
527+ } satisfies PresetMeta < FluidWaterfallProps > ;
0 commit comments