foundry-component-library 0.2.9 → 0.2.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. package/lib/components/ServiceHubsTeaserEffects/TileBalls.tsx +35 -0
  2. package/lib/components/ServiceHubsTeaserEffects/TileFluid.tsx +29 -0
  3. package/lib/components/ServiceHubsTeaserEffects/TileGlass.tsx +23 -0
  4. package/lib/components/ServiceHubsTeaserEffects/TileRays.tsx +94 -0
  5. package/lib/components/ServiceHubsTeaserEffects/bubbles/Bubble.tsx +35 -0
  6. package/lib/components/ServiceHubsTeaserEffects/bubbles/Bubbles.tsx +44 -0
  7. package/lib/components/ServiceHubsTeaserEffects/fluid/Fluid.tsx +192 -0
  8. package/lib/components/ServiceHubsTeaserEffects/fluid/constant.ts +23 -0
  9. package/lib/components/ServiceHubsTeaserEffects/fluid/effect/Fluid.tsx +22 -0
  10. package/lib/components/ServiceHubsTeaserEffects/fluid/effect/FluidEffect.tsx +58 -0
  11. package/lib/components/ServiceHubsTeaserEffects/fluid/glsl/advection.frag +16 -0
  12. package/lib/components/ServiceHubsTeaserEffects/fluid/glsl/base.vert +26 -0
  13. package/lib/components/ServiceHubsTeaserEffects/fluid/glsl/clear.frag +7 -0
  14. package/lib/components/ServiceHubsTeaserEffects/fluid/glsl/composite.frag +41 -0
  15. package/lib/components/ServiceHubsTeaserEffects/fluid/glsl/curl.frag +22 -0
  16. package/lib/components/ServiceHubsTeaserEffects/fluid/glsl/divergence.frag +41 -0
  17. package/lib/components/ServiceHubsTeaserEffects/fluid/glsl/gradientSubstract.frag +26 -0
  18. package/lib/components/ServiceHubsTeaserEffects/fluid/glsl/pressure.frag +28 -0
  19. package/lib/components/ServiceHubsTeaserEffects/fluid/glsl/splat.frag +19 -0
  20. package/lib/components/ServiceHubsTeaserEffects/fluid/glsl/vorticity.frag +36 -0
  21. package/lib/components/ServiceHubsTeaserEffects/fluid/glsl.d.ts +14 -0
  22. package/lib/components/ServiceHubsTeaserEffects/fluid/hooks/useDoubleFBO.tsx +37 -0
  23. package/lib/components/ServiceHubsTeaserEffects/fluid/hooks/useFBOs.tsx +71 -0
  24. package/lib/components/ServiceHubsTeaserEffects/fluid/hooks/useMaterials.tsx +242 -0
  25. package/lib/components/ServiceHubsTeaserEffects/fluid/hooks/usePointer.tsx +54 -0
  26. package/lib/components/ServiceHubsTeaserEffects/fluid/index.ts +5 -0
  27. package/lib/components/ServiceHubsTeaserEffects/fluid/types.ts +27 -0
  28. package/lib/components/ServiceHubsTeaserEffects/fluid/utils.ts +12 -0
  29. package/lib/components/ServiceHubsTeaserEffects/glass/Lens.tsx +66 -0
  30. package/lib/components/ServiceHubsTeaserEffects/index.tsx +67 -0
  31. package/lib/components/ServiceHubsTeaserEffects/rays/LightSource.tsx +64 -0
  32. package/lib/components/ServiceHubsTeaserEffects/rays/noise.js +97 -0
  33. package/lib/components/ServiceHubsTeaserEffects/styles.module.scss +135 -0
  34. package/lib/index.ts +2 -0
  35. package/package.json +6 -2
@@ -0,0 +1,35 @@
1
+ import { Canvas } from "@react-three/fiber";
2
+ import { Environment, Text } from "@react-three/drei";
3
+ import { EffectComposer, N8AO, TiltShift2 } from "@react-three/postprocessing";
4
+ import Bubbles from "./bubbles/Bubbles";
5
+
6
+ const TileBalls = () => {
7
+ return (
8
+ <Canvas
9
+ shadows
10
+ dpr={[1, 2]}
11
+ gl={{ antialias: false }}
12
+ camera={{ fov: 15, position: [0, 0, 20] }}>
13
+ <color attach="background" args={["#380de8"]} />
14
+ <fog attach="fog" args={["red", 20, -5]} />
15
+ <ambientLight intensity={1.5} />
16
+ <pointLight position={[10, 10, 10]} intensity={1} castShadow />
17
+ <Bubbles />
18
+ <EffectComposer>
19
+ <N8AO aoRadius={6} intensity={2} color="red" />
20
+ <TiltShift2 blur={0.1} />
21
+ </EffectComposer>
22
+ <Environment preset="city" />
23
+ <Text
24
+ position={[0, 0, 0]}
25
+ fontSize={0.4}
26
+ textAlign="center"
27
+ fontWeight={600}
28
+ color="#fff">
29
+ Content and{"\n"}Campaigning
30
+ </Text>
31
+ </Canvas>
32
+ );
33
+ };
34
+
35
+ export default TileBalls;
@@ -0,0 +1,29 @@
1
+ import { Text } from "@react-three/drei";
2
+ import { Canvas } from "@react-three/fiber";
3
+ import { EffectComposer } from "@react-three/postprocessing";
4
+ import { Fluid } from "./fluid/Fluid";
5
+
6
+ const TileFluid = () => {
7
+ return (
8
+ <Canvas
9
+ style={{
10
+ height: "100%",
11
+ width: "100%",
12
+ }}
13
+ camera={{ position: [0, 0, 20], fov: 15 }}>
14
+ <Text
15
+ position={[0, 0, 0]}
16
+ fontSize={0.4}
17
+ textAlign="center"
18
+ fontWeight={600}
19
+ color="#380de8">
20
+ Branding &{"\n"}Corporate ID
21
+ </Text>
22
+ <EffectComposer>
23
+ <Fluid backgroundColor="#fbff00" fluidColor="#380de8" rainbow={true} />
24
+ </EffectComposer>
25
+ </Canvas>
26
+ );
27
+ };
28
+
29
+ export default TileFluid;
@@ -0,0 +1,23 @@
1
+ import { Canvas } from "@react-three/fiber";
2
+ import { Text } from "@react-three/drei";
3
+ import Lens from "./glass/Lens";
4
+
5
+ const TileGlass = () => {
6
+ return (
7
+ <Canvas camera={{ position: [0, 0, 20], fov: 15 }}>
8
+ <Lens>
9
+ <Text
10
+ position={[0, 0, 0]}
11
+ fontSize={0.4}
12
+ textAlign="center"
13
+ fontWeight={600}
14
+ color="#491b11">
15
+ Strategy &{"\n"}
16
+ Positioning
17
+ </Text>
18
+ </Lens>
19
+ </Canvas>
20
+ );
21
+ };
22
+
23
+ export default TileGlass;
@@ -0,0 +1,94 @@
1
+ "use client";
2
+
3
+ import React, { useRef } from "react";
4
+ import { Canvas, useFrame, useThree } from "@react-three/fiber";
5
+ import { OrbitControls, useGLTF } from "@react-three/drei";
6
+ import { Vector2, MeshBasicMaterial, DoubleSide } from "three";
7
+ import { LightSource } from "./rays/LightSource";
8
+ import {
9
+ EffectComposer,
10
+ EffectPass,
11
+ GodRaysEffect,
12
+ RenderPass,
13
+ } from "postprocessing";
14
+
15
+ function Slab({ url }) {
16
+ const gltf = useGLTF(url);
17
+ const slabRef = useRef();
18
+ const { camera, scene, gl } = useThree();
19
+
20
+ // GodRays light
21
+ const lightRef = useRef();
22
+ useFrame(({ pointer }) => {
23
+ if (lightRef.current) {
24
+ const LIGHT_RANGE = 5;
25
+ lightRef.current.position.x = pointer.x * LIGHT_RANGE;
26
+ lightRef.current.position.y = pointer.y * LIGHT_RANGE;
27
+ }
28
+ });
29
+
30
+ React.useEffect(() => {
31
+ if (!gltf) return;
32
+
33
+ const slab = gltf.scene;
34
+ slab.rotation.x = Math.PI / 2;
35
+
36
+ slab.traverse((obj) => {
37
+ if (obj.isMesh) {
38
+ obj.material = new MeshBasicMaterial({
39
+ color: 0x491b11,
40
+ side: DoubleSide,
41
+ });
42
+ }
43
+ });
44
+
45
+ slabRef.current.add(slab);
46
+
47
+ // Setup postprocessing
48
+ const composer = new EffectComposer(gl);
49
+ composer.addPass(new RenderPass(scene, camera));
50
+
51
+ const gre = new GodRaysEffect(camera, lightRef.current, {
52
+ height: 480,
53
+ kernelSize: 2,
54
+ density: 1,
55
+ decay: 0.8,
56
+ weight: 0.5,
57
+ exposure: 0.3,
58
+ samples: 20,
59
+ clampMax: 0.95,
60
+ });
61
+
62
+ composer.addPass(new EffectPass(camera, gre));
63
+
64
+ // Render loop override
65
+ const originalSetAnimationLoop = gl.setAnimationLoop;
66
+ gl.setAnimationLoop(() => composer.render());
67
+
68
+ return () => {
69
+ // Cleanup
70
+ gl.setAnimationLoop(originalSetAnimationLoop);
71
+ composer.dispose();
72
+ };
73
+ }, [gltf, gl, scene, camera]);
74
+
75
+ return (
76
+ <>
77
+ {/* <mesh ref={lightRef} position={[0, 0, -10]} /> */}
78
+ <group ref={slabRef} />
79
+ <LightSource ref={lightRef} position={[0, 0, -20]} />
80
+ </>
81
+ );
82
+ }
83
+
84
+ export default function SlabScene() {
85
+ return (
86
+ <Canvas
87
+ camera={{ fov: 60, position: [0, 0, 10], near: 1, far: 100 }}
88
+ gl={{ antialias: true, powerPreference: "high-performance" }}>
89
+ {/* <ambientLight intensity={0.2} /> */}
90
+ {/* <OrbitControls /> */}
91
+ <Slab url="/slab-with-text.glb" />
92
+ </Canvas>
93
+ );
94
+ }
@@ -0,0 +1,35 @@
1
+ import { useRef } from "react";
2
+ import { useFrame } from "@react-three/fiber";
3
+ import { Instance } from "@react-three/drei";
4
+
5
+ const Bubble = ({ factor, speed, xFactor, yFactor, zFactor }) => {
6
+ const ref = useRef();
7
+
8
+ useFrame((state) => {
9
+ const t = factor + state.clock.elapsedTime * (speed / 2);
10
+
11
+ ref.current!.scale.setScalar(Math.max(1.5, Math.cos(t) * 5));
12
+
13
+ ref.current!.position.set(
14
+ Math.cos(t) +
15
+ Math.sin(t * 1) / 10 +
16
+ xFactor +
17
+ Math.cos((t / 10) * factor) +
18
+ (Math.sin(t * 1) * factor) / 10,
19
+ Math.sin(t) +
20
+ Math.cos(t * 2) / 10 +
21
+ yFactor +
22
+ Math.sin((t / 10) * factor) +
23
+ (Math.cos(t * 2) * factor) / 10,
24
+ Math.sin(t) +
25
+ Math.cos(t * 2) / 10 +
26
+ zFactor +
27
+ Math.cos((t / 10) * factor) +
28
+ (Math.sin(t * 3) * factor) / 4
29
+ );
30
+ });
31
+
32
+ return <Instance ref={ref} />;
33
+ };
34
+
35
+ export default Bubble;
@@ -0,0 +1,44 @@
1
+ import { MathUtils } from "three";
2
+ import { useRef } from "react";
3
+ import { useFrame } from "@react-three/fiber";
4
+ import { Instances } from "@react-three/drei";
5
+ import Bubble from "./Bubble";
6
+
7
+ const particles = Array.from({ length: 20 }, () => ({
8
+ factor: MathUtils.randInt(20, 100),
9
+ speed: MathUtils.randFloat(0.01, 0.75),
10
+ xFactor: MathUtils.randFloatSpread(3),
11
+ yFactor: MathUtils.randFloatSpread(3),
12
+ zFactor: MathUtils.randFloatSpread(5),
13
+ }));
14
+
15
+ const Bubbles = () => {
16
+ const ref = useRef(null);
17
+
18
+ useFrame(
19
+ (state, delta) =>
20
+ void (ref.current.rotation.y = MathUtils.damp(
21
+ ref.current.rotation.y,
22
+ (-state.pointer.x * Math.PI) / 6,
23
+ 2.75,
24
+ delta
25
+ ))
26
+ );
27
+
28
+ return (
29
+ <Instances
30
+ limit={particles.length}
31
+ ref={ref}
32
+ castShadow
33
+ receiveShadow
34
+ position={[0, 2.5, 0]}>
35
+ <sphereGeometry args={[0.45, 64, 64]} />
36
+ <meshStandardMaterial roughness={1} color="#f0f0f0" />
37
+ {particles.map((data, i) => (
38
+ <Bubble key={i} {...data} />
39
+ ))}
40
+ </Instances>
41
+ );
42
+ };
43
+
44
+ export default Bubbles;
@@ -0,0 +1,192 @@
1
+ import { createPortal, useFrame, useThree } from '@react-three/fiber';
2
+ import { useCallback, useMemo, useRef, useState } from 'react';
3
+ import { Camera, Color, Mesh, Scene, Texture, Vector2, Vector3 } from 'three';
4
+ import { ShaderPass } from 'three/examples/jsm/Addons.js';
5
+ import { Effect as FluidEffect } from './effect/Fluid';
6
+ import { useFBOs } from './hooks/useFBOs';
7
+ import { useMaterials } from './hooks/useMaterials';
8
+ import { type FluidProps } from './types';
9
+ import { DEFAULT_CONFIG } from './constant';
10
+ import { usePointer } from './hooks/usePointer';
11
+ import { normalizeScreenHz } from './utils';
12
+
13
+ type MaterialName = keyof ReturnType<typeof useMaterials>;
14
+ type FBONames = keyof ReturnType<typeof useFBOs>;
15
+
16
+ type Uniforms = {
17
+ uColor: Vector3 | Color;
18
+ uPointer: Vector2;
19
+ uTarget: Texture | null;
20
+ uVelocity: Texture;
21
+ uCurl: Texture;
22
+ uTexture: Texture;
23
+ uPressure: Texture;
24
+ uDivergence: Texture;
25
+ uSource: Texture;
26
+ uRadius: number;
27
+ uClearValue: number;
28
+ uCurlValue: number;
29
+ uDissipation: number;
30
+ };
31
+
32
+ export const Fluid = ({
33
+ blend = DEFAULT_CONFIG.blend,
34
+ force = DEFAULT_CONFIG.force,
35
+ radius = DEFAULT_CONFIG.radius,
36
+ curl = DEFAULT_CONFIG.curl,
37
+ swirl = DEFAULT_CONFIG.swirl,
38
+ intensity = DEFAULT_CONFIG.intensity,
39
+ distortion = DEFAULT_CONFIG.distortion,
40
+ fluidColor = DEFAULT_CONFIG.fluidColor,
41
+ backgroundColor = DEFAULT_CONFIG.backgroundColor,
42
+ showBackground = DEFAULT_CONFIG.showBackground,
43
+ rainbow = DEFAULT_CONFIG.rainbow,
44
+ pressure = DEFAULT_CONFIG.pressure,
45
+ densityDissipation = DEFAULT_CONFIG.densityDissipation,
46
+ velocityDissipation = DEFAULT_CONFIG.velocityDissipation,
47
+ blendFunction = DEFAULT_CONFIG.blendFunction,
48
+ }: FluidProps) => {
49
+ const size = useThree((three) => three.size);
50
+ const gl = useThree((three) => three.gl);
51
+
52
+ const [bufferScene] = useState(() => new Scene());
53
+ const bufferCamera = useMemo(() => new Camera(), []);
54
+
55
+ const meshRef = useRef<Mesh>(null);
56
+ const postRef = useRef<ShaderPass>(null);
57
+ const pointerRef = useRef(new Vector2());
58
+ const colorRef = useRef(new Vector3());
59
+
60
+ const FBOs = useFBOs();
61
+ const materials = useMaterials();
62
+ const splatStack = usePointer({ force });
63
+
64
+ const setShaderMaterial = useCallback(
65
+ (name: MaterialName) => {
66
+ if (!meshRef.current) return;
67
+
68
+ meshRef.current.material = materials[name];
69
+ meshRef.current.material.needsUpdate = true;
70
+ },
71
+ [materials],
72
+ );
73
+
74
+ const setRenderTarget = useCallback(
75
+ (name: FBONames) => {
76
+ const target = FBOs[name];
77
+
78
+ if ('write' in target) {
79
+ gl.setRenderTarget(target.write);
80
+ gl.clear();
81
+ gl.render(bufferScene, bufferCamera);
82
+ target.swap();
83
+ } else {
84
+ gl.setRenderTarget(target);
85
+ gl.clear();
86
+ gl.render(bufferScene, bufferCamera);
87
+ }
88
+ },
89
+ [bufferCamera, bufferScene, FBOs, gl],
90
+ );
91
+
92
+ const setUniforms = useCallback(
93
+ <K extends keyof Uniforms>(material: MaterialName, uniform: K, value: Uniforms[K]) => {
94
+ const mat = materials[material];
95
+
96
+ if (mat && mat.uniforms[uniform]) {
97
+ mat.uniforms[uniform].value = value;
98
+ }
99
+ },
100
+ [materials],
101
+ );
102
+
103
+ useFrame((_, delta) => {
104
+ if (!meshRef.current || !postRef.current) return;
105
+
106
+ for (let i = splatStack.length - 1; i >= 0; i--) {
107
+ const { mouseX, mouseY, velocityX, velocityY } = splatStack[i];
108
+
109
+ pointerRef.current.set(mouseX, mouseY);
110
+ colorRef.current.set(velocityX, velocityY, 10.0);
111
+
112
+ setShaderMaterial('splat');
113
+ setUniforms('splat', 'uTarget', FBOs.velocity.read.texture);
114
+ setUniforms('splat', 'uPointer', pointerRef.current);
115
+ setUniforms('splat', 'uColor', colorRef.current);
116
+ setUniforms('splat', 'uRadius', radius / 100.0);
117
+ setRenderTarget('velocity');
118
+ setUniforms('splat', 'uTarget', FBOs.density.read.texture);
119
+ setRenderTarget('density');
120
+
121
+ splatStack.pop();
122
+ }
123
+
124
+ setShaderMaterial('curl');
125
+ setUniforms('curl', 'uVelocity', FBOs.velocity.read.texture);
126
+ setRenderTarget('curl');
127
+
128
+ setShaderMaterial('vorticity');
129
+ setUniforms('vorticity', 'uVelocity', FBOs.velocity.read.texture);
130
+ setUniforms('vorticity', 'uCurl', FBOs.curl.texture);
131
+ setUniforms('vorticity', 'uCurlValue', curl);
132
+ setRenderTarget('velocity');
133
+
134
+ setShaderMaterial('divergence');
135
+ setUniforms('divergence', 'uVelocity', FBOs.velocity.read.texture);
136
+ setRenderTarget('divergence');
137
+
138
+ setShaderMaterial('clear');
139
+ setUniforms('clear', 'uTexture', FBOs.pressure.read.texture);
140
+ setUniforms('clear', 'uClearValue', normalizeScreenHz(pressure, delta));
141
+ setRenderTarget('pressure');
142
+
143
+ setShaderMaterial('pressure');
144
+ setUniforms('pressure', 'uDivergence', FBOs.divergence.texture);
145
+
146
+ for (let i = 0; i < swirl; i++) {
147
+ setUniforms('pressure', 'uPressure', FBOs.pressure.read.texture);
148
+ setRenderTarget('pressure');
149
+ }
150
+
151
+ setShaderMaterial('gradientSubstract');
152
+ setUniforms('gradientSubstract', 'uPressure', FBOs.pressure.read.texture);
153
+ setUniforms('gradientSubstract', 'uVelocity', FBOs.velocity.read.texture);
154
+ setRenderTarget('velocity');
155
+
156
+ setShaderMaterial('advection');
157
+ setUniforms('advection', 'uVelocity', FBOs.velocity.read.texture);
158
+ setUniforms('advection', 'uSource', FBOs.velocity.read.texture);
159
+ setUniforms('advection', 'uDissipation', normalizeScreenHz(velocityDissipation, delta));
160
+
161
+ setRenderTarget('velocity');
162
+ setUniforms('advection', 'uVelocity', FBOs.velocity.read.texture);
163
+ setUniforms('advection', 'uSource', FBOs.density.read.texture);
164
+ setUniforms('advection', 'uDissipation', normalizeScreenHz(densityDissipation, delta));
165
+
166
+ setRenderTarget('density');
167
+ });
168
+
169
+ return (
170
+ <>
171
+ {createPortal(
172
+ <mesh ref={meshRef} scale={[size.width, size.height, 1]}>
173
+ <planeGeometry args={[2, 2]} />
174
+ </mesh>,
175
+ bufferScene,
176
+ )}
177
+
178
+ <FluidEffect
179
+ blendFunction={blendFunction}
180
+ intensity={intensity}
181
+ rainbow={rainbow}
182
+ distortion={distortion}
183
+ backgroundColor={backgroundColor}
184
+ blend={blend}
185
+ fluidColor={fluidColor}
186
+ showBackground={showBackground}
187
+ ref={postRef}
188
+ tFluid={FBOs.density.read.texture}
189
+ />
190
+ </>
191
+ );
192
+ };
@@ -0,0 +1,23 @@
1
+ import { BlendFunction } from 'postprocessing';
2
+
3
+ export const DEFAULT_CONFIG = {
4
+ blend: 5,
5
+ intensity: 2,
6
+ force: 1.1,
7
+ distortion: 0.4,
8
+ curl: 1.9,
9
+ radius: 0.3,
10
+ swirl: 4,
11
+ pressure: 0.8,
12
+ densityDissipation: 0.96,
13
+ velocityDissipation: 1.0,
14
+ fluidColor: '#3300ff',
15
+ backgroundColor: '#070410',
16
+ showBackground: true,
17
+ rainbow: false,
18
+ dyeRes: 512,
19
+ simRes: 128,
20
+ blendFunction: BlendFunction.SET,
21
+ } as const;
22
+
23
+ export const REFRESH_RATE = 60;
@@ -0,0 +1,22 @@
1
+ import { forwardRef, useEffect, useMemo } from 'react';
2
+ import { EffectProps } from '../types';
3
+ import { FluidEffect } from './FluidEffect';
4
+
5
+ export const Effect = forwardRef(function Fluid(props: EffectProps, ref) {
6
+ // prevent re-creating the effect on every render
7
+ // eslint-disable-next-line react-hooks/exhaustive-deps
8
+ const effect = useMemo(() => new FluidEffect(props), []);
9
+
10
+ useEffect(() => {
11
+ effect.state = { ...props };
12
+ effect.update();
13
+ }, [effect, props]);
14
+
15
+ useEffect(() => {
16
+ return () => {
17
+ effect.dispose?.();
18
+ };
19
+ }, [effect]);
20
+
21
+ return <primitive ref={ref} object={effect} dispose={null} />;
22
+ });
@@ -0,0 +1,58 @@
1
+ import { Effect, EffectAttribute } from 'postprocessing';
2
+ import { Texture, Uniform, Vector3 } from 'three';
3
+ import compositeFrag from '../glsl/composite.frag';
4
+ import { type EffectProps } from '../types';
5
+ import { hexToRgb } from '../utils';
6
+
7
+ type Uniforms = {
8
+ tFluid: Texture;
9
+ uColor: Vector3;
10
+ uBackgroundColor: Vector3;
11
+ uRainbow: boolean;
12
+ uShowBackground: boolean;
13
+ uDistort: number;
14
+ uBlend: number;
15
+ uIntensity: number;
16
+ };
17
+
18
+ export class FluidEffect extends Effect {
19
+ state: EffectProps;
20
+
21
+ constructor(props: EffectProps) {
22
+ const uniforms: Record<keyof Uniforms, Uniform> = {
23
+ tFluid: new Uniform(props.tFluid),
24
+ uDistort: new Uniform(props.distortion),
25
+ uRainbow: new Uniform(props.rainbow),
26
+ uIntensity: new Uniform(props.intensity),
27
+ uBlend: new Uniform(props.blend),
28
+ uShowBackground: new Uniform(props.showBackground),
29
+ uColor: new Uniform(hexToRgb(props.fluidColor!)),
30
+ uBackgroundColor: new Uniform(hexToRgb(props.backgroundColor!)),
31
+ };
32
+
33
+ super('FluidEffect', compositeFrag, {
34
+ blendFunction: props.blendFunction,
35
+ attributes: EffectAttribute.CONVOLUTION,
36
+ uniforms: new Map(Object.entries(uniforms)),
37
+ });
38
+
39
+ this.state = props;
40
+ }
41
+
42
+ private updateUniform<K extends keyof Uniforms>(key: K, value: Uniforms[K]) {
43
+ const uniform = this.uniforms.get(key);
44
+ if (uniform) {
45
+ uniform.value = value;
46
+ }
47
+ }
48
+
49
+ update() {
50
+ this.updateUniform('uIntensity', this.state.intensity);
51
+ this.updateUniform('uDistort', this.state.distortion);
52
+ this.updateUniform('uRainbow', this.state.rainbow);
53
+ this.updateUniform('uBlend', this.state.blend);
54
+ this.updateUniform('uShowBackground', this.state.showBackground);
55
+ this.updateUniform('uColor', hexToRgb(this.state.fluidColor));
56
+ this.updateUniform('uBackgroundColor', hexToRgb(this.state.backgroundColor));
57
+ }
58
+ }
@@ -0,0 +1,16 @@
1
+ precision highp float;
2
+
3
+ varying vec2 vUv;
4
+ uniform sampler2D uVelocity;
5
+ uniform sampler2D uSource;
6
+ uniform vec2 texelSize;
7
+ uniform float dt;
8
+ uniform float uDissipation;
9
+
10
+ void main() {
11
+ vec2 coord = vUv - dt * texture2D(uVelocity, vUv).xy * texelSize;
12
+
13
+ gl_FragColor = uDissipation * texture2D(uSource, coord);
14
+
15
+ gl_FragColor.a = 1.0;
16
+ }
@@ -0,0 +1,26 @@
1
+ #ifdef USE_V_UV
2
+ varying vec2 vUv;
3
+ #endif
4
+
5
+ #ifdef USE_OFFSETS
6
+ varying vec2 vL;
7
+ varying vec2 vR;
8
+ varying vec2 vT;
9
+ varying vec2 vB;
10
+ uniform vec2 texelSize;
11
+ #endif
12
+
13
+ void main() {
14
+ #ifdef USE_V_UV
15
+ vUv = uv;
16
+ #endif
17
+
18
+ #ifdef USE_OFFSETS
19
+ vL = uv - vec2(texelSize.x, 0.0);
20
+ vR = uv + vec2(texelSize.x, 0.0);
21
+ vT = uv + vec2(0.0, texelSize.y);
22
+ vB = uv - vec2(0.0, texelSize.y);
23
+ #endif
24
+
25
+ gl_Position = vec4(position, 1.0);
26
+ }
@@ -0,0 +1,7 @@
1
+ precision highp float;
2
+
3
+ varying vec2 vUv;
4
+ uniform sampler2D uTexture;
5
+ uniform float uClearValue;
6
+
7
+ void main() { gl_FragColor = uClearValue * texture2D(uTexture, vUv); }
@@ -0,0 +1,41 @@
1
+ uniform sampler2D tFluid;
2
+
3
+ uniform vec3 uColor;
4
+ uniform vec3 uBackgroundColor;
5
+
6
+ uniform float uDistort;
7
+ uniform float uIntensity;
8
+ uniform float uRainbow;
9
+ uniform float uBlend;
10
+ uniform float uShowBackground;
11
+
12
+ void mainImage(const in vec4 inputColor, const in vec2 uv, out vec4 outputColor) {
13
+
14
+ vec3 fluidColor = texture2D(tFluid, uv).rgb;
15
+
16
+ vec2 distortedUv = uv - fluidColor.rg * uDistort * 0.001;
17
+
18
+ vec4 texture = texture2D(inputBuffer, distortedUv);
19
+
20
+ float intensity = length(fluidColor) * uIntensity * 0.0001;
21
+
22
+ vec3 selectedColor = uColor * length(fluidColor);
23
+
24
+ vec4 colorForFluidEffect = vec4(uRainbow == 1.0 ? fluidColor : selectedColor, 1.0);
25
+
26
+ vec4 computedBgColor = uShowBackground != 0.0 ? vec4(uBackgroundColor, 1.0) : vec4(0.0, 0.0, 0.0, 0.0);
27
+
28
+ outputColor = mix(texture, colorForFluidEffect, intensity);
29
+
30
+ vec4 computedFluidColor = mix(texture, colorForFluidEffect, uBlend * 0.01);
31
+
32
+ vec4 finalColor;
33
+
34
+ if(texture.a < 0.1) {
35
+ finalColor = mix(computedBgColor, colorForFluidEffect, intensity);
36
+ } else {
37
+ finalColor = mix(computedFluidColor, computedBgColor, 1.0 - texture.a);
38
+ }
39
+
40
+ outputColor = finalColor;
41
+ }
@@ -0,0 +1,22 @@
1
+ precision highp float;
2
+
3
+ varying vec2 vL;
4
+ varying vec2 vR;
5
+ varying vec2 vT;
6
+ varying vec2 vB;
7
+
8
+ uniform sampler2D uVelocity;
9
+
10
+ void main() {
11
+ float L = texture2D(uVelocity, vL).y;
12
+
13
+ float R = texture2D(uVelocity, vR).y;
14
+
15
+ float T = texture2D(uVelocity, vT).x;
16
+
17
+ float B = texture2D(uVelocity, vB).x;
18
+
19
+ float vorticity = R - L - T + B;
20
+
21
+ gl_FragColor = vec4(vorticity, 0.0, 0.0, 1.0);
22
+ }