From 8c720926cd1ce6dd805eb589eba042be1258872a Mon Sep 17 00:00:00 2001 From: takuma-hmng8 Date: Fri, 13 Sep 2024 18:52:33 +0900 Subject: [PATCH 01/60] wip --- app/_home/Playground.tsx | 6 +- app/v2/FxMaterial.tsx | 50 + app/v2/Playground.tsx | 31 + app/v2/page.tsx | 18 + packages/use-shader-fx/build/use-shader-fx.js | 4808 ----------------- .../use-shader-fx/build/use-shader-fx.js.map | 1 - .../use-shader-fx/build/use-shader-fx.umd.cjs | 1615 ------ .../build/use-shader-fx.umd.cjs.map | 1 - .../{src => legacy}/fxs/3D/types/index.ts | 0 .../fxs/3D/useMorphParticles/index.ts | 0 .../3D/useMorphParticles/shaders/main.frag | 0 .../3D/useMorphParticles/shaders/main.vert | 0 .../useCreateMorphParticles.ts | 0 .../utils/modifyAttributes.ts | 0 .../utils/rewriteFragmentShader.ts | 0 .../utils/rewriteVertexShader.ts | 0 .../utils/useCreateObject.ts | 0 .../3D/useMorphParticles/utils/useMaterial.ts | 0 .../fxs/3D/useWobble3D/index.ts | 0 .../shaders/transmission_fragment.glsl | 0 .../shaders/transmission_pars_fragment.glsl | 0 .../fxs/3D/useWobble3D/useCreateWobble3D.ts | 0 .../fxs/3D/useWobble3D/useMaterial.ts | 0 .../useWobble3D/utils/resolveEachMaterial.ts | 0 .../utils/rewriteFragmentShader.ts | 0 .../useWobble3D/utils/rewriteVertexShader.ts | 0 .../fxs/blank/useBlank/index.ts | 0 .../fxs/blank/useBlank/shader/main.frag | 0 .../fxs/blank/useBlank/shader/main.vert | 0 .../fxs/blank/useBlank/useMesh.ts | 0 .../fxs/blank/useRawBlank/index.ts | 0 .../fxs/blank/useRawBlank/shader/main.frag | 0 .../fxs/blank/useRawBlank/shader/main.vert | 0 .../fxs/blank/useRawBlank/useMesh.ts | 0 .../fxs/effects/useMotionBlur/index.ts | 0 .../effects/useMotionBlur/shader/main.frag | 0 .../effects/useMotionBlur/shader/main.vert | 0 .../fxs/effects/useMotionBlur/useMesh.ts | 0 .../fxs/effects/useSimpleBlur/index.ts | 0 .../effects/useSimpleBlur/shader/main.frag | 0 .../effects/useSimpleBlur/shader/main.vert | 0 .../fxs/effects/useSimpleBlur/useMesh.ts | 0 .../fxs/effects/useWave/index.ts | 0 .../fxs/effects/useWave/shader/main.frag | 0 .../fxs/effects/useWave/shader/main.vert | 0 .../fxs/effects/useWave/useMesh.ts | 0 .../fxs/interactions/useBrush/index.ts | 0 .../interactions/useBrush/shader/main.frag | 0 .../interactions/useBrush/shader/main.vert | 0 .../fxs/interactions/useBrush/useMesh.ts | 0 .../fxs/misc/useChromaKey/index.ts | 0 .../fxs/misc/useChromaKey/shader/main.frag | 0 .../fxs/misc/useChromaKey/shader/main.vert | 0 .../fxs/misc/useChromaKey/useMesh.ts | 0 .../fxs/noises/useColorStrata/index.ts | 0 .../noises/useColorStrata/shader/main.frag | 0 .../noises/useColorStrata/shader/main.vert | 0 .../fxs/noises/useColorStrata/useMesh.ts | 0 .../fxs/noises/useCosPalette/index.ts | 0 .../fxs/noises/useCosPalette/shader/main.frag | 0 .../fxs/noises/useCosPalette/shader/main.vert | 0 .../fxs/noises/useCosPalette/useMesh.ts | 0 .../fxs/noises/useMarble/index.ts | 0 .../fxs/noises/useMarble/shader/main.frag | 0 .../fxs/noises/useMarble/shader/main.vert | 0 .../fxs/noises/useMarble/useMesh.ts | 0 .../fxs/noises/useNoise/index.ts | 0 .../fxs/noises/useNoise/shader/main.frag | 0 .../fxs/noises/useNoise/shader/main.vert | 0 .../fxs/noises/useNoise/useMesh.ts | 0 .../fxs/simulations/useFluid/index.ts | 0 .../materials/useAdvectionMaterial.ts | 0 .../useFluid/materials/useClearMaterial.ts | 0 .../useFluid/materials/useCurlMaterial.ts | 0 .../materials/useDivergenceMaterial.ts | 0 .../materials/useGradientSubtractMaterial.ts | 0 .../useFluid/materials/useInitialMaterial.ts | 0 .../useFluid/materials/usePressureMaterial.ts | 0 .../useFluid/materials/useSplatMaterial.ts | 0 .../materials/useVorticityMaterial.ts | 0 .../useFluid/shaders/advection.frag | 0 .../simulations/useFluid/shaders/clear.frag | 0 .../simulations/useFluid/shaders/curl.frag | 0 .../useFluid/shaders/divergence.frag | 0 .../useFluid/shaders/gradientSubtract.frag | 0 .../simulations/useFluid/shaders/init.frag | 0 .../simulations/useFluid/shaders/main.vert | 0 .../useFluid/shaders/pressure.frag | 0 .../simulations/useFluid/shaders/splat.frag | 0 .../useFluid/shaders/vorticity.frag | 0 .../fxs/simulations/useFluid/useMesh.ts | 0 .../fxs/simulations/useRipple/index.ts | 0 .../simulations/useRipple/shader/main.frag | 0 .../simulations/useRipple/shader/main.vert | 0 .../fxs/simulations/useRipple/useMesh.ts | 0 .../use-shader-fx/legacy/fxs/types/index.ts | 71 + .../fxs/utils/useAlphaBlending/index.ts | 0 .../utils/useAlphaBlending/shader/main.frag | 0 .../utils/useAlphaBlending/shader/main.vert | 0 .../fxs/utils/useAlphaBlending/useMesh.ts | 0 .../fxs/utils/useBlending/index.ts | 0 .../fxs/utils/useBlending/shader/main.frag | 0 .../fxs/utils/useBlending/shader/main.vert | 0 .../fxs/utils/useBlending/useMesh.ts | 0 .../fxs/utils/useBrightnessPicker/index.ts | 0 .../useBrightnessPicker/shader/main.frag | 0 .../useBrightnessPicker/shader/main.vert | 0 .../fxs/utils/useBrightnessPicker/useMesh.ts | 0 .../fxs/utils/useCoverTexture/index.ts | 0 .../utils/useCoverTexture/shader/main.frag | 0 .../utils/useCoverTexture/shader/main.vert | 0 .../fxs/utils/useCoverTexture/useMesh.ts | 0 .../fxs/utils/useDuoTone/index.ts | 0 .../fxs/utils/useDuoTone/shader/main.frag | 0 .../fxs/utils/useDuoTone/shader/main.vert | 0 .../fxs/utils/useDuoTone/useMesh.ts | 0 .../fxs/utils/useFxBlending/index.ts | 0 .../fxs/utils/useFxBlending/shader/main.frag | 0 .../fxs/utils/useFxBlending/shader/main.vert | 0 .../fxs/utils/useFxBlending/useMesh.ts | 0 .../fxs/utils/useFxTexture/index.ts | 0 .../fxs/utils/useFxTexture/shader/main.frag | 0 .../fxs/utils/useFxTexture/shader/main.vert | 0 .../fxs/utils/useFxTexture/useMesh.ts | 0 .../{src => legacy}/fxs/utils/useHSV/index.ts | 0 .../fxs/utils/useHSV/shader/main.frag | 0 .../fxs/utils/useHSV/shader/main.vert | 0 .../fxs/utils/useHSV/useMesh.ts | 0 .../{types/index.d.ts => legacy/index.js} | 38 + packages/use-shader-fx/legacy/libs/Easings.ts | 184 + .../{src => legacy}/libs/Utils.ts | 0 .../use-shader-fx/legacy/libs/constants.ts | 16 + .../legacy/libs/shaders/ShaderChunk.ts | 29 + .../libs/shaders/resolveShaders.ts | 0 .../shaders/shaderChunk/coverTexture.glsl | 7 + .../shaders/shaderChunk/defaultVertex.glsl | 6 + .../libs/shaders/shaderChunk/fxBlending.glsl | 6 + .../libs/shaders/shaderChunk/hsv2rgb.glsl | 6 + .../libs/shaders/shaderChunk/planeVertex.glsl | 8 + .../libs/shaders/shaderChunk/rgb2hsv.glsl | 10 + .../libs/shaders/shaderChunk/snoise.glsl | 58 + .../libs/shaders/shaderChunk/wobble3D.glsl | 111 + packages/use-shader-fx/legacy/misc/useBeat.ts | 42 + .../{src => legacy}/misc/useCopyTexture.ts | 0 .../misc/useDomSyncer/index.ts | 0 .../misc/useDomSyncer/shader/main.frag | 0 .../misc/useDomSyncer/shader/main.vert | 0 .../misc/useDomSyncer/utils/createMesh.ts | 0 .../useDomSyncer/utils/createUseDomView.ts | 0 .../misc/useDomSyncer/utils/errorHandler.ts | 0 .../utils/useIntersectionHandler.ts | 0 .../useDomSyncer/utils/useIsIntersecting.ts | 0 .../useDomSyncer/utils/useUpdateDomRect.ts | 0 .../{src => legacy}/misc/useFPSLimiter.ts | 0 .../use-shader-fx/legacy/misc/usePointer.ts | 80 + .../utils/createMaterialParameters.ts | 0 packages/use-shader-fx/legacy/utils/getDpr.ts | 13 + .../{src => legacy}/utils/setUniforms.ts | 0 .../{src => legacy}/utils/useAddMesh.ts | 0 .../legacy/utils/useAddObject.ts | 36 + .../use-shader-fx/legacy/utils/useCamera.ts | 35 + .../legacy/utils/useDoubleFBO.ts | 122 + .../{src => legacy}/utils/useParams.ts | 0 .../utils/useResizeBoundary.ts | 0 .../legacy/utils/useResolution.ts | 17 + .../legacy/utils/useSingleFBO.ts | 126 + .../src/fxs/materials/FxMaterial.ts | 42 + packages/use-shader-fx/src/fxs/types/index.ts | 62 +- .../use-shader-fx/src/fxs/useFluid/index.ts | 124 + .../useFluid/materials/AdvectionMaterial.ts | 37 + .../useFluid/materials/DivergenceMaterial.ts | 35 + .../fxs/useFluid/materials/PoissonMaterial.ts | 35 + .../useFluid/materials/PressureMaterial.ts | 37 + .../fxs/useFluid/materials/SplatMaterial.ts | 39 + .../useFluid/materials/shaders/advection.frag | 16 + .../materials/shaders/divergence.frag | 16 + .../fxs/useFluid/materials/shaders/face.vert | 17 + .../useFluid/materials/shaders/poisson.frag | 17 + .../useFluid/materials/shaders/pressure.frag | 21 + .../fxs/useFluid/materials/shaders/splat.frag | 12 + .../fxs/useFluid/materials/shaders/splat.vert | 12 + .../src/fxs/useFluid/useAdvection.ts | 51 + .../src/fxs/useFluid/useDivergence.ts | 47 + .../src/fxs/useFluid/usePoisson.ts | 50 + .../src/fxs/useFluid/usePressure.ts | 48 + .../src/fxs/useFluid/useSplat.ts | 49 + .../src/fxs/useNoise/NoiseMaterial.ts | 45 + .../use-shader-fx/src/fxs/useNoise/index.ts | 95 + .../use-shader-fx/src/fxs/useNoise/noise.frag | 76 + packages/use-shader-fx/src/index.js | 78 +- .../use-shader-fx/src/utils/useDoubleFBO.ts | 30 +- .../use-shader-fx/src/utils/useSingleFBO.ts | 49 +- .../types/fxs/3D/types/index.d.ts | 10 - .../types/fxs/3D/useMorphParticles/index.d.ts | 66 - .../useCreateMorphParticles.d.ts | 29 - .../utils/modifyAttributes.d.ts | 5 - .../utils/rewriteFragmentShader.d.ts | 5 - .../utils/rewriteVertexShader.d.ts | 2 - .../utils/useCreateObject.d.ts | 13 - .../useMorphParticles/utils/useMaterial.d.ts | 123 - .../types/fxs/3D/useWobble3D/index.d.ts | 56 - .../fxs/3D/useWobble3D/useCreateWobble3D.d.ts | 20 - .../types/fxs/3D/useWobble3D/useMaterial.d.ts | 88 - .../utils/resolveEachMaterial.d.ts | 6 - .../utils/rewriteFragmentShader.d.ts | 2 - .../utils/rewriteVertexShader.d.ts | 2 - .../types/fxs/blank/useBlank/index.d.ts | 30 - .../types/fxs/blank/useBlank/useMesh.d.ts | 29 - .../types/fxs/blank/useRawBlank/index.d.ts | 37 - .../types/fxs/blank/useRawBlank/useMesh.d.ts | 17 - .../fxs/effects/useMotionBlur/index.d.ts | 27 - .../fxs/effects/useMotionBlur/useMesh.d.ts | 27 - .../fxs/effects/useSimpleBlur/index.d.ts | 25 - .../fxs/effects/useSimpleBlur/useMesh.d.ts | 21 - .../types/fxs/effects/useWave/index.d.ts | 28 - .../types/fxs/effects/useWave/useMesh.d.ts | 27 - .../fxs/interactions/useBrush/index.d.ts | 44 - .../fxs/interactions/useBrush/useMesh.d.ts | 71 - .../types/fxs/misc/useChromaKey/index.d.ts | 36 - .../types/fxs/misc/useChromaKey/useMesh.d.ts | 44 - .../fxs/noises/useColorStrata/index.d.ts | 40 - .../fxs/noises/useColorStrata/useMesh.d.ts | 51 - .../types/fxs/noises/useCosPalette/index.d.ts | 30 - .../fxs/noises/useCosPalette/useMesh.d.ts | 30 - .../types/fxs/noises/useMarble/index.d.ts | 32 - .../types/fxs/noises/useMarble/useMesh.d.ts | 33 - .../types/fxs/noises/useNoise/index.d.ts | 36 - .../types/fxs/noises/useNoise/useMesh.d.ts | 36 - .../types/fxs/simulations/useFluid/index.d.ts | 56 - .../materials/useAdvectionMaterial.d.ts | 22 - .../useFluid/materials/useClearMaterial.d.ts | 16 - .../useFluid/materials/useCurlMaterial.d.ts | 13 - .../materials/useDivergenceMaterial.d.ts | 13 - .../useGradientSubtractMaterial.d.ts | 16 - .../materials/useInitialMaterial.d.ts | 2 - .../materials/usePressureMaterial.d.ts | 16 - .../useFluid/materials/useSplatMaterial.d.ts | 25 - .../materials/useVorticityMaterial.d.ts | 22 - .../fxs/simulations/useFluid/useMesh.d.ts | 52 - .../fxs/simulations/useRipple/index.d.ts | 39 - .../fxs/simulations/useRipple/useMesh.d.ts | 10 - .../use-shader-fx/types/fxs/types/index.d.ts | 68 - .../fxs/utils/useAlphaBlending/index.d.ts | 22 - .../fxs/utils/useAlphaBlending/useMesh.d.ts | 19 - .../types/fxs/utils/useBlending/index.d.ts | 36 - .../types/fxs/utils/useBlending/useMesh.d.ts | 42 - .../fxs/utils/useBrightnessPicker/index.d.ts | 26 - .../utils/useBrightnessPicker/useMesh.d.ts | 24 - .../fxs/utils/useCoverTexture/index.d.ts | 20 - .../fxs/utils/useCoverTexture/useMesh.d.ts | 23 - .../types/fxs/utils/useDuoTone/index.d.ts | 25 - .../types/fxs/utils/useDuoTone/useMesh.d.ts | 21 - .../types/fxs/utils/useFxBlending/index.d.ts | 25 - .../fxs/utils/useFxBlending/useMesh.d.ts | 21 - .../types/fxs/utils/useFxTexture/index.d.ts | 36 - .../types/fxs/utils/useFxTexture/useMesh.d.ts | 50 - .../types/fxs/utils/useHSV/index.d.ts | 24 - .../types/fxs/utils/useHSV/useMesh.d.ts | 22 - .../use-shader-fx/types/libs/Easings.d.ts | 9 - packages/use-shader-fx/types/libs/Utils.d.ts | 6 - .../use-shader-fx/types/libs/constants.d.ts | 8 - .../types/libs/shaders/ShaderChunk.d.ts | 4 - .../types/libs/shaders/resolveShaders.d.ts | 2 - .../use-shader-fx/types/misc/useBeat.d.ts | 14 - .../types/misc/useCopyTexture.d.ts | 17 - .../types/misc/useDomSyncer/index.d.ts | 45 - .../misc/useDomSyncer/utils/createMesh.d.ts | 24 - .../useDomSyncer/utils/createUseDomView.d.ts | 6 - .../misc/useDomSyncer/utils/errorHandler.d.ts | 2 - .../utils/useIntersectionHandler.d.ts | 6 - .../useDomSyncer/utils/useIsIntersecting.d.ts | 7 - .../useDomSyncer/utils/useUpdateDomRect.d.ts | 16 - .../types/misc/useFPSLimiter.d.ts | 14 - .../use-shader-fx/types/misc/usePointer.d.ts | 16 - .../types/utils/createMaterialParameters.d.ts | 2 - .../use-shader-fx/types/utils/getDpr.d.ts | 5 - .../types/utils/setUniforms.d.ts | 17 - .../use-shader-fx/types/utils/useAddMesh.d.ts | 3 - .../types/utils/useAddObject.d.ts | 7 - .../use-shader-fx/types/utils/useCamera.d.ts | 3 - .../types/utils/useDoubleFBO.d.ts | 25 - .../use-shader-fx/types/utils/useParams.d.ts | 7 - .../types/utils/useResizeBoundary.d.ts | 6 - .../types/utils/useResolution.d.ts | 6 - .../types/utils/useSingleFBO.d.ts | 36 - 285 files changed, 2119 insertions(+), 8869 deletions(-) create mode 100644 app/v2/FxMaterial.tsx create mode 100644 app/v2/Playground.tsx create mode 100644 app/v2/page.tsx delete mode 100644 packages/use-shader-fx/build/use-shader-fx.js delete mode 100644 packages/use-shader-fx/build/use-shader-fx.js.map delete mode 100644 packages/use-shader-fx/build/use-shader-fx.umd.cjs delete mode 100644 packages/use-shader-fx/build/use-shader-fx.umd.cjs.map rename packages/use-shader-fx/{src => legacy}/fxs/3D/types/index.ts (100%) rename packages/use-shader-fx/{src => legacy}/fxs/3D/useMorphParticles/index.ts (100%) rename packages/use-shader-fx/{src => legacy}/fxs/3D/useMorphParticles/shaders/main.frag (100%) rename packages/use-shader-fx/{src => legacy}/fxs/3D/useMorphParticles/shaders/main.vert (100%) rename packages/use-shader-fx/{src => legacy}/fxs/3D/useMorphParticles/useCreateMorphParticles.ts (100%) rename packages/use-shader-fx/{src => legacy}/fxs/3D/useMorphParticles/utils/modifyAttributes.ts (100%) rename packages/use-shader-fx/{src => legacy}/fxs/3D/useMorphParticles/utils/rewriteFragmentShader.ts (100%) rename packages/use-shader-fx/{src => legacy}/fxs/3D/useMorphParticles/utils/rewriteVertexShader.ts (100%) rename packages/use-shader-fx/{src => legacy}/fxs/3D/useMorphParticles/utils/useCreateObject.ts (100%) rename packages/use-shader-fx/{src => legacy}/fxs/3D/useMorphParticles/utils/useMaterial.ts (100%) rename packages/use-shader-fx/{src => legacy}/fxs/3D/useWobble3D/index.ts (100%) rename packages/use-shader-fx/{src => legacy}/fxs/3D/useWobble3D/shaders/transmission_fragment.glsl (100%) rename packages/use-shader-fx/{src => legacy}/fxs/3D/useWobble3D/shaders/transmission_pars_fragment.glsl (100%) rename packages/use-shader-fx/{src => legacy}/fxs/3D/useWobble3D/useCreateWobble3D.ts (100%) rename packages/use-shader-fx/{src => legacy}/fxs/3D/useWobble3D/useMaterial.ts (100%) rename packages/use-shader-fx/{src => legacy}/fxs/3D/useWobble3D/utils/resolveEachMaterial.ts (100%) rename packages/use-shader-fx/{src => legacy}/fxs/3D/useWobble3D/utils/rewriteFragmentShader.ts (100%) rename packages/use-shader-fx/{src => legacy}/fxs/3D/useWobble3D/utils/rewriteVertexShader.ts (100%) rename packages/use-shader-fx/{src => legacy}/fxs/blank/useBlank/index.ts (100%) rename packages/use-shader-fx/{src => legacy}/fxs/blank/useBlank/shader/main.frag (100%) rename packages/use-shader-fx/{src => legacy}/fxs/blank/useBlank/shader/main.vert (100%) rename packages/use-shader-fx/{src => legacy}/fxs/blank/useBlank/useMesh.ts (100%) rename packages/use-shader-fx/{src => legacy}/fxs/blank/useRawBlank/index.ts (100%) rename packages/use-shader-fx/{src => legacy}/fxs/blank/useRawBlank/shader/main.frag (100%) rename packages/use-shader-fx/{src => legacy}/fxs/blank/useRawBlank/shader/main.vert (100%) rename packages/use-shader-fx/{src => legacy}/fxs/blank/useRawBlank/useMesh.ts (100%) rename packages/use-shader-fx/{src => legacy}/fxs/effects/useMotionBlur/index.ts (100%) rename packages/use-shader-fx/{src => legacy}/fxs/effects/useMotionBlur/shader/main.frag (100%) rename packages/use-shader-fx/{src => legacy}/fxs/effects/useMotionBlur/shader/main.vert (100%) rename packages/use-shader-fx/{src => legacy}/fxs/effects/useMotionBlur/useMesh.ts (100%) rename packages/use-shader-fx/{src => legacy}/fxs/effects/useSimpleBlur/index.ts (100%) rename packages/use-shader-fx/{src => legacy}/fxs/effects/useSimpleBlur/shader/main.frag (100%) rename packages/use-shader-fx/{src => legacy}/fxs/effects/useSimpleBlur/shader/main.vert (100%) rename packages/use-shader-fx/{src => legacy}/fxs/effects/useSimpleBlur/useMesh.ts (100%) rename packages/use-shader-fx/{src => legacy}/fxs/effects/useWave/index.ts (100%) rename packages/use-shader-fx/{src => legacy}/fxs/effects/useWave/shader/main.frag (100%) rename packages/use-shader-fx/{src => legacy}/fxs/effects/useWave/shader/main.vert (100%) rename packages/use-shader-fx/{src => legacy}/fxs/effects/useWave/useMesh.ts (100%) rename packages/use-shader-fx/{src => legacy}/fxs/interactions/useBrush/index.ts (100%) rename packages/use-shader-fx/{src => legacy}/fxs/interactions/useBrush/shader/main.frag (100%) rename packages/use-shader-fx/{src => legacy}/fxs/interactions/useBrush/shader/main.vert (100%) rename packages/use-shader-fx/{src => legacy}/fxs/interactions/useBrush/useMesh.ts (100%) rename packages/use-shader-fx/{src => legacy}/fxs/misc/useChromaKey/index.ts (100%) rename packages/use-shader-fx/{src => legacy}/fxs/misc/useChromaKey/shader/main.frag (100%) rename packages/use-shader-fx/{src => legacy}/fxs/misc/useChromaKey/shader/main.vert (100%) rename packages/use-shader-fx/{src => legacy}/fxs/misc/useChromaKey/useMesh.ts (100%) rename packages/use-shader-fx/{src => legacy}/fxs/noises/useColorStrata/index.ts (100%) rename packages/use-shader-fx/{src => legacy}/fxs/noises/useColorStrata/shader/main.frag (100%) rename packages/use-shader-fx/{src => legacy}/fxs/noises/useColorStrata/shader/main.vert (100%) rename packages/use-shader-fx/{src => legacy}/fxs/noises/useColorStrata/useMesh.ts (100%) rename packages/use-shader-fx/{src => legacy}/fxs/noises/useCosPalette/index.ts (100%) rename packages/use-shader-fx/{src => legacy}/fxs/noises/useCosPalette/shader/main.frag (100%) rename packages/use-shader-fx/{src => legacy}/fxs/noises/useCosPalette/shader/main.vert (100%) rename packages/use-shader-fx/{src => legacy}/fxs/noises/useCosPalette/useMesh.ts (100%) rename packages/use-shader-fx/{src => legacy}/fxs/noises/useMarble/index.ts (100%) rename packages/use-shader-fx/{src => legacy}/fxs/noises/useMarble/shader/main.frag (100%) rename packages/use-shader-fx/{src => legacy}/fxs/noises/useMarble/shader/main.vert (100%) rename packages/use-shader-fx/{src => legacy}/fxs/noises/useMarble/useMesh.ts (100%) rename packages/use-shader-fx/{src => legacy}/fxs/noises/useNoise/index.ts (100%) rename packages/use-shader-fx/{src => legacy}/fxs/noises/useNoise/shader/main.frag (100%) rename packages/use-shader-fx/{src => legacy}/fxs/noises/useNoise/shader/main.vert (100%) rename packages/use-shader-fx/{src => legacy}/fxs/noises/useNoise/useMesh.ts (100%) rename packages/use-shader-fx/{src => legacy}/fxs/simulations/useFluid/index.ts (100%) rename packages/use-shader-fx/{src => legacy}/fxs/simulations/useFluid/materials/useAdvectionMaterial.ts (100%) rename packages/use-shader-fx/{src => legacy}/fxs/simulations/useFluid/materials/useClearMaterial.ts (100%) rename packages/use-shader-fx/{src => legacy}/fxs/simulations/useFluid/materials/useCurlMaterial.ts (100%) rename packages/use-shader-fx/{src => legacy}/fxs/simulations/useFluid/materials/useDivergenceMaterial.ts (100%) rename packages/use-shader-fx/{src => legacy}/fxs/simulations/useFluid/materials/useGradientSubtractMaterial.ts (100%) rename packages/use-shader-fx/{src => legacy}/fxs/simulations/useFluid/materials/useInitialMaterial.ts (100%) rename packages/use-shader-fx/{src => legacy}/fxs/simulations/useFluid/materials/usePressureMaterial.ts (100%) rename packages/use-shader-fx/{src => legacy}/fxs/simulations/useFluid/materials/useSplatMaterial.ts (100%) rename packages/use-shader-fx/{src => legacy}/fxs/simulations/useFluid/materials/useVorticityMaterial.ts (100%) rename packages/use-shader-fx/{src => legacy}/fxs/simulations/useFluid/shaders/advection.frag (100%) rename packages/use-shader-fx/{src => legacy}/fxs/simulations/useFluid/shaders/clear.frag (100%) rename packages/use-shader-fx/{src => legacy}/fxs/simulations/useFluid/shaders/curl.frag (100%) rename packages/use-shader-fx/{src => legacy}/fxs/simulations/useFluid/shaders/divergence.frag (100%) rename packages/use-shader-fx/{src => legacy}/fxs/simulations/useFluid/shaders/gradientSubtract.frag (100%) rename packages/use-shader-fx/{src => legacy}/fxs/simulations/useFluid/shaders/init.frag (100%) rename packages/use-shader-fx/{src => legacy}/fxs/simulations/useFluid/shaders/main.vert (100%) rename packages/use-shader-fx/{src => legacy}/fxs/simulations/useFluid/shaders/pressure.frag (100%) rename packages/use-shader-fx/{src => legacy}/fxs/simulations/useFluid/shaders/splat.frag (100%) rename packages/use-shader-fx/{src => legacy}/fxs/simulations/useFluid/shaders/vorticity.frag (100%) rename packages/use-shader-fx/{src => legacy}/fxs/simulations/useFluid/useMesh.ts (100%) rename packages/use-shader-fx/{src => legacy}/fxs/simulations/useRipple/index.ts (100%) rename packages/use-shader-fx/{src => legacy}/fxs/simulations/useRipple/shader/main.frag (100%) rename packages/use-shader-fx/{src => legacy}/fxs/simulations/useRipple/shader/main.vert (100%) rename packages/use-shader-fx/{src => legacy}/fxs/simulations/useRipple/useMesh.ts (100%) create mode 100644 packages/use-shader-fx/legacy/fxs/types/index.ts rename packages/use-shader-fx/{src => legacy}/fxs/utils/useAlphaBlending/index.ts (100%) rename packages/use-shader-fx/{src => legacy}/fxs/utils/useAlphaBlending/shader/main.frag (100%) rename packages/use-shader-fx/{src => legacy}/fxs/utils/useAlphaBlending/shader/main.vert (100%) rename packages/use-shader-fx/{src => legacy}/fxs/utils/useAlphaBlending/useMesh.ts (100%) rename packages/use-shader-fx/{src => legacy}/fxs/utils/useBlending/index.ts (100%) rename packages/use-shader-fx/{src => legacy}/fxs/utils/useBlending/shader/main.frag (100%) rename packages/use-shader-fx/{src => legacy}/fxs/utils/useBlending/shader/main.vert (100%) rename packages/use-shader-fx/{src => legacy}/fxs/utils/useBlending/useMesh.ts (100%) rename packages/use-shader-fx/{src => legacy}/fxs/utils/useBrightnessPicker/index.ts (100%) rename packages/use-shader-fx/{src => legacy}/fxs/utils/useBrightnessPicker/shader/main.frag (100%) rename packages/use-shader-fx/{src => legacy}/fxs/utils/useBrightnessPicker/shader/main.vert (100%) rename packages/use-shader-fx/{src => legacy}/fxs/utils/useBrightnessPicker/useMesh.ts (100%) rename packages/use-shader-fx/{src => legacy}/fxs/utils/useCoverTexture/index.ts (100%) rename packages/use-shader-fx/{src => legacy}/fxs/utils/useCoverTexture/shader/main.frag (100%) rename packages/use-shader-fx/{src => legacy}/fxs/utils/useCoverTexture/shader/main.vert (100%) rename packages/use-shader-fx/{src => legacy}/fxs/utils/useCoverTexture/useMesh.ts (100%) rename packages/use-shader-fx/{src => legacy}/fxs/utils/useDuoTone/index.ts (100%) rename packages/use-shader-fx/{src => legacy}/fxs/utils/useDuoTone/shader/main.frag (100%) rename packages/use-shader-fx/{src => legacy}/fxs/utils/useDuoTone/shader/main.vert (100%) rename packages/use-shader-fx/{src => legacy}/fxs/utils/useDuoTone/useMesh.ts (100%) rename packages/use-shader-fx/{src => legacy}/fxs/utils/useFxBlending/index.ts (100%) rename packages/use-shader-fx/{src => legacy}/fxs/utils/useFxBlending/shader/main.frag (100%) rename packages/use-shader-fx/{src => legacy}/fxs/utils/useFxBlending/shader/main.vert (100%) rename packages/use-shader-fx/{src => legacy}/fxs/utils/useFxBlending/useMesh.ts (100%) rename packages/use-shader-fx/{src => legacy}/fxs/utils/useFxTexture/index.ts (100%) rename packages/use-shader-fx/{src => legacy}/fxs/utils/useFxTexture/shader/main.frag (100%) rename packages/use-shader-fx/{src => legacy}/fxs/utils/useFxTexture/shader/main.vert (100%) rename packages/use-shader-fx/{src => legacy}/fxs/utils/useFxTexture/useMesh.ts (100%) rename packages/use-shader-fx/{src => legacy}/fxs/utils/useHSV/index.ts (100%) rename packages/use-shader-fx/{src => legacy}/fxs/utils/useHSV/shader/main.frag (100%) rename packages/use-shader-fx/{src => legacy}/fxs/utils/useHSV/shader/main.vert (100%) rename packages/use-shader-fx/{src => legacy}/fxs/utils/useHSV/useMesh.ts (100%) rename packages/use-shader-fx/{types/index.d.ts => legacy/index.js} (69%) create mode 100644 packages/use-shader-fx/legacy/libs/Easings.ts rename packages/use-shader-fx/{src => legacy}/libs/Utils.ts (100%) create mode 100644 packages/use-shader-fx/legacy/libs/constants.ts create mode 100644 packages/use-shader-fx/legacy/libs/shaders/ShaderChunk.ts rename packages/use-shader-fx/{src => legacy}/libs/shaders/resolveShaders.ts (100%) create mode 100644 packages/use-shader-fx/legacy/libs/shaders/shaderChunk/coverTexture.glsl create mode 100644 packages/use-shader-fx/legacy/libs/shaders/shaderChunk/defaultVertex.glsl create mode 100644 packages/use-shader-fx/legacy/libs/shaders/shaderChunk/fxBlending.glsl create mode 100644 packages/use-shader-fx/legacy/libs/shaders/shaderChunk/hsv2rgb.glsl create mode 100644 packages/use-shader-fx/legacy/libs/shaders/shaderChunk/planeVertex.glsl create mode 100644 packages/use-shader-fx/legacy/libs/shaders/shaderChunk/rgb2hsv.glsl create mode 100644 packages/use-shader-fx/legacy/libs/shaders/shaderChunk/snoise.glsl create mode 100644 packages/use-shader-fx/legacy/libs/shaders/shaderChunk/wobble3D.glsl create mode 100644 packages/use-shader-fx/legacy/misc/useBeat.ts rename packages/use-shader-fx/{src => legacy}/misc/useCopyTexture.ts (100%) rename packages/use-shader-fx/{src => legacy}/misc/useDomSyncer/index.ts (100%) rename packages/use-shader-fx/{src => legacy}/misc/useDomSyncer/shader/main.frag (100%) rename packages/use-shader-fx/{src => legacy}/misc/useDomSyncer/shader/main.vert (100%) rename packages/use-shader-fx/{src => legacy}/misc/useDomSyncer/utils/createMesh.ts (100%) rename packages/use-shader-fx/{src => legacy}/misc/useDomSyncer/utils/createUseDomView.ts (100%) rename packages/use-shader-fx/{src => legacy}/misc/useDomSyncer/utils/errorHandler.ts (100%) rename packages/use-shader-fx/{src => legacy}/misc/useDomSyncer/utils/useIntersectionHandler.ts (100%) rename packages/use-shader-fx/{src => legacy}/misc/useDomSyncer/utils/useIsIntersecting.ts (100%) rename packages/use-shader-fx/{src => legacy}/misc/useDomSyncer/utils/useUpdateDomRect.ts (100%) rename packages/use-shader-fx/{src => legacy}/misc/useFPSLimiter.ts (100%) create mode 100644 packages/use-shader-fx/legacy/misc/usePointer.ts rename packages/use-shader-fx/{src => legacy}/utils/createMaterialParameters.ts (100%) create mode 100644 packages/use-shader-fx/legacy/utils/getDpr.ts rename packages/use-shader-fx/{src => legacy}/utils/setUniforms.ts (100%) rename packages/use-shader-fx/{src => legacy}/utils/useAddMesh.ts (100%) create mode 100644 packages/use-shader-fx/legacy/utils/useAddObject.ts create mode 100644 packages/use-shader-fx/legacy/utils/useCamera.ts create mode 100644 packages/use-shader-fx/legacy/utils/useDoubleFBO.ts rename packages/use-shader-fx/{src => legacy}/utils/useParams.ts (100%) rename packages/use-shader-fx/{src => legacy}/utils/useResizeBoundary.ts (100%) create mode 100644 packages/use-shader-fx/legacy/utils/useResolution.ts create mode 100644 packages/use-shader-fx/legacy/utils/useSingleFBO.ts create mode 100644 packages/use-shader-fx/src/fxs/materials/FxMaterial.ts create mode 100644 packages/use-shader-fx/src/fxs/useFluid/index.ts create mode 100644 packages/use-shader-fx/src/fxs/useFluid/materials/AdvectionMaterial.ts create mode 100644 packages/use-shader-fx/src/fxs/useFluid/materials/DivergenceMaterial.ts create mode 100644 packages/use-shader-fx/src/fxs/useFluid/materials/PoissonMaterial.ts create mode 100644 packages/use-shader-fx/src/fxs/useFluid/materials/PressureMaterial.ts create mode 100644 packages/use-shader-fx/src/fxs/useFluid/materials/SplatMaterial.ts create mode 100644 packages/use-shader-fx/src/fxs/useFluid/materials/shaders/advection.frag create mode 100644 packages/use-shader-fx/src/fxs/useFluid/materials/shaders/divergence.frag create mode 100644 packages/use-shader-fx/src/fxs/useFluid/materials/shaders/face.vert create mode 100644 packages/use-shader-fx/src/fxs/useFluid/materials/shaders/poisson.frag create mode 100644 packages/use-shader-fx/src/fxs/useFluid/materials/shaders/pressure.frag create mode 100644 packages/use-shader-fx/src/fxs/useFluid/materials/shaders/splat.frag create mode 100644 packages/use-shader-fx/src/fxs/useFluid/materials/shaders/splat.vert create mode 100644 packages/use-shader-fx/src/fxs/useFluid/useAdvection.ts create mode 100644 packages/use-shader-fx/src/fxs/useFluid/useDivergence.ts create mode 100644 packages/use-shader-fx/src/fxs/useFluid/usePoisson.ts create mode 100644 packages/use-shader-fx/src/fxs/useFluid/usePressure.ts create mode 100644 packages/use-shader-fx/src/fxs/useFluid/useSplat.ts create mode 100644 packages/use-shader-fx/src/fxs/useNoise/NoiseMaterial.ts create mode 100644 packages/use-shader-fx/src/fxs/useNoise/index.ts create mode 100644 packages/use-shader-fx/src/fxs/useNoise/noise.frag delete mode 100644 packages/use-shader-fx/types/fxs/3D/types/index.d.ts delete mode 100644 packages/use-shader-fx/types/fxs/3D/useMorphParticles/index.d.ts delete mode 100644 packages/use-shader-fx/types/fxs/3D/useMorphParticles/useCreateMorphParticles.d.ts delete mode 100644 packages/use-shader-fx/types/fxs/3D/useMorphParticles/utils/modifyAttributes.d.ts delete mode 100644 packages/use-shader-fx/types/fxs/3D/useMorphParticles/utils/rewriteFragmentShader.d.ts delete mode 100644 packages/use-shader-fx/types/fxs/3D/useMorphParticles/utils/rewriteVertexShader.d.ts delete mode 100644 packages/use-shader-fx/types/fxs/3D/useMorphParticles/utils/useCreateObject.d.ts delete mode 100644 packages/use-shader-fx/types/fxs/3D/useMorphParticles/utils/useMaterial.d.ts delete mode 100644 packages/use-shader-fx/types/fxs/3D/useWobble3D/index.d.ts delete mode 100644 packages/use-shader-fx/types/fxs/3D/useWobble3D/useCreateWobble3D.d.ts delete mode 100644 packages/use-shader-fx/types/fxs/3D/useWobble3D/useMaterial.d.ts delete mode 100644 packages/use-shader-fx/types/fxs/3D/useWobble3D/utils/resolveEachMaterial.d.ts delete mode 100644 packages/use-shader-fx/types/fxs/3D/useWobble3D/utils/rewriteFragmentShader.d.ts delete mode 100644 packages/use-shader-fx/types/fxs/3D/useWobble3D/utils/rewriteVertexShader.d.ts delete mode 100644 packages/use-shader-fx/types/fxs/blank/useBlank/index.d.ts delete mode 100644 packages/use-shader-fx/types/fxs/blank/useBlank/useMesh.d.ts delete mode 100644 packages/use-shader-fx/types/fxs/blank/useRawBlank/index.d.ts delete mode 100644 packages/use-shader-fx/types/fxs/blank/useRawBlank/useMesh.d.ts delete mode 100644 packages/use-shader-fx/types/fxs/effects/useMotionBlur/index.d.ts delete mode 100644 packages/use-shader-fx/types/fxs/effects/useMotionBlur/useMesh.d.ts delete mode 100644 packages/use-shader-fx/types/fxs/effects/useSimpleBlur/index.d.ts delete mode 100644 packages/use-shader-fx/types/fxs/effects/useSimpleBlur/useMesh.d.ts delete mode 100644 packages/use-shader-fx/types/fxs/effects/useWave/index.d.ts delete mode 100644 packages/use-shader-fx/types/fxs/effects/useWave/useMesh.d.ts delete mode 100644 packages/use-shader-fx/types/fxs/interactions/useBrush/index.d.ts delete mode 100644 packages/use-shader-fx/types/fxs/interactions/useBrush/useMesh.d.ts delete mode 100644 packages/use-shader-fx/types/fxs/misc/useChromaKey/index.d.ts delete mode 100644 packages/use-shader-fx/types/fxs/misc/useChromaKey/useMesh.d.ts delete mode 100644 packages/use-shader-fx/types/fxs/noises/useColorStrata/index.d.ts delete mode 100644 packages/use-shader-fx/types/fxs/noises/useColorStrata/useMesh.d.ts delete mode 100644 packages/use-shader-fx/types/fxs/noises/useCosPalette/index.d.ts delete mode 100644 packages/use-shader-fx/types/fxs/noises/useCosPalette/useMesh.d.ts delete mode 100644 packages/use-shader-fx/types/fxs/noises/useMarble/index.d.ts delete mode 100644 packages/use-shader-fx/types/fxs/noises/useMarble/useMesh.d.ts delete mode 100644 packages/use-shader-fx/types/fxs/noises/useNoise/index.d.ts delete mode 100644 packages/use-shader-fx/types/fxs/noises/useNoise/useMesh.d.ts delete mode 100644 packages/use-shader-fx/types/fxs/simulations/useFluid/index.d.ts delete mode 100644 packages/use-shader-fx/types/fxs/simulations/useFluid/materials/useAdvectionMaterial.d.ts delete mode 100644 packages/use-shader-fx/types/fxs/simulations/useFluid/materials/useClearMaterial.d.ts delete mode 100644 packages/use-shader-fx/types/fxs/simulations/useFluid/materials/useCurlMaterial.d.ts delete mode 100644 packages/use-shader-fx/types/fxs/simulations/useFluid/materials/useDivergenceMaterial.d.ts delete mode 100644 packages/use-shader-fx/types/fxs/simulations/useFluid/materials/useGradientSubtractMaterial.d.ts delete mode 100644 packages/use-shader-fx/types/fxs/simulations/useFluid/materials/useInitialMaterial.d.ts delete mode 100644 packages/use-shader-fx/types/fxs/simulations/useFluid/materials/usePressureMaterial.d.ts delete mode 100644 packages/use-shader-fx/types/fxs/simulations/useFluid/materials/useSplatMaterial.d.ts delete mode 100644 packages/use-shader-fx/types/fxs/simulations/useFluid/materials/useVorticityMaterial.d.ts delete mode 100644 packages/use-shader-fx/types/fxs/simulations/useFluid/useMesh.d.ts delete mode 100644 packages/use-shader-fx/types/fxs/simulations/useRipple/index.d.ts delete mode 100644 packages/use-shader-fx/types/fxs/simulations/useRipple/useMesh.d.ts delete mode 100644 packages/use-shader-fx/types/fxs/types/index.d.ts delete mode 100644 packages/use-shader-fx/types/fxs/utils/useAlphaBlending/index.d.ts delete mode 100644 packages/use-shader-fx/types/fxs/utils/useAlphaBlending/useMesh.d.ts delete mode 100644 packages/use-shader-fx/types/fxs/utils/useBlending/index.d.ts delete mode 100644 packages/use-shader-fx/types/fxs/utils/useBlending/useMesh.d.ts delete mode 100644 packages/use-shader-fx/types/fxs/utils/useBrightnessPicker/index.d.ts delete mode 100644 packages/use-shader-fx/types/fxs/utils/useBrightnessPicker/useMesh.d.ts delete mode 100644 packages/use-shader-fx/types/fxs/utils/useCoverTexture/index.d.ts delete mode 100644 packages/use-shader-fx/types/fxs/utils/useCoverTexture/useMesh.d.ts delete mode 100644 packages/use-shader-fx/types/fxs/utils/useDuoTone/index.d.ts delete mode 100644 packages/use-shader-fx/types/fxs/utils/useDuoTone/useMesh.d.ts delete mode 100644 packages/use-shader-fx/types/fxs/utils/useFxBlending/index.d.ts delete mode 100644 packages/use-shader-fx/types/fxs/utils/useFxBlending/useMesh.d.ts delete mode 100644 packages/use-shader-fx/types/fxs/utils/useFxTexture/index.d.ts delete mode 100644 packages/use-shader-fx/types/fxs/utils/useFxTexture/useMesh.d.ts delete mode 100644 packages/use-shader-fx/types/fxs/utils/useHSV/index.d.ts delete mode 100644 packages/use-shader-fx/types/fxs/utils/useHSV/useMesh.d.ts delete mode 100644 packages/use-shader-fx/types/libs/Easings.d.ts delete mode 100644 packages/use-shader-fx/types/libs/Utils.d.ts delete mode 100644 packages/use-shader-fx/types/libs/constants.d.ts delete mode 100644 packages/use-shader-fx/types/libs/shaders/ShaderChunk.d.ts delete mode 100644 packages/use-shader-fx/types/libs/shaders/resolveShaders.d.ts delete mode 100644 packages/use-shader-fx/types/misc/useBeat.d.ts delete mode 100644 packages/use-shader-fx/types/misc/useCopyTexture.d.ts delete mode 100644 packages/use-shader-fx/types/misc/useDomSyncer/index.d.ts delete mode 100644 packages/use-shader-fx/types/misc/useDomSyncer/utils/createMesh.d.ts delete mode 100644 packages/use-shader-fx/types/misc/useDomSyncer/utils/createUseDomView.d.ts delete mode 100644 packages/use-shader-fx/types/misc/useDomSyncer/utils/errorHandler.d.ts delete mode 100644 packages/use-shader-fx/types/misc/useDomSyncer/utils/useIntersectionHandler.d.ts delete mode 100644 packages/use-shader-fx/types/misc/useDomSyncer/utils/useIsIntersecting.d.ts delete mode 100644 packages/use-shader-fx/types/misc/useDomSyncer/utils/useUpdateDomRect.d.ts delete mode 100644 packages/use-shader-fx/types/misc/useFPSLimiter.d.ts delete mode 100644 packages/use-shader-fx/types/misc/usePointer.d.ts delete mode 100644 packages/use-shader-fx/types/utils/createMaterialParameters.d.ts delete mode 100644 packages/use-shader-fx/types/utils/getDpr.d.ts delete mode 100644 packages/use-shader-fx/types/utils/setUniforms.d.ts delete mode 100644 packages/use-shader-fx/types/utils/useAddMesh.d.ts delete mode 100644 packages/use-shader-fx/types/utils/useAddObject.d.ts delete mode 100644 packages/use-shader-fx/types/utils/useCamera.d.ts delete mode 100644 packages/use-shader-fx/types/utils/useDoubleFBO.d.ts delete mode 100644 packages/use-shader-fx/types/utils/useParams.d.ts delete mode 100644 packages/use-shader-fx/types/utils/useResizeBoundary.d.ts delete mode 100644 packages/use-shader-fx/types/utils/useResolution.d.ts delete mode 100644 packages/use-shader-fx/types/utils/useSingleFBO.d.ts diff --git a/app/_home/Playground.tsx b/app/_home/Playground.tsx index b9e883fd..befee727 100644 --- a/app/_home/Playground.tsx +++ b/app/_home/Playground.tsx @@ -12,10 +12,10 @@ import { HSVParams, MarbleParams, useBlank, -} from "@/packages/use-shader-fx/src"; +} from "@/packages/use-shader-fx/legacy"; import { Environment, OrbitControls } from "@react-three/drei"; -import { OnBeforeInitParameters } from "@/packages/use-shader-fx/src/fxs/types"; +// import { OnBeforeInitParameters } from "@/packages/use-shader-fx/src/fxs/types"; export const CONFIG = { marble: { @@ -102,7 +102,7 @@ export const Playground = ({ height: size.height, }, dpr: viewport.dpr, - onBeforeInit: useCallback((params: OnBeforeInitParameters) => { + onBeforeInit: useCallback((params: any) => { Object.assign(params.uniforms, { u_noise: { value: marble, diff --git a/app/v2/FxMaterial.tsx b/app/v2/FxMaterial.tsx new file mode 100644 index 00000000..80a45ce3 --- /dev/null +++ b/app/v2/FxMaterial.tsx @@ -0,0 +1,50 @@ +import * as THREE from "three"; +import { shaderMaterial } from "@react-three/drei"; + +declare global { + namespace JSX { + interface IntrinsicElements { + fxMaterial: any; + } + } +} + +export type FxMaterialProps = { + u_fx: THREE.Texture; +}; + +export const FxMaterial = shaderMaterial( + { + u_fx: new THREE.Texture(), + }, + + ` + varying vec2 vUv; + void main() { + vUv = uv; + gl_Position = vec4(position, 1.0); + } + `, + ` + precision highp float; + varying vec2 vUv; + uniform sampler2D u_fx; + + void main() { + vec2 uv = vUv; + // vec4 color = texture2D(u_fx, uv); + // gl_FragColor = vec4(vec3(color.rgb),1.); + // // gl_FragColor.rgb = color.rgb; + // // gl_FragColor.a = color.r + color.g + color.b; + + vec2 vel = texture2D(u_fx, uv).xy; + float len = length(vel); + vel = vel * 0.5 + 0.5; + + vec3 color = vec3(vel.x, vel.y, 1.0); + color = mix(vec3(1.0), color, len); + + gl_FragColor = vec4(color, 1.0); + } + ` +); diff --git a/app/v2/Playground.tsx b/app/v2/Playground.tsx new file mode 100644 index 00000000..1a644f5c --- /dev/null +++ b/app/v2/Playground.tsx @@ -0,0 +1,31 @@ +"use client"; + +import * as THREE from "three"; +import { useEffect, useMemo, useRef, useState } from "react"; +import { useFrame, useThree, extend, useLoader } from "@react-three/fiber"; +import { useNoise, useFluid } from "@/packages/use-shader-fx/src"; +import { FxMaterial } from "./FxMaterial"; + +extend({ FxMaterial }); + +export const Playground = () => { + const { size, gl } = useThree(); + + const fluid = useFluid({ + size, + dpr: 0.5, + }); + + useFrame((state) => { + fluid.render(state); + }); + + return ( + <> + + + + + + ); +}; diff --git a/app/v2/page.tsx b/app/v2/page.tsx new file mode 100644 index 00000000..a84dd222 --- /dev/null +++ b/app/v2/page.tsx @@ -0,0 +1,18 @@ +import { ShaderFx } from "../ShaderFx"; +import { Playground } from "./Playground"; + +export default function Page() { + return ( +
+ + + +
+ ); +} diff --git a/packages/use-shader-fx/build/use-shader-fx.js b/packages/use-shader-fx/build/use-shader-fx.js deleted file mode 100644 index 726d0fa2..00000000 --- a/packages/use-shader-fx/build/use-shader-fx.js +++ /dev/null @@ -1,4808 +0,0 @@ -import * as o from "three"; -import { useMemo as y, useEffect as Z, useRef as B, useCallback as _, useState as Be } from "react"; -import { mergeVertices as Ee } from "three-stdlib"; -var Le = "#usf ", $e = `precision highp float; - -uniform sampler2D uBuffer; -uniform sampler2D uTexture; -uniform bool uIsTexture; -uniform sampler2D uMap; -uniform bool uIsMap; -uniform float uMapIntensity; -uniform float uRadius; -uniform float uDissipation; -uniform vec2 uResolution; -uniform float uSmudge; -uniform vec2 uMouse; -uniform vec2 uPrevMouse; -uniform vec2 uVelocity; -uniform vec3 uColor; -uniform float uMotionBlur; -uniform int uMotionSample; -uniform bool uIsCursor; -uniform float uPressureStart; -uniform float uPressureEnd; - -varying vec2 vUv; - -float isOnLine(vec2 point, vec2 start, vec2 end, float radius, float pressureStart, float pressureEnd) { - - float aspect = uResolution.x / uResolution.y; - - point.x *= aspect; - start.x *= aspect; - end.x *= aspect; - - vec2 dir = normalize(end - start); - vec2 n = vec2(dir.y, -dir.x); - vec2 p0 = point - start; - - float distToLine = abs(dot(p0, n)); - float distAlongLine = dot(p0, dir); - float totalLength = length(end - start); - - float progress = clamp(distAlongLine / totalLength, 0.0, 1.0); - float pressure = mix(pressureStart, pressureEnd, progress); - radius = min(radius,radius * pressure); - - float distFromStart = length(point - start); - float distFromEnd = length(point - end); - - bool withinLine = (distToLine < radius && distAlongLine > 0.0 && distAlongLine < totalLength) || distFromStart < radius || distFromEnd < radius; - - return float(withinLine); -} - -vec4 createSmudge(vec2 uv){ - vec2 offsets[9]; - offsets[0] = vec2(-1, -1); offsets[1] = vec2( 0, -1); offsets[2] = vec2( 1, -1); - offsets[3] = vec2(-1, 0); offsets[4] = vec2( 0, 0); offsets[5] = vec2( 1, 0); - offsets[6] = vec2(-1, 1); offsets[7] = vec2( 0, 1); offsets[8] = vec2( 1, 1); - - for(int i = 0; i < 9; i++) { - offsets[i] = (offsets[i] * uSmudge) / uResolution; - } - vec4 smudgedColor = vec4(0.); - for(int i = 0; i < 9; i++) { - smudgedColor += texture2D(uBuffer, uv + offsets[i]); - } - return smudgedColor / 9.0; -} - -vec4 createMotionBlur(vec2 uv , vec4 baseColor, vec2 velocity) { - vec2 scaledV = velocity * uMotionBlur; - for(int i = 1; i < uMotionSample; i++) { - float t = float(i) / float(uMotionSample - 1); - vec2 offset = t * scaledV / uResolution; - baseColor += texture2D(uBuffer, uv + offset); - } - return baseColor / float(uMotionSample); -} - -void main() { - - vec2 uv = vUv; - if(uIsMap){ - vec2 mapColor = texture2D(uMap, uv).rg; - vec2 normalizedMap = mapColor * 2.0 - 1.0; - uv = uv * 2.0 - 1.0; - uv *= mix(vec2(1.0), abs(normalizedMap.rg), uMapIntensity); - uv = (uv + 1.0) / 2.0; - } - vec2 suv = uv*2.-1.; - - vec2 velocity = uVelocity * uResolution; - - float radius = max(0.0,uRadius); - - vec4 smudgedColor = uSmudge > 0. ? createSmudge(uv) : texture2D(uBuffer, uv); - - vec4 motionBlurredColor = uMotionBlur > 0. ? createMotionBlur(uv,smudgedColor, velocity) : smudgedColor; - - vec4 bufferColor = motionBlurredColor; - bufferColor.a = bufferColor.a < 1e-10 ? 0.0 : bufferColor.a * uDissipation; - - vec4 brushColor = uIsTexture ? texture2D(uTexture, uv) : vec4(uColor,1.); - - float onLine = isOnLine(suv, uPrevMouse, uMouse, radius, uPressureStart,uPressureEnd); - float isOnLine = length(velocity) > 0. ? onLine : uIsCursor ? onLine : 0.; - - vec4 finalColor = mix(bufferColor, brushColor, isOnLine); - - gl_FragColor = finalColor; -}`; -const K = (e, t = !1) => { - const n = t ? e.width * t : e.width, r = t ? e.height * t : e.height; - return y( - () => new o.Vector2(n, r), - [n, r] - ); -}, R = (e) => (t, n) => { - if (n === void 0) - return; - const r = e.uniforms; - r && r[t] && (r[t].value = n); -}, F = (e) => (t) => { - t !== void 0 && Object.keys(t).forEach((n) => { - const r = e.uniforms; - r && r[n] && (r[n].value = t[n]); - }); -}, E = (e, t, n, r) => { - const s = y(() => { - const l = new r(t, n); - return e && e.add(l), l; - }, [t, n, r, e]); - return Z(() => () => { - e && e.remove(s), t.dispose(), n.dispose(); - }, [e, t, n, s]), s; -}, Re = process.env.NODE_ENV === "development", I = { - transparent: !1, - depthTest: !1, - depthWrite: !1 -}, w = new o.DataTexture( - new Uint8Array([0, 0, 0, 0]), - 1, - 1, - o.RGBAFormat -); -var je = `vec4 permute(vec4 x){return mod(((x*34.0)+1.0)*x, 289.0);} -float permute(float x){return floor(mod(((x*34.0)+1.0)*x, 289.0));} -vec4 taylorInvSqrt(vec4 r){return 1.79284291400159 - 0.85373472095314 * r;} -float taylorInvSqrt(float r){return 1.79284291400159 - 0.85373472095314 * r;} - -vec4 grad4(float j, vec4 ip) -{ - const vec4 ones = vec4(1.0, 1.0, 1.0, -1.0); - vec4 p,s; - - p.xyz = floor( fract (vec3(j) * ip.xyz) * 7.0) * ip.z - 1.0; - p.w = 1.5 - dot(abs(p.xyz), ones.xyz); - s = vec4(lessThan(p, vec4(0.0))); - p.xyz = p.xyz + (s.xyz*2.0 - 1.0) * s.www; - - return p; -} - -float simplexNoise4d(vec4 v) -{ - const vec2 C = vec2( 0.138196601125010504, - 0.309016994374947451); - - vec4 i = floor(v + dot(v, C.yyyy) ); - vec4 x0 = v - i + dot(i, C.xxxx); - - - - - vec4 i0; - - vec3 isX = step( x0.yzw, x0.xxx ); - vec3 isYZ = step( x0.zww, x0.yyz ); - - i0.x = isX.x + isX.y + isX.z; - i0.yzw = 1.0 - isX; - - - i0.y += isYZ.x + isYZ.y; - i0.zw += 1.0 - isYZ.xy; - - i0.z += isYZ.z; - i0.w += 1.0 - isYZ.z; - - - vec4 i3 = clamp( i0, 0.0, 1.0 ); - vec4 i2 = clamp( i0-1.0, 0.0, 1.0 ); - vec4 i1 = clamp( i0-2.0, 0.0, 1.0 ); - - - vec4 x1 = x0 - i1 + 1.0 * C.xxxx; - vec4 x2 = x0 - i2 + 2.0 * C.xxxx; - vec4 x3 = x0 - i3 + 3.0 * C.xxxx; - vec4 x4 = x0 - 1.0 + 4.0 * C.xxxx; - - - i = mod(i, 289.0); - float j0 = permute( permute( permute( permute(i.w) + i.z) + i.y) + i.x); - vec4 j1 = permute( permute( permute( permute ( - i.w + vec4(i1.w, i2.w, i3.w, 1.0 )) - + i.z + vec4(i1.z, i2.z, i3.z, 1.0 )) - + i.y + vec4(i1.y, i2.y, i3.y, 1.0 )) - + i.x + vec4(i1.x, i2.x, i3.x, 1.0 )); - - - - - vec4 ip = vec4(1.0/294.0, 1.0/49.0, 1.0/7.0, 0.0) ; - - vec4 p0 = grad4(j0, ip); - vec4 p1 = grad4(j1.x, ip); - vec4 p2 = grad4(j1.y, ip); - vec4 p3 = grad4(j1.z, ip); - vec4 p4 = grad4(j1.w, ip); - - - vec4 norm = taylorInvSqrt(vec4(dot(p0,p0), dot(p1,p1), dot(p2, p2), dot(p3,p3))); - p0 *= norm.x; - p1 *= norm.y; - p2 *= norm.z; - p3 *= norm.w; - p4 *= taylorInvSqrt(dot(p4,p4)); - - - vec3 m0 = max(0.6 - vec3(dot(x0,x0), dot(x1,x1), dot(x2,x2)), 0.0); - vec2 m1 = max(0.6 - vec2(dot(x3,x3), dot(x4,x4) ), 0.0); - m0 = m0 * m0; - m1 = m1 * m1; - return 49.0 * ( dot(m0*m0, vec3( dot( p0, x0 ), dot( p1, x1 ), dot( p2, x2 ))) - + dot(m1*m1, vec2( dot( p3, x3 ), dot( p4, x4 ) ) ) ) ; - -} - -float getWobble(vec3 position) -{ - vec3 warpedPosition = position; - warpedPosition += simplexNoise4d( - vec4( - position * uWarpPositionFrequency, - uTime * uWarpTimeFrequency - ) - ) * uWarpStrength; - - return simplexNoise4d(vec4( - warpedPosition * uWobblePositionFrequency, - uTime * uWobbleTimeFrequency - )) * uWobbleStrength; -}`, qe = `vec3 random3(vec3 c) { - float j = 4096.0*sin(dot(c,vec3(17.0, 59.4, 15.0))); - vec3 r; - r.z = fract(512.0*j); - j *= .125; - r.x = fract(512.0*j); - j *= .125; - r.y = fract(512.0*j); - return r-0.5; -} - -const float F3 = 0.3333333; -const float G3 = 0.1666667; - -float snoise(vec3 p) { - - vec3 s = floor(p + dot(p, vec3(F3))); - vec3 x = p - s + dot(s, vec3(G3)); - - vec3 e = step(vec3(0.0), x - x.yzx); - vec3 i1 = e*(1.0 - e.zxy); - vec3 i2 = 1.0 - e.zxy*(1.0 - e); - - vec3 x1 = x - i1 + G3; - vec3 x2 = x - i2 + 2.0*G3; - vec3 x3 = x - 1.0 + 3.0*G3; - - vec4 w, d; - - w.x = dot(x, x); - w.y = dot(x1, x1); - w.z = dot(x2, x2); - w.w = dot(x3, x3); - - w = max(0.6 - w, 0.0); - - d.x = dot(random3(s), x); - d.y = dot(random3(s + i1), x1); - d.z = dot(random3(s + i2), x2); - d.w = dot(random3(s + 1.0), x3); - - w *= w; - w *= w; - d *= w; - - return dot(d, vec4(52.0)); -} - -float snoiseFractal(vec3 m) { - return 0.5333333* snoise(m) - +0.2666667* snoise(2.0*m) - +0.1333333* snoise(4.0*m) - +0.0666667* snoise(8.0*m); -}`, We = `float screenAspect = uResolution.x / uResolution.y; -float textureAspect = uTextureResolution.x / uTextureResolution.y; -vec2 aspectRatio = vec2( - min(screenAspect / textureAspect, 1.0), - min(textureAspect / screenAspect, 1.0) -); -vec2 uv = vUv * aspectRatio + (1.0 - aspectRatio) * .5;`, Ne = `vec3 mapColor = texture2D(uMap, uv).rgb; -vec3 normalizedMap = mapColor * 2.0 - 1.0; - -uv = uv * 2.0 - 1.0; -uv *= mix(vec2(1.0), abs(normalizedMap.rg), uMapIntensity); -uv = (uv + 1.0) / 2.0;`, ke = `precision highp float; - -varying vec2 vUv; - -void main() { - vUv = uv; - gl_Position = vec4(position, 1.0); -}`, Ge = `varying vec2 vUv; - -void main() { - vUv = uv; - gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0); -}`, Ke = `vec3 hsv2rgb(vec3 c) -{ - vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0); - vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www); - return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y); -}`, He = `vec3 rgb2hsv(vec3 c) -{ - vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0); - vec4 p = mix(vec4(c.bg, K.wz), vec4(c.gb, K.xy), step(c.b, c.g)); - vec4 q = mix(vec4(p.xyw, c.r), vec4(c.r, p.yzx), step(p.x, c.r)); - - float d = q.x - min(q.w, q.y); - float e = 1.0e-10; - return vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x); -}`; -const Xe = Object.freeze({ - wobble3D: je, - snoise: qe, - coverTexture: We, - fxBlending: Ne, - planeVertex: ke, - defaultVertex: Ge, - hsv2rgb: Ke, - rgb2hsv: He -}), Ye = /^[ \t]*#usf +<([\w\d./]+)>/gm; -function Qe(e, t) { - return ye(Xe[t] || ""); -} -function ye(e) { - return e.replace(Ye, Qe); -} -const V = (e, t) => (t && t(e), e.vertexShader = ye(e.vertexShader), e.fragmentShader = ye(e.fragmentShader), e), Ze = ({ - scene: e, - size: t, - dpr: n, - onBeforeInit: r -}) => { - const s = y(() => new o.PlaneGeometry(2, 2), []), l = y(() => new o.ShaderMaterial({ - ...V( - { - uniforms: { - uBuffer: { value: w }, - uResolution: { value: new o.Vector2(0, 0) }, - uTexture: { value: w }, - uIsTexture: { value: !1 }, - uMap: { value: w }, - uIsMap: { value: !1 }, - uMapIntensity: { value: re.mapIntensity }, - uRadius: { value: re.radius }, - uSmudge: { value: re.smudge }, - uDissipation: { value: re.dissipation }, - uMotionBlur: { value: re.motionBlur }, - uMotionSample: { value: re.motionSample }, - uMouse: { value: new o.Vector2(-10, -10) }, - uPrevMouse: { value: new o.Vector2(-10, -10) }, - uVelocity: { value: new o.Vector2(0, 0) }, - uColor: { value: re.color }, - uIsCursor: { value: !1 }, - uPressureStart: { value: 1 }, - uPressureEnd: { value: 1 } - }, - vertexShader: Le, - fragmentShader: $e - }, - r - ), - ...I, - // Must be transparent - transparent: !0 - }), [r]), c = K(t, n); - R(l)("uResolution", c.clone()); - const i = E(e, s, l, o.Mesh); - return { material: l, mesh: i }; -}, Je = (e, t) => { - const n = t, r = e / t, [s, l] = [n * r / 2, n / 2]; - return { width: s, height: l, near: -1e3, far: 1e3 }; -}, L = (e, t = "OrthographicCamera") => { - const n = K(e), { width: r, height: s, near: l, far: c } = Je( - n.x, - n.y - ); - return y(() => t === "OrthographicCamera" ? new o.OrthographicCamera( - -r, - r, - s, - -s, - l, - c - ) : new o.PerspectiveCamera(50, r / s), [r, s, l, c, t]); -}, Se = (e = 0) => { - const t = B(new o.Vector2(0, 0)), n = B(new o.Vector2(0, 0)), r = B(new o.Vector2(0, 0)), s = B(0), l = B(new o.Vector2(0, 0)), c = B(!1); - return _( - (d) => { - const p = performance.now(); - let f; - c.current && e ? (r.current = r.current.lerp( - d, - 1 - e - ), f = r.current.clone()) : (f = d.clone(), r.current = f), s.current === 0 && (s.current = p, t.current = f); - const x = Math.max(1, p - s.current); - s.current = p, l.current.copy(f).sub(t.current).divideScalar(x); - const a = l.current.length() > 0, v = c.current ? t.current.clone() : f; - return !c.current && a && (c.current = !0), t.current = f, { - currentPointer: f, - prevPointer: v, - diffPointer: n.current.subVectors(f, v), - velocity: l.current, - isVelocityUpdate: a - }; - }, - [e] - ); -}, j = (e) => { - const n = B( - ((s) => Object.values(s).some((l) => typeof l == "function"))(e) ? e : structuredClone(e) - ), r = _((s) => { - if (s !== void 0) - for (const l in s) { - const c = l; - c in n.current && s[c] !== void 0 && s[c] !== null ? n.current[c] = s[c] : console.error( - `"${String( - c - )}" does not exist in the params. or "${String( - c - )}" is null | undefined` - ); - } - }, []); - return [n.current, r]; -}, he = { - depthBuffer: !1 -}, _e = ({ - gl: e, - fbo: t, - scene: n, - camera: r, - onBeforeRender: s, - onSwap: l -}) => { - e.setRenderTarget(t), s(), e.clear(), e.render(n, r), l && l(), e.setRenderTarget(null), e.clear(); -}, $ = (e) => { - var x; - const { - scene: t, - camera: n, - size: r, - dpr: s = !1, - isSizeUpdate: l = !1, - depth: c = !1, - ...i - } = e, d = B(), p = K(r, s); - d.current = y( - () => { - const a = new o.WebGLRenderTarget( - p.x, - p.y, - { - ...he, - ...i - } - ); - return c && (a.depthTexture = new o.DepthTexture( - p.x, - p.y, - o.FloatType - )), a; - }, - // eslint-disable-next-line react-hooks/exhaustive-deps - [] - ), l && ((x = d.current) == null || x.setSize(p.x, p.y)), Z(() => { - const a = d.current; - return () => { - a == null || a.dispose(); - }; - }, []); - const f = _( - (a, v) => { - const u = d.current; - return _e({ - gl: a, - fbo: u, - scene: t, - camera: n, - onBeforeRender: () => v && v({ read: u.texture }) - }), u.texture; - }, - [t, n] - ); - return [d.current, f]; -}, se = (e) => { - var x, a; - const { - scene: t, - camera: n, - size: r, - dpr: s = !1, - isSizeUpdate: l = !1, - depth: c = !1, - ...i - } = e, d = K(r, s), p = y(() => { - const v = new o.WebGLRenderTarget(d.x, d.y, { - ...he, - ...i - }), u = new o.WebGLRenderTarget(d.x, d.y, { - ...he, - ...i - }); - return c && (v.depthTexture = new o.DepthTexture( - d.x, - d.y, - o.FloatType - ), u.depthTexture = new o.DepthTexture( - d.x, - d.y, - o.FloatType - )), { - read: v, - write: u, - swap: function() { - let m = this.read; - this.read = this.write, this.write = m; - } - }; - }, []); - l && ((x = p.read) == null || x.setSize(d.x, d.y), (a = p.write) == null || a.setSize(d.x, d.y)), Z(() => { - const v = p; - return () => { - var u, m; - (u = v.read) == null || u.dispose(), (m = v.write) == null || m.dispose(); - }; - }, [p]); - const f = _( - (v, u) => { - var h; - const m = p; - return _e({ - gl: v, - scene: t, - camera: n, - fbo: m.write, - onBeforeRender: () => u && u({ - read: m.read.texture, - write: m.write.texture - }), - onSwap: () => m.swap() - }), (h = m.read) == null ? void 0 : h.texture; - }, - [t, n, p] - ); - return [ - { read: p.read, write: p.write }, - f - ]; -}, U = (e) => typeof e == "number" ? { shader: e, fbo: e } : { - shader: e.shader ?? !1, - fbo: e.fbo ?? !1 -}, re = Object.freeze({ - texture: !1, - map: !1, - mapIntensity: 0.1, - radius: 0.05, - smudge: 0, - dissipation: 1, - motionBlur: 0, - motionSample: 5, - color: new o.Vector3(1, 0, 0), - isCursor: !1, - pressure: 1, - pointerValues: !1 -}), Jn = ({ - size: e, - dpr: t, - renderTargetOptions: n, - isSizeUpdate: r, - onBeforeInit: s -}) => { - const l = U(t), c = y(() => new o.Scene(), []), { material: i, mesh: d } = Ze({ - scene: c, - size: e, - dpr: l.shader, - onBeforeInit: s - }), p = L(e), f = Se(), [x, a] = se({ - scene: c, - camera: p, - size: e, - dpr: l.fbo, - isSizeUpdate: r, - ...n - }), [v, u] = j(re), m = B(null), h = R(i), M = F(i), b = _( - (S, C) => { - u(S), M(C); - }, - [u, M] - ); - return [ - _( - (S, C, T) => { - const { gl: A, pointer: z } = S; - b(C, T), v.texture ? (h("uIsTexture", !0), h("uTexture", v.texture)) : h("uIsTexture", !1), v.map ? (h("uIsMap", !0), h("uMap", v.map), h("uMapIntensity", v.mapIntensity)) : h("uIsMap", !1), h("uRadius", v.radius), h("uSmudge", v.smudge), h("uDissipation", v.dissipation), h("uMotionBlur", v.motionBlur), h("uMotionSample", v.motionSample); - const P = v.pointerValues || f(z); - P.isVelocityUpdate && (h("uMouse", P.currentPointer), h("uPrevMouse", P.prevPointer)), h("uVelocity", P.velocity); - const q = typeof v.color == "function" ? v.color(P.velocity) : v.color; - return h("uColor", q), h("uIsCursor", v.isCursor), h("uPressureEnd", v.pressure), m.current === null && (m.current = v.pressure), h("uPressureStart", m.current), m.current = v.pressure, a(A, ({ read: D }) => { - h("uBuffer", D); - }); - }, - [h, f, a, v, b] - ), - b, - { - scene: c, - mesh: d, - material: i, - camera: p, - renderTarget: x, - output: x.read.texture - } - ]; -}; -var J = `varying vec2 vUv; -varying vec2 vL; -varying vec2 vR; -varying vec2 vT; -varying vec2 vB; -uniform vec2 texelSize; - -void main () { - vUv = uv; - vL = vUv - vec2(texelSize.x, 0.0); - vR = vUv + vec2(texelSize.x, 0.0); - vT = vUv + vec2(0.0, texelSize.y); - vB = vUv - vec2(0.0, texelSize.y); - gl_Position = vec4(position, 1.0); -}`, et = `precision highp float; - -void main(){ - gl_FragColor = vec4(0.0); -}`; -const tt = () => y(() => new o.ShaderMaterial({ - vertexShader: J, - fragmentShader: et, - ...I -}), []); -var nt = `precision highp float; - -varying vec2 vUv; -uniform sampler2D uVelocity; -uniform sampler2D uSource; -uniform vec2 texelSize; -uniform float dt; -uniform float dissipation; - -void main () { - vec2 coord = vUv - dt * texture2D(uVelocity, vUv).xy * texelSize; - gl_FragColor = vec4(dissipation * texture2D(uSource, coord).rgb,1.); -}`; -const rt = ({ onBeforeInit: e }) => y(() => new o.ShaderMaterial({ - ...V( - { - uniforms: { - uVelocity: { value: w }, - uSource: { value: w }, - texelSize: { value: new o.Vector2() }, - dt: { value: Ae }, - dissipation: { value: 0 } - }, - vertexShader: J, - fragmentShader: nt - }, - e - ), - ...I -}), [e]); -var ot = `precision highp float; - -varying vec2 vUv; -varying vec2 vL; -varying vec2 vR; -varying vec2 vT; -varying vec2 vB; -uniform sampler2D uVelocity; - -vec2 sampleVelocity(in vec2 uv) { - vec2 clampedUV = clamp(uv, 0.0, 1.0); - vec2 multiplier = vec2(1.0, 1.0); - multiplier.x = uv.x < 0.0 || uv.x > 1.0 ? -1.0 : 1.0; - multiplier.y = uv.y < 0.0 || uv.y > 1.0 ? -1.0 : 1.0; - return multiplier * texture2D(uVelocity, clampedUV).xy; -} - -void main () { - float L = sampleVelocity(vL).x; - float R = sampleVelocity(vR).x; - float T = sampleVelocity(vT).y; - float B = sampleVelocity(vB).y; - float div = 0.5 * (R - L + T - B); - gl_FragColor = vec4(div, 0.0, 0.0, 1.0); -}`; -const at = ({ onBeforeInit: e }) => y(() => new o.ShaderMaterial({ - ...V( - { - uniforms: { - uVelocity: { value: null }, - texelSize: { value: new o.Vector2() } - }, - vertexShader: J, - fragmentShader: ot - }, - e - ), - ...I -}), [e]); -var it = `precision highp float; - -varying vec2 vUv; -varying vec2 vL; -varying vec2 vR; -varying vec2 vT; -varying vec2 vB; -uniform sampler2D uPressure; -uniform sampler2D uDivergence; - -void main () { - float L = texture2D(uPressure, clamp(vL,0.,1.)).x; - float R = texture2D(uPressure, clamp(vR,0.,1.)).x; - float T = texture2D(uPressure, clamp(vT,0.,1.)).x; - float B = texture2D(uPressure, clamp(vB,0.,1.)).x; - float C = texture2D(uPressure, vUv).x; - float divergence = texture2D(uDivergence, vUv).x; - float pressure = (L + R + B + T - divergence) * 0.25; - gl_FragColor = vec4(pressure, 0.0, 0.0, 1.0); -}`; -const ut = ({ onBeforeInit: e }) => y(() => new o.ShaderMaterial({ - ...V( - { - uniforms: { - uPressure: { value: null }, - uDivergence: { value: null }, - texelSize: { value: new o.Vector2() } - }, - vertexShader: J, - fragmentShader: it - }, - e - ), - ...I -}), [e]); -var st = `precision highp float; - -varying vec2 vUv; -varying vec2 vL; -varying vec2 vR; -varying vec2 vT; -varying vec2 vB; -uniform sampler2D uVelocity; - -void main () { - float L = texture2D(uVelocity, vL).y; - float R = texture2D(uVelocity, vR).y; - float T = texture2D(uVelocity, vT).x; - float B = texture2D(uVelocity, vB).x; - float vorticity = R - L - T + B; - gl_FragColor = vec4(vorticity, 0.0, 0.0, 1.0); -}`; -const lt = ({ onBeforeInit: e }) => y(() => new o.ShaderMaterial({ - ...V( - { - uniforms: { - uVelocity: { value: null }, - texelSize: { value: new o.Vector2() } - }, - vertexShader: J, - fragmentShader: st - }, - e - ), - ...I -}), [e]); -var ct = `precision highp float; - -varying vec2 vUv; -varying vec2 vT; -varying vec2 vB; -uniform sampler2D uVelocity; -uniform sampler2D uCurl; -uniform float curl; -uniform float dt; - -void main () { - float T = texture2D(uCurl, vT).x; - float B = texture2D(uCurl, vB).x; - float C = texture2D(uCurl, vUv).x; - vec2 force = vec2(abs(T) - abs(B), 0.0); - force *= 1.0 / length(force + 0.00001) * curl * C; - vec2 vel = texture2D(uVelocity, vUv).xy; - gl_FragColor = vec4(vel + force * dt, 0.0, 1.0); -}`; -const vt = ({ onBeforeInit: e }) => y(() => new o.ShaderMaterial({ - ...V( - { - uniforms: { - uVelocity: { value: null }, - uCurl: { value: null }, - curl: { value: 0 }, - dt: { value: Ae }, - texelSize: { value: new o.Vector2() } - }, - vertexShader: J, - fragmentShader: ct - }, - e - ), - ...I -}), [e]); -var mt = `precision highp float; - -varying vec2 vUv; -uniform sampler2D uTexture; -uniform float value; - -void main () { - gl_FragColor = value * texture2D(uTexture, vUv); -}`; -const pt = ({ onBeforeInit: e }) => y(() => new o.ShaderMaterial({ - ...V( - { - uniforms: { - uTexture: { value: w }, - value: { value: 0 }, - texelSize: { value: new o.Vector2() } - }, - vertexShader: J, - fragmentShader: mt - }, - e - ), - ...I -}), [e]); -var dt = `precision highp float; - -varying vec2 vUv; -varying vec2 vL; -varying vec2 vR; -varying vec2 vT; -varying vec2 vB; -uniform sampler2D uPressure; -uniform sampler2D uVelocity; - -void main () { - float L = texture2D(uPressure, clamp(vL,0.,1.)).x; - float R = texture2D(uPressure, clamp(vR,0.,1.)).x; - float T = texture2D(uPressure, clamp(vT,0.,1.)).x; - float B = texture2D(uPressure, clamp(vB,0.,1.)).x; - vec2 velocity = texture2D(uVelocity, vUv).xy; - velocity.xy -= vec2(R - L, T - B); - gl_FragColor = vec4(velocity, 0.0, 1.0); -}`; -const ft = ({ - onBeforeInit: e -}) => y(() => new o.ShaderMaterial({ - ...V( - { - uniforms: { - uPressure: { value: w }, - uVelocity: { value: w }, - texelSize: { value: new o.Vector2() } - }, - vertexShader: J, - fragmentShader: dt - }, - e - ), - ...I -}), [e]); -var gt = `precision highp float; - -varying vec2 vUv; -uniform sampler2D uTarget; -uniform float aspectRatio; -uniform vec3 color; -uniform vec2 point; -uniform float radius; - -void main () { - vec2 nPoint = (point + vec2(1.0)) * 0.5; - vec2 p = vUv - nPoint.xy; - p.x *= aspectRatio; - vec3 splat = exp(-dot(p, p) / radius) * color; - vec3 base = texture2D(uTarget, vUv).xyz; - gl_FragColor = vec4(base + splat, 1.0); -}`; -const ht = ({ onBeforeInit: e }) => y(() => new o.ShaderMaterial({ - ...V( - { - uniforms: { - uTarget: { value: w }, - aspectRatio: { value: 0 }, - color: { value: new o.Vector3() }, - point: { value: new o.Vector2() }, - radius: { value: 0 }, - texelSize: { value: new o.Vector2() } - }, - vertexShader: J, - fragmentShader: gt - }, - e - ), - ...I -}), [e]), X = (e, t) => e(t ?? {}), xt = ({ - scene: e, - size: t, - dpr: n, - customFluidProps: r -}) => { - const s = y(() => new o.PlaneGeometry(2, 2), []), { - curl: l, - vorticity: c, - advection: i, - divergence: d, - pressure: p, - clear: f, - gradientSubtract: x, - splat: a - } = r ?? {}, v = X(tt), u = v.clone(), m = X(lt, l), h = X(vt, c), M = X(rt, i), b = X( - at, - d - ), g = X(ut, p), S = X(pt, f), C = X( - ft, - x - ), T = X(ht, a), A = y( - () => ({ - vorticityMaterial: h, - curlMaterial: m, - advectionMaterial: M, - divergenceMaterial: b, - pressureMaterial: g, - clearMaterial: S, - gradientSubtractMaterial: C, - splatMaterial: T - }), - [ - h, - m, - M, - b, - g, - S, - C, - T - ] - ), z = K(t, n); - y(() => { - R(A.splatMaterial)( - "aspectRatio", - z.x / z.y - ); - for (const D of Object.values(A)) - R(D)( - "texelSize", - new o.Vector2(1 / z.x, 1 / z.y) - ); - }, [z, A]); - const P = E(e, s, v, o.Mesh); - y(() => { - v.dispose(), P.material = u; - }, [v, P, u]), Z(() => () => { - for (const D of Object.values(A)) - D.dispose(); - }, [A]); - const q = _( - (D) => { - P.material = D, P.material.needsUpdate = !0; - }, - [P] - ); - return { materials: A, setMeshMaterial: q, mesh: P }; -}, Ae = 0.016, yt = Object.freeze({ - densityDissipation: 0.98, - velocityDissipation: 0.99, - velocityAcceleration: 10, - pressureDissipation: 0.9, - pressureIterations: 20, - curlStrength: 35, - splatRadius: 2e-3, - fluidColor: new o.Vector3(1, 1, 1), - pointerValues: !1 -}), er = ({ - size: e, - dpr: t, - renderTargetOptions: n, - isSizeUpdate: r, - customFluidProps: s -}) => { - const l = U(t), c = y(() => new o.Scene(), []), { materials: i, setMeshMaterial: d, mesh: p } = xt({ - scene: c, - size: e, - dpr: l.shader, - customFluidProps: s - }), f = L(e), x = Se(), a = y( - () => ({ - scene: c, - camera: f, - dpr: l.fbo, - size: e, - isSizeUpdate: r, - type: o.HalfFloatType, - ...n - }), - [c, f, e, l.fbo, r, n] - ), [v, u] = se(a), [m, h] = se(a), [M, b] = $(a), [g, S] = $(a), [C, T] = se(a), A = B(new o.Vector2(0, 0)), z = B(new o.Vector3(0, 0, 0)), [P, q] = j(yt), D = y( - () => ({ - advection: R(i.advectionMaterial), - splat: R(i.splatMaterial), - curl: R(i.curlMaterial), - vorticity: R(i.vorticityMaterial), - divergence: R(i.divergenceMaterial), - clear: R(i.clearMaterial), - pressure: R(i.pressureMaterial), - gradientSubtract: R(i.gradientSubtractMaterial) - }), - [i] - ), k = y( - () => ({ - advection: F(i.advectionMaterial), - splat: F(i.splatMaterial), - curl: F(i.curlMaterial), - vorticity: F(i.vorticityMaterial), - divergence: F(i.divergenceMaterial), - clear: F(i.clearMaterial), - pressure: F(i.pressureMaterial), - gradientSubtract: F(i.gradientSubtractMaterial) - }), - [i] - ), H = _( - (te, ne) => { - q(te), ne && Object.keys(ne).forEach((ie) => { - k[ie]( - ne[ie] - ); - }); - }, - [q, k] - ); - return [ - _( - (te, ne, ie) => { - const { gl: G, pointer: Ie, size: Ce } = te; - H(ne, ie); - const xe = u(G, ({ read: N }) => { - d(i.advectionMaterial), D.advection("uVelocity", N), D.advection("uSource", N), D.advection( - "dissipation", - P.velocityDissipation - ); - }), ze = h(G, ({ read: N }) => { - d(i.advectionMaterial), D.advection("uVelocity", xe), D.advection("uSource", N), D.advection( - "dissipation", - P.densityDissipation - ); - }), pe = P.pointerValues || x(Ie); - pe.isVelocityUpdate && (u(G, ({ read: N }) => { - d(i.splatMaterial), D.splat("uTarget", N), D.splat("point", pe.currentPointer); - const le = pe.diffPointer.multiply( - A.current.set(Ce.width, Ce.height).multiplyScalar(P.velocityAcceleration) - ); - D.splat( - "color", - z.current.set(le.x, le.y, 1) - ), D.splat("radius", P.splatRadius); - }), h(G, ({ read: N }) => { - d(i.splatMaterial), D.splat("uTarget", N); - const le = typeof P.fluidColor == "function" ? P.fluidColor(pe.velocity) : P.fluidColor; - D.splat("color", le); - })); - const Ue = b(G, () => { - d(i.curlMaterial), D.curl("uVelocity", xe); - }); - u(G, ({ read: N }) => { - d(i.vorticityMaterial), D.vorticity("uVelocity", N), D.vorticity("uCurl", Ue), D.vorticity("curl", P.curlStrength); - }); - const Oe = S(G, () => { - d(i.divergenceMaterial), D.divergence("uVelocity", xe); - }); - T(G, ({ read: N }) => { - d(i.clearMaterial), D.clear("uTexture", N), D.clear("value", P.pressureDissipation); - }), d(i.pressureMaterial), D.pressure("uDivergence", Oe); - let we; - for (let N = 0; N < P.pressureIterations; N++) - we = T(G, ({ read: le }) => { - D.pressure("uPressure", le); - }); - return u(G, ({ read: N }) => { - d(i.gradientSubtractMaterial), D.gradientSubtract("uPressure", we), D.gradientSubtract("uVelocity", N); - }), ze; - }, - [ - i, - D, - d, - b, - h, - S, - x, - T, - u, - P, - H - ] - ), - H, - { - scene: c, - mesh: p, - materials: i, - camera: f, - renderTarget: { - velocity: v, - density: m, - curl: M, - divergence: g, - pressure: C - }, - output: m.read.texture - } - ]; -}; -var bt = "#usf ", Mt = `precision highp float; - -uniform sampler2D uMap; -uniform float uOpacity; - -varying vec2 vUv; - -void main() { - vec2 uv = vUv; - vec3 color = texture2D(uMap, uv).rgb; - gl_FragColor = vec4(color,uOpacity); -}`; -const St = ({ - scale: e, - max: t, - texture: n, - scene: r, - onBeforeInit: s -}) => { - const l = y( - () => new o.PlaneGeometry(e, e), - [e] - ), c = y(() => new o.ShaderMaterial({ - ...V( - { - uniforms: { - uOpacity: { value: 0 }, - uMap: { value: n || w } - }, - vertexShader: bt, - fragmentShader: Mt - }, - s - ), - blending: o.AdditiveBlending, - ...I, - // Must be transparent. - transparent: !0 - }), [n, s]), i = y(() => { - const d = []; - for (let p = 0; p < t; p++) { - const f = c.clone(), x = new o.Mesh(l.clone(), f); - x.rotateZ(2 * Math.PI * Math.random()), x.visible = !1, r.add(x), d.push(x); - } - return d; - }, [l, c, r, t]); - return Z(() => () => { - i.forEach((d) => { - d.geometry.dispose(), Array.isArray(d.material) ? d.material.forEach((p) => p.dispose()) : d.material.dispose(), r.remove(d); - }); - }, [r, i]), i; -}, _t = Object.freeze({ - frequency: 0.01, - rotation: 0.05, - fadeoutSpeed: 0.9, - scale: 0.3, - alpha: 0.6, - pointerValues: !1 -}), tr = ({ - texture: e, - scale: t = 64, - max: n = 100, - size: r, - dpr: s, - renderTargetOptions: l, - isSizeUpdate: c, - onBeforeInit: i -}) => { - const d = U(s), p = y(() => new o.Scene(), []), f = St({ - scale: t, - max: n, - texture: e, - scene: p, - onBeforeInit: i - }), x = L(r), a = Se(), [v, u] = $({ - scene: p, - camera: x, - size: r, - dpr: d.fbo, - isSizeUpdate: c, - ...l - }), [m, h] = j(_t), M = B(0), b = y(() => (S, C) => { - h(S), f.forEach((T) => { - if (T.visible) { - const A = T.material; - T.rotation.z += m.rotation, T.scale.x = m.fadeoutSpeed * T.scale.x + m.scale, T.scale.y = T.scale.x; - const z = A.uniforms.uOpacity.value; - R(A)("uOpacity", z * m.fadeoutSpeed), z < 1e-3 && (T.visible = !1); - } - F(T.material)(C); - }); - }, [f, m, h]); - return [ - _( - (S, C, T) => { - const { gl: A, pointer: z, size: P } = S; - b(C, T); - const q = m.pointerValues || a(z); - if (m.frequency < q.diffPointer.length()) { - const D = f[M.current], k = D.material; - D.visible = !0, D.position.set( - q.currentPointer.x * (P.width / 2), - q.currentPointer.y * (P.height / 2), - 0 - ), D.scale.x = D.scale.y = 0, R(k)("uOpacity", m.alpha), M.current = (M.current + 1) % n; - } - return u(A); - }, - [u, f, a, n, m, b] - ), - b, - { - scene: p, - camera: x, - meshArr: f, - renderTarget: v, - output: v.texture - } - ]; -}; -var Ct = "#usf ", wt = `precision highp float; -precision highp int; - -varying vec2 vUv; -uniform float uTime; -uniform float timeStrength; -uniform int noiseOctaves; -uniform int fbmOctaves; -uniform int warpOctaves; -uniform vec2 warpDirection; -uniform float warpStrength; -uniform float scale; - -const float per = 0.5; -const float PI = 3.14159265359; - -float rnd(vec2 n) { - float a = 0.129898; - float b = 0.78233; - float c = 437.585453; - float dt= dot(n ,vec2(a, b)); - float sn= mod(dt, PI); - return fract(sin(sn) * c); -} - -float interpolate(float a, float b, float x){ - float f = (1.0 - cos(x * PI)) * 0.5; - return a * (1.0 - f) + b * f; -} - -float irnd(vec2 p){ - vec2 i = floor(p); - vec2 f = fract(p); - vec4 v = vec4(rnd(vec2(i.x,i.y)),rnd(vec2(i.x + 1.0,i.y)),rnd(vec2(i.x,i.y + 1.0)),rnd(vec2(i.x + 1.0, i.y + 1.0))); - return interpolate(interpolate(v.x, v.y, f.x), interpolate(v.z, v.w, f.x), f.y); -} - -float noise(vec2 p, float time){ - float t = 0.0; - for(int i = 0; i < noiseOctaves; i++){ - float freq = pow(2.0, float(i)); - float amp = pow(per, float(noiseOctaves - i)); - t += irnd(vec2(p.y / freq + time, p.x / freq + time)) * amp; - } - return t; -} - -float fbm(vec2 x, float time) { - float v = 0.0; - float a = 0.5; - vec2 shift = vec2(100); - mat2 rot = mat2(cos(0.5), sin(0.5), -sin(0.5), cos(0.5)); - float sign = 1.0; - for (int i = 0; i < fbmOctaves; ++i) { - v += a * noise(x, time * sign); - x = rot * x * 2.0 + shift; - a *= 0.5; - sign *= -1.0; - } - return v; -} - -float warp(vec2 x, float g,float time){ - float val = 0.0; - for (int i = 0; i < warpOctaves; i++){ - val = fbm(x + g * vec2(cos(warpDirection.x * val), sin(warpDirection.y * val)), time); - } - return val; -} - -void main() { - float noise = warp(gl_FragCoord.xy * scale ,warpStrength,uTime * timeStrength); - gl_FragColor = vec4(vec3(noise),1.0); -}`; -const Tt = ({ - scene: e, - onBeforeInit: t -}) => { - const n = y(() => new o.PlaneGeometry(2, 2), []), r = y(() => new o.ShaderMaterial({ - ...V( - { - uniforms: { - uTime: { value: 0 }, - scale: { value: oe.scale }, - timeStrength: { value: oe.timeStrength }, - noiseOctaves: { value: oe.noiseOctaves }, - fbmOctaves: { value: oe.fbmOctaves }, - warpOctaves: { value: oe.warpOctaves }, - warpDirection: { value: oe.warpDirection }, - warpStrength: { value: oe.warpStrength } - }, - vertexShader: Ct, - fragmentShader: wt - }, - t - ), - ...I - }), [t]), s = E(e, n, r, o.Mesh); - return { material: r, mesh: s }; -}, oe = Object.freeze({ - scale: 4e-3, - timeStrength: 0.3, - noiseOctaves: 2, - fbmOctaves: 2, - warpOctaves: 2, - warpDirection: new o.Vector2(2, 2), - warpStrength: 8, - beat: !1 -}), nr = ({ - size: e, - dpr: t, - renderTargetOptions: n, - isSizeUpdate: r, - onBeforeInit: s -}) => { - const l = U(t), c = y(() => new o.Scene(), []), { material: i, mesh: d } = Tt({ scene: c, onBeforeInit: s }), p = L(e), [f, x] = $({ - scene: c, - camera: p, - size: e, - dpr: l.fbo, - isSizeUpdate: r, - ...n - }), [a, v] = j(oe), u = R(i), m = F(i), h = _( - (b, g) => { - v(b), m(g); - }, - [v, m] - ); - return [ - _( - (b, g, S) => { - const { gl: C, clock: T } = b; - return h(g, S), u("scale", a.scale), u("timeStrength", a.timeStrength), u("noiseOctaves", a.noiseOctaves), u("fbmOctaves", a.fbmOctaves), u("warpOctaves", a.warpOctaves), u("warpDirection", a.warpDirection), u("warpStrength", a.warpStrength), u("uTime", a.beat || T.getElapsedTime()), x(C); - }, - [x, u, a, h] - ), - h, - { - scene: c, - mesh: d, - material: i, - camera: p, - renderTarget: f, - output: f.texture - } - ]; -}; -var Dt = "#usf ", Pt = `precision highp float; -varying vec2 vUv; - -uniform sampler2D uTexture; -uniform bool isTexture; -uniform sampler2D noise; -uniform bool isNoise; -uniform vec2 noiseStrength; -uniform float laminateLayer; -uniform vec2 laminateInterval; -uniform vec2 laminateDetail; -uniform vec2 distortion; -uniform vec3 colorFactor; -uniform float uTime; -uniform vec2 timeStrength; -uniform float scale; - -void main() { - vec2 uv = vUv; - - vec2 pos = isTexture ? texture2D(uTexture, uv).rg : uv * scale; - vec2 noise = isNoise ? texture2D(noise, uv).rg : vec2(0.0); - float alpha = isTexture ? texture2D(uTexture, uv).a : 1.0; - - - alpha = (alpha < 1e-10) ? 0.0 : alpha; - - vec3 col; - for(float j = 0.0; j < 3.0; j++){ - for(float i = 1.0; i < laminateLayer; i++){ - float timeNoiseSin = sin(uTime / (i + j)) * timeStrength.x + noise.r * noiseStrength.x; - float timeNoiseCos = cos(uTime / (i + j)) * timeStrength.y + noise.g * noiseStrength.y; - pos.x += laminateInterval.x / (i + j) * cos(i * distortion.x * pos.y + timeNoiseSin + sin(i + j)); - pos.y += laminateInterval.y / (i + j) * cos(i * distortion.y * pos.x + timeNoiseCos + sin(i + j)); - } - col[int(j)] = sin(pow(pos.x, 2.) * pow(laminateDetail.x, 2.)) + sin(pow(pos.y, 2.) * pow(laminateDetail.y, 2.)); - } - - col *= colorFactor * alpha; - col = clamp(col, 0.0, 1.0); - - gl_FragColor = vec4(col, alpha); -}`; -const Rt = ({ - scene: e, - onBeforeInit: t -}) => { - const n = y(() => new o.PlaneGeometry(2, 2), []), r = y(() => new o.ShaderMaterial({ - ...V( - { - uniforms: { - uTexture: { value: w }, - isTexture: { value: !1 }, - scale: { value: Y.scale }, - noise: { value: w }, - noiseStrength: { value: Y.noiseStrength }, - isNoise: { value: !1 }, - laminateLayer: { value: Y.laminateLayer }, - laminateInterval: { - value: Y.laminateInterval - }, - laminateDetail: { value: Y.laminateDetail }, - distortion: { value: Y.distortion }, - colorFactor: { value: Y.colorFactor }, - uTime: { value: 0 }, - timeStrength: { value: Y.timeStrength } - }, - vertexShader: Dt, - fragmentShader: Pt - }, - t - ), - ...I - }), [t]), s = E(e, n, r, o.Mesh); - return { material: r, mesh: s }; -}, Y = Object.freeze({ - texture: !1, - scale: 1, - laminateLayer: 1, - laminateInterval: new o.Vector2(0.1, 0.1), - laminateDetail: new o.Vector2(1, 1), - distortion: new o.Vector2(0, 0), - colorFactor: new o.Vector3(1, 1, 1), - timeStrength: new o.Vector2(0, 0), - noise: !1, - noiseStrength: new o.Vector2(0, 0), - beat: !1 -}), rr = ({ - size: e, - dpr: t, - renderTargetOptions: n, - isSizeUpdate: r, - onBeforeInit: s -}) => { - const l = U(t), c = y(() => new o.Scene(), []), { material: i, mesh: d } = Rt({ scene: c, onBeforeInit: s }), p = L(e), [f, x] = $({ - scene: c, - camera: p, - size: e, - dpr: l.fbo, - isSizeUpdate: r, - ...n - }), [a, v] = j(Y), u = R(i), m = F(i), h = _( - (b, g) => { - v(b), m(g); - }, - [v, m] - ); - return [ - _( - (b, g, S) => { - const { gl: C, clock: T } = b; - return h(g, S), a.texture ? (u("uTexture", a.texture), u("isTexture", !0)) : (u("isTexture", !1), u("scale", a.scale)), a.noise ? (u("noise", a.noise), u("isNoise", !0), u("noiseStrength", a.noiseStrength)) : u("isNoise", !1), u("uTime", a.beat || T.getElapsedTime()), u("laminateLayer", a.laminateLayer), u("laminateInterval", a.laminateInterval), u("laminateDetail", a.laminateDetail), u("distortion", a.distortion), u("colorFactor", a.colorFactor), u("timeStrength", a.timeStrength), x(C); - }, - [x, u, a, h] - ), - h, - { - scene: c, - mesh: d, - material: i, - camera: p, - renderTarget: f, - output: f.texture - } - ]; -}; -var At = "#usf ", Vt = `precision highp float; - -varying vec2 vUv; -uniform float u_time; -uniform float u_pattern; -uniform float u_complexity; -uniform float u_complexityAttenuation; -uniform float u_iterations; -uniform float u_timeStrength; -uniform float u_scale; - -vec3 marble(vec3 p){ - vec4 n; - for(float i;i { - const n = y(() => new o.PlaneGeometry(2, 2), []), r = y(() => new o.ShaderMaterial({ - ...V( - { - uniforms: { - u_time: { value: 0 }, - u_pattern: { value: ue.pattern }, - u_complexity: { value: ue.complexity }, - u_complexityAttenuation: { - value: ue.complexityAttenuation - }, - u_iterations: { value: ue.iterations }, - u_timeStrength: { value: ue.timeStrength }, - u_scale: { value: ue.scale } - }, - vertexShader: At, - fragmentShader: Vt - }, - t - ), - ...I - }), [t]), s = E(e, n, r, o.Mesh); - return { material: r, mesh: s }; -}, ue = Object.freeze({ - pattern: 0, - complexity: 2, - complexityAttenuation: 0.2, - iterations: 8, - timeStrength: 0.2, - scale: 2e-3, - beat: !1 -}), or = ({ - size: e, - dpr: t, - renderTargetOptions: n, - isSizeUpdate: r, - onBeforeInit: s -}) => { - const l = U(t), c = y(() => new o.Scene(), []), { material: i, mesh: d } = Ft({ scene: c, onBeforeInit: s }), p = L(e), [f, x] = $({ - scene: c, - camera: p, - size: e, - dpr: l.fbo, - isSizeUpdate: r, - ...n - }), [a, v] = j(ue), u = R(i), m = F(i), h = _( - (b, g) => { - v(b), m(g); - }, - [v, m] - ); - return [ - _( - (b, g, S) => { - const { gl: C, clock: T } = b; - return h(g, S), u("u_pattern", a.pattern), u("u_complexity", a.complexity), u("u_complexityAttenuation", a.complexityAttenuation), u("u_iterations", a.iterations), u("u_timeStrength", a.timeStrength), u("u_scale", a.scale), u("u_time", a.beat || T.getElapsedTime()), x(C); - }, - [x, u, a, h] - ), - h, - { - scene: c, - mesh: d, - material: i, - camera: p, - renderTarget: f, - output: f.texture - } - ]; -}; -var It = "#usf ", zt = `precision highp float; -precision highp int; - -varying vec2 vUv; -uniform sampler2D uTexture; -uniform vec3 uColor1; -uniform vec3 uColor2; -uniform vec3 uColor3; -uniform vec3 uColor4; -uniform vec3 uRgbWeight; - -vec3 cosPalette( float t, vec3 color1, vec3 color2, vec3 color3, vec3 color4 ){ - return color1 + color2 * cos( 6.28318 * ( color3 * t + color4) ); -} - -void main() { - - vec4 tex = texture2D(uTexture, vUv); - float gray = dot(tex.rgb, uRgbWeight); - - vec3 outColor = cosPalette( - gray, - uColor1, - uColor2, - uColor3, - uColor4 - ); - - gl_FragColor = vec4(outColor, tex.a); -}`; -const Ut = ({ - scene: e, - onBeforeInit: t -}) => { - const n = y(() => new o.PlaneGeometry(2, 2), []), r = y(() => new o.ShaderMaterial({ - ...V( - { - uniforms: { - uTexture: { value: w }, - uRgbWeight: { value: ce.rgbWeight }, - uColor1: { value: ce.color1 }, - uColor2: { value: ce.color2 }, - uColor3: { value: ce.color3 }, - uColor4: { value: ce.color4 } - }, - vertexShader: It, - fragmentShader: zt - }, - t - ), - ...I - }), [t]), s = E(e, n, r, o.Mesh); - return { material: r, mesh: s }; -}, ce = Object.freeze({ - texture: w, - color1: new o.Color().set(0.5, 0.5, 0.5), - color2: new o.Color().set(0.5, 0.5, 0.5), - color3: new o.Color().set(1, 1, 1), - color4: new o.Color().set(0, 0.1, 0.2), - rgbWeight: new o.Vector3(0.299, 0.587, 0.114) -}), ar = ({ - size: e, - dpr: t, - renderTargetOptions: n, - isSizeUpdate: r, - onBeforeInit: s -}) => { - const l = U(t), c = y(() => new o.Scene(), []), { material: i, mesh: d } = Ut({ scene: c, onBeforeInit: s }), p = L(e), [f, x] = $({ - scene: c, - camera: p, - size: e, - dpr: l.fbo, - isSizeUpdate: r, - ...n - }), [a, v] = j(ce), u = R(i), m = F(i), h = _( - (b, g) => { - v(b), m(g); - }, - [v, m] - ); - return [ - _( - (b, g, S) => { - const { gl: C } = b; - return h(g, S), u("uTexture", a.texture), u("uColor1", a.color1), u("uColor2", a.color2), u("uColor3", a.color3), u("uColor4", a.color4), u("uRgbWeight", a.rgbWeight), x(C); - }, - [x, u, a, h] - ), - h, - { - scene: c, - mesh: d, - material: i, - camera: p, - renderTarget: f, - output: f.texture - } - ]; -}; -var Ot = "#usf ", Bt = `precision highp float; - -varying vec2 vUv; -uniform sampler2D uTexture; - -uniform vec3 uColor0; -uniform vec3 uColor1; - -void main() { - vec2 uv = vUv; - vec4 texColor = texture2D(uTexture, uv); - float grayscale = dot(texColor.rgb, vec3(0.299, 0.587, 0.114)); - vec3 duotone = mix(uColor0, uColor1, grayscale); - gl_FragColor = vec4(duotone, texColor.a); -}`; -const Et = ({ - scene: e, - onBeforeInit: t -}) => { - const n = y(() => new o.PlaneGeometry(2, 2), []), r = y(() => new o.ShaderMaterial({ - ...V( - { - uniforms: { - uTexture: { value: w }, - uColor0: { value: be.color0 }, - uColor1: { value: be.color1 } - }, - vertexShader: Ot, - fragmentShader: Bt - }, - t - ), - ...I - }), [t]), s = E(e, n, r, o.Mesh); - return { material: r, mesh: s }; -}, be = Object.freeze({ - texture: w, - color0: new o.Color(16777215), - color1: new o.Color(0) -}), ir = ({ - size: e, - dpr: t, - renderTargetOptions: n, - isSizeUpdate: r, - onBeforeInit: s -}) => { - const l = U(t), c = y(() => new o.Scene(), []), { material: i, mesh: d } = Et({ scene: c, onBeforeInit: s }), p = L(e), [f, x] = $({ - scene: c, - camera: p, - size: e, - dpr: l.fbo, - isSizeUpdate: r, - ...n - }), [a, v] = j(be), u = R(i), m = F(i), h = _( - (b, g) => { - v(b), m(g); - }, - [v, m] - ); - return [ - _( - (b, g, S) => { - const { gl: C } = b; - return h(g, S), u("uTexture", a.texture), u("uColor0", a.color0), u("uColor1", a.color1), x(C); - }, - [x, u, a, h] - ), - h, - { - scene: c, - mesh: d, - material: i, - camera: p, - renderTarget: f, - output: f.texture - } - ]; -}; -var Lt = "#usf ", $t = `precision highp float; - -varying vec2 vUv; -uniform sampler2D u_texture; -uniform sampler2D uMap; -uniform bool u_isAlphaMap; -uniform sampler2D u_alphaMap; -uniform float uMapIntensity; -uniform vec3 u_brightness; -uniform float u_min; -uniform float u_max; -uniform vec3 u_dodgeColor; -uniform bool u_isDodgeColor; - -void main() { - vec2 uv = vUv; - - #usf - - - float brightness = dot(mapColor,u_brightness); - vec4 textureMap = texture2D(u_texture, uv); - float blendValue = smoothstep(u_min, u_max, brightness); - - - vec3 dodgeColor = u_isDodgeColor ? u_dodgeColor : mapColor; - vec3 outputColor = blendValue * dodgeColor + (1.0 - blendValue) * textureMap.rgb; - - - float alpha = u_isAlphaMap ? texture2D(u_alphaMap, uv).a : textureMap.a; - float mixValue = u_isAlphaMap ? alpha : 0.0; - vec3 alphaColor = vec3(mix(outputColor,mapColor,mixValue)); - - gl_FragColor = vec4(alphaColor,alpha); -}`; -const jt = ({ - scene: e, - onBeforeInit: t -}) => { - const n = y(() => new o.PlaneGeometry(2, 2), []), r = y(() => new o.ShaderMaterial({ - ...V( - { - uniforms: { - u_texture: { value: w }, - uMap: { value: w }, - u_alphaMap: { value: w }, - u_isAlphaMap: { value: !1 }, - uMapIntensity: { value: ve.mapIntensity }, - u_brightness: { value: ve.brightness }, - u_min: { value: ve.min }, - u_max: { value: ve.max }, - u_dodgeColor: { value: new o.Color() }, - u_isDodgeColor: { value: !1 } - }, - vertexShader: Lt, - fragmentShader: $t - }, - t - ), - ...I - }), [t]), s = E(e, n, r, o.Mesh); - return { material: r, mesh: s }; -}, ve = Object.freeze({ - texture: w, - map: w, - alphaMap: !1, - mapIntensity: 0.3, - brightness: new o.Vector3(0.5, 0.5, 0.5), - min: 0, - max: 1, - dodgeColor: !1 -}), ur = ({ - size: e, - dpr: t, - renderTargetOptions: n, - isSizeUpdate: r, - onBeforeInit: s -}) => { - const l = U(t), c = y(() => new o.Scene(), []), { material: i, mesh: d } = jt({ scene: c, onBeforeInit: s }), p = L(e), [f, x] = $({ - scene: c, - camera: p, - size: e, - dpr: l.fbo, - isSizeUpdate: r, - ...n - }), [a, v] = j(ve), u = R(i), m = F(i), h = _( - (b, g) => { - v(b), m(g); - }, - [v, m] - ); - return [ - _( - (b, g, S) => { - const { gl: C } = b; - return h(g, S), u("u_texture", a.texture), u("uMap", a.map), u("uMapIntensity", a.mapIntensity), a.alphaMap ? (u("u_alphaMap", a.alphaMap), u("u_isAlphaMap", !0)) : u("u_isAlphaMap", !1), u("u_brightness", a.brightness), u("u_min", a.min), u("u_max", a.max), a.dodgeColor ? (u("u_dodgeColor", a.dodgeColor), u("u_isDodgeColor", !0)) : u("u_isDodgeColor", !1), x(C); - }, - [x, u, a, h] - ), - h, - { - scene: c, - mesh: d, - material: i, - camera: p, - renderTarget: f, - output: f.texture - } - ]; -}; -var qt = "#usf ", Wt = `precision highp float; - -varying vec2 vUv; -uniform vec2 uResolution; -uniform vec2 uTextureResolution; -uniform sampler2D uTexture0; -uniform sampler2D uTexture1; -uniform sampler2D uMap; -uniform float mapIntensity; -uniform float edgeIntensity; -uniform float progress; -uniform float dirX; -uniform float dirY; -uniform vec2 epicenter; -uniform float padding; - -bool isInPaddingArea(vec2 uv) { - return uv.x < padding || uv.x > 1.0 - padding || uv.y < padding || uv.y > 1.0 - padding; -} - -void main() { - #usf - - - vec2 map = texture2D(uMap, uv).rg; - vec2 normalizedMap = map * 2.0 - 1.0; - - - uv = uv * 2.0 - 1.0; - uv *= map * distance(epicenter, uv) * edgeIntensity + 1.0; - uv = (uv + 1.0) / 2.0; - - - if (isInPaddingArea(uv)) { - gl_FragColor = vec4(0.0, 0.0, 0.0, 0.0); - return; - } - vec2 paddedUV = uv * (1.0 - 2.0 * padding * -1.) + padding * -1.; - - - vec2 centeredUV = paddedUV - vec2(0.5); - - - centeredUV *= normalizedMap * map * mapIntensity + 1.0; - - - float xOffsetTexture0 = 0.5 - dirX * progress; - float yOffsetTexture0 = 0.5 - dirY * progress; - vec2 samplePosTexture0 = vec2(xOffsetTexture0, yOffsetTexture0) + centeredUV; - - - float xOffsetTexture1 = 0.5 + dirX * (1.0 - progress); - float yOffsetTexture1 = 0.5 + dirY * (1.0 - progress); - vec2 samplePosTexture1 = vec2(xOffsetTexture1, yOffsetTexture1) + centeredUV; - - vec4 color0 = texture2D(uTexture0, samplePosTexture0); - vec4 color1 = texture2D(uTexture1, samplePosTexture1); - - gl_FragColor = mix(color0, color1, progress); - -}`; -const Nt = ({ - scene: e, - size: t, - dpr: n, - onBeforeInit: r -}) => { - const s = y(() => new o.PlaneGeometry(2, 2), []), l = y(() => { - var p, f; - return new o.ShaderMaterial({ - ...V( - { - uniforms: { - uResolution: { value: new o.Vector2() }, - uTextureResolution: { value: new o.Vector2() }, - uTexture0: { value: w }, - uTexture1: { value: w }, - padding: { value: ae.padding }, - uMap: { value: w }, - edgeIntensity: { value: ae.edgeIntensity }, - mapIntensity: { value: ae.mapIntensity }, - epicenter: { value: ae.epicenter }, - progress: { value: ae.progress }, - dirX: { value: (p = ae.dir) == null ? void 0 : p.x }, - dirY: { value: (f = ae.dir) == null ? void 0 : f.y } - }, - vertexShader: qt, - fragmentShader: Wt - }, - r - ), - ...I - }); - }, [r]), c = K(t, n); - R(l)("uResolution", c.clone()); - const i = E(e, s, l, o.Mesh); - return { material: l, mesh: i }; -}, ae = Object.freeze({ - texture0: w, - texture1: w, - padding: 0, - map: w, - mapIntensity: 0, - edgeIntensity: 0, - epicenter: new o.Vector2(0, 0), - progress: 0, - dir: new o.Vector2(0, 0) -}), sr = ({ - size: e, - dpr: t, - renderTargetOptions: n, - isSizeUpdate: r, - onBeforeInit: s -}) => { - const l = U(t), c = y(() => new o.Scene(), []), { material: i, mesh: d } = Nt({ - scene: c, - size: e, - dpr: l.shader, - onBeforeInit: s - }), p = L(e), [f, x] = $({ - scene: c, - camera: p, - dpr: l.fbo, - size: e, - isSizeUpdate: r, - ...n - }), [a, v] = j(ae), u = R(i), m = F(i), h = _( - (b, g) => { - v(b), m(g); - }, - [v, m] - ); - return [ - _( - (b, g, S) => { - var P, q, D, k, H, ee, te, ne; - const { gl: C } = b; - h(g, S), u("uTexture0", a.texture0), u("uTexture1", a.texture1), u("progress", a.progress); - const T = [ - ((q = (P = a.texture0) == null ? void 0 : P.image) == null ? void 0 : q.width) || 0, - ((k = (D = a.texture0) == null ? void 0 : D.image) == null ? void 0 : k.height) || 0 - ], A = [ - ((ee = (H = a.texture1) == null ? void 0 : H.image) == null ? void 0 : ee.width) || 0, - ((ne = (te = a.texture1) == null ? void 0 : te.image) == null ? void 0 : ne.height) || 0 - ], z = T.map((ie, G) => ie + (A[G] - ie) * a.progress); - return u("uTextureResolution", z), u("padding", a.padding), u("uMap", a.map), u("mapIntensity", a.mapIntensity), u("edgeIntensity", a.edgeIntensity), u("epicenter", a.epicenter), u("dirX", a.dir.x), u("dirY", a.dir.y), x(C); - }, - [x, u, a, h] - ), - h, - { - scene: c, - mesh: d, - material: i, - camera: p, - renderTarget: f, - output: f.texture - } - ]; -}; -var kt = "#usf ", Gt = `precision highp float; - -varying vec2 vUv; -uniform sampler2D u_texture; -uniform vec3 u_brightness; -uniform float u_min; -uniform float u_max; - -void main() { - vec2 uv = vUv; - vec3 color = texture2D(u_texture, uv).rgb; - float brightness = dot(color,u_brightness); - float alpha = clamp(smoothstep(u_min, u_max, brightness),0.0,1.0); - gl_FragColor = vec4(color, alpha); -}`; -const Kt = ({ - scene: e, - onBeforeInit: t -}) => { - const n = y(() => new o.PlaneGeometry(2, 2), []), r = y(() => new o.ShaderMaterial({ - ...V( - { - uniforms: { - u_texture: { value: w }, - u_brightness: { value: de.brightness }, - u_min: { value: de.min }, - u_max: { value: de.max } - }, - vertexShader: kt, - fragmentShader: Gt - }, - t - ), - ...I - }), [t]), s = E(e, n, r, o.Mesh); - return { material: r, mesh: s }; -}, de = Object.freeze({ - texture: w, - brightness: new o.Vector3(0.5, 0.5, 0.5), - min: 0, - max: 1 -}), lr = ({ - size: e, - dpr: t, - renderTargetOptions: n, - isSizeUpdate: r, - onBeforeInit: s -}) => { - const l = U(t), c = y(() => new o.Scene(), []), { material: i, mesh: d } = Kt({ scene: c, onBeforeInit: s }), p = L(e), [f, x] = $({ - scene: c, - camera: p, - size: e, - dpr: l.fbo, - isSizeUpdate: r, - ...n - }), [a, v] = j( - de - ), u = R(i), m = F(i), h = _( - (b, g) => { - v(b), m(g); - }, - [v, m] - ); - return [ - _( - (b, g, S) => { - const { gl: C } = b; - return h(g, S), u("u_texture", a.texture), u("u_brightness", a.brightness), u("u_min", a.min), u("u_max", a.max), x(C); - }, - [x, u, a, h] - ), - h, - { - scene: c, - mesh: d, - material: i, - camera: p, - renderTarget: f, - output: f.texture - } - ]; -}; -var Ht = "#usf ", Xt = `precision highp float; - -varying vec2 vUv; -uniform sampler2D u_texture; -uniform sampler2D uMap; -uniform float uMapIntensity; - -void main() { - vec2 uv = vUv; - - #usf - - gl_FragColor = texture2D(u_texture, uv); -}`; -const Yt = ({ - scene: e, - onBeforeInit: t -}) => { - const n = y(() => new o.PlaneGeometry(2, 2), []), r = y(() => new o.ShaderMaterial({ - ...V( - { - uniforms: { - u_texture: { value: w }, - uMap: { value: w }, - uMapIntensity: { value: Ve.mapIntensity } - }, - vertexShader: Ht, - fragmentShader: Xt - }, - t - ), - ...I - }), [t]), s = E(e, n, r, o.Mesh); - return { material: r, mesh: s }; -}, Ve = Object.freeze({ - texture: w, - map: w, - mapIntensity: 0.3 -}), cr = ({ - size: e, - dpr: t, - renderTargetOptions: n, - isSizeUpdate: r, - onBeforeInit: s -}) => { - const l = U(t), c = y(() => new o.Scene(), []), { material: i, mesh: d } = Yt({ scene: c, onBeforeInit: s }), p = L(e), [f, x] = $({ - scene: c, - camera: p, - size: e, - dpr: l.fbo, - isSizeUpdate: r, - ...n - }), [a, v] = j(Ve), u = R(i), m = F(i), h = _( - (b, g) => { - v(b), m(g); - }, - [v, m] - ); - return [ - _( - (b, g, S) => { - const { gl: C } = b; - return h(g, S), u("u_texture", a.texture), u("uMap", a.map), u("uMapIntensity", a.mapIntensity), x(C); - }, - [x, u, a, h] - ), - h, - { - scene: c, - mesh: d, - material: i, - camera: p, - renderTarget: f, - output: f.texture - } - ]; -}; -var Qt = "#usf ", Zt = `precision highp float; - -uniform sampler2D uTexture; -uniform sampler2D uMap; - -varying vec2 vUv; - -void main() { - vec2 uv = vUv; - vec4 tex = texture2D(uTexture, uv); - vec4 map = texture2D(uMap, uv); - gl_FragColor = mix(tex,map,map.a); -}`; -const Jt = ({ - scene: e, - onBeforeInit: t -}) => { - const n = y(() => new o.PlaneGeometry(2, 2), []), r = y(() => new o.ShaderMaterial({ - ...V( - { - uniforms: { - uTexture: { value: w }, - uMap: { value: w } - }, - vertexShader: Qt, - fragmentShader: Zt - }, - t - ), - ...I - }), [t]), s = E(e, n, r, o.Mesh); - return { material: r, mesh: s }; -}, en = Object.freeze({ - texture: w, - map: w -}), vr = ({ - size: e, - dpr: t, - renderTargetOptions: n, - isSizeUpdate: r, - onBeforeInit: s -}) => { - const l = U(t), c = y(() => new o.Scene(), []), { material: i, mesh: d } = Jt({ - scene: c, - size: e, - onBeforeInit: s - }), p = L(e), [f, x] = $({ - scene: c, - camera: p, - size: e, - dpr: l.fbo, - isSizeUpdate: r, - ...n - }), [a, v] = j(en), u = R(i), m = F(i), h = _( - (b, g) => { - v(b), m(g); - }, - [v, m] - ); - return [ - _( - (b, g, S) => { - const { gl: C } = b; - return h(g, S), u("uTexture", a.texture), u("uMap", a.map), x(C); - }, - [u, x, a, h] - ), - h, - { - scene: c, - mesh: d, - material: i, - camera: p, - renderTarget: f, - output: f.texture - } - ]; -}; -var tn = "#usf ", nn = `precision highp float; - -varying vec2 vUv; -uniform sampler2D u_texture; -uniform float u_brightness; -uniform float u_saturation; - -#usf - -#usf - -void main() { - vec4 tex = texture2D(u_texture, vUv); - vec3 hsv = rgb2hsv(tex.rgb); - hsv.y *= u_saturation; - hsv.z *= u_brightness; - vec3 final = hsv2rgb(hsv); - gl_FragColor = vec4(final, tex.a); -}`; -const rn = ({ - scene: e, - onBeforeInit: t -}) => { - const n = y(() => new o.PlaneGeometry(2, 2), []), r = y(() => new o.ShaderMaterial({ - ...V( - { - uniforms: { - u_texture: { value: w }, - u_brightness: { value: Me.brightness }, - u_saturation: { value: Me.saturation } - }, - vertexShader: tn, - fragmentShader: nn - }, - t - ), - ...I - }), [t]), s = E(e, n, r, o.Mesh); - return { material: r, mesh: s }; -}, Me = Object.freeze({ - texture: w, - brightness: 1, - saturation: 1 -}), mr = ({ - size: e, - dpr: t, - renderTargetOptions: n, - isSizeUpdate: r, - onBeforeInit: s -}) => { - const l = U(t), c = y(() => new o.Scene(), []), { material: i, mesh: d } = rn({ - scene: c, - size: e, - onBeforeInit: s - }), p = L(e), [f, x] = $({ - scene: c, - camera: p, - size: e, - dpr: l.fbo, - isSizeUpdate: r, - ...n - }), [a, v] = j(Me), u = R(i), m = F(i), h = _( - (b, g) => { - v(b), m(g); - }, - [v, m] - ); - return [ - _( - (b, g, S) => { - const { gl: C } = b; - return h(g, S), u("u_texture", a.texture), u("u_brightness", a.brightness), u("u_saturation", a.saturation), x(C); - }, - [u, x, a, h] - ), - h, - { - scene: c, - mesh: d, - material: i, - camera: p, - renderTarget: f, - output: f.texture - } - ]; -}; -var on = "#usf ", an = `precision highp float; - -varying vec2 vUv; -uniform vec2 uResolution; -uniform vec2 uTextureResolution; -uniform sampler2D uTexture; - -void main() { - #usf - - gl_FragColor = texture2D(uTexture, uv); -}`; -const un = ({ - scene: e, - size: t, - dpr: n, - onBeforeInit: r -}) => { - const s = y(() => new o.PlaneGeometry(2, 2), []), l = y(() => new o.ShaderMaterial({ - ...V( - { - uniforms: { - uResolution: { value: new o.Vector2() }, - uTextureResolution: { value: new o.Vector2() }, - uTexture: { value: w } - }, - vertexShader: on, - fragmentShader: an - }, - r - ), - ...I - }), [r]), c = K(t, n); - R(l)("uResolution", c.clone()); - const i = E(e, s, l, o.Mesh); - return { material: l, mesh: i }; -}, sn = Object.freeze({ - texture: w -}), pr = ({ - size: e, - dpr: t, - renderTargetOptions: n, - isSizeUpdate: r, - onBeforeInit: s -}) => { - const l = U(t), c = y(() => new o.Scene(), []), { material: i, mesh: d } = un({ - scene: c, - size: e, - dpr: l.shader, - onBeforeInit: s - }), p = L(e), [f, x] = $({ - scene: c, - camera: p, - dpr: l.fbo, - size: e, - isSizeUpdate: r, - ...n - }), [a, v] = j(sn), u = R(i), m = F(i), h = _( - (b, g) => { - v(b), m(g); - }, - [v, m] - ); - return [ - _( - (b, g, S) => { - var T, A, z, P, q, D; - const { gl: C } = b; - return h(g, S), u("uTexture", a.texture), u("uTextureResolution", [ - ((z = (A = (T = a.texture) == null ? void 0 : T.source) == null ? void 0 : A.data) == null ? void 0 : z.width) || 0, - ((D = (q = (P = a.texture) == null ? void 0 : P.source) == null ? void 0 : q.data) == null ? void 0 : D.height) || 0 - ]), x(C); - }, - [x, u, a, h] - ), - h, - { - scene: c, - mesh: d, - material: i, - camera: p, - renderTarget: f, - output: f.texture - } - ]; -}; -var ln = "#usf ", cn = `precision highp float; - -varying vec2 vUv; -uniform sampler2D uTexture; -uniform vec2 uResolution; -uniform float uBlurSize; - -void main() { - vec2 uv = vUv; - vec2 perDivSize = uBlurSize / uResolution; - - - vec4 outColor = vec4( - texture2D(uTexture, uv + perDivSize * vec2(-1.0, -1.0)) + - texture2D(uTexture, uv + perDivSize * vec2(0.0, -1.0)) + - texture2D(uTexture, uv + perDivSize * vec2(1.0, -1.0)) + - texture2D(uTexture, uv + perDivSize * vec2(-1.0, 0.0)) + - texture2D(uTexture, uv + perDivSize * vec2(0.0, 0.0)) + - texture2D(uTexture, uv + perDivSize * vec2(1.0, 0.0)) + - texture2D(uTexture, uv + perDivSize * vec2(-1.0, 1.0)) + - texture2D(uTexture, uv + perDivSize * vec2(0.0, 1.0)) + - texture2D(uTexture, uv + perDivSize * vec2(1.0, 1.0)) - ) / 9.0; - - gl_FragColor = outColor; -}`; -const vn = ({ - scene: e, - onBeforeInit: t -}) => { - const n = y(() => new o.PlaneGeometry(2, 2), []), r = y(() => new o.ShaderMaterial({ - ...V( - { - uniforms: { - uTexture: { value: w }, - uResolution: { value: new o.Vector2(0, 0) }, - uBlurSize: { value: Fe.blurSize } - }, - vertexShader: ln, - fragmentShader: cn - }, - t - ), - ...I - }), [t]), s = E(e, n, r, o.Mesh); - return { material: r, mesh: s }; -}, Fe = Object.freeze({ - texture: w, - blurSize: 3, - blurPower: 5 -}), dr = ({ - size: e, - dpr: t, - renderTargetOptions: n, - isSizeUpdate: r, - onBeforeInit: s -}) => { - const l = U(t), c = y(() => new o.Scene(), []), { material: i, mesh: d } = vn({ scene: c, onBeforeInit: s }), p = L(e), f = y( - () => ({ - scene: c, - camera: p, - size: e, - dpr: l.fbo, - isSizeUpdate: r, - ...n - }), - [c, p, e, l.fbo, r, n] - ), [x, a] = se(f), [v, u] = j(Fe), m = R(i), h = F(i), M = _( - (g, S) => { - u(g), h(S); - }, - [u, h] - ); - return [ - _( - (g, S, C) => { - var z, P, q, D, k, H; - const { gl: T } = g; - M(S, C), m("uTexture", v.texture), m("uResolution", [ - ((q = (P = (z = v.texture) == null ? void 0 : z.source) == null ? void 0 : P.data) == null ? void 0 : q.width) || 0, - ((H = (k = (D = v.texture) == null ? void 0 : D.source) == null ? void 0 : k.data) == null ? void 0 : H.height) || 0 - ]), m("uBlurSize", v.blurSize); - let A = a(T); - for (let ee = 0; ee < v.blurPower; ee++) - m("uTexture", A), A = a(T); - return A; - }, - [a, m, v, M] - ), - M, - { - scene: c, - mesh: d, - material: i, - camera: p, - renderTarget: x, - output: x.read.texture - } - ]; -}; -var mn = "#usf ", pn = `precision highp float; - -varying vec2 vUv; -uniform sampler2D uTexture; -uniform sampler2D uBackbuffer; -uniform vec2 uBegin; -uniform vec2 uEnd; -uniform float uStrength; - -void main() { - vec2 uv = vUv; - vec4 current = texture2D(uTexture, uv + uBegin*.1); - vec4 back = texture2D(uBackbuffer, uv + uEnd*.1); - vec4 mixed = mix(current,back,uStrength); - gl_FragColor = mixed; -}`; -const dn = ({ - scene: e, - onBeforeInit: t -}) => { - const n = y(() => new o.PlaneGeometry(2, 2), []), r = y(() => new o.ShaderMaterial({ - ...V( - { - uniforms: { - uTexture: { value: w }, - uBackbuffer: { value: w }, - uBegin: { value: fe.begin }, - uEnd: { value: fe.end }, - uStrength: { value: fe.strength } - }, - vertexShader: mn, - fragmentShader: pn - }, - t - ), - ...I - }), [t]), s = E(e, n, r, o.Mesh); - return { material: r, mesh: s }; -}, fe = Object.freeze({ - texture: w, - begin: new o.Vector2(0, 0), - end: new o.Vector2(0, 0), - strength: 0.9 -}), fr = ({ - size: e, - dpr: t, - renderTargetOptions: n, - isSizeUpdate: r, - onBeforeInit: s -}) => { - const l = U(t), c = y(() => new o.Scene(), []), { material: i, mesh: d } = dn({ scene: c, onBeforeInit: s }), p = L(e), f = y( - () => ({ - scene: c, - camera: p, - size: e, - dpr: l.fbo, - isSizeUpdate: r, - ...n - }), - [c, p, e, l.fbo, r, n] - ), [x, a] = se(f), [v, u] = j(fe), m = R(i), h = F(i), M = _( - (g, S) => { - u(g), h(S); - }, - [u, h] - ); - return [ - _( - (g, S, C) => { - const { gl: T } = g; - return M(S, C), m("uTexture", v.texture), m("uBegin", v.begin), m("uEnd", v.end), m("uStrength", v.strength), a(T, ({ read: A }) => { - m("uBackbuffer", A); - }); - }, - [a, m, M, v] - ), - M, - { - scene: c, - mesh: d, - material: i, - camera: p, - renderTarget: x, - output: x.read.texture - } - ]; -}; -var fn = "#usf ", gn = `precision highp float; - -varying vec2 vUv; -uniform float uProgress; -uniform float uStrength; -uniform float uWidth; -uniform vec2 uEpicenter; -uniform int uMode; - -float PI = 3.141592653589; - -void main() { - - vec2 uv = vUv; - - float progress = min(uProgress, 1.0); - float progressFactor = sin(progress * PI); - - float border = progress - progress * progressFactor * uWidth; - float blur = uStrength * progressFactor; - - - vec2 normalizeCenter = (uEpicenter + 1.0) / 2.0; - - - float dist = uMode == 0 ? length(uv - normalizeCenter) : uMode == 1 ? length(uv.x - normalizeCenter.x) : length(uv.y - normalizeCenter.y); - - - float maxDistance = max( - length(vec2(0.0, 0.0) - normalizeCenter), - max( - length(vec2(1.0, 0.0) - normalizeCenter), - max( - length(vec2(0.0, 1.0) - normalizeCenter), - length(vec2(1.0, 1.0) - normalizeCenter) - ) - ) - ); - - - dist = maxDistance > 0.0 ? dist / maxDistance : dist; - - vec3 color = vec3(smoothstep(border - blur, border, dist) - - smoothstep(progress, progress + blur, dist)); - - - color *= progressFactor; - - gl_FragColor = vec4(color, 1.0); -}`; -const hn = ({ - scene: e, - onBeforeInit: t -}) => { - const n = y(() => new o.PlaneGeometry(2, 2), []), r = y(() => new o.ShaderMaterial({ - ...V( - { - uniforms: { - uEpicenter: { value: me.epicenter }, - uProgress: { value: me.progress }, - uStrength: { value: me.strength }, - uWidth: { value: me.width }, - uMode: { value: 0 } - }, - vertexShader: fn, - fragmentShader: gn - }, - t - ), - ...I - }), [t]), s = E(e, n, r, o.Mesh); - return { material: r, mesh: s }; -}, me = Object.freeze({ - epicenter: new o.Vector2(0, 0), - progress: 0, - width: 0, - strength: 0, - mode: "center" -}), gr = ({ - size: e, - dpr: t, - renderTargetOptions: n, - isSizeUpdate: r, - onBeforeInit: s -}) => { - const l = U(t), c = y(() => new o.Scene(), []), { material: i, mesh: d } = hn({ scene: c, onBeforeInit: s }), p = L(e), [f, x] = $({ - scene: c, - camera: p, - size: e, - dpr: l.fbo, - isSizeUpdate: r, - ...n - }), [a, v] = j(me), u = R(i), m = F(i), h = _( - (b, g) => { - v(b), m(g); - }, - [v, m] - ); - return [ - _( - (b, g, S) => { - const { gl: C } = b; - return h(g, S), u("uEpicenter", a.epicenter), u("uProgress", a.progress), u("uWidth", a.width), u("uStrength", a.strength), u( - "uMode", - a.mode === "center" ? 0 : a.mode === "horizontal" ? 1 : 2 - ), x(C); - }, - [x, u, a, h] - ), - h, - { - scene: c, - mesh: d, - material: i, - camera: p, - renderTarget: f, - output: f.texture - } - ]; -}; -var xn = "#usf ", yn = `precision highp float; -varying vec2 vUv; - -uniform sampler2D u_texture; -uniform vec2 u_resolution; -uniform vec3 u_keyColor; -uniform float u_similarity; -uniform float u_smoothness; -uniform float u_spill; - -uniform vec4 u_color; -uniform float u_contrast; -uniform float u_brightness; -uniform float u_gamma; - -vec2 RGBtoUV(vec3 rgb) { - return vec2( - rgb.r * -0.169 + rgb.g * -0.331 + rgb.b * 0.5 + 0.5, - rgb.r * 0.5 + rgb.g * -0.419 + rgb.b * -0.081 + 0.5 - ); -} -float getChromeDist(vec3 texColor){ - float chromaDist = distance(RGBtoUV(texColor), RGBtoUV(u_keyColor)); - return chromaDist; -} - -float getBoxFilteredChromaDist(vec3 rgb, vec2 uv) -{ - vec2 pixel_size = vec2(1.) / u_resolution; - vec2 h_pixel_size = pixel_size / 2.0; - vec2 point_0 = vec2(pixel_size.x, h_pixel_size.y); - vec2 point_1 = vec2(h_pixel_size.x, -pixel_size.y); - float distVal = getChromeDist(texture2D(u_texture,uv-point_0).rgb); - distVal += getChromeDist(texture2D(u_texture,uv+point_0).rgb); - distVal += getChromeDist(texture2D(u_texture,uv-point_1).rgb); - distVal += getChromeDist(texture2D(u_texture,uv+point_1).rgb); - distVal *= 2.0; - distVal += getChromeDist(rgb); - return distVal / 9.0; -} - -vec4 CalcColor(vec4 rgba) -{ - return vec4(pow(rgba.rgb, vec3(u_gamma, u_gamma, u_gamma)) * u_contrast + u_brightness, rgba.a); -} - -void main() { - - vec2 uv = vUv; - - vec4 texColor = texture2D(u_texture, uv); - texColor.rgb *= (texColor.a > 0.) ? (1. / texColor.a) : 0.; - - float chromaDist = getBoxFilteredChromaDist(texColor.rgb,uv); - - float baseMask = chromaDist - u_similarity; - float fullMask = pow(clamp(baseMask / u_smoothness, 0., 1.), 1.5); - - texColor.rgba *= u_color; - texColor.a = fullMask; - - float spillVal = pow(clamp(baseMask / u_spill, 0., 1.), 1.5); - float desat = clamp(texColor.r * 0.2126 + texColor.g * 0.7152 + texColor.b * 0.0722, 0., 1.); - texColor.rgb = mix(vec3(desat, desat, desat), texColor.rgb, spillVal); - - vec4 finColor = CalcColor(texColor); - - gl_FragColor = finColor; -}`; -const bn = ({ - scene: e, - size: t, - dpr: n, - onBeforeInit: r -}) => { - const s = y(() => new o.PlaneGeometry(2, 2), []), l = y(() => new o.ShaderMaterial({ - ...V( - { - uniforms: { - u_texture: { value: w }, - u_resolution: { value: new o.Vector2() }, - u_keyColor: { value: Q.color }, - u_similarity: { value: Q.similarity }, - u_smoothness: { value: Q.smoothness }, - u_spill: { value: Q.spill }, - u_color: { value: Q.color }, - u_contrast: { value: Q.contrast }, - u_brightness: { value: Q.brightness }, - u_gamma: { value: Q.gamma } - }, - vertexShader: xn, - fragmentShader: yn - }, - r - ), - ...I - }), [r]), c = K(t, n); - R(l)("u_resolution", c.clone()); - const i = E(e, s, l, o.Mesh); - return { material: l, mesh: i }; -}, Q = Object.freeze({ - texture: w, - keyColor: new o.Color(65280), - similarity: 0.2, - smoothness: 0.1, - spill: 0.2, - color: new o.Vector4(1, 1, 1, 1), - contrast: 1, - brightness: 0, - gamma: 1 -}), hr = ({ - size: e, - dpr: t, - renderTargetOptions: n, - isSizeUpdate: r, - onBeforeInit: s -}) => { - const l = U(t), c = y(() => new o.Scene(), []), { material: i, mesh: d } = bn({ - scene: c, - size: e, - dpr: l.shader, - onBeforeInit: s - }), p = L(e), [f, x] = $({ - scene: c, - camera: p, - size: e, - dpr: l.fbo, - isSizeUpdate: r, - ...n - }), [a, v] = j(Q), u = R(i), m = F(i), h = _( - (b, g) => { - v(b), m(g); - }, - [v, m] - ); - return [ - _( - (b, g, S) => { - const { gl: C } = b; - return h(g, S), u("u_texture", a.texture), u("u_keyColor", a.keyColor), u("u_similarity", a.similarity), u("u_smoothness", a.smoothness), u("u_spill", a.spill), u("u_color", a.color), u("u_contrast", a.contrast), u("u_brightness", a.brightness), u("u_gamma", a.gamma), x(C); - }, - [x, u, a, h] - ), - h, - { - scene: c, - mesh: d, - material: i, - camera: p, - renderTarget: f, - output: f.texture - } - ]; -}; -var Mn = `precision highp float; - -varying vec2 vUv; -#usf - -#usf - -void main() { - vec4 usf_Position = vec4(position,1.); - vUv = uv; - - #usf
- - gl_Position = usf_Position; -}`, Sn = `precision highp float; - -varying vec2 vUv; -#usf - -uniform sampler2D uTexture; -uniform sampler2D uBackbuffer; -uniform float uTime; -uniform vec2 uPointer; -uniform vec2 uResolution; - -#usf - -void main() { - vec4 usf_FragColor = vec4(1.); - - #usf
- - gl_FragColor = usf_FragColor; -}`; -const _n = ({ - scene: e, - size: t, - dpr: n, - onBeforeInit: r -}) => { - const s = y(() => new o.PlaneGeometry(2, 2), []), l = y(() => new o.ShaderMaterial({ - ...V( - { - uniforms: { - uTexture: { value: w }, - uBackbuffer: { value: w }, - uTime: { value: 0 }, - uPointer: { value: new o.Vector2() }, - uResolution: { value: new o.Vector2() } - }, - vertexShader: Mn, - fragmentShader: Sn - }, - r - ), - ...I - }), [r]), c = K(t, n); - R(l)("uResolution", c.clone()); - const i = E(e, s, l, o.Mesh); - return { material: l, mesh: i }; -}, Cn = Object.freeze({ - texture: w, - beat: !1 -}), xr = ({ - size: e, - dpr: t, - renderTargetOptions: n, - isSizeUpdate: r, - onBeforeInit: s -}) => { - const l = U(t), c = y(() => new o.Scene(), []), { material: i, mesh: d } = _n({ - scene: c, - size: e, - dpr: l.shader, - onBeforeInit: s - }), p = L(e), f = y( - () => ({ - scene: c, - camera: p, - size: e, - dpr: l.fbo, - isSizeUpdate: r, - ...n - }), - [c, p, e, l.fbo, r, n] - ), [x, a] = se(f), [v, u] = j(Cn), m = R(i), h = F(i), M = _( - (g, S) => { - u(g), h(S); - }, - [u, h] - ); - return [ - _( - (g, S, C) => { - const { gl: T, clock: A, pointer: z } = g; - return M(S, C), m("uPointer", z), m("uTexture", v.texture), m("uTime", v.beat || A.getElapsedTime()), a(T, ({ read: P }) => { - m("uBackbuffer", P); - }); - }, - [a, m, v, M] - ), - M, - { - scene: c, - mesh: d, - material: i, - camera: p, - renderTarget: x, - output: x.read.texture - } - ]; -}; -var wn = `precision highp float; - -varying vec2 vUv; -#usf - -#usf - -void main() { - vec4 usf_Position = vec4(position,1.); - vUv = uv; - - #usf
- - gl_Position = usf_Position; -}`, Tn = `precision highp float; - -varying vec2 vUv; -#usf - -uniform vec2 uResolution; - -#usf - -void main() { - vec4 usf_FragColor = vec4(1.); - - #usf
- - gl_FragColor = usf_FragColor; -}`; -const Dn = ({ - scene: e, - size: t, - dpr: n, - onBeforeInit: r -}) => { - const s = y(() => new o.PlaneGeometry(2, 2), []), l = y(() => new o.ShaderMaterial({ - ...V( - { - uniforms: { - uResolution: { value: new o.Vector2() } - }, - vertexShader: wn, - fragmentShader: Tn - }, - r - ), - ...I - }), [r]), c = K(t, n); - R(l)("uResolution", c.clone()); - const i = E(e, s, l, o.Mesh); - return { material: l, mesh: i }; -}, yr = Object.freeze({}), br = ({ - size: e, - dpr: t, - renderTargetOptions: n, - isSizeUpdate: r, - onBeforeInit: s -}) => { - const l = U(t), c = y(() => new o.Scene(), []), { material: i, mesh: d } = Dn({ - scene: c, - size: e, - dpr: l.shader, - onBeforeInit: s - }), p = L(e), f = y( - () => ({ - scene: c, - camera: p, - size: e, - dpr: l.fbo, - isSizeUpdate: r, - ...n - }), - [c, p, e, l.fbo, r, n] - ), [x, a] = $(f), v = F(i), u = _( - (h, M) => { - v(M); - }, - [v] - ); - return [ - _( - (h, M, b) => { - const { gl: g } = h; - return u(M, b), a(g); - }, - [a, u] - ), - u, - { - scene: c, - mesh: d, - material: i, - camera: p, - renderTarget: x, - output: x.texture - } - ]; -}, Pn = ({ - scene: e, - geometry: t, - material: n -}) => { - const r = E( - e, - t, - n, - o.Points - ), s = E( - e, - y(() => t.clone(), [t]), - y(() => n.clone(), [n]), - o.Mesh - ); - return s.visible = !1, { - points: r, - interactiveMesh: s - }; -}; -var Rn = `uniform vec2 uResolution; -uniform float uMorphProgress; -uniform float uPointSize; - -uniform sampler2D uPicture; -uniform bool uIsPicture; -uniform sampler2D uAlphaPicture; -uniform bool uIsAlphaPicture; - -uniform vec3 uColor0; -uniform vec3 uColor1; -uniform vec3 uColor2; -uniform vec3 uColor3; - -uniform float uTime; - -uniform float uWobblePositionFrequency; -uniform float uWobbleTimeFrequency; -uniform float uWobbleStrength; -uniform float uWarpPositionFrequency; -uniform float uWarpTimeFrequency; -uniform float uWarpStrength; - -uniform sampler2D uDisplacement; -uniform bool uIsDisplacement; -uniform float uDisplacementIntensity; - -uniform float uSizeRandomIntensity; -uniform float uSizeRandomTimeFrequency; -uniform float uSizeRandomMin; -uniform float uSizeRandomMax; - -uniform float uMapArrayLength; - -uniform float uDivergence; -uniform vec3 uDivergencePoint; - -varying vec3 vColor; -varying float vPictureAlpha; -varying vec3 vDisplacementColor; -varying float vDisplacementIntensity; -varying float vMapArrayIndex; - -#usf - -#usf - -#usf - -float random3D(vec3 co) { - return fract(sin(dot(co.xyz ,vec3(12.9898, 78.233, 45.764))) * 43758.5453); -} - -void main() { - vec3 newPosition = position; - vec2 newUv = uv; - - #usf - #usf - - - vec3 displacement = uIsDisplacement ? texture2D(uDisplacement, newUv).rgb : vec3(0.0); - float displacementIntensity = smoothstep(0., 1., displacement.g); - vDisplacementColor = displacement; - vDisplacementIntensity = displacementIntensity; - - - displacement = displacement * 2.-1.; - displacement *= displacementIntensity * uDisplacementIntensity; - newPosition += displacement; - - - vec3 divergenceDir = newPosition - uDivergencePoint; - if (uDivergence > 0.0) { - newPosition += normalize(divergenceDir) * uDivergence; - } else if (uDivergence < 0.0) { - newPosition -= normalize(divergenceDir) * abs(uDivergence); - } - - - vec4 modelPosition = modelMatrix * vec4(newPosition, 1.0); - vec4 viewPosition = viewMatrix * modelPosition; - vec4 projectedPosition = projectionMatrix * viewPosition; - - - float wobble = uWobbleStrength > 0. ? getWobble(projectedPosition.xyz) : 0.0; - - gl_Position = projectedPosition += wobble; - - - vColor = uIsPicture ? texture2D(uPicture, newUv).rgb : mix(mix(uColor0, uColor1, newPosition.x), mix(uColor2, uColor3, newPosition.y), newPosition.z); - - - vPictureAlpha = uIsAlphaPicture ? texture2D(uAlphaPicture, newUv).g : 1.; - - - - float sizeRand = uSizeRandomIntensity > 0. ? mix(uSizeRandomMin,uSizeRandomMax,(simplexNoise4d(vec4(newPosition,uTime * uSizeRandomTimeFrequency))*.5+.5)) * uSizeRandomIntensity : 1.; - gl_PointSize = uPointSize * vPictureAlpha * uResolution.y * sizeRand; - gl_PointSize *= (1.0 / - viewPosition.z); - - - vMapArrayIndex = uMapArrayLength > 0. ? floor(random3D(position) * uMapArrayLength) : 0.; -}`, An = `precision highp float; -precision highp int; - -varying vec3 vColor; -varying float vPictureAlpha; -varying vec3 vDisplacementColor; -varying float vDisplacementIntensity; -varying float vMapArrayIndex; - -uniform float uBlurAlpha; -uniform float uBlurRadius; -uniform sampler2D uMap; -uniform bool uIsMap; -uniform sampler2D uAlphaMap; -uniform bool uIsAlphaMap; -uniform float uDisplacementColorIntensity; -uniform float uPointAlpha; - -#usf - -void main() { - vec2 uv = gl_PointCoord; - uv.y = 1.0 - uv.y; - - - float distanceToCenter = length(uv - .5); - float alpha = clamp(uBlurRadius / distanceToCenter - (1.-uBlurAlpha) , 0. , 1.); - - - vec4 mapArrayColor; - #usf - vec4 mapColor = isMapArray ? mapArrayColor : uIsMap ? texture2D(uMap,uv) : vec4(1.); - vec3 finalColor = isMapArray || uIsMap ? mapColor.rgb : vColor; - - - float mixIntensity = clamp(uDisplacementColorIntensity * vDisplacementIntensity,0.,1.); - finalColor = vDisplacementIntensity > 0. ? mix(finalColor,vDisplacementColor,mixIntensity) : finalColor; - - - float alphaMap = uIsAlphaMap ? texture2D(uAlphaMap,uv).g : 1.; - - gl_FragColor = vec4(finalColor,alpha * vPictureAlpha * alphaMap * mapColor.a * uPointAlpha); -}`; -const Te = (e, t, n, r, s) => { - var f; - const l = n === "position" ? "positionTarget" : "uvTarget", c = n === "position" ? "#usf " : "#usf ", i = n === "position" ? "#usf " : "#usf ", d = n === "position" ? "positionsList" : "uvsList", p = n === "position" ? ` - float scaledProgress = uMorphProgress * ${e.length - 1}.; - int baseIndex = int(floor(scaledProgress)); - baseIndex = clamp(baseIndex, 0, ${e.length - 1}); - float progress = fract(scaledProgress); - int nextIndex = baseIndex + 1; - newPosition = mix(positionsList[baseIndex], positionsList[nextIndex], progress); - ` : "newUv = mix(uvsList[baseIndex], uvsList[nextIndex], progress);"; - if (e.length > 0) { - t.deleteAttribute(n), t.setAttribute( - n, - new o.BufferAttribute(e[0], s) - ); - let x = "", a = ""; - e.forEach((v, u) => { - t.setAttribute( - `${l}${u}`, - new o.BufferAttribute(v, s) - ), x += `attribute vec${s} ${l}${u}; -`, u === 0 ? a += `${l}${u}` : a += `,${l}${u}`; - }), r = r.replace( - `${c}`, - x - ), r = r.replace( - `${i}`, - `vec${s} ${d}[${e.length}] = vec${s}[](${a}); - ${p} - ` - ); - } else - r = r.replace(`${c}`, ""), r = r.replace(`${i}`, ""), (f = t == null ? void 0 : t.attributes[n]) != null && f.array || Re && console.error( - `use-shader-fx:geometry.attributes.${n}.array is not found` - ); - return r; -}, De = (e, t, n, r) => { - var l; - let s = []; - if (e && e.length > 0) { - (l = t == null ? void 0 : t.attributes[n]) != null && l.array ? s = [ - t.attributes[n].array, - ...e - ] : s = e; - const c = Math.max(...s.map((i) => i.length)); - s.forEach((i, d) => { - if (i.length < c) { - const p = (c - i.length) / r, f = [], x = Array.from(i); - for (let a = 0; a < p; a++) { - const v = Math.floor(i.length / r * Math.random()) * r; - for (let u = 0; u < r; u++) - f.push(x[v + u]); - } - s[d] = new Float32Array([...x, ...f]); - } - }); - } - return s; -}, Vn = (e, t) => { - let n = ""; - const r = {}; - let s = "mapArrayColor = "; - return e && e.length > 0 ? (e.forEach((c, i) => { - const d = `vMapArrayIndex < ${i}.1`, p = `texture2D(uMapArray${i}, uv)`; - s += `( ${d} ) ? ${p} : `, n += ` - uniform sampler2D uMapArray${i}; - `, r[`uMapArray${i}`] = { value: c }; - }), s += "vec4(1.);", n += "bool isMapArray = true;", r.uMapArrayLength = { value: e.length }) : (s += "vec4(1.0);", n += "bool isMapArray = false;", r.uMapArrayLength = { value: 0 }), { rewritedFragmentShader: t.replace("#usf ", s).replace("#usf ", n), mapArrayUniforms: r }; -}, Fn = ({ - size: e, - dpr: t, - geometry: n, - positions: r, - uvs: s, - mapArray: l, - onBeforeInit: c -}) => { - const i = y( - () => De(r, n, "position", 3), - [r, n] - ), d = y( - () => De(s, n, "uv", 2), - [s, n] - ), p = y(() => { - i.length !== d.length && Re && console.log("use-shader-fx:positions and uvs are not matched"); - const x = Te( - d, - n, - "uv", - Te( - i, - n, - "position", - Rn, - 3 - ), - 2 - ), { rewritedFragmentShader: a, mapArrayUniforms: v } = Vn(l, An); - return new o.ShaderMaterial({ - ...V( - { - uniforms: { - uResolution: { value: new o.Vector2(0, 0) }, - uMorphProgress: { - value: O.morphProgress - }, - uBlurAlpha: { value: O.blurAlpha }, - uBlurRadius: { value: O.blurRadius }, - uPointSize: { value: O.pointSize }, - uPointAlpha: { value: O.pointAlpha }, - uPicture: { value: w }, - uIsPicture: { value: !1 }, - uAlphaPicture: { value: w }, - uIsAlphaPicture: { value: !1 }, - uColor0: { value: O.color0 }, - uColor1: { value: O.color1 }, - uColor2: { value: O.color2 }, - uColor3: { value: O.color3 }, - uMap: { value: w }, - uIsMap: { value: !1 }, - uAlphaMap: { value: w }, - uIsAlphaMap: { value: !1 }, - uTime: { value: 0 }, - uWobblePositionFrequency: { - value: O.wobblePositionFrequency - }, - uWobbleTimeFrequency: { - value: O.wobbleTimeFrequency - }, - uWobbleStrength: { - value: O.wobbleStrength - }, - uWarpPositionFrequency: { - value: O.warpPositionFrequency - }, - uWarpTimeFrequency: { - value: O.warpTimeFrequency - }, - uWarpStrength: { value: O.warpStrength }, - uDisplacement: { value: w }, - uIsDisplacement: { value: !1 }, - uDisplacementIntensity: { - value: O.displacementIntensity - }, - uDisplacementColorIntensity: { - value: O.displacementColorIntensity - }, - uSizeRandomIntensity: { - value: O.sizeRandomIntensity - }, - uSizeRandomTimeFrequency: { - value: O.sizeRandomTimeFrequency - }, - uSizeRandomMin: { - value: O.sizeRandomMin - }, - uSizeRandomMax: { - value: O.sizeRandomMax - }, - uDivergence: { value: O.divergence }, - uDivergencePoint: { - value: O.divergencePoint - }, - ...v - }, - vertexShader: x, - fragmentShader: a - }, - c - ), - ...I, - blending: o.AdditiveBlending, - // Must be transparent - transparent: !0 - }); - }, [ - n, - i, - d, - l, - c - ]), f = K(e, t); - return R(p)("uResolution", f.clone()), { material: p, modifiedPositions: i, modifiedUvs: d }; -}, In = ({ - size: e, - dpr: t, - scene: n = !1, - geometry: r, - positions: s, - uvs: l, - mapArray: c, - onBeforeInit: i -}) => { - const d = U(t), p = y(() => { - const b = r || new o.SphereGeometry(1, 32, 32); - return b.setIndex(null), b.deleteAttribute("normal"), b; - }, [r]), { material: f, modifiedPositions: x, modifiedUvs: a } = Fn({ - size: e, - dpr: d.shader, - geometry: p, - positions: s, - uvs: l, - mapArray: c, - onBeforeInit: i - }), { points: v, interactiveMesh: u } = Pn({ - scene: n, - geometry: p, - material: f - }), m = R(f), h = F(f); - return [ - _( - (b, g, S) => { - b && m( - "uTime", - (g == null ? void 0 : g.beat) || b.clock.getElapsedTime() - ), g !== void 0 && (m("uMorphProgress", g.morphProgress), m("uBlurAlpha", g.blurAlpha), m("uBlurRadius", g.blurRadius), m("uPointSize", g.pointSize), m("uPointAlpha", g.pointAlpha), g.picture ? (m("uPicture", g.picture), m("uIsPicture", !0)) : g.picture === !1 && m("uIsPicture", !1), g.alphaPicture ? (m("uAlphaPicture", g.alphaPicture), m("uIsAlphaPicture", !0)) : g.alphaPicture === !1 && m("uIsAlphaPicture", !1), m("uColor0", g.color0), m("uColor1", g.color1), m("uColor2", g.color2), m("uColor3", g.color3), g.map ? (m("uMap", g.map), m("uIsMap", !0)) : g.map === !1 && m("uIsMap", !1), g.alphaMap ? (m("uAlphaMap", g.alphaMap), m("uIsAlphaMap", !0)) : g.alphaMap === !1 && m("uIsAlphaMap", !1), m("uWobbleStrength", g.wobbleStrength), m( - "uWobblePositionFrequency", - g.wobblePositionFrequency - ), m("uWobbleTimeFrequency", g.wobbleTimeFrequency), m("uWarpStrength", g.warpStrength), m("uWarpPositionFrequency", g.warpPositionFrequency), m("uWarpTimeFrequency", g.warpTimeFrequency), g.displacement ? (m("uDisplacement", g.displacement), m("uIsDisplacement", !0)) : g.displacement === !1 && m("uIsDisplacement", !1), m("uDisplacementIntensity", g.displacementIntensity), m( - "uDisplacementColorIntensity", - g.displacementColorIntensity - ), m("uSizeRandomIntensity", g.sizeRandomIntensity), m( - "uSizeRandomTimeFrequency", - g.sizeRandomTimeFrequency - ), m("uSizeRandomMin", g.sizeRandomMin), m("uSizeRandomMax", g.sizeRandomMax), m("uDivergence", g.divergence), m("uDivergencePoint", g.divergencePoint), h(S)); - }, - [m, h] - ), - { - points: v, - interactiveMesh: u, - positions: x, - uvs: a - } - ]; -}, O = Object.freeze({ - morphProgress: 0, - blurAlpha: 0.9, - blurRadius: 0.05, - pointSize: 0.05, - pointAlpha: 1, - picture: !1, - alphaPicture: !1, - color0: new o.Color(16711680), - color1: new o.Color(65280), - color2: new o.Color(255), - color3: new o.Color(16776960), - map: !1, - alphaMap: !1, - wobbleStrength: 0, - wobblePositionFrequency: 0.5, - wobbleTimeFrequency: 0.5, - warpStrength: 0, - warpPositionFrequency: 0.5, - warpTimeFrequency: 0.5, - displacement: !1, - displacementIntensity: 1, - displacementColorIntensity: 0, - sizeRandomIntensity: 0, - sizeRandomTimeFrequency: 0.2, - sizeRandomMin: 0.5, - sizeRandomMax: 1.5, - divergence: 0, - divergencePoint: new o.Vector3(0), - beat: !1 -}), Mr = ({ - size: e, - dpr: t, - isSizeUpdate: n, - renderTargetOptions: r, - camera: s, - geometry: l, - positions: c, - uvs: i, - onBeforeInit: d -}) => { - const p = U(t), f = y(() => new o.Scene(), []), [ - x, - { - points: a, - interactiveMesh: v, - positions: u, - uvs: m - } - ] = In({ - scene: f, - size: e, - dpr: t, - geometry: l, - positions: c, - uvs: i, - onBeforeInit: d - }), [h, M] = $({ - scene: f, - camera: s, - size: e, - dpr: p.fbo, - isSizeUpdate: n, - depthBuffer: !0, - ...r - }), b = _( - (S, C, T) => (x(S, C, T), M(S.gl)), - [M, x] - ), g = _( - (S, C) => { - x(null, S, C); - }, - [x] - ); - return [ - b, - g, - { - scene: f, - points: a, - interactiveMesh: v, - renderTarget: h, - output: h.texture, - positions: u, - uvs: m - } - ]; -}, Pe = (e) => { - const t = e.shaderType === "MeshDepthMaterial"; - e.vertexShader = e.vertexShader.replace( - "#include ", - ` - vec3 objectNormal = usf_Normal; - #ifdef USE_TANGENT - vec3 objectTangent = vec3( tangent.xyz ); - #endif - ` - ), e.vertexShader = e.vertexShader.replace( - "#include ", - ` - vec3 transformed = usf_Position; - #ifdef USE_ALPHAHASH - vPosition = vec3( position ); - #endif - ` - ), e.vertexShader = e.vertexShader.replace( - "void main() {", - ` - uniform float uTime; - uniform float uWobblePositionFrequency; - uniform float uWobbleTimeFrequency; - uniform float uWobbleStrength; - uniform float uWarpPositionFrequency; - uniform float uWarpTimeFrequency; - uniform float uWarpStrength; - - ${t ? "attribute vec4 tangent;" : ""} - - varying float vWobble; - varying vec2 vPosition; - - // edge - varying vec3 vEdgeNormal; - varying vec3 vEdgeViewPosition; - - #usf - - void main() { - - vec3 usf_Position = position; - vec3 usf_Normal = normal; - vec3 biTangent = cross(normal, tangent.xyz); - - // Neighbours positions - float shift = 0.01; - vec3 positionA = usf_Position + tangent.xyz * shift; - vec3 positionB = usf_Position + biTangent * shift; - - // wobble - float wobble = (uWobbleStrength > 0.) ? getWobble(usf_Position) : 0.0; - float wobblePositionA = (uWobbleStrength > 0.) ? getWobble(positionA) : 0.0; - float wobblePositionB = (uWobbleStrength > 0.) ? getWobble(positionB) : 0.0; - - usf_Position += wobble * normal; - positionA += wobblePositionA * normal; - positionB += wobblePositionB * normal; - - // Compute normal - vec3 toA = normalize(positionA - usf_Position); - vec3 toB = normalize(positionB - usf_Position); - usf_Normal = cross(toA, toB); - - // Varying - vPosition = usf_Position.xy; - vWobble = wobble/uWobbleStrength; - - vEdgeNormal = normalize(normalMatrix * usf_Normal); - vec4 viewPosition = viewMatrix * modelMatrix * vec4(usf_Position, 1.0); - vEdgeViewPosition = normalize(viewPosition.xyz); - ` - ); -}, zn = (e) => { - e.fragmentShader = e.fragmentShader.replace( - "#include ", - ` - #include - - if (uEdgeThreshold > 0.0) { - float edgeThreshold = dot(vEdgeNormal, -vEdgeViewPosition); - diffuseColor = edgeThreshold < uEdgeThreshold ? vec4(uEdgeColor, 1.0) : mix(diffuseColor, usf_DiffuseColor, uColorMix); - } else { - diffuseColor = mix(diffuseColor, usf_DiffuseColor, uColorMix); - } - ` - ), e.fragmentShader = e.fragmentShader.replace( - "void main() {", - ` - uniform vec3 uColor0; - uniform vec3 uColor1; - uniform vec3 uColor2; - uniform vec3 uColor3; - uniform float uColorMix; - uniform float uEdgeThreshold; - uniform vec3 uEdgeColor; - - // transmission - uniform float uChromaticAberration; - uniform float uAnisotropicBlur; - uniform float uTime; - uniform float uDistortion; - uniform float uDistortionScale; - uniform float uTemporalDistortion; - uniform float uRefractionSamples; - - float rand(float n){return fract(sin(n) * 43758.5453123);} - - #usf - - varying float vWobble; - varying vec2 vPosition; - varying vec3 vEdgeNormal; - varying vec3 vEdgeViewPosition; - - void main(){ - - vec4 usf_DiffuseColor = vec4(1.0); - float colorWobbleMix = smoothstep(-1.,1.,vWobble); - vec2 colorPosMix = vec2(smoothstep(-1.,1.,vPosition.x),smoothstep(-1.,1.,vPosition.y)); - - usf_DiffuseColor.rgb = mix(mix(uColor0, uColor1, colorPosMix.x), mix(uColor2, uColor3, colorPosMix.y), colorWobbleMix); - ` - ); -}; -var Un = `#ifdef USE_TRANSMISSION - - - - - uniform float _transmission; - uniform float thickness; - uniform float attenuationDistance; - uniform vec3 attenuationColor; - - #ifdef USE_TRANSMISSIONMAP - - uniform sampler2D transmissionMap; - - #endif - - #ifdef USE_THICKNESSMAP - - uniform sampler2D thicknessMap; - - #endif - - uniform vec2 transmissionSamplerSize; - uniform sampler2D transmissionSamplerMap; - - uniform mat4 modelMatrix; - uniform mat4 projectionMatrix; - - varying vec3 vWorldPosition; - - - - - float w0( float a ) { - - return ( 1.0 / 6.0 ) * ( a * ( a * ( - a + 3.0 ) - 3.0 ) + 1.0 ); - - } - - float w1( float a ) { - - return ( 1.0 / 6.0 ) * ( a * a * ( 3.0 * a - 6.0 ) + 4.0 ); - - } - - float w2( float a ){ - - return ( 1.0 / 6.0 ) * ( a * ( a * ( - 3.0 * a + 3.0 ) + 3.0 ) + 1.0 ); - - } - - float w3( float a ) { - - return ( 1.0 / 6.0 ) * ( a * a * a ); - - } - - - float g0( float a ) { - - return w0( a ) + w1( a ); - - } - - float g1( float a ) { - - return w2( a ) + w3( a ); - - } - - - float h0( float a ) { - - return - 1.0 + w1( a ) / ( w0( a ) + w1( a ) ); - - } - - float h1( float a ) { - - return 1.0 + w3( a ) / ( w2( a ) + w3( a ) ); - - } - - vec4 bicubic( sampler2D tex, vec2 uv, vec4 texelSize, float lod ) { - - uv = uv * texelSize.zw + 0.5; - - vec2 iuv = floor( uv ); - vec2 fuv = fract( uv ); - - float g0x = g0( fuv.x ); - float g1x = g1( fuv.x ); - float h0x = h0( fuv.x ); - float h1x = h1( fuv.x ); - float h0y = h0( fuv.y ); - float h1y = h1( fuv.y ); - - vec2 p0 = ( vec2( iuv.x + h0x, iuv.y + h0y ) - 0.5 ) * texelSize.xy; - vec2 p1 = ( vec2( iuv.x + h1x, iuv.y + h0y ) - 0.5 ) * texelSize.xy; - vec2 p2 = ( vec2( iuv.x + h0x, iuv.y + h1y ) - 0.5 ) * texelSize.xy; - vec2 p3 = ( vec2( iuv.x + h1x, iuv.y + h1y ) - 0.5 ) * texelSize.xy; - - return g0( fuv.y ) * ( g0x * textureLod( tex, p0, lod ) + g1x * textureLod( tex, p1, lod ) ) + - g1( fuv.y ) * ( g0x * textureLod( tex, p2, lod ) + g1x * textureLod( tex, p3, lod ) ); - - } - - vec4 textureBicubic( sampler2D sampler, vec2 uv, float lod ) { - - vec2 fLodSize = vec2( textureSize( sampler, int( lod ) ) ); - vec2 cLodSize = vec2( textureSize( sampler, int( lod + 1.0 ) ) ); - vec2 fLodSizeInv = 1.0 / fLodSize; - vec2 cLodSizeInv = 1.0 / cLodSize; - vec4 fSample = bicubic( sampler, uv, vec4( fLodSizeInv, fLodSize ), floor( lod ) ); - vec4 cSample = bicubic( sampler, uv, vec4( cLodSizeInv, cLodSize ), ceil( lod ) ); - return mix( fSample, cSample, fract( lod ) ); - - } - - vec3 getVolumeTransmissionRay( const in vec3 n, const in vec3 v, const in float thickness, const in float ior, const in mat4 modelMatrix ) { - - - vec3 refractionVector = refract( - v, normalize( n ), 1.0 / ior ); - - - vec3 modelScale; - modelScale.x = length( vec3( modelMatrix[ 0 ].xyz ) ); - modelScale.y = length( vec3( modelMatrix[ 1 ].xyz ) ); - modelScale.z = length( vec3( modelMatrix[ 2 ].xyz ) ); - - - return normalize( refractionVector ) * thickness * modelScale; - - } - - float applyIorToRoughness( const in float roughness, const in float ior ) { - - - - return roughness * clamp( ior * 2.0 - 2.0, 0.0, 1.0 ); - - } - - vec4 getTransmissionSample( const in vec2 fragCoord, const in float roughness, const in float ior ) { - - float lod = log2( transmissionSamplerSize.x ) * applyIorToRoughness( roughness, ior ); - return textureBicubic( transmissionSamplerMap, fragCoord.xy, lod ); - - } - - vec3 volumeAttenuation( const in float transmissionDistance, const in vec3 attenuationColor, const in float attenuationDistance ) { - - if ( isinf( attenuationDistance ) ) { - - - return vec3( 1.0 ); - - } else { - - - vec3 attenuationCoefficient = -log( attenuationColor ) / attenuationDistance; - vec3 transmittance = exp( - attenuationCoefficient * transmissionDistance ); - return transmittance; - - } - - } - - vec4 getIBLVolumeRefraction( const in vec3 n, const in vec3 v, const in float roughness, const in vec3 diffuseColor, - const in vec3 specularColor, const in float specularF90, const in vec3 position, const in mat4 modelMatrix, - const in mat4 viewMatrix, const in mat4 projMatrix, const in float ior, const in float thickness, - const in vec3 attenuationColor, const in float attenuationDistance ) { - - vec3 transmissionRay = getVolumeTransmissionRay( n, v, thickness, ior, modelMatrix ); - vec3 refractedRayExit = position + transmissionRay; - - - vec4 ndcPos = projMatrix * viewMatrix * vec4( refractedRayExit, 1.0 ); - vec2 refractionCoords = ndcPos.xy / ndcPos.w; - refractionCoords += 1.0; - refractionCoords /= 2.0; - - - vec4 transmittedLight = getTransmissionSample( refractionCoords, roughness, ior ); - - vec3 transmittance = diffuseColor * volumeAttenuation( length( transmissionRay ), attenuationColor, attenuationDistance ); - vec3 attenuatedColor = transmittance * transmittedLight.rgb; - - - vec3 F = EnvironmentBRDF( n, v, specularColor, specularF90, roughness ); - - - - float transmittanceFactor = ( transmittance.r + transmittance.g + transmittance.b ) / 3.0; - - return vec4( ( 1.0 - F ) * attenuatedColor, 1.0 - ( 1.0 - transmittedLight.a ) * transmittanceFactor ); - - } -#endif`, On = `#ifdef USE_TRANSMISSION - -material.transmission = _transmission; -material.transmissionAlpha = 1.0; -material.thickness = thickness; -material.attenuationDistance = attenuationDistance; -material.attenuationColor = attenuationColor; - -#ifdef USE_TRANSMISSIONMAP - - material.transmission *= texture2D( transmissionMap, vTransmissionMapUv ).r; - -#endif - -#ifdef USE_THICKNESSMAP - - material.thickness *= texture2D( thicknessMap, vThicknessMapUv ).g; - -#endif - -vec3 pos = vWorldPosition; - -vec3 v = normalize( cameraPosition - pos ); -vec3 n = inverseTransformDirection( normal, viewMatrix ); - -vec4 transmitted = getIBLVolumeRefraction( - n, v, material.roughness, material.diffuseColor, material.specularColor, material.specularF90, - pos, modelMatrix, viewMatrix, projectionMatrix, material.ior, material.thickness, - material.attenuationColor, material.attenuationDistance ); - -material.transmissionAlpha = mix( material.transmissionAlpha, transmitted.a, material.transmission ); - -float runningSeed = 0.0; -vec3 transmission = vec3(0.0); -float transmissionR, transmissionB, transmissionG; -float randomCoords = rand(runningSeed++); -float thickness_smear = thickness * max(pow(roughnessFactor, 0.33), uAnisotropicBlur); -vec3 distortionNormal = vec3(0.0); -vec3 temporalOffset = vec3(uTime, -uTime, -uTime) * uTemporalDistortion; - -if (uDistortion > 0.0) { - distortionNormal = uDistortion * vec3(snoiseFractal(vec3((pos * uDistortionScale + temporalOffset))), snoiseFractal(vec3(pos.zxy * uDistortionScale - temporalOffset)), snoiseFractal(vec3(pos.yxz * uDistortionScale + temporalOffset))); -} - -for (float i = 0.0; i < uRefractionSamples; i ++) { - vec3 sampleNorm = normalize(n + roughnessFactor * roughnessFactor * 2.0 * normalize(vec3(rand(runningSeed++) - 0.5, rand(runningSeed++) - 0.5, rand(runningSeed++) - 0.5)) * pow(rand(runningSeed++), 0.33) + distortionNormal); - - transmissionR = getIBLVolumeRefraction( - sampleNorm, v, material.roughness, material.diffuseColor, material.specularColor, material.specularF90, - pos, modelMatrix, viewMatrix, projectionMatrix, material.ior, material.thickness + thickness_smear * (i + randomCoords) / uRefractionSamples, - material.attenuationColor, material.attenuationDistance - ).r; - transmissionG = getIBLVolumeRefraction( - sampleNorm, v, material.roughness, material.diffuseColor, material.specularColor, material.specularF90, - pos, modelMatrix, viewMatrix, projectionMatrix, material.ior * (1.0 + uChromaticAberration * (i + randomCoords) / uRefractionSamples) , material.thickness + thickness_smear * (i + randomCoords) / uRefractionSamples, - material.attenuationColor, material.attenuationDistance - ).g; - transmissionB = getIBLVolumeRefraction( - sampleNorm, v, material.roughness, material.diffuseColor, material.specularColor, material.specularF90, - pos, modelMatrix, viewMatrix, projectionMatrix, material.ior * (1.0 + 2.0 * uChromaticAberration * (i + randomCoords) / uRefractionSamples), material.thickness + thickness_smear * (i + randomCoords) / uRefractionSamples, - material.attenuationColor, material.attenuationDistance - ).b; - transmission.r += transmissionR; - transmission.g += transmissionG; - transmission.b += transmissionB; -} - -transmission /= uRefractionSamples; - -totalDiffuse = mix( totalDiffuse, transmission.rgb, material.transmission ); - -#endif`; -const Bn = ({ - mat: e, - isCustomTransmission: t, - parameters: n -}) => { - e.type === "MeshPhysicalMaterial" && t && (n.fragmentShader = n.fragmentShader.replace( - "#include ", - `${Un}` - ), n.fragmentShader = n.fragmentShader.replace( - "#include ", - `${On}` - )), e.normalMap || (n.vertexShader = n.vertexShader.replace( - "void main() {", - ` - attribute vec4 tangent; - - void main() { - ` - )); -}, En = ({ - baseMaterial: e, - materialParameters: t, - isCustomTransmission: n = !1, - onBeforeInit: r, - depthOnBeforeInit: s, - depth: l = !1 -}) => { - const { material: c, depthMaterial: i } = y(() => { - const d = new (e || o.MeshPhysicalMaterial)( - t || {} - ); - Object.assign(d.userData, { - uniforms: { - uTime: { value: 0 }, - uWobblePositionFrequency: { - value: W.wobblePositionFrequency - }, - uWobbleTimeFrequency: { - value: W.wobbleTimeFrequency - }, - uWobbleStrength: { value: W.wobbleStrength }, - uWarpPositionFrequency: { - value: W.warpPositionFrequency - }, - uWarpTimeFrequency: { value: W.warpTimeFrequency }, - uWarpStrength: { value: W.warpStrength }, - uColor0: { value: W.color0 }, - uColor1: { value: W.color1 }, - uColor2: { value: W.color2 }, - uColor3: { value: W.color3 }, - uColorMix: { value: W.colorMix }, - uEdgeThreshold: { value: W.edgeThreshold }, - uEdgeColor: { value: W.edgeColor }, - uChromaticAberration: { - value: W.chromaticAberration - }, - uAnisotropicBlur: { value: W.anisotropicBlur }, - uDistortion: { value: W.distortion }, - uDistortionScale: { value: W.distortionScale }, - uTemporalDistortion: { value: W.temporalDistortion }, - uRefractionSamples: { value: W.refractionSamples }, - transmission: { value: 0 }, - _transmission: { value: 1 }, - transmissionMap: { value: null } - } - }), d.onBeforeCompile = (f) => { - Pe(f), zn(f), Bn({ - parameters: f, - mat: d, - isCustomTransmission: n - }); - const x = V( - { - fragmentShader: f.fragmentShader, - vertexShader: f.vertexShader, - // Because wobble3D uses userData to update uniforms. - uniforms: d.userData.uniforms - }, - r - ); - f.fragmentShader = x.fragmentShader, f.vertexShader = x.vertexShader, Object.assign(f.uniforms, x.uniforms); - }, d.needsUpdate = !0; - let p = null; - return l && (p = new o.MeshDepthMaterial({ - depthPacking: o.RGBADepthPacking - }), p.onBeforeCompile = (f) => { - Object.assign(f.uniforms, d.userData.uniforms), Pe(f), V(f, s); - }, p.needsUpdate = !0), { material: d, depthMaterial: p }; - }, [ - t, - e, - r, - s, - n, - l - ]); - return Z(() => () => { - i && i.dispose(); - }, [i]), { - material: c, - depthMaterial: i - }; -}, Ln = ({ - scene: e = !1, - geometry: t, - isCustomTransmission: n, - baseMaterial: r, - materialParameters: s, - depth: l, - onBeforeInit: c, - depthOnBeforeInit: i -}) => { - const d = y(() => { - let h = t || new o.IcosahedronGeometry(2, 20); - return h = Ee(h), h.computeTangents(), h; - }, [t]), { material: p, depthMaterial: f } = En({ - baseMaterial: r, - materialParameters: s, - isCustomTransmission: n, - onBeforeInit: c, - depthOnBeforeInit: i, - depth: l - }), x = E(e, d, p, o.Mesh), a = p.userData, v = R(a), u = F(a); - return [ - _( - (h, M, b) => { - h && v( - "uTime", - (M == null ? void 0 : M.beat) || h.clock.getElapsedTime() - ), M !== void 0 && (v("uWobbleStrength", M.wobbleStrength), v( - "uWobblePositionFrequency", - M.wobblePositionFrequency - ), v("uWobbleTimeFrequency", M.wobbleTimeFrequency), v("uWarpStrength", M.warpStrength), v("uWarpPositionFrequency", M.warpPositionFrequency), v("uWarpTimeFrequency", M.warpTimeFrequency), v("uColor0", M.color0), v("uColor1", M.color1), v("uColor2", M.color2), v("uColor3", M.color3), v("uColorMix", M.colorMix), v("uEdgeThreshold", M.edgeThreshold), v("uEdgeColor", M.edgeColor), v("uChromaticAberration", M.chromaticAberration), v("uAnisotropicBlur", M.anisotropicBlur), v("uDistortion", M.distortion), v("uDistortionScale", M.distortionScale), v("uRefractionSamples", M.refractionSamples), v("uTemporalDistortion", M.temporalDistortion), u(b)); - }, - [v, u] - ), - { - mesh: x, - depthMaterial: f - } - ]; -}, W = Object.freeze({ - wobbleStrength: 0.3, - wobblePositionFrequency: 0.3, - wobbleTimeFrequency: 0.3, - warpStrength: 0.3, - warpPositionFrequency: 0.3, - warpTimeFrequency: 0.3, - color0: new o.Color(16711680), - color1: new o.Color(65280), - color2: new o.Color(255), - color3: new o.Color(16776960), - colorMix: 1, - edgeThreshold: 0, - edgeColor: new o.Color(0), - chromaticAberration: 0.1, - anisotropicBlur: 0.1, - distortion: 0, - distortionScale: 0.1, - temporalDistortion: 0, - refractionSamples: 6, - beat: !1 -}), Sr = ({ - size: e, - dpr: t, - renderTargetOptions: n, - isSizeUpdate: r, - camera: s, - geometry: l, - baseMaterial: c, - materialParameters: i, - isCustomTransmission: d, - onBeforeInit: p, - depthOnBeforeInit: f, - depth: x -}) => { - const a = U(t), v = y(() => new o.Scene(), []), [u, { mesh: m, depthMaterial: h }] = Ln({ - baseMaterial: c, - materialParameters: i, - scene: v, - geometry: l, - isCustomTransmission: d, - onBeforeInit: p, - depthOnBeforeInit: f, - depth: x - }), [M, b] = $({ - scene: v, - camera: s, - size: e, - dpr: a.fbo, - isSizeUpdate: r, - depthBuffer: !0, - ...n - }), g = _( - (C, T, A) => (u(C, T, A), b(C.gl)), - [b, u] - ), S = _( - (C, T) => { - u(null, C, T); - }, - [u] - ); - return [ - g, - S, - { - scene: v, - mesh: m, - depthMaterial: h, - renderTarget: M, - output: M.texture - } - ]; -}, _r = (e, t, n) => { - const r = y(() => { - const s = new o.Mesh(t, n); - return e.add(s), s; - }, [t, n, e]); - return Z(() => () => { - e.remove(r), t.dispose(), n.dispose(); - }, [e, t, n, r]), r; -}, $n = (e, t, n, r, s, l) => { - const c = e < n - s || t < r - s, i = e > n + s || t > r + s; - return l === "smaller" && c || l === "larger" && i || l === "both" && (c || i); -}, Cr = ({ - size: e, - boundFor: t, - threshold: n -}) => { - const r = B(e); - return y(() => { - const { width: l, height: c } = e, { width: i, height: d } = r.current, p = $n( - l, - c, - i, - d, - n, - t - ); - return p && (r.current = e), p; - }, [e, t, n]); -}, ge = Object.freeze({ - easeInSine(e) { - return 1 - Math.cos(e * Math.PI / 2); - }, - easeOutSine(e) { - return Math.sin(e * Math.PI / 2); - }, - easeInOutSine(e) { - return -(Math.cos(Math.PI * e) - 1) / 2; - }, - easeInQuad(e) { - return e * e; - }, - easeOutQuad(e) { - return 1 - (1 - e) * (1 - e); - }, - easeInOutQuad(e) { - return e < 0.5 ? 2 * e * e : 1 - Math.pow(-2 * e + 2, 2) / 2; - }, - easeInCubic(e) { - return e * e * e; - }, - easeOutCubic(e) { - return 1 - Math.pow(1 - e, 3); - }, - easeInOutCubic(e) { - return e < 0.5 ? 4 * e * e * e : 1 - Math.pow(-2 * e + 2, 3) / 2; - }, - easeInQuart(e) { - return e * e * e * e; - }, - easeOutQuart(e) { - return 1 - Math.pow(1 - e, 4); - }, - easeInOutQuart(e) { - return e < 0.5 ? 8 * e * e * e * e : 1 - Math.pow(-2 * e + 2, 4) / 2; - }, - easeInQuint(e) { - return e * e * e * e * e; - }, - easeOutQuint(e) { - return 1 - Math.pow(1 - e, 5); - }, - easeInOutQuint(e) { - return e < 0.5 ? 16 * e * e * e * e * e : 1 - Math.pow(-2 * e + 2, 5) / 2; - }, - easeInExpo(e) { - return e === 0 ? 0 : Math.pow(2, 10 * e - 10); - }, - easeOutExpo(e) { - return e === 1 ? 1 : 1 - Math.pow(2, -10 * e); - }, - easeInOutExpo(e) { - return e === 0 ? 0 : e === 1 ? 1 : e < 0.5 ? Math.pow(2, 20 * e - 10) / 2 : (2 - Math.pow(2, -20 * e + 10)) / 2; - }, - easeInCirc(e) { - return 1 - Math.sqrt(1 - Math.pow(e, 2)); - }, - easeOutCirc(e) { - return Math.sqrt(1 - Math.pow(e - 1, 2)); - }, - easeInOutCirc(e) { - return e < 0.5 ? (1 - Math.sqrt(1 - Math.pow(2 * e, 2))) / 2 : (Math.sqrt(1 - Math.pow(-2 * e + 2, 2)) + 1) / 2; - }, - easeInBack(e) { - return 2.70158 * e * e * e - 1.70158 * e * e; - }, - easeOutBack(e) { - return 1 + 2.70158 * Math.pow(e - 1, 3) + 1.70158 * Math.pow(e - 1, 2); - }, - easeInOutBack(e) { - const n = 2.5949095; - return e < 0.5 ? Math.pow(2 * e, 2) * ((n + 1) * 2 * e - n) / 2 : (Math.pow(2 * e - 2, 2) * ((n + 1) * (e * 2 - 2) + n) + 2) / 2; - }, - easeInElastic(e) { - const t = 2 * Math.PI / 3; - return e === 0 ? 0 : e === 1 ? 1 : -Math.pow(2, 10 * e - 10) * Math.sin((e * 10 - 10.75) * t); - }, - easeOutElastic(e) { - const t = 2 * Math.PI / 3; - return e === 0 ? 0 : e === 1 ? 1 : Math.pow(2, -10 * e) * Math.sin((e * 10 - 0.75) * t) + 1; - }, - easeInOutElastic(e) { - const t = 2 * Math.PI / 4.5; - return e === 0 ? 0 : e === 1 ? 1 : e < 0.5 ? -(Math.pow(2, 20 * e - 10) * Math.sin((20 * e - 11.125) * t)) / 2 : Math.pow(2, -20 * e + 10) * Math.sin((20 * e - 11.125) * t) / 2 + 1; - }, - easeInBounce(e) { - return 1 - ge.easeOutBounce(1 - e); - }, - easeOutBounce(e) { - return e < 1 / 2.75 ? 7.5625 * e * e : e < 2 / 2.75 ? 7.5625 * (e -= 1.5 / 2.75) * e + 0.75 : e < 2.5 / 2.75 ? 7.5625 * (e -= 2.25 / 2.75) * e + 0.9375 : 7.5625 * (e -= 2.625 / 2.75) * e + 0.984375; - }, - easeInOutBounce(e) { - return e < 0.5 ? (1 - ge.easeOutBounce(1 - 2 * e)) / 2 : (1 + ge.easeOutBounce(2 * e - 1)) / 2; - } -}); -function jn(e) { - let t = Math.sin(e * 12.9898) * 43758.5453; - return t - Math.floor(t); -} -const wr = (e, t = "easeOutQuart") => { - const n = e / 60, r = ge[t]; - return _( - (l) => { - let c = l.getElapsedTime() * n; - const i = Math.floor(c), d = r(c - i); - c = d + i; - const p = jn(i); - return { - beat: c, - floor: i, - fract: d, - hash: p - }; - }, - [n, r] - ); -}, Tr = (e = 60) => { - const t = y(() => 1 / Math.max(Math.min(e, 60), 1), [e]), n = B(null); - return _( - (s) => { - const l = s.getElapsedTime(); - return n.current === null || l - n.current >= t ? (n.current = l, !0) : !1; - }, - [t] - ); -}, qn = (e) => { - var r, s; - const t = (r = e.dom) == null ? void 0 : r.length, n = (s = e.texture) == null ? void 0 : s.length; - return !t || !n || t !== n; -}; -var Wn = `varying vec2 vUv; - -void main() { - vUv = uv; - gl_Position = projectionMatrix * viewMatrix * modelMatrix * vec4(position, 1.0); -}`, Nn = `precision highp float; - -varying vec2 vUv; -uniform sampler2D u_texture; -uniform vec2 u_textureResolution; -uniform vec2 u_resolution; -uniform float u_borderRadius; - -void main() { - - float screenAspect = u_resolution.x / u_resolution.y; - float textureAspect = u_textureResolution.x / u_textureResolution.y; - vec2 ratio = vec2( - min(screenAspect / textureAspect, 1.0), - min(textureAspect / screenAspect, 1.0) - ); - - vec2 adjustedUv = vUv * ratio + (1.0 - ratio) * 0.5; - vec3 textureColor = texture2D(u_texture, adjustedUv).rgb; - float textureAlpha = texture2D(u_texture, adjustedUv).a; - - - float maxSide = max(u_resolution.x, u_resolution.y); - float minSide = min(u_resolution.x, u_resolution.y); - vec2 aspect = u_resolution / maxSide; - vec2 alphaUv = vUv - 0.5; - - float borderRadius = min(u_borderRadius, minSide * 0.5); - vec2 offset = vec2(borderRadius) / u_resolution; - vec2 alphaXY = smoothstep(vec2(0.5 - offset), vec2(0.5 - offset - 0.001), abs(alphaUv)); - float alpha = min(1.0, alphaXY.x + alphaXY.y); - - vec2 alphaUv2 = abs(vUv - 0.5); - float radius = borderRadius / maxSide; - alphaUv2 = (alphaUv2 - 0.5) * aspect + radius; - float roundAlpha = smoothstep(radius + 0.001, radius, length(alphaUv2)); - - alpha = min(1.0, alpha + roundAlpha); - - - alpha *= textureAlpha; - - gl_FragColor = vec4(textureColor, alpha); -}`; -const kn = ({ - params: e, - scene: t, - onBeforeInit: n -}) => { - t.children.length > 0 && (t.children.forEach((r) => { - r instanceof o.Mesh && (r.geometry.dispose(), r.material.dispose()); - }), t.remove(...t.children)), e.texture.forEach((r, s) => { - const l = new o.ShaderMaterial({ - ...V( - { - uniforms: { - u_texture: { value: r }, - u_textureResolution: { - value: new o.Vector2(0, 0) - }, - u_resolution: { value: new o.Vector2(0, 0) }, - u_borderRadius: { - value: e.boderRadius[s] ? e.boderRadius[s] : 0 - } - }, - vertexShader: Wn, - fragmentShader: Nn - }, - n - ), - ...I, - // Must be transparent. - transparent: !0 - }), c = new o.Mesh(new o.PlaneGeometry(1, 1), l); - t.add(c); - }); -}, Gn = () => { - const e = B([]), t = B([]); - return _( - ({ - isIntersectingRef: r, - isIntersectingOnceRef: s, - params: l - }) => { - e.current.length > 0 && e.current.forEach((i, d) => { - i.unobserve(t.current[d]); - }), t.current = [], e.current = []; - const c = new Array(l.dom.length).fill(!1); - r.current = [...c], s.current = [...c], l.dom.forEach((i, d) => { - const p = (x) => { - x.forEach((a) => { - l.onIntersect[d] && l.onIntersect[d](a), r.current[d] = a.isIntersecting; - }); - }, f = new IntersectionObserver(p, { - rootMargin: "0px", - threshold: 0 - }); - f.observe(i), e.current.push(f), t.current.push(i); - }); - }, - [] - ); -}, Kn = () => { - const e = B([]), t = _( - ({ - params: n, - customParams: r, - size: s, - resolutionRef: l, - scene: c, - isIntersectingRef: i - }) => { - c.children.length !== e.current.length && (e.current = new Array(c.children.length)), c.children.forEach((d, p) => { - var a, v, u, m, h, M; - const f = n.dom[p]; - if (!f) - return; - const x = f.getBoundingClientRect(); - if (e.current[p] = x, d.scale.set(x.width, x.height, 1), d.position.set( - x.left + x.width * 0.5 - s.width * 0.5, - -x.top - x.height * 0.5 + s.height * 0.5, - 0 - ), i.current[p] && (n.rotation[p] && d.rotation.copy(n.rotation[p]), d instanceof o.Mesh)) { - const b = d.material, g = R(b), S = F(b); - g("u_texture", n.texture[p]), g("u_textureResolution", [ - ((u = (v = (a = n.texture[p]) == null ? void 0 : a.source) == null ? void 0 : v.data) == null ? void 0 : u.width) || 0, - ((M = (h = (m = n.texture[p]) == null ? void 0 : m.source) == null ? void 0 : h.data) == null ? void 0 : M.height) || 0 - ]), g( - "u_resolution", - l.current.set(x.width, x.height) - ), g( - "u_borderRadius", - n.boderRadius[p] ? n.boderRadius[p] : 0 - ), S(r); - } - }); - }, - [] - ); - return [e.current, t]; -}, Hn = () => { - const e = B([]), t = B([]), n = _((r, s = !1) => { - e.current.forEach((c, i) => { - c && (t.current[i] = !0); - }); - const l = s ? [...t.current] : [...e.current]; - return r < 0 ? l : l[r]; - }, []); - return { - isIntersectingRef: e, - isIntersectingOnceRef: t, - isIntersecting: n - }; -}, Xn = (e) => ({ onView: n, onHidden: r }) => { - const s = B(!1); - Z(() => { - let l; - const c = () => { - e.current.some((i) => i) ? s.current || (n && n(), s.current = !0) : s.current && (r && r(), s.current = !1), l = requestAnimationFrame(c); - }; - return l = requestAnimationFrame(c), () => { - cancelAnimationFrame(l); - }; - }, [n, r]); -}, Yn = { - texture: [], - dom: [], - boderRadius: [], - rotation: [], - onIntersect: [] -}, Dr = ({ size: e, dpr: t, isSizeUpdate: n, renderTargetOptions: r, onBeforeInit: s }, l = []) => { - const c = U(t), i = y(() => new o.Scene(), []), d = L(e), [p, f] = $({ - scene: i, - camera: d, - size: e, - dpr: c.fbo, - isSizeUpdate: n, - ...r - }), [x, a] = j({ - ...Yn, - updateKey: performance.now() - }), [v, u] = Kn(), m = B(new o.Vector2(0, 0)), [h, M] = Be(!0); - y( - () => M(!0), - // eslint-disable-next-line react-hooks/exhaustive-deps - l - ); - const b = B(null), g = y(() => w, []), S = Gn(), { isIntersectingOnceRef: C, isIntersectingRef: T, isIntersecting: A } = Hn(), z = Xn(T), P = y(() => (D, k) => { - a(D), u({ - params: x, - customParams: k, - size: e, - resolutionRef: m, - scene: i, - isIntersectingRef: T - }); - }, [T, a, u, e, i, x]); - return [ - _( - (D, k, H) => { - const { gl: ee, size: te } = D; - if (P(k, H), qn(x)) - return g; - if (h) { - if (b.current === x.updateKey) - return g; - b.current = x.updateKey; - } - return h && (kn({ - params: x, - size: te, - scene: i, - onBeforeInit: s - }), S({ - isIntersectingRef: T, - isIntersectingOnceRef: C, - params: x - }), M(!1)), f(ee); - }, - [ - f, - S, - s, - P, - h, - i, - x, - C, - T, - g - ] - ), - P, - { - scene: i, - camera: d, - renderTarget: p, - output: p.texture, - isIntersecting: A, - DOMRects: v, - intersections: T.current, - useDomView: z - } - ]; -}, Pr = (e, t) => { - const { - scene: n, - camera: r, - size: s, - dpr: l = !1, - isSizeUpdate: c = !1, - depth: i = !1, - ...d - } = e, p = B([]), f = K(s, l); - p.current = y(() => Array.from({ length: t }, () => { - const a = new o.WebGLRenderTarget( - f.x, - f.y, - { - ...he, - ...d - } - ); - return i && (a.depthTexture = new o.DepthTexture( - f.x, - f.y, - o.FloatType - )), a; - }), [t]), c && p.current.forEach( - (a) => a.setSize(f.x, f.y) - ), Z(() => { - const a = p.current; - return () => { - a.forEach((v) => v.dispose()); - }; - }, [t]); - const x = _( - (a, v, u) => { - const m = p.current[v]; - return _e({ - gl: a, - scene: n, - camera: r, - fbo: m, - onBeforeRender: () => u && u({ read: m.texture }) - }), m.texture; - }, - [n, r] - ); - return [p.current, x]; -}, Rr = Object.freeze({ - interpolate(e, t, n, r = 1e-6) { - const s = e + (t - e) * n; - return Math.abs(s) < r ? 0 : s; - }, - smoothstep(e, t, n) { - const r = Math.min(Math.max((n - e) / (t - e), 0), 1); - return r * r * (3 - 2 * r); - } -}); -export { - en as ALPHABLENDING_PARAMS, - Cn as BLANK_PARAMS, - ve as BLENDING_PARAMS, - de as BRIGHTNESSPICKER_PARAMS, - re as BRUSH_PARAMS, - Q as CHROMAKEY_PARAMS, - Y as COLORSTRATA_PARAMS, - ce as COSPALETTE_PARAMS, - sn as COVERTEXTURE_PARAMS, - Ae as DELTA_TIME, - Yn as DOMSYNCER_PARAMS, - be as DUOTONE_PARAMS, - ge as Easing, - he as FBO_DEFAULT_OPTION, - yt as FLUID_PARAMS, - Ve as FXBLENDING_PARAMS, - ae as FXTEXTURE_PARAMS, - Me as HSV_PARAMS, - ue as MARBLE_PARAMS, - O as MORPHPARTICLES_PARAMS, - fe as MOTIONBLUR_PARAMS, - oe as NOISE_PARAMS, - yr as RAWBLANK_PARAMS, - _t as RIPPLE_PARAMS, - Fe as SIMPLEBLUR_PARAMS, - Xe as ShaderChunk, - Rr as Utils, - me as WAVE_PARAMS, - W as WOBBLE3D_PARAMS, - _e as renderFBO, - F as setCustomUniform, - R as setUniform, - _r as useAddMesh, - vr as useAlphaBlending, - wr as useBeat, - xr as useBlank, - ur as useBlending, - lr as useBrightnessPicker, - Jn as useBrush, - L as useCamera, - hr as useChromaKey, - rr as useColorStrata, - Pr as useCopyTexture, - ar as useCosPalette, - pr as useCoverTexture, - In as useCreateMorphParticles, - Ln as useCreateWobble3D, - Dr as useDomSyncer, - se as useDoubleFBO, - ir as useDuoTone, - Tr as useFPSLimiter, - er as useFluid, - cr as useFxBlending, - sr as useFxTexture, - mr as useHSV, - or as useMarble, - Mr as useMorphParticles, - fr as useMotionBlur, - nr as useNoise, - j as useParams, - Se as usePointer, - br as useRawBlank, - Cr as useResizeBoundary, - K as useResolution, - tr as useRipple, - dr as useSimpleBlur, - $ as useSingleFBO, - gr as useWave, - Sr as useWobble3D -}; -//# sourceMappingURL=use-shader-fx.js.map diff --git a/packages/use-shader-fx/build/use-shader-fx.js.map b/packages/use-shader-fx/build/use-shader-fx.js.map deleted file mode 100644 index a4c30435..00000000 --- a/packages/use-shader-fx/build/use-shader-fx.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"use-shader-fx.js","sources":["../src/fxs/interactions/useBrush/shader/main.vert","../src/fxs/interactions/useBrush/shader/main.frag","../src/utils/useResolution.ts","../src/utils/setUniforms.ts","../src/utils/useAddObject.ts","../src/libs/constants.ts","../src/libs/shaders/shaderChunk/wobble3D.glsl","../src/libs/shaders/shaderChunk/snoise.glsl","../src/libs/shaders/shaderChunk/coverTexture.glsl","../src/libs/shaders/shaderChunk/fxBlending.glsl","../src/libs/shaders/shaderChunk/planeVertex.glsl","../src/libs/shaders/shaderChunk/defaultVertex.glsl","../src/libs/shaders/shaderChunk/hsv2rgb.glsl","../src/libs/shaders/shaderChunk/rgb2hsv.glsl","../src/libs/shaders/ShaderChunk.ts","../src/libs/shaders/resolveShaders.ts","../src/utils/createMaterialParameters.ts","../src/fxs/interactions/useBrush/useMesh.ts","../src/utils/useCamera.ts","../src/misc/usePointer.ts","../src/utils/useParams.ts","../src/utils/useSingleFBO.ts","../src/utils/useDoubleFBO.ts","../src/utils/getDpr.ts","../src/fxs/interactions/useBrush/index.ts","../src/fxs/simulations/useFluid/shaders/main.vert","../src/fxs/simulations/useFluid/shaders/init.frag","../src/fxs/simulations/useFluid/materials/useInitialMaterial.ts","../src/fxs/simulations/useFluid/shaders/advection.frag","../src/fxs/simulations/useFluid/materials/useAdvectionMaterial.ts","../src/fxs/simulations/useFluid/shaders/divergence.frag","../src/fxs/simulations/useFluid/materials/useDivergenceMaterial.ts","../src/fxs/simulations/useFluid/shaders/pressure.frag","../src/fxs/simulations/useFluid/materials/usePressureMaterial.ts","../src/fxs/simulations/useFluid/shaders/curl.frag","../src/fxs/simulations/useFluid/materials/useCurlMaterial.ts","../src/fxs/simulations/useFluid/shaders/vorticity.frag","../src/fxs/simulations/useFluid/materials/useVorticityMaterial.ts","../src/fxs/simulations/useFluid/shaders/clear.frag","../src/fxs/simulations/useFluid/materials/useClearMaterial.ts","../src/fxs/simulations/useFluid/shaders/gradientSubtract.frag","../src/fxs/simulations/useFluid/materials/useGradientSubtractMaterial.ts","../src/fxs/simulations/useFluid/shaders/splat.frag","../src/fxs/simulations/useFluid/materials/useSplatMaterial.ts","../src/fxs/simulations/useFluid/useMesh.ts","../src/fxs/simulations/useFluid/index.ts","../src/fxs/simulations/useRipple/shader/main.vert","../src/fxs/simulations/useRipple/shader/main.frag","../src/fxs/simulations/useRipple/useMesh.ts","../src/fxs/simulations/useRipple/index.ts","../src/fxs/noises/useNoise/shader/main.vert","../src/fxs/noises/useNoise/shader/main.frag","../src/fxs/noises/useNoise/useMesh.ts","../src/fxs/noises/useNoise/index.ts","../src/fxs/noises/useColorStrata/shader/main.vert","../src/fxs/noises/useColorStrata/shader/main.frag","../src/fxs/noises/useColorStrata/useMesh.ts","../src/fxs/noises/useColorStrata/index.ts","../src/fxs/noises/useMarble/shader/main.vert","../src/fxs/noises/useMarble/shader/main.frag","../src/fxs/noises/useMarble/useMesh.ts","../src/fxs/noises/useMarble/index.ts","../src/fxs/noises/useCosPalette/shader/main.vert","../src/fxs/noises/useCosPalette/shader/main.frag","../src/fxs/noises/useCosPalette/useMesh.ts","../src/fxs/noises/useCosPalette/index.ts","../src/fxs/utils/useDuoTone/shader/main.vert","../src/fxs/utils/useDuoTone/shader/main.frag","../src/fxs/utils/useDuoTone/useMesh.ts","../src/fxs/utils/useDuoTone/index.ts","../src/fxs/utils/useBlending/shader/main.vert","../src/fxs/utils/useBlending/shader/main.frag","../src/fxs/utils/useBlending/useMesh.ts","../src/fxs/utils/useBlending/index.ts","../src/fxs/utils/useFxTexture/shader/main.vert","../src/fxs/utils/useFxTexture/shader/main.frag","../src/fxs/utils/useFxTexture/useMesh.ts","../src/fxs/utils/useFxTexture/index.ts","../src/fxs/utils/useBrightnessPicker/shader/main.vert","../src/fxs/utils/useBrightnessPicker/shader/main.frag","../src/fxs/utils/useBrightnessPicker/useMesh.ts","../src/fxs/utils/useBrightnessPicker/index.ts","../src/fxs/utils/useFxBlending/shader/main.vert","../src/fxs/utils/useFxBlending/shader/main.frag","../src/fxs/utils/useFxBlending/useMesh.ts","../src/fxs/utils/useFxBlending/index.ts","../src/fxs/utils/useAlphaBlending/shader/main.vert","../src/fxs/utils/useAlphaBlending/shader/main.frag","../src/fxs/utils/useAlphaBlending/useMesh.ts","../src/fxs/utils/useAlphaBlending/index.ts","../src/fxs/utils/useHSV/shader/main.vert","../src/fxs/utils/useHSV/shader/main.frag","../src/fxs/utils/useHSV/useMesh.ts","../src/fxs/utils/useHSV/index.ts","../src/fxs/utils/useCoverTexture/shader/main.vert","../src/fxs/utils/useCoverTexture/shader/main.frag","../src/fxs/utils/useCoverTexture/useMesh.ts","../src/fxs/utils/useCoverTexture/index.ts","../src/fxs/effects/useSimpleBlur/shader/main.vert","../src/fxs/effects/useSimpleBlur/shader/main.frag","../src/fxs/effects/useSimpleBlur/useMesh.ts","../src/fxs/effects/useSimpleBlur/index.ts","../src/fxs/effects/useMotionBlur/shader/main.vert","../src/fxs/effects/useMotionBlur/shader/main.frag","../src/fxs/effects/useMotionBlur/useMesh.ts","../src/fxs/effects/useMotionBlur/index.ts","../src/fxs/effects/useWave/shader/main.vert","../src/fxs/effects/useWave/shader/main.frag","../src/fxs/effects/useWave/useMesh.ts","../src/fxs/effects/useWave/index.ts","../src/fxs/misc/useChromaKey/shader/main.vert","../src/fxs/misc/useChromaKey/shader/main.frag","../src/fxs/misc/useChromaKey/useMesh.ts","../src/fxs/misc/useChromaKey/index.ts","../src/fxs/blank/useBlank/shader/main.vert","../src/fxs/blank/useBlank/shader/main.frag","../src/fxs/blank/useBlank/useMesh.ts","../src/fxs/blank/useBlank/index.ts","../src/fxs/blank/useRawBlank/shader/main.vert","../src/fxs/blank/useRawBlank/shader/main.frag","../src/fxs/blank/useRawBlank/useMesh.ts","../src/fxs/blank/useRawBlank/index.ts","../src/fxs/3D/useMorphParticles/utils/useCreateObject.ts","../src/fxs/3D/useMorphParticles/shaders/main.vert","../src/fxs/3D/useMorphParticles/shaders/main.frag","../src/fxs/3D/useMorphParticles/utils/rewriteVertexShader.ts","../src/fxs/3D/useMorphParticles/utils/modifyAttributes.ts","../src/fxs/3D/useMorphParticles/utils/rewriteFragmentShader.ts","../src/fxs/3D/useMorphParticles/utils/useMaterial.ts","../src/fxs/3D/useMorphParticles/useCreateMorphParticles.ts","../src/fxs/3D/useMorphParticles/index.ts","../src/fxs/3D/useWobble3D/utils/rewriteVertexShader.ts","../src/fxs/3D/useWobble3D/utils/rewriteFragmentShader.ts","../src/fxs/3D/useWobble3D/shaders/transmission_pars_fragment.glsl","../src/fxs/3D/useWobble3D/shaders/transmission_fragment.glsl","../src/fxs/3D/useWobble3D/utils/resolveEachMaterial.ts","../src/fxs/3D/useWobble3D/useMaterial.ts","../src/fxs/3D/useWobble3D/useCreateWobble3D.ts","../src/fxs/3D/useWobble3D/index.ts","../src/utils/useAddMesh.ts","../src/utils/useResizeBoundary.ts","../src/libs/Easings.ts","../src/misc/useBeat.ts","../src/misc/useFPSLimiter.ts","../src/misc/useDomSyncer/utils/errorHandler.ts","../src/misc/useDomSyncer/shader/main.vert","../src/misc/useDomSyncer/shader/main.frag","../src/misc/useDomSyncer/utils/createMesh.ts","../src/misc/useDomSyncer/utils/useIntersectionHandler.ts","../src/misc/useDomSyncer/utils/useUpdateDomRect.ts","../src/misc/useDomSyncer/utils/useIsIntersecting.ts","../src/misc/useDomSyncer/utils/createUseDomView.ts","../src/misc/useDomSyncer/index.ts","../src/misc/useCopyTexture.ts","../src/libs/Utils.ts"],"sourcesContent":["#usf ","precision highp float;\n\nuniform sampler2D uBuffer;\nuniform sampler2D uTexture;\nuniform bool uIsTexture;\nuniform sampler2D uMap;\nuniform bool uIsMap;\nuniform float uMapIntensity;\nuniform float uRadius;\nuniform float uDissipation;\nuniform vec2 uResolution;\nuniform float uSmudge;\nuniform vec2 uMouse;\nuniform vec2 uPrevMouse;\nuniform vec2 uVelocity;\nuniform vec3 uColor;\nuniform float uMotionBlur;\nuniform int uMotionSample;\nuniform bool uIsCursor;\nuniform float uPressureStart;\nuniform float uPressureEnd;\n\nvarying vec2 vUv;\n\nfloat isOnLine(vec2 point, vec2 start, vec2 end, float radius, float pressureStart, float pressureEnd) {\n\t\n\tfloat aspect = uResolution.x / uResolution.y;\n\n\tpoint.x *= aspect;\n\tstart.x *= aspect;\n\tend.x *= aspect;\n\n\tvec2 dir = normalize(end - start);\n\tvec2 n = vec2(dir.y, -dir.x);\n\tvec2 p0 = point - start;\n\t\n\tfloat distToLine = abs(dot(p0, n));\n\tfloat distAlongLine = dot(p0, dir);\n\tfloat totalLength = length(end - start);\n\n\tfloat progress = clamp(distAlongLine / totalLength, 0.0, 1.0);\n\tfloat pressure = mix(pressureStart, pressureEnd, progress);\n\tradius = min(radius,radius * pressure);\n\n\tfloat distFromStart = length(point - start);\n\tfloat distFromEnd = length(point - end);\n\t\n\tbool withinLine = (distToLine < radius && distAlongLine > 0.0 && distAlongLine < totalLength) || distFromStart < radius || distFromEnd < radius;\n\n\treturn float(withinLine);\n}\n\nvec4 createSmudge(vec2 uv){\n\tvec2 offsets[9];\n\toffsets[0] = vec2(-1, -1); offsets[1] = vec2( 0, -1); offsets[2] = vec2( 1, -1);\n\toffsets[3] = vec2(-1, 0); offsets[4] = vec2( 0, 0); offsets[5] = vec2( 1, 0);\n\toffsets[6] = vec2(-1, 1); offsets[7] = vec2( 0, 1); offsets[8] = vec2( 1, 1);\n\n\tfor(int i = 0; i < 9; i++) {\n\t\toffsets[i] = (offsets[i] * uSmudge) / uResolution;\n\t}\t\n\tvec4 smudgedColor = vec4(0.);\n\tfor(int i = 0; i < 9; i++) {\n\t\tsmudgedColor += texture2D(uBuffer, uv + offsets[i]);\n\t}\n\treturn smudgedColor / 9.0;\n}\n\nvec4 createMotionBlur(vec2 uv , vec4 baseColor, vec2 velocity) {\n\tvec2 scaledV = velocity * uMotionBlur;\n\tfor(int i = 1; i < uMotionSample; i++) {\n\t\tfloat t = float(i) / float(uMotionSample - 1);\n\t\tvec2 offset = t * scaledV / uResolution;\n\t\tbaseColor += texture2D(uBuffer, uv + offset);\n\t}\n\treturn baseColor / float(uMotionSample);\n}\n\nvoid main() {\n\n\tvec2 uv = vUv;\n\tif(uIsMap){\n\t\tvec2 mapColor = texture2D(uMap, uv).rg;\n\t\tvec2 normalizedMap = mapColor * 2.0 - 1.0;\n\t\tuv = uv * 2.0 - 1.0;\n\t\tuv *= mix(vec2(1.0), abs(normalizedMap.rg), uMapIntensity);\n\t\tuv = (uv + 1.0) / 2.0;\n\t}\n\tvec2 suv = uv*2.-1.;\n\n\tvec2 velocity = uVelocity * uResolution;\n\n\tfloat radius = max(0.0,uRadius);\n\t\n\tvec4 smudgedColor = uSmudge > 0. ? createSmudge(uv) : texture2D(uBuffer, uv);\n\n\tvec4 motionBlurredColor = uMotionBlur > 0. ? createMotionBlur(uv,smudgedColor, velocity) : smudgedColor;\n\n\tvec4 bufferColor = motionBlurredColor;\n\tbufferColor.a = bufferColor.a < 1e-10 ? 0.0 : bufferColor.a * uDissipation;\n\t\n\tvec4 brushColor = uIsTexture ? texture2D(uTexture, uv) : vec4(uColor,1.);\n\t\n\tfloat onLine = isOnLine(suv, uPrevMouse, uMouse, radius, uPressureStart,uPressureEnd);\n\tfloat isOnLine = length(velocity) > 0. ? onLine : uIsCursor ? onLine : 0.;\n\n\tvec4 finalColor = mix(bufferColor, brushColor, isOnLine);\n\n\tgl_FragColor = finalColor;\n}","import * as THREE from \"three\";\nimport { useMemo } from \"react\";\nimport { Size } from \"../fxs/types\";\n\n/**\n * @params dpr if dpr is set, it returns the resolution which is size multiplied by dpr.\n */\nexport const useResolution = (size: Size, dpr: number | false = false) => {\n const _width = dpr ? size.width * dpr : size.width;\n const _height = dpr ? size.height * dpr : size.height;\n\n const resolution = useMemo(\n () => new THREE.Vector2(_width, _height),\n [_width, _height]\n );\n return resolution;\n};\n","import * as THREE from \"three\";\ntype UniformValue =\n | THREE.CubeTexture\n | THREE.Texture\n | Int32Array\n | Float32Array\n | THREE.Matrix4\n | THREE.Matrix3\n | THREE.Quaternion\n | THREE.Vector4\n | THREE.Vector3\n | THREE.Vector2\n | THREE.Color\n | number\n | boolean\n | Array\n | null\n | undefined;\ntype UniformObject = { [key: string]: { value: UniformValue } };\n\nexport const setUniform =\n (material: { uniforms: T }) =>\n (key: keyof T, value: UniformValue) => {\n if (value === undefined) {\n return;\n }\n const uniforms = material.uniforms;\n if (uniforms && uniforms[key]) {\n uniforms[key].value = value;\n }\n };\n\nexport type CustomParams = { [uniform: string]: UniformValue };\nexport const setCustomUniform =\n (material: { uniforms: UniformObject }) =>\n (customParams: CustomParams | undefined) => {\n if (customParams === undefined) {\n return;\n }\n Object.keys(customParams).forEach((key) => {\n const uniforms = material.uniforms;\n if (uniforms && uniforms[key]) {\n uniforms[key].value = customParams[key];\n }\n });\n };\n","import * as THREE from \"three\";\nimport { useEffect, useMemo } from \"react\";\n\ntype Object3DConstructor = new (\n geometry: THREE.BufferGeometry,\n material: M\n) => T;\n\n/**\n * Add geometry and material to Object3D and add them to scene.\n */\nexport const useAddObject = <\n T extends THREE.Object3D,\n M extends THREE.Material\n>(\n scene: THREE.Scene | false,\n geometry: THREE.BufferGeometry,\n material: M,\n Proto: Object3DConstructor\n) => {\n const object3D = useMemo(() => {\n const obj = new Proto(geometry, material);\n scene && scene.add(obj);\n return obj;\n }, [geometry, material, Proto, scene]);\n\n useEffect(() => {\n return () => {\n scene && scene.remove(object3D);\n geometry.dispose();\n material.dispose();\n };\n }, [scene, geometry, material, object3D]);\n\n return object3D;\n};\n","import * as THREE from \"three\";\n\nexport const ISDEV = process.env.NODE_ENV === \"development\";\n\nexport const MATERIAL_BASIC_PARAMS = {\n transparent: false,\n depthTest: false,\n depthWrite: false,\n};\n\nexport const DEFAULT_TEXTURE = new THREE.DataTexture(\n new Uint8Array([0, 0, 0, 0]),\n 1,\n 1,\n THREE.RGBAFormat\n);\n","//\tSimplex 4D Noise \n//\tby Ian McEwan, Ashima Arts\n//\nvec4 permute(vec4 x){return mod(((x*34.0)+1.0)*x, 289.0);}\nfloat permute(float x){return floor(mod(((x*34.0)+1.0)*x, 289.0));}\nvec4 taylorInvSqrt(vec4 r){return 1.79284291400159 - 0.85373472095314 * r;}\nfloat taylorInvSqrt(float r){return 1.79284291400159 - 0.85373472095314 * r;}\n\nvec4 grad4(float j, vec4 ip)\n{\n\tconst vec4 ones = vec4(1.0, 1.0, 1.0, -1.0);\n\tvec4 p,s;\n\n\tp.xyz = floor( fract (vec3(j) * ip.xyz) * 7.0) * ip.z - 1.0;\n\tp.w = 1.5 - dot(abs(p.xyz), ones.xyz);\n\ts = vec4(lessThan(p, vec4(0.0)));\n\tp.xyz = p.xyz + (s.xyz*2.0 - 1.0) * s.www; \n\n\treturn p;\n}\n\nfloat simplexNoise4d(vec4 v)\n{\n\tconst vec2 C = vec2( 0.138196601125010504, // (5 - sqrt(5))/20 G4\n\t\t\t\t\t\t\t\t\t0.309016994374947451); // (sqrt(5) - 1)/4 F4\n\t// First corner\n\tvec4 i = floor(v + dot(v, C.yyyy) );\n\tvec4 x0 = v - i + dot(i, C.xxxx);\n\n\t// Other corners\n\n\t// Rank sorting originally contributed by Bill Licea-Kane, AMD (formerly ATI)\n\tvec4 i0;\n\n\tvec3 isX = step( x0.yzw, x0.xxx );\n\tvec3 isYZ = step( x0.zww, x0.yyz );\n\t// i0.x = dot( isX, vec3( 1.0 ) );\n\ti0.x = isX.x + isX.y + isX.z;\n\ti0.yzw = 1.0 - isX;\n\n\t// i0.y += dot( isYZ.xy, vec2( 1.0 ) );\n\ti0.y += isYZ.x + isYZ.y;\n\ti0.zw += 1.0 - isYZ.xy;\n\n\ti0.z += isYZ.z;\n\ti0.w += 1.0 - isYZ.z;\n\n\t// i0 now contains the unique values 0,1,2,3 in each channel\n\tvec4 i3 = clamp( i0, 0.0, 1.0 );\n\tvec4 i2 = clamp( i0-1.0, 0.0, 1.0 );\n\tvec4 i1 = clamp( i0-2.0, 0.0, 1.0 );\n\n\t// x0 = x0 - 0.0 + 0.0 * C \n\tvec4 x1 = x0 - i1 + 1.0 * C.xxxx;\n\tvec4 x2 = x0 - i2 + 2.0 * C.xxxx;\n\tvec4 x3 = x0 - i3 + 3.0 * C.xxxx;\n\tvec4 x4 = x0 - 1.0 + 4.0 * C.xxxx;\n\n\t// Permutations\n\ti = mod(i, 289.0); \n\tfloat j0 = permute( permute( permute( permute(i.w) + i.z) + i.y) + i.x);\n\tvec4 j1 = permute( permute( permute( permute (\n\t\t\t\t\ti.w + vec4(i1.w, i2.w, i3.w, 1.0 ))\n\t\t\t\t+ i.z + vec4(i1.z, i2.z, i3.z, 1.0 ))\n\t\t\t\t+ i.y + vec4(i1.y, i2.y, i3.y, 1.0 ))\n\t\t\t\t+ i.x + vec4(i1.x, i2.x, i3.x, 1.0 ));\n\t// Gradients\n\t// ( 7*7*6 points uniformly over a cube, mapped onto a 4-octahedron.)\n\t// 7*7*6 = 294, which is close to the ring size 17*17 = 289.\n\n\tvec4 ip = vec4(1.0/294.0, 1.0/49.0, 1.0/7.0, 0.0) ;\n\n\tvec4 p0 = grad4(j0, ip);\n\tvec4 p1 = grad4(j1.x, ip);\n\tvec4 p2 = grad4(j1.y, ip);\n\tvec4 p3 = grad4(j1.z, ip);\n\tvec4 p4 = grad4(j1.w, ip);\n\n\t// Normalise gradients\n\tvec4 norm = taylorInvSqrt(vec4(dot(p0,p0), dot(p1,p1), dot(p2, p2), dot(p3,p3)));\n\tp0 *= norm.x;\n\tp1 *= norm.y;\n\tp2 *= norm.z;\n\tp3 *= norm.w;\n\tp4 *= taylorInvSqrt(dot(p4,p4));\n\n\t// Mix contributions from the five corners\n\tvec3 m0 = max(0.6 - vec3(dot(x0,x0), dot(x1,x1), dot(x2,x2)), 0.0);\n\tvec2 m1 = max(0.6 - vec2(dot(x3,x3), dot(x4,x4) ), 0.0);\n\tm0 = m0 * m0;\n\tm1 = m1 * m1;\n\treturn 49.0 * ( dot(m0*m0, vec3( dot( p0, x0 ), dot( p1, x1 ), dot( p2, x2 )))\n\t\t\t\t\t\t+ dot(m1*m1, vec2( dot( p3, x3 ), dot( p4, x4 ) ) ) ) ;\n\n}\n\nfloat getWobble(vec3 position)\n{\n\tvec3 warpedPosition = position;\n\twarpedPosition += simplexNoise4d(\n\t\tvec4(\n\t\t\t\tposition * uWarpPositionFrequency,\n\t\t\t\tuTime * uWarpTimeFrequency\n\t\t)\n\t) * uWarpStrength;\n\n\treturn simplexNoise4d(vec4(\n\t\twarpedPosition * uWobblePositionFrequency, // XYZ\n\t\tuTime * uWobbleTimeFrequency // W\n\t)) * uWobbleStrength;\n}","// \n//\tby Nikita Miropolskiy\n\n/* discontinuous pseudorandom uniformly distributed in [-0.5, +0.5]^3 */\nvec3 random3(vec3 c) {\n\tfloat j = 4096.0*sin(dot(c,vec3(17.0, 59.4, 15.0)));\n\tvec3 r;\n\tr.z = fract(512.0*j);\n\tj *= .125;\n\tr.x = fract(512.0*j);\n\tj *= .125;\n\tr.y = fract(512.0*j);\n\treturn r-0.5;\n}\n\nconst float F3 = 0.3333333;\nconst float G3 = 0.1666667;\n\nfloat snoise(vec3 p) {\n\n\tvec3 s = floor(p + dot(p, vec3(F3)));\n\tvec3 x = p - s + dot(s, vec3(G3));\n\t\n\tvec3 e = step(vec3(0.0), x - x.yzx);\n\tvec3 i1 = e*(1.0 - e.zxy);\n\tvec3 i2 = 1.0 - e.zxy*(1.0 - e);\n \t\n\tvec3 x1 = x - i1 + G3;\n\tvec3 x2 = x - i2 + 2.0*G3;\n\tvec3 x3 = x - 1.0 + 3.0*G3;\n\t \n\tvec4 w, d;\n\t \n\tw.x = dot(x, x);\n\tw.y = dot(x1, x1);\n\tw.z = dot(x2, x2);\n\tw.w = dot(x3, x3);\n\t \n\tw = max(0.6 - w, 0.0);\n\t \n\td.x = dot(random3(s), x);\n\td.y = dot(random3(s + i1), x1);\n\td.z = dot(random3(s + i2), x2);\n\td.w = dot(random3(s + 1.0), x3);\n\t \n\tw *= w;\n\tw *= w;\n\td *= w;\n\t \n\treturn dot(d, vec4(52.0));\n}\n\nfloat snoiseFractal(vec3 m) {\n\treturn 0.5333333* snoise(m)\n\t\t\t\t+0.2666667* snoise(2.0*m)\n\t\t\t\t+0.1333333* snoise(4.0*m)\n\t\t\t\t+0.0666667* snoise(8.0*m);\n}","float screenAspect = uResolution.x / uResolution.y;\nfloat textureAspect = uTextureResolution.x / uTextureResolution.y;\nvec2 aspectRatio = vec2(\n\tmin(screenAspect / textureAspect, 1.0),\n\tmin(textureAspect / screenAspect, 1.0)\n);\nvec2 uv = vUv * aspectRatio + (1.0 - aspectRatio) * .5;","vec3 mapColor = texture2D(uMap, uv).rgb;\nvec3 normalizedMap = mapColor * 2.0 - 1.0;\n\nuv = uv * 2.0 - 1.0;\nuv *= mix(vec2(1.0), abs(normalizedMap.rg), uMapIntensity);\nuv = (uv + 1.0) / 2.0;","precision highp float;\n\nvarying vec2 vUv;\n\nvoid main() {\n\tvUv = uv;\n\tgl_Position = vec4(position, 1.0);\n}","varying vec2 vUv;\n\nvoid main() {\n\tvUv = uv;\n\tgl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);\n}","vec3 hsv2rgb(vec3 c)\n{\n vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);\n vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);\n return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);\n}","vec3 rgb2hsv(vec3 c)\n{\n vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);\n vec4 p = mix(vec4(c.bg, K.wz), vec4(c.gb, K.xy), step(c.b, c.g));\n vec4 q = mix(vec4(p.xyw, c.r), vec4(c.r, p.yzx), step(p.x, c.r));\n\n float d = q.x - min(q.w, q.y);\n float e = 1.0e-10;\n return vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x);\n}","import wobble3D from \"./shaderChunk/wobble3D.glsl\";\nimport snoise from \"./shaderChunk/snoise.glsl\";\nimport coverTexture from \"./shaderChunk/coverTexture.glsl\";\nimport fxBlending from \"./shaderChunk/fxBlending.glsl\";\nimport planeVertex from \"./shaderChunk/planeVertex.glsl\";\nimport defaultVertex from \"./shaderChunk/defaultVertex.glsl\";\nimport hsv2rgb from \"./shaderChunk/hsv2rgb.glsl\";\nimport rgb2hsv from \"./shaderChunk/rgb2hsv.glsl\";\n\nexport type ShaderChunkTypes =\n | \"wobble3D\"\n | \"snoise\"\n | \"coverTexture\"\n | \"fxBlending\"\n | \"planeVertex\"\n | \"defaultVertex\"\n | \"hsv2rgb\"\n | \"rgb2hsv\";\n\nexport const ShaderChunk: { [K in ShaderChunkTypes]: string } = Object.freeze({\n wobble3D,\n snoise,\n coverTexture,\n fxBlending,\n planeVertex,\n defaultVertex,\n hsv2rgb,\n rgb2hsv,\n});\n","import { ShaderChunk, ShaderChunkTypes } from \"./ShaderChunk\";\n\nconst includePattern = /^[ \\t]*#usf +<([\\w\\d./]+)>/gm;\n\nfunction includeReplacer(match: string, include: ShaderChunkTypes): string {\n return resolveIncludes(ShaderChunk[include] || \"\");\n}\n\nfunction resolveIncludes(string: string): string {\n return string.replace(includePattern, includeReplacer);\n}\n\nexport { resolveIncludes };\n","import { resolveIncludes } from \"../libs/shaders/resolveShaders\";\nimport { OnBeforeInitParameters } from \"../fxs/types\";\n\nexport const createMaterialParameters = (\n parameters: OnBeforeInitParameters,\n onBeforeInit?: (parameters: OnBeforeInitParameters) => void\n) => {\n onBeforeInit && onBeforeInit(parameters);\n parameters.vertexShader = resolveIncludes(parameters.vertexShader);\n parameters.fragmentShader = resolveIncludes(parameters.fragmentShader);\n return parameters;\n};\n","import * as THREE from \"three\";\nimport vertexShader from \"./shader/main.vert\";\nimport fragmentShader from \"./shader/main.frag\";\nimport { useMemo } from \"react\";\nimport { useResolution } from \"../../../utils/useResolution\";\nimport { setUniform } from \"../../../utils/setUniforms\";\nimport { useAddObject } from \"../../../utils/useAddObject\";\nimport { MaterialProps, Size } from \"../../types\";\nimport {\n DEFAULT_TEXTURE,\n MATERIAL_BASIC_PARAMS,\n} from \"../../../libs/constants\";\nimport { BRUSH_PARAMS } from \".\";\nimport { createMaterialParameters } from \"../../../utils/createMaterialParameters\";\n\nexport class BrushMaterial extends THREE.ShaderMaterial {\n uniforms!: {\n uBuffer: { value: THREE.Texture };\n uTexture: { value: THREE.Texture };\n uIsTexture: { value: boolean };\n uMap: { value: THREE.Texture };\n uIsMap: { value: boolean };\n uMapIntensity: { value: number };\n uResolution: { value: THREE.Vector2 };\n uRadius: { value: number };\n uSmudge: { value: number };\n uDissipation: { value: number };\n uMotionBlur: { value: number };\n uMotionSample: { value: number };\n uMouse: { value: number };\n uPrevMouse: { value: number };\n uVelocity: { value: number };\n uColor: { value: THREE.Vector3 | THREE.Color };\n uIsCursor: { value: boolean };\n uPressureStart: { value: number };\n uPressureEnd: { value: number };\n };\n}\n\nexport const useMesh = ({\n scene,\n size,\n dpr,\n onBeforeInit,\n}: {\n scene: THREE.Scene;\n size: Size;\n dpr: number | false;\n} & MaterialProps) => {\n const geometry = useMemo(() => new THREE.PlaneGeometry(2, 2), []);\n const material = useMemo(() => {\n const mat = new THREE.ShaderMaterial({\n ...createMaterialParameters(\n {\n uniforms: {\n uBuffer: { value: DEFAULT_TEXTURE },\n uResolution: { value: new THREE.Vector2(0, 0) },\n uTexture: { value: DEFAULT_TEXTURE },\n uIsTexture: { value: false },\n uMap: { value: DEFAULT_TEXTURE },\n uIsMap: { value: false },\n uMapIntensity: { value: BRUSH_PARAMS.mapIntensity },\n uRadius: { value: BRUSH_PARAMS.radius },\n uSmudge: { value: BRUSH_PARAMS.smudge },\n uDissipation: { value: BRUSH_PARAMS.dissipation },\n uMotionBlur: { value: BRUSH_PARAMS.motionBlur },\n uMotionSample: { value: BRUSH_PARAMS.motionSample },\n uMouse: { value: new THREE.Vector2(-10, -10) },\n uPrevMouse: { value: new THREE.Vector2(-10, -10) },\n uVelocity: { value: new THREE.Vector2(0, 0) },\n uColor: { value: BRUSH_PARAMS.color },\n uIsCursor: { value: false },\n uPressureStart: { value: 1.0 },\n uPressureEnd: { value: 1.0 },\n },\n vertexShader: vertexShader,\n fragmentShader: fragmentShader,\n },\n onBeforeInit\n ),\n ...MATERIAL_BASIC_PARAMS,\n // Must be transparent\n transparent: true,\n });\n\n return mat;\n }, [onBeforeInit]) as BrushMaterial;\n\n const resolution = useResolution(size, dpr);\n setUniform(material)(\"uResolution\", resolution.clone());\n\n const mesh = useAddObject(scene, geometry, material, THREE.Mesh);\n\n return { material, mesh };\n};\n","import * as THREE from \"three\";\nimport { useResolution } from \"./useResolution\";\nimport { useMemo } from \"react\";\nimport { Size } from \"../fxs/types\";\n\nconst getCameraProps = (width: number, height: number) => {\n const frustumSize = height;\n const aspect = width / height;\n const [w, h] = [(frustumSize * aspect) / 2, frustumSize / 2];\n return { width: w, height: h, near: -1000, far: 1000 };\n};\n\nexport const useCamera = (\n size: Size,\n cameraType: \"OrthographicCamera\" | \"PerspectiveCamera\" = \"OrthographicCamera\"\n) => {\n const resolution = useResolution(size);\n const { width, height, near, far } = getCameraProps(\n resolution.x,\n resolution.y\n );\n const camera = useMemo(() => {\n return cameraType === \"OrthographicCamera\"\n ? new THREE.OrthographicCamera(\n -width,\n width,\n height,\n -height,\n near,\n far\n )\n : new THREE.PerspectiveCamera(50, width / height);\n }, [width, height, near, far, cameraType]);\n return camera;\n};\n","import * as THREE from \"three\";\nimport { useCallback, useRef } from \"react\";\n\nexport type PointerValues = {\n currentPointer: THREE.Vector2;\n prevPointer: THREE.Vector2;\n diffPointer: THREE.Vector2;\n velocity: THREE.Vector2;\n isVelocityUpdate: boolean;\n};\n\ntype UpdatePointer = (currentPointer: THREE.Vector2) => PointerValues;\n\n/**\n * @description When given the pointer vector2 from r3f's RootState, it generates an update function that returns {`currentPointer`, `prevPointer`, `diffPointer`, `isVelocityUpdate`, `velocity`}.\n * @description When calling custom in a `useFrame` loop, you can avoid duplication of execution by passing `pointerValues` to the update function of a Pointer-activated fxHook, such as `useBrush`.\n * @param lerp 0~1, lerp intensity (0 to less than 1) , default : `0`\n */\nexport const usePointer = (lerp: number = 0): UpdatePointer => {\n const prevPointer = useRef(new THREE.Vector2(0, 0));\n const diffPointer = useRef(new THREE.Vector2(0, 0));\n const lerpPointer = useRef(new THREE.Vector2(0, 0));\n const lastUpdateTime = useRef(0);\n const velocity = useRef(new THREE.Vector2(0, 0));\n const isMoved = useRef(false);\n\n const updatePointer = useCallback(\n (currentPointer: THREE.Vector2) => {\n const now = performance.now();\n\n // lerp\n let current: THREE.Vector2;\n if (isMoved.current && lerp) {\n lerpPointer.current = lerpPointer.current.lerp(\n currentPointer,\n 1 - lerp\n );\n current = lerpPointer.current.clone();\n } else {\n current = currentPointer.clone();\n lerpPointer.current = current;\n }\n\n // first frame\n if (lastUpdateTime.current === 0) {\n lastUpdateTime.current = now;\n prevPointer.current = current;\n }\n const deltaTime = Math.max(1, now - lastUpdateTime.current);\n lastUpdateTime.current = now;\n\n // get velocity\n velocity.current\n .copy(current)\n .sub(prevPointer.current)\n .divideScalar(deltaTime);\n const isUpdate = velocity.current.length() > 0;\n\n //set prev temp pos\n const prevTemp = isMoved.current\n ? prevPointer.current.clone()\n : current;\n if (!isMoved.current && isUpdate) {\n isMoved.current = true;\n }\n prevPointer.current = current;\n\n return {\n currentPointer: current,\n prevPointer: prevTemp,\n diffPointer: diffPointer.current.subVectors(current, prevTemp),\n velocity: velocity.current,\n isVelocityUpdate: isUpdate,\n };\n },\n [lerp]\n );\n\n return updatePointer;\n};\n","import { useCallback, useRef } from \"react\";\n\ntype SetParams = (newParams?: Partial) => void;\ntype UseParamsReturn = [T, SetParams];\n\n/**\n * @param params Receives an initial value object. With structuredClone, deep copy and set, but if the object contains a function, just set it.\n */\nexport const useParams = (params: T): UseParamsReturn => {\n const isContainsFunctions = (obj: object): boolean =>\n Object.values(obj).some((value) => typeof value === \"function\");\n const paramsRef = useRef(\n isContainsFunctions(params) ? params : structuredClone(params)\n );\n\n const setParams = useCallback>((newParams) => {\n if (newParams === undefined) {\n return;\n }\n for (const key in newParams) {\n const paramKey = key as keyof T;\n if (\n paramKey in paramsRef.current &&\n newParams[paramKey] !== undefined &&\n newParams[paramKey] !== null\n ) {\n paramsRef.current[paramKey] = newParams[paramKey]!;\n } else {\n console.error(\n `\"${String(\n paramKey\n )}\" does not exist in the params. or \"${String(\n paramKey\n )}\" is null | undefined`\n );\n }\n }\n }, []);\n return [paramsRef.current, setParams];\n};\n","import * as THREE from \"three\";\nimport { useCallback, useEffect, useMemo, useRef } from \"react\";\nimport { useResolution } from \"./useResolution\";\nimport { Size } from \"../fxs/types\";\n\nexport const FBO_DEFAULT_OPTION: THREE.RenderTargetOptions = {\n depthBuffer: false,\n};\n\nexport type UseFboProps = {\n scene: THREE.Scene;\n camera: THREE.Camera;\n size: Size;\n /** If dpr is set, dpr will be multiplied, default : `false` */\n dpr?: number | false;\n /** Whether to resize when resizing occurs. If isDpr is true, set FBO to setSize even if dpr is changed, default : `false` */\n isSizeUpdate?: boolean;\n /** If set, the scene depth will be rendered into buffer.depthTexture. default : `false` */\n depth?: boolean;\n} & THREE.RenderTargetOptions;\n\nexport const renderFBO = ({\n gl,\n fbo,\n scene,\n camera,\n onBeforeRender,\n onSwap,\n}: {\n gl: THREE.WebGLRenderer;\n fbo: THREE.WebGLRenderTarget;\n scene: THREE.Scene;\n camera: THREE.Camera;\n onBeforeRender: () => void;\n onSwap?: () => void;\n}) => {\n gl.setRenderTarget(fbo);\n onBeforeRender();\n gl.clear();\n gl.render(scene, camera);\n onSwap && onSwap();\n gl.setRenderTarget(null);\n gl.clear();\n};\n\ntype UpdateRenderTarget = (\n gl: THREE.WebGLRenderer,\n /** call before FBO is rendered */\n onBeforeRender?: ({ read }: { read: THREE.Texture }) => void\n) => THREE.Texture;\n\ntype UseSingleFBOReturn = [THREE.WebGLRenderTarget, UpdateRenderTarget];\n\n/**\n * @param dpr If dpr is set, dpr will be multiplied, default:false\n * @param isSizeUpdate Whether to resize when resizing occurs. If isDpr is true, set FBO to setSize even if dpr is changed, default:false\n * @param depthBuffer Unlike the default in three.js, the default is `false`.\n * @returns [THREE.WebGLRenderTarget , updateFBO] -Receives the RenderTarget as the first argument and the update function as the second argument.\n */\nexport const useSingleFBO = (props: UseFboProps): UseSingleFBOReturn => {\n const {\n scene,\n camera,\n size,\n dpr = false,\n isSizeUpdate = false,\n depth = false,\n ...renderTargetOptions\n } = props;\n\n const renderTarget = useRef();\n\n const resolution = useResolution(size, dpr);\n\n renderTarget.current = useMemo(\n () => {\n const target = new THREE.WebGLRenderTarget(\n resolution.x,\n resolution.y,\n {\n ...FBO_DEFAULT_OPTION,\n ...renderTargetOptions,\n }\n );\n if (depth) {\n target.depthTexture = new THREE.DepthTexture(\n resolution.x,\n resolution.y,\n THREE.FloatType\n );\n }\n return target;\n },\n // eslint-disable-next-line react-hooks/exhaustive-deps\n []\n );\n\n if (isSizeUpdate) {\n renderTarget.current?.setSize(resolution.x, resolution.y);\n }\n\n useEffect(() => {\n const temp = renderTarget.current;\n return () => {\n temp?.dispose();\n };\n }, []);\n\n const updateRenderTarget: UpdateRenderTarget = useCallback(\n (gl, onBeforeRender) => {\n const fbo = renderTarget.current!;\n renderFBO({\n gl,\n fbo,\n scene,\n camera,\n onBeforeRender: () =>\n onBeforeRender && onBeforeRender({ read: fbo.texture }),\n });\n return fbo.texture;\n },\n [scene, camera]\n );\n\n return [renderTarget.current, updateRenderTarget];\n};\n","import * as THREE from \"three\";\nimport { useCallback, useEffect, useMemo } from \"react\";\nimport { FBO_DEFAULT_OPTION, UseFboProps, renderFBO } from \"./useSingleFBO\";\nimport { useResolution } from \"./useResolution\";\n\nexport type DoubleRenderTarget = {\n read: THREE.WebGLRenderTarget;\n write: THREE.WebGLRenderTarget;\n};\n\ninterface WebGLDoubleRenderTarget extends DoubleRenderTarget {\n swap: () => void;\n}\n\ntype FBOUpdateFunction = (\n gl: THREE.WebGLRenderer,\n /** call before FBO is rendered */\n onBeforeRender?: ({\n read,\n write,\n }: {\n read: THREE.Texture;\n write: THREE.Texture;\n }) => void\n) => THREE.Texture;\n\ntype UseDoubleFBOReturn = [\n { read: THREE.WebGLRenderTarget; write: THREE.WebGLRenderTarget },\n FBOUpdateFunction\n];\n\n/**\n * @description Custom hook for setting up double buffering with WebGL render targets.\n * @param UseFboProps same as `useSingleFBO`\n */\nexport const useDoubleFBO = (props: UseFboProps): UseDoubleFBOReturn => {\n const {\n scene,\n camera,\n size,\n dpr = false,\n isSizeUpdate = false,\n depth = false,\n ...renderTargetOptions\n } = props;\n\n const resolution = useResolution(size, dpr);\n\n const renderTarget = useMemo(() => {\n const read = new THREE.WebGLRenderTarget(resolution.x, resolution.y, {\n ...FBO_DEFAULT_OPTION,\n ...renderTargetOptions,\n });\n const write = new THREE.WebGLRenderTarget(resolution.x, resolution.y, {\n ...FBO_DEFAULT_OPTION,\n ...renderTargetOptions,\n });\n\n if (depth) {\n read.depthTexture = new THREE.DepthTexture(\n resolution.x,\n resolution.y,\n THREE.FloatType\n );\n write.depthTexture = new THREE.DepthTexture(\n resolution.x,\n resolution.y,\n THREE.FloatType\n );\n }\n\n return {\n read: read,\n write: write,\n swap: function () {\n let temp = this.read;\n this.read = this.write;\n this.write = temp;\n },\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n if (isSizeUpdate) {\n renderTarget.read?.setSize(resolution.x, resolution.y);\n renderTarget.write?.setSize(resolution.x, resolution.y);\n }\n\n useEffect(() => {\n const temp = renderTarget;\n return () => {\n temp.read?.dispose();\n temp.write?.dispose();\n };\n }, [renderTarget]);\n\n const updateRenderTarget: FBOUpdateFunction = useCallback(\n (gl, onBeforeRender) => {\n const fbo = renderTarget;\n renderFBO({\n gl,\n scene,\n camera,\n fbo: fbo.write!,\n onBeforeRender: () =>\n onBeforeRender &&\n onBeforeRender({\n read: fbo.read!.texture,\n write: fbo.write!.texture,\n }),\n onSwap: () => fbo.swap(),\n });\n return fbo.read?.texture as THREE.Texture;\n },\n [scene, camera, renderTarget]\n );\n\n return [\n { read: renderTarget.read, write: renderTarget.write },\n updateRenderTarget,\n ];\n};\n","import { Dpr } from \"../fxs/types\";\n\nexport const getDpr = (\n dpr: Dpr\n): { shader: number | false; fbo: number | false } => {\n if (typeof dpr === \"number\") {\n return { shader: dpr, fbo: dpr };\n }\n return {\n shader: dpr.shader ?? false,\n fbo: dpr.fbo ?? false,\n };\n};\n","import * as THREE from \"three\";\nimport { useMesh } from \"./useMesh\";\nimport { useCamera } from \"../../../utils/useCamera\";\nimport { useCallback, useMemo, useRef } from \"react\";\nimport { RootState } from \"@react-three/fiber\";\nimport { PointerValues, usePointer } from \"../../../misc/usePointer\";\nimport {\n CustomParams,\n setCustomUniform,\n setUniform,\n} from \"../../../utils/setUniforms\";\nimport { HooksProps, HooksReturn } from \"../../types\";\nimport { useParams } from \"../../../utils/useParams\";\nimport { DoubleRenderTarget, useDoubleFBO } from \"../../../utils/useDoubleFBO\";\nimport { getDpr } from \"../../../utils/getDpr\";\n\nexport type BrushParams = {\n /** Texture applied to the brush, If texture is true, it will take precedence over color , default : `false` */\n texture?: THREE.Texture | false;\n /** You can attach an fx map , default : `false` */\n map?: THREE.Texture | false;\n /** map intensity , default : `0.1` */\n mapIntensity?: number;\n /** size of the stamp, percentage of the size ,default : `0.05` */\n radius?: number;\n /** Strength of smudge effect , default : `0.0`*/\n smudge?: number;\n /** dissipation rate. If set to 1, it will remain. , default : `1.0` */\n dissipation?: number;\n /** Strength of motion blur , default : `0.0` */\n motionBlur?: number;\n /** Number of motion blur samples. Affects performance default : `5` */\n motionSample?: number;\n /** brush color , it accepts a function that returns THREE.Vector3.The function takes velocity:THREE.Vector2 as an argument. , default : `THREE.Vector3(1.0, 1.0, 1.0)` */\n color?:\n | ((velocity: THREE.Vector2) => THREE.Vector3)\n | THREE.Vector3\n | THREE.Color;\n /** Follows the cursor even if it loses speed , default : `false` */\n isCursor?: boolean;\n /** brush pressure (0 to 1) , default : `1.0` */\n pressure?: number;\n /** When calling usePointer in a frame loop, setting PointerValues ​​to this value prevents double calls , default : `false` */\n pointerValues?: PointerValues | false;\n};\n\nexport type BrushObject = {\n scene: THREE.Scene;\n mesh: THREE.Mesh;\n material: THREE.Material;\n camera: THREE.Camera;\n renderTarget: DoubleRenderTarget;\n output: THREE.Texture;\n};\n\nexport const BRUSH_PARAMS: BrushParams = Object.freeze({\n texture: false,\n map: false,\n mapIntensity: 0.1,\n radius: 0.05,\n smudge: 0.0,\n dissipation: 1.0,\n motionBlur: 0.0,\n motionSample: 5,\n color: new THREE.Vector3(1.0, 0.0, 0.0),\n isCursor: false,\n pressure: 1.0,\n pointerValues: false,\n});\n\n/**\n * @link https://github.com/FunTechInc/use-shader-fx?tab=readme-ov-file#usage\n */\nexport const useBrush = ({\n size,\n dpr,\n renderTargetOptions,\n isSizeUpdate,\n onBeforeInit,\n}: HooksProps): HooksReturn => {\n const _dpr = getDpr(dpr);\n\n const scene = useMemo(() => new THREE.Scene(), []);\n const { material, mesh } = useMesh({\n scene,\n size,\n dpr: _dpr.shader,\n onBeforeInit,\n });\n const camera = useCamera(size);\n const updatePointer = usePointer();\n const [renderTarget, updateRenderTarget] = useDoubleFBO({\n scene,\n camera,\n size,\n dpr: _dpr.fbo,\n isSizeUpdate,\n ...renderTargetOptions,\n });\n\n const [params, setParams] = useParams(BRUSH_PARAMS);\n\n const pressureEnd = useRef(null);\n\n const updateValue = setUniform(material);\n const updateCustomValue = setCustomUniform(material);\n\n const updateParams = useCallback(\n (newParams?: BrushParams, customParams?: CustomParams) => {\n setParams(newParams);\n updateCustomValue(customParams);\n },\n [setParams, updateCustomValue]\n );\n\n const updateFx = useCallback(\n (\n rootState: RootState,\n newParams?: BrushParams,\n customParams?: CustomParams\n ) => {\n const { gl, pointer } = rootState;\n\n updateParams(newParams, customParams);\n\n if (params.texture!) {\n updateValue(\"uIsTexture\", true);\n updateValue(\"uTexture\", params.texture!);\n } else {\n updateValue(\"uIsTexture\", false);\n }\n\n if (params.map!) {\n updateValue(\"uIsMap\", true);\n updateValue(\"uMap\", params.map!);\n updateValue(\"uMapIntensity\", params.mapIntensity!);\n } else {\n updateValue(\"uIsMap\", false);\n }\n\n updateValue(\"uRadius\", params.radius!);\n updateValue(\"uSmudge\", params.smudge!);\n updateValue(\"uDissipation\", params.dissipation!);\n updateValue(\"uMotionBlur\", params.motionBlur!);\n updateValue(\"uMotionSample\", params.motionSample!);\n\n const pointerValues = params.pointerValues! || updatePointer(pointer);\n\n if (pointerValues.isVelocityUpdate) {\n updateValue(\"uMouse\", pointerValues.currentPointer);\n updateValue(\"uPrevMouse\", pointerValues.prevPointer);\n }\n updateValue(\"uVelocity\", pointerValues.velocity);\n\n const color: THREE.Vector3 | THREE.Color =\n typeof params.color === \"function\"\n ? params.color(pointerValues.velocity)\n : params.color!;\n updateValue(\"uColor\", color);\n\n updateValue(\"uIsCursor\", params.isCursor!);\n\n // pressure\n updateValue(\"uPressureEnd\", params.pressure!);\n if (pressureEnd.current === null) {\n pressureEnd.current = params.pressure!;\n }\n updateValue(\"uPressureStart\", pressureEnd.current);\n pressureEnd.current = params.pressure!;\n\n return updateRenderTarget(gl, ({ read }) => {\n updateValue(\"uBuffer\", read);\n });\n },\n [updateValue, updatePointer, updateRenderTarget, params, updateParams]\n );\n\n return [\n updateFx,\n updateParams,\n {\n scene: scene,\n mesh: mesh,\n material: material,\n camera: camera,\n renderTarget: renderTarget,\n output: renderTarget.read.texture,\n },\n ];\n};\n","varying vec2 vUv;\nvarying vec2 vL;\nvarying vec2 vR;\nvarying vec2 vT;\nvarying vec2 vB;\nuniform vec2 texelSize;\n\nvoid main () {\n\tvUv = uv;\n\tvL = vUv - vec2(texelSize.x, 0.0);\n\tvR = vUv + vec2(texelSize.x, 0.0);\n\tvT = vUv + vec2(0.0, texelSize.y);\n\tvB = vUv - vec2(0.0, texelSize.y);\n\tgl_Position = vec4(position, 1.0);\n}","precision highp float;\n\nvoid main(){\n\tgl_FragColor = vec4(0.0);\n}","import * as THREE from \"three\";\nimport { useMemo } from \"react\";\nimport vertexShader from \"../shaders/main.vert\";\nimport fragmentShader from \"../shaders/init.frag\";\nimport { MATERIAL_BASIC_PARAMS } from \"../../../../libs/constants\";\n\nexport const useInitialMaterial = () => {\n const initialMaterial = useMemo(() => {\n const mat = new THREE.ShaderMaterial({\n vertexShader: vertexShader,\n fragmentShader: fragmentShader,\n ...MATERIAL_BASIC_PARAMS,\n });\n return mat;\n }, []);\n\n return initialMaterial as THREE.ShaderMaterial;\n};\n","precision highp float;\n\nvarying vec2 vUv;\nuniform sampler2D uVelocity;\nuniform sampler2D uSource;\nuniform vec2 texelSize;\nuniform float dt;\nuniform float dissipation;\n\nvoid main () {\n\tvec2 coord = vUv - dt * texture2D(uVelocity, vUv).xy * texelSize;\n\tgl_FragColor = vec4(dissipation * texture2D(uSource, coord).rgb,1.);\n}","import * as THREE from \"three\";\nimport { useMemo } from \"react\";\nimport vertexShader from \"../shaders/main.vert\";\nimport fragmentShader from \"../shaders/advection.frag\";\nimport { MaterialProps } from \"../../../types\";\nimport {\n DEFAULT_TEXTURE,\n MATERIAL_BASIC_PARAMS,\n} from \"../../../../libs/constants\";\nimport { DELTA_TIME } from \"..\";\nimport { createMaterialParameters } from \"../../../../utils/createMaterialParameters\";\n\nexport class AdvectionMaterial extends THREE.ShaderMaterial {\n uniforms!: {\n uVelocity: { value: THREE.Texture };\n uSource: { value: THREE.Texture };\n texelSize: { value: THREE.Vector2 };\n dt: { value: number };\n dissipation: { value: number };\n };\n}\n\nexport const useAdvectionMaterial = ({ onBeforeInit }: MaterialProps) => {\n const advectionMaterial = useMemo(() => {\n const mat = new THREE.ShaderMaterial({\n ...createMaterialParameters(\n {\n uniforms: {\n uVelocity: { value: DEFAULT_TEXTURE },\n uSource: { value: DEFAULT_TEXTURE },\n texelSize: { value: new THREE.Vector2() },\n dt: { value: DELTA_TIME },\n dissipation: { value: 0.0 },\n },\n vertexShader: vertexShader,\n fragmentShader: fragmentShader,\n },\n onBeforeInit\n ),\n ...MATERIAL_BASIC_PARAMS,\n });\n\n return mat;\n }, [onBeforeInit]);\n\n return advectionMaterial as AdvectionMaterial;\n};\n","precision highp float;\n\nvarying vec2 vUv;\nvarying vec2 vL;\nvarying vec2 vR;\nvarying vec2 vT;\nvarying vec2 vB;\nuniform sampler2D uVelocity;\n\nvec2 sampleVelocity(in vec2 uv) {\n\tvec2 clampedUV = clamp(uv, 0.0, 1.0);\n\tvec2 multiplier = vec2(1.0, 1.0);\n\tmultiplier.x = uv.x < 0.0 || uv.x > 1.0 ? -1.0 : 1.0;\n\tmultiplier.y = uv.y < 0.0 || uv.y > 1.0 ? -1.0 : 1.0;\n\treturn multiplier * texture2D(uVelocity, clampedUV).xy;\n}\n\nvoid main () {\n\tfloat L = sampleVelocity(vL).x;\n\tfloat R = sampleVelocity(vR).x;\n\tfloat T = sampleVelocity(vT).y;\n\tfloat B = sampleVelocity(vB).y;\n\tfloat div = 0.5 * (R - L + T - B);\n\tgl_FragColor = vec4(div, 0.0, 0.0, 1.0);\n}","import * as THREE from \"three\";\nimport { useMemo } from \"react\";\nimport vertexShader from \"../shaders/main.vert\";\nimport fragmentShader from \"../shaders/divergence.frag\";\nimport { MaterialProps } from \"../../../types\";\nimport { MATERIAL_BASIC_PARAMS } from \"../../../../libs/constants\";\nimport { createMaterialParameters } from \"../../../../utils/createMaterialParameters\";\n\nexport class DivergenceMaterial extends THREE.ShaderMaterial {\n uniforms!: {\n uVelocity: { value: THREE.Texture };\n texelSize: { value: THREE.Vector2 };\n };\n}\n\nexport const useDivergenceMaterial = ({ onBeforeInit }: MaterialProps) => {\n const divergenceMaterial = useMemo(() => {\n const mat = new THREE.ShaderMaterial({\n ...createMaterialParameters(\n {\n uniforms: {\n uVelocity: { value: null },\n texelSize: { value: new THREE.Vector2() },\n },\n vertexShader: vertexShader,\n fragmentShader: fragmentShader,\n },\n onBeforeInit\n ),\n ...MATERIAL_BASIC_PARAMS,\n });\n return mat;\n }, [onBeforeInit]);\n\n return divergenceMaterial as DivergenceMaterial;\n};\n","precision highp float;\n\nvarying vec2 vUv;\nvarying vec2 vL;\nvarying vec2 vR;\nvarying vec2 vT;\nvarying vec2 vB;\nuniform sampler2D uPressure;\nuniform sampler2D uDivergence;\n\nvoid main () {\n\tfloat L = texture2D(uPressure, clamp(vL,0.,1.)).x;\n\tfloat R = texture2D(uPressure, clamp(vR,0.,1.)).x;\n\tfloat T = texture2D(uPressure, clamp(vT,0.,1.)).x;\n\tfloat B = texture2D(uPressure, clamp(vB,0.,1.)).x;\n\tfloat C = texture2D(uPressure, vUv).x;\n\tfloat divergence = texture2D(uDivergence, vUv).x;\n\tfloat pressure = (L + R + B + T - divergence) * 0.25;\n\tgl_FragColor = vec4(pressure, 0.0, 0.0, 1.0);\n}","import * as THREE from \"three\";\nimport { useMemo } from \"react\";\nimport vertexShader from \"../shaders/main.vert\";\nimport fragmentShader from \"../shaders/pressure.frag\";\nimport { MaterialProps } from \"../../../types\";\nimport { MATERIAL_BASIC_PARAMS } from \"../../../../libs/constants\";\nimport { createMaterialParameters } from \"../../../../utils/createMaterialParameters\";\n\nexport class PressureMaterial extends THREE.ShaderMaterial {\n uniforms!: {\n uPressure: { value: THREE.Texture };\n uDivergence: { value: THREE.Texture };\n texelSize: { value: THREE.Vector2 };\n };\n}\n\nexport const usePressureMaterial = ({ onBeforeInit }: MaterialProps) => {\n const pressureMaterial = useMemo(() => {\n const mat = new THREE.ShaderMaterial({\n ...createMaterialParameters(\n {\n uniforms: {\n uPressure: { value: null },\n uDivergence: { value: null },\n texelSize: { value: new THREE.Vector2() },\n },\n vertexShader: vertexShader,\n fragmentShader: fragmentShader,\n },\n onBeforeInit\n ),\n ...MATERIAL_BASIC_PARAMS,\n });\n\n return mat;\n }, [onBeforeInit]);\n\n return pressureMaterial as PressureMaterial;\n};\n","precision highp float;\n\nvarying vec2 vUv;\nvarying vec2 vL;\nvarying vec2 vR;\nvarying vec2 vT;\nvarying vec2 vB;\nuniform sampler2D uVelocity;\n\nvoid main () {\n\tfloat L = texture2D(uVelocity, vL).y;\n\tfloat R = texture2D(uVelocity, vR).y;\n\tfloat T = texture2D(uVelocity, vT).x;\n\tfloat B = texture2D(uVelocity, vB).x;\n\tfloat vorticity = R - L - T + B;\n\tgl_FragColor = vec4(vorticity, 0.0, 0.0, 1.0);\n}","import * as THREE from \"three\";\nimport { useMemo } from \"react\";\nimport vertexShader from \"../shaders/main.vert\";\nimport fragmentShader from \"../shaders/curl.frag\";\nimport { MaterialProps } from \"../../../types\";\nimport { MATERIAL_BASIC_PARAMS } from \"../../../../libs/constants\";\nimport { createMaterialParameters } from \"../../../../utils/createMaterialParameters\";\n\nexport class CurlMaterial extends THREE.ShaderMaterial {\n uniforms!: {\n uVelocity: { value: THREE.Texture };\n texelSize: { value: THREE.Vector2 };\n };\n}\n\nexport const useCurlMaterial = ({ onBeforeInit }: MaterialProps) => {\n const curlMaterial = useMemo(() => {\n const mat = new THREE.ShaderMaterial({\n ...createMaterialParameters(\n {\n uniforms: {\n uVelocity: { value: null },\n texelSize: { value: new THREE.Vector2() },\n },\n vertexShader: vertexShader,\n fragmentShader: fragmentShader,\n },\n onBeforeInit\n ),\n ...MATERIAL_BASIC_PARAMS,\n });\n\n return mat;\n }, [onBeforeInit]);\n\n return curlMaterial as CurlMaterial;\n};\n","precision highp float;\n\nvarying vec2 vUv;\nvarying vec2 vT;\nvarying vec2 vB;\nuniform sampler2D uVelocity;\nuniform sampler2D uCurl;\nuniform float curl;\nuniform float dt;\n\nvoid main () {\n\tfloat T = texture2D(uCurl, vT).x;\n\tfloat B = texture2D(uCurl, vB).x;\n\tfloat C = texture2D(uCurl, vUv).x;\n\tvec2 force = vec2(abs(T) - abs(B), 0.0);\n\tforce *= 1.0 / length(force + 0.00001) * curl * C;\n\tvec2 vel = texture2D(uVelocity, vUv).xy;\n\tgl_FragColor = vec4(vel + force * dt, 0.0, 1.0);\n}","import * as THREE from \"three\";\nimport { useMemo } from \"react\";\nimport vertexShader from \"../shaders/main.vert\";\nimport fragmentShader from \"../shaders/vorticity.frag\";\nimport { MaterialProps } from \"../../../types\";\nimport { MATERIAL_BASIC_PARAMS } from \"../../../../libs/constants\";\nimport { DELTA_TIME } from \"..\";\nimport { createMaterialParameters } from \"../../../../utils/createMaterialParameters\";\n\nexport class VorticityMaterial extends THREE.ShaderMaterial {\n uniforms!: {\n uVelocity: { value: THREE.Texture };\n uCurl: { value: THREE.Texture };\n curl: { value: number };\n dt: { value: number };\n texelSize: { value: THREE.Vector2 };\n };\n}\n\nexport const useVorticityMaterial = ({ onBeforeInit }: MaterialProps) => {\n const vorticityMaterial = useMemo(() => {\n const mat = new THREE.ShaderMaterial({\n ...createMaterialParameters(\n {\n uniforms: {\n uVelocity: { value: null },\n uCurl: { value: null },\n curl: { value: 0 },\n dt: { value: DELTA_TIME },\n texelSize: { value: new THREE.Vector2() },\n },\n vertexShader: vertexShader,\n fragmentShader: fragmentShader,\n },\n onBeforeInit\n ),\n ...MATERIAL_BASIC_PARAMS,\n });\n return mat;\n }, [onBeforeInit]);\n\n return vorticityMaterial as VorticityMaterial;\n};\n","precision highp float;\n\nvarying vec2 vUv;\nuniform sampler2D uTexture;\nuniform float value;\n\nvoid main () {\n\tgl_FragColor = value * texture2D(uTexture, vUv);\n}","import * as THREE from \"three\";\nimport { useMemo } from \"react\";\nimport vertexShader from \"../shaders/main.vert\";\nimport fragmentShader from \"../shaders/clear.frag\";\nimport { MaterialProps } from \"../../../types\";\nimport {\n MATERIAL_BASIC_PARAMS,\n DEFAULT_TEXTURE,\n} from \"../../../../libs/constants\";\nimport { createMaterialParameters } from \"../../../../utils/createMaterialParameters\";\n\nexport class ClearMaterial extends THREE.ShaderMaterial {\n uniforms!: {\n uTexture: { value: THREE.Texture };\n value: { value: number };\n texelSize: { value: THREE.Vector2 };\n };\n}\n\nexport const useClearMaterial = ({ onBeforeInit }: MaterialProps) => {\n const advectionMaterial = useMemo(() => {\n const mat = new THREE.ShaderMaterial({\n ...createMaterialParameters(\n {\n uniforms: {\n uTexture: { value: DEFAULT_TEXTURE },\n value: { value: 0.0 },\n texelSize: { value: new THREE.Vector2() },\n },\n vertexShader: vertexShader,\n fragmentShader: fragmentShader,\n },\n onBeforeInit\n ),\n ...MATERIAL_BASIC_PARAMS,\n });\n\n return mat;\n }, [onBeforeInit]);\n\n return advectionMaterial as ClearMaterial;\n};\n","precision highp float;\n\nvarying vec2 vUv;\nvarying vec2 vL;\nvarying vec2 vR;\nvarying vec2 vT;\nvarying vec2 vB;\nuniform sampler2D uPressure;\nuniform sampler2D uVelocity;\n\nvoid main () {\n\tfloat L = texture2D(uPressure, clamp(vL,0.,1.)).x;\n\tfloat R = texture2D(uPressure, clamp(vR,0.,1.)).x;\n\tfloat T = texture2D(uPressure, clamp(vT,0.,1.)).x;\n\tfloat B = texture2D(uPressure, clamp(vB,0.,1.)).x;\n\tvec2 velocity = texture2D(uVelocity, vUv).xy;\n\tvelocity.xy -= vec2(R - L, T - B);\n\tgl_FragColor = vec4(velocity, 0.0, 1.0);\n}","import * as THREE from \"three\";\nimport { useMemo } from \"react\";\nimport vertexShader from \"../shaders/main.vert\";\nimport fragmentShader from \"../shaders/gradientSubtract.frag\";\nimport { MaterialProps } from \"../../../types\";\nimport {\n MATERIAL_BASIC_PARAMS,\n DEFAULT_TEXTURE,\n} from \"../../../../libs/constants\";\nimport { createMaterialParameters } from \"../../../../utils/createMaterialParameters\";\n\nexport class GradientSubtractMaterial extends THREE.ShaderMaterial {\n uniforms!: {\n uPressure: { value: THREE.Texture };\n uVelocity: { value: THREE.Texture };\n texelSize: { value: THREE.Vector2 };\n };\n}\n\nexport const useGradientSubtractMaterial = ({\n onBeforeInit,\n}: MaterialProps) => {\n const gradientSubtractMaterial = useMemo(() => {\n const mat = new THREE.ShaderMaterial({\n ...createMaterialParameters(\n {\n uniforms: {\n uPressure: { value: DEFAULT_TEXTURE },\n uVelocity: { value: DEFAULT_TEXTURE },\n texelSize: { value: new THREE.Vector2() },\n },\n vertexShader: vertexShader,\n fragmentShader: fragmentShader,\n },\n onBeforeInit\n ),\n ...MATERIAL_BASIC_PARAMS,\n });\n\n return mat;\n }, [onBeforeInit]);\n\n return gradientSubtractMaterial as GradientSubtractMaterial;\n};\n","precision highp float;\n\nvarying vec2 vUv;\nuniform sampler2D uTarget;\nuniform float aspectRatio;\nuniform vec3 color;\nuniform vec2 point;\nuniform float radius;\n\nvoid main () {\n\tvec2 nPoint = (point + vec2(1.0)) * 0.5;\n\tvec2 p = vUv - nPoint.xy;\n\tp.x *= aspectRatio;\n\tvec3 splat = exp(-dot(p, p) / radius) * color;\n\tvec3 base = texture2D(uTarget, vUv).xyz;\n\tgl_FragColor = vec4(base + splat, 1.0);\n}","import * as THREE from \"three\";\nimport { useMemo } from \"react\";\nimport vertexShader from \"../shaders/main.vert\";\nimport fragmentShader from \"../shaders/splat.frag\";\nimport { MaterialProps } from \"../../../types\";\nimport {\n MATERIAL_BASIC_PARAMS,\n DEFAULT_TEXTURE,\n} from \"../../../../libs/constants\";\nimport { createMaterialParameters } from \"../../../../utils/createMaterialParameters\";\n\nexport class SplatMaterial extends THREE.ShaderMaterial {\n uniforms!: {\n uTarget: { value: THREE.Texture };\n aspectRatio: { value: number };\n color: { value: THREE.Vector3 | THREE.Color };\n point: { value: THREE.Vector2 };\n radius: { value: number };\n texelSize: { value: THREE.Vector2 };\n };\n}\n\nexport const useSplatMaterial = ({ onBeforeInit }: MaterialProps) => {\n const splatMaterial = useMemo(() => {\n const mat = new THREE.ShaderMaterial({\n ...createMaterialParameters(\n {\n uniforms: {\n uTarget: { value: DEFAULT_TEXTURE },\n aspectRatio: { value: 0 },\n color: { value: new THREE.Vector3() },\n point: { value: new THREE.Vector2() },\n radius: { value: 0.0 },\n texelSize: { value: new THREE.Vector2() },\n },\n vertexShader: vertexShader,\n fragmentShader: fragmentShader,\n },\n onBeforeInit\n ),\n ...MATERIAL_BASIC_PARAMS,\n });\n\n return mat;\n }, [onBeforeInit]);\n\n return splatMaterial as SplatMaterial;\n};\n","import * as THREE from \"three\";\nimport { useCallback, useEffect, useMemo } from \"react\";\nimport { useInitialMaterial } from \"./materials/useInitialMaterial\";\nimport {\n AdvectionMaterial,\n useAdvectionMaterial,\n} from \"./materials/useAdvectionMaterial\";\nimport {\n DivergenceMaterial,\n useDivergenceMaterial,\n} from \"./materials/useDivergenceMaterial\";\nimport {\n PressureMaterial,\n usePressureMaterial,\n} from \"./materials/usePressureMaterial\";\nimport { CurlMaterial, useCurlMaterial } from \"./materials/useCurlMaterial\";\nimport {\n VorticityMaterial,\n useVorticityMaterial,\n} from \"./materials/useVorticityMaterial\";\nimport { useResolution } from \"../../../utils/useResolution\";\nimport { ClearMaterial, useClearMaterial } from \"./materials/useClearMaterial\";\nimport {\n GradientSubtractMaterial,\n useGradientSubtractMaterial,\n} from \"./materials/useGradientSubtractMaterial\";\nimport { SplatMaterial, useSplatMaterial } from \"./materials/useSplatMaterial\";\nimport { CustomParams, setUniform } from \"../../../utils/setUniforms\";\nimport { useAddObject } from \"../../../utils/useAddObject\";\nimport { MaterialProps, Size } from \"../../types\";\n\ntype TMaterials =\n | AdvectionMaterial\n | DivergenceMaterial\n | CurlMaterial\n | PressureMaterial\n | ClearMaterial\n | GradientSubtractMaterial\n | SplatMaterial;\n\nexport type FluidMaterials = {\n vorticityMaterial: VorticityMaterial;\n curlMaterial: CurlMaterial;\n advectionMaterial: AdvectionMaterial;\n divergenceMaterial: DivergenceMaterial;\n pressureMaterial: PressureMaterial;\n clearMaterial: ClearMaterial;\n gradientSubtractMaterial: GradientSubtractMaterial;\n splatMaterial: SplatMaterial;\n};\n\nexport type CustomizableKeys =\n | \"advection\"\n | \"splat\"\n | \"curl\"\n | \"vorticity\"\n | \"divergence\"\n | \"clear\"\n | \"pressure\"\n | \"gradientSubtract\";\n\nexport type CustomFluidProps = {\n [K in CustomizableKeys]?: MaterialProps;\n};\nexport type CustomFluidParams = {\n [K in CustomizableKeys]?: CustomParams;\n};\n\nconst useCustomMaterial = (\n materialHook: (materialProps: MaterialProps) => T,\n materialProps?: MaterialProps\n) => {\n return materialHook(materialProps ?? {});\n};\n\n/**\n * Returns the material update function in the second argument\n */\nexport const useMesh = ({\n scene,\n size,\n dpr,\n customFluidProps,\n}: {\n scene: THREE.Scene;\n size: Size;\n dpr: number | false;\n customFluidProps?: CustomFluidProps;\n}) => {\n const geometry = useMemo(() => new THREE.PlaneGeometry(2, 2), []);\n\n const {\n curl,\n vorticity,\n advection,\n divergence,\n pressure,\n clear,\n gradientSubtract,\n splat,\n } = customFluidProps ?? {};\n\n const initialMaterial = useCustomMaterial(useInitialMaterial);\n const updateMaterial = initialMaterial.clone();\n const curlMaterial = useCustomMaterial(useCurlMaterial, curl);\n const vorticityMaterial = useCustomMaterial(useVorticityMaterial, vorticity);\n const advectionMaterial = useCustomMaterial(useAdvectionMaterial, advection);\n const divergenceMaterial = useCustomMaterial(\n useDivergenceMaterial,\n divergence\n );\n const pressureMaterial = useCustomMaterial(usePressureMaterial, pressure);\n const clearMaterial = useCustomMaterial(useClearMaterial, clear);\n const gradientSubtractMaterial = useCustomMaterial(\n useGradientSubtractMaterial,\n gradientSubtract\n );\n const splatMaterial = useCustomMaterial(useSplatMaterial, splat);\n const materials = useMemo(\n () => ({\n vorticityMaterial,\n curlMaterial,\n advectionMaterial,\n divergenceMaterial,\n pressureMaterial,\n clearMaterial,\n gradientSubtractMaterial,\n splatMaterial,\n }),\n [\n vorticityMaterial,\n curlMaterial,\n advectionMaterial,\n divergenceMaterial,\n pressureMaterial,\n clearMaterial,\n gradientSubtractMaterial,\n splatMaterial,\n ]\n );\n\n const resolution = useResolution(size, dpr);\n useMemo(() => {\n setUniform(materials.splatMaterial)(\n \"aspectRatio\",\n resolution.x / resolution.y\n );\n for (const material of Object.values(materials)) {\n setUniform(material)(\n \"texelSize\",\n new THREE.Vector2(1.0 / resolution.x, 1.0 / resolution.y)\n );\n }\n }, [resolution, materials]);\n\n const mesh = useAddObject(scene, geometry, initialMaterial, THREE.Mesh);\n\n useMemo(() => {\n initialMaterial.dispose();\n mesh.material = updateMaterial;\n }, [initialMaterial, mesh, updateMaterial]);\n\n useEffect(() => {\n return () => {\n for (const material of Object.values(materials)) {\n material.dispose();\n }\n };\n }, [materials]);\n\n const setMeshMaterial = useCallback(\n (material: TMaterials) => {\n mesh.material = material;\n mesh.material.needsUpdate = true;\n },\n [mesh]\n );\n\n return { materials, setMeshMaterial, mesh };\n};\n","import * as THREE from \"three\";\nimport {\n CustomizableKeys,\n FluidMaterials,\n CustomFluidProps,\n CustomFluidParams,\n useMesh,\n} from \"./useMesh\";\nimport { useCamera } from \"../../../utils/useCamera\";\nimport { useCallback, useMemo, useRef } from \"react\";\nimport { PointerValues, usePointer } from \"../../../misc/usePointer\";\nimport { RootState } from \"@react-three/fiber\";\nimport { useSingleFBO } from \"../../../utils/useSingleFBO\";\nimport {\n CustomParams,\n setCustomUniform,\n setUniform,\n} from \"../../../utils/setUniforms\";\nimport { HooksProps, HooksReturn } from \"../../types\";\nimport { useParams } from \"../../../utils/useParams\";\nimport { UseFboProps } from \"../../../utils/useSingleFBO\";\nimport { DoubleRenderTarget, useDoubleFBO } from \"../../../utils/useDoubleFBO\";\nimport { getDpr } from \"../../../utils/getDpr\";\n\nexport const DELTA_TIME = 0.016;\n\nexport type FluidParams = {\n /** density disspation , default : `0.98` */\n densityDissipation?: number;\n /** velocity dissipation , default : `0.99` */\n velocityDissipation?: number;\n /** velocity acceleration , default : `10.0` */\n velocityAcceleration?: number;\n /** pressure dissipation , default : `0.9` */\n pressureDissipation?: number;\n /** pressure iterations. affects performance , default : `20` */\n pressureIterations?: number;\n /** curl_strength , default : `35` */\n curlStrength?: number;\n /** splat radius , default : `0.002` */\n splatRadius?: number;\n /** Fluid Color.THREE.Vector3 Alternatively, it accepts a function that returns THREE.Vector3.The function takes velocity:THREE.Vector2 as an argument. , default : `THREE.Vector3(1.0, 1.0, 1.0)` */\n fluidColor?:\n | ((velocity: THREE.Vector2) => THREE.Vector3)\n | THREE.Vector3\n | THREE.Color;\n /** When calling usePointer in a frame loop, setting PointerValues ​​to this value prevents double calls , default : `false` */\n pointerValues?: PointerValues | false;\n};\n\nexport type FluidObject = {\n scene: THREE.Scene;\n mesh: THREE.Mesh;\n materials: FluidMaterials;\n camera: THREE.Camera;\n renderTarget: {\n velocity: DoubleRenderTarget;\n density: DoubleRenderTarget;\n curl: THREE.WebGLRenderTarget;\n divergence: THREE.WebGLRenderTarget;\n pressure: DoubleRenderTarget;\n };\n output: THREE.Texture;\n};\n\nexport const FLUID_PARAMS: FluidParams = Object.freeze({\n densityDissipation: 0.98,\n velocityDissipation: 0.99,\n velocityAcceleration: 10.0,\n pressureDissipation: 0.9,\n pressureIterations: 20,\n curlStrength: 35,\n splatRadius: 0.002,\n fluidColor: new THREE.Vector3(1.0, 1.0, 1.0),\n pointerValues: false,\n});\n\n/**\n * @link https://github.com/FunTechInc/use-shader-fx?tab=readme-ov-file#usage\n */\nexport const useFluid = ({\n size,\n dpr,\n renderTargetOptions,\n isSizeUpdate,\n customFluidProps,\n}: {\n /** you can add `onBeforeInit` of the next material.`initial`,`curl`,`vorticity`,`advection`,`divergence`,`pressure`,`clear`,`gradientSubtract`,`splat` \n\t * ```ts\n\t * customFluidProps: {\n vorticity: {\n onBeforeInit: (parameters) => console.log(parameters),\n },\n },\n\t * ```\n\t*/\n customFluidProps?: CustomFluidProps;\n} & HooksProps): HooksReturn => {\n const _dpr = getDpr(dpr);\n\n const scene = useMemo(() => new THREE.Scene(), []);\n const { materials, setMeshMaterial, mesh } = useMesh({\n scene,\n size,\n dpr: _dpr.shader,\n customFluidProps,\n });\n const camera = useCamera(size);\n const updatePointer = usePointer();\n\n const fboProps = useMemo(\n () => ({\n scene,\n camera,\n dpr: _dpr.fbo,\n size,\n isSizeUpdate,\n type: THREE.HalfFloatType,\n ...renderTargetOptions,\n }),\n [scene, camera, size, _dpr.fbo, isSizeUpdate, renderTargetOptions]\n );\n const [velocityFBO, updateVelocityFBO] = useDoubleFBO(fboProps);\n const [densityFBO, updateDensityFBO] = useDoubleFBO(fboProps);\n const [curlFBO, updateCurlFBO] = useSingleFBO(fboProps);\n const [divergenceFBO, updateDivergenceFBO] = useSingleFBO(fboProps);\n const [pressureFBO, updatePressureFBO] = useDoubleFBO(fboProps);\n\n const scaledDiffVec = useRef(new THREE.Vector2(0, 0));\n const spaltVec = useRef(new THREE.Vector3(0, 0, 0));\n\n const [params, setParams] = useParams(FLUID_PARAMS);\n\n // setUniform\n const updateParamsList = useMemo(\n () => ({\n advection: setUniform(materials.advectionMaterial),\n splat: setUniform(materials.splatMaterial),\n curl: setUniform(materials.curlMaterial),\n vorticity: setUniform(materials.vorticityMaterial),\n divergence: setUniform(materials.divergenceMaterial),\n clear: setUniform(materials.clearMaterial),\n pressure: setUniform(materials.pressureMaterial),\n gradientSubtract: setUniform(materials.gradientSubtractMaterial),\n }),\n [materials]\n );\n // customSetUniform\n const updateCustomParamsList = useMemo<{\n [K in CustomizableKeys]: (customParams: CustomParams | undefined) => void;\n }>(\n () => ({\n advection: setCustomUniform(materials.advectionMaterial),\n splat: setCustomUniform(materials.splatMaterial),\n curl: setCustomUniform(materials.curlMaterial),\n vorticity: setCustomUniform(materials.vorticityMaterial),\n divergence: setCustomUniform(materials.divergenceMaterial),\n clear: setCustomUniform(materials.clearMaterial),\n pressure: setCustomUniform(materials.pressureMaterial),\n gradientSubtract: setCustomUniform(materials.gradientSubtractMaterial),\n }),\n [materials]\n );\n\n const updateParams = useCallback(\n (newParams?: FluidParams, customParams?: CustomFluidParams) => {\n setParams(newParams);\n if (customParams) {\n Object.keys(customParams).forEach((key) => {\n updateCustomParamsList[key as CustomizableKeys](\n customParams[key as CustomizableKeys]\n );\n });\n }\n },\n [setParams, updateCustomParamsList]\n );\n\n const updateFx = useCallback(\n (\n rootState: RootState,\n newParams?: FluidParams,\n customParams?: CustomFluidParams\n ) => {\n const { gl, pointer, size } = rootState;\n\n updateParams(newParams, customParams);\n\n const velocityTex = updateVelocityFBO(gl, ({ read }) => {\n setMeshMaterial(materials.advectionMaterial);\n updateParamsList.advection(\"uVelocity\", read);\n updateParamsList.advection(\"uSource\", read);\n updateParamsList.advection(\n \"dissipation\",\n params.velocityDissipation!\n );\n });\n\n const densityTex = updateDensityFBO(gl, ({ read }) => {\n setMeshMaterial(materials.advectionMaterial);\n updateParamsList.advection(\"uVelocity\", velocityTex);\n updateParamsList.advection(\"uSource\", read);\n updateParamsList.advection(\n \"dissipation\",\n params.densityDissipation!\n );\n });\n\n const pointerValues = params.pointerValues! || updatePointer(pointer);\n\n if (pointerValues.isVelocityUpdate) {\n updateVelocityFBO(gl, ({ read }) => {\n setMeshMaterial(materials.splatMaterial);\n updateParamsList.splat(\"uTarget\", read);\n updateParamsList.splat(\"point\", pointerValues.currentPointer);\n const scaledDiff = pointerValues.diffPointer.multiply(\n scaledDiffVec.current\n .set(size.width, size.height)\n .multiplyScalar(params.velocityAcceleration!)\n );\n updateParamsList.splat(\n \"color\",\n spaltVec.current.set(scaledDiff.x, scaledDiff.y, 1.0)\n );\n updateParamsList.splat(\"radius\", params.splatRadius!);\n });\n updateDensityFBO(gl, ({ read }) => {\n setMeshMaterial(materials.splatMaterial);\n updateParamsList.splat(\"uTarget\", read);\n const color: THREE.Vector3 | THREE.Color =\n typeof params.fluidColor === \"function\"\n ? params.fluidColor(pointerValues.velocity)\n : params.fluidColor!;\n updateParamsList.splat(\"color\", color);\n });\n }\n\n const curlTex = updateCurlFBO(gl, () => {\n setMeshMaterial(materials.curlMaterial);\n updateParamsList.curl(\"uVelocity\", velocityTex);\n });\n\n updateVelocityFBO(gl, ({ read }) => {\n setMeshMaterial(materials.vorticityMaterial);\n updateParamsList.vorticity(\"uVelocity\", read);\n updateParamsList.vorticity(\"uCurl\", curlTex);\n updateParamsList.vorticity(\"curl\", params.curlStrength!);\n });\n\n const divergenceTex = updateDivergenceFBO(gl, () => {\n setMeshMaterial(materials.divergenceMaterial);\n updateParamsList.divergence(\"uVelocity\", velocityTex);\n });\n\n updatePressureFBO(gl, ({ read }) => {\n setMeshMaterial(materials.clearMaterial);\n updateParamsList.clear(\"uTexture\", read);\n updateParamsList.clear(\"value\", params.pressureDissipation!);\n });\n\n setMeshMaterial(materials.pressureMaterial);\n updateParamsList.pressure(\"uDivergence\", divergenceTex);\n let pressureTexTemp: THREE.Texture;\n for (let i = 0; i < params.pressureIterations!; i++) {\n pressureTexTemp = updatePressureFBO(gl, ({ read }) => {\n updateParamsList.pressure(\"uPressure\", read);\n });\n }\n\n updateVelocityFBO(gl, ({ read }) => {\n setMeshMaterial(materials.gradientSubtractMaterial);\n updateParamsList.gradientSubtract(\"uPressure\", pressureTexTemp);\n updateParamsList.gradientSubtract(\"uVelocity\", read);\n });\n\n return densityTex;\n },\n [\n materials,\n updateParamsList,\n setMeshMaterial,\n updateCurlFBO,\n updateDensityFBO,\n updateDivergenceFBO,\n updatePointer,\n updatePressureFBO,\n updateVelocityFBO,\n params,\n updateParams,\n ]\n );\n return [\n updateFx,\n updateParams,\n {\n scene: scene,\n mesh: mesh,\n materials: materials,\n camera: camera,\n renderTarget: {\n velocity: velocityFBO,\n density: densityFBO,\n curl: curlFBO,\n divergence: divergenceFBO,\n pressure: pressureFBO,\n },\n output: densityFBO.read.texture,\n },\n ];\n};\n","#usf ","precision highp float;\n\nuniform sampler2D uMap;\nuniform float uOpacity;\n\nvarying vec2 vUv;\n\nvoid main() {\n\tvec2 uv = vUv;\n\tvec3 color = texture2D(uMap, uv).rgb;\n\tgl_FragColor = vec4(color,uOpacity);\n}","import * as THREE from \"three\";\nimport { useEffect, useMemo } from \"react\";\nimport vertexShader from \"./shader/main.vert\";\nimport fragmentShader from \"./shader/main.frag\";\nimport { MaterialProps } from \"../../types\";\nimport {\n DEFAULT_TEXTURE,\n MATERIAL_BASIC_PARAMS,\n} from \"../../../libs/constants\";\nimport { createMaterialParameters } from \"../../../utils/createMaterialParameters\";\n\ntype UseMeshProps = {\n scale: number;\n max: number;\n scene: THREE.Scene;\n texture?: THREE.Texture;\n};\n\nexport const useMesh = ({\n scale,\n max,\n texture,\n scene,\n onBeforeInit,\n}: UseMeshProps & MaterialProps) => {\n const geometry = useMemo(\n () => new THREE.PlaneGeometry(scale, scale),\n [scale]\n );\n\n const material = useMemo(() => {\n const mat = new THREE.ShaderMaterial({\n ...createMaterialParameters(\n {\n uniforms: {\n uOpacity: { value: 0.0 },\n uMap: { value: texture || DEFAULT_TEXTURE },\n },\n vertexShader: vertexShader,\n fragmentShader: fragmentShader,\n },\n onBeforeInit\n ),\n blending: THREE.AdditiveBlending,\n ...MATERIAL_BASIC_PARAMS,\n // Must be transparent.\n transparent: true,\n });\n return mat;\n }, [texture, onBeforeInit]);\n\n const meshArr = useMemo(() => {\n const temp = [];\n for (let i = 0; i < max; i++) {\n const clonedMat = material.clone();\n const mesh = new THREE.Mesh(geometry.clone(), clonedMat);\n mesh.rotateZ(2 * Math.PI * Math.random());\n mesh.visible = false;\n scene.add(mesh);\n temp.push(mesh);\n }\n return temp;\n }, [geometry, material, scene, max]);\n\n useEffect(() => {\n return () => {\n meshArr.forEach((mesh) => {\n mesh.geometry.dispose();\n if (Array.isArray(mesh.material)) {\n mesh.material.forEach((material) => material.dispose());\n } else {\n mesh.material.dispose();\n }\n scene.remove(mesh);\n });\n };\n }, [scene, meshArr]);\n\n return meshArr;\n};\n","import { useCallback, useMemo, useRef } from \"react\";\nimport * as THREE from \"three\";\nimport { useMesh } from \"./useMesh\";\nimport { useCamera } from \"../../../utils/useCamera\";\nimport { RootState } from \"@react-three/fiber\";\nimport { useSingleFBO } from \"../../../utils/useSingleFBO\";\nimport { usePointer, PointerValues } from \"../../../misc/usePointer\";\nimport { HooksProps, HooksReturn } from \"../../types\";\nimport { useParams } from \"../../../utils/useParams\";\nimport { getDpr } from \"../../../utils/getDpr\";\nimport {\n CustomParams,\n setCustomUniform,\n setUniform,\n} from \"../../../utils/setUniforms\";\n\nexport type RippleParams = {\n /** How often ripples appear, default : `0.01` */\n frequency?: number;\n /** rotation rate, default : `0.05` */\n rotation?: number;\n /** fadeout speed, default : `0.9` */\n fadeoutSpeed?: number;\n /** scale rate, default : `0.3` */\n scale?: number;\n /** alpha, default : `0.6` */\n alpha?: number;\n /** When calling usePointer in a frame loop, setting PointerValues ​​to this value prevents double calls , default : `false` */\n pointerValues?: PointerValues | false;\n};\n\nexport type RippleObject = {\n scene: THREE.Scene;\n meshArr: THREE.Mesh[];\n camera: THREE.Camera;\n renderTarget: THREE.WebGLRenderTarget;\n output: THREE.Texture;\n};\n\nexport const RIPPLE_PARAMS: RippleParams = Object.freeze({\n frequency: 0.01,\n rotation: 0.05,\n fadeoutSpeed: 0.9,\n scale: 0.3,\n alpha: 0.6,\n pointerValues: false,\n});\n\ninterface UseRippleProps extends HooksProps {\n /** texture applied to ripple */\n texture?: THREE.Texture;\n /** ripple size, default:64 */\n scale?: number;\n /** ripple max length, default:100 */\n max?: number;\n}\n\n/**\n * @link https://github.com/FunTechInc/use-shader-fx?tab=readme-ov-file#usage\n */\nexport const useRipple = ({\n texture,\n scale = 64,\n max = 100,\n size,\n dpr,\n renderTargetOptions,\n isSizeUpdate,\n onBeforeInit,\n}: UseRippleProps): HooksReturn => {\n const _dpr = getDpr(dpr);\n const scene = useMemo(() => new THREE.Scene(), []);\n const meshArr = useMesh({\n scale: scale,\n max: max,\n texture,\n scene,\n onBeforeInit,\n });\n const camera = useCamera(size);\n const updatePointer = usePointer();\n const [renderTarget, updateRenderTarget] = useSingleFBO({\n scene,\n camera,\n size,\n dpr: _dpr.fbo,\n isSizeUpdate,\n ...renderTargetOptions,\n });\n\n const [params, setParams] = useParams(RIPPLE_PARAMS);\n\n const currentWave = useRef(0);\n\n const updateParams = useMemo(() => {\n return (newParams?: RippleParams, customParams?: CustomParams) => {\n setParams(newParams);\n meshArr.forEach((mesh) => {\n if (mesh.visible) {\n const material = mesh.material as THREE.ShaderMaterial;\n mesh.rotation.z += params.rotation!;\n mesh.scale.x =\n params.fadeoutSpeed! * mesh.scale.x + params.scale!;\n mesh.scale.y = mesh.scale.x;\n const opacity = material.uniforms.uOpacity.value;\n setUniform(material)(\"uOpacity\", opacity * params.fadeoutSpeed!);\n if (opacity < 0.001) mesh.visible = false;\n }\n setCustomUniform(mesh.material)(customParams);\n });\n };\n }, [meshArr, params, setParams]);\n\n const updateFx = useCallback(\n (\n rootState: RootState,\n newParams?: RippleParams,\n customParams?: CustomParams\n ) => {\n const { gl, pointer, size } = rootState;\n\n updateParams(newParams, customParams);\n\n const pointerValues = params.pointerValues! || updatePointer(pointer);\n\n if (params.frequency! < pointerValues.diffPointer.length()) {\n const mesh = meshArr[currentWave.current];\n const material = mesh.material as THREE.ShaderMaterial;\n mesh.visible = true;\n mesh.position.set(\n pointerValues.currentPointer.x * (size.width / 2),\n pointerValues.currentPointer.y * (size.height / 2),\n 0\n );\n mesh.scale.x = mesh.scale.y = 0.0;\n setUniform(material)(\"uOpacity\", params.alpha!);\n currentWave.current = (currentWave.current + 1) % max;\n }\n\n return updateRenderTarget(gl);\n },\n [updateRenderTarget, meshArr, updatePointer, max, params, updateParams]\n );\n return [\n updateFx,\n updateParams,\n {\n scene: scene,\n camera: camera,\n meshArr: meshArr,\n renderTarget: renderTarget,\n output: renderTarget.texture,\n },\n ];\n};\n","#usf ","precision highp float;\nprecision highp int;\n\nvarying vec2 vUv;\nuniform float uTime;\nuniform float timeStrength;\nuniform int noiseOctaves;\nuniform int fbmOctaves;\nuniform int warpOctaves;\nuniform vec2 warpDirection;\nuniform float warpStrength;\nuniform float scale;\n\nconst float per = 0.5;\nconst float PI = 3.14159265359;\n\nfloat rnd(vec2 n) {\n\tfloat a = 0.129898;\n\tfloat b = 0.78233;\n\tfloat c = 437.585453;\n\tfloat dt= dot(n ,vec2(a, b));\n\tfloat sn= mod(dt, PI);\n\treturn fract(sin(sn) * c);\n}\n\nfloat interpolate(float a, float b, float x){\n float f = (1.0 - cos(x * PI)) * 0.5;\n return a * (1.0 - f) + b * f;\n}\n\nfloat irnd(vec2 p){\n\tvec2 i = floor(p);\n\tvec2 f = fract(p);\n\tvec4 v = vec4(rnd(vec2(i.x,i.y)),rnd(vec2(i.x + 1.0,i.y)),rnd(vec2(i.x,i.y + 1.0)),rnd(vec2(i.x + 1.0, i.y + 1.0)));\n\treturn interpolate(interpolate(v.x, v.y, f.x), interpolate(v.z, v.w, f.x), f.y);\n}\n\n// Based on The Book of Shaders\n// https://thebookofshaders.com/13/\nfloat noise(vec2 p, float time){\n\tfloat t = 0.0;\n\tfor(int i = 0; i < noiseOctaves; i++){\n\t\tfloat freq = pow(2.0, float(i));\n\t\tfloat amp = pow(per, float(noiseOctaves - i));\n\t\tt += irnd(vec2(p.y / freq + time, p.x / freq + time)) * amp;\n\t}\n\treturn t;\n}\n\nfloat fbm(vec2 x, float time) {\n\tfloat v = 0.0;\n\tfloat a = 0.5;\n\tvec2 shift = vec2(100);\n\tmat2 rot = mat2(cos(0.5), sin(0.5), -sin(0.5), cos(0.5));\n\tfloat sign = 1.0;\n\tfor (int i = 0; i < fbmOctaves; ++i) {\n\t\tv += a * noise(x, time * sign);\n\t\tx = rot * x * 2.0 + shift;\n\t\ta *= 0.5;\n\t\tsign *= -1.0;\n\t}\n\treturn v;\n}\n\nfloat warp(vec2 x, float g,float time){\n\tfloat val = 0.0;\n\tfor (int i = 0; i < warpOctaves; i++){\n\t\tval = fbm(x + g * vec2(cos(warpDirection.x * val), sin(warpDirection.y * val)), time);\n\t}\n\treturn val;\n}\n\nvoid main() {\n\tfloat noise = warp(gl_FragCoord.xy * scale ,warpStrength,uTime * timeStrength);\n\tgl_FragColor = vec4(vec3(noise),1.0);\n}","import { useMemo } from \"react\";\nimport * as THREE from \"three\";\nimport vertexShader from \"./shader/main.vert\";\nimport fragmentShader from \"./shader/main.frag\";\nimport { useAddObject } from \"../../../utils/useAddObject\";\nimport { MaterialProps } from \"../../types\";\nimport { MATERIAL_BASIC_PARAMS } from \"../../../libs/constants\";\nimport { NOISE_PARAMS } from \".\";\nimport { createMaterialParameters } from \"../../../utils/createMaterialParameters\";\n\nexport class NoiseMaterial extends THREE.ShaderMaterial {\n uniforms!: {\n uTime: { value: number };\n scale: { value: number };\n timeStrength: { value: number };\n noiseOctaves: { value: number };\n fbmOctaves: { value: number };\n warpOctaves: { value: number };\n warpDirection: { value: THREE.Vector2 };\n warpStrength: { value: number };\n };\n}\n\nexport const useMesh = ({\n scene,\n onBeforeInit,\n}: { scene: THREE.Scene } & MaterialProps) => {\n const geometry = useMemo(() => new THREE.PlaneGeometry(2, 2), []);\n const material = useMemo(() => {\n const mat = new THREE.ShaderMaterial({\n ...createMaterialParameters(\n {\n uniforms: {\n uTime: { value: 0.0 },\n scale: { value: NOISE_PARAMS.scale },\n timeStrength: { value: NOISE_PARAMS.timeStrength },\n noiseOctaves: { value: NOISE_PARAMS.noiseOctaves },\n fbmOctaves: { value: NOISE_PARAMS.fbmOctaves },\n warpOctaves: { value: NOISE_PARAMS.warpOctaves },\n warpDirection: { value: NOISE_PARAMS.warpDirection },\n warpStrength: { value: NOISE_PARAMS.warpStrength },\n },\n vertexShader: vertexShader,\n fragmentShader: fragmentShader,\n },\n onBeforeInit\n ),\n ...MATERIAL_BASIC_PARAMS,\n });\n return mat;\n }, [onBeforeInit]) as NoiseMaterial;\n const mesh = useAddObject(scene, geometry, material, THREE.Mesh);\n return { material, mesh };\n};\n","import { useCallback, useMemo } from \"react\";\nimport * as THREE from \"three\";\nimport { useMesh } from \"./useMesh\";\nimport { RootState } from \"@react-three/fiber\";\nimport { useCamera } from \"../../../utils/useCamera\";\nimport { useSingleFBO } from \"../../../utils/useSingleFBO\";\nimport {\n CustomParams,\n setCustomUniform,\n setUniform,\n} from \"../../../utils/setUniforms\";\nimport { useParams } from \"../../../utils/useParams\";\nimport { HooksProps, HooksReturn } from \"../../types\";\nimport { getDpr } from \"../../../utils/getDpr\";\n\nexport type NoiseParams = {\n /** noise scale , default : `0.004` */\n scale?: number;\n /** time factor default : `0.3` */\n timeStrength?: number;\n /** noiseOctaves, affects performance default : `2` */\n noiseOctaves?: number;\n /** fbmOctaves, affects performance default : `2` */\n fbmOctaves?: number;\n /** domain warping octaves , affects performance default : `2` */\n warpOctaves?: number;\n /** direction of domain warping , default : `(2.0,2,0)` */\n warpDirection?: THREE.Vector2;\n /** strength of domain warping , default : `8.0` */\n warpStrength?: number;\n /** you can get into the rhythm ♪ , default : `false` */\n beat?: number | false;\n};\n\nexport type NoiseObject = {\n scene: THREE.Scene;\n mesh: THREE.Mesh;\n material: THREE.Material;\n camera: THREE.Camera;\n renderTarget: THREE.WebGLRenderTarget;\n output: THREE.Texture;\n};\n\nexport const NOISE_PARAMS: NoiseParams = Object.freeze({\n scale: 0.004,\n timeStrength: 0.3,\n noiseOctaves: 2,\n fbmOctaves: 2,\n warpOctaves: 2,\n warpDirection: new THREE.Vector2(2.0, 2.0),\n warpStrength: 8.0,\n beat: false,\n});\n\n/**\n * @link https://github.com/FunTechInc/use-shader-fx?tab=readme-ov-file#usage\n *\n * It is a basic value noise with `fbm` and `domain warping`\n */\nexport const useNoise = ({\n size,\n dpr,\n renderTargetOptions,\n isSizeUpdate,\n onBeforeInit,\n}: HooksProps): HooksReturn => {\n const _dpr = getDpr(dpr);\n\n const scene = useMemo(() => new THREE.Scene(), []);\n const { material, mesh } = useMesh({ scene, onBeforeInit });\n const camera = useCamera(size);\n const [renderTarget, updateRenderTarget] = useSingleFBO({\n scene,\n camera,\n size,\n dpr: _dpr.fbo,\n isSizeUpdate,\n ...renderTargetOptions,\n });\n\n const [params, setParams] = useParams(NOISE_PARAMS);\n\n const updateValue = setUniform(material);\n const updateCustomValue = setCustomUniform(material);\n\n const updateParams = useCallback(\n (newParams?: NoiseParams, customParams?: CustomParams) => {\n setParams(newParams);\n updateCustomValue(customParams);\n },\n [setParams, updateCustomValue]\n );\n\n const updateFx = useCallback(\n (\n rootState: RootState,\n newParams?: NoiseParams,\n customParams?: CustomParams\n ) => {\n const { gl, clock } = rootState;\n\n updateParams(newParams, customParams);\n\n updateValue(\"scale\", params.scale!);\n updateValue(\"timeStrength\", params.timeStrength!);\n updateValue(\"noiseOctaves\", params.noiseOctaves!);\n updateValue(\"fbmOctaves\", params.fbmOctaves!);\n updateValue(\"warpOctaves\", params.warpOctaves!);\n updateValue(\"warpDirection\", params.warpDirection!);\n updateValue(\"warpStrength\", params.warpStrength!);\n updateValue(\"uTime\", params.beat || clock.getElapsedTime());\n\n return updateRenderTarget(gl);\n },\n [updateRenderTarget, updateValue, params, updateParams]\n );\n\n return [\n updateFx,\n updateParams,\n {\n scene: scene,\n mesh: mesh,\n material: material,\n camera: camera,\n renderTarget: renderTarget,\n output: renderTarget.texture,\n },\n ];\n};\n","#usf ","precision highp float;\nvarying vec2 vUv;\n\nuniform sampler2D uTexture;\nuniform bool isTexture;\nuniform sampler2D noise;\nuniform bool isNoise;\nuniform vec2 noiseStrength;\nuniform float laminateLayer;\nuniform vec2 laminateInterval;\nuniform vec2 laminateDetail;\nuniform vec2 distortion;\nuniform vec3 colorFactor;\nuniform float uTime;\nuniform vec2 timeStrength;\nuniform float scale;\n\nvoid main() {\n\tvec2 uv = vUv;\n\n\tvec2 pos = isTexture ? texture2D(uTexture, uv).rg : uv * scale;\n\tvec2 noise = isNoise ? texture2D(noise, uv).rg : vec2(0.0);\n\tfloat alpha = isTexture ? texture2D(uTexture, uv).a : 1.0;\n\t\n\t// Avoid floating point bugs caused by GPU drivers.\n\talpha = (alpha < 1e-10) ? 0.0 : alpha;\n\n\tvec3 col;\n\tfor(float j = 0.0; j < 3.0; j++){\n\t\tfor(float i = 1.0; i < laminateLayer; i++){\n\t\t\tfloat timeNoiseSin = sin(uTime / (i + j)) * timeStrength.x + noise.r * noiseStrength.x;\n\t\t\tfloat timeNoiseCos = cos(uTime / (i + j)) * timeStrength.y + noise.g * noiseStrength.y;\n\t\t\tpos.x += laminateInterval.x / (i + j) * cos(i * distortion.x * pos.y + timeNoiseSin + sin(i + j));\n\t\t\tpos.y += laminateInterval.y / (i + j) * cos(i * distortion.y * pos.x + timeNoiseCos + sin(i + j));\n\t\t}\n\t\tcol[int(j)] = sin(pow(pos.x, 2.) * pow(laminateDetail.x, 2.)) + sin(pow(pos.y, 2.) * pow(laminateDetail.y, 2.));\n\t}\n\n\tcol *= colorFactor * alpha;\n\tcol = clamp(col, 0.0, 1.0);\n\t\n\tgl_FragColor = vec4(col, alpha);\n}","import { useMemo } from \"react\";\nimport * as THREE from \"three\";\nimport vertexShader from \"./shader/main.vert\";\nimport fragmentShader from \"./shader/main.frag\";\nimport { useAddObject } from \"../../../utils/useAddObject\";\nimport { MaterialProps } from \"../../types\";\nimport {\n MATERIAL_BASIC_PARAMS,\n DEFAULT_TEXTURE,\n} from \"../../../libs/constants\";\nimport { COLORSTRATA_PARAMS } from \".\";\nimport { createMaterialParameters } from \"../../../utils/createMaterialParameters\";\n\nexport class ColorStrataMaterial extends THREE.ShaderMaterial {\n uniforms!: {\n uTexture: { value: THREE.Texture };\n isTexture: { value: boolean };\n scale: { value: number };\n noise: { value: THREE.Texture };\n noiseStrength: { value: THREE.Vector2 };\n isNoise: { value: boolean };\n laminateLayer: { value: number };\n laminateInterval: { value: THREE.Vector2 };\n laminateDetail: { value: THREE.Vector2 };\n distortion: { value: THREE.Vector2 };\n colorFactor: { value: THREE.Vector3 };\n uTime: { value: number };\n timeStrength: { value: THREE.Vector2 };\n };\n}\n\nexport const useMesh = ({\n scene,\n onBeforeInit,\n}: { scene: THREE.Scene } & MaterialProps) => {\n const geometry = useMemo(() => new THREE.PlaneGeometry(2, 2), []);\n const material = useMemo(() => {\n const mat = new THREE.ShaderMaterial({\n ...createMaterialParameters(\n {\n uniforms: {\n uTexture: { value: DEFAULT_TEXTURE },\n isTexture: { value: false },\n scale: { value: COLORSTRATA_PARAMS.scale },\n noise: { value: DEFAULT_TEXTURE },\n noiseStrength: { value: COLORSTRATA_PARAMS.noiseStrength },\n isNoise: { value: false },\n laminateLayer: { value: COLORSTRATA_PARAMS.laminateLayer },\n laminateInterval: {\n value: COLORSTRATA_PARAMS.laminateInterval,\n },\n laminateDetail: { value: COLORSTRATA_PARAMS.laminateDetail },\n distortion: { value: COLORSTRATA_PARAMS.distortion },\n colorFactor: { value: COLORSTRATA_PARAMS.colorFactor },\n uTime: { value: 0 },\n timeStrength: { value: COLORSTRATA_PARAMS.timeStrength },\n },\n vertexShader: vertexShader,\n fragmentShader: fragmentShader,\n },\n onBeforeInit\n ),\n ...MATERIAL_BASIC_PARAMS,\n });\n\n return mat;\n }, [onBeforeInit]) as ColorStrataMaterial;\n\n const mesh = useAddObject(scene, geometry, material, THREE.Mesh);\n\n return { material, mesh };\n};\n","import { useCallback, useMemo } from \"react\";\nimport * as THREE from \"three\";\nimport { useMesh } from \"./useMesh\";\nimport { useCamera } from \"../../../utils/useCamera\";\nimport { RootState } from \"@react-three/fiber\";\nimport { useSingleFBO } from \"../../../utils/useSingleFBO\";\nimport {\n CustomParams,\n setCustomUniform,\n setUniform,\n} from \"../../../utils/setUniforms\";\nimport { HooksProps, HooksReturn } from \"../../types\";\nimport { useParams } from \"../../../utils/useParams\";\nimport { getDpr } from \"../../../utils/getDpr\";\n\nexport type ColorStrataParams = {\n /** default : `null` */\n texture?: THREE.Texture | false;\n /** Valid when texture is false. default : `1` */\n scale?: number;\n /** default : `1.0` */\n laminateLayer?: number;\n /** default : `(0.1, 0.1)` */\n laminateInterval?: THREE.Vector2;\n /** default : `(1.0, 1.0)` */\n laminateDetail?: THREE.Vector2;\n /** default : `(0.0, 0.0)` */\n distortion?: THREE.Vector2;\n /** default : `(1.0, 1.0, 1.0)` */\n colorFactor?: THREE.Vector3;\n /** default : `(0.0, 0.0)` */\n timeStrength?: THREE.Vector2;\n /** default : `false` */\n noise?: THREE.Texture | false;\n /** default : `(0.0,0.0)` */\n noiseStrength?: THREE.Vector2;\n /** you can get into the rhythm ♪ , default : `false` */\n beat?: number | false;\n};\n\nexport type ColorStrataObject = {\n scene: THREE.Scene;\n mesh: THREE.Mesh;\n material: THREE.Material;\n camera: THREE.Camera;\n renderTarget: THREE.WebGLRenderTarget;\n output: THREE.Texture;\n};\n\nexport const COLORSTRATA_PARAMS: ColorStrataParams = Object.freeze({\n texture: false,\n scale: 1.0,\n laminateLayer: 1.0,\n laminateInterval: new THREE.Vector2(0.1, 0.1),\n laminateDetail: new THREE.Vector2(1, 1),\n distortion: new THREE.Vector2(0, 0),\n colorFactor: new THREE.Vector3(1, 1, 1),\n timeStrength: new THREE.Vector2(0, 0),\n noise: false,\n noiseStrength: new THREE.Vector2(0, 0),\n beat: false,\n});\n\n/**\n * @link https://github.com/FunTechInc/use-shader-fx?tab=readme-ov-file#usage\n */\nexport const useColorStrata = ({\n size,\n dpr,\n renderTargetOptions,\n isSizeUpdate,\n onBeforeInit,\n}: HooksProps): HooksReturn<\n ColorStrataParams,\n ColorStrataObject,\n CustomParams\n> => {\n const _dpr = getDpr(dpr);\n\n const scene = useMemo(() => new THREE.Scene(), []);\n const { material, mesh } = useMesh({ scene, onBeforeInit });\n const camera = useCamera(size);\n const [renderTarget, updateRenderTarget] = useSingleFBO({\n scene,\n camera,\n size,\n dpr: _dpr.fbo,\n isSizeUpdate,\n ...renderTargetOptions,\n });\n\n const [params, setParams] = useParams(COLORSTRATA_PARAMS);\n\n const updateValue = setUniform(material);\n const updateCustomValue = setCustomUniform(material);\n\n const updateParams = useCallback(\n (newParams?: ColorStrataParams, customParams?: CustomParams) => {\n setParams(newParams);\n updateCustomValue(customParams);\n },\n [setParams, updateCustomValue]\n );\n\n const updateFx = useCallback(\n (\n rootState: RootState,\n newParams?: ColorStrataParams,\n customParams?: CustomParams\n ) => {\n const { gl, clock } = rootState;\n\n updateParams(newParams, customParams);\n\n if (params.texture) {\n updateValue(\"uTexture\", params.texture);\n updateValue(\"isTexture\", true);\n } else {\n updateValue(\"isTexture\", false);\n updateValue(\"scale\", params.scale!);\n }\n\n if (params.noise) {\n updateValue(\"noise\", params.noise);\n updateValue(\"isNoise\", true);\n updateValue(\"noiseStrength\", params.noiseStrength!);\n } else {\n updateValue(\"isNoise\", false);\n }\n\n updateValue(\"uTime\", params.beat || clock.getElapsedTime());\n\n updateValue(\"laminateLayer\", params.laminateLayer!);\n updateValue(\"laminateInterval\", params.laminateInterval!);\n updateValue(\"laminateDetail\", params.laminateDetail!);\n updateValue(\"distortion\", params.distortion!);\n updateValue(\"colorFactor\", params.colorFactor!);\n updateValue(\"timeStrength\", params.timeStrength!);\n\n return updateRenderTarget(gl);\n },\n [updateRenderTarget, updateValue, params, updateParams]\n );\n\n return [\n updateFx,\n updateParams,\n {\n scene: scene,\n mesh: mesh,\n material: material,\n camera: camera,\n renderTarget: renderTarget,\n output: renderTarget.texture,\n },\n ];\n};\n","#usf ","precision highp float;\n\nvarying vec2 vUv;\nuniform float u_time;\nuniform float u_pattern;\nuniform float u_complexity;\nuniform float u_complexityAttenuation;\nuniform float u_iterations;\nuniform float u_timeStrength;\nuniform float u_scale;\n\nvec3 marble(vec3 p){\n\tvec4 n;\n\tfor(float i;i {\n const geometry = useMemo(() => new THREE.PlaneGeometry(2, 2), []);\n const material = useMemo(() => {\n const mat = new THREE.ShaderMaterial({\n ...createMaterialParameters(\n {\n uniforms: {\n u_time: { value: 0 },\n u_pattern: { value: MARBLE_PARAMS.pattern },\n u_complexity: { value: MARBLE_PARAMS.complexity },\n u_complexityAttenuation: {\n value: MARBLE_PARAMS.complexityAttenuation,\n },\n u_iterations: { value: MARBLE_PARAMS.iterations },\n u_timeStrength: { value: MARBLE_PARAMS.timeStrength },\n u_scale: { value: MARBLE_PARAMS.scale },\n },\n vertexShader: vertexShader,\n fragmentShader: fragmentShader,\n },\n onBeforeInit\n ),\n ...MATERIAL_BASIC_PARAMS,\n });\n\n return mat;\n }, [onBeforeInit]) as MarbleMaterial;\n const mesh = useAddObject(scene, geometry, material, THREE.Mesh);\n return { material, mesh };\n};\n","import { useCallback, useMemo } from \"react\";\nimport * as THREE from \"three\";\nimport { useMesh } from \"./useMesh\";\nimport { useCamera } from \"../../../utils/useCamera\";\nimport { RootState } from \"@react-three/fiber\";\nimport { useSingleFBO } from \"../../../utils/useSingleFBO\";\nimport {\n CustomParams,\n setCustomUniform,\n setUniform,\n} from \"../../../utils/setUniforms\";\nimport { HooksProps, HooksReturn } from \"../../types\";\nimport { useParams } from \"../../../utils/useParams\";\nimport { getDpr } from \"../../../utils/getDpr\";\n\nexport type MarbleParams = {\n /** You can add random patterns to noise by passing random numbers ,default : `0` */\n pattern?: number;\n /** default : `2` */\n complexity?: number;\n /** default : `0.2` */\n complexityAttenuation?: number;\n /** default : `8` */\n iterations?: number;\n /** default : `0.2` */\n timeStrength?: number;\n /** default : `0.002` */\n scale?: number;\n /** you can get into the rhythm ♪ , default : `false` */\n beat?: number | false;\n};\n\nexport type MarbleObject = {\n scene: THREE.Scene;\n mesh: THREE.Mesh;\n material: THREE.Material;\n camera: THREE.Camera;\n renderTarget: THREE.WebGLRenderTarget;\n output: THREE.Texture;\n};\n\nexport const MARBLE_PARAMS: MarbleParams = Object.freeze({\n pattern: 0,\n complexity: 2,\n complexityAttenuation: 0.2,\n iterations: 8,\n timeStrength: 0.2,\n scale: 0.002,\n beat: false,\n});\n\n/**\n * @link https://github.com/FunTechInc/use-shader-fx?tab=readme-ov-file#usage\n */\nexport const useMarble = ({\n size,\n dpr,\n renderTargetOptions,\n isSizeUpdate,\n onBeforeInit,\n}: HooksProps): HooksReturn => {\n const _dpr = getDpr(dpr);\n const scene = useMemo(() => new THREE.Scene(), []);\n const { material, mesh } = useMesh({ scene, onBeforeInit });\n const camera = useCamera(size);\n const [renderTarget, updateRenderTarget] = useSingleFBO({\n scene,\n camera,\n size,\n dpr: _dpr.fbo,\n isSizeUpdate,\n ...renderTargetOptions,\n });\n\n const [params, setParams] = useParams(MARBLE_PARAMS);\n\n const updateValue = setUniform(material);\n const updateCustomValue = setCustomUniform(material);\n\n const updateParams = useCallback(\n (newParams?: MarbleParams, customParams?: CustomParams) => {\n setParams(newParams);\n updateCustomValue(customParams);\n },\n [setParams, updateCustomValue]\n );\n\n const updateFx = useCallback(\n (\n rootState: RootState,\n newParams?: MarbleParams,\n customParams?: CustomParams\n ) => {\n const { gl, clock } = rootState;\n\n updateParams(newParams, customParams);\n\n updateValue(\"u_pattern\", params.pattern!);\n updateValue(\"u_complexity\", params.complexity!);\n updateValue(\"u_complexityAttenuation\", params.complexityAttenuation!);\n updateValue(\"u_iterations\", params.iterations!);\n updateValue(\"u_timeStrength\", params.timeStrength!);\n updateValue(\"u_scale\", params.scale!);\n updateValue(\"u_time\", params.beat || clock.getElapsedTime());\n\n return updateRenderTarget(gl);\n },\n [updateRenderTarget, updateValue, params, updateParams]\n );\n\n return [\n updateFx,\n updateParams,\n {\n scene: scene,\n mesh: mesh,\n material: material,\n camera: camera,\n renderTarget: renderTarget,\n output: renderTarget.texture,\n },\n ];\n};\n","#usf ","precision highp float;\nprecision highp int;\n\nvarying vec2 vUv;\nuniform sampler2D uTexture;\nuniform vec3 uColor1;\nuniform vec3 uColor2;\nuniform vec3 uColor3;\nuniform vec3 uColor4;\nuniform vec3 uRgbWeight;\n\n\n// Based on glsl-cos-palette by Erkaman\n// https://github.com/Erkaman/glsl-cos-palette\nvec3 cosPalette( float t, vec3 color1, vec3 color2, vec3 color3, vec3 color4 ){\n return color1 + color2 * cos( 6.28318 * ( color3 * t + color4) );\n}\n\nvoid main() {\n\n\tvec4 tex = texture2D(uTexture, vUv);\n\tfloat gray = dot(tex.rgb, uRgbWeight);\t\t\n\n\tvec3 outColor = cosPalette(\n\t\tgray,\n\t\tuColor1,\n\t\tuColor2,\n\t\tuColor3,\n\t\tuColor4\n\t);\n\n\tgl_FragColor = vec4(outColor, tex.a);\n}","import { useMemo } from \"react\";\nimport * as THREE from \"three\";\nimport vertexShader from \"./shader/main.vert\";\nimport fragmentShader from \"./shader/main.frag\";\nimport { useAddObject } from \"../../../utils/useAddObject\";\nimport { MaterialProps } from \"../../types\";\nimport {\n MATERIAL_BASIC_PARAMS,\n DEFAULT_TEXTURE,\n} from \"../../../libs/constants\";\nimport { COSPALETTE_PARAMS } from \".\";\nimport { createMaterialParameters } from \"../../../utils/createMaterialParameters\";\n\nexport class CosPaletteMaterial extends THREE.ShaderMaterial {\n uniforms!: {\n uTexture: { value: THREE.Texture };\n uRgbWeight: { value: THREE.Vector3 };\n uColor1: { value: THREE.Color };\n uColor2: { value: THREE.Color };\n uColor3: { value: THREE.Color };\n uColor4: { value: THREE.Color };\n };\n}\n\nexport const useMesh = ({\n scene,\n onBeforeInit,\n}: { scene: THREE.Scene } & MaterialProps) => {\n const geometry = useMemo(() => new THREE.PlaneGeometry(2, 2), []);\n const material = useMemo(() => {\n const mat = new THREE.ShaderMaterial({\n ...createMaterialParameters(\n {\n uniforms: {\n uTexture: { value: DEFAULT_TEXTURE },\n uRgbWeight: { value: COSPALETTE_PARAMS.rgbWeight },\n uColor1: { value: COSPALETTE_PARAMS.color1 },\n uColor2: { value: COSPALETTE_PARAMS.color2 },\n uColor3: { value: COSPALETTE_PARAMS.color3 },\n uColor4: { value: COSPALETTE_PARAMS.color4 },\n },\n vertexShader: vertexShader,\n fragmentShader: fragmentShader,\n },\n onBeforeInit\n ),\n ...MATERIAL_BASIC_PARAMS,\n });\n\n return mat;\n }, [onBeforeInit]) as CosPaletteMaterial;\n const mesh = useAddObject(scene, geometry, material, THREE.Mesh);\n return { material, mesh };\n};\n","import { useCallback, useMemo } from \"react\";\nimport * as THREE from \"three\";\nimport { useMesh } from \"./useMesh\";\nimport { RootState } from \"@react-three/fiber\";\nimport { useCamera } from \"../../../utils/useCamera\";\nimport { useSingleFBO } from \"../../../utils/useSingleFBO\";\nimport {\n CustomParams,\n setCustomUniform,\n setUniform,\n} from \"../../../utils/setUniforms\";\nimport { useParams } from \"../../../utils/useParams\";\nimport { HooksProps, HooksReturn } from \"../../types\";\nimport { getDpr } from \"../../../utils/getDpr\";\nimport { DEFAULT_TEXTURE } from \"../../../libs/constants\";\n\nexport type CosPaletteParams = {\n /** color1, default : `rgb(50%, 50%, 50%)` */\n color1?: THREE.Color;\n /** color2, default : `rgb(50%, 50%, 50%)` */\n color2?: THREE.Color;\n /** color3, default : `rgb(100%, 100%, 100%)` */\n color3?: THREE.Color;\n /** color4, default : `rgb(0%, 10%, 20%)` */\n color4?: THREE.Color;\n /** texture to be used as a palette */\n texture?: THREE.Texture;\n /** weight of the rgb, default : `THREE.Vector3(1.0,0.0,0.0)` */\n rgbWeight?: THREE.Vector3;\n};\n\nexport type ColorPaletteObject = {\n scene: THREE.Scene;\n mesh: THREE.Mesh;\n material: THREE.Material;\n camera: THREE.Camera;\n renderTarget: THREE.WebGLRenderTarget;\n output: THREE.Texture;\n};\n\nexport const COSPALETTE_PARAMS: CosPaletteParams = Object.freeze({\n texture: DEFAULT_TEXTURE,\n color1: new THREE.Color().set(0.5, 0.5, 0.5),\n color2: new THREE.Color().set(0.5, 0.5, 0.5),\n color3: new THREE.Color().set(1, 1, 1),\n color4: new THREE.Color().set(0, 0.1, 0.2),\n rgbWeight: new THREE.Vector3(0.299, 0.587, 0.114),\n});\n\n/**\n * @link https://github.com/FunTechInc/use-shader-fx?tab=readme-ov-file#usage\n */\nexport const useCosPalette = ({\n size,\n dpr,\n renderTargetOptions,\n isSizeUpdate,\n onBeforeInit,\n}: HooksProps): HooksReturn<\n CosPaletteParams,\n ColorPaletteObject,\n CustomParams\n> => {\n const _dpr = getDpr(dpr);\n\n const scene = useMemo(() => new THREE.Scene(), []);\n const { material, mesh } = useMesh({ scene, onBeforeInit });\n const camera = useCamera(size);\n const [renderTarget, updateRenderTarget] = useSingleFBO({\n scene,\n camera,\n size,\n dpr: _dpr.fbo,\n isSizeUpdate,\n ...renderTargetOptions,\n });\n\n const [params, setParams] = useParams(COSPALETTE_PARAMS);\n\n const updateValue = setUniform(material);\n const updateCustomValue = setCustomUniform(material);\n\n const updateParams = useCallback(\n (newParams?: CosPaletteParams, customParams?: CustomParams) => {\n setParams(newParams);\n updateCustomValue(customParams);\n },\n [setParams, updateCustomValue]\n );\n\n const updateFx = useCallback(\n (\n rootState: RootState,\n newParams?: CosPaletteParams,\n customParams?: CustomParams\n ) => {\n const { gl } = rootState;\n\n updateParams(newParams, customParams);\n\n updateValue(\"uTexture\", params.texture!);\n updateValue(\"uColor1\", params.color1!);\n updateValue(\"uColor2\", params.color2!);\n updateValue(\"uColor3\", params.color3!);\n updateValue(\"uColor4\", params.color4!);\n updateValue(\"uRgbWeight\", params.rgbWeight!);\n\n return updateRenderTarget(gl);\n },\n [updateRenderTarget, updateValue, params, updateParams]\n );\n\n return [\n updateFx,\n updateParams,\n {\n scene: scene,\n mesh: mesh,\n material: material,\n camera: camera,\n renderTarget: renderTarget,\n output: renderTarget.texture,\n },\n ];\n};\n","#usf ","precision highp float;\n\nvarying vec2 vUv;\nuniform sampler2D uTexture;\n\nuniform vec3 uColor0;\nuniform vec3 uColor1;\n\nvoid main() {\n\tvec2 uv = vUv;\n\tvec4 texColor = texture2D(uTexture, uv);\n\tfloat grayscale = dot(texColor.rgb, vec3(0.299, 0.587, 0.114));\n\tvec3 duotone = mix(uColor0, uColor1, grayscale);\n\tgl_FragColor = vec4(duotone, texColor.a);\n}","import { useMemo } from \"react\";\nimport * as THREE from \"three\";\nimport vertexShader from \"./shader/main.vert\";\nimport fragmentShader from \"./shader/main.frag\";\nimport { useAddObject } from \"../../../utils/useAddObject\";\nimport { MaterialProps } from \"../../types\";\nimport {\n MATERIAL_BASIC_PARAMS,\n DEFAULT_TEXTURE,\n} from \"../../../libs/constants\";\nimport { DUOTONE_PARAMS } from \".\";\nimport { createMaterialParameters } from \"../../../utils/createMaterialParameters\";\n\nexport class DuoToneMaterial extends THREE.ShaderMaterial {\n uniforms!: {\n uTexture: { value: THREE.Texture };\n uColor0: { value: THREE.Color };\n uColor1: { value: THREE.Color };\n };\n}\n\nexport const useMesh = ({\n scene,\n onBeforeInit,\n}: { scene: THREE.Scene } & MaterialProps) => {\n const geometry = useMemo(() => new THREE.PlaneGeometry(2, 2), []);\n const material = useMemo(() => {\n const mat = new THREE.ShaderMaterial({\n ...createMaterialParameters(\n {\n uniforms: {\n uTexture: { value: DEFAULT_TEXTURE },\n uColor0: { value: DUOTONE_PARAMS.color0 },\n uColor1: { value: DUOTONE_PARAMS.color1 },\n },\n vertexShader: vertexShader,\n fragmentShader: fragmentShader,\n },\n onBeforeInit\n ),\n ...MATERIAL_BASIC_PARAMS,\n });\n return mat;\n }, [onBeforeInit]) as DuoToneMaterial;\n const mesh = useAddObject(scene, geometry, material, THREE.Mesh);\n return { material, mesh };\n};\n","import { useCallback, useMemo } from \"react\";\nimport * as THREE from \"three\";\nimport { DuoToneMaterial, useMesh } from \"./useMesh\";\nimport { useCamera } from \"../../../utils/useCamera\";\nimport { RootState } from \"@react-three/fiber\";\nimport { useSingleFBO } from \"../../../utils/useSingleFBO\";\nimport {\n CustomParams,\n setCustomUniform,\n setUniform,\n} from \"../../../utils/setUniforms\";\nimport { HooksProps, HooksReturn } from \"../../types\";\nimport { useParams } from \"../../../utils/useParams\";\nimport { getDpr } from \"../../../utils/getDpr\";\nimport { DEFAULT_TEXTURE } from \"../../../libs/constants\";\n\nexport type DuoToneParams = {\n /** Make this texture duotone , Default : `THREE.Texture()` */\n texture?: THREE.Texture;\n /** 1st color , Default : `THREE.Color(0xffffff)` */\n color0?: THREE.Color;\n /** 2nd color , Default : `THREE.Color(0x000000)` */\n color1?: THREE.Color;\n};\n\nexport type DuoToneObject = {\n scene: THREE.Scene;\n mesh: THREE.Mesh;\n material: DuoToneMaterial;\n camera: THREE.Camera;\n renderTarget: THREE.WebGLRenderTarget;\n output: THREE.Texture;\n};\n\nexport const DUOTONE_PARAMS: DuoToneParams = Object.freeze({\n texture: DEFAULT_TEXTURE,\n color0: new THREE.Color(0xffffff),\n color1: new THREE.Color(0x000000),\n});\n\n/**\n * @link https://github.com/FunTechInc/use-shader-fx?tab=readme-ov-file#usage\n */\nexport const useDuoTone = ({\n size,\n dpr,\n renderTargetOptions,\n isSizeUpdate,\n onBeforeInit,\n}: HooksProps): HooksReturn => {\n const _dpr = getDpr(dpr);\n\n const scene = useMemo(() => new THREE.Scene(), []);\n const { material, mesh } = useMesh({ scene, onBeforeInit });\n const camera = useCamera(size);\n const [renderTarget, updateRenderTarget] = useSingleFBO({\n scene,\n camera,\n size,\n dpr: _dpr.fbo,\n isSizeUpdate,\n ...renderTargetOptions,\n });\n\n const [params, setParams] = useParams(DUOTONE_PARAMS);\n\n const updateValue = setUniform(material);\n const updateCustomValue = setCustomUniform(material);\n\n const updateParams = useCallback(\n (newParams?: DuoToneParams, customParams?: CustomParams) => {\n setParams(newParams);\n updateCustomValue(customParams);\n },\n [setParams, updateCustomValue]\n );\n\n const updateFx = useCallback(\n (\n rootState: RootState,\n newParams?: DuoToneParams,\n customParams?: CustomParams\n ) => {\n const { gl } = rootState;\n\n updateParams(newParams, customParams);\n\n updateValue(\"uTexture\", params.texture!);\n updateValue(\"uColor0\", params.color0!);\n updateValue(\"uColor1\", params.color1!);\n\n return updateRenderTarget(gl);\n },\n [updateRenderTarget, updateValue, params, updateParams]\n );\n\n return [\n updateFx,\n updateParams,\n {\n scene: scene,\n mesh: mesh,\n material: material,\n camera: camera,\n renderTarget: renderTarget,\n output: renderTarget.texture,\n },\n ];\n};\n","#usf ","precision highp float;\n\nvarying vec2 vUv;\nuniform sampler2D u_texture;\nuniform sampler2D uMap;\nuniform bool u_isAlphaMap;\nuniform sampler2D u_alphaMap;\nuniform float uMapIntensity;\nuniform vec3 u_brightness;\nuniform float u_min;\nuniform float u_max;\nuniform vec3 u_dodgeColor;\nuniform bool u_isDodgeColor;\n\nvoid main() {\n\tvec2 uv = vUv;\n\n\t#usf \n\n\t// color blending\n\tfloat brightness = dot(mapColor,u_brightness);\n\tvec4 textureMap = texture2D(u_texture, uv);\n\tfloat blendValue = smoothstep(u_min, u_max, brightness);\n\n\t// set dodge color\n\tvec3 dodgeColor = u_isDodgeColor ? u_dodgeColor : mapColor;\n\tvec3 outputColor = blendValue * dodgeColor + (1.0 - blendValue) * textureMap.rgb;\n\t\n\t// alpha blending\n\tfloat alpha = u_isAlphaMap ? texture2D(u_alphaMap, uv).a : textureMap.a;\n\tfloat mixValue = u_isAlphaMap ? alpha : 0.0;\n\tvec3 alphaColor = vec3(mix(outputColor,mapColor,mixValue));\n\n\tgl_FragColor = vec4(alphaColor,alpha);\n}","import { useMemo } from \"react\";\nimport * as THREE from \"three\";\nimport vertexShader from \"./shader/main.vert\";\nimport fragmentShader from \"./shader/main.frag\";\nimport { useAddObject } from \"../../../utils/useAddObject\";\nimport { MaterialProps } from \"../../types\";\nimport {\n DEFAULT_TEXTURE,\n MATERIAL_BASIC_PARAMS,\n} from \"../../../libs/constants\";\nimport { BLENDING_PARAMS } from \".\";\nimport { createMaterialParameters } from \"../../../utils/createMaterialParameters\";\n\nexport class BlendingMaterial extends THREE.ShaderMaterial {\n uniforms!: {\n u_texture: { value: THREE.Texture };\n uMap: { value: THREE.Texture };\n u_alphaMap: { value: THREE.Texture };\n u_isAlphaMap: { value: boolean };\n uMapIntensity: { value: number };\n u_brightness: { value: THREE.Vector3 };\n u_min: { value: number };\n u_max: { value: number };\n u_dodgeColor: { value: THREE.Color };\n u_isDodgeColor: { value: boolean };\n };\n}\n\nexport const useMesh = ({\n scene,\n onBeforeInit,\n}: { scene: THREE.Scene } & MaterialProps) => {\n const geometry = useMemo(() => new THREE.PlaneGeometry(2, 2), []);\n const material = useMemo(() => {\n const mat = new THREE.ShaderMaterial({\n ...createMaterialParameters(\n {\n uniforms: {\n u_texture: { value: DEFAULT_TEXTURE },\n uMap: { value: DEFAULT_TEXTURE },\n u_alphaMap: { value: DEFAULT_TEXTURE },\n u_isAlphaMap: { value: false },\n uMapIntensity: { value: BLENDING_PARAMS.mapIntensity },\n u_brightness: { value: BLENDING_PARAMS.brightness },\n u_min: { value: BLENDING_PARAMS.min },\n u_max: { value: BLENDING_PARAMS.max },\n u_dodgeColor: { value: new THREE.Color() },\n u_isDodgeColor: { value: false },\n },\n vertexShader: vertexShader,\n fragmentShader: fragmentShader,\n },\n onBeforeInit\n ),\n ...MATERIAL_BASIC_PARAMS,\n });\n\n return mat;\n }, [onBeforeInit]) as BlendingMaterial;\n const mesh = useAddObject(scene, geometry, material, THREE.Mesh);\n return { material, mesh };\n};\n","import { useCallback, useMemo } from \"react\";\nimport * as THREE from \"three\";\nimport { useMesh } from \"./useMesh\";\nimport { useCamera } from \"../../../utils/useCamera\";\nimport { RootState } from \"@react-three/fiber\";\nimport { useSingleFBO } from \"../../../utils/useSingleFBO\";\nimport {\n CustomParams,\n setCustomUniform,\n setUniform,\n} from \"../../../utils/setUniforms\";\nimport { HooksProps, HooksReturn } from \"../../types\";\nimport { useParams } from \"../../../utils/useParams\";\nimport { getDpr } from \"../../../utils/getDpr\";\nimport { DEFAULT_TEXTURE } from \"../../../libs/constants\";\n\nexport type BlendingParams = {\n /** Make this texture Blending , default : `THREE.Texture` */\n texture?: THREE.Texture;\n /** map texture, default : `THREE.Texture` */\n map?: THREE.Texture;\n /** map strength , r,g value are affecting , default : `0.3` */\n mapIntensity?: number;\n /** Alpha blending is performed using the alpha of the set texture. , default : `false` */\n alphaMap?: THREE.Texture | false;\n /** default : `(0.5,0.5,0.5)` */\n brightness?: THREE.Vector3;\n /** default : `0.0` */\n min?: number;\n /** default : `1.0` */\n max?: number;\n /** If set, this value will apply color dodge , default : `false` */\n dodgeColor?: THREE.Color | false;\n};\n\nexport type BlendingObject = {\n scene: THREE.Scene;\n mesh: THREE.Mesh;\n material: THREE.Material;\n camera: THREE.Camera;\n renderTarget: THREE.WebGLRenderTarget;\n output: THREE.Texture;\n};\n\nexport const BLENDING_PARAMS: BlendingParams = Object.freeze({\n texture: DEFAULT_TEXTURE,\n map: DEFAULT_TEXTURE,\n alphaMap: false,\n mapIntensity: 0.3,\n brightness: new THREE.Vector3(0.5, 0.5, 0.5),\n min: 0.0,\n max: 1.0,\n dodgeColor: false,\n});\n\n/**\n * Blend map to texture. You can set the threshold for blending with brightness. You can set the dodge color by setting color. \nIf you don't want to reflect the map's color, you can use useFxBlending instead.\n * @link https://github.com/FunTechInc/use-shader-fx?tab=readme-ov-file#usage\n */\nexport const useBlending = ({\n size,\n dpr,\n renderTargetOptions,\n isSizeUpdate,\n onBeforeInit,\n}: HooksProps): HooksReturn => {\n const _dpr = getDpr(dpr);\n\n const scene = useMemo(() => new THREE.Scene(), []);\n const { material, mesh } = useMesh({ scene, onBeforeInit });\n const camera = useCamera(size);\n const [renderTarget, updateRenderTarget] = useSingleFBO({\n scene,\n camera,\n size,\n dpr: _dpr.fbo,\n isSizeUpdate,\n ...renderTargetOptions,\n });\n\n const [params, setParams] = useParams(BLENDING_PARAMS);\n\n const updateValue = setUniform(material);\n const updateCustomValue = setCustomUniform(material);\n\n const updateParams = useCallback(\n (newParams?: BlendingParams, customParams?: CustomParams) => {\n setParams(newParams);\n updateCustomValue(customParams);\n },\n [setParams, updateCustomValue]\n );\n\n const updateFx = useCallback(\n (\n rootState: RootState,\n newParams?: BlendingParams,\n customParams?: CustomParams\n ) => {\n const { gl } = rootState;\n\n updateParams(newParams, customParams);\n\n updateValue(\"u_texture\", params.texture!);\n updateValue(\"uMap\", params.map!);\n updateValue(\"uMapIntensity\", params.mapIntensity!);\n if (params.alphaMap) {\n updateValue(\"u_alphaMap\", params.alphaMap!);\n updateValue(\"u_isAlphaMap\", true);\n } else {\n updateValue(\"u_isAlphaMap\", false);\n }\n updateValue(\"u_brightness\", params.brightness!);\n updateValue(\"u_min\", params.min!);\n updateValue(\"u_max\", params.max!);\n if (params.dodgeColor) {\n updateValue(\"u_dodgeColor\", params.dodgeColor);\n updateValue(\"u_isDodgeColor\", true);\n } else {\n updateValue(\"u_isDodgeColor\", false);\n }\n\n return updateRenderTarget(gl);\n },\n [updateRenderTarget, updateValue, params, updateParams]\n );\n\n return [\n updateFx,\n updateParams,\n {\n scene: scene,\n mesh: mesh,\n material: material,\n camera: camera,\n renderTarget: renderTarget,\n output: renderTarget.texture,\n },\n ];\n};\n","#usf ","precision highp float;\n\nvarying vec2 vUv;\nuniform vec2 uResolution;\nuniform vec2 uTextureResolution;\nuniform sampler2D uTexture0;\nuniform sampler2D uTexture1;\nuniform sampler2D uMap;\nuniform float mapIntensity;\nuniform float edgeIntensity;\nuniform float progress;\nuniform float dirX;\nuniform float dirY;\nuniform vec2 epicenter;\nuniform float padding;\n\nbool isInPaddingArea(vec2 uv) {\n return uv.x < padding || uv.x > 1.0 - padding || uv.y < padding || uv.y > 1.0 - padding;\n}\n\nvoid main() {\n\t#usf \n\n\t// fx map\n\tvec2 map = texture2D(uMap, uv).rg;\n\tvec2 normalizedMap = map * 2.0 - 1.0;\n\n\t// multiply edge fx\n\tuv = uv * 2.0 - 1.0;\n\tuv *= map * distance(epicenter, uv) * edgeIntensity + 1.0;\n\tuv = (uv + 1.0) / 2.0;\n\n\t// padding\n\tif (isInPaddingArea(uv)) {\n\t\tgl_FragColor = vec4(0.0, 0.0, 0.0, 0.0);\n\t\treturn;\n\t}\n\tvec2 paddedUV = uv * (1.0 - 2.0 * padding * -1.) + padding * -1.;\n\n\t// centered uv\n\tvec2 centeredUV = paddedUV - vec2(0.5);\n\n\t// multiply map fx\n\tcenteredUV *= normalizedMap * map * mapIntensity + 1.0;\n\n\t// texture 0\n\tfloat xOffsetTexture0 = 0.5 - dirX * progress;\n\tfloat yOffsetTexture0 = 0.5 - dirY * progress;\n\tvec2 samplePosTexture0 = vec2(xOffsetTexture0, yOffsetTexture0) + centeredUV;\n\n\t//texture 1\n\tfloat xOffsetTexture1 = 0.5 + dirX * (1.0 - progress);\n\tfloat yOffsetTexture1 = 0.5 + dirY * (1.0 - progress);\n\tvec2 samplePosTexture1 = vec2(xOffsetTexture1, yOffsetTexture1) + centeredUV;\n\n\tvec4 color0 = texture2D(uTexture0, samplePosTexture0);\n\tvec4 color1 = texture2D(uTexture1, samplePosTexture1);\n\n\tgl_FragColor = mix(color0, color1, progress);\n\n}","import { useMemo } from \"react\";\nimport * as THREE from \"three\";\nimport { useResolution } from \"../../../utils/useResolution\";\nimport vertexShader from \"./shader/main.vert\";\nimport fragmentShader from \"./shader/main.frag\";\nimport { setUniform } from \"../../../utils/setUniforms\";\nimport { useAddObject } from \"../../../utils/useAddObject\";\nimport { MaterialProps, Size } from \"../../types\";\nimport {\n MATERIAL_BASIC_PARAMS,\n DEFAULT_TEXTURE,\n} from \"../../../libs/constants\";\nimport { FXTEXTURE_PARAMS } from \".\";\nimport { createMaterialParameters } from \"../../../utils/createMaterialParameters\";\n\nexport class FxTextureMaterial extends THREE.ShaderMaterial {\n uniforms!: {\n uResolution: { value: THREE.Vector2 };\n uTextureResolution: { value: THREE.Vector2 };\n uTexture0: { value: THREE.Texture };\n uTexture1: { value: THREE.Texture };\n padding: { value: number };\n uMap: { value: THREE.Texture };\n edgeIntensity: { value: number };\n mapIntensity: { value: number };\n epicenter: { value: THREE.Vector2 };\n progress: { value: number };\n dirX: { value: number };\n dirY: { value: number };\n };\n}\n\nexport const useMesh = ({\n scene,\n size,\n dpr,\n onBeforeInit,\n}: {\n scene: THREE.Scene;\n size: Size;\n dpr: number | false;\n} & MaterialProps) => {\n const geometry = useMemo(() => new THREE.PlaneGeometry(2, 2), []);\n const material = useMemo(() => {\n const mat = new THREE.ShaderMaterial({\n ...createMaterialParameters(\n {\n uniforms: {\n uResolution: { value: new THREE.Vector2() },\n uTextureResolution: { value: new THREE.Vector2() },\n uTexture0: { value: DEFAULT_TEXTURE },\n uTexture1: { value: DEFAULT_TEXTURE },\n padding: { value: FXTEXTURE_PARAMS.padding },\n uMap: { value: DEFAULT_TEXTURE },\n edgeIntensity: { value: FXTEXTURE_PARAMS.edgeIntensity },\n mapIntensity: { value: FXTEXTURE_PARAMS.mapIntensity },\n epicenter: { value: FXTEXTURE_PARAMS.epicenter },\n progress: { value: FXTEXTURE_PARAMS.progress },\n dirX: { value: FXTEXTURE_PARAMS.dir?.x },\n dirY: { value: FXTEXTURE_PARAMS.dir?.y },\n },\n vertexShader: vertexShader,\n fragmentShader: fragmentShader,\n },\n onBeforeInit\n ),\n ...MATERIAL_BASIC_PARAMS,\n });\n return mat;\n }, [onBeforeInit]) as FxTextureMaterial;\n\n const resolution = useResolution(size, dpr);\n setUniform(material)(\"uResolution\", resolution.clone());\n\n const mesh = useAddObject(scene, geometry, material, THREE.Mesh);\n\n return { material, mesh };\n};\n","import * as THREE from \"three\";\nimport { useCallback, useMemo } from \"react\";\nimport { useMesh } from \"./useMesh\";\nimport { useCamera } from \"../../../utils/useCamera\";\nimport { RootState } from \"@react-three/fiber\";\nimport { useSingleFBO } from \"../../../utils/useSingleFBO\";\nimport {\n CustomParams,\n setCustomUniform,\n setUniform,\n} from \"../../../utils/setUniforms\";\nimport { HooksProps, HooksReturn } from \"../../types\";\nimport { useParams } from \"../../../utils/useParams\";\nimport { getDpr } from \"../../../utils/getDpr\";\nimport { DEFAULT_TEXTURE } from \"../../../libs/constants\";\n\nexport type FxTextureParams = {\n /** 1st texture , default : `THREE.Texture()` */\n texture0?: THREE.Texture;\n /** 2nd texture , default : `THREE.Texture()` */\n texture1?: THREE.Texture;\n /** add transparent padding, 0.0 ~ 1.0 , default : `0.0` */\n padding?: number;\n /** The color map. The uv value is affected according to this rbg , default : `THREE.Texture()` */\n map?: THREE.Texture;\n /** intensity of map , r,g value are affecting , default : `0.0` */\n mapIntensity?: number;\n /** Intensity of effect on edges , default : `0.0` */\n edgeIntensity?: number;\n /** epicenter of fx, -1 ~ 1 , default : `vec2(0.0,0.0)` */\n epicenter?: THREE.Vector2;\n /** Switch value to switch between texture0 and texture1 , 0 ~ 1 , default : `0` */\n progress?: number;\n /** direction of transition , default: `THREE.Vector2(0, 0)` */\n dir?: THREE.Vector2;\n};\n\nexport type FxTextureObject = {\n scene: THREE.Scene;\n mesh: THREE.Mesh;\n material: THREE.Material;\n camera: THREE.Camera;\n renderTarget: THREE.WebGLRenderTarget;\n output: THREE.Texture;\n};\n\nexport const FXTEXTURE_PARAMS: FxTextureParams = Object.freeze({\n texture0: DEFAULT_TEXTURE,\n texture1: DEFAULT_TEXTURE,\n padding: 0.0,\n map: DEFAULT_TEXTURE,\n mapIntensity: 0.0,\n edgeIntensity: 0.0,\n epicenter: new THREE.Vector2(0, 0),\n progress: 0.0,\n dir: new THREE.Vector2(0, 0),\n});\n\n/**\n * @link https://github.com/FunTechInc/use-shader-fx?tab=readme-ov-file#usage\n */\nexport const useFxTexture = ({\n size,\n dpr,\n renderTargetOptions,\n isSizeUpdate,\n onBeforeInit,\n}: HooksProps): HooksReturn => {\n const _dpr = getDpr(dpr);\n\n const scene = useMemo(() => new THREE.Scene(), []);\n const { material, mesh } = useMesh({\n scene,\n size,\n dpr: _dpr.shader,\n onBeforeInit,\n });\n const camera = useCamera(size);\n const [renderTarget, updateRenderTarget] = useSingleFBO({\n scene,\n camera,\n dpr: _dpr.fbo,\n size,\n isSizeUpdate,\n ...renderTargetOptions,\n });\n\n const [params, setParams] = useParams(FXTEXTURE_PARAMS);\n\n const updateValue = setUniform(material);\n const updateCustomValue = setCustomUniform(material);\n\n const updateParams = useCallback(\n (newParams?: FxTextureParams, customParams?: CustomParams) => {\n setParams(newParams);\n updateCustomValue(customParams);\n },\n [setParams, updateCustomValue]\n );\n\n const updateFx = useCallback(\n (\n rootState: RootState,\n newParams?: FxTextureParams,\n customParams?: CustomParams\n ) => {\n const { gl } = rootState;\n\n updateParams(newParams, customParams);\n\n updateValue(\"uTexture0\", params.texture0!);\n updateValue(\"uTexture1\", params.texture1!);\n updateValue(\"progress\", params.progress!);\n // calculate resolution by linear interpolation.\n const tex0Res = [\n params.texture0!?.image?.width || 0,\n params.texture0!?.image?.height || 0,\n ];\n const tex1Res = [\n params.texture1!?.image?.width || 0,\n params.texture1!?.image?.height || 0,\n ];\n const interpolatedResolution = tex0Res.map((value, index) => {\n return value + (tex1Res[index] - value) * params.progress!;\n });\n updateValue(\"uTextureResolution\", interpolatedResolution);\n updateValue(\"padding\", params.padding!);\n updateValue(\"uMap\", params.map!);\n updateValue(\"mapIntensity\", params.mapIntensity!);\n updateValue(\"edgeIntensity\", params.edgeIntensity!);\n updateValue(\"epicenter\", params.epicenter!);\n updateValue(\"dirX\", params.dir!.x);\n updateValue(\"dirY\", params.dir!.y);\n\n return updateRenderTarget(gl);\n },\n [updateRenderTarget, updateValue, params, updateParams]\n );\n return [\n updateFx,\n updateParams,\n {\n scene: scene,\n mesh: mesh,\n material: material,\n camera: camera,\n renderTarget: renderTarget,\n output: renderTarget.texture,\n },\n ];\n};\n","#usf ","precision highp float;\n\nvarying vec2 vUv;\nuniform sampler2D u_texture;\nuniform vec3 u_brightness;\nuniform float u_min;\nuniform float u_max;\n\nvoid main() {\n\tvec2 uv = vUv;\n\tvec3 color = texture2D(u_texture, uv).rgb;\n\tfloat brightness = dot(color,u_brightness);\n\tfloat alpha = clamp(smoothstep(u_min, u_max, brightness),0.0,1.0);\n\tgl_FragColor = vec4(color, alpha);\n}","import * as THREE from \"three\";\nimport { useMemo } from \"react\";\nimport vertexShader from \"./shader/main.vert\";\nimport fragmentShader from \"./shader/main.frag\";\nimport { useAddObject } from \"../../../utils/useAddObject\";\nimport { MaterialProps } from \"../../types\";\nimport {\n MATERIAL_BASIC_PARAMS,\n DEFAULT_TEXTURE,\n} from \"../../../libs/constants\";\nimport { BRIGHTNESSPICKER_PARAMS } from \".\";\nimport { createMaterialParameters } from \"../../../utils/createMaterialParameters\";\n\nexport class BrightnessPickerMaterial extends THREE.ShaderMaterial {\n uniforms!: {\n u_texture: { value: THREE.Texture };\n u_brightness: { value: THREE.Vector3 };\n u_min: { value: number };\n u_max: { value: number };\n };\n}\n\nexport const useMesh = ({\n scene,\n onBeforeInit,\n}: { scene: THREE.Scene } & MaterialProps) => {\n const geometry = useMemo(() => new THREE.PlaneGeometry(2, 2), []);\n const material = useMemo(() => {\n const mat = new THREE.ShaderMaterial({\n ...createMaterialParameters(\n {\n uniforms: {\n u_texture: { value: DEFAULT_TEXTURE },\n u_brightness: { value: BRIGHTNESSPICKER_PARAMS.brightness },\n u_min: { value: BRIGHTNESSPICKER_PARAMS.min },\n u_max: { value: BRIGHTNESSPICKER_PARAMS.max },\n },\n vertexShader: vertexShader,\n fragmentShader: fragmentShader,\n },\n onBeforeInit\n ),\n ...MATERIAL_BASIC_PARAMS,\n });\n return mat;\n }, [onBeforeInit]) as BrightnessPickerMaterial;\n const mesh = useAddObject(scene, geometry, material, THREE.Mesh);\n return { material, mesh };\n};\n","import { useCallback, useMemo } from \"react\";\nimport * as THREE from \"three\";\nimport { useMesh } from \"./useMesh\";\nimport { useCamera } from \"../../../utils/useCamera\";\nimport { RootState } from \"@react-three/fiber\";\nimport { useSingleFBO } from \"../../../utils/useSingleFBO\";\nimport {\n CustomParams,\n setCustomUniform,\n setUniform,\n} from \"../../../utils/setUniforms\";\nimport { HooksProps, HooksReturn } from \"../../types\";\nimport { useParams } from \"../../../utils/useParams\";\nimport { getDpr } from \"../../../utils/getDpr\";\nimport { DEFAULT_TEXTURE } from \"../../../libs/constants\";\n\nexport type BrightnessPickerParams = {\n /** pick brightness from this texture , default : `THREE.Texture` */\n texture?: THREE.Texture;\n /** default : `(0.5,0.5,0.5)` */\n brightness?: THREE.Vector3;\n /** default : `0.0` */\n min?: number;\n /** default : `1.0` */\n max?: number;\n};\n\nexport type BrightnessPickerObject = {\n scene: THREE.Scene;\n mesh: THREE.Mesh;\n material: THREE.Material;\n camera: THREE.Camera;\n renderTarget: THREE.WebGLRenderTarget;\n output: THREE.Texture;\n};\n\nexport const BRIGHTNESSPICKER_PARAMS: BrightnessPickerParams = Object.freeze({\n texture: DEFAULT_TEXTURE,\n brightness: new THREE.Vector3(0.5, 0.5, 0.5),\n min: 0.0,\n max: 1.0,\n});\n\n/**\n * @link https://github.com/FunTechInc/use-shader-fx?tab=readme-ov-file#usage\n */\nexport const useBrightnessPicker = ({\n size,\n dpr,\n renderTargetOptions,\n isSizeUpdate,\n onBeforeInit,\n}: HooksProps): HooksReturn<\n BrightnessPickerParams,\n BrightnessPickerObject,\n CustomParams\n> => {\n const _dpr = getDpr(dpr);\n const scene = useMemo(() => new THREE.Scene(), []);\n const { material, mesh } = useMesh({ scene, onBeforeInit });\n const camera = useCamera(size);\n const [renderTarget, updateRenderTarget] = useSingleFBO({\n scene,\n camera,\n size,\n dpr: _dpr.fbo,\n isSizeUpdate,\n ...renderTargetOptions,\n });\n\n const [params, setParams] = useParams(\n BRIGHTNESSPICKER_PARAMS\n );\n\n const updateValue = setUniform(material);\n const updateCustomValue = setCustomUniform(material);\n\n const updateParams = useCallback(\n (newParams?: BrightnessPickerParams, customParams?: CustomParams) => {\n setParams(newParams);\n updateCustomValue(customParams);\n },\n [setParams, updateCustomValue]\n );\n\n const updateFx = useCallback(\n (\n rootState: RootState,\n newParams?: BrightnessPickerParams,\n customParams?: CustomParams\n ) => {\n const { gl } = rootState;\n\n updateParams(newParams, customParams);\n\n updateValue(\"u_texture\", params.texture!);\n updateValue(\"u_brightness\", params.brightness!);\n updateValue(\"u_min\", params.min!);\n updateValue(\"u_max\", params.max!);\n\n return updateRenderTarget(gl);\n },\n [updateRenderTarget, updateValue, params, updateParams]\n );\n\n return [\n updateFx,\n updateParams,\n {\n scene: scene,\n mesh: mesh,\n material: material,\n camera: camera,\n renderTarget: renderTarget,\n output: renderTarget.texture,\n },\n ];\n};\n","#usf ","precision highp float;\n\nvarying vec2 vUv;\nuniform sampler2D u_texture;\nuniform sampler2D uMap;\nuniform float uMapIntensity;\n\nvoid main() {\n\tvec2 uv = vUv;\n\n\t#usf \n\n\tgl_FragColor = texture2D(u_texture, uv);\n}","import { useMemo } from \"react\";\nimport * as THREE from \"three\";\nimport vertexShader from \"./shader/main.vert\";\nimport fragmentShader from \"./shader/main.frag\";\nimport { useAddObject } from \"../../../utils/useAddObject\";\nimport { MaterialProps } from \"../../types\";\nimport {\n MATERIAL_BASIC_PARAMS,\n DEFAULT_TEXTURE,\n} from \"../../../libs/constants\";\nimport { FXBLENDING_PARAMS } from \".\";\nimport { createMaterialParameters } from \"../../../utils/createMaterialParameters\";\n\nexport class FxBlendingMaterial extends THREE.ShaderMaterial {\n uniforms!: {\n u_texture: { value: THREE.Texture };\n uMap: { value: THREE.Texture };\n uMapIntensity: { value: number };\n };\n}\n\nexport const useMesh = ({\n scene,\n onBeforeInit,\n}: { scene: THREE.Scene } & MaterialProps) => {\n const geometry = useMemo(() => new THREE.PlaneGeometry(2, 2), []);\n const material = useMemo(() => {\n const mat = new THREE.ShaderMaterial({\n ...createMaterialParameters(\n {\n uniforms: {\n u_texture: { value: DEFAULT_TEXTURE },\n uMap: { value: DEFAULT_TEXTURE },\n uMapIntensity: { value: FXBLENDING_PARAMS.mapIntensity },\n },\n vertexShader: vertexShader,\n fragmentShader: fragmentShader,\n },\n onBeforeInit\n ),\n ...MATERIAL_BASIC_PARAMS,\n });\n return mat;\n }, [onBeforeInit]) as FxBlendingMaterial;\n\n const mesh = useAddObject(scene, geometry, material, THREE.Mesh);\n return { material, mesh };\n};\n","import { useCallback, useMemo } from \"react\";\nimport * as THREE from \"three\";\nimport { useMesh } from \"./useMesh\";\nimport { useCamera } from \"../../../utils/useCamera\";\nimport { RootState } from \"@react-three/fiber\";\nimport { useSingleFBO } from \"../../../utils/useSingleFBO\";\nimport {\n CustomParams,\n setCustomUniform,\n setUniform,\n} from \"../../../utils/setUniforms\";\nimport { HooksProps, HooksReturn } from \"../../types\";\nimport { useParams } from \"../../../utils/useParams\";\nimport { getDpr } from \"../../../utils/getDpr\";\nimport { DEFAULT_TEXTURE } from \"../../../libs/constants\";\n\nexport type FxBlendingParams = {\n /** Make this texture Blending , default : `THREE.Texture` */\n texture?: THREE.Texture;\n /** map texture, default : `THREE.Texture` */\n map?: THREE.Texture;\n /** map strength , r,g value are affecting , default : `0.3` */\n mapIntensity?: number;\n};\n\nexport type FxBlendingObject = {\n scene: THREE.Scene;\n mesh: THREE.Mesh;\n material: THREE.Material;\n camera: THREE.Camera;\n renderTarget: THREE.WebGLRenderTarget;\n output: THREE.Texture;\n};\n\nexport const FXBLENDING_PARAMS: FxBlendingParams = Object.freeze({\n texture: DEFAULT_TEXTURE,\n map: DEFAULT_TEXTURE,\n mapIntensity: 0.3,\n});\n\n/**\n * Blend map to texture. You can change the intensity of fx applied by the rg value of map. Unlike \"useBlending\", the map color is not reflected.\n * @link https://github.com/FunTechInc/use-shader-fx?tab=readme-ov-file#usage\n */\nexport const useFxBlending = ({\n size,\n dpr,\n renderTargetOptions,\n isSizeUpdate,\n onBeforeInit,\n}: HooksProps): HooksReturn<\n FxBlendingParams,\n FxBlendingObject,\n CustomParams\n> => {\n const _dpr = getDpr(dpr);\n\n const scene = useMemo(() => new THREE.Scene(), []);\n const { material, mesh } = useMesh({ scene, onBeforeInit });\n const camera = useCamera(size);\n const [renderTarget, updateRenderTarget] = useSingleFBO({\n scene,\n camera,\n size,\n dpr: _dpr.fbo,\n isSizeUpdate,\n ...renderTargetOptions,\n });\n\n const [params, setParams] = useParams(FXBLENDING_PARAMS);\n\n const updateValue = setUniform(material);\n const updateCustomValue = setCustomUniform(material);\n\n const updateParams = useCallback(\n (newParams?: FxBlendingParams, customParams?: CustomParams) => {\n setParams(newParams);\n updateCustomValue(customParams);\n },\n [setParams, updateCustomValue]\n );\n\n const updateFx = useCallback(\n (\n rootState: RootState,\n newParams?: FxBlendingParams,\n customParams?: CustomParams\n ) => {\n const { gl } = rootState;\n\n updateParams(newParams, customParams);\n\n updateValue(\"u_texture\", params.texture!);\n updateValue(\"uMap\", params.map!);\n updateValue(\"uMapIntensity\", params.mapIntensity!);\n\n return updateRenderTarget(gl);\n },\n [updateRenderTarget, updateValue, params, updateParams]\n );\n\n return [\n updateFx,\n updateParams,\n {\n scene: scene,\n mesh: mesh,\n material: material,\n camera: camera,\n renderTarget: renderTarget,\n output: renderTarget.texture,\n },\n ];\n};\n","#usf ","precision highp float;\n\nuniform sampler2D uTexture;\nuniform sampler2D uMap;\n\nvarying vec2 vUv;\n\nvoid main() {\n\tvec2 uv = vUv;\n\tvec4 tex = texture2D(uTexture, uv);\n\tvec4 map = texture2D(uMap, uv);\n\tgl_FragColor = mix(tex,map,map.a);\n}\n\n","import * as THREE from \"three\";\nimport vertexShader from \"./shader/main.vert\";\nimport fragmentShader from \"./shader/main.frag\";\nimport { useMemo } from \"react\";\nimport { useAddObject } from \"../../../utils/useAddObject\";\nimport { MaterialProps, Size } from \"../../types\";\nimport {\n DEFAULT_TEXTURE,\n MATERIAL_BASIC_PARAMS,\n} from \"../../../libs/constants\";\nimport { createMaterialParameters } from \"../../../utils/createMaterialParameters\";\n\nexport class AlphaBlendingMaterial extends THREE.ShaderMaterial {\n uniforms!: {\n uTexture: { value: THREE.Texture };\n uMap: { value: THREE.Texture };\n };\n}\n\nexport const useMesh = ({\n scene,\n onBeforeInit,\n}: {\n scene: THREE.Scene;\n size: Size;\n} & MaterialProps) => {\n const geometry = useMemo(() => new THREE.PlaneGeometry(2, 2), []);\n const material = useMemo(() => {\n const mat = new THREE.ShaderMaterial({\n ...createMaterialParameters(\n {\n uniforms: {\n uTexture: { value: DEFAULT_TEXTURE },\n uMap: { value: DEFAULT_TEXTURE },\n },\n vertexShader: vertexShader,\n fragmentShader: fragmentShader,\n },\n onBeforeInit\n ),\n ...MATERIAL_BASIC_PARAMS,\n });\n\n return mat;\n }, [onBeforeInit]) as AlphaBlendingMaterial;\n\n const mesh = useAddObject(scene, geometry, material, THREE.Mesh);\n\n return { material, mesh };\n};\n","import * as THREE from \"three\";\nimport { useMesh } from \"./useMesh\";\nimport { useCamera } from \"../../../utils/useCamera\";\nimport { useCallback, useMemo } from \"react\";\nimport { RootState } from \"@react-three/fiber\";\nimport {\n CustomParams,\n setCustomUniform,\n setUniform,\n} from \"../../../utils/setUniforms\";\nimport { HooksProps, HooksReturn } from \"../../types\";\nimport { useParams } from \"../../../utils/useParams\";\nimport { useSingleFBO } from \"../../../utils/useSingleFBO\";\nimport { getDpr } from \"../../../utils/getDpr\";\nimport { DEFAULT_TEXTURE } from \"../../../libs/constants\";\n\nexport type AlphaBlendingParams = {\n /** default : `THREE.Texture()` */\n texture?: THREE.Texture;\n /** alpha map , default : `THREE.Texture()` */\n map?: THREE.Texture;\n};\n\nexport type AlphaBlendingObject = {\n scene: THREE.Scene;\n mesh: THREE.Mesh;\n material: THREE.Material;\n camera: THREE.Camera;\n renderTarget: THREE.WebGLRenderTarget;\n output: THREE.Texture;\n};\n\nexport const ALPHABLENDING_PARAMS: AlphaBlendingParams = Object.freeze({\n texture: DEFAULT_TEXTURE,\n map: DEFAULT_TEXTURE,\n});\n\n/**\n * @link https://github.com/FunTechInc/use-shader-fx?tab=readme-ov-file#usage\n */\nexport const useAlphaBlending = ({\n size,\n dpr,\n renderTargetOptions,\n isSizeUpdate,\n onBeforeInit,\n}: HooksProps): HooksReturn<\n AlphaBlendingParams,\n AlphaBlendingObject,\n CustomParams\n> => {\n const _dpr = getDpr(dpr);\n\n const scene = useMemo(() => new THREE.Scene(), []);\n const { material, mesh } = useMesh({\n scene,\n size,\n onBeforeInit,\n });\n const camera = useCamera(size);\n\n const [renderTarget, updateRenderTarget] = useSingleFBO({\n scene,\n camera,\n size,\n dpr: _dpr.fbo,\n isSizeUpdate,\n ...renderTargetOptions,\n });\n\n const [params, setParams] =\n useParams(ALPHABLENDING_PARAMS);\n\n const updateValue = setUniform(material);\n const updateCustomValue = setCustomUniform(material);\n\n const updateParams = useCallback(\n (newParams?: AlphaBlendingParams, customParams?: CustomParams) => {\n setParams(newParams);\n updateCustomValue(customParams);\n },\n [setParams, updateCustomValue]\n );\n\n const updateFx = useCallback(\n (\n rootState: RootState,\n newParams?: AlphaBlendingParams,\n customParams?: CustomParams\n ) => {\n const { gl } = rootState;\n\n updateParams(newParams, customParams);\n\n updateValue(\"uTexture\", params.texture!);\n updateValue(\"uMap\", params.map!);\n\n return updateRenderTarget(gl);\n },\n [updateValue, updateRenderTarget, params, updateParams]\n );\n\n return [\n updateFx,\n updateParams,\n {\n scene: scene,\n mesh: mesh,\n material: material,\n camera: camera,\n renderTarget: renderTarget,\n output: renderTarget.texture,\n },\n ];\n};\n","#usf ","precision highp float;\n\nvarying vec2 vUv;\nuniform sampler2D u_texture;\nuniform float u_brightness;\nuniform float u_saturation;\n\n#usf \n\n#usf \n\nvoid main() {\n\tvec4 tex = texture2D(u_texture, vUv);\n\tvec3 hsv = rgb2hsv(tex.rgb);\n\thsv.y *= u_saturation;\n\thsv.z *= u_brightness;\n\tvec3 final = hsv2rgb(hsv);\n\tgl_FragColor = vec4(final, tex.a);\n}\n\n","import * as THREE from \"three\";\nimport vertexShader from \"./shader/main.vert\";\nimport fragmentShader from \"./shader/main.frag\";\nimport { useMemo } from \"react\";\nimport { useAddObject } from \"../../../utils/useAddObject\";\nimport { MaterialProps, Size } from \"../../types\";\nimport {\n MATERIAL_BASIC_PARAMS,\n DEFAULT_TEXTURE,\n} from \"../../../libs/constants\";\nimport { HSV_PARAMS } from \".\";\nimport { createMaterialParameters } from \"../../../utils/createMaterialParameters\";\n\nexport class HSVMaterial extends THREE.ShaderMaterial {\n uniforms!: {\n u_texture: { value: THREE.Texture };\n u_brightness: { value: number };\n u_saturation: { value: number };\n };\n}\n\nexport const useMesh = ({\n scene,\n onBeforeInit,\n}: {\n scene: THREE.Scene;\n size: Size;\n} & MaterialProps) => {\n const geometry = useMemo(() => new THREE.PlaneGeometry(2, 2), []);\n const material = useMemo(() => {\n const mat = new THREE.ShaderMaterial({\n ...createMaterialParameters(\n {\n uniforms: {\n u_texture: { value: DEFAULT_TEXTURE },\n u_brightness: { value: HSV_PARAMS.brightness },\n u_saturation: { value: HSV_PARAMS.saturation },\n },\n vertexShader: vertexShader,\n fragmentShader: fragmentShader,\n },\n onBeforeInit\n ),\n ...MATERIAL_BASIC_PARAMS,\n });\n return mat;\n }, [onBeforeInit]) as HSVMaterial;\n const mesh = useAddObject(scene, geometry, material, THREE.Mesh);\n return { material, mesh };\n};\n","import * as THREE from \"three\";\nimport { useMesh } from \"./useMesh\";\nimport { useCamera } from \"../../../utils/useCamera\";\nimport { useCallback, useMemo } from \"react\";\nimport { RootState } from \"@react-three/fiber\";\nimport {\n CustomParams,\n setCustomUniform,\n setUniform,\n} from \"../../../utils/setUniforms\";\nimport { HooksProps, HooksReturn } from \"../../types\";\nimport { useParams } from \"../../../utils/useParams\";\nimport { useSingleFBO } from \"../../../utils/useSingleFBO\";\nimport { getDpr } from \"../../../utils/getDpr\";\nimport { DEFAULT_TEXTURE } from \"../../../libs/constants\";\n\nexport type HSVParams = {\n /** default : `THREE.Texture()` */\n texture?: THREE.Texture;\n /** default : `1` */\n brightness?: number;\n /** default : `1` */\n saturation?: number;\n};\n\nexport type HSVObject = {\n scene: THREE.Scene;\n mesh: THREE.Mesh;\n material: THREE.Material;\n camera: THREE.Camera;\n renderTarget: THREE.WebGLRenderTarget;\n output: THREE.Texture;\n};\n\nexport const HSV_PARAMS: HSVParams = Object.freeze({\n texture: DEFAULT_TEXTURE,\n brightness: 1,\n saturation: 1,\n});\n\n/**\n * @link https://github.com/FunTechInc/use-shader-fx?tab=readme-ov-file#usage\n */\nexport const useHSV = ({\n size,\n dpr,\n renderTargetOptions,\n isSizeUpdate,\n onBeforeInit,\n}: HooksProps): HooksReturn => {\n const _dpr = getDpr(dpr);\n\n const scene = useMemo(() => new THREE.Scene(), []);\n const { material, mesh } = useMesh({\n scene,\n size,\n onBeforeInit,\n });\n const camera = useCamera(size);\n\n const [renderTarget, updateRenderTarget] = useSingleFBO({\n scene,\n camera,\n size,\n dpr: _dpr.fbo,\n isSizeUpdate,\n ...renderTargetOptions,\n });\n\n const [params, setParams] = useParams(HSV_PARAMS);\n\n const updateValue = setUniform(material);\n const updateCustomValue = setCustomUniform(material);\n\n const updateParams = useCallback(\n (newParams?: HSVParams, customParams?: CustomParams) => {\n setParams(newParams);\n updateCustomValue(customParams);\n },\n [setParams, updateCustomValue]\n );\n\n const updateFx = useCallback(\n (\n rootState: RootState,\n newParams?: HSVParams,\n customParams?: CustomParams\n ) => {\n const { gl } = rootState;\n\n updateParams(newParams, customParams);\n\n updateValue(\"u_texture\", params.texture!);\n updateValue(\"u_brightness\", params.brightness!);\n updateValue(\"u_saturation\", params.saturation!);\n\n return updateRenderTarget(gl);\n },\n [updateValue, updateRenderTarget, params, updateParams]\n );\n\n return [\n updateFx,\n updateParams,\n {\n scene: scene,\n mesh: mesh,\n material: material,\n camera: camera,\n renderTarget: renderTarget,\n output: renderTarget.texture,\n },\n ];\n};\n","#usf ","precision highp float;\n\nvarying vec2 vUv;\nuniform vec2 uResolution;\nuniform vec2 uTextureResolution;\nuniform sampler2D uTexture;\n\nvoid main() {\n\t#usf \n\t\n\tgl_FragColor = texture2D(uTexture, uv);\n}\n\n","import { useMemo } from \"react\";\nimport * as THREE from \"three\";\nimport { useResolution } from \"../../../utils/useResolution\";\nimport vertexShader from \"./shader/main.vert\";\nimport fragmentShader from \"./shader/main.frag\";\nimport { setUniform } from \"../../../utils/setUniforms\";\nimport { useAddObject } from \"../../../utils/useAddObject\";\nimport { MaterialProps, Size } from \"../../types\";\nimport {\n MATERIAL_BASIC_PARAMS,\n DEFAULT_TEXTURE,\n} from \"../../../libs/constants\";\nimport { createMaterialParameters } from \"../../../utils/createMaterialParameters\";\n\nexport class FxTextureMaterial extends THREE.ShaderMaterial {\n uniforms!: {\n uResolution: { value: THREE.Vector2 };\n uTextureResolution: { value: THREE.Vector2 };\n uTexture: { value: THREE.Texture };\n };\n}\n\nexport const useMesh = ({\n scene,\n size,\n dpr,\n onBeforeInit,\n}: {\n scene: THREE.Scene;\n size: Size;\n dpr: number | false;\n} & MaterialProps) => {\n const geometry = useMemo(() => new THREE.PlaneGeometry(2, 2), []);\n const material = useMemo(() => {\n const mat = new THREE.ShaderMaterial({\n ...createMaterialParameters(\n {\n uniforms: {\n uResolution: { value: new THREE.Vector2() },\n uTextureResolution: { value: new THREE.Vector2() },\n uTexture: { value: DEFAULT_TEXTURE },\n },\n vertexShader: vertexShader,\n fragmentShader: fragmentShader,\n },\n onBeforeInit\n ),\n ...MATERIAL_BASIC_PARAMS,\n });\n return mat;\n }, [onBeforeInit]) as FxTextureMaterial;\n\n const resolution = useResolution(size, dpr);\n setUniform(material)(\"uResolution\", resolution.clone());\n\n const mesh = useAddObject(scene, geometry, material, THREE.Mesh);\n\n return { material, mesh };\n};\n","import * as THREE from \"three\";\nimport { useCallback, useMemo } from \"react\";\nimport { useMesh } from \"./useMesh\";\nimport { useCamera } from \"../../../utils/useCamera\";\nimport { RootState } from \"@react-three/fiber\";\nimport { useSingleFBO } from \"../../../utils/useSingleFBO\";\nimport {\n CustomParams,\n setCustomUniform,\n setUniform,\n} from \"../../../utils/setUniforms\";\nimport { HooksProps, HooksReturn } from \"../../types\";\nimport { useParams } from \"../../../utils/useParams\";\nimport { getDpr } from \"../../../utils/getDpr\";\nimport { DEFAULT_TEXTURE } from \"../../../libs/constants\";\n\nexport type CoverTextureParams = {\n /** Textures that you want to display exactly on the screen , default : `THREE.Texture()` */\n texture?: THREE.Texture;\n};\n\nexport type CoverTextureObject = {\n scene: THREE.Scene;\n mesh: THREE.Mesh;\n material: THREE.Material;\n camera: THREE.Camera;\n renderTarget: THREE.WebGLRenderTarget;\n output: THREE.Texture;\n};\n\nexport const COVERTEXTURE_PARAMS: CoverTextureParams = Object.freeze({\n texture: DEFAULT_TEXTURE,\n});\n\n/**\n * @link https://github.com/FunTechInc/use-shader-fx?tab=readme-ov-file#usage\n */\nexport const useCoverTexture = ({\n size,\n dpr,\n renderTargetOptions,\n isSizeUpdate,\n onBeforeInit,\n}: HooksProps): HooksReturn<\n CoverTextureParams,\n CoverTextureObject,\n CustomParams\n> => {\n const _dpr = getDpr(dpr);\n\n const scene = useMemo(() => new THREE.Scene(), []);\n const { material, mesh } = useMesh({\n scene,\n size,\n dpr: _dpr.shader,\n onBeforeInit,\n });\n const camera = useCamera(size);\n const [renderTarget, updateRenderTarget] = useSingleFBO({\n scene,\n camera,\n dpr: _dpr.fbo,\n size,\n isSizeUpdate,\n ...renderTargetOptions,\n });\n\n const [params, setParams] =\n useParams(COVERTEXTURE_PARAMS);\n\n const updateValue = setUniform(material);\n const updateCustomValue = setCustomUniform(material);\n\n const updateParams = useCallback(\n (newParams?: CoverTextureParams, customParams?: CustomParams) => {\n setParams(newParams);\n updateCustomValue(customParams);\n },\n [setParams, updateCustomValue]\n );\n\n const updateFx = useCallback(\n (\n rootState: RootState,\n newParams?: CoverTextureParams,\n customParams?: CustomParams\n ) => {\n const { gl } = rootState;\n\n updateParams(newParams, customParams);\n\n updateValue(\"uTexture\", params.texture!);\n updateValue(\"uTextureResolution\", [\n params.texture!?.source?.data?.width || 0,\n params.texture!?.source?.data?.height || 0,\n ]);\n\n return updateRenderTarget(gl);\n },\n [updateRenderTarget, updateValue, params, updateParams]\n );\n return [\n updateFx,\n updateParams,\n {\n scene: scene,\n mesh: mesh,\n material: material,\n camera: camera,\n renderTarget: renderTarget,\n output: renderTarget.texture,\n },\n ];\n};\n","#usf ","precision highp float;\n\nvarying vec2 vUv;\nuniform sampler2D uTexture;\nuniform vec2 uResolution;\nuniform float uBlurSize;\n\nvoid main() {\n\tvec2 uv = vUv;\t\n\tvec2 perDivSize = uBlurSize / uResolution;\n\n\t// calc average color value from adjacent point\n\tvec4 outColor = vec4(\n\t\ttexture2D(uTexture, uv + perDivSize * vec2(-1.0, -1.0)) +\n\t\ttexture2D(uTexture, uv + perDivSize * vec2(0.0, -1.0)) + \n\t\ttexture2D(uTexture, uv + perDivSize * vec2(1.0, -1.0)) + \n\t\ttexture2D(uTexture, uv + perDivSize * vec2(-1.0, 0.0)) + \n\t\ttexture2D(uTexture, uv + perDivSize * vec2(0.0, 0.0)) + \n\t\ttexture2D(uTexture, uv + perDivSize * vec2(1.0, 0.0)) + \n\t\ttexture2D(uTexture, uv + perDivSize * vec2(-1.0, 1.0)) + \n\t\ttexture2D(uTexture, uv + perDivSize * vec2(0.0, 1.0)) + \n\t\ttexture2D(uTexture, uv + perDivSize * vec2(1.0, 1.0))\n\t\t) / 9.0;\n\t\n\tgl_FragColor = outColor;\n}","import { useMemo } from \"react\";\nimport * as THREE from \"three\";\nimport vertexShader from \"./shader/main.vert\";\nimport fragmentShader from \"./shader/main.frag\";\nimport { useAddObject } from \"../../../utils/useAddObject\";\nimport { SIMPLEBLUR_PARAMS } from \".\";\nimport { MaterialProps } from \"../../types\";\nimport {\n MATERIAL_BASIC_PARAMS,\n DEFAULT_TEXTURE,\n} from \"../../../libs/constants\";\nimport { createMaterialParameters } from \"../../../utils/createMaterialParameters\";\n\nexport class SampleMaterial extends THREE.ShaderMaterial {\n uniforms!: {\n uTexture: { value: THREE.Texture };\n uResolution: { value: THREE.Vector2 };\n uBlurSize: { value: number };\n };\n}\n\nexport const useMesh = ({\n scene,\n onBeforeInit,\n}: { scene: THREE.Scene } & MaterialProps) => {\n const geometry = useMemo(() => new THREE.PlaneGeometry(2, 2), []);\n const material = useMemo(() => {\n const mat = new THREE.ShaderMaterial({\n ...createMaterialParameters(\n {\n uniforms: {\n uTexture: { value: DEFAULT_TEXTURE },\n uResolution: { value: new THREE.Vector2(0, 0) },\n uBlurSize: { value: SIMPLEBLUR_PARAMS.blurSize },\n },\n vertexShader: vertexShader,\n fragmentShader: fragmentShader,\n },\n onBeforeInit\n ),\n ...MATERIAL_BASIC_PARAMS,\n });\n\n return mat;\n }, [onBeforeInit]) as SampleMaterial;\n\n const mesh = useAddObject(scene, geometry, material, THREE.Mesh);\n\n return { material, mesh };\n};\n","import { useCallback, useMemo } from \"react\";\nimport * as THREE from \"three\";\nimport { RootState } from \"@react-three/fiber\";\nimport { useMesh } from \"./useMesh\";\nimport { useCamera } from \"../../../utils/useCamera\";\nimport { useDoubleFBO, DoubleRenderTarget } from \"../../../utils/useDoubleFBO\";\nimport {\n CustomParams,\n setCustomUniform,\n setUniform,\n} from \"../../../utils/setUniforms\";\nimport { useParams } from \"../../../utils/useParams\";\nimport type { HooksProps, HooksReturn } from \"../../types\";\nimport { getDpr } from \"../../../utils/getDpr\";\nimport { UseFboProps } from \"../../..\";\nimport { DEFAULT_TEXTURE } from \"../../../libs/constants\";\n\nexport type SimpleBlurParams = {\n /** Make this texture blur , default : `THREE.Texture()` */\n texture?: THREE.Texture;\n /** blurSize, default : `3` */\n blurSize?: number;\n /** blurPower, affects performance default : `5` */\n blurPower?: number;\n};\n\nexport type SimpleBlurObject = {\n scene: THREE.Scene;\n mesh: THREE.Mesh;\n material: THREE.Material;\n camera: THREE.Camera;\n renderTarget: DoubleRenderTarget;\n output: THREE.Texture;\n};\n\nexport const SIMPLEBLUR_PARAMS: SimpleBlurParams = Object.freeze({\n texture: DEFAULT_TEXTURE,\n blurSize: 3,\n blurPower: 5,\n});\n\n/**\n * @link https://github.com/FunTechInc/use-shader-fx?tab=readme-ov-file#usage\n */\nexport const useSimpleBlur = ({\n size,\n dpr,\n renderTargetOptions,\n isSizeUpdate,\n onBeforeInit,\n}: HooksProps): HooksReturn<\n SimpleBlurParams,\n SimpleBlurObject,\n CustomParams\n> => {\n const _dpr = getDpr(dpr);\n const scene = useMemo(() => new THREE.Scene(), []);\n const { material, mesh } = useMesh({ scene, onBeforeInit });\n const camera = useCamera(size);\n\n const fboProps = useMemo(\n () => ({\n scene,\n camera,\n size,\n dpr: _dpr.fbo,\n isSizeUpdate,\n ...renderTargetOptions,\n }),\n [scene, camera, size, _dpr.fbo, isSizeUpdate, renderTargetOptions]\n ) as UseFboProps;\n\n const [renderTarget, updateTempTexture] = useDoubleFBO(fboProps);\n const [params, setParams] = useParams(SIMPLEBLUR_PARAMS);\n\n const updateValue = setUniform(material);\n const updateCustomValue = setCustomUniform(material);\n\n const updateParams = useCallback(\n (newParams?: SimpleBlurParams, customParams?: CustomParams) => {\n setParams(newParams);\n updateCustomValue(customParams);\n },\n [setParams, updateCustomValue]\n );\n\n const updateFx = useCallback(\n (\n rootState: RootState,\n newParams?: SimpleBlurParams,\n customParams?: CustomParams\n ) => {\n const { gl } = rootState;\n\n updateParams(newParams, customParams);\n\n updateValue(\"uTexture\", params.texture!);\n updateValue(\"uResolution\", [\n params.texture!?.source?.data?.width || 0,\n params.texture!?.source?.data?.height || 0,\n ]);\n updateValue(\"uBlurSize\", params.blurSize!);\n\n let _tempTexture: THREE.Texture = updateTempTexture(gl);\n\n for (let i = 0; i < params.blurPower!; i++) {\n updateValue(\"uTexture\", _tempTexture);\n _tempTexture = updateTempTexture(gl);\n }\n\n return _tempTexture;\n },\n [updateTempTexture, updateValue, params, updateParams]\n );\n\n return [\n updateFx,\n updateParams,\n {\n scene: scene,\n mesh: mesh,\n material: material,\n camera: camera,\n renderTarget: renderTarget,\n output: renderTarget.read.texture,\n },\n ];\n};\n","#usf ","precision highp float;\n\nvarying vec2 vUv;\nuniform sampler2D uTexture;\nuniform sampler2D uBackbuffer;\nuniform vec2 uBegin;\nuniform vec2 uEnd;\nuniform float uStrength;\n\nvoid main() {\n\tvec2 uv = vUv;\t\n\tvec4 current = texture2D(uTexture, uv + uBegin*.1);\n\tvec4 back = texture2D(uBackbuffer, uv + uEnd*.1);\n\tvec4 mixed = mix(current,back,uStrength);\n\tgl_FragColor = mixed;\n}","import { useMemo } from \"react\";\nimport * as THREE from \"three\";\nimport vertexShader from \"./shader/main.vert\";\nimport fragmentShader from \"./shader/main.frag\";\nimport { useAddObject } from \"../../../utils/useAddObject\";\nimport { MOTIONBLUR_PARAMS } from \".\";\nimport { MaterialProps } from \"../../types\";\nimport {\n MATERIAL_BASIC_PARAMS,\n DEFAULT_TEXTURE,\n} from \"../../../libs/constants\";\nimport { createMaterialParameters } from \"../../../utils/createMaterialParameters\";\n\nexport class MotionBlurMaterial extends THREE.ShaderMaterial {\n uniforms!: {\n uTexture: { value: THREE.Texture };\n uBackbuffer: { value: THREE.Texture };\n uBegin: { value: THREE.Vector2 };\n uEnd: { value: THREE.Vector2 };\n uStrength: { value: number };\n };\n}\n\nexport const useMesh = ({\n scene,\n onBeforeInit,\n}: { scene: THREE.Scene } & MaterialProps) => {\n const geometry = useMemo(() => new THREE.PlaneGeometry(2, 2), []);\n const material = useMemo(() => {\n const mat = new THREE.ShaderMaterial({\n ...createMaterialParameters(\n {\n uniforms: {\n uTexture: { value: DEFAULT_TEXTURE },\n uBackbuffer: { value: DEFAULT_TEXTURE },\n uBegin: { value: MOTIONBLUR_PARAMS.begin },\n uEnd: { value: MOTIONBLUR_PARAMS.end },\n uStrength: { value: MOTIONBLUR_PARAMS.strength },\n },\n vertexShader: vertexShader,\n fragmentShader: fragmentShader,\n },\n onBeforeInit\n ),\n ...MATERIAL_BASIC_PARAMS,\n });\n return mat;\n }, [onBeforeInit]) as MotionBlurMaterial;\n\n const mesh = useAddObject(scene, geometry, material, THREE.Mesh);\n\n return { material, mesh };\n};\n","import { useCallback, useMemo } from \"react\";\nimport * as THREE from \"three\";\nimport { RootState } from \"@react-three/fiber\";\nimport { useMesh } from \"./useMesh\";\nimport { useCamera } from \"../../../utils/useCamera\";\nimport { useDoubleFBO, DoubleRenderTarget } from \"../../../utils/useDoubleFBO\";\nimport {\n CustomParams,\n setCustomUniform,\n setUniform,\n} from \"../../../utils/setUniforms\";\nimport { useParams } from \"../../../utils/useParams\";\nimport type { HooksProps, HooksReturn } from \"../../types\";\nimport { getDpr } from \"../../../utils/getDpr\";\nimport { UseFboProps } from \"../../..\";\nimport { DEFAULT_TEXTURE } from \"../../../libs/constants\";\n\nexport type MotionBlurParams = {\n /** Make this texture blur, default : `THREE.Texture()` */\n texture?: THREE.Texture;\n /** motion begin, default : `THREE.Vector2(0, 0)` */\n begin?: THREE.Vector2;\n /** motion end, default : `THREE.Vector2(0, 0)` */\n end?: THREE.Vector2;\n /** motion strength, default : `0.9` */\n strength?: number;\n};\n\nexport type MotionBlurObject = {\n scene: THREE.Scene;\n mesh: THREE.Mesh;\n material: THREE.Material;\n camera: THREE.Camera;\n renderTarget: DoubleRenderTarget;\n output: THREE.Texture;\n};\n\nexport const MOTIONBLUR_PARAMS: MotionBlurParams = Object.freeze({\n texture: DEFAULT_TEXTURE,\n begin: new THREE.Vector2(0, 0),\n end: new THREE.Vector2(0, 0),\n strength: 0.9,\n});\n\n/**\n * @link https://github.com/FunTechInc/use-shader-fx?tab=readme-ov-file#usage\n */\nexport const useMotionBlur = ({\n size,\n dpr,\n renderTargetOptions,\n isSizeUpdate,\n onBeforeInit,\n}: HooksProps): HooksReturn<\n MotionBlurParams,\n MotionBlurObject,\n CustomParams\n> => {\n const _dpr = getDpr(dpr);\n\n const scene = useMemo(() => new THREE.Scene(), []);\n const { material, mesh } = useMesh({ scene, onBeforeInit });\n const camera = useCamera(size);\n\n const fboProps = useMemo(\n () => ({\n scene,\n camera,\n size,\n dpr: _dpr.fbo,\n isSizeUpdate,\n ...renderTargetOptions,\n }),\n [scene, camera, size, _dpr.fbo, isSizeUpdate, renderTargetOptions]\n ) as UseFboProps;\n\n const [renderTarget, updateRenderTarget] = useDoubleFBO(fboProps);\n\n const [params, setParams] = useParams(MOTIONBLUR_PARAMS);\n\n const updateValue = setUniform(material);\n const updateCustomValue = setCustomUniform(material);\n\n const updateParams = useCallback(\n (newParams?: MotionBlurParams, customParams?: CustomParams) => {\n setParams(newParams);\n updateCustomValue(customParams);\n },\n [setParams, updateCustomValue]\n );\n\n const updateFx = useCallback(\n (\n rootState: RootState,\n newParams?: MotionBlurParams,\n customParams?: CustomParams\n ) => {\n const { gl } = rootState;\n\n updateParams(newParams, customParams);\n\n updateValue(\"uTexture\", params.texture!);\n updateValue(\"uBegin\", params.begin!);\n updateValue(\"uEnd\", params.end!);\n updateValue(\"uStrength\", params.strength!);\n\n return updateRenderTarget(gl, ({ read }) => {\n updateValue(\"uBackbuffer\", read);\n });\n },\n [updateRenderTarget, updateValue, updateParams, params]\n );\n\n return [\n updateFx,\n updateParams,\n {\n scene: scene,\n mesh: mesh,\n material: material,\n camera: camera,\n renderTarget: renderTarget,\n output: renderTarget.read.texture,\n },\n ];\n};\n","#usf ","precision highp float;\n\nvarying vec2 vUv;\nuniform float uProgress;\nuniform float uStrength;\nuniform float uWidth;\nuniform vec2 uEpicenter;\nuniform int uMode;\n\nfloat PI = 3.141592653589;\n\nvoid main() {\n\n\tvec2 uv = vUv;\n\n\tfloat progress = min(uProgress, 1.0);\n\tfloat progressFactor = sin(progress * PI);\n\n\tfloat border = progress - progress * progressFactor * uWidth;\n\tfloat blur = uStrength * progressFactor;\n\t\n\t// 0 ~ 1\n\tvec2 normalizeCenter = (uEpicenter + 1.0) / 2.0;\n\n\t// 0:center 1:horizontal 2:vertical\n\tfloat dist = uMode == 0 ? length(uv - normalizeCenter) : uMode == 1 ? length(uv.x - normalizeCenter.x) : length(uv.y - normalizeCenter.y);\n\n\t// Calculate the maximum distance to the four corners of the screen\n\tfloat maxDistance = max(\n\t\tlength(vec2(0.0, 0.0) - normalizeCenter),\n\t\tmax(\n\t\t\t\tlength(vec2(1.0, 0.0) - normalizeCenter),\n\t\t\t\tmax(\n\t\t\t\t\tlength(vec2(0.0, 1.0) - normalizeCenter),\n\t\t\t\t\tlength(vec2(1.0, 1.0) - normalizeCenter)\n\t\t\t\t)\n\t\t)\n\t);\n\n\t// Scale distance so that waves extend to the edge of the screen\n\tdist = maxDistance > 0.0 ? dist / maxDistance : dist;\n\n\tvec3 color = vec3(smoothstep(border - blur, border, dist) -\n smoothstep(progress, progress + blur, dist));\n\t\n\t// Ensure color is 0 when progress is 0,1\n\tcolor *= progressFactor;\n\n\tgl_FragColor = vec4(color, 1.0);\n}\n\n","import * as THREE from \"three\";\nimport { useMemo } from \"react\";\nimport vertexShader from \"./shader/main.vert\";\nimport fragmentShader from \"./shader/main.frag\";\nimport { WAVE_PARAMS } from \".\";\nimport { useAddObject } from \"../../../utils/useAddObject\";\nimport { MaterialProps } from \"../../types\";\nimport { MATERIAL_BASIC_PARAMS } from \"../../../libs/constants\";\nimport { createMaterialParameters } from \"../../../utils/createMaterialParameters\";\n\nexport class WaveMaterial extends THREE.ShaderMaterial {\n uniforms!: {\n uEpicenter: { value: THREE.Vector2 };\n uProgress: { value: number };\n uStrength: { value: number };\n uWidth: { value: number };\n uMode: { value: number };\n };\n}\n\nexport const useMesh = ({\n scene,\n onBeforeInit,\n}: { scene: THREE.Scene } & MaterialProps) => {\n const geometry = useMemo(() => new THREE.PlaneGeometry(2, 2), []);\n const material = useMemo(() => {\n const mat = new THREE.ShaderMaterial({\n ...createMaterialParameters(\n {\n uniforms: {\n uEpicenter: { value: WAVE_PARAMS.epicenter },\n uProgress: { value: WAVE_PARAMS.progress },\n uStrength: { value: WAVE_PARAMS.strength },\n uWidth: { value: WAVE_PARAMS.width },\n uMode: { value: 0 },\n },\n vertexShader: vertexShader,\n fragmentShader: fragmentShader,\n },\n onBeforeInit\n ),\n ...MATERIAL_BASIC_PARAMS,\n });\n\n return mat;\n }, [onBeforeInit]) as WaveMaterial;\n\n const mesh = useAddObject(scene, geometry, material, THREE.Mesh);\n\n return { material, mesh };\n};\n","import * as THREE from \"three\";\nimport { useCallback, useMemo } from \"react\";\nimport { useMesh } from \"./useMesh\";\nimport { RootState } from \"@react-three/fiber\";\nimport { useCamera } from \"../../../utils/useCamera\";\nimport { useSingleFBO } from \"../../../utils/useSingleFBO\";\nimport {\n CustomParams,\n setCustomUniform,\n setUniform,\n} from \"../../../utils/setUniforms\";\nimport { useParams } from \"../../../utils/useParams\";\nimport { HooksProps, HooksReturn } from \"../../types\";\nimport { getDpr } from \"../../../utils/getDpr\";\n\nexport type WaveParams = {\n /** -1.0 ~ 1.0 , default : `vec2(0.0,0.0)` */\n epicenter?: THREE.Vector2;\n /** 0.0 ~ 1.0 , default : `0.0` */\n progress?: number;\n /** default : `0.0` */\n width?: number;\n /** default : `0.0` */\n strength?: number;\n /** default : `center` */\n mode?: \"center\" | \"horizontal\" | \"vertical\";\n};\n\nexport type WaveObject = {\n scene: THREE.Scene;\n mesh: THREE.Mesh;\n material: THREE.Material;\n camera: THREE.Camera;\n renderTarget: THREE.WebGLRenderTarget;\n output: THREE.Texture;\n};\n\nexport const WAVE_PARAMS: WaveParams = Object.freeze({\n epicenter: new THREE.Vector2(0.0, 0.0),\n progress: 0.0,\n width: 0.0,\n strength: 0.0,\n mode: \"center\",\n});\n\n/**\n * @link https://github.com/FunTechInc/use-shader-fx\n */\nexport const useWave = ({\n size,\n dpr,\n renderTargetOptions,\n isSizeUpdate,\n onBeforeInit,\n}: HooksProps): HooksReturn => {\n const _dpr = getDpr(dpr);\n const scene = useMemo(() => new THREE.Scene(), []);\n const { material, mesh } = useMesh({ scene, onBeforeInit });\n const camera = useCamera(size);\n const [renderTarget, updateRenderTarget] = useSingleFBO({\n scene,\n camera,\n size,\n dpr: _dpr.fbo,\n isSizeUpdate,\n ...renderTargetOptions,\n });\n\n const [params, setParams] = useParams(WAVE_PARAMS);\n\n const updateValue = setUniform(material);\n const updateCustomValue = setCustomUniform(material);\n\n const updateParams = useCallback(\n (newParams?: WaveParams, customParams?: CustomParams) => {\n setParams(newParams);\n updateCustomValue(customParams);\n },\n [setParams, updateCustomValue]\n );\n\n const updateFx = useCallback(\n (\n rootState: RootState,\n newParams?: WaveParams,\n customParams?: CustomParams\n ) => {\n const { gl } = rootState;\n\n updateParams(newParams, customParams);\n\n updateValue(\"uEpicenter\", params.epicenter!);\n updateValue(\"uProgress\", params.progress!);\n updateValue(\"uWidth\", params.width!);\n updateValue(\"uStrength\", params.strength!);\n updateValue(\n \"uMode\",\n params.mode! === \"center\"\n ? 0\n : params.mode! === \"horizontal\"\n ? 1\n : 2\n );\n\n return updateRenderTarget(gl);\n },\n [updateRenderTarget, updateValue, params, updateParams]\n );\n\n return [\n updateFx,\n updateParams,\n {\n scene: scene,\n mesh: mesh,\n material: material,\n camera: camera,\n renderTarget: renderTarget,\n output: renderTarget.texture,\n },\n ];\n};\n","#usf ","precision highp float;\nvarying vec2 vUv;\n\nuniform sampler2D u_texture;\nuniform vec2 u_resolution;\nuniform vec3 u_keyColor;\nuniform float u_similarity;\nuniform float u_smoothness;\nuniform float u_spill;\n\nuniform vec4 u_color;\nuniform float u_contrast;\nuniform float u_brightness;\nuniform float u_gamma;\n\n// From https://github.com/libretro/glsl-shaders/blob/master/nnedi3/shaders/rgb-to-yuv.glsl\nvec2 RGBtoUV(vec3 rgb) {\n return vec2(\n rgb.r * -0.169 + rgb.g * -0.331 + rgb.b * 0.5 + 0.5,\n rgb.r * 0.5 + rgb.g * -0.419 + rgb.b * -0.081 + 0.5\n );\n}\nfloat getChromeDist(vec3 texColor){\n\tfloat chromaDist = distance(RGBtoUV(texColor), RGBtoUV(u_keyColor));\n\treturn chromaDist;\n}\n\nfloat getBoxFilteredChromaDist(vec3 rgb, vec2 uv)\n{\n\tvec2 pixel_size = vec2(1.) / u_resolution;\n\tvec2 h_pixel_size = pixel_size / 2.0;\n\tvec2 point_0 = vec2(pixel_size.x, h_pixel_size.y);\n\tvec2 point_1 = vec2(h_pixel_size.x, -pixel_size.y);\n\tfloat distVal = getChromeDist(texture2D(u_texture,uv-point_0).rgb);\n\tdistVal += getChromeDist(texture2D(u_texture,uv+point_0).rgb);\n\tdistVal += getChromeDist(texture2D(u_texture,uv-point_1).rgb);\n\tdistVal += getChromeDist(texture2D(u_texture,uv+point_1).rgb);\n\tdistVal *= 2.0;\n\tdistVal += getChromeDist(rgb);\n\treturn distVal / 9.0;\n}\n\nvec4 CalcColor(vec4 rgba)\n{\n\treturn vec4(pow(rgba.rgb, vec3(u_gamma, u_gamma, u_gamma)) * u_contrast + u_brightness, rgba.a);\n}\n\nvoid main() {\n\n\tvec2 uv = vUv;\n\n\tvec4 texColor = texture2D(u_texture, uv);\n\ttexColor.rgb *= (texColor.a > 0.) ? (1. / texColor.a) : 0.;\n\n\tfloat chromaDist = getBoxFilteredChromaDist(texColor.rgb,uv);\n\t\n\tfloat baseMask = chromaDist - u_similarity;\n\tfloat fullMask = pow(clamp(baseMask / u_smoothness, 0., 1.), 1.5);\n\t\n\ttexColor.rgba *= u_color;\n\ttexColor.a = fullMask;\n\n\tfloat spillVal = pow(clamp(baseMask / u_spill, 0., 1.), 1.5);\n\tfloat desat = clamp(texColor.r * 0.2126 + texColor.g * 0.7152 + texColor.b * 0.0722, 0., 1.);\n\ttexColor.rgb = mix(vec3(desat, desat, desat), texColor.rgb, spillVal);\n\n\tvec4 finColor = CalcColor(texColor);\n\n\tgl_FragColor = finColor;\n}","import { useMemo } from \"react\";\nimport * as THREE from \"three\";\nimport vertexShader from \"./shader/main.vert\";\nimport fragmentShader from \"./shader/main.frag\";\nimport { setUniform } from \"../../../utils/setUniforms\";\nimport { useResolution } from \"../../../utils/useResolution\";\nimport { useAddObject } from \"../../../utils/useAddObject\";\nimport { MaterialProps, Size } from \"../../types\";\nimport {\n MATERIAL_BASIC_PARAMS,\n DEFAULT_TEXTURE,\n} from \"../../../libs/constants\";\nimport { CHROMAKEY_PARAMS } from \".\";\nimport { createMaterialParameters } from \"../../../utils/createMaterialParameters\";\n\nexport class ChromaKeyMaterial extends THREE.ShaderMaterial {\n uniforms!: {\n u_texture: { value: THREE.Texture };\n u_resolution: { value: THREE.Vector2 };\n u_keyColor: { value: THREE.Color };\n u_similarity: { value: number };\n u_smoothness: { value: number };\n u_spill: { value: number };\n u_color: { value: THREE.Vector4 };\n u_contrast: { value: number };\n u_brightness: { value: number };\n u_gamma: { value: number };\n };\n}\n\nexport const useMesh = ({\n scene,\n size,\n dpr,\n onBeforeInit,\n}: {\n scene: THREE.Scene;\n size: Size;\n dpr: number | false;\n} & MaterialProps) => {\n const geometry = useMemo(() => new THREE.PlaneGeometry(2, 2), []);\n const material = useMemo(() => {\n const mat = new THREE.ShaderMaterial({\n ...createMaterialParameters(\n {\n uniforms: {\n u_texture: { value: DEFAULT_TEXTURE },\n u_resolution: { value: new THREE.Vector2() },\n u_keyColor: { value: CHROMAKEY_PARAMS.color },\n u_similarity: { value: CHROMAKEY_PARAMS.similarity },\n u_smoothness: { value: CHROMAKEY_PARAMS.smoothness },\n u_spill: { value: CHROMAKEY_PARAMS.spill },\n u_color: { value: CHROMAKEY_PARAMS.color },\n u_contrast: { value: CHROMAKEY_PARAMS.contrast },\n u_brightness: { value: CHROMAKEY_PARAMS.brightness },\n u_gamma: { value: CHROMAKEY_PARAMS.gamma },\n },\n vertexShader: vertexShader,\n fragmentShader: fragmentShader,\n },\n onBeforeInit\n ),\n ...MATERIAL_BASIC_PARAMS,\n });\n\n return mat;\n }, [onBeforeInit]) as ChromaKeyMaterial;\n\n const resolution = useResolution(size, dpr);\n setUniform(material)(\"u_resolution\", resolution.clone());\n\n const mesh = useAddObject(scene, geometry, material, THREE.Mesh);\n\n return { material, mesh };\n};\n","import { useCallback, useMemo } from \"react\";\nimport * as THREE from \"three\";\nimport { useMesh } from \"./useMesh\";\nimport { useCamera } from \"../../../utils/useCamera\";\nimport { RootState } from \"@react-three/fiber\";\nimport { useSingleFBO } from \"../../../utils/useSingleFBO\";\nimport {\n CustomParams,\n setCustomUniform,\n setUniform,\n} from \"../../../utils/setUniforms\";\nimport { HooksProps, HooksReturn } from \"../../types\";\nimport { useParams } from \"../../../utils/useParams\";\nimport { getDpr } from \"../../../utils/getDpr\";\nimport { DEFAULT_TEXTURE } from \"../../../libs/constants\";\n\nexport type ChromaKeyParams = {\n /** Process this texture with chroma key , default : `THREE.Texture` */\n texture?: THREE.Texture;\n /** key color for chromakey processing , default: `THREE.Color(0x00ff00)` */\n keyColor?: THREE.Color;\n /** If the similarity with the key color exceeds this value, it becomes transparent. , default : `0.2` */\n similarity?: number;\n /** smoothness , default : `0.1` */\n smoothness?: number;\n /** spill , default : `0.2` */\n spill?: number;\n /** tone correction , default : `THREE.Vector4(1.0, 1.0, 1.0, 1.0)` */\n color?: THREE.Vector4;\n /** contrast , default : `1.0` */\n contrast?: number;\n /** brightness , default : `0.0` */\n brightness?: number;\n /** gamma correction , default : `1.0` */\n gamma?: number;\n};\n\nexport type ChromaKeyObject = {\n scene: THREE.Scene;\n mesh: THREE.Mesh;\n material: THREE.Material;\n camera: THREE.Camera;\n renderTarget: THREE.WebGLRenderTarget;\n output: THREE.Texture;\n};\n\nexport const CHROMAKEY_PARAMS: ChromaKeyParams = Object.freeze({\n texture: DEFAULT_TEXTURE,\n keyColor: new THREE.Color(0x00ff00),\n similarity: 0.2,\n smoothness: 0.1,\n spill: 0.2,\n color: new THREE.Vector4(1.0, 1.0, 1.0, 1.0),\n contrast: 1.0,\n brightness: 0.0,\n gamma: 1.0,\n});\n\n/**\n * @link https://github.com/FunTechInc/use-shader-fx?tab=readme-ov-file#usage\n */\nexport const useChromaKey = ({\n size,\n dpr,\n renderTargetOptions,\n isSizeUpdate,\n onBeforeInit,\n}: HooksProps): HooksReturn => {\n const _dpr = getDpr(dpr);\n\n const scene = useMemo(() => new THREE.Scene(), []);\n const { material, mesh } = useMesh({\n scene,\n size,\n dpr: _dpr.shader,\n onBeforeInit,\n });\n const camera = useCamera(size);\n const [renderTarget, updateRenderTarget] = useSingleFBO({\n scene,\n camera,\n size,\n dpr: _dpr.fbo,\n isSizeUpdate,\n ...renderTargetOptions,\n });\n\n const [params, setParams] = useParams(CHROMAKEY_PARAMS);\n\n const updateValue = setUniform(material);\n const updateCustomValue = setCustomUniform(material);\n\n const updateParams = useCallback(\n (newParams?: ChromaKeyParams, customParams?: CustomParams) => {\n setParams(newParams);\n updateCustomValue(customParams);\n },\n [setParams, updateCustomValue]\n );\n\n const updateFx = useCallback(\n (\n rootState: RootState,\n newParams?: ChromaKeyParams,\n customParams?: CustomParams\n ) => {\n const { gl } = rootState;\n\n updateParams(newParams, customParams);\n\n updateValue(\"u_texture\", params.texture!);\n updateValue(\"u_keyColor\", params.keyColor!);\n updateValue(\"u_similarity\", params.similarity!);\n updateValue(\"u_smoothness\", params.smoothness!);\n updateValue(\"u_spill\", params.spill!);\n updateValue(\"u_color\", params.color!);\n updateValue(\"u_contrast\", params.contrast!);\n updateValue(\"u_brightness\", params.brightness!);\n updateValue(\"u_gamma\", params.gamma!);\n\n return updateRenderTarget(gl);\n },\n [updateRenderTarget, updateValue, params, updateParams]\n );\n\n return [\n updateFx,\n updateParams,\n {\n scene: scene,\n mesh: mesh,\n material: material,\n camera: camera,\n renderTarget: renderTarget,\n output: renderTarget.texture,\n },\n ];\n};\n","precision highp float;\n\nvarying vec2 vUv;\n#usf \n\n#usf \n\nvoid main() {\n\tvec4 usf_Position = vec4(position,1.);\n\tvUv = uv;\n\n\t#usf
\n\t\n\tgl_Position = usf_Position;\n}","precision highp float;\n\nvarying vec2 vUv;\n#usf \n\nuniform sampler2D uTexture;\nuniform sampler2D uBackbuffer;\nuniform float uTime;\nuniform vec2 uPointer;\nuniform vec2 uResolution;\n\n#usf \n\nvoid main() {\n\tvec4 usf_FragColor = vec4(1.);\n\n\t#usf
\n\t\n\tgl_FragColor = usf_FragColor;\n}","import { useMemo } from \"react\";\nimport * as THREE from \"three\";\nimport vertexShader from \"./shader/main.vert\";\nimport fragmentShader from \"./shader/main.frag\";\nimport { useAddObject } from \"../../../utils/useAddObject\";\nimport { MaterialProps, Size } from \"../../types\";\nimport { setUniform, useResolution } from \"../../..\";\nimport {\n MATERIAL_BASIC_PARAMS,\n DEFAULT_TEXTURE,\n} from \"../../../libs/constants\";\nimport { createMaterialParameters } from \"../../../utils/createMaterialParameters\";\n\nexport class BlankMaterial extends THREE.ShaderMaterial {\n uniforms!: {\n uTexture: { value: THREE.Texture };\n uBackbuffer: { value: THREE.Texture };\n uTime: { value: number };\n uPointer: { value: THREE.Vector2 };\n uResolution: { value: THREE.Vector2 };\n };\n}\nexport const useMesh = ({\n scene,\n size,\n dpr,\n onBeforeInit,\n}: {\n scene: THREE.Scene;\n size: Size;\n dpr: number | false;\n} & MaterialProps) => {\n const geometry = useMemo(() => new THREE.PlaneGeometry(2, 2), []);\n const material = useMemo(() => {\n const mat = new THREE.ShaderMaterial({\n ...createMaterialParameters(\n {\n uniforms: {\n uTexture: { value: DEFAULT_TEXTURE },\n uBackbuffer: { value: DEFAULT_TEXTURE },\n uTime: { value: 0 },\n uPointer: { value: new THREE.Vector2() },\n uResolution: { value: new THREE.Vector2() },\n },\n vertexShader: vertexShader,\n fragmentShader: fragmentShader,\n },\n onBeforeInit\n ),\n ...MATERIAL_BASIC_PARAMS,\n });\n return mat;\n }, [onBeforeInit]) as BlankMaterial;\n\n const resolution = useResolution(size, dpr);\n setUniform(material)(\"uResolution\", resolution.clone());\n\n const mesh = useAddObject(scene, geometry, material, THREE.Mesh);\n\n return { material, mesh };\n};\n","import { useCallback, useMemo } from \"react\";\nimport * as THREE from \"three\";\nimport { RootState } from \"@react-three/fiber\";\nimport { BlankMaterial, useMesh } from \"./useMesh\";\nimport { useCamera } from \"../../../utils/useCamera\";\nimport { useDoubleFBO, DoubleRenderTarget } from \"../../../utils/useDoubleFBO\";\nimport {\n CustomParams,\n setCustomUniform,\n setUniform,\n} from \"../../../utils/setUniforms\";\nimport { useParams } from \"../../../utils/useParams\";\nimport type { HooksProps, HooksReturn } from \"../../types\";\nimport { getDpr } from \"../../../utils/getDpr\";\nimport { UseFboProps } from \"../../..\";\nimport { DEFAULT_TEXTURE } from \"../../../libs/constants\";\n\nexport type BlankParams = {\n /** texture, default : `THREE.Texture()` */\n texture?: THREE.Texture;\n /** you can get into the rhythm ♪ , default : `false` */\n beat?: number | false;\n};\n\nexport type BlankObject = {\n scene: THREE.Scene;\n mesh: THREE.Mesh<\n THREE.BufferGeometry,\n BlankMaterial\n >;\n material: BlankMaterial;\n camera: THREE.Camera;\n renderTarget: DoubleRenderTarget;\n output: THREE.Texture;\n};\n\nexport const BLANK_PARAMS: BlankParams = Object.freeze({\n texture: DEFAULT_TEXTURE,\n beat: false,\n});\n\n/**\n * By default, it is a blank canvas with nothing drawn on it. You can customise the shaders using `onBeforeCompile`.\n * Fragment shaders have `uTexture`,`uBackbuffer`,`uTime`,`uPointer` and `uResolution` as default uniforms.\n *\n * ※ `usf_FragColor` overrides `gl_FragColor`\n *\n * ※ `usf_Position` overrides `gl_Position`\n * @link https://github.com/FunTechInc/use-shader-fx?tab=readme-ov-file#usage\n */\nexport const useBlank = ({\n size,\n dpr,\n renderTargetOptions,\n isSizeUpdate,\n onBeforeInit,\n}: HooksProps): HooksReturn => {\n const _dpr = getDpr(dpr);\n\n const scene = useMemo(() => new THREE.Scene(), []);\n\n const { material, mesh } = useMesh({\n scene,\n size,\n dpr: _dpr.shader,\n onBeforeInit,\n });\n\n const camera = useCamera(size);\n\n const fboProps = useMemo(\n () => ({\n scene,\n camera,\n size,\n dpr: _dpr.fbo,\n isSizeUpdate,\n ...renderTargetOptions,\n }),\n [scene, camera, size, _dpr.fbo, isSizeUpdate, renderTargetOptions]\n ) as UseFboProps;\n\n const [renderTarget, updateRenderTarget] = useDoubleFBO(fboProps);\n\n const [params, setParams] = useParams(BLANK_PARAMS);\n\n const updateValue = setUniform(material);\n const updateCustomValue = setCustomUniform(material);\n\n const updateParams = useCallback(\n (newParams?: BlankParams, customParams?: CustomParams) => {\n setParams(newParams);\n updateCustomValue(customParams);\n },\n [setParams, updateCustomValue]\n );\n\n const updateFx = useCallback(\n (\n rootState: RootState,\n newParams?: BlankParams,\n customParams?: CustomParams\n ) => {\n const { gl, clock, pointer } = rootState;\n\n updateParams(newParams, customParams);\n\n updateValue(\"uPointer\", pointer);\n updateValue(\"uTexture\", params.texture!);\n updateValue(\"uTime\", params.beat || clock.getElapsedTime());\n\n return updateRenderTarget(gl, ({ read }) => {\n updateValue(\"uBackbuffer\", read);\n });\n },\n [updateRenderTarget, updateValue, params, updateParams]\n );\n\n return [\n updateFx,\n updateParams,\n {\n scene: scene,\n mesh: mesh,\n material: material,\n camera: camera,\n renderTarget: renderTarget,\n output: renderTarget.read.texture,\n },\n ];\n};\n","precision highp float;\n\nvarying vec2 vUv;\n#usf \n\n#usf \n\nvoid main() {\n\tvec4 usf_Position = vec4(position,1.);\n\tvUv = uv;\n\n\t#usf
\n\t\n\tgl_Position = usf_Position;\n}","precision highp float;\n\nvarying vec2 vUv;\n#usf \n\nuniform vec2 uResolution;\n\n#usf \n\nvoid main() {\n\tvec4 usf_FragColor = vec4(1.);\n\n\t#usf
\n\t\n\tgl_FragColor = usf_FragColor;\n}","import { useMemo } from \"react\";\nimport * as THREE from \"three\";\nimport vertexShader from \"./shader/main.vert\";\nimport fragmentShader from \"./shader/main.frag\";\nimport { useAddObject } from \"../../../utils/useAddObject\";\nimport { MaterialProps, Size } from \"../../types\";\nimport { setUniform, useResolution } from \"../../..\";\nimport { MATERIAL_BASIC_PARAMS } from \"../../../libs/constants\";\nimport { createMaterialParameters } from \"../../../utils/createMaterialParameters\";\n\nexport class RawBlankMaterial extends THREE.ShaderMaterial {\n uniforms!: {\n uResolution: { value: THREE.Vector2 };\n };\n}\nexport const useMesh = ({\n scene,\n size,\n dpr,\n onBeforeInit,\n}: {\n scene: THREE.Scene;\n size: Size;\n dpr: number | false;\n} & MaterialProps) => {\n const geometry = useMemo(() => new THREE.PlaneGeometry(2, 2), []);\n const material = useMemo(() => {\n const mat = new THREE.ShaderMaterial({\n ...createMaterialParameters(\n {\n uniforms: {\n uResolution: { value: new THREE.Vector2() },\n },\n vertexShader: vertexShader,\n fragmentShader: fragmentShader,\n },\n onBeforeInit\n ),\n ...MATERIAL_BASIC_PARAMS,\n });\n return mat;\n }, [onBeforeInit]) as RawBlankMaterial;\n\n const resolution = useResolution(size, dpr);\n setUniform(material)(\"uResolution\", resolution.clone());\n\n const mesh = useAddObject(scene, geometry, material, THREE.Mesh);\n\n return { material, mesh };\n};\n","import { useCallback, useMemo } from \"react\";\nimport * as THREE from \"three\";\nimport { RootState } from \"@react-three/fiber\";\nimport { RawBlankMaterial, useMesh } from \"./useMesh\";\nimport { useCamera } from \"../../../utils/useCamera\";\nimport { CustomParams, setCustomUniform } from \"../../../utils/setUniforms\";\nimport type { HooksProps, HooksReturn } from \"../../types\";\nimport { getDpr } from \"../../../utils/getDpr\";\nimport { UseFboProps, useSingleFBO } from \"../../../utils/useSingleFBO\";\n\nexport type RawBlankParams = {};\n\nexport type RawBlankObject = {\n scene: THREE.Scene;\n mesh: THREE.Mesh<\n THREE.BufferGeometry,\n RawBlankMaterial\n >;\n material: RawBlankMaterial;\n camera: THREE.Camera;\n renderTarget: THREE.WebGLRenderTarget;\n output: THREE.Texture;\n};\n\nexport const RAWBLANK_PARAMS: RawBlankParams = Object.freeze({});\n\n/**\n * By default, it is a blank canvas with nothing drawn on it. You can customise the shaders using `onBeforeCompile`.\n * Fragment shaders have `uResolution` as default uniforms.\n *\n * ※ `usf_FragColor` overrides `gl_FragColor`\n *\n * ※ `usf_Position` overrides `gl_Position`\n * \n * `RawBlankParams` is an empty object. so you can't pass any parameters to second argument. Nothing will happen if you pass them.\n * ```tsx\n * useFrame((state) => {\n update(\n state,\n {},\n {\n uTime: state.clock.getElapsedTime(),\n }\n );\n });\n * ```\n * @link https://github.com/FunTechInc/use-shader-fx?tab=readme-ov-file#usage\n */\nexport const useRawBlank = ({\n size,\n dpr,\n renderTargetOptions,\n isSizeUpdate,\n onBeforeInit,\n}: HooksProps): HooksReturn => {\n const _dpr = getDpr(dpr);\n\n const scene = useMemo(() => new THREE.Scene(), []);\n\n const { material, mesh } = useMesh({\n scene,\n size,\n dpr: _dpr.shader,\n onBeforeInit,\n });\n\n const camera = useCamera(size);\n\n const fboProps = useMemo(\n () => ({\n scene,\n camera,\n size,\n dpr: _dpr.fbo,\n isSizeUpdate,\n ...renderTargetOptions,\n }),\n [scene, camera, size, _dpr.fbo, isSizeUpdate, renderTargetOptions]\n ) as UseFboProps;\n\n const [renderTarget, updateRenderTarget] = useSingleFBO(fboProps);\n\n const updateCustomValue = setCustomUniform(material);\n\n const updateParams = useCallback(\n (newParams?: RawBlankParams, customParams?: CustomParams) => {\n updateCustomValue(customParams);\n },\n [updateCustomValue]\n );\n\n const updateFx = useCallback(\n (\n rootState: RootState,\n newParams?: RawBlankParams,\n customParams?: CustomParams\n ) => {\n const { gl } = rootState;\n updateParams(newParams, customParams);\n return updateRenderTarget(gl);\n },\n [updateRenderTarget, updateParams]\n );\n\n return [\n updateFx,\n updateParams,\n {\n scene: scene,\n mesh: mesh,\n material: material,\n camera: camera,\n renderTarget: renderTarget,\n output: renderTarget.texture,\n },\n ];\n};\n","import * as THREE from \"three\";\nimport { useMemo } from \"react\";\nimport { useAddObject } from \"../../../../utils/useAddObject\";\n\ntype UseCreateObjectProps = {\n scene: THREE.Scene | false;\n geometry: THREE.BufferGeometry;\n material: THREE.ShaderMaterial;\n};\n\nexport type MorphParticlePoints = THREE.Points<\n THREE.BufferGeometry,\n THREE.ShaderMaterial\n>;\nexport type InteractiveMesh = THREE.Mesh<\n THREE.BufferGeometry,\n THREE.ShaderMaterial\n>;\n\nexport const useCreateObject = ({\n scene,\n geometry,\n material,\n}: UseCreateObjectProps) => {\n const points = useAddObject(\n scene,\n geometry,\n material,\n THREE.Points\n ) as MorphParticlePoints;\n\n // Generate a mesh for pointer\n const interactiveMesh = useAddObject(\n scene,\n useMemo(() => geometry.clone(), [geometry]),\n useMemo(() => material.clone(), [material]),\n THREE.Mesh\n ) as InteractiveMesh;\n interactiveMesh.visible = false;\n\n return {\n points,\n interactiveMesh,\n };\n};\n","uniform vec2 uResolution;\nuniform float uMorphProgress;\nuniform float uPointSize;\n\nuniform sampler2D uPicture;\nuniform bool uIsPicture;\nuniform sampler2D uAlphaPicture;\nuniform bool uIsAlphaPicture;\n\nuniform vec3 uColor0;\nuniform vec3 uColor1;\nuniform vec3 uColor2;\nuniform vec3 uColor3;\n\nuniform float uTime;\n\nuniform float uWobblePositionFrequency;\nuniform float uWobbleTimeFrequency;\nuniform float uWobbleStrength;\nuniform float uWarpPositionFrequency;\nuniform float uWarpTimeFrequency;\nuniform float uWarpStrength;\n\nuniform sampler2D uDisplacement;\nuniform bool uIsDisplacement;\nuniform float uDisplacementIntensity;\n\nuniform float uSizeRandomIntensity;\nuniform float uSizeRandomTimeFrequency;\nuniform float uSizeRandomMin;\nuniform float uSizeRandomMax;\n\nuniform float uMapArrayLength;\n\nuniform float uDivergence;\nuniform vec3 uDivergencePoint;\n\nvarying vec3 vColor;\nvarying float vPictureAlpha;\nvarying vec3 vDisplacementColor;\nvarying float vDisplacementIntensity;\nvarying float vMapArrayIndex;\n\n#usf \n\n#usf \n\n#usf \n\nfloat random3D(vec3 co) {\n\treturn fract(sin(dot(co.xyz ,vec3(12.9898, 78.233, 45.764))) * 43758.5453);\n}\n\nvoid main() {\n\tvec3 newPosition = position;\n\tvec2 newUv = uv;\n\t\n\t#usf \n\t#usf \n\n\t// displacement for `newPosition`\n\tvec3 displacement = uIsDisplacement ? texture2D(uDisplacement, newUv).rgb : vec3(0.0);\n\tfloat displacementIntensity = smoothstep(0., 1., displacement.g);\n\tvDisplacementColor = displacement;\n\tvDisplacementIntensity = displacementIntensity;\n\n\t// At this point displacement is 0 ~ 1, so normalize it to -1 ~ 1\n\tdisplacement = displacement * 2.-1.;\n\tdisplacement *= displacementIntensity * uDisplacementIntensity;\n\tnewPosition += displacement;\n\n\t// divergence\n\tvec3 divergenceDir = newPosition - uDivergencePoint;\n\tif (uDivergence > 0.0) {\n\t\tnewPosition += normalize(divergenceDir) * uDivergence;\n\t} else if (uDivergence < 0.0) {\n\t\tnewPosition -= normalize(divergenceDir) * abs(uDivergence);\n\t}\n\n\t// Final position\n\tvec4 modelPosition = modelMatrix * vec4(newPosition, 1.0);\n\tvec4 viewPosition = viewMatrix * modelPosition;\n\tvec4 projectedPosition = projectionMatrix * viewPosition;\n\n\t// wobble ※Do not calculate noise if uWobbleStrength is 0\n\tfloat wobble = uWobbleStrength > 0. ? getWobble(projectedPosition.xyz) : 0.0;\n\n\tgl_Position = projectedPosition += wobble;\n\t\n\t// If picture is true then display picture, otherwise 4 color linear interpolation\n\tvColor = uIsPicture ? texture2D(uPicture, newUv).rgb : mix(mix(uColor0, uColor1, newPosition.x), mix(uColor2, uColor3, newPosition.y), newPosition.z);\n\n\t// Set Alpha on picture's g channel\n\tvPictureAlpha = uIsAlphaPicture ? texture2D(uAlphaPicture, newUv).g : 1.;\n\n\t// Multiply the point size by picturAalpha. The size can also be adjusted with alphaMap.\n\t// If uSizeRandomTimeFrequency is greater than 0, the size will be randomly changed\n\tfloat sizeRand = uSizeRandomIntensity > 0. ? mix(uSizeRandomMin,uSizeRandomMax,(simplexNoise4d(vec4(newPosition,uTime * uSizeRandomTimeFrequency))*.5+.5)) * uSizeRandomIntensity : 1.;\n\tgl_PointSize = uPointSize * vPictureAlpha * uResolution.y * sizeRand;\n\tgl_PointSize *= (1.0 / - viewPosition.z);\n\n\t// mapArrayIndex\n\tvMapArrayIndex = uMapArrayLength > 0. ? floor(random3D(position) * uMapArrayLength) : 0.;\n}","precision highp float;\nprecision highp int;\n\nvarying vec3 vColor;\nvarying float vPictureAlpha;\nvarying vec3 vDisplacementColor;\nvarying float vDisplacementIntensity;\nvarying float vMapArrayIndex;\n\nuniform float uBlurAlpha;\nuniform float uBlurRadius;\nuniform sampler2D uMap;\nuniform bool uIsMap;\nuniform sampler2D uAlphaMap;\nuniform bool uIsAlphaMap;\nuniform float uDisplacementColorIntensity;\nuniform float uPointAlpha;\n\n#usf \n\nvoid main() { \n\tvec2 uv = gl_PointCoord;\n\tuv.y = 1.0 - uv.y;\n \n\t// make it a circle\n\tfloat distanceToCenter = length(uv - .5);\n\tfloat alpha = clamp(uBlurRadius / distanceToCenter - (1.-uBlurAlpha) , 0. , 1.);\n\n\t// Map if there is a map\t\n\tvec4 mapArrayColor;\n\t#usf \n\tvec4 mapColor = isMapArray ? mapArrayColor : uIsMap ? texture2D(uMap,uv) : vec4(1.);\n\tvec3 finalColor = isMapArray || uIsMap ? mapColor.rgb : vColor;\n\n\t// Mix with finalColor if displacement is true\n\tfloat mixIntensity = clamp(uDisplacementColorIntensity * vDisplacementIntensity,0.,1.);\n\tfinalColor = vDisplacementIntensity > 0. ? mix(finalColor,vDisplacementColor,mixIntensity) : finalColor;\n\n\t// get alpha map\n\tfloat alphaMap = uIsAlphaMap ? texture2D(uAlphaMap,uv).g : 1.;\n\n\tgl_FragColor = vec4(finalColor,alpha * vPictureAlpha * alphaMap * mapColor.a * uPointAlpha);\n}\n","import * as THREE from \"three\";\nimport { ISDEV } from \"../../../../libs/constants\";\n\nexport const rewriteVertexShader = (\n modifeidAttributes: Float32Array[],\n targetGeometry: THREE.BufferGeometry,\n targetAttibute: \"position\" | \"uv\",\n vertexShader: string,\n itemSize: number\n) => {\n const vTargetName =\n targetAttibute === \"position\" ? \"positionTarget\" : \"uvTarget\";\n const vAttributeRewriteKey =\n targetAttibute === \"position\"\n ? \"#usf \"\n : \"#usf \";\n const vTransitionRewriteKey =\n targetAttibute === \"position\"\n ? \"#usf \"\n : \"#usf \";\n const vListName =\n targetAttibute === \"position\" ? \"positionsList\" : \"uvsList\";\n const vMorphTransition =\n targetAttibute === \"position\"\n ? `\n\t\t\t\tfloat scaledProgress = uMorphProgress * ${modifeidAttributes.length - 1}.;\n\t\t\t\tint baseIndex = int(floor(scaledProgress));\t\t\n\t\t\t\tbaseIndex = clamp(baseIndex, 0, ${modifeidAttributes.length - 1});\t\t\n\t\t\t\tfloat progress = fract(scaledProgress);\n\t\t\t\tint nextIndex = baseIndex + 1;\n\t\t\t\tnewPosition = mix(positionsList[baseIndex], positionsList[nextIndex], progress);\n\t\t\t`\n : \"newUv = mix(uvsList[baseIndex], uvsList[nextIndex], progress);\";\n\n if (modifeidAttributes.length > 0) {\n // Delete the position at initialization and add the position after normalization\n targetGeometry.deleteAttribute(targetAttibute);\n targetGeometry.setAttribute(\n targetAttibute,\n new THREE.BufferAttribute(modifeidAttributes[0], itemSize)\n );\n\n let stringToAddToMorphAttibutes = \"\";\n let stringToAddToMorphAttibutesList = \"\";\n\n modifeidAttributes.forEach((target, index) => {\n targetGeometry.setAttribute(\n `${vTargetName}${index}`,\n new THREE.BufferAttribute(target, itemSize)\n );\n stringToAddToMorphAttibutes += `attribute vec${itemSize} ${vTargetName}${index};\\n`;\n if (index === 0) {\n stringToAddToMorphAttibutesList += `${vTargetName}${index}`;\n } else {\n stringToAddToMorphAttibutesList += `,${vTargetName}${index}`;\n }\n });\n\n vertexShader = vertexShader.replace(\n `${vAttributeRewriteKey}`,\n stringToAddToMorphAttibutes\n );\n vertexShader = vertexShader.replace(\n `${vTransitionRewriteKey}`,\n `vec${itemSize} ${vListName}[${modifeidAttributes.length}] = vec${itemSize}[](${stringToAddToMorphAttibutesList});\n\t\t\t\t${vMorphTransition}\n\t\t\t`\n );\n } else {\n vertexShader = vertexShader.replace(`${vAttributeRewriteKey}`, \"\");\n vertexShader = vertexShader.replace(`${vTransitionRewriteKey}`, \"\");\n if (!targetGeometry?.attributes[targetAttibute]?.array) {\n ISDEV &&\n console.error(\n `use-shader-fx:geometry.attributes.${targetAttibute}.array is not found`\n );\n }\n }\n\n return vertexShader;\n};\n","import * as THREE from \"three\";\n\n/**\n * Calculate the maximum length of attribute (position and uv) to match the length of all lists. Randomly map missing attributes when matching to maximum length\n * */\nexport const modifyAttributes = (\n attribute: Float32Array[] | undefined,\n targetGeometry: THREE.BufferGeometry,\n targetAttibute: \"position\" | \"uv\",\n itemSize: number\n) => {\n let modifiedAttribute: Float32Array[] = [];\n if (attribute && attribute.length > 0) {\n if (targetGeometry?.attributes[targetAttibute]?.array) {\n modifiedAttribute = [\n targetGeometry.attributes[targetAttibute].array as Float32Array,\n ...attribute,\n ];\n } else {\n modifiedAttribute = attribute;\n }\n\n const maxLength = Math.max(...modifiedAttribute.map((arr) => arr.length));\n\n modifiedAttribute.forEach((arr, i) => {\n if (arr.length < maxLength) {\n const diff = (maxLength - arr.length) / itemSize;\n const addArray = [];\n const oldArray = Array.from(arr);\n for (let i = 0; i < diff; i++) {\n const randomIndex =\n Math.floor((arr.length / itemSize) * Math.random()) *\n itemSize;\n for (let j = 0; j < itemSize; j++) {\n addArray.push(oldArray[randomIndex + j]);\n }\n }\n modifiedAttribute[i] = new Float32Array([...oldArray, ...addArray]);\n }\n });\n }\n return modifiedAttribute;\n};\n","import * as THREE from \"three\";\n\nexport const rewriteFragmentShader = (\n mapArray: THREE.Texture[] | undefined,\n fragmentShader: string\n) => {\n let mapArrayShader = \"\";\n const mapArrayUniforms: any = {};\n let textureSwitcherCode = \"mapArrayColor = \";\n\n if (mapArray && mapArray.length > 0) {\n mapArray.forEach((map, index) => {\n const condition = `vMapArrayIndex < ${index}.1`; // Comparison with a number with .1 added as the handling of floating points may vary between GPU drivers\n const action = `texture2D(uMapArray${index}, uv)`;\n textureSwitcherCode += `( ${condition} ) ? ${action} : `;\n mapArrayShader += `\n uniform sampler2D uMapArray${index};\n `;\n mapArrayUniforms[`uMapArray${index}`] = { value: map };\n });\n textureSwitcherCode += \"vec4(1.);\";\n mapArrayShader += `bool isMapArray = true;`;\n mapArrayUniforms[\"uMapArrayLength\"] = { value: mapArray.length };\n } else {\n textureSwitcherCode += \"vec4(1.0);\";\n mapArrayShader += `bool isMapArray = false;`;\n mapArrayUniforms[\"uMapArrayLength\"] = { value: 0 };\n }\n const rewritedFragmentShader = fragmentShader\n .replace(`#usf `, textureSwitcherCode)\n .replace(`#usf `, mapArrayShader);\n\n return { rewritedFragmentShader, mapArrayUniforms };\n};\n","import * as THREE from \"three\";\nimport { useMemo } from \"react\";\nimport { useResolution } from \"../../../../utils/useResolution\";\nimport { setUniform } from \"../../../../utils/setUniforms\";\nimport vertexShader from \"../shaders/main.vert\";\nimport fragmentShader from \"../shaders/main.frag\";\nimport { MORPHPARTICLES_PARAMS } from \"..\";\nimport {\n DEFAULT_TEXTURE,\n ISDEV,\n MATERIAL_BASIC_PARAMS,\n} from \"../../../../libs/constants\";\nimport { rewriteVertexShader } from \"./rewriteVertexShader\";\nimport { modifyAttributes } from \"./modifyAttributes\";\nimport { rewriteFragmentShader } from \"./rewriteFragmentShader\";\nimport { MaterialProps, Size } from \"../../../types\";\nimport { createMaterialParameters } from \"../../../../utils/createMaterialParameters\";\n\nexport class MorphParticlesMaterial extends THREE.ShaderMaterial {\n uniforms!: {\n uResolution: { value: THREE.Vector2 };\n uMorphProgress: { value: number };\n uBlurAlpha: { value: number };\n uBlurRadius: { value: number };\n uPointSize: { value: number };\n uPointAlpha: { value: number };\n uPicture: { value: THREE.Texture };\n uIsPicture: { value: boolean };\n uAlphaPicture: { value: THREE.Texture };\n uIsAlphaPicture: { value: boolean };\n uColor0: { value: THREE.Color };\n uColor1: { value: THREE.Color };\n uColor2: { value: THREE.Color };\n uColor3: { value: THREE.Color };\n uMap: { value: THREE.Texture };\n uIsMap: { value: boolean };\n uAlphaMap: { value: THREE.Texture };\n uIsAlphaMap: { value: boolean };\n uTime: { value: number };\n uWobblePositionFrequency: { value: number };\n uWobbleTimeFrequency: { value: number };\n uWobbleStrength: { value: number };\n uWarpPositionFrequency: { value: number };\n uWarpTimeFrequency: { value: number };\n uWarpStrength: { value: number };\n uDisplacement: { value: THREE.Texture };\n uIsDisplacement: { value: boolean };\n uDisplacementIntensity: { value: number };\n uDisplacementColorIntensity: { value: number };\n uSizeRandomIntensity: { value: number };\n uSizeRandomTimeFrequency: { value: number };\n uSizeRandomMin: { value: number };\n uSizeRandomMax: { value: number };\n uDivergence: { value: number };\n uDivergencePoint: { value: THREE.Vector3 };\n };\n}\n\nexport const useMaterial = ({\n size,\n dpr,\n geometry,\n positions,\n uvs,\n mapArray,\n onBeforeInit,\n}: {\n size: Size;\n dpr: number | false;\n geometry: THREE.BufferGeometry;\n positions?: Float32Array[];\n uvs?: Float32Array[];\n mapArray?: THREE.Texture[];\n} & MaterialProps) => {\n const modifiedPositions = useMemo(\n () => modifyAttributes(positions, geometry, \"position\", 3),\n [positions, geometry]\n );\n\n const modifiedUvs = useMemo(\n () => modifyAttributes(uvs, geometry, \"uv\", 2),\n [uvs, geometry]\n );\n\n const material = useMemo(() => {\n if (modifiedPositions.length !== modifiedUvs.length) {\n ISDEV &&\n console.log(\"use-shader-fx:positions and uvs are not matched\");\n }\n\n // vertex\n const rewritedVertexShader = rewriteVertexShader(\n modifiedUvs,\n geometry,\n \"uv\",\n rewriteVertexShader(\n modifiedPositions,\n geometry,\n \"position\",\n vertexShader,\n 3\n ),\n 2\n );\n\n // fragment\n const { rewritedFragmentShader, mapArrayUniforms } =\n rewriteFragmentShader(mapArray, fragmentShader);\n\n const mat = new THREE.ShaderMaterial({\n ...createMaterialParameters(\n {\n uniforms: {\n uResolution: { value: new THREE.Vector2(0, 0) },\n uMorphProgress: {\n value: MORPHPARTICLES_PARAMS.morphProgress,\n },\n uBlurAlpha: { value: MORPHPARTICLES_PARAMS.blurAlpha },\n uBlurRadius: { value: MORPHPARTICLES_PARAMS.blurRadius },\n uPointSize: { value: MORPHPARTICLES_PARAMS.pointSize },\n uPointAlpha: { value: MORPHPARTICLES_PARAMS.pointAlpha },\n uPicture: { value: DEFAULT_TEXTURE },\n uIsPicture: { value: false },\n uAlphaPicture: { value: DEFAULT_TEXTURE },\n uIsAlphaPicture: { value: false },\n uColor0: { value: MORPHPARTICLES_PARAMS.color0 },\n uColor1: { value: MORPHPARTICLES_PARAMS.color1 },\n uColor2: { value: MORPHPARTICLES_PARAMS.color2 },\n uColor3: { value: MORPHPARTICLES_PARAMS.color3 },\n uMap: { value: DEFAULT_TEXTURE },\n uIsMap: { value: false },\n uAlphaMap: { value: DEFAULT_TEXTURE },\n uIsAlphaMap: { value: false },\n uTime: { value: 0 },\n uWobblePositionFrequency: {\n value: MORPHPARTICLES_PARAMS.wobblePositionFrequency,\n },\n uWobbleTimeFrequency: {\n value: MORPHPARTICLES_PARAMS.wobbleTimeFrequency,\n },\n uWobbleStrength: {\n value: MORPHPARTICLES_PARAMS.wobbleStrength,\n },\n uWarpPositionFrequency: {\n value: MORPHPARTICLES_PARAMS.warpPositionFrequency,\n },\n uWarpTimeFrequency: {\n value: MORPHPARTICLES_PARAMS.warpTimeFrequency,\n },\n uWarpStrength: { value: MORPHPARTICLES_PARAMS.warpStrength },\n uDisplacement: { value: DEFAULT_TEXTURE },\n uIsDisplacement: { value: false },\n uDisplacementIntensity: {\n value: MORPHPARTICLES_PARAMS.displacementIntensity,\n },\n uDisplacementColorIntensity: {\n value: MORPHPARTICLES_PARAMS.displacementColorIntensity,\n },\n uSizeRandomIntensity: {\n value: MORPHPARTICLES_PARAMS.sizeRandomIntensity,\n },\n uSizeRandomTimeFrequency: {\n value: MORPHPARTICLES_PARAMS.sizeRandomTimeFrequency,\n },\n uSizeRandomMin: {\n value: MORPHPARTICLES_PARAMS.sizeRandomMin,\n },\n uSizeRandomMax: {\n value: MORPHPARTICLES_PARAMS.sizeRandomMax,\n },\n uDivergence: { value: MORPHPARTICLES_PARAMS.divergence },\n uDivergencePoint: {\n value: MORPHPARTICLES_PARAMS.divergencePoint,\n },\n ...mapArrayUniforms,\n },\n vertexShader: rewritedVertexShader,\n fragmentShader: rewritedFragmentShader,\n },\n onBeforeInit\n ),\n ...MATERIAL_BASIC_PARAMS,\n blending: THREE.AdditiveBlending,\n // Must be transparent\n transparent: true,\n });\n\n return mat;\n }, [\n geometry,\n modifiedPositions,\n modifiedUvs,\n mapArray,\n onBeforeInit,\n ]) as MorphParticlesMaterial;\n\n const resolution = useResolution(size, dpr);\n setUniform(material)(\"uResolution\", resolution.clone());\n\n return { material, modifiedPositions, modifiedUvs };\n};\n","import * as THREE from \"three\";\nimport { RootState } from \"@react-three/fiber\";\nimport {\n InteractiveMesh,\n MorphParticlePoints,\n useCreateObject,\n} from \"./utils/useCreateObject\";\nimport { useMaterial } from \"./utils/useMaterial\";\nimport { MorphParticlesParams } from \".\";\nimport {\n setUniform,\n CustomParams,\n setCustomUniform,\n} from \"../../../utils/setUniforms\";\nimport { useCallback, useMemo } from \"react\";\nimport { Create3DHooksProps } from \"../types\";\nimport { Dpr, Size } from \"../../types\";\nimport { getDpr } from \"../../../utils/getDpr\";\n\nexport type UseCreateMorphParticlesProps = {\n size: Size;\n dpr: Dpr;\n /** default : `THREE.SphereGeometry(1, 32, 32)` */\n geometry?: THREE.BufferGeometry;\n positions?: Float32Array[];\n uvs?: Float32Array[];\n /** Array of textures to map to points. Mapped at random. */\n mapArray?: THREE.Texture[];\n};\n\ntype UpdateUniform = (\n rootState: RootState | null,\n newParams?: MorphParticlesParams,\n customParams?: CustomParams\n) => void;\n\ntype UseCreateMorphParticlesReturn = [\n UpdateUniform,\n {\n points: MorphParticlePoints;\n interactiveMesh: InteractiveMesh;\n positions: Float32Array[];\n uvs: Float32Array[];\n }\n];\n\nexport const useCreateMorphParticles = ({\n size,\n dpr,\n scene = false,\n geometry,\n positions,\n uvs,\n mapArray,\n onBeforeInit,\n}: Create3DHooksProps &\n UseCreateMorphParticlesProps): UseCreateMorphParticlesReturn => {\n const _dpr = getDpr(dpr);\n\n const morphGeometry = useMemo(() => {\n const geo = geometry || new THREE.SphereGeometry(1, 32, 32);\n geo.setIndex(null);\n // Since it is a particle, normal is not necessary\n geo.deleteAttribute(\"normal\");\n return geo;\n }, [geometry]);\n\n const { material, modifiedPositions, modifiedUvs } = useMaterial({\n size,\n dpr: _dpr.shader,\n geometry: morphGeometry,\n positions,\n uvs,\n mapArray,\n onBeforeInit,\n });\n\n const { points, interactiveMesh } = useCreateObject({\n scene,\n geometry: morphGeometry,\n material,\n });\n\n const updateValue = setUniform(material);\n const updateCustomValue = setCustomUniform(material);\n\n const updateUniform = useCallback(\n (rootState, newParams, customParams) => {\n if (rootState) {\n updateValue(\n \"uTime\",\n newParams?.beat || rootState.clock.getElapsedTime()\n );\n }\n if (newParams === undefined) {\n return;\n }\n updateValue(\"uMorphProgress\", newParams.morphProgress);\n updateValue(\"uBlurAlpha\", newParams.blurAlpha);\n updateValue(\"uBlurRadius\", newParams.blurRadius);\n updateValue(\"uPointSize\", newParams.pointSize);\n updateValue(\"uPointAlpha\", newParams.pointAlpha);\n if (newParams.picture) {\n updateValue(\"uPicture\", newParams.picture);\n updateValue(\"uIsPicture\", true);\n } else if (newParams.picture === false) {\n updateValue(\"uIsPicture\", false);\n }\n if (newParams.alphaPicture) {\n updateValue(\"uAlphaPicture\", newParams.alphaPicture);\n updateValue(\"uIsAlphaPicture\", true);\n } else if (newParams.alphaPicture === false) {\n updateValue(\"uIsAlphaPicture\", false);\n }\n updateValue(\"uColor0\", newParams.color0);\n updateValue(\"uColor1\", newParams.color1);\n updateValue(\"uColor2\", newParams.color2);\n updateValue(\"uColor3\", newParams.color3);\n if (newParams.map) {\n updateValue(\"uMap\", newParams.map);\n updateValue(\"uIsMap\", true);\n } else if (newParams.map === false) {\n updateValue(\"uIsMap\", false);\n }\n if (newParams.alphaMap) {\n updateValue(\"uAlphaMap\", newParams.alphaMap);\n updateValue(\"uIsAlphaMap\", true);\n } else if (newParams.alphaMap === false) {\n updateValue(\"uIsAlphaMap\", false);\n }\n updateValue(\"uWobbleStrength\", newParams.wobbleStrength);\n updateValue(\n \"uWobblePositionFrequency\",\n newParams.wobblePositionFrequency\n );\n updateValue(\"uWobbleTimeFrequency\", newParams.wobbleTimeFrequency);\n updateValue(\"uWarpStrength\", newParams.warpStrength);\n updateValue(\"uWarpPositionFrequency\", newParams.warpPositionFrequency);\n updateValue(\"uWarpTimeFrequency\", newParams.warpTimeFrequency);\n if (newParams.displacement) {\n updateValue(\"uDisplacement\", newParams.displacement);\n updateValue(\"uIsDisplacement\", true);\n } else if (newParams.displacement === false) {\n updateValue(\"uIsDisplacement\", false);\n }\n updateValue(\"uDisplacementIntensity\", newParams.displacementIntensity);\n updateValue(\n \"uDisplacementColorIntensity\",\n newParams.displacementColorIntensity\n );\n updateValue(\"uSizeRandomIntensity\", newParams.sizeRandomIntensity);\n updateValue(\n \"uSizeRandomTimeFrequency\",\n newParams.sizeRandomTimeFrequency\n );\n updateValue(\"uSizeRandomMin\", newParams.sizeRandomMin);\n updateValue(\"uSizeRandomMax\", newParams.sizeRandomMax);\n updateValue(\"uDivergence\", newParams.divergence);\n updateValue(\"uDivergencePoint\", newParams.divergencePoint);\n\n updateCustomValue(customParams);\n },\n [updateValue, updateCustomValue]\n );\n\n return [\n updateUniform,\n {\n points,\n interactiveMesh,\n positions: modifiedPositions,\n uvs: modifiedUvs,\n },\n ];\n};\n","import * as THREE from \"three\";\nimport { useCallback, useMemo } from \"react\";\nimport { RootState } from \"@react-three/fiber\";\nimport { useSingleFBO } from \"../../../utils/useSingleFBO\";\nimport { HooksReturn } from \"../../types\";\nimport {\n useCreateMorphParticles,\n UseCreateMorphParticlesProps,\n} from \"./useCreateMorphParticles\";\nimport { HooksProps3D } from \"../types\";\nimport { InteractiveMesh, MorphParticlePoints } from \"./utils/useCreateObject\";\nimport { getDpr } from \"../../../utils/getDpr\";\nimport { CustomParams } from \"../../../utils/setUniforms\";\n\nexport type MorphParticlesParams = {\n /** progress value to morph vertices,0~1 */\n morphProgress?: number;\n blurAlpha?: number;\n blurRadius?: number;\n pointSize?: number;\n /** default : `1` */\n pointAlpha?: number;\n /** Since the color is extracted based on the attribute `uv`, the intended behavior will not occur if there is no uv in the attribute. */\n picture?: THREE.Texture | false;\n /** The alpha map is a grayscale texture that controls the opacity across the surface (black: fully transparent; white: fully opaque). use the green channel when sampling this texture. It also affects the size of the point. default : `false` */\n alphaPicture?: THREE.Texture | false;\n color0?: THREE.Color;\n color1?: THREE.Color;\n color2?: THREE.Color;\n color3?: THREE.Color;\n /** This maps to point,texture */\n map?: THREE.Texture | false;\n /** The alpha map is a grayscale texture that controls the opacity across the surface (black: fully transparent; white: fully opaque). use the green channel when sampling this texture. default : `false` */\n alphaMap?: THREE.Texture | false;\n /** If ​​wobbleStrength is set to 0, wobble will stop. It will also affect noise calculation, default : `0` */\n wobbleStrength?: number;\n wobblePositionFrequency?: number;\n wobbleTimeFrequency?: number;\n /** default : `0` */\n warpStrength?: number;\n warpPositionFrequency?: number;\n warpTimeFrequency?: number;\n /** Manipulate the vertices using the color channels of this texture. The strength of the displacement changes depending on the g channel of this texture */\n displacement?: THREE.Texture | false;\n /** Strength of displacement. The strength of displacement depends on g ch, but is the value multiplied by it , default : `1` */\n displacementIntensity?: number;\n /** Strength to reflect color ch of displacement texture */\n displacementColorIntensity?: number;\n /** If set to 0, noise calculation stops, default : `0` */\n sizeRandomIntensity?: number;\n sizeRandomTimeFrequency?: number;\n sizeRandomMin?: number;\n sizeRandomMax?: number;\n /** Divergence rate of a point. Negative cases are dense, positive cases are divergent, default : `0` */\n divergence?: number;\n /** Divergence centre point, default : `THREE.Vector3(0)` */\n divergencePoint?: THREE.Vector3;\n /** you can get into the rhythm ♪ , default : `false` */\n beat?: number | false;\n};\n\nexport type MorphParticlesObject = {\n scene: THREE.Scene;\n points: MorphParticlePoints;\n interactiveMesh: InteractiveMesh;\n renderTarget: THREE.WebGLRenderTarget;\n output: THREE.Texture;\n positions: Float32Array[];\n uvs: Float32Array[];\n};\n\nexport const MORPHPARTICLES_PARAMS: MorphParticlesParams = Object.freeze({\n morphProgress: 0,\n blurAlpha: 0.9,\n blurRadius: 0.05,\n pointSize: 0.05,\n pointAlpha: 1,\n picture: false,\n alphaPicture: false,\n color0: new THREE.Color(0xff0000),\n color1: new THREE.Color(0x00ff00),\n color2: new THREE.Color(0x0000ff),\n color3: new THREE.Color(0xffff00),\n map: false,\n alphaMap: false,\n wobbleStrength: 0.0,\n wobblePositionFrequency: 0.5,\n wobbleTimeFrequency: 0.5,\n warpStrength: 0.0,\n warpPositionFrequency: 0.5,\n warpTimeFrequency: 0.5,\n displacement: false,\n displacementIntensity: 1,\n displacementColorIntensity: 0,\n sizeRandomIntensity: 0,\n sizeRandomTimeFrequency: 0.2,\n sizeRandomMin: 0.5,\n sizeRandomMax: 1.5,\n divergence: 0,\n divergencePoint: new THREE.Vector3(0),\n beat: false,\n});\n\n/**\n * @link https://github.com/FunTechInc/use-shader-fx\n */\nexport const useMorphParticles = ({\n size,\n dpr,\n isSizeUpdate,\n renderTargetOptions,\n camera,\n geometry,\n positions,\n uvs,\n onBeforeInit,\n}: HooksProps3D & UseCreateMorphParticlesProps): HooksReturn<\n MorphParticlesParams,\n MorphParticlesObject,\n CustomParams\n> => {\n const _dpr = getDpr(dpr);\n\n const scene = useMemo(() => new THREE.Scene(), []);\n\n const [\n updateUniform,\n {\n points,\n interactiveMesh,\n positions: generatedPositions,\n uvs: generatedUvs,\n },\n ] = useCreateMorphParticles({\n scene,\n size,\n dpr,\n geometry,\n positions,\n uvs,\n onBeforeInit,\n });\n\n const [renderTarget, updateRenderTarget] = useSingleFBO({\n scene,\n camera,\n size,\n dpr: _dpr.fbo,\n isSizeUpdate,\n depthBuffer: true,\n ...renderTargetOptions,\n });\n\n const updateFx = useCallback(\n (\n rootState: RootState,\n newParams?: MorphParticlesParams,\n customParams?: CustomParams\n ) => {\n updateUniform(rootState, newParams, customParams);\n return updateRenderTarget(rootState.gl);\n },\n [updateRenderTarget, updateUniform]\n );\n\n const updateParams = useCallback(\n (newParams?: MorphParticlesParams, customParams?: CustomParams) => {\n updateUniform(null, newParams, customParams);\n },\n [updateUniform]\n );\n\n return [\n updateFx,\n updateParams,\n {\n scene,\n points,\n interactiveMesh,\n renderTarget,\n output: renderTarget.texture,\n positions: generatedPositions,\n uvs: generatedUvs,\n },\n ];\n};\n","import * as THREE from \"three\";\n\nexport const rewriteVertexShader = (\n parameters: THREE.WebGLProgramParametersWithUniforms\n) => {\n const isDepth = parameters.shaderType === \"MeshDepthMaterial\";\n\n parameters.vertexShader = parameters.vertexShader.replace(\n \"#include \",\n `\n\t\t\tvec3 objectNormal = usf_Normal;\n\t\t\t#ifdef USE_TANGENT\n\t\t\tvec3 objectTangent = vec3( tangent.xyz );\n\t\t\t#endif\n\t\t`\n );\n\n parameters.vertexShader = parameters.vertexShader.replace(\n \"#include \",\n `\n\t\t\tvec3 transformed = usf_Position;\n\t\t\t#ifdef USE_ALPHAHASH\n\t\t\tvPosition = vec3( position );\n\t\t\t#endif\n\t\t`\n );\n\n parameters.vertexShader = parameters.vertexShader.replace(\n \"void main() {\",\n `\n\t\tuniform float uTime;\n\t\tuniform float uWobblePositionFrequency;\n\t\tuniform float uWobbleTimeFrequency;\n\t\tuniform float uWobbleStrength;\n\t\tuniform float uWarpPositionFrequency;\n\t\tuniform float uWarpTimeFrequency;\n\t\tuniform float uWarpStrength;\n\n\t\t${isDepth ? \"attribute vec4 tangent;\" : \"\"}\n\t\t\n\t\tvarying float vWobble;\n\t\tvarying vec2 vPosition;\n\t\t\n\t\t// edge\n\t\tvarying vec3 vEdgeNormal;\n\t\tvarying vec3 vEdgeViewPosition;\n\n\t\t#usf \n\n\t\tvoid main() {\n\t\t\n\t\t\tvec3 usf_Position = position;\n\t\t\tvec3 usf_Normal = normal;\n\t\t\tvec3 biTangent = cross(normal, tangent.xyz);\n\t\t\t\n\t\t\t// Neighbours positions\n\t\t\tfloat shift = 0.01;\n\t\t\tvec3 positionA = usf_Position + tangent.xyz * shift;\n\t\t\tvec3 positionB = usf_Position + biTangent * shift;\n\t\t\t\n\t\t\t// wobble\n\t\t\tfloat wobble = (uWobbleStrength > 0.) ? getWobble(usf_Position) : 0.0;\n\t\t\tfloat wobblePositionA = (uWobbleStrength > 0.) ? getWobble(positionA) : 0.0;\n\t\t\tfloat wobblePositionB = (uWobbleStrength > 0.) ? getWobble(positionB) : 0.0;\n\t\t\t\n\t\t\tusf_Position += wobble * normal;\n\t\t\tpositionA += wobblePositionA * normal;\n\t\t\tpositionB += wobblePositionB * normal;\n\n\t\t\t// Compute normal\n\t\t\tvec3 toA = normalize(positionA - usf_Position);\n\t\t\tvec3 toB = normalize(positionB - usf_Position);\n\t\t\tusf_Normal = cross(toA, toB);\n\t\t\t\n\t\t\t// Varying\n\t\t\tvPosition = usf_Position.xy;\n\t\t\tvWobble = wobble/uWobbleStrength;\n\t\t\t\n\t\t\tvEdgeNormal = normalize(normalMatrix * usf_Normal);\n\t\t\tvec4 viewPosition = viewMatrix * modelMatrix * vec4(usf_Position, 1.0);\n\t\t\tvEdgeViewPosition = normalize(viewPosition.xyz);\n\t\t`\n );\n};\n","import * as THREE from \"three\";\n\nexport const rewriteFragmentShader = (\n parameters: THREE.WebGLProgramParametersWithUniforms\n) => {\n // diffuse color , Manipulate color mixing ratio with `uColorMix`\n parameters.fragmentShader = parameters.fragmentShader.replace(\n \"#include \",\n `\n\t\t\t#include \n\n\t\t\tif (uEdgeThreshold > 0.0) {\n\t\t\t\tfloat edgeThreshold = dot(vEdgeNormal, -vEdgeViewPosition);\n\t\t\t\tdiffuseColor = edgeThreshold < uEdgeThreshold ? vec4(uEdgeColor, 1.0) : mix(diffuseColor, usf_DiffuseColor, uColorMix);\n\t\t\t} else {\n\t\t\t\tdiffuseColor = mix(diffuseColor, usf_DiffuseColor, uColorMix);\n\t\t\t}\n\t\t`\n );\n\n parameters.fragmentShader = parameters.fragmentShader.replace(\n \"void main() {\",\n `\n\t\t\tuniform vec3 uColor0;\n\t\t\tuniform vec3 uColor1;\n\t\t\tuniform vec3 uColor2;\n\t\t\tuniform vec3 uColor3;\n\t\t\tuniform float uColorMix;\n\t\t\tuniform float uEdgeThreshold;\n\t\t\tuniform vec3 uEdgeColor;\n\t\t\t\n\t\t\t// transmission\n\t\t\tuniform float uChromaticAberration; \n\t\t\tuniform float uAnisotropicBlur; \n\t\t\tuniform float uTime;\n\t\t\tuniform float uDistortion;\n\t\t\tuniform float uDistortionScale;\n\t\t\tuniform float uTemporalDistortion;\n\t\t\tuniform float uRefractionSamples;\n\t\t\t\n\t\t\tfloat rand(float n){return fract(sin(n) * 43758.5453123);}\n\t\t\t\n\t\t\t#usf \n\n\t\t\tvarying float vWobble;\n\t\t\tvarying vec2 vPosition;\n\t\t\tvarying vec3 vEdgeNormal;\n\t\t\tvarying vec3 vEdgeViewPosition;\n\t\t\t\n\t\t\tvoid main(){\n\t\t\t\t\n\t\t\t\tvec4 usf_DiffuseColor = vec4(1.0);\n\t\t\t\tfloat colorWobbleMix = smoothstep(-1.,1.,vWobble);\n\t\t\t\tvec2 colorPosMix = vec2(smoothstep(-1.,1.,vPosition.x),smoothstep(-1.,1.,vPosition.y));\n\t\t\t\n\t\t\t\tusf_DiffuseColor.rgb = mix(mix(uColor0, uColor1, colorPosMix.x), mix(uColor2, uColor3, colorPosMix.y), colorWobbleMix);\n\t\t`\n );\n};\n","#ifdef USE_TRANSMISSION\n\n\t// Transmission code is based on glTF-Sampler-Viewer\n\t// https://github.com/KhronosGroup/glTF-Sample-Viewer\n\n\tuniform float _transmission;\n\tuniform float thickness;\n\tuniform float attenuationDistance;\n\tuniform vec3 attenuationColor;\n\n\t#ifdef USE_TRANSMISSIONMAP\n\n\t\tuniform sampler2D transmissionMap;\n\n\t#endif\n\n\t#ifdef USE_THICKNESSMAP\n\n\t\tuniform sampler2D thicknessMap;\n\n\t#endif\n\n\tuniform vec2 transmissionSamplerSize;\n\tuniform sampler2D transmissionSamplerMap;\n\n\tuniform mat4 modelMatrix;\n\tuniform mat4 projectionMatrix;\n\n\tvarying vec3 vWorldPosition;\n\n\t// Mipped Bicubic Texture Filtering by N8\n\t// https://www.shadertoy.com/view/Dl2SDW\n\n\tfloat w0( float a ) {\n\n\t\treturn ( 1.0 / 6.0 ) * ( a * ( a * ( - a + 3.0 ) - 3.0 ) + 1.0 );\n\n\t}\n\n\tfloat w1( float a ) {\n\n\t\treturn ( 1.0 / 6.0 ) * ( a * a * ( 3.0 * a - 6.0 ) + 4.0 );\n\n\t}\n\n\tfloat w2( float a ){\n\n\t\treturn ( 1.0 / 6.0 ) * ( a * ( a * ( - 3.0 * a + 3.0 ) + 3.0 ) + 1.0 );\n\n\t}\n\n\tfloat w3( float a ) {\n\n\t\treturn ( 1.0 / 6.0 ) * ( a * a * a );\n\n\t}\n\n\t// g0 and g1 are the two amplitude functions\n\tfloat g0( float a ) {\n\n\t\treturn w0( a ) + w1( a );\n\n\t}\n\n\tfloat g1( float a ) {\n\n\t\treturn w2( a ) + w3( a );\n\n\t}\n\n\t// h0 and h1 are the two offset functions\n\tfloat h0( float a ) {\n\n\t\treturn - 1.0 + w1( a ) / ( w0( a ) + w1( a ) );\n\n\t}\n\n\tfloat h1( float a ) {\n\n\t\treturn 1.0 + w3( a ) / ( w2( a ) + w3( a ) );\n\n\t}\n\n\tvec4 bicubic( sampler2D tex, vec2 uv, vec4 texelSize, float lod ) {\n\n\t\tuv = uv * texelSize.zw + 0.5;\n\n\t\tvec2 iuv = floor( uv );\n\t\tvec2 fuv = fract( uv );\n\n\t\tfloat g0x = g0( fuv.x );\n\t\tfloat g1x = g1( fuv.x );\n\t\tfloat h0x = h0( fuv.x );\n\t\tfloat h1x = h1( fuv.x );\n\t\tfloat h0y = h0( fuv.y );\n\t\tfloat h1y = h1( fuv.y );\n\n\t\tvec2 p0 = ( vec2( iuv.x + h0x, iuv.y + h0y ) - 0.5 ) * texelSize.xy;\n\t\tvec2 p1 = ( vec2( iuv.x + h1x, iuv.y + h0y ) - 0.5 ) * texelSize.xy;\n\t\tvec2 p2 = ( vec2( iuv.x + h0x, iuv.y + h1y ) - 0.5 ) * texelSize.xy;\n\t\tvec2 p3 = ( vec2( iuv.x + h1x, iuv.y + h1y ) - 0.5 ) * texelSize.xy;\n\n\t\treturn g0( fuv.y ) * ( g0x * textureLod( tex, p0, lod ) + g1x * textureLod( tex, p1, lod ) ) +\n\t\t\tg1( fuv.y ) * ( g0x * textureLod( tex, p2, lod ) + g1x * textureLod( tex, p3, lod ) );\n\n\t}\n\n\tvec4 textureBicubic( sampler2D sampler, vec2 uv, float lod ) {\n\n\t\tvec2 fLodSize = vec2( textureSize( sampler, int( lod ) ) );\n\t\tvec2 cLodSize = vec2( textureSize( sampler, int( lod + 1.0 ) ) );\n\t\tvec2 fLodSizeInv = 1.0 / fLodSize;\n\t\tvec2 cLodSizeInv = 1.0 / cLodSize;\n\t\tvec4 fSample = bicubic( sampler, uv, vec4( fLodSizeInv, fLodSize ), floor( lod ) );\n\t\tvec4 cSample = bicubic( sampler, uv, vec4( cLodSizeInv, cLodSize ), ceil( lod ) );\n\t\treturn mix( fSample, cSample, fract( lod ) );\n\n\t}\n\n\tvec3 getVolumeTransmissionRay( const in vec3 n, const in vec3 v, const in float thickness, const in float ior, const in mat4 modelMatrix ) {\n\n\t\t// Direction of refracted light.\n\t\tvec3 refractionVector = refract( - v, normalize( n ), 1.0 / ior );\n\n\t\t// Compute rotation-independant scaling of the model matrix.\n\t\tvec3 modelScale;\n\t\tmodelScale.x = length( vec3( modelMatrix[ 0 ].xyz ) );\n\t\tmodelScale.y = length( vec3( modelMatrix[ 1 ].xyz ) );\n\t\tmodelScale.z = length( vec3( modelMatrix[ 2 ].xyz ) );\n\n\t\t// The thickness is specified in local space.\n\t\treturn normalize( refractionVector ) * thickness * modelScale;\n\n\t}\n\n\tfloat applyIorToRoughness( const in float roughness, const in float ior ) {\n\n\t\t// Scale roughness with IOR so that an IOR of 1.0 results in no microfacet refraction and\n\t\t// an IOR of 1.5 results in the default amount of microfacet refraction.\n\t\treturn roughness * clamp( ior * 2.0 - 2.0, 0.0, 1.0 );\n\n\t}\n\n\tvec4 getTransmissionSample( const in vec2 fragCoord, const in float roughness, const in float ior ) {\n\n\t\tfloat lod = log2( transmissionSamplerSize.x ) * applyIorToRoughness( roughness, ior );\n\t\treturn textureBicubic( transmissionSamplerMap, fragCoord.xy, lod );\n\n\t}\n\n\tvec3 volumeAttenuation( const in float transmissionDistance, const in vec3 attenuationColor, const in float attenuationDistance ) {\n\n\t\tif ( isinf( attenuationDistance ) ) {\n\n\t\t\t// Attenuation distance is +∞, i.e. the transmitted color is not attenuated at all.\n\t\t\treturn vec3( 1.0 );\n\n\t\t} else {\n\n\t\t\t// Compute light attenuation using Beer's law.\n\t\t\tvec3 attenuationCoefficient = -log( attenuationColor ) / attenuationDistance;\n\t\t\tvec3 transmittance = exp( - attenuationCoefficient * transmissionDistance ); // Beer's law\n\t\t\treturn transmittance;\n\n\t\t}\n\n\t}\n\n\tvec4 getIBLVolumeRefraction( const in vec3 n, const in vec3 v, const in float roughness, const in vec3 diffuseColor,\n\t\tconst in vec3 specularColor, const in float specularF90, const in vec3 position, const in mat4 modelMatrix,\n\t\tconst in mat4 viewMatrix, const in mat4 projMatrix, const in float ior, const in float thickness,\n\t\tconst in vec3 attenuationColor, const in float attenuationDistance ) {\n\n\t\tvec3 transmissionRay = getVolumeTransmissionRay( n, v, thickness, ior, modelMatrix );\n\t\tvec3 refractedRayExit = position + transmissionRay;\n\n\t\t// Project refracted vector on the framebuffer, while mapping to normalized device coordinates.\n\t\tvec4 ndcPos = projMatrix * viewMatrix * vec4( refractedRayExit, 1.0 );\n\t\tvec2 refractionCoords = ndcPos.xy / ndcPos.w;\n\t\trefractionCoords += 1.0;\n\t\trefractionCoords /= 2.0;\n\n\t\t// Sample framebuffer to get pixel the refracted ray hits.\n\t\tvec4 transmittedLight = getTransmissionSample( refractionCoords, roughness, ior );\n\n\t\tvec3 transmittance = diffuseColor * volumeAttenuation( length( transmissionRay ), attenuationColor, attenuationDistance );\n\t\tvec3 attenuatedColor = transmittance * transmittedLight.rgb;\n\n\t\t// Get the specular component.\n\t\tvec3 F = EnvironmentBRDF( n, v, specularColor, specularF90, roughness );\n\n\t\t// As less light is transmitted, the opacity should be increased. This simple approximation does a decent job \n\t\t// of modulating a CSS background, and has no effect when the buffer is opaque, due to a solid object or clear color.\n\t\tfloat transmittanceFactor = ( transmittance.r + transmittance.g + transmittance.b ) / 3.0;\n\n\t\treturn vec4( ( 1.0 - F ) * attenuatedColor, 1.0 - ( 1.0 - transmittedLight.a ) * transmittanceFactor );\n\n\t}\n#endif","#ifdef USE_TRANSMISSION\n\nmaterial.transmission = _transmission;\nmaterial.transmissionAlpha = 1.0;\nmaterial.thickness = thickness;\nmaterial.attenuationDistance = attenuationDistance;\nmaterial.attenuationColor = attenuationColor;\n\n#ifdef USE_TRANSMISSIONMAP\n\n\tmaterial.transmission *= texture2D( transmissionMap, vTransmissionMapUv ).r;\n\n#endif\n\n#ifdef USE_THICKNESSMAP\n\n\tmaterial.thickness *= texture2D( thicknessMap, vThicknessMapUv ).g;\n\n#endif\n\nvec3 pos = vWorldPosition;\n\nvec3 v = normalize( cameraPosition - pos );\nvec3 n = inverseTransformDirection( normal, viewMatrix );\n\nvec4 transmitted = getIBLVolumeRefraction(\n\tn, v, material.roughness, material.diffuseColor, material.specularColor, material.specularF90,\n\tpos, modelMatrix, viewMatrix, projectionMatrix, material.ior, material.thickness,\n\tmaterial.attenuationColor, material.attenuationDistance );\n\nmaterial.transmissionAlpha = mix( material.transmissionAlpha, transmitted.a, material.transmission );\n\n// Custom from here\nfloat runningSeed = 0.0;\nvec3 transmission = vec3(0.0);\nfloat transmissionR, transmissionB, transmissionG;\nfloat randomCoords = rand(runningSeed++);\nfloat thickness_smear = thickness * max(pow(roughnessFactor, 0.33), uAnisotropicBlur);\nvec3 distortionNormal = vec3(0.0);\nvec3 temporalOffset = vec3(uTime, -uTime, -uTime) * uTemporalDistortion;\n\nif (uDistortion > 0.0) {\n\tdistortionNormal = uDistortion * vec3(snoiseFractal(vec3((pos * uDistortionScale + temporalOffset))), snoiseFractal(vec3(pos.zxy * uDistortionScale - temporalOffset)), snoiseFractal(vec3(pos.yxz * uDistortionScale + temporalOffset)));\n}\n\nfor (float i = 0.0; i < uRefractionSamples; i ++) {\n\tvec3 sampleNorm = normalize(n + roughnessFactor * roughnessFactor * 2.0 * normalize(vec3(rand(runningSeed++) - 0.5, rand(runningSeed++) - 0.5, rand(runningSeed++) - 0.5)) * pow(rand(runningSeed++), 0.33) + distortionNormal);\n\t\n\ttransmissionR = getIBLVolumeRefraction(\n\t\tsampleNorm, v, material.roughness, material.diffuseColor, material.specularColor, material.specularF90,\n\t\tpos, modelMatrix, viewMatrix, projectionMatrix, material.ior, material.thickness + thickness_smear * (i + randomCoords) / uRefractionSamples,\n\t\tmaterial.attenuationColor, material.attenuationDistance\n\t).r;\n\ttransmissionG = getIBLVolumeRefraction(\n\t\tsampleNorm, v, material.roughness, material.diffuseColor, material.specularColor, material.specularF90,\n\t\tpos, modelMatrix, viewMatrix, projectionMatrix, material.ior * (1.0 + uChromaticAberration * (i + randomCoords) / uRefractionSamples) , material.thickness + thickness_smear * (i + randomCoords) / uRefractionSamples,\n\t\tmaterial.attenuationColor, material.attenuationDistance\n\t).g;\n\ttransmissionB = getIBLVolumeRefraction(\n\t\tsampleNorm, v, material.roughness, material.diffuseColor, material.specularColor, material.specularF90,\n\t\tpos, modelMatrix, viewMatrix, projectionMatrix, material.ior * (1.0 + 2.0 * uChromaticAberration * (i + randomCoords) / uRefractionSamples), material.thickness + thickness_smear * (i + randomCoords) / uRefractionSamples,\n\t\tmaterial.attenuationColor, material.attenuationDistance\n\t).b;\n\ttransmission.r += transmissionR;\n\ttransmission.g += transmissionG;\n\ttransmission.b += transmissionB;\n}\n\ntransmission /= uRefractionSamples;\n// to here\n\ntotalDiffuse = mix( totalDiffuse, transmission.rgb, material.transmission );\n\n#endif","import * as THREE from \"three\";\nimport transmission_pars_fragment from \"../shaders/transmission_pars_fragment.glsl\";\nimport transmission_fragment from \"../shaders/transmission_fragment.glsl\";\n\nexport const resolveEachMaterial = ({\n mat,\n isCustomTransmission,\n parameters,\n}: {\n mat: THREE.Material;\n isCustomTransmission: boolean;\n parameters: THREE.WebGLProgramParametersWithUniforms;\n}) => {\n // custom transmission\n if (mat.type === \"MeshPhysicalMaterial\" && isCustomTransmission) {\n parameters.fragmentShader = parameters.fragmentShader.replace(\n \"#include \",\n `${transmission_pars_fragment}`\n );\n\n parameters.fragmentShader = parameters.fragmentShader.replace(\n \"#include \",\n `${transmission_fragment}`\n );\n }\n\n // if normalMap is defined, don't add tangent attribute\n if (!(mat as any).normalMap) {\n parameters.vertexShader = parameters.vertexShader.replace(\n \"void main() {\",\n `\n\t\t\t\tattribute vec4 tangent;\n\t\t\t\t\n\t\t\t\tvoid main() {\n\t\t\t`\n );\n }\n};\n","import * as THREE from \"three\";\nimport { useEffect, useMemo } from \"react\";\nimport { WOBBLE3D_PARAMS } from \".\";\nimport { MaterialProps, OnBeforeInitParameters } from \"../../types\";\nimport { createMaterialParameters } from \"../../../utils/createMaterialParameters\";\nimport { rewriteVertexShader } from \"./utils/rewriteVertexShader\";\nimport { rewriteFragmentShader } from \"./utils/rewriteFragmentShader\";\nimport { resolveEachMaterial } from \"./utils/resolveEachMaterial\";\n\nexport class Wobble3DMaterial extends THREE.Material {\n uniforms!: {\n uTime: { value: number };\n uWobblePositionFrequency: { value: number };\n uWobbleTimeFrequency: { value: number };\n uWobbleStrength: { value: number };\n uWarpPositionFrequency: { value: number };\n uWarpTimeFrequency: { value: number };\n uWarpStrength: { value: number };\n uColor0: { value: THREE.Color };\n uColor1: { value: THREE.Color };\n uColor2: { value: THREE.Color };\n uColor3: { value: THREE.Color };\n uColorMix: { value: number };\n uEdgeThreshold: { value: number };\n uEdgeColor: { value: THREE.Color };\n uChromaticAberration: { value: number };\n uAnisotropicBlur: { value: number };\n uDistortion: { value: number };\n uDistortionScale: { value: number };\n uTemporalDistortion: { value: number };\n uRefractionSamples: { value: number };\n };\n}\n\nexport type WobbleMaterialConstructor = new (opts: {\n [key: string]: any;\n}) => THREE.Material;\n\ntype WobbleMaterialParams =\n ConstructorParameters[0];\n\nexport interface WobbleMaterialProps\n extends MaterialProps {\n /** default:THREE.MeshPhysicalMaterial */\n baseMaterial?: T;\n materialParameters?: WobbleMaterialParams;\n depthOnBeforeInit?: (parameters: OnBeforeInitParameters) => void;\n /**\n * Whether to apply more advanced `transmission` or not. valid only for `MeshPhysicalMaterial`. This is a function referring to `drei/MeshTransmissionMaterial`, default : `false`\n * @link https://github.com/pmndrs/drei?tab=readme-ov-file#meshtransmissionmaterial\n * */\n isCustomTransmission?: boolean;\n /** Whether to initialise `MeshDepthMaterial` or not , default : `false` */\n depth?: boolean;\n}\n\nexport const useMaterial = ({\n baseMaterial,\n materialParameters,\n isCustomTransmission = false,\n onBeforeInit,\n depthOnBeforeInit,\n depth = false,\n}: WobbleMaterialProps) => {\n const { material, depthMaterial } = useMemo(() => {\n const mat = new (baseMaterial || THREE.MeshPhysicalMaterial)(\n materialParameters || {}\n );\n\n Object.assign(mat.userData, {\n uniforms: {\n uTime: { value: 0 },\n uWobblePositionFrequency: {\n value: WOBBLE3D_PARAMS.wobblePositionFrequency,\n },\n uWobbleTimeFrequency: {\n value: WOBBLE3D_PARAMS.wobbleTimeFrequency,\n },\n uWobbleStrength: { value: WOBBLE3D_PARAMS.wobbleStrength },\n uWarpPositionFrequency: {\n value: WOBBLE3D_PARAMS.warpPositionFrequency,\n },\n uWarpTimeFrequency: { value: WOBBLE3D_PARAMS.warpTimeFrequency },\n uWarpStrength: { value: WOBBLE3D_PARAMS.warpStrength },\n uColor0: { value: WOBBLE3D_PARAMS.color0 },\n uColor1: { value: WOBBLE3D_PARAMS.color1 },\n uColor2: { value: WOBBLE3D_PARAMS.color2 },\n uColor3: { value: WOBBLE3D_PARAMS.color3 },\n uColorMix: { value: WOBBLE3D_PARAMS.colorMix },\n uEdgeThreshold: { value: WOBBLE3D_PARAMS.edgeThreshold },\n uEdgeColor: { value: WOBBLE3D_PARAMS.edgeColor },\n uChromaticAberration: {\n value: WOBBLE3D_PARAMS.chromaticAberration,\n },\n uAnisotropicBlur: { value: WOBBLE3D_PARAMS.anisotropicBlur },\n uDistortion: { value: WOBBLE3D_PARAMS.distortion },\n uDistortionScale: { value: WOBBLE3D_PARAMS.distortionScale },\n uTemporalDistortion: { value: WOBBLE3D_PARAMS.temporalDistortion },\n uRefractionSamples: { value: WOBBLE3D_PARAMS.refractionSamples },\n transmission: { value: 0 },\n _transmission: { value: 1 },\n transmissionMap: { value: null },\n },\n });\n\n mat.onBeforeCompile = (parameters) => {\n rewriteVertexShader(parameters);\n\n rewriteFragmentShader(parameters);\n\n resolveEachMaterial({\n parameters,\n mat,\n isCustomTransmission,\n });\n\n const cutomizedParams = createMaterialParameters(\n {\n fragmentShader: parameters.fragmentShader,\n vertexShader: parameters.vertexShader,\n // Because wobble3D uses userData to update uniforms.\n uniforms: mat.userData.uniforms,\n },\n onBeforeInit\n );\n parameters.fragmentShader = cutomizedParams.fragmentShader;\n parameters.vertexShader = cutomizedParams.vertexShader;\n Object.assign(parameters.uniforms, cutomizedParams.uniforms);\n };\n mat.needsUpdate = true;\n\n /*===============================================\n\t\tdepthMaterial\n\t\t===============================================*/\n let depthMat = null;\n if (depth) {\n depthMat = new THREE.MeshDepthMaterial({\n depthPacking: THREE.RGBADepthPacking,\n });\n depthMat.onBeforeCompile = (parameters) => {\n Object.assign(parameters.uniforms, mat.userData.uniforms);\n rewriteVertexShader(parameters);\n createMaterialParameters(parameters, depthOnBeforeInit);\n };\n depthMat.needsUpdate = true;\n }\n\n return { material: mat, depthMaterial: depthMat };\n }, [\n materialParameters,\n baseMaterial,\n onBeforeInit,\n depthOnBeforeInit,\n isCustomTransmission,\n depth,\n ]);\n\n // Only the depthMaterial is disposed of because the material is disposed of by useAddObject.\n useEffect(() => {\n return () => {\n if (depthMaterial) depthMaterial.dispose();\n };\n }, [depthMaterial]);\n\n return {\n material: material as Wobble3DMaterial,\n depthMaterial,\n };\n};\n","import * as THREE from \"three\";\nimport { RootState } from \"@react-three/fiber\";\nimport { mergeVertices } from \"three-stdlib\";\nimport {\n useMaterial,\n Wobble3DMaterial,\n WobbleMaterialProps,\n WobbleMaterialConstructor,\n} from \"./useMaterial\";\nimport { Wobble3DParams } from \".\";\nimport {\n setUniform,\n setCustomUniform,\n CustomParams,\n} from \"../../../utils/setUniforms\";\nimport { useCallback, useMemo } from \"react\";\nimport { useAddObject } from \"../../../utils/useAddObject\";\nimport { Create3DHooksProps } from \"../types\";\n\nexport type UseCreateWobble3DProps = {\n /** default : `THREE.IcosahedronGeometry(2,20)` */\n geometry?: THREE.BufferGeometry;\n};\n\ntype UpdateUniform = (\n rootState: RootState | null,\n newParams?: Wobble3DParams,\n customParams?: CustomParams\n) => void;\n\ntype UseCreateWobble3DReturn = [\n UpdateUniform,\n {\n mesh: THREE.Mesh;\n depthMaterial: THREE.MeshDepthMaterial | null;\n }\n];\n\nexport const useCreateWobble3D = ({\n scene = false,\n geometry,\n isCustomTransmission,\n baseMaterial,\n materialParameters,\n depth,\n onBeforeInit,\n depthOnBeforeInit,\n}: UseCreateWobble3DProps &\n Create3DHooksProps &\n WobbleMaterialProps): UseCreateWobble3DReturn => {\n const wobbleGeometry = useMemo(() => {\n let geo = geometry || new THREE.IcosahedronGeometry(2, 20);\n geo = mergeVertices(geo);\n geo.computeTangents();\n return geo;\n }, [geometry]);\n const { material, depthMaterial } = useMaterial({\n baseMaterial,\n materialParameters,\n isCustomTransmission,\n onBeforeInit,\n depthOnBeforeInit,\n depth,\n });\n\n const mesh = useAddObject(scene, wobbleGeometry, material, THREE.Mesh);\n\n const userData = material.userData as Wobble3DMaterial;\n\n const updateValue = setUniform(userData);\n const updateCustomValue = setCustomUniform(userData);\n\n const updateUniform = useCallback(\n (rootState, newParams, customParams) => {\n if (rootState) {\n updateValue(\n \"uTime\",\n newParams?.beat || rootState.clock.getElapsedTime()\n );\n }\n if (newParams === undefined) {\n return;\n }\n updateValue(\"uWobbleStrength\", newParams.wobbleStrength);\n updateValue(\n \"uWobblePositionFrequency\",\n newParams.wobblePositionFrequency\n );\n updateValue(\"uWobbleTimeFrequency\", newParams.wobbleTimeFrequency);\n updateValue(\"uWarpStrength\", newParams.warpStrength);\n updateValue(\"uWarpPositionFrequency\", newParams.warpPositionFrequency);\n updateValue(\"uWarpTimeFrequency\", newParams.warpTimeFrequency);\n updateValue(\"uColor0\", newParams.color0);\n updateValue(\"uColor1\", newParams.color1);\n updateValue(\"uColor2\", newParams.color2);\n updateValue(\"uColor3\", newParams.color3);\n updateValue(\"uColorMix\", newParams.colorMix);\n updateValue(\"uEdgeThreshold\", newParams.edgeThreshold);\n updateValue(\"uEdgeColor\", newParams.edgeColor);\n updateValue(\"uChromaticAberration\", newParams.chromaticAberration);\n updateValue(\"uAnisotropicBlur\", newParams.anisotropicBlur);\n updateValue(\"uDistortion\", newParams.distortion);\n updateValue(\"uDistortionScale\", newParams.distortionScale);\n updateValue(\"uRefractionSamples\", newParams.refractionSamples);\n updateValue(\"uTemporalDistortion\", newParams.temporalDistortion);\n\n updateCustomValue(customParams);\n },\n [updateValue, updateCustomValue]\n );\n\n return [\n updateUniform,\n {\n mesh,\n depthMaterial,\n },\n ];\n};\n","import * as THREE from \"three\";\nimport { useCallback, useMemo } from \"react\";\nimport { RootState } from \"@react-three/fiber\";\nimport { useSingleFBO } from \"../../../utils/useSingleFBO\";\nimport { HooksReturn } from \"../../types\";\nimport { useCreateWobble3D, UseCreateWobble3DProps } from \"./useCreateWobble3D\";\nimport { WobbleMaterialProps, WobbleMaterialConstructor } from \"./useMaterial\";\nimport { HooksProps3D } from \"../types\";\nimport { getDpr } from \"../../../utils/getDpr\";\nimport { CustomParams } from \"../../../utils/setUniforms\";\n\nexport type Wobble3DParams = {\n /** default : `0.3` */\n wobbleStrength?: number;\n /** default : `0.3` */\n wobblePositionFrequency?: number;\n /** default : `0.3` */\n wobbleTimeFrequency?: number;\n /** default : `0.3` */\n warpStrength?: number;\n /** default : `0.3` */\n warpPositionFrequency?: number;\n /** default : `0.3` */\n warpTimeFrequency?: number;\n color0?: THREE.Color;\n color1?: THREE.Color;\n color2?: THREE.Color;\n color3?: THREE.Color;\n /** Mixing ratio with the material's original output color, 0~1 , defaulat : `1` */\n colorMix?: number;\n /** Threshold of edge. 0 for edge disabled, default : `0` */\n edgeThreshold?: number;\n /** Color of edge. default : `0x000000` */\n edgeColor?: THREE.Color;\n /** you can get into the rhythm ♪ , default : `false` */\n beat?: number | false;\n /** valid only for `MeshPhysicalMaterial` && `isCustomTransmission:true` , default : `0.1` */\n chromaticAberration?: number;\n /** valid only for `MeshPhysicalMaterial` && `isCustomTransmission:true` , default : `0.1` */\n anisotropicBlur?: number;\n /** valid only for `MeshPhysicalMaterial` && `isCustomTransmission:true` , default : `0.0` */\n distortion?: number;\n /** valid only for `MeshPhysicalMaterial` && `isCustomTransmission:true` , default : `0.1` */\n distortionScale?: number;\n /** valid only for `MeshPhysicalMaterial` && `isCustomTransmission:true` , default : `0.0` */\n temporalDistortion?: number;\n /** valid only for `MeshPhysicalMaterial` && `isCustomTransmission:true` , default : `6` */\n refractionSamples?: number;\n};\n\nexport type Wobble3DObject = {\n scene: THREE.Scene;\n mesh: THREE.Mesh;\n depthMaterial: THREE.MeshDepthMaterial | null;\n renderTarget: THREE.WebGLRenderTarget;\n output: THREE.Texture;\n};\n\nexport const WOBBLE3D_PARAMS: Wobble3DParams = Object.freeze({\n wobbleStrength: 0.3,\n wobblePositionFrequency: 0.3,\n wobbleTimeFrequency: 0.3,\n warpStrength: 0.3,\n warpPositionFrequency: 0.3,\n warpTimeFrequency: 0.3,\n color0: new THREE.Color(0xff0000),\n color1: new THREE.Color(0x00ff00),\n color2: new THREE.Color(0x0000ff),\n color3: new THREE.Color(0xffff00),\n colorMix: 1,\n edgeThreshold: 0.0,\n edgeColor: new THREE.Color(0x000000),\n chromaticAberration: 0.1,\n anisotropicBlur: 0.1,\n distortion: 0.0,\n distortionScale: 0.1,\n temporalDistortion: 0.0,\n refractionSamples: 6,\n beat: false,\n});\n\n/**\n * @link https://github.com/FunTechInc/use-shader-fx\n */\nexport const useWobble3D = ({\n size,\n dpr,\n renderTargetOptions,\n isSizeUpdate,\n camera,\n geometry,\n baseMaterial,\n materialParameters,\n isCustomTransmission,\n onBeforeInit,\n depthOnBeforeInit,\n depth,\n}: HooksProps3D & UseCreateWobble3DProps & WobbleMaterialProps): HooksReturn<\n Wobble3DParams,\n Wobble3DObject,\n CustomParams\n> => {\n const _dpr = getDpr(dpr);\n\n const scene = useMemo(() => new THREE.Scene(), []);\n\n const [updateUniform, { mesh, depthMaterial }] = useCreateWobble3D({\n baseMaterial,\n materialParameters,\n scene,\n geometry,\n isCustomTransmission,\n onBeforeInit,\n depthOnBeforeInit,\n depth,\n });\n\n const [renderTarget, updateRenderTarget] = useSingleFBO({\n scene,\n camera,\n size,\n dpr: _dpr.fbo,\n isSizeUpdate,\n depthBuffer: true,\n ...renderTargetOptions,\n });\n\n const updateFx = useCallback(\n (\n RootState: RootState,\n newParams?: Wobble3DParams,\n customParams?: CustomParams\n ) => {\n updateUniform(RootState, newParams, customParams);\n return updateRenderTarget(RootState.gl);\n },\n [updateRenderTarget, updateUniform]\n );\n\n const updateParams = useCallback(\n (newParams?: Wobble3DParams, customParams?: CustomParams) => {\n updateUniform(null, newParams, customParams);\n },\n [updateUniform]\n );\n\n return [\n updateFx,\n updateParams,\n {\n scene,\n mesh,\n depthMaterial,\n renderTarget,\n output: renderTarget.texture,\n },\n ];\n};\n","import * as THREE from \"three\";\nimport { useEffect, useMemo } from \"react\";\n\n/** Generate mesh from geometry and material and add to scene */\nexport const useAddMesh = (\n scene: THREE.Scene,\n geometry: THREE.BufferGeometry,\n material: THREE.Material\n) => {\n const mesh = useMemo(() => {\n const mesh = new THREE.Mesh(geometry, material);\n scene.add(mesh);\n return mesh;\n }, [geometry, material, scene]);\n\n useEffect(() => {\n return () => {\n scene.remove(mesh);\n geometry.dispose();\n material.dispose();\n };\n }, [scene, geometry, material, mesh]);\n\n return mesh;\n};\n","import { useMemo, useRef } from \"react\";\nimport { Size } from \"../fxs/types\";\n\nconst checkUpdate = (\n currentW: number,\n currentH: number,\n memoW: number,\n memoH: number,\n threshold: number,\n boundFor: \"smaller\" | \"larger\" | \"both\"\n) => {\n const isSmaller =\n currentW < memoW - threshold || currentH < memoH - threshold;\n const isLarger =\n currentW > memoW + threshold || currentH > memoH + threshold;\n\n return (\n (boundFor === \"smaller\" && isSmaller) ||\n (boundFor === \"larger\" && isLarger) ||\n (boundFor === \"both\" && (isSmaller || isLarger))\n );\n};\n\nexport const useResizeBoundary = ({\n size,\n boundFor,\n threshold,\n}: {\n size: Size;\n boundFor: \"smaller\" | \"larger\" | \"both\";\n threshold: number;\n}) => {\n const memorizedSize = useRef(size);\n\n const isBeyondBoundary = useMemo(() => {\n const { width: currentW, height: currentH } = size;\n const { width: memoW, height: memoH } = memorizedSize.current;\n\n const isUpdate = checkUpdate(\n currentW,\n currentH,\n memoW,\n memoH,\n threshold,\n boundFor\n );\n\n if (isUpdate) {\n memorizedSize.current = size;\n }\n return isUpdate;\n }, [size, boundFor, threshold]);\n\n return isBeyondBoundary;\n};\n","export type EasingTypes =\n | \"easeInSine\"\n | \"easeOutSine\"\n | \"easeInOutSine\"\n | \"easeInQuad\"\n | \"easeOutQuad\"\n | \"easeInOutQuad\"\n | \"easeInCubic\"\n | \"easeOutCubic\"\n | \"easeInOutCubic\"\n | \"easeInQuart\"\n | \"easeOutQuart\"\n | \"easeInOutQuart\"\n | \"easeInQuint\"\n | \"easeOutQuint\"\n | \"easeInOutQuint\"\n | \"easeInExpo\"\n | \"easeOutExpo\"\n | \"easeInOutExpo\"\n | \"easeInCirc\"\n | \"easeOutCirc\"\n | \"easeInOutCirc\"\n | \"easeInBack\"\n | \"easeOutBack\"\n | \"easeInOutBack\"\n | \"easeInElastic\"\n | \"easeOutElastic\"\n | \"easeInOutElastic\"\n | \"easeInBounce\"\n | \"easeOutBounce\"\n | \"easeInOutBounce\";\n\ntype EasingFunctions = {\n [K in EasingTypes]: (x: number) => number;\n};\n\n/**\n * from https://github.com/ai/easings.net\n */\nexport const Easing: EasingFunctions = Object.freeze({\n easeInSine(x: number): number {\n return 1 - Math.cos((x * Math.PI) / 2);\n },\n easeOutSine(x: number): number {\n return Math.sin((x * Math.PI) / 2);\n },\n easeInOutSine(x: number): number {\n return -(Math.cos(Math.PI * x) - 1) / 2;\n },\n easeInQuad(x: number): number {\n return x * x;\n },\n easeOutQuad(x: number): number {\n return 1 - (1 - x) * (1 - x);\n },\n easeInOutQuad(x: number): number {\n return x < 0.5 ? 2 * x * x : 1 - Math.pow(-2 * x + 2, 2) / 2;\n },\n easeInCubic(x: number): number {\n return x * x * x;\n },\n easeOutCubic(x: number): number {\n return 1 - Math.pow(1 - x, 3);\n },\n easeInOutCubic(x: number): number {\n return x < 0.5 ? 4 * x * x * x : 1 - Math.pow(-2 * x + 2, 3) / 2;\n },\n easeInQuart(x: number): number {\n return x * x * x * x;\n },\n easeOutQuart(x: number): number {\n return 1 - Math.pow(1 - x, 4);\n },\n easeInOutQuart(x: number): number {\n return x < 0.5 ? 8 * x * x * x * x : 1 - Math.pow(-2 * x + 2, 4) / 2;\n },\n easeInQuint(x: number): number {\n return x * x * x * x * x;\n },\n easeOutQuint(x: number): number {\n return 1 - Math.pow(1 - x, 5);\n },\n easeInOutQuint(x: number): number {\n return x < 0.5 ? 16 * x * x * x * x * x : 1 - Math.pow(-2 * x + 2, 5) / 2;\n },\n easeInExpo(x: number): number {\n return x === 0 ? 0 : Math.pow(2, 10 * x - 10);\n },\n easeOutExpo(x: number): number {\n return x === 1 ? 1 : 1 - Math.pow(2, -10 * x);\n },\n easeInOutExpo(x: number): number {\n return x === 0\n ? 0\n : x === 1\n ? 1\n : x < 0.5\n ? Math.pow(2, 20 * x - 10) / 2\n : (2 - Math.pow(2, -20 * x + 10)) / 2;\n },\n easeInCirc(x: number): number {\n return 1 - Math.sqrt(1 - Math.pow(x, 2));\n },\n easeOutCirc(x: number): number {\n return Math.sqrt(1 - Math.pow(x - 1, 2));\n },\n easeInOutCirc(x: number): number {\n return x < 0.5\n ? (1 - Math.sqrt(1 - Math.pow(2 * x, 2))) / 2\n : (Math.sqrt(1 - Math.pow(-2 * x + 2, 2)) + 1) / 2;\n },\n easeInBack(x: number): number {\n const c1 = 1.70158;\n const c3 = c1 + 1;\n\n return c3 * x * x * x - c1 * x * x;\n },\n easeOutBack(x: number): number {\n const c1 = 1.70158;\n const c3 = c1 + 1;\n\n return 1 + c3 * Math.pow(x - 1, 3) + c1 * Math.pow(x - 1, 2);\n },\n easeInOutBack(x: number): number {\n const c1 = 1.70158;\n const c2 = c1 * 1.525;\n\n return x < 0.5\n ? (Math.pow(2 * x, 2) * ((c2 + 1) * 2 * x - c2)) / 2\n : (Math.pow(2 * x - 2, 2) * ((c2 + 1) * (x * 2 - 2) + c2) + 2) / 2;\n },\n easeInElastic(x: number): number {\n const c4 = (2 * Math.PI) / 3;\n\n return x === 0\n ? 0\n : x === 1\n ? 1\n : -Math.pow(2, 10 * x - 10) * Math.sin((x * 10 - 10.75) * c4);\n },\n easeOutElastic(x: number): number {\n const c4 = (2 * Math.PI) / 3;\n\n return x === 0\n ? 0\n : x === 1\n ? 1\n : Math.pow(2, -10 * x) * Math.sin((x * 10 - 0.75) * c4) + 1;\n },\n easeInOutElastic(x: number): number {\n const c5 = (2 * Math.PI) / 4.5;\n\n return x === 0\n ? 0\n : x === 1\n ? 1\n : x < 0.5\n ? -(Math.pow(2, 20 * x - 10) * Math.sin((20 * x - 11.125) * c5)) / 2\n : (Math.pow(2, -20 * x + 10) * Math.sin((20 * x - 11.125) * c5)) / 2 +\n 1;\n },\n easeInBounce(x: number): number {\n return 1 - Easing.easeOutBounce(1 - x);\n },\n easeOutBounce(x: number): number {\n const n1 = 7.5625;\n const d1 = 2.75;\n\n if (x < 1 / d1) {\n return n1 * x * x;\n } else if (x < 2 / d1) {\n return n1 * (x -= 1.5 / d1) * x + 0.75;\n } else if (x < 2.5 / d1) {\n return n1 * (x -= 2.25 / d1) * x + 0.9375;\n } else {\n return n1 * (x -= 2.625 / d1) * x + 0.984375;\n }\n },\n easeInOutBounce(x: number): number {\n return x < 0.5\n ? (1 - Easing.easeOutBounce(1 - 2 * x)) / 2\n : (1 + Easing.easeOutBounce(2 * x - 1)) / 2;\n },\n});\n","import * as THREE from \"three\";\nimport { Easing, EasingTypes } from \"../libs/Easings\";\nimport { useCallback } from \"react\";\n\n/** Returns a unique hash specific to the beat */\nfunction getHash(input: number) {\n let n = Math.sin(input * 12.9898) * 43758.5453;\n return n - Math.floor(n);\n}\n\ntype BeatValues = {\n beat: number;\n floor: number;\n fract: number;\n /** unique hash specific to the beat */\n hash: number;\n};\n\n/**\n * @param ease easing functions are referenced from https://github.com/ai/easings.net , default : \"easeOutQuart\"\n */\nexport const useBeat = (bpm: number, ease: EasingTypes = \"easeOutQuart\") => {\n const rhythm = bpm / 60;\n const easing = Easing[ease];\n const updateBeat = useCallback(\n (clock: THREE.Clock) => {\n let beat = clock.getElapsedTime() * rhythm;\n const floor = Math.floor(beat);\n const fract = easing(beat - floor);\n beat = fract + floor;\n const hash = getHash(floor);\n return {\n beat,\n floor,\n fract,\n hash,\n } as BeatValues;\n },\n [rhythm, easing]\n );\n return updateBeat;\n};\n","import * as THREE from \"three\";\nimport { useCallback, useMemo, useRef } from \"react\";\n\n/**\n * @param fps FPS you want to limit , default : `60`\n *\n * ```tsx\n * const limiter = useFPSLimiter(fps);\n * useFrame((props) => {\n * if (limiter(props.clock)) {\n *\t\t //some code\n * }\n * });\n * ```\n */\nexport const useFPSLimiter = (fps: number = 60) => {\n const interval = useMemo(() => 1 / Math.max(Math.min(fps, 60), 1), [fps]);\n const prevTime = useRef(null);\n\n const limiter = useCallback(\n (clock: THREE.Clock) => {\n const tick = clock.getElapsedTime();\n if (prevTime.current === null) {\n prevTime.current = tick;\n return true;\n }\n const deltaTime = tick - prevTime.current;\n if (deltaTime >= interval) {\n prevTime.current = tick;\n return true;\n }\n return false;\n },\n [interval]\n );\n\n return limiter;\n};\n","import { DomSyncerParams } from \"..\";\n\nexport const errorHandler = (params: DomSyncerParams) => {\n const domLength = params.dom?.length;\n const textureLength = params.texture?.length;\n\n if (!domLength || !textureLength) {\n return true;\n }\n\n if (domLength !== textureLength) {\n return true;\n }\n\n return false;\n};\n","varying vec2 vUv;\n\nvoid main() {\n\tvUv = uv;\n\tgl_Position = projectionMatrix * viewMatrix * modelMatrix * vec4(position, 1.0);\n}","precision highp float;\n\nvarying vec2 vUv;\nuniform sampler2D u_texture;\nuniform vec2 u_textureResolution;\nuniform vec2 u_resolution;\nuniform float u_borderRadius;\n\nvoid main() {\n\t// texuture color\n\tfloat screenAspect = u_resolution.x / u_resolution.y;\n\tfloat textureAspect = u_textureResolution.x / u_textureResolution.y;\n\tvec2 ratio = vec2(\n\t\tmin(screenAspect / textureAspect, 1.0),\n\t\tmin(textureAspect / screenAspect, 1.0)\n\t);\n\n\tvec2 adjustedUv = vUv * ratio + (1.0 - ratio) * 0.5;\n\tvec3 textureColor = texture2D(u_texture, adjustedUv).rgb;\n\tfloat textureAlpha = texture2D(u_texture, adjustedUv).a;\n\n\t// Based on https://mofu-dev.com/en/blog/three-dom-alignment/\n\tfloat maxSide = max(u_resolution.x, u_resolution.y);\n\tfloat minSide = min(u_resolution.x, u_resolution.y);\n\tvec2 aspect = u_resolution / maxSide;\n\tvec2 alphaUv = vUv - 0.5;\n\n\tfloat borderRadius = min(u_borderRadius, minSide * 0.5);\n\tvec2 offset = vec2(borderRadius) / u_resolution;\n\tvec2 alphaXY = smoothstep(vec2(0.5 - offset), vec2(0.5 - offset - 0.001), abs(alphaUv));\n\tfloat alpha = min(1.0, alphaXY.x + alphaXY.y);\n\n\tvec2 alphaUv2 = abs(vUv - 0.5);\n\tfloat radius = borderRadius / maxSide;\n\talphaUv2 = (alphaUv2 - 0.5) * aspect + radius;\n\tfloat roundAlpha = smoothstep(radius + 0.001, radius, length(alphaUv2));\n\n\talpha = min(1.0, alpha + roundAlpha);\n\n\t// multiply texture alpha\n\talpha *= textureAlpha;\n\n\tgl_FragColor = vec4(textureColor, alpha);\n}\n","import * as THREE from \"three\";\nimport { DomSyncerParams } from \"../\";\nimport vertexShader from \"../shader/main.vert\";\nimport fragmentShader from \"../shader/main.frag\";\nimport { MaterialProps, Size } from \"../../../fxs/types\";\nimport { MATERIAL_BASIC_PARAMS } from \"../../../libs/constants\";\nimport { createMaterialParameters } from \"../../../utils/createMaterialParameters\";\n\nexport class DomSyncerMaterial extends THREE.ShaderMaterial {\n uniforms!: {\n u_texture: { value: THREE.Texture };\n u_textureResolution: { value: THREE.Vector2 };\n u_resolution: { value: THREE.Vector2 };\n u_borderRadius: { value: number };\n };\n}\n\nexport const createMesh = ({\n params,\n scene,\n onBeforeInit,\n}: {\n params: DomSyncerParams;\n size: Size;\n scene: THREE.Scene;\n} & MaterialProps) => {\n if (scene.children.length > 0) {\n scene.children.forEach((child) => {\n if (child instanceof THREE.Mesh) {\n child.geometry.dispose();\n child.material.dispose();\n }\n });\n scene.remove(...scene.children);\n }\n\n params.texture!.forEach((texture, i) => {\n const mat = new THREE.ShaderMaterial({\n ...createMaterialParameters(\n {\n uniforms: {\n u_texture: { value: texture },\n u_textureResolution: {\n value: new THREE.Vector2(0, 0),\n },\n u_resolution: { value: new THREE.Vector2(0, 0) },\n u_borderRadius: {\n value: params.boderRadius![i]\n ? params.boderRadius![i]\n : 0.0,\n },\n },\n vertexShader: vertexShader,\n fragmentShader: fragmentShader,\n },\n onBeforeInit\n ),\n ...MATERIAL_BASIC_PARAMS,\n // Must be transparent.\n transparent: true,\n });\n\n const mesh = new THREE.Mesh(new THREE.PlaneGeometry(1, 1), mat);\n scene.add(mesh);\n });\n};\n","import { useCallback, useRef } from \"react\";\nimport { DomSyncerParams } from \"..\";\n\nexport const useIntersectionHandler = () => {\n const intersectionObserverRef = useRef([]);\n const intersectionDomRef = useRef<(HTMLElement | Element | null)[]>([]);\n\n const intersectionHandler = useCallback(\n ({\n isIntersectingRef,\n isIntersectingOnceRef,\n params,\n }: {\n isIntersectingRef: React.MutableRefObject;\n isIntersectingOnceRef: React.MutableRefObject;\n params: DomSyncerParams;\n }) => {\n if (intersectionObserverRef.current.length > 0) {\n intersectionObserverRef.current.forEach((observer, i) => {\n observer.unobserve(intersectionDomRef.current[i]!);\n });\n }\n\n intersectionDomRef.current = [];\n intersectionObserverRef.current = [];\n\n const newArr = new Array(params.dom!.length).fill(false);\n isIntersectingRef.current = [...newArr];\n isIntersectingOnceRef.current = [...newArr];\n\n params.dom!.forEach((dom, i) => {\n const callback = (entries: IntersectionObserverEntry[]) => {\n entries.forEach((entry) => {\n params.onIntersect![i] && params.onIntersect![i](entry);\n // Update the judgment after execution so that the judgment of isIntersectin can be used when executing onIntersect\n isIntersectingRef.current[i] = entry.isIntersecting;\n });\n };\n const observer = new IntersectionObserver(callback, {\n rootMargin: \"0px\",\n threshold: 0,\n });\n observer.observe(dom!);\n intersectionObserverRef.current.push(observer);\n intersectionDomRef.current.push(dom!);\n });\n },\n []\n );\n\n return intersectionHandler;\n};\n","import * as THREE from \"three\";\nimport { DomSyncerParams } from \"..\";\nimport {\n CustomParams,\n setCustomUniform,\n setUniform,\n} from \"../../../utils/setUniforms\";\nimport { DomSyncerMaterial } from \"./createMesh\";\nimport { useCallback, useRef } from \"react\";\nimport { Size } from \"../../../fxs/types\";\n\ntype UpdateDomRect = ({\n params,\n customParams,\n size,\n resolutionRef,\n scene,\n isIntersectingRef,\n}: {\n params: DomSyncerParams;\n customParams?: CustomParams;\n size: Size;\n resolutionRef: React.MutableRefObject;\n scene: THREE.Scene;\n isIntersectingRef: React.MutableRefObject;\n}) => void;\n\ntype UseUpdateDomRectReturn = [DOMRect[], UpdateDomRect];\n\nexport const useUpdateDomRect = (): UseUpdateDomRectReturn => {\n const domRects = useRef([]);\n\n const updateDomRects: UpdateDomRect = useCallback(\n ({\n params,\n customParams,\n size,\n resolutionRef,\n scene,\n isIntersectingRef,\n }) => {\n // Initialize domRects if the number of children in the scene is different from the number of DOMRect\n if (scene.children.length !== domRects.current!.length) {\n domRects.current = new Array(scene.children.length);\n }\n\n scene.children.forEach((mesh, i) => {\n const domElement = params.dom![i];\n if (!domElement) {\n return;\n }\n\n // DOMRect is updated even outside the intersection\n const rect = domElement.getBoundingClientRect();\n domRects.current[i] = rect;\n\n // Intersection cannot be determined accurately depending on the mobile navigation bar, so it seems better to update it constantly\n mesh.scale.set(rect.width, rect.height, 1.0);\n mesh.position.set(\n rect.left + rect.width * 0.5 - size.width * 0.5,\n -rect.top - rect.height * 0.5 + size.height * 0.5,\n 0.0\n );\n\n if (isIntersectingRef.current[i]) {\n if (params.rotation![i]) {\n mesh.rotation.copy(params.rotation![i]);\n }\n\n if (mesh instanceof THREE.Mesh) {\n const material: DomSyncerMaterial = mesh.material;\n const updateValue = setUniform(material);\n const updateCustomValue = setCustomUniform(material);\n updateValue(\"u_texture\", params.texture![i]);\n updateValue(\"u_textureResolution\", [\n params.texture![i]?.source?.data?.width || 0,\n params.texture![i]?.source?.data?.height || 0,\n ]);\n updateValue(\n \"u_resolution\",\n resolutionRef.current.set(rect.width, rect.height)\n );\n updateValue(\n \"u_borderRadius\",\n params.boderRadius![i] ? params.boderRadius![i] : 0.0\n );\n updateCustomValue(customParams);\n }\n }\n });\n },\n []\n );\n\n return [domRects.current, updateDomRects];\n};\n","import { useCallback, useRef } from \"react\";\n\nexport type IsIntersecting = (\n index: number,\n once?: boolean\n) => boolean[] | boolean;\n\nexport const useIsIntersecting = () => {\n const isIntersectingRef = useRef([]);\n const isIntersectingOnceRef = useRef([]);\n\n const isIntersecting: IsIntersecting = useCallback((index, once = false) => {\n isIntersectingRef.current.forEach((value, i) => {\n if (value) {\n isIntersectingOnceRef.current[i] = true;\n }\n });\n const temp = once\n ? [...isIntersectingOnceRef.current]\n : [...isIntersectingRef.current];\n return index < 0 ? temp : temp[index];\n }, []);\n\n return {\n isIntersectingRef,\n isIntersectingOnceRef,\n isIntersecting,\n };\n};\n","import { useEffect, useRef } from \"react\";\n\nexport type UseDomViewProps = {\n onView?: () => void;\n onHidden?: () => void;\n};\n\nexport type UseDomView = (props: UseDomViewProps) => void;\n\nexport const createUseDomView = (\n isIntersectingRef: React.MutableRefObject\n): UseDomView => {\n const useDomView = ({ onView, onHidden }: UseDomViewProps) => {\n const isView = useRef(false);\n useEffect(() => {\n let id: number;\n const filterIntersection = () => {\n if (isIntersectingRef.current.some((item) => item)) {\n if (!isView.current) {\n onView && onView();\n isView.current = true;\n }\n } else {\n if (isView.current) {\n onHidden && onHidden();\n isView.current = false;\n }\n }\n id = requestAnimationFrame(filterIntersection);\n };\n id = requestAnimationFrame(filterIntersection);\n return () => {\n cancelAnimationFrame(id);\n };\n }, [onView, onHidden]);\n };\n return useDomView;\n};\n","import * as THREE from \"three\";\nimport { useCallback, useMemo, useRef, useState, Key } from \"react\";\nimport { useCamera } from \"../../utils/useCamera\";\nimport { RootState } from \"@react-three/fiber\";\nimport { useSingleFBO } from \"../../utils/useSingleFBO\";\nimport { HooksProps, HooksReturn } from \"../../fxs/types\";\nimport { useParams } from \"../../utils/useParams\";\nimport { errorHandler } from \"./utils/errorHandler\";\nimport { createMesh } from \"./utils/createMesh\";\nimport { useIntersectionHandler } from \"./utils/useIntersectionHandler\";\nimport { useUpdateDomRect } from \"./utils/useUpdateDomRect\";\nimport { useIsIntersecting, IsIntersecting } from \"./utils/useIsIntersecting\";\nimport { UseDomView, createUseDomView } from \"./utils/createUseDomView\";\nimport { getDpr } from \"../../utils/getDpr\";\nimport { CustomParams } from \"../../utils/setUniforms\";\nimport { DEFAULT_TEXTURE } from \"../../libs/constants\";\n\nexport type DomSyncerParams = {\n /** DOM array you want to synchronize */\n dom?: (HTMLElement | Element | null)[];\n /** Texture array that you want to synchronize with the DOM rectangle */\n texture?: THREE.Texture[];\n /** default : `0.0[]` */\n boderRadius?: number[];\n /** the angle you want to rotate */\n rotation?: THREE.Euler[];\n /** Array of callback functions when crossed */\n onIntersect?: ((entry: IntersectionObserverEntry) => void)[];\n /** Because DOM rendering and React updates occur asynchronously, there may be a lag between updating dependent arrays and setting DOM arrays. That's what the Key is for. If the dependent array is updated but the Key is not, the loop will skip and return an empty texture. By updating the timing key when DOM acquisition is complete, you can perfectly synchronize DOM and Mesh updates.updateKey must be a unique value for each update, for example `performance.now()`.*/\n updateKey?: Key;\n};\n\nexport type DomSyncerObject = {\n scene: THREE.Scene;\n camera: THREE.Camera;\n renderTarget: THREE.WebGLRenderTarget;\n output: THREE.Texture;\n /**\n * A function that returns a determination whether the DOM intersects or not.\n * The boolean will be updated after executing the onIntersect function.\n * @param index - Index of the dom for which you want to return an intersection decision. -1 will return the entire array.\n * @param once - If set to true, it will continue to return true once crossed.\n */\n isIntersecting: IsIntersecting;\n /** target's DOMRect[] */\n DOMRects: DOMRect[];\n /** target's intersetions boolean[] */\n intersections: boolean[];\n /** You can set callbacks for when at least one DOM is visible and when it is completely hidden. */\n useDomView: UseDomView;\n};\n\nexport const DOMSYNCER_PARAMS: DomSyncerParams = {\n texture: [],\n dom: [],\n boderRadius: [],\n rotation: [],\n onIntersect: [],\n};\n\n/**\n * @link https://github.com/FunTechInc/use-shader-fx?tab=readme-ov-file#usedomsyncer\n * @param dependencies - When this dependency array is changed, the mesh and intersection judgment will be updated according to the passed DOM array.\n */\nexport const useDomSyncer = (\n { size, dpr, isSizeUpdate, renderTargetOptions, onBeforeInit }: HooksProps,\n dependencies: React.DependencyList = []\n): HooksReturn => {\n const _dpr = getDpr(dpr);\n\n const scene = useMemo(() => new THREE.Scene(), []);\n const camera = useCamera(size);\n const [renderTarget, updateRenderTarget] = useSingleFBO({\n scene,\n camera,\n size,\n dpr: _dpr.fbo,\n isSizeUpdate,\n ...renderTargetOptions,\n });\n const [params, setParams] = useParams({\n ...DOMSYNCER_PARAMS,\n updateKey: performance.now(),\n });\n\n const [DOMRects, updateDomRects] = useUpdateDomRect();\n\n // Avoid instancing vec2 every frame\n const resolutionRef = useRef(new THREE.Vector2(0, 0));\n\n // Update monitored doms according to the dependency array\n const [refreshTrigger, setRefreshTrigger] = useState(true);\n useMemo(\n () => setRefreshTrigger(true),\n // eslint-disable-next-line react-hooks/exhaustive-deps\n dependencies\n );\n\n // If the dependencies have been updated but the key has not been updated, skip processing and return an empty texture\n const updateKey = useRef(null);\n const emptyTexture = useMemo(() => DEFAULT_TEXTURE, []);\n\n // set intersection\n const intersectionHandler = useIntersectionHandler();\n const { isIntersectingOnceRef, isIntersectingRef, isIntersecting } =\n useIsIntersecting();\n\n // create useDomView\n const useDomView = createUseDomView(isIntersectingRef);\n\n const updateParams = useMemo(() => {\n return (newParams?: DomSyncerParams, customParams?: CustomParams) => {\n setParams(newParams);\n updateDomRects({\n params,\n customParams,\n size,\n resolutionRef,\n scene,\n isIntersectingRef,\n });\n };\n }, [isIntersectingRef, setParams, updateDomRects, size, scene, params]);\n\n const updateFx = useCallback(\n (\n rootState: RootState,\n newParams?: DomSyncerParams,\n customParams?: CustomParams\n ) => {\n const { gl, size } = rootState;\n\n updateParams(newParams, customParams);\n\n if (errorHandler(params)) {\n return emptyTexture;\n }\n\n if (refreshTrigger) {\n if (updateKey.current === params.updateKey) {\n return emptyTexture;\n } else {\n updateKey.current = params.updateKey!;\n }\n }\n\n if (refreshTrigger) {\n createMesh({\n params,\n size,\n scene,\n onBeforeInit,\n });\n\n intersectionHandler({\n isIntersectingRef,\n isIntersectingOnceRef,\n params,\n });\n\n setRefreshTrigger(false);\n }\n\n return updateRenderTarget(gl);\n },\n [\n updateRenderTarget,\n intersectionHandler,\n onBeforeInit,\n updateParams,\n refreshTrigger,\n scene,\n params,\n isIntersectingOnceRef,\n isIntersectingRef,\n emptyTexture,\n ]\n );\n\n return [\n updateFx,\n updateParams,\n {\n scene,\n camera,\n renderTarget,\n output: renderTarget.texture,\n isIntersecting,\n DOMRects,\n intersections: isIntersectingRef.current,\n useDomView,\n },\n ];\n};\n","import * as THREE from \"three\";\nimport { useCallback, useEffect, useMemo, useRef } from \"react\";\nimport { useResolution } from \"../utils/useResolution\";\nimport {\n UseFboProps,\n renderFBO,\n FBO_DEFAULT_OPTION,\n} from \"../utils/useSingleFBO\";\n\ntype UpdateCopyFunction = (\n gl: THREE.WebGLRenderer,\n index: number,\n /** call before FBO is rendered */\n onBeforeRender?: ({ read }: { read: THREE.Texture }) => void\n) => THREE.Texture;\n\ntype UseCopyTextureReturn = [THREE.WebGLRenderTarget[], UpdateCopyFunction];\n\n/**\n * Generate an FBO array to copy the texture.\n * @param dpr If dpr is set, dpr will be multiplied, default : `false`\n * @param isSizeUpdate Whether to resize when resizing occurs. If isDpr is true, set FBO to setSize even if dpr is changed, default : `false`\n * @param length The number of FBOs to create\n * @returns [THREE.WebGLRenderTarget[] , updateCopyTexture] - Receives the RenderTarget array as the first argument and the update function as the second argument. `updateCopyTexture()` receives gl as the first argument and the index of the texture you want to copy as the second argument.\n */\nexport const useCopyTexture = (\n props: UseFboProps,\n length: number\n): UseCopyTextureReturn => {\n const {\n scene,\n camera,\n size,\n dpr = false,\n isSizeUpdate = false,\n depth = false,\n ...targetSettings\n } = props;\n\n const renderTargetArr = useRef([]);\n const resolution = useResolution(size, dpr);\n\n renderTargetArr.current = useMemo(() => {\n return Array.from({ length }, () => {\n const target = new THREE.WebGLRenderTarget(\n resolution.x,\n resolution.y,\n {\n ...FBO_DEFAULT_OPTION,\n ...targetSettings,\n }\n );\n if (depth) {\n target.depthTexture = new THREE.DepthTexture(\n resolution.x,\n resolution.y,\n THREE.FloatType\n );\n }\n return target;\n });\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [length]);\n\n if (isSizeUpdate) {\n renderTargetArr.current.forEach((fbo) =>\n fbo.setSize(resolution.x, resolution.y)\n );\n }\n\n useEffect(() => {\n const temp = renderTargetArr.current;\n return () => {\n temp.forEach((fbo) => fbo.dispose());\n };\n }, [length]);\n\n const updateCopyTexture: UpdateCopyFunction = useCallback(\n (gl, index, onBeforeRender) => {\n const fbo = renderTargetArr.current[index];\n renderFBO({\n gl,\n scene,\n camera,\n fbo,\n onBeforeRender: () =>\n onBeforeRender && onBeforeRender({ read: fbo.texture }),\n });\n return fbo.texture;\n },\n [scene, camera]\n );\n\n return [renderTargetArr.current, updateCopyTexture];\n};\n","type Utils = {\n interpolate: (\n startValue: number,\n endValue: number,\n progress: number,\n threshold?: number\n ) => number;\n smoothstep: (edge0: number, edge1: number, x: number) => number;\n};\n\nexport const Utils: Utils = Object.freeze({\n interpolate(startValue, endValue, progress, threshold = 1e-6): number {\n const t = startValue + (endValue - startValue) * progress;\n return Math.abs(t) < threshold ? 0 : t;\n },\n smoothstep(edge0, edge1, x) {\n const t = Math.min(Math.max((x - edge0) / (edge1 - edge0), 0), 1);\n return t * t * (3 - 2 * t);\n },\n});\n"],"names":["main_default","useResolution","size","dpr","_width","_height","useMemo","THREE","setUniform","material","key","value","uniforms","setCustomUniform","customParams","useAddObject","scene","geometry","Proto","object3D","obj","useEffect","ISDEV","MATERIAL_BASIC_PARAMS","DEFAULT_TEXTURE","wobble3D_default","snoise_default","coverTexture_default","fxBlending_default","planeVertex_default","defaultVertex_default","hsv2rgb_default","rgb2hsv_default","ShaderChunk","wobble3D","snoise","coverTexture","fxBlending","planeVertex","defaultVertex","hsv2rgb","rgb2hsv","includePattern","includeReplacer","match","include","resolveIncludes","string","createMaterialParameters","parameters","onBeforeInit","useMesh","BRUSH_PARAMS","vertexShader","fragmentShader","resolution","mesh","getCameraProps","width","height","frustumSize","aspect","w","h","useCamera","cameraType","near","far","usePointer","lerp","prevPointer","useRef","diffPointer","lerpPointer","lastUpdateTime","velocity","isMoved","useCallback","currentPointer","now","current","deltaTime","isUpdate","prevTemp","useParams","params","paramsRef","setParams","newParams","paramKey","FBO_DEFAULT_OPTION","renderFBO","gl","fbo","camera","onBeforeRender","onSwap","useSingleFBO","props","isSizeUpdate","depth","renderTargetOptions","renderTarget","target","_a","temp","updateRenderTarget","useDoubleFBO","read","write","_b","getDpr","useBrush","_dpr","updatePointer","pressureEnd","updateValue","updateCustomValue","updateParams","rootState","pointer","pointerValues","color","init_default","useInitialMaterial","advection_default","useAdvectionMaterial","DELTA_TIME","divergence_default","useDivergenceMaterial","pressure_default","usePressureMaterial","curl_default","useCurlMaterial","vorticity_default","useVorticityMaterial","clear_default","useClearMaterial","gradientSubtract_default","useGradientSubtractMaterial","splat_default","useSplatMaterial","useCustomMaterial","materialHook","materialProps","customFluidProps","curl","vorticity","advection","divergence","pressure","clear","gradientSubtract","splat","initialMaterial","updateMaterial","curlMaterial","vorticityMaterial","advectionMaterial","divergenceMaterial","pressureMaterial","clearMaterial","gradientSubtractMaterial","splatMaterial","materials","setMeshMaterial","FLUID_PARAMS","useFluid","fboProps","velocityFBO","updateVelocityFBO","densityFBO","updateDensityFBO","curlFBO","updateCurlFBO","divergenceFBO","updateDivergenceFBO","pressureFBO","updatePressureFBO","scaledDiffVec","spaltVec","updateParamsList","updateCustomParamsList","velocityTex","densityTex","scaledDiff","curlTex","divergenceTex","pressureTexTemp","i","scale","max","texture","meshArr","clonedMat","RIPPLE_PARAMS","useRipple","currentWave","opacity","NOISE_PARAMS","useNoise","clock","COLORSTRATA_PARAMS","useColorStrata","MARBLE_PARAMS","useMarble","COSPALETTE_PARAMS","useCosPalette","DUOTONE_PARAMS","useDuoTone","BLENDING_PARAMS","useBlending","FXTEXTURE_PARAMS","useFxTexture","tex0Res","_d","_c","tex1Res","_f","_e","_h","_g","interpolatedResolution","index","BRIGHTNESSPICKER_PARAMS","useBrightnessPicker","FXBLENDING_PARAMS","useFxBlending","ALPHABLENDING_PARAMS","useAlphaBlending","HSV_PARAMS","useHSV","COVERTEXTURE_PARAMS","useCoverTexture","SIMPLEBLUR_PARAMS","useSimpleBlur","updateTempTexture","_tempTexture","MOTIONBLUR_PARAMS","useMotionBlur","WAVE_PARAMS","useWave","CHROMAKEY_PARAMS","useChromaKey","BLANK_PARAMS","useBlank","RAWBLANK_PARAMS","useRawBlank","useCreateObject","points","interactiveMesh","rewriteVertexShader","modifeidAttributes","targetGeometry","targetAttibute","itemSize","vTargetName","vAttributeRewriteKey","vTransitionRewriteKey","vListName","vMorphTransition","stringToAddToMorphAttibutes","stringToAddToMorphAttibutesList","modifyAttributes","attribute","modifiedAttribute","maxLength","arr","diff","addArray","oldArray","randomIndex","j","rewriteFragmentShader","mapArray","mapArrayShader","mapArrayUniforms","textureSwitcherCode","map","condition","action","useMaterial","positions","uvs","modifiedPositions","modifiedUvs","rewritedVertexShader","rewritedFragmentShader","MORPHPARTICLES_PARAMS","useCreateMorphParticles","morphGeometry","geo","useMorphParticles","updateUniform","generatedPositions","generatedUvs","updateFx","isDepth","transmission_pars_fragment_default","transmission_fragment_default","resolveEachMaterial","mat","isCustomTransmission","transmission_pars_fragment","transmission_fragment","baseMaterial","materialParameters","depthOnBeforeInit","depthMaterial","WOBBLE3D_PARAMS","cutomizedParams","depthMat","useCreateWobble3D","wobbleGeometry","mergeVertices","userData","useWobble3D","RootState","useAddMesh","checkUpdate","currentW","currentH","memoW","memoH","threshold","boundFor","isSmaller","isLarger","useResizeBoundary","memorizedSize","Easing","x","c2","c4","c5","getHash","input","n","useBeat","bpm","ease","rhythm","easing","beat","floor","fract","hash","useFPSLimiter","fps","interval","prevTime","tick","errorHandler","domLength","textureLength","createMesh","child","useIntersectionHandler","intersectionObserverRef","intersectionDomRef","isIntersectingRef","isIntersectingOnceRef","observer","newArr","dom","callback","entries","entry","useUpdateDomRect","domRects","updateDomRects","resolutionRef","domElement","rect","useIsIntersecting","isIntersecting","once","createUseDomView","onView","onHidden","isView","id","filterIntersection","item","DOMSYNCER_PARAMS","useDomSyncer","dependencies","DOMRects","refreshTrigger","setRefreshTrigger","useState","updateKey","emptyTexture","intersectionHandler","useDomView","useCopyTexture","length","targetSettings","renderTargetArr","updateCopyTexture","Utils","startValue","endValue","progress","t","edge0","edge1"],"mappings":"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"} \ No newline at end of file diff --git a/packages/use-shader-fx/build/use-shader-fx.umd.cjs b/packages/use-shader-fx/build/use-shader-fx.umd.cjs deleted file mode 100644 index 32b41a5d..00000000 --- a/packages/use-shader-fx/build/use-shader-fx.umd.cjs +++ /dev/null @@ -1,1615 +0,0 @@ -(function(S,me){typeof exports=="object"&&typeof module<"u"?me(exports,require("three"),require("react"),require("three-stdlib")):typeof define=="function"&&define.amd?define(["exports","three","react","three-stdlib"],me):(S=typeof globalThis<"u"?globalThis:S||self,me(S["use-shader-fx"]={},S.THREE,S.react,S.threeStdlib))})(this,function(S,me,a,$e){"use strict";function je(e){const n=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(e){for(const t in e)if(t!=="default"){const r=Object.getOwnPropertyDescriptor(e,t);Object.defineProperty(n,t,r.get?r:{enumerable:!0,get:()=>e[t]})}}return n.default=e,Object.freeze(n)}const o=je(me);var We="#usf ",qe=`precision highp float; - -uniform sampler2D uBuffer; -uniform sampler2D uTexture; -uniform bool uIsTexture; -uniform sampler2D uMap; -uniform bool uIsMap; -uniform float uMapIntensity; -uniform float uRadius; -uniform float uDissipation; -uniform vec2 uResolution; -uniform float uSmudge; -uniform vec2 uMouse; -uniform vec2 uPrevMouse; -uniform vec2 uVelocity; -uniform vec3 uColor; -uniform float uMotionBlur; -uniform int uMotionSample; -uniform bool uIsCursor; -uniform float uPressureStart; -uniform float uPressureEnd; - -varying vec2 vUv; - -float isOnLine(vec2 point, vec2 start, vec2 end, float radius, float pressureStart, float pressureEnd) { - - float aspect = uResolution.x / uResolution.y; - - point.x *= aspect; - start.x *= aspect; - end.x *= aspect; - - vec2 dir = normalize(end - start); - vec2 n = vec2(dir.y, -dir.x); - vec2 p0 = point - start; - - float distToLine = abs(dot(p0, n)); - float distAlongLine = dot(p0, dir); - float totalLength = length(end - start); - - float progress = clamp(distAlongLine / totalLength, 0.0, 1.0); - float pressure = mix(pressureStart, pressureEnd, progress); - radius = min(radius,radius * pressure); - - float distFromStart = length(point - start); - float distFromEnd = length(point - end); - - bool withinLine = (distToLine < radius && distAlongLine > 0.0 && distAlongLine < totalLength) || distFromStart < radius || distFromEnd < radius; - - return float(withinLine); -} - -vec4 createSmudge(vec2 uv){ - vec2 offsets[9]; - offsets[0] = vec2(-1, -1); offsets[1] = vec2( 0, -1); offsets[2] = vec2( 1, -1); - offsets[3] = vec2(-1, 0); offsets[4] = vec2( 0, 0); offsets[5] = vec2( 1, 0); - offsets[6] = vec2(-1, 1); offsets[7] = vec2( 0, 1); offsets[8] = vec2( 1, 1); - - for(int i = 0; i < 9; i++) { - offsets[i] = (offsets[i] * uSmudge) / uResolution; - } - vec4 smudgedColor = vec4(0.); - for(int i = 0; i < 9; i++) { - smudgedColor += texture2D(uBuffer, uv + offsets[i]); - } - return smudgedColor / 9.0; -} - -vec4 createMotionBlur(vec2 uv , vec4 baseColor, vec2 velocity) { - vec2 scaledV = velocity * uMotionBlur; - for(int i = 1; i < uMotionSample; i++) { - float t = float(i) / float(uMotionSample - 1); - vec2 offset = t * scaledV / uResolution; - baseColor += texture2D(uBuffer, uv + offset); - } - return baseColor / float(uMotionSample); -} - -void main() { - - vec2 uv = vUv; - if(uIsMap){ - vec2 mapColor = texture2D(uMap, uv).rg; - vec2 normalizedMap = mapColor * 2.0 - 1.0; - uv = uv * 2.0 - 1.0; - uv *= mix(vec2(1.0), abs(normalizedMap.rg), uMapIntensity); - uv = (uv + 1.0) / 2.0; - } - vec2 suv = uv*2.-1.; - - vec2 velocity = uVelocity * uResolution; - - float radius = max(0.0,uRadius); - - vec4 smudgedColor = uSmudge > 0. ? createSmudge(uv) : texture2D(uBuffer, uv); - - vec4 motionBlurredColor = uMotionBlur > 0. ? createMotionBlur(uv,smudgedColor, velocity) : smudgedColor; - - vec4 bufferColor = motionBlurredColor; - bufferColor.a = bufferColor.a < 1e-10 ? 0.0 : bufferColor.a * uDissipation; - - vec4 brushColor = uIsTexture ? texture2D(uTexture, uv) : vec4(uColor,1.); - - float onLine = isOnLine(suv, uPrevMouse, uMouse, radius, uPressureStart,uPressureEnd); - float isOnLine = length(velocity) > 0. ? onLine : uIsCursor ? onLine : 0.; - - vec4 finalColor = mix(bufferColor, brushColor, isOnLine); - - gl_FragColor = finalColor; -}`;const N=(e,n=!1)=>{const t=n?e.width*n:e.width,r=n?e.height*n:e.height;return a.useMemo(()=>new o.Vector2(t,r),[t,r])},P=e=>(n,t)=>{if(t===void 0)return;const r=e.uniforms;r&&r[n]&&(r[n].value=t)},A=e=>n=>{n!==void 0&&Object.keys(n).forEach(t=>{const r=e.uniforms;r&&r[t]&&(r[t].value=n[t])})},B=(e,n,t,r)=>{const l=a.useMemo(()=>{const c=new r(n,t);return e&&e.add(c),c},[n,t,r,e]);return a.useEffect(()=>()=>{e&&e.remove(l),n.dispose(),t.dispose()},[e,n,t,l]),l},we=process.env.NODE_ENV==="development",I={transparent:!1,depthTest:!1,depthWrite:!1},T=new o.DataTexture(new Uint8Array([0,0,0,0]),1,1,o.RGBAFormat);var Ne=`vec4 permute(vec4 x){return mod(((x*34.0)+1.0)*x, 289.0);} -float permute(float x){return floor(mod(((x*34.0)+1.0)*x, 289.0));} -vec4 taylorInvSqrt(vec4 r){return 1.79284291400159 - 0.85373472095314 * r;} -float taylorInvSqrt(float r){return 1.79284291400159 - 0.85373472095314 * r;} - -vec4 grad4(float j, vec4 ip) -{ - const vec4 ones = vec4(1.0, 1.0, 1.0, -1.0); - vec4 p,s; - - p.xyz = floor( fract (vec3(j) * ip.xyz) * 7.0) * ip.z - 1.0; - p.w = 1.5 - dot(abs(p.xyz), ones.xyz); - s = vec4(lessThan(p, vec4(0.0))); - p.xyz = p.xyz + (s.xyz*2.0 - 1.0) * s.www; - - return p; -} - -float simplexNoise4d(vec4 v) -{ - const vec2 C = vec2( 0.138196601125010504, - 0.309016994374947451); - - vec4 i = floor(v + dot(v, C.yyyy) ); - vec4 x0 = v - i + dot(i, C.xxxx); - - - - - vec4 i0; - - vec3 isX = step( x0.yzw, x0.xxx ); - vec3 isYZ = step( x0.zww, x0.yyz ); - - i0.x = isX.x + isX.y + isX.z; - i0.yzw = 1.0 - isX; - - - i0.y += isYZ.x + isYZ.y; - i0.zw += 1.0 - isYZ.xy; - - i0.z += isYZ.z; - i0.w += 1.0 - isYZ.z; - - - vec4 i3 = clamp( i0, 0.0, 1.0 ); - vec4 i2 = clamp( i0-1.0, 0.0, 1.0 ); - vec4 i1 = clamp( i0-2.0, 0.0, 1.0 ); - - - vec4 x1 = x0 - i1 + 1.0 * C.xxxx; - vec4 x2 = x0 - i2 + 2.0 * C.xxxx; - vec4 x3 = x0 - i3 + 3.0 * C.xxxx; - vec4 x4 = x0 - 1.0 + 4.0 * C.xxxx; - - - i = mod(i, 289.0); - float j0 = permute( permute( permute( permute(i.w) + i.z) + i.y) + i.x); - vec4 j1 = permute( permute( permute( permute ( - i.w + vec4(i1.w, i2.w, i3.w, 1.0 )) - + i.z + vec4(i1.z, i2.z, i3.z, 1.0 )) - + i.y + vec4(i1.y, i2.y, i3.y, 1.0 )) - + i.x + vec4(i1.x, i2.x, i3.x, 1.0 )); - - - - - vec4 ip = vec4(1.0/294.0, 1.0/49.0, 1.0/7.0, 0.0) ; - - vec4 p0 = grad4(j0, ip); - vec4 p1 = grad4(j1.x, ip); - vec4 p2 = grad4(j1.y, ip); - vec4 p3 = grad4(j1.z, ip); - vec4 p4 = grad4(j1.w, ip); - - - vec4 norm = taylorInvSqrt(vec4(dot(p0,p0), dot(p1,p1), dot(p2, p2), dot(p3,p3))); - p0 *= norm.x; - p1 *= norm.y; - p2 *= norm.z; - p3 *= norm.w; - p4 *= taylorInvSqrt(dot(p4,p4)); - - - vec3 m0 = max(0.6 - vec3(dot(x0,x0), dot(x1,x1), dot(x2,x2)), 0.0); - vec2 m1 = max(0.6 - vec2(dot(x3,x3), dot(x4,x4) ), 0.0); - m0 = m0 * m0; - m1 = m1 * m1; - return 49.0 * ( dot(m0*m0, vec3( dot( p0, x0 ), dot( p1, x1 ), dot( p2, x2 ))) - + dot(m1*m1, vec2( dot( p3, x3 ), dot( p4, x4 ) ) ) ) ; - -} - -float getWobble(vec3 position) -{ - vec3 warpedPosition = position; - warpedPosition += simplexNoise4d( - vec4( - position * uWarpPositionFrequency, - uTime * uWarpTimeFrequency - ) - ) * uWarpStrength; - - return simplexNoise4d(vec4( - warpedPosition * uWobblePositionFrequency, - uTime * uWobbleTimeFrequency - )) * uWobbleStrength; -}`,Ge=`vec3 random3(vec3 c) { - float j = 4096.0*sin(dot(c,vec3(17.0, 59.4, 15.0))); - vec3 r; - r.z = fract(512.0*j); - j *= .125; - r.x = fract(512.0*j); - j *= .125; - r.y = fract(512.0*j); - return r-0.5; -} - -const float F3 = 0.3333333; -const float G3 = 0.1666667; - -float snoise(vec3 p) { - - vec3 s = floor(p + dot(p, vec3(F3))); - vec3 x = p - s + dot(s, vec3(G3)); - - vec3 e = step(vec3(0.0), x - x.yzx); - vec3 i1 = e*(1.0 - e.zxy); - vec3 i2 = 1.0 - e.zxy*(1.0 - e); - - vec3 x1 = x - i1 + G3; - vec3 x2 = x - i2 + 2.0*G3; - vec3 x3 = x - 1.0 + 3.0*G3; - - vec4 w, d; - - w.x = dot(x, x); - w.y = dot(x1, x1); - w.z = dot(x2, x2); - w.w = dot(x3, x3); - - w = max(0.6 - w, 0.0); - - d.x = dot(random3(s), x); - d.y = dot(random3(s + i1), x1); - d.z = dot(random3(s + i2), x2); - d.w = dot(random3(s + 1.0), x3); - - w *= w; - w *= w; - d *= w; - - return dot(d, vec4(52.0)); -} - -float snoiseFractal(vec3 m) { - return 0.5333333* snoise(m) - +0.2666667* snoise(2.0*m) - +0.1333333* snoise(4.0*m) - +0.0666667* snoise(8.0*m); -}`,He=`float screenAspect = uResolution.x / uResolution.y; -float textureAspect = uTextureResolution.x / uTextureResolution.y; -vec2 aspectRatio = vec2( - min(screenAspect / textureAspect, 1.0), - min(textureAspect / screenAspect, 1.0) -); -vec2 uv = vUv * aspectRatio + (1.0 - aspectRatio) * .5;`,Ke=`vec3 mapColor = texture2D(uMap, uv).rgb; -vec3 normalizedMap = mapColor * 2.0 - 1.0; - -uv = uv * 2.0 - 1.0; -uv *= mix(vec2(1.0), abs(normalizedMap.rg), uMapIntensity); -uv = (uv + 1.0) / 2.0;`,Xe=`precision highp float; - -varying vec2 vUv; - -void main() { - vUv = uv; - gl_Position = vec4(position, 1.0); -}`,Ye=`varying vec2 vUv; - -void main() { - vUv = uv; - gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0); -}`,Qe=`vec3 hsv2rgb(vec3 c) -{ - vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0); - vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www); - return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y); -}`,Ze=`vec3 rgb2hsv(vec3 c) -{ - vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0); - vec4 p = mix(vec4(c.bg, K.wz), vec4(c.gb, K.xy), step(c.b, c.g)); - vec4 q = mix(vec4(p.xyw, c.r), vec4(c.r, p.yzx), step(p.x, c.r)); - - float d = q.x - min(q.w, q.y); - float e = 1.0e-10; - return vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x); -}`;const De=Object.freeze({wobble3D:Ne,snoise:Ge,coverTexture:He,fxBlending:Ke,planeVertex:Xe,defaultVertex:Ye,hsv2rgb:Qe,rgb2hsv:Ze}),Je=/^[ \t]*#usf +<([\w\d./]+)>/gm;function en(e,n){return be(De[n]||"")}function be(e){return e.replace(Je,en)}const F=(e,n)=>(n&&n(e),e.vertexShader=be(e.vertexShader),e.fragmentShader=be(e.fragmentShader),e),nn=({scene:e,size:n,dpr:t,onBeforeInit:r})=>{const l=a.useMemo(()=>new o.PlaneGeometry(2,2),[]),c=a.useMemo(()=>new o.ShaderMaterial({...F({uniforms:{uBuffer:{value:T},uResolution:{value:new o.Vector2(0,0)},uTexture:{value:T},uIsTexture:{value:!1},uMap:{value:T},uIsMap:{value:!1},uMapIntensity:{value:Y.mapIntensity},uRadius:{value:Y.radius},uSmudge:{value:Y.smudge},uDissipation:{value:Y.dissipation},uMotionBlur:{value:Y.motionBlur},uMotionSample:{value:Y.motionSample},uMouse:{value:new o.Vector2(-10,-10)},uPrevMouse:{value:new o.Vector2(-10,-10)},uVelocity:{value:new o.Vector2(0,0)},uColor:{value:Y.color},uIsCursor:{value:!1},uPressureStart:{value:1},uPressureEnd:{value:1}},vertexShader:We,fragmentShader:qe},r),...I,transparent:!0}),[r]),m=N(n,t);P(c)("uResolution",m.clone());const i=B(e,l,c,o.Mesh);return{material:c,mesh:i}},tn=(e,n)=>{const t=n,r=e/n,[l,c]=[t*r/2,t/2];return{width:l,height:c,near:-1e3,far:1e3}},E=(e,n="OrthographicCamera")=>{const t=N(e),{width:r,height:l,near:c,far:m}=tn(t.x,t.y);return a.useMemo(()=>n==="OrthographicCamera"?new o.OrthographicCamera(-r,r,l,-l,c,m):new o.PerspectiveCamera(50,r/l),[r,l,c,m,n])},ge=(e=0)=>{const n=a.useRef(new o.Vector2(0,0)),t=a.useRef(new o.Vector2(0,0)),r=a.useRef(new o.Vector2(0,0)),l=a.useRef(0),c=a.useRef(new o.Vector2(0,0)),m=a.useRef(!1);return a.useCallback(d=>{const p=performance.now();let g;m.current&&e?(r.current=r.current.lerp(d,1-e),g=r.current.clone()):(g=d.clone(),r.current=g),l.current===0&&(l.current=p,n.current=g);const M=Math.max(1,p-l.current);l.current=p,c.current.copy(g).sub(n.current).divideScalar(M);const u=c.current.length()>0,v=m.current?n.current.clone():g;return!m.current&&u&&(m.current=!0),n.current=g,{currentPointer:g,prevPointer:v,diffPointer:t.current.subVectors(g,v),velocity:c.current,isVelocityUpdate:u}},[e])},L=e=>{const n=l=>Object.values(l).some(c=>typeof c=="function"),t=a.useRef(n(e)?e:structuredClone(e)),r=a.useCallback(l=>{if(l!==void 0)for(const c in l){const m=c;m in t.current&&l[m]!==void 0&&l[m]!==null?t.current[m]=l[m]:console.error(`"${String(m)}" does not exist in the params. or "${String(m)}" is null | undefined`)}},[]);return[t.current,r]},ve={depthBuffer:!1},he=({gl:e,fbo:n,scene:t,camera:r,onBeforeRender:l,onSwap:c})=>{e.setRenderTarget(n),l(),e.clear(),e.render(t,r),c&&c(),e.setRenderTarget(null),e.clear()},k=e=>{var M;const{scene:n,camera:t,size:r,dpr:l=!1,isSizeUpdate:c=!1,depth:m=!1,...i}=e,d=a.useRef(),p=N(r,l);d.current=a.useMemo(()=>{const u=new o.WebGLRenderTarget(p.x,p.y,{...ve,...i});return m&&(u.depthTexture=new o.DepthTexture(p.x,p.y,o.FloatType)),u},[]),c&&((M=d.current)==null||M.setSize(p.x,p.y)),a.useEffect(()=>{const u=d.current;return()=>{u==null||u.dispose()}},[]);const g=a.useCallback((u,v)=>{const s=d.current;return he({gl:u,fbo:s,scene:n,camera:t,onBeforeRender:()=>v&&v({read:s.texture})}),s.texture},[n,t]);return[d.current,g]},ne=e=>{var M,u;const{scene:n,camera:t,size:r,dpr:l=!1,isSizeUpdate:c=!1,depth:m=!1,...i}=e,d=N(r,l),p=a.useMemo(()=>{const v=new o.WebGLRenderTarget(d.x,d.y,{...ve,...i}),s=new o.WebGLRenderTarget(d.x,d.y,{...ve,...i});return m&&(v.depthTexture=new o.DepthTexture(d.x,d.y,o.FloatType),s.depthTexture=new o.DepthTexture(d.x,d.y,o.FloatType)),{read:v,write:s,swap:function(){let f=this.read;this.read=this.write,this.write=f}}},[]);c&&((M=p.read)==null||M.setSize(d.x,d.y),(u=p.write)==null||u.setSize(d.x,d.y)),a.useEffect(()=>{const v=p;return()=>{var s,f;(s=v.read)==null||s.dispose(),(f=v.write)==null||f.dispose()}},[p]);const g=a.useCallback((v,s)=>{var x;const f=p;return he({gl:v,scene:n,camera:t,fbo:f.write,onBeforeRender:()=>s&&s({read:f.read.texture,write:f.write.texture}),onSwap:()=>f.swap()}),(x=f.read)==null?void 0:x.texture},[n,t,p]);return[{read:p.read,write:p.write},g]},O=e=>typeof e=="number"?{shader:e,fbo:e}:{shader:e.shader??!1,fbo:e.fbo??!1},Y=Object.freeze({texture:!1,map:!1,mapIntensity:.1,radius:.05,smudge:0,dissipation:1,motionBlur:0,motionSample:5,color:new o.Vector3(1,0,0),isCursor:!1,pressure:1,pointerValues:!1}),rn=({size:e,dpr:n,renderTargetOptions:t,isSizeUpdate:r,onBeforeInit:l})=>{const c=O(n),m=a.useMemo(()=>new o.Scene,[]),{material:i,mesh:d}=nn({scene:m,size:e,dpr:c.shader,onBeforeInit:l}),p=E(e),g=ge(),[M,u]=ne({scene:m,camera:p,size:e,dpr:c.fbo,isSizeUpdate:r,...t}),[v,s]=L(Y),f=a.useRef(null),x=P(i),b=A(i),y=a.useCallback((C,_)=>{s(C),b(_)},[s,b]);return[a.useCallback((C,_,w)=>{const{gl:V,pointer:z}=C;y(_,w),v.texture?(x("uIsTexture",!0),x("uTexture",v.texture)):x("uIsTexture",!1),v.map?(x("uIsMap",!0),x("uMap",v.map),x("uMapIntensity",v.mapIntensity)):x("uIsMap",!1),x("uRadius",v.radius),x("uSmudge",v.smudge),x("uDissipation",v.dissipation),x("uMotionBlur",v.motionBlur),x("uMotionSample",v.motionSample);const R=v.pointerValues||g(z);R.isVelocityUpdate&&(x("uMouse",R.currentPointer),x("uPrevMouse",R.prevPointer)),x("uVelocity",R.velocity);const j=typeof v.color=="function"?v.color(R.velocity):v.color;return x("uColor",j),x("uIsCursor",v.isCursor),x("uPressureEnd",v.pressure),f.current===null&&(f.current=v.pressure),x("uPressureStart",f.current),f.current=v.pressure,u(V,({read:D})=>{x("uBuffer",D)})},[x,g,u,v,y]),y,{scene:m,mesh:d,material:i,camera:p,renderTarget:M,output:M.read.texture}]};var Q=`varying vec2 vUv; -varying vec2 vL; -varying vec2 vR; -varying vec2 vT; -varying vec2 vB; -uniform vec2 texelSize; - -void main () { - vUv = uv; - vL = vUv - vec2(texelSize.x, 0.0); - vR = vUv + vec2(texelSize.x, 0.0); - vT = vUv + vec2(0.0, texelSize.y); - vB = vUv - vec2(0.0, texelSize.y); - gl_Position = vec4(position, 1.0); -}`,on=`precision highp float; - -void main(){ - gl_FragColor = vec4(0.0); -}`;const an=()=>a.useMemo(()=>new o.ShaderMaterial({vertexShader:Q,fragmentShader:on,...I}),[]);var un=`precision highp float; - -varying vec2 vUv; -uniform sampler2D uVelocity; -uniform sampler2D uSource; -uniform vec2 texelSize; -uniform float dt; -uniform float dissipation; - -void main () { - vec2 coord = vUv - dt * texture2D(uVelocity, vUv).xy * texelSize; - gl_FragColor = vec4(dissipation * texture2D(uSource, coord).rgb,1.); -}`;const sn=({onBeforeInit:e})=>a.useMemo(()=>new o.ShaderMaterial({...F({uniforms:{uVelocity:{value:T},uSource:{value:T},texelSize:{value:new o.Vector2},dt:{value:Se},dissipation:{value:0}},vertexShader:Q,fragmentShader:un},e),...I}),[e]);var ln=`precision highp float; - -varying vec2 vUv; -varying vec2 vL; -varying vec2 vR; -varying vec2 vT; -varying vec2 vB; -uniform sampler2D uVelocity; - -vec2 sampleVelocity(in vec2 uv) { - vec2 clampedUV = clamp(uv, 0.0, 1.0); - vec2 multiplier = vec2(1.0, 1.0); - multiplier.x = uv.x < 0.0 || uv.x > 1.0 ? -1.0 : 1.0; - multiplier.y = uv.y < 0.0 || uv.y > 1.0 ? -1.0 : 1.0; - return multiplier * texture2D(uVelocity, clampedUV).xy; -} - -void main () { - float L = sampleVelocity(vL).x; - float R = sampleVelocity(vR).x; - float T = sampleVelocity(vT).y; - float B = sampleVelocity(vB).y; - float div = 0.5 * (R - L + T - B); - gl_FragColor = vec4(div, 0.0, 0.0, 1.0); -}`;const cn=({onBeforeInit:e})=>a.useMemo(()=>new o.ShaderMaterial({...F({uniforms:{uVelocity:{value:null},texelSize:{value:new o.Vector2}},vertexShader:Q,fragmentShader:ln},e),...I}),[e]);var mn=`precision highp float; - -varying vec2 vUv; -varying vec2 vL; -varying vec2 vR; -varying vec2 vT; -varying vec2 vB; -uniform sampler2D uPressure; -uniform sampler2D uDivergence; - -void main () { - float L = texture2D(uPressure, clamp(vL,0.,1.)).x; - float R = texture2D(uPressure, clamp(vR,0.,1.)).x; - float T = texture2D(uPressure, clamp(vT,0.,1.)).x; - float B = texture2D(uPressure, clamp(vB,0.,1.)).x; - float C = texture2D(uPressure, vUv).x; - float divergence = texture2D(uDivergence, vUv).x; - float pressure = (L + R + B + T - divergence) * 0.25; - gl_FragColor = vec4(pressure, 0.0, 0.0, 1.0); -}`;const vn=({onBeforeInit:e})=>a.useMemo(()=>new o.ShaderMaterial({...F({uniforms:{uPressure:{value:null},uDivergence:{value:null},texelSize:{value:new o.Vector2}},vertexShader:Q,fragmentShader:mn},e),...I}),[e]);var fn=`precision highp float; - -varying vec2 vUv; -varying vec2 vL; -varying vec2 vR; -varying vec2 vT; -varying vec2 vB; -uniform sampler2D uVelocity; - -void main () { - float L = texture2D(uVelocity, vL).y; - float R = texture2D(uVelocity, vR).y; - float T = texture2D(uVelocity, vT).x; - float B = texture2D(uVelocity, vB).x; - float vorticity = R - L - T + B; - gl_FragColor = vec4(vorticity, 0.0, 0.0, 1.0); -}`;const pn=({onBeforeInit:e})=>a.useMemo(()=>new o.ShaderMaterial({...F({uniforms:{uVelocity:{value:null},texelSize:{value:new o.Vector2}},vertexShader:Q,fragmentShader:fn},e),...I}),[e]);var dn=`precision highp float; - -varying vec2 vUv; -varying vec2 vT; -varying vec2 vB; -uniform sampler2D uVelocity; -uniform sampler2D uCurl; -uniform float curl; -uniform float dt; - -void main () { - float T = texture2D(uCurl, vT).x; - float B = texture2D(uCurl, vB).x; - float C = texture2D(uCurl, vUv).x; - vec2 force = vec2(abs(T) - abs(B), 0.0); - force *= 1.0 / length(force + 0.00001) * curl * C; - vec2 vel = texture2D(uVelocity, vUv).xy; - gl_FragColor = vec4(vel + force * dt, 0.0, 1.0); -}`;const gn=({onBeforeInit:e})=>a.useMemo(()=>new o.ShaderMaterial({...F({uniforms:{uVelocity:{value:null},uCurl:{value:null},curl:{value:0},dt:{value:Se},texelSize:{value:new o.Vector2}},vertexShader:Q,fragmentShader:dn},e),...I}),[e]);var hn=`precision highp float; - -varying vec2 vUv; -uniform sampler2D uTexture; -uniform float value; - -void main () { - gl_FragColor = value * texture2D(uTexture, vUv); -}`;const xn=({onBeforeInit:e})=>a.useMemo(()=>new o.ShaderMaterial({...F({uniforms:{uTexture:{value:T},value:{value:0},texelSize:{value:new o.Vector2}},vertexShader:Q,fragmentShader:hn},e),...I}),[e]);var Mn=`precision highp float; - -varying vec2 vUv; -varying vec2 vL; -varying vec2 vR; -varying vec2 vT; -varying vec2 vB; -uniform sampler2D uPressure; -uniform sampler2D uVelocity; - -void main () { - float L = texture2D(uPressure, clamp(vL,0.,1.)).x; - float R = texture2D(uPressure, clamp(vR,0.,1.)).x; - float T = texture2D(uPressure, clamp(vT,0.,1.)).x; - float B = texture2D(uPressure, clamp(vB,0.,1.)).x; - vec2 velocity = texture2D(uVelocity, vUv).xy; - velocity.xy -= vec2(R - L, T - B); - gl_FragColor = vec4(velocity, 0.0, 1.0); -}`;const yn=({onBeforeInit:e})=>a.useMemo(()=>new o.ShaderMaterial({...F({uniforms:{uPressure:{value:T},uVelocity:{value:T},texelSize:{value:new o.Vector2}},vertexShader:Q,fragmentShader:Mn},e),...I}),[e]);var bn=`precision highp float; - -varying vec2 vUv; -uniform sampler2D uTarget; -uniform float aspectRatio; -uniform vec3 color; -uniform vec2 point; -uniform float radius; - -void main () { - vec2 nPoint = (point + vec2(1.0)) * 0.5; - vec2 p = vUv - nPoint.xy; - p.x *= aspectRatio; - vec3 splat = exp(-dot(p, p) / radius) * color; - vec3 base = texture2D(uTarget, vUv).xyz; - gl_FragColor = vec4(base + splat, 1.0); -}`;const Sn=({onBeforeInit:e})=>a.useMemo(()=>new o.ShaderMaterial({...F({uniforms:{uTarget:{value:T},aspectRatio:{value:0},color:{value:new o.Vector3},point:{value:new o.Vector2},radius:{value:0},texelSize:{value:new o.Vector2}},vertexShader:Q,fragmentShader:bn},e),...I}),[e]),Z=(e,n)=>e(n??{}),Cn=({scene:e,size:n,dpr:t,customFluidProps:r})=>{const l=a.useMemo(()=>new o.PlaneGeometry(2,2),[]),{curl:c,vorticity:m,advection:i,divergence:d,pressure:p,clear:g,gradientSubtract:M,splat:u}=r??{},v=Z(an),s=v.clone(),f=Z(pn,c),x=Z(gn,m),b=Z(sn,i),y=Z(cn,d),h=Z(vn,p),C=Z(xn,g),_=Z(yn,M),w=Z(Sn,u),V=a.useMemo(()=>({vorticityMaterial:x,curlMaterial:f,advectionMaterial:b,divergenceMaterial:y,pressureMaterial:h,clearMaterial:C,gradientSubtractMaterial:_,splatMaterial:w}),[x,f,b,y,h,C,_,w]),z=N(n,t);a.useMemo(()=>{P(V.splatMaterial)("aspectRatio",z.x/z.y);for(const D of Object.values(V))P(D)("texelSize",new o.Vector2(1/z.x,1/z.y))},[z,V]);const R=B(e,l,v,o.Mesh);a.useMemo(()=>{v.dispose(),R.material=s},[v,R,s]),a.useEffect(()=>()=>{for(const D of Object.values(V))D.dispose()},[V]);const j=a.useCallback(D=>{R.material=D,R.material.needsUpdate=!0},[R]);return{materials:V,setMeshMaterial:j,mesh:R}},Se=.016,Re=Object.freeze({densityDissipation:.98,velocityDissipation:.99,velocityAcceleration:10,pressureDissipation:.9,pressureIterations:20,curlStrength:35,splatRadius:.002,fluidColor:new o.Vector3(1,1,1),pointerValues:!1}),_n=({size:e,dpr:n,renderTargetOptions:t,isSizeUpdate:r,customFluidProps:l})=>{const c=O(n),m=a.useMemo(()=>new o.Scene,[]),{materials:i,setMeshMaterial:d,mesh:p}=Cn({scene:m,size:e,dpr:c.shader,customFluidProps:l}),g=E(e),M=ge(),u=a.useMemo(()=>({scene:m,camera:g,dpr:c.fbo,size:e,isSizeUpdate:r,type:o.HalfFloatType,...t}),[m,g,e,c.fbo,r,t]),[v,s]=ne(u),[f,x]=ne(u),[b,y]=k(u),[h,C]=k(u),[_,w]=ne(u),V=a.useRef(new o.Vector2(0,0)),z=a.useRef(new o.Vector3(0,0,0)),[R,j]=L(Re),D=a.useMemo(()=>({advection:P(i.advectionMaterial),splat:P(i.splatMaterial),curl:P(i.curlMaterial),vorticity:P(i.vorticityMaterial),divergence:P(i.divergenceMaterial),clear:P(i.clearMaterial),pressure:P(i.pressureMaterial),gradientSubtract:P(i.gradientSubtractMaterial)}),[i]),q=a.useMemo(()=>({advection:A(i.advectionMaterial),splat:A(i.splatMaterial),curl:A(i.curlMaterial),vorticity:A(i.vorticityMaterial),divergence:A(i.divergenceMaterial),clear:A(i.clearMaterial),pressure:A(i.pressureMaterial),gradientSubtract:A(i.gradientSubtractMaterial)}),[i]),H=a.useCallback((oe,ae)=>{j(oe),ae&&Object.keys(ae).forEach(ie=>{q[ie](ae[ie])})},[j,q]);return[a.useCallback((oe,ae,ie)=>{const{gl:G,pointer:Cr,size:Le}=oe;H(ae,ie);const Te=s(G,({read:W})=>{d(i.advectionMaterial),D.advection("uVelocity",W),D.advection("uSource",W),D.advection("dissipation",R.velocityDissipation)}),_r=x(G,({read:W})=>{d(i.advectionMaterial),D.advection("uVelocity",Te),D.advection("uSource",W),D.advection("dissipation",R.densityDissipation)}),ye=R.pointerValues||M(Cr);ye.isVelocityUpdate&&(s(G,({read:W})=>{d(i.splatMaterial),D.splat("uTarget",W),D.splat("point",ye.currentPointer);const ce=ye.diffPointer.multiply(V.current.set(Le.width,Le.height).multiplyScalar(R.velocityAcceleration));D.splat("color",z.current.set(ce.x,ce.y,1)),D.splat("radius",R.splatRadius)}),x(G,({read:W})=>{d(i.splatMaterial),D.splat("uTarget",W);const ce=typeof R.fluidColor=="function"?R.fluidColor(ye.velocity):R.fluidColor;D.splat("color",ce)}));const Tr=y(G,()=>{d(i.curlMaterial),D.curl("uVelocity",Te)});s(G,({read:W})=>{d(i.vorticityMaterial),D.vorticity("uVelocity",W),D.vorticity("uCurl",Tr),D.vorticity("curl",R.curlStrength)});const wr=C(G,()=>{d(i.divergenceMaterial),D.divergence("uVelocity",Te)});w(G,({read:W})=>{d(i.clearMaterial),D.clear("uTexture",W),D.clear("value",R.pressureDissipation)}),d(i.pressureMaterial),D.pressure("uDivergence",wr);let ke;for(let W=0;W{D.pressure("uPressure",ce)});return s(G,({read:W})=>{d(i.gradientSubtractMaterial),D.gradientSubtract("uPressure",ke),D.gradientSubtract("uVelocity",W)}),_r},[i,D,d,y,x,C,M,w,s,R,H]),H,{scene:m,mesh:p,materials:i,camera:g,renderTarget:{velocity:v,density:f,curl:b,divergence:h,pressure:_},output:f.read.texture}]};var Tn="#usf ",wn=`precision highp float; - -uniform sampler2D uMap; -uniform float uOpacity; - -varying vec2 vUv; - -void main() { - vec2 uv = vUv; - vec3 color = texture2D(uMap, uv).rgb; - gl_FragColor = vec4(color,uOpacity); -}`;const Dn=({scale:e,max:n,texture:t,scene:r,onBeforeInit:l})=>{const c=a.useMemo(()=>new o.PlaneGeometry(e,e),[e]),m=a.useMemo(()=>new o.ShaderMaterial({...F({uniforms:{uOpacity:{value:0},uMap:{value:t||T}},vertexShader:Tn,fragmentShader:wn},l),blending:o.AdditiveBlending,...I,transparent:!0}),[t,l]),i=a.useMemo(()=>{const d=[];for(let p=0;p()=>{i.forEach(d=>{d.geometry.dispose(),Array.isArray(d.material)?d.material.forEach(p=>p.dispose()):d.material.dispose(),r.remove(d)})},[r,i]),i},Pe=Object.freeze({frequency:.01,rotation:.05,fadeoutSpeed:.9,scale:.3,alpha:.6,pointerValues:!1}),Rn=({texture:e,scale:n=64,max:t=100,size:r,dpr:l,renderTargetOptions:c,isSizeUpdate:m,onBeforeInit:i})=>{const d=O(l),p=a.useMemo(()=>new o.Scene,[]),g=Dn({scale:n,max:t,texture:e,scene:p,onBeforeInit:i}),M=E(r),u=ge(),[v,s]=k({scene:p,camera:M,size:r,dpr:d.fbo,isSizeUpdate:m,...c}),[f,x]=L(Pe),b=a.useRef(0),y=a.useMemo(()=>(C,_)=>{x(C),g.forEach(w=>{if(w.visible){const V=w.material;w.rotation.z+=f.rotation,w.scale.x=f.fadeoutSpeed*w.scale.x+f.scale,w.scale.y=w.scale.x;const z=V.uniforms.uOpacity.value;P(V)("uOpacity",z*f.fadeoutSpeed),z<.001&&(w.visible=!1)}A(w.material)(_)})},[g,f,x]);return[a.useCallback((C,_,w)=>{const{gl:V,pointer:z,size:R}=C;y(_,w);const j=f.pointerValues||u(z);if(f.frequency{const t=a.useMemo(()=>new o.PlaneGeometry(2,2),[]),r=a.useMemo(()=>new o.ShaderMaterial({...F({uniforms:{uTime:{value:0},scale:{value:J.scale},timeStrength:{value:J.timeStrength},noiseOctaves:{value:J.noiseOctaves},fbmOctaves:{value:J.fbmOctaves},warpOctaves:{value:J.warpOctaves},warpDirection:{value:J.warpDirection},warpStrength:{value:J.warpStrength}},vertexShader:Pn,fragmentShader:An},n),...I}),[n]),l=B(e,t,r,o.Mesh);return{material:r,mesh:l}},J=Object.freeze({scale:.004,timeStrength:.3,noiseOctaves:2,fbmOctaves:2,warpOctaves:2,warpDirection:new o.Vector2(2,2),warpStrength:8,beat:!1}),Vn=({size:e,dpr:n,renderTargetOptions:t,isSizeUpdate:r,onBeforeInit:l})=>{const c=O(n),m=a.useMemo(()=>new o.Scene,[]),{material:i,mesh:d}=Fn({scene:m,onBeforeInit:l}),p=E(e),[g,M]=k({scene:m,camera:p,size:e,dpr:c.fbo,isSizeUpdate:r,...t}),[u,v]=L(J),s=P(i),f=A(i),x=a.useCallback((y,h)=>{v(y),f(h)},[v,f]);return[a.useCallback((y,h,C)=>{const{gl:_,clock:w}=y;return x(h,C),s("scale",u.scale),s("timeStrength",u.timeStrength),s("noiseOctaves",u.noiseOctaves),s("fbmOctaves",u.fbmOctaves),s("warpOctaves",u.warpOctaves),s("warpDirection",u.warpDirection),s("warpStrength",u.warpStrength),s("uTime",u.beat||w.getElapsedTime()),M(_)},[M,s,u,x]),x,{scene:m,mesh:d,material:i,camera:p,renderTarget:g,output:g.texture}]};var In="#usf ",zn=`precision highp float; -varying vec2 vUv; - -uniform sampler2D uTexture; -uniform bool isTexture; -uniform sampler2D noise; -uniform bool isNoise; -uniform vec2 noiseStrength; -uniform float laminateLayer; -uniform vec2 laminateInterval; -uniform vec2 laminateDetail; -uniform vec2 distortion; -uniform vec3 colorFactor; -uniform float uTime; -uniform vec2 timeStrength; -uniform float scale; - -void main() { - vec2 uv = vUv; - - vec2 pos = isTexture ? texture2D(uTexture, uv).rg : uv * scale; - vec2 noise = isNoise ? texture2D(noise, uv).rg : vec2(0.0); - float alpha = isTexture ? texture2D(uTexture, uv).a : 1.0; - - - alpha = (alpha < 1e-10) ? 0.0 : alpha; - - vec3 col; - for(float j = 0.0; j < 3.0; j++){ - for(float i = 1.0; i < laminateLayer; i++){ - float timeNoiseSin = sin(uTime / (i + j)) * timeStrength.x + noise.r * noiseStrength.x; - float timeNoiseCos = cos(uTime / (i + j)) * timeStrength.y + noise.g * noiseStrength.y; - pos.x += laminateInterval.x / (i + j) * cos(i * distortion.x * pos.y + timeNoiseSin + sin(i + j)); - pos.y += laminateInterval.y / (i + j) * cos(i * distortion.y * pos.x + timeNoiseCos + sin(i + j)); - } - col[int(j)] = sin(pow(pos.x, 2.) * pow(laminateDetail.x, 2.)) + sin(pow(pos.y, 2.) * pow(laminateDetail.y, 2.)); - } - - col *= colorFactor * alpha; - col = clamp(col, 0.0, 1.0); - - gl_FragColor = vec4(col, alpha); -}`;const On=({scene:e,onBeforeInit:n})=>{const t=a.useMemo(()=>new o.PlaneGeometry(2,2),[]),r=a.useMemo(()=>new o.ShaderMaterial({...F({uniforms:{uTexture:{value:T},isTexture:{value:!1},scale:{value:K.scale},noise:{value:T},noiseStrength:{value:K.noiseStrength},isNoise:{value:!1},laminateLayer:{value:K.laminateLayer},laminateInterval:{value:K.laminateInterval},laminateDetail:{value:K.laminateDetail},distortion:{value:K.distortion},colorFactor:{value:K.colorFactor},uTime:{value:0},timeStrength:{value:K.timeStrength}},vertexShader:In,fragmentShader:zn},n),...I}),[n]),l=B(e,t,r,o.Mesh);return{material:r,mesh:l}},K=Object.freeze({texture:!1,scale:1,laminateLayer:1,laminateInterval:new o.Vector2(.1,.1),laminateDetail:new o.Vector2(1,1),distortion:new o.Vector2(0,0),colorFactor:new o.Vector3(1,1,1),timeStrength:new o.Vector2(0,0),noise:!1,noiseStrength:new o.Vector2(0,0),beat:!1}),Un=({size:e,dpr:n,renderTargetOptions:t,isSizeUpdate:r,onBeforeInit:l})=>{const c=O(n),m=a.useMemo(()=>new o.Scene,[]),{material:i,mesh:d}=On({scene:m,onBeforeInit:l}),p=E(e),[g,M]=k({scene:m,camera:p,size:e,dpr:c.fbo,isSizeUpdate:r,...t}),[u,v]=L(K),s=P(i),f=A(i),x=a.useCallback((y,h)=>{v(y),f(h)},[v,f]);return[a.useCallback((y,h,C)=>{const{gl:_,clock:w}=y;return x(h,C),u.texture?(s("uTexture",u.texture),s("isTexture",!0)):(s("isTexture",!1),s("scale",u.scale)),u.noise?(s("noise",u.noise),s("isNoise",!0),s("noiseStrength",u.noiseStrength)):s("isNoise",!1),s("uTime",u.beat||w.getElapsedTime()),s("laminateLayer",u.laminateLayer),s("laminateInterval",u.laminateInterval),s("laminateDetail",u.laminateDetail),s("distortion",u.distortion),s("colorFactor",u.colorFactor),s("timeStrength",u.timeStrength),M(_)},[M,s,u,x]),x,{scene:m,mesh:d,material:i,camera:p,renderTarget:g,output:g.texture}]};var Bn="#usf ",En=`precision highp float; - -varying vec2 vUv; -uniform float u_time; -uniform float u_pattern; -uniform float u_complexity; -uniform float u_complexityAttenuation; -uniform float u_iterations; -uniform float u_timeStrength; -uniform float u_scale; - -vec3 marble(vec3 p){ - vec4 n; - for(float i;i{const t=a.useMemo(()=>new o.PlaneGeometry(2,2),[]),r=a.useMemo(()=>new o.ShaderMaterial({...F({uniforms:{u_time:{value:0},u_pattern:{value:te.pattern},u_complexity:{value:te.complexity},u_complexityAttenuation:{value:te.complexityAttenuation},u_iterations:{value:te.iterations},u_timeStrength:{value:te.timeStrength},u_scale:{value:te.scale}},vertexShader:Bn,fragmentShader:En},n),...I}),[n]),l=B(e,t,r,o.Mesh);return{material:r,mesh:l}},te=Object.freeze({pattern:0,complexity:2,complexityAttenuation:.2,iterations:8,timeStrength:.2,scale:.002,beat:!1}),kn=({size:e,dpr:n,renderTargetOptions:t,isSizeUpdate:r,onBeforeInit:l})=>{const c=O(n),m=a.useMemo(()=>new o.Scene,[]),{material:i,mesh:d}=Ln({scene:m,onBeforeInit:l}),p=E(e),[g,M]=k({scene:m,camera:p,size:e,dpr:c.fbo,isSizeUpdate:r,...t}),[u,v]=L(te),s=P(i),f=A(i),x=a.useCallback((y,h)=>{v(y),f(h)},[v,f]);return[a.useCallback((y,h,C)=>{const{gl:_,clock:w}=y;return x(h,C),s("u_pattern",u.pattern),s("u_complexity",u.complexity),s("u_complexityAttenuation",u.complexityAttenuation),s("u_iterations",u.iterations),s("u_timeStrength",u.timeStrength),s("u_scale",u.scale),s("u_time",u.beat||w.getElapsedTime()),M(_)},[M,s,u,x]),x,{scene:m,mesh:d,material:i,camera:p,renderTarget:g,output:g.texture}]};var $n="#usf ",jn=`precision highp float; -precision highp int; - -varying vec2 vUv; -uniform sampler2D uTexture; -uniform vec3 uColor1; -uniform vec3 uColor2; -uniform vec3 uColor3; -uniform vec3 uColor4; -uniform vec3 uRgbWeight; - -vec3 cosPalette( float t, vec3 color1, vec3 color2, vec3 color3, vec3 color4 ){ - return color1 + color2 * cos( 6.28318 * ( color3 * t + color4) ); -} - -void main() { - - vec4 tex = texture2D(uTexture, vUv); - float gray = dot(tex.rgb, uRgbWeight); - - vec3 outColor = cosPalette( - gray, - uColor1, - uColor2, - uColor3, - uColor4 - ); - - gl_FragColor = vec4(outColor, tex.a); -}`;const Wn=({scene:e,onBeforeInit:n})=>{const t=a.useMemo(()=>new o.PlaneGeometry(2,2),[]),r=a.useMemo(()=>new o.ShaderMaterial({...F({uniforms:{uTexture:{value:T},uRgbWeight:{value:ue.rgbWeight},uColor1:{value:ue.color1},uColor2:{value:ue.color2},uColor3:{value:ue.color3},uColor4:{value:ue.color4}},vertexShader:$n,fragmentShader:jn},n),...I}),[n]),l=B(e,t,r,o.Mesh);return{material:r,mesh:l}},ue=Object.freeze({texture:T,color1:new o.Color().set(.5,.5,.5),color2:new o.Color().set(.5,.5,.5),color3:new o.Color().set(1,1,1),color4:new o.Color().set(0,.1,.2),rgbWeight:new o.Vector3(.299,.587,.114)}),qn=({size:e,dpr:n,renderTargetOptions:t,isSizeUpdate:r,onBeforeInit:l})=>{const c=O(n),m=a.useMemo(()=>new o.Scene,[]),{material:i,mesh:d}=Wn({scene:m,onBeforeInit:l}),p=E(e),[g,M]=k({scene:m,camera:p,size:e,dpr:c.fbo,isSizeUpdate:r,...t}),[u,v]=L(ue),s=P(i),f=A(i),x=a.useCallback((y,h)=>{v(y),f(h)},[v,f]);return[a.useCallback((y,h,C)=>{const{gl:_}=y;return x(h,C),s("uTexture",u.texture),s("uColor1",u.color1),s("uColor2",u.color2),s("uColor3",u.color3),s("uColor4",u.color4),s("uRgbWeight",u.rgbWeight),M(_)},[M,s,u,x]),x,{scene:m,mesh:d,material:i,camera:p,renderTarget:g,output:g.texture}]};var Nn="#usf ",Gn=`precision highp float; - -varying vec2 vUv; -uniform sampler2D uTexture; - -uniform vec3 uColor0; -uniform vec3 uColor1; - -void main() { - vec2 uv = vUv; - vec4 texColor = texture2D(uTexture, uv); - float grayscale = dot(texColor.rgb, vec3(0.299, 0.587, 0.114)); - vec3 duotone = mix(uColor0, uColor1, grayscale); - gl_FragColor = vec4(duotone, texColor.a); -}`;const Hn=({scene:e,onBeforeInit:n})=>{const t=a.useMemo(()=>new o.PlaneGeometry(2,2),[]),r=a.useMemo(()=>new o.ShaderMaterial({...F({uniforms:{uTexture:{value:T},uColor0:{value:xe.color0},uColor1:{value:xe.color1}},vertexShader:Nn,fragmentShader:Gn},n),...I}),[n]),l=B(e,t,r,o.Mesh);return{material:r,mesh:l}},xe=Object.freeze({texture:T,color0:new o.Color(16777215),color1:new o.Color(0)}),Kn=({size:e,dpr:n,renderTargetOptions:t,isSizeUpdate:r,onBeforeInit:l})=>{const c=O(n),m=a.useMemo(()=>new o.Scene,[]),{material:i,mesh:d}=Hn({scene:m,onBeforeInit:l}),p=E(e),[g,M]=k({scene:m,camera:p,size:e,dpr:c.fbo,isSizeUpdate:r,...t}),[u,v]=L(xe),s=P(i),f=A(i),x=a.useCallback((y,h)=>{v(y),f(h)},[v,f]);return[a.useCallback((y,h,C)=>{const{gl:_}=y;return x(h,C),s("uTexture",u.texture),s("uColor0",u.color0),s("uColor1",u.color1),M(_)},[M,s,u,x]),x,{scene:m,mesh:d,material:i,camera:p,renderTarget:g,output:g.texture}]};var Xn="#usf ",Yn=`precision highp float; - -varying vec2 vUv; -uniform sampler2D u_texture; -uniform sampler2D uMap; -uniform bool u_isAlphaMap; -uniform sampler2D u_alphaMap; -uniform float uMapIntensity; -uniform vec3 u_brightness; -uniform float u_min; -uniform float u_max; -uniform vec3 u_dodgeColor; -uniform bool u_isDodgeColor; - -void main() { - vec2 uv = vUv; - - #usf - - - float brightness = dot(mapColor,u_brightness); - vec4 textureMap = texture2D(u_texture, uv); - float blendValue = smoothstep(u_min, u_max, brightness); - - - vec3 dodgeColor = u_isDodgeColor ? u_dodgeColor : mapColor; - vec3 outputColor = blendValue * dodgeColor + (1.0 - blendValue) * textureMap.rgb; - - - float alpha = u_isAlphaMap ? texture2D(u_alphaMap, uv).a : textureMap.a; - float mixValue = u_isAlphaMap ? alpha : 0.0; - vec3 alphaColor = vec3(mix(outputColor,mapColor,mixValue)); - - gl_FragColor = vec4(alphaColor,alpha); -}`;const Qn=({scene:e,onBeforeInit:n})=>{const t=a.useMemo(()=>new o.PlaneGeometry(2,2),[]),r=a.useMemo(()=>new o.ShaderMaterial({...F({uniforms:{u_texture:{value:T},uMap:{value:T},u_alphaMap:{value:T},u_isAlphaMap:{value:!1},uMapIntensity:{value:se.mapIntensity},u_brightness:{value:se.brightness},u_min:{value:se.min},u_max:{value:se.max},u_dodgeColor:{value:new o.Color},u_isDodgeColor:{value:!1}},vertexShader:Xn,fragmentShader:Yn},n),...I}),[n]),l=B(e,t,r,o.Mesh);return{material:r,mesh:l}},se=Object.freeze({texture:T,map:T,alphaMap:!1,mapIntensity:.3,brightness:new o.Vector3(.5,.5,.5),min:0,max:1,dodgeColor:!1}),Zn=({size:e,dpr:n,renderTargetOptions:t,isSizeUpdate:r,onBeforeInit:l})=>{const c=O(n),m=a.useMemo(()=>new o.Scene,[]),{material:i,mesh:d}=Qn({scene:m,onBeforeInit:l}),p=E(e),[g,M]=k({scene:m,camera:p,size:e,dpr:c.fbo,isSizeUpdate:r,...t}),[u,v]=L(se),s=P(i),f=A(i),x=a.useCallback((y,h)=>{v(y),f(h)},[v,f]);return[a.useCallback((y,h,C)=>{const{gl:_}=y;return x(h,C),s("u_texture",u.texture),s("uMap",u.map),s("uMapIntensity",u.mapIntensity),u.alphaMap?(s("u_alphaMap",u.alphaMap),s("u_isAlphaMap",!0)):s("u_isAlphaMap",!1),s("u_brightness",u.brightness),s("u_min",u.min),s("u_max",u.max),u.dodgeColor?(s("u_dodgeColor",u.dodgeColor),s("u_isDodgeColor",!0)):s("u_isDodgeColor",!1),M(_)},[M,s,u,x]),x,{scene:m,mesh:d,material:i,camera:p,renderTarget:g,output:g.texture}]};var Jn="#usf ",et=`precision highp float; - -varying vec2 vUv; -uniform vec2 uResolution; -uniform vec2 uTextureResolution; -uniform sampler2D uTexture0; -uniform sampler2D uTexture1; -uniform sampler2D uMap; -uniform float mapIntensity; -uniform float edgeIntensity; -uniform float progress; -uniform float dirX; -uniform float dirY; -uniform vec2 epicenter; -uniform float padding; - -bool isInPaddingArea(vec2 uv) { - return uv.x < padding || uv.x > 1.0 - padding || uv.y < padding || uv.y > 1.0 - padding; -} - -void main() { - #usf - - - vec2 map = texture2D(uMap, uv).rg; - vec2 normalizedMap = map * 2.0 - 1.0; - - - uv = uv * 2.0 - 1.0; - uv *= map * distance(epicenter, uv) * edgeIntensity + 1.0; - uv = (uv + 1.0) / 2.0; - - - if (isInPaddingArea(uv)) { - gl_FragColor = vec4(0.0, 0.0, 0.0, 0.0); - return; - } - vec2 paddedUV = uv * (1.0 - 2.0 * padding * -1.) + padding * -1.; - - - vec2 centeredUV = paddedUV - vec2(0.5); - - - centeredUV *= normalizedMap * map * mapIntensity + 1.0; - - - float xOffsetTexture0 = 0.5 - dirX * progress; - float yOffsetTexture0 = 0.5 - dirY * progress; - vec2 samplePosTexture0 = vec2(xOffsetTexture0, yOffsetTexture0) + centeredUV; - - - float xOffsetTexture1 = 0.5 + dirX * (1.0 - progress); - float yOffsetTexture1 = 0.5 + dirY * (1.0 - progress); - vec2 samplePosTexture1 = vec2(xOffsetTexture1, yOffsetTexture1) + centeredUV; - - vec4 color0 = texture2D(uTexture0, samplePosTexture0); - vec4 color1 = texture2D(uTexture1, samplePosTexture1); - - gl_FragColor = mix(color0, color1, progress); - -}`;const nt=({scene:e,size:n,dpr:t,onBeforeInit:r})=>{const l=a.useMemo(()=>new o.PlaneGeometry(2,2),[]),c=a.useMemo(()=>{var p,g;return new o.ShaderMaterial({...F({uniforms:{uResolution:{value:new o.Vector2},uTextureResolution:{value:new o.Vector2},uTexture0:{value:T},uTexture1:{value:T},padding:{value:ee.padding},uMap:{value:T},edgeIntensity:{value:ee.edgeIntensity},mapIntensity:{value:ee.mapIntensity},epicenter:{value:ee.epicenter},progress:{value:ee.progress},dirX:{value:(p=ee.dir)==null?void 0:p.x},dirY:{value:(g=ee.dir)==null?void 0:g.y}},vertexShader:Jn,fragmentShader:et},r),...I})},[r]),m=N(n,t);P(c)("uResolution",m.clone());const i=B(e,l,c,o.Mesh);return{material:c,mesh:i}},ee=Object.freeze({texture0:T,texture1:T,padding:0,map:T,mapIntensity:0,edgeIntensity:0,epicenter:new o.Vector2(0,0),progress:0,dir:new o.Vector2(0,0)}),tt=({size:e,dpr:n,renderTargetOptions:t,isSizeUpdate:r,onBeforeInit:l})=>{const c=O(n),m=a.useMemo(()=>new o.Scene,[]),{material:i,mesh:d}=nt({scene:m,size:e,dpr:c.shader,onBeforeInit:l}),p=E(e),[g,M]=k({scene:m,camera:p,dpr:c.fbo,size:e,isSizeUpdate:r,...t}),[u,v]=L(ee),s=P(i),f=A(i),x=a.useCallback((y,h)=>{v(y),f(h)},[v,f]);return[a.useCallback((y,h,C)=>{var R,j,D,q,H,re,oe,ae;const{gl:_}=y;x(h,C),s("uTexture0",u.texture0),s("uTexture1",u.texture1),s("progress",u.progress);const w=[((j=(R=u.texture0)==null?void 0:R.image)==null?void 0:j.width)||0,((q=(D=u.texture0)==null?void 0:D.image)==null?void 0:q.height)||0],V=[((re=(H=u.texture1)==null?void 0:H.image)==null?void 0:re.width)||0,((ae=(oe=u.texture1)==null?void 0:oe.image)==null?void 0:ae.height)||0],z=w.map((ie,G)=>ie+(V[G]-ie)*u.progress);return s("uTextureResolution",z),s("padding",u.padding),s("uMap",u.map),s("mapIntensity",u.mapIntensity),s("edgeIntensity",u.edgeIntensity),s("epicenter",u.epicenter),s("dirX",u.dir.x),s("dirY",u.dir.y),M(_)},[M,s,u,x]),x,{scene:m,mesh:d,material:i,camera:p,renderTarget:g,output:g.texture}]};var rt="#usf ",ot=`precision highp float; - -varying vec2 vUv; -uniform sampler2D u_texture; -uniform vec3 u_brightness; -uniform float u_min; -uniform float u_max; - -void main() { - vec2 uv = vUv; - vec3 color = texture2D(u_texture, uv).rgb; - float brightness = dot(color,u_brightness); - float alpha = clamp(smoothstep(u_min, u_max, brightness),0.0,1.0); - gl_FragColor = vec4(color, alpha); -}`;const at=({scene:e,onBeforeInit:n})=>{const t=a.useMemo(()=>new o.PlaneGeometry(2,2),[]),r=a.useMemo(()=>new o.ShaderMaterial({...F({uniforms:{u_texture:{value:T},u_brightness:{value:fe.brightness},u_min:{value:fe.min},u_max:{value:fe.max}},vertexShader:rt,fragmentShader:ot},n),...I}),[n]),l=B(e,t,r,o.Mesh);return{material:r,mesh:l}},fe=Object.freeze({texture:T,brightness:new o.Vector3(.5,.5,.5),min:0,max:1}),ut=({size:e,dpr:n,renderTargetOptions:t,isSizeUpdate:r,onBeforeInit:l})=>{const c=O(n),m=a.useMemo(()=>new o.Scene,[]),{material:i,mesh:d}=at({scene:m,onBeforeInit:l}),p=E(e),[g,M]=k({scene:m,camera:p,size:e,dpr:c.fbo,isSizeUpdate:r,...t}),[u,v]=L(fe),s=P(i),f=A(i),x=a.useCallback((y,h)=>{v(y),f(h)},[v,f]);return[a.useCallback((y,h,C)=>{const{gl:_}=y;return x(h,C),s("u_texture",u.texture),s("u_brightness",u.brightness),s("u_min",u.min),s("u_max",u.max),M(_)},[M,s,u,x]),x,{scene:m,mesh:d,material:i,camera:p,renderTarget:g,output:g.texture}]};var it="#usf ",st=`precision highp float; - -varying vec2 vUv; -uniform sampler2D u_texture; -uniform sampler2D uMap; -uniform float uMapIntensity; - -void main() { - vec2 uv = vUv; - - #usf - - gl_FragColor = texture2D(u_texture, uv); -}`;const lt=({scene:e,onBeforeInit:n})=>{const t=a.useMemo(()=>new o.PlaneGeometry(2,2),[]),r=a.useMemo(()=>new o.ShaderMaterial({...F({uniforms:{u_texture:{value:T},uMap:{value:T},uMapIntensity:{value:Ce.mapIntensity}},vertexShader:it,fragmentShader:st},n),...I}),[n]),l=B(e,t,r,o.Mesh);return{material:r,mesh:l}},Ce=Object.freeze({texture:T,map:T,mapIntensity:.3}),ct=({size:e,dpr:n,renderTargetOptions:t,isSizeUpdate:r,onBeforeInit:l})=>{const c=O(n),m=a.useMemo(()=>new o.Scene,[]),{material:i,mesh:d}=lt({scene:m,onBeforeInit:l}),p=E(e),[g,M]=k({scene:m,camera:p,size:e,dpr:c.fbo,isSizeUpdate:r,...t}),[u,v]=L(Ce),s=P(i),f=A(i),x=a.useCallback((y,h)=>{v(y),f(h)},[v,f]);return[a.useCallback((y,h,C)=>{const{gl:_}=y;return x(h,C),s("u_texture",u.texture),s("uMap",u.map),s("uMapIntensity",u.mapIntensity),M(_)},[M,s,u,x]),x,{scene:m,mesh:d,material:i,camera:p,renderTarget:g,output:g.texture}]};var mt="#usf ",vt=`precision highp float; - -uniform sampler2D uTexture; -uniform sampler2D uMap; - -varying vec2 vUv; - -void main() { - vec2 uv = vUv; - vec4 tex = texture2D(uTexture, uv); - vec4 map = texture2D(uMap, uv); - gl_FragColor = mix(tex,map,map.a); -}`;const ft=({scene:e,onBeforeInit:n})=>{const t=a.useMemo(()=>new o.PlaneGeometry(2,2),[]),r=a.useMemo(()=>new o.ShaderMaterial({...F({uniforms:{uTexture:{value:T},uMap:{value:T}},vertexShader:mt,fragmentShader:vt},n),...I}),[n]),l=B(e,t,r,o.Mesh);return{material:r,mesh:l}},Ae=Object.freeze({texture:T,map:T}),pt=({size:e,dpr:n,renderTargetOptions:t,isSizeUpdate:r,onBeforeInit:l})=>{const c=O(n),m=a.useMemo(()=>new o.Scene,[]),{material:i,mesh:d}=ft({scene:m,size:e,onBeforeInit:l}),p=E(e),[g,M]=k({scene:m,camera:p,size:e,dpr:c.fbo,isSizeUpdate:r,...t}),[u,v]=L(Ae),s=P(i),f=A(i),x=a.useCallback((y,h)=>{v(y),f(h)},[v,f]);return[a.useCallback((y,h,C)=>{const{gl:_}=y;return x(h,C),s("uTexture",u.texture),s("uMap",u.map),M(_)},[s,M,u,x]),x,{scene:m,mesh:d,material:i,camera:p,renderTarget:g,output:g.texture}]};var dt="#usf ",gt=`precision highp float; - -varying vec2 vUv; -uniform sampler2D u_texture; -uniform float u_brightness; -uniform float u_saturation; - -#usf - -#usf - -void main() { - vec4 tex = texture2D(u_texture, vUv); - vec3 hsv = rgb2hsv(tex.rgb); - hsv.y *= u_saturation; - hsv.z *= u_brightness; - vec3 final = hsv2rgb(hsv); - gl_FragColor = vec4(final, tex.a); -}`;const ht=({scene:e,onBeforeInit:n})=>{const t=a.useMemo(()=>new o.PlaneGeometry(2,2),[]),r=a.useMemo(()=>new o.ShaderMaterial({...F({uniforms:{u_texture:{value:T},u_brightness:{value:Me.brightness},u_saturation:{value:Me.saturation}},vertexShader:dt,fragmentShader:gt},n),...I}),[n]),l=B(e,t,r,o.Mesh);return{material:r,mesh:l}},Me=Object.freeze({texture:T,brightness:1,saturation:1}),xt=({size:e,dpr:n,renderTargetOptions:t,isSizeUpdate:r,onBeforeInit:l})=>{const c=O(n),m=a.useMemo(()=>new o.Scene,[]),{material:i,mesh:d}=ht({scene:m,size:e,onBeforeInit:l}),p=E(e),[g,M]=k({scene:m,camera:p,size:e,dpr:c.fbo,isSizeUpdate:r,...t}),[u,v]=L(Me),s=P(i),f=A(i),x=a.useCallback((y,h)=>{v(y),f(h)},[v,f]);return[a.useCallback((y,h,C)=>{const{gl:_}=y;return x(h,C),s("u_texture",u.texture),s("u_brightness",u.brightness),s("u_saturation",u.saturation),M(_)},[s,M,u,x]),x,{scene:m,mesh:d,material:i,camera:p,renderTarget:g,output:g.texture}]};var Mt="#usf ",yt=`precision highp float; - -varying vec2 vUv; -uniform vec2 uResolution; -uniform vec2 uTextureResolution; -uniform sampler2D uTexture; - -void main() { - #usf - - gl_FragColor = texture2D(uTexture, uv); -}`;const bt=({scene:e,size:n,dpr:t,onBeforeInit:r})=>{const l=a.useMemo(()=>new o.PlaneGeometry(2,2),[]),c=a.useMemo(()=>new o.ShaderMaterial({...F({uniforms:{uResolution:{value:new o.Vector2},uTextureResolution:{value:new o.Vector2},uTexture:{value:T}},vertexShader:Mt,fragmentShader:yt},r),...I}),[r]),m=N(n,t);P(c)("uResolution",m.clone());const i=B(e,l,c,o.Mesh);return{material:c,mesh:i}},Fe=Object.freeze({texture:T}),St=({size:e,dpr:n,renderTargetOptions:t,isSizeUpdate:r,onBeforeInit:l})=>{const c=O(n),m=a.useMemo(()=>new o.Scene,[]),{material:i,mesh:d}=bt({scene:m,size:e,dpr:c.shader,onBeforeInit:l}),p=E(e),[g,M]=k({scene:m,camera:p,dpr:c.fbo,size:e,isSizeUpdate:r,...t}),[u,v]=L(Fe),s=P(i),f=A(i),x=a.useCallback((y,h)=>{v(y),f(h)},[v,f]);return[a.useCallback((y,h,C)=>{var w,V,z,R,j,D;const{gl:_}=y;return x(h,C),s("uTexture",u.texture),s("uTextureResolution",[((z=(V=(w=u.texture)==null?void 0:w.source)==null?void 0:V.data)==null?void 0:z.width)||0,((D=(j=(R=u.texture)==null?void 0:R.source)==null?void 0:j.data)==null?void 0:D.height)||0]),M(_)},[M,s,u,x]),x,{scene:m,mesh:d,material:i,camera:p,renderTarget:g,output:g.texture}]};var Ct="#usf ",_t=`precision highp float; - -varying vec2 vUv; -uniform sampler2D uTexture; -uniform vec2 uResolution; -uniform float uBlurSize; - -void main() { - vec2 uv = vUv; - vec2 perDivSize = uBlurSize / uResolution; - - - vec4 outColor = vec4( - texture2D(uTexture, uv + perDivSize * vec2(-1.0, -1.0)) + - texture2D(uTexture, uv + perDivSize * vec2(0.0, -1.0)) + - texture2D(uTexture, uv + perDivSize * vec2(1.0, -1.0)) + - texture2D(uTexture, uv + perDivSize * vec2(-1.0, 0.0)) + - texture2D(uTexture, uv + perDivSize * vec2(0.0, 0.0)) + - texture2D(uTexture, uv + perDivSize * vec2(1.0, 0.0)) + - texture2D(uTexture, uv + perDivSize * vec2(-1.0, 1.0)) + - texture2D(uTexture, uv + perDivSize * vec2(0.0, 1.0)) + - texture2D(uTexture, uv + perDivSize * vec2(1.0, 1.0)) - ) / 9.0; - - gl_FragColor = outColor; -}`;const Tt=({scene:e,onBeforeInit:n})=>{const t=a.useMemo(()=>new o.PlaneGeometry(2,2),[]),r=a.useMemo(()=>new o.ShaderMaterial({...F({uniforms:{uTexture:{value:T},uResolution:{value:new o.Vector2(0,0)},uBlurSize:{value:_e.blurSize}},vertexShader:Ct,fragmentShader:_t},n),...I}),[n]),l=B(e,t,r,o.Mesh);return{material:r,mesh:l}},_e=Object.freeze({texture:T,blurSize:3,blurPower:5}),wt=({size:e,dpr:n,renderTargetOptions:t,isSizeUpdate:r,onBeforeInit:l})=>{const c=O(n),m=a.useMemo(()=>new o.Scene,[]),{material:i,mesh:d}=Tt({scene:m,onBeforeInit:l}),p=E(e),g=a.useMemo(()=>({scene:m,camera:p,size:e,dpr:c.fbo,isSizeUpdate:r,...t}),[m,p,e,c.fbo,r,t]),[M,u]=ne(g),[v,s]=L(_e),f=P(i),x=A(i),b=a.useCallback((h,C)=>{s(h),x(C)},[s,x]);return[a.useCallback((h,C,_)=>{var z,R,j,D,q,H;const{gl:w}=h;b(C,_),f("uTexture",v.texture),f("uResolution",[((j=(R=(z=v.texture)==null?void 0:z.source)==null?void 0:R.data)==null?void 0:j.width)||0,((H=(q=(D=v.texture)==null?void 0:D.source)==null?void 0:q.data)==null?void 0:H.height)||0]),f("uBlurSize",v.blurSize);let V=u(w);for(let re=0;re{const t=a.useMemo(()=>new o.PlaneGeometry(2,2),[]),r=a.useMemo(()=>new o.ShaderMaterial({...F({uniforms:{uTexture:{value:T},uBackbuffer:{value:T},uBegin:{value:pe.begin},uEnd:{value:pe.end},uStrength:{value:pe.strength}},vertexShader:Dt,fragmentShader:Rt},n),...I}),[n]),l=B(e,t,r,o.Mesh);return{material:r,mesh:l}},pe=Object.freeze({texture:T,begin:new o.Vector2(0,0),end:new o.Vector2(0,0),strength:.9}),At=({size:e,dpr:n,renderTargetOptions:t,isSizeUpdate:r,onBeforeInit:l})=>{const c=O(n),m=a.useMemo(()=>new o.Scene,[]),{material:i,mesh:d}=Pt({scene:m,onBeforeInit:l}),p=E(e),g=a.useMemo(()=>({scene:m,camera:p,size:e,dpr:c.fbo,isSizeUpdate:r,...t}),[m,p,e,c.fbo,r,t]),[M,u]=ne(g),[v,s]=L(pe),f=P(i),x=A(i),b=a.useCallback((h,C)=>{s(h),x(C)},[s,x]);return[a.useCallback((h,C,_)=>{const{gl:w}=h;return b(C,_),f("uTexture",v.texture),f("uBegin",v.begin),f("uEnd",v.end),f("uStrength",v.strength),u(w,({read:V})=>{f("uBackbuffer",V)})},[u,f,b,v]),b,{scene:m,mesh:d,material:i,camera:p,renderTarget:M,output:M.read.texture}]};var Ft="#usf ",Vt=`precision highp float; - -varying vec2 vUv; -uniform float uProgress; -uniform float uStrength; -uniform float uWidth; -uniform vec2 uEpicenter; -uniform int uMode; - -float PI = 3.141592653589; - -void main() { - - vec2 uv = vUv; - - float progress = min(uProgress, 1.0); - float progressFactor = sin(progress * PI); - - float border = progress - progress * progressFactor * uWidth; - float blur = uStrength * progressFactor; - - - vec2 normalizeCenter = (uEpicenter + 1.0) / 2.0; - - - float dist = uMode == 0 ? length(uv - normalizeCenter) : uMode == 1 ? length(uv.x - normalizeCenter.x) : length(uv.y - normalizeCenter.y); - - - float maxDistance = max( - length(vec2(0.0, 0.0) - normalizeCenter), - max( - length(vec2(1.0, 0.0) - normalizeCenter), - max( - length(vec2(0.0, 1.0) - normalizeCenter), - length(vec2(1.0, 1.0) - normalizeCenter) - ) - ) - ); - - - dist = maxDistance > 0.0 ? dist / maxDistance : dist; - - vec3 color = vec3(smoothstep(border - blur, border, dist) - - smoothstep(progress, progress + blur, dist)); - - - color *= progressFactor; - - gl_FragColor = vec4(color, 1.0); -}`;const It=({scene:e,onBeforeInit:n})=>{const t=a.useMemo(()=>new o.PlaneGeometry(2,2),[]),r=a.useMemo(()=>new o.ShaderMaterial({...F({uniforms:{uEpicenter:{value:le.epicenter},uProgress:{value:le.progress},uStrength:{value:le.strength},uWidth:{value:le.width},uMode:{value:0}},vertexShader:Ft,fragmentShader:Vt},n),...I}),[n]),l=B(e,t,r,o.Mesh);return{material:r,mesh:l}},le=Object.freeze({epicenter:new o.Vector2(0,0),progress:0,width:0,strength:0,mode:"center"}),zt=({size:e,dpr:n,renderTargetOptions:t,isSizeUpdate:r,onBeforeInit:l})=>{const c=O(n),m=a.useMemo(()=>new o.Scene,[]),{material:i,mesh:d}=It({scene:m,onBeforeInit:l}),p=E(e),[g,M]=k({scene:m,camera:p,size:e,dpr:c.fbo,isSizeUpdate:r,...t}),[u,v]=L(le),s=P(i),f=A(i),x=a.useCallback((y,h)=>{v(y),f(h)},[v,f]);return[a.useCallback((y,h,C)=>{const{gl:_}=y;return x(h,C),s("uEpicenter",u.epicenter),s("uProgress",u.progress),s("uWidth",u.width),s("uStrength",u.strength),s("uMode",u.mode==="center"?0:u.mode==="horizontal"?1:2),M(_)},[M,s,u,x]),x,{scene:m,mesh:d,material:i,camera:p,renderTarget:g,output:g.texture}]};var Ot="#usf ",Ut=`precision highp float; -varying vec2 vUv; - -uniform sampler2D u_texture; -uniform vec2 u_resolution; -uniform vec3 u_keyColor; -uniform float u_similarity; -uniform float u_smoothness; -uniform float u_spill; - -uniform vec4 u_color; -uniform float u_contrast; -uniform float u_brightness; -uniform float u_gamma; - -vec2 RGBtoUV(vec3 rgb) { - return vec2( - rgb.r * -0.169 + rgb.g * -0.331 + rgb.b * 0.5 + 0.5, - rgb.r * 0.5 + rgb.g * -0.419 + rgb.b * -0.081 + 0.5 - ); -} -float getChromeDist(vec3 texColor){ - float chromaDist = distance(RGBtoUV(texColor), RGBtoUV(u_keyColor)); - return chromaDist; -} - -float getBoxFilteredChromaDist(vec3 rgb, vec2 uv) -{ - vec2 pixel_size = vec2(1.) / u_resolution; - vec2 h_pixel_size = pixel_size / 2.0; - vec2 point_0 = vec2(pixel_size.x, h_pixel_size.y); - vec2 point_1 = vec2(h_pixel_size.x, -pixel_size.y); - float distVal = getChromeDist(texture2D(u_texture,uv-point_0).rgb); - distVal += getChromeDist(texture2D(u_texture,uv+point_0).rgb); - distVal += getChromeDist(texture2D(u_texture,uv-point_1).rgb); - distVal += getChromeDist(texture2D(u_texture,uv+point_1).rgb); - distVal *= 2.0; - distVal += getChromeDist(rgb); - return distVal / 9.0; -} - -vec4 CalcColor(vec4 rgba) -{ - return vec4(pow(rgba.rgb, vec3(u_gamma, u_gamma, u_gamma)) * u_contrast + u_brightness, rgba.a); -} - -void main() { - - vec2 uv = vUv; - - vec4 texColor = texture2D(u_texture, uv); - texColor.rgb *= (texColor.a > 0.) ? (1. / texColor.a) : 0.; - - float chromaDist = getBoxFilteredChromaDist(texColor.rgb,uv); - - float baseMask = chromaDist - u_similarity; - float fullMask = pow(clamp(baseMask / u_smoothness, 0., 1.), 1.5); - - texColor.rgba *= u_color; - texColor.a = fullMask; - - float spillVal = pow(clamp(baseMask / u_spill, 0., 1.), 1.5); - float desat = clamp(texColor.r * 0.2126 + texColor.g * 0.7152 + texColor.b * 0.0722, 0., 1.); - texColor.rgb = mix(vec3(desat, desat, desat), texColor.rgb, spillVal); - - vec4 finColor = CalcColor(texColor); - - gl_FragColor = finColor; -}`;const Bt=({scene:e,size:n,dpr:t,onBeforeInit:r})=>{const l=a.useMemo(()=>new o.PlaneGeometry(2,2),[]),c=a.useMemo(()=>new o.ShaderMaterial({...F({uniforms:{u_texture:{value:T},u_resolution:{value:new o.Vector2},u_keyColor:{value:X.color},u_similarity:{value:X.similarity},u_smoothness:{value:X.smoothness},u_spill:{value:X.spill},u_color:{value:X.color},u_contrast:{value:X.contrast},u_brightness:{value:X.brightness},u_gamma:{value:X.gamma}},vertexShader:Ot,fragmentShader:Ut},r),...I}),[r]),m=N(n,t);P(c)("u_resolution",m.clone());const i=B(e,l,c,o.Mesh);return{material:c,mesh:i}},X=Object.freeze({texture:T,keyColor:new o.Color(65280),similarity:.2,smoothness:.1,spill:.2,color:new o.Vector4(1,1,1,1),contrast:1,brightness:0,gamma:1}),Et=({size:e,dpr:n,renderTargetOptions:t,isSizeUpdate:r,onBeforeInit:l})=>{const c=O(n),m=a.useMemo(()=>new o.Scene,[]),{material:i,mesh:d}=Bt({scene:m,size:e,dpr:c.shader,onBeforeInit:l}),p=E(e),[g,M]=k({scene:m,camera:p,size:e,dpr:c.fbo,isSizeUpdate:r,...t}),[u,v]=L(X),s=P(i),f=A(i),x=a.useCallback((y,h)=>{v(y),f(h)},[v,f]);return[a.useCallback((y,h,C)=>{const{gl:_}=y;return x(h,C),s("u_texture",u.texture),s("u_keyColor",u.keyColor),s("u_similarity",u.similarity),s("u_smoothness",u.smoothness),s("u_spill",u.spill),s("u_color",u.color),s("u_contrast",u.contrast),s("u_brightness",u.brightness),s("u_gamma",u.gamma),M(_)},[M,s,u,x]),x,{scene:m,mesh:d,material:i,camera:p,renderTarget:g,output:g.texture}]};var Lt=`precision highp float; - -varying vec2 vUv; -#usf - -#usf - -void main() { - vec4 usf_Position = vec4(position,1.); - vUv = uv; - - #usf
- - gl_Position = usf_Position; -}`,kt=`precision highp float; - -varying vec2 vUv; -#usf - -uniform sampler2D uTexture; -uniform sampler2D uBackbuffer; -uniform float uTime; -uniform vec2 uPointer; -uniform vec2 uResolution; - -#usf - -void main() { - vec4 usf_FragColor = vec4(1.); - - #usf
- - gl_FragColor = usf_FragColor; -}`;const $t=({scene:e,size:n,dpr:t,onBeforeInit:r})=>{const l=a.useMemo(()=>new o.PlaneGeometry(2,2),[]),c=a.useMemo(()=>new o.ShaderMaterial({...F({uniforms:{uTexture:{value:T},uBackbuffer:{value:T},uTime:{value:0},uPointer:{value:new o.Vector2},uResolution:{value:new o.Vector2}},vertexShader:Lt,fragmentShader:kt},r),...I}),[r]),m=N(n,t);P(c)("uResolution",m.clone());const i=B(e,l,c,o.Mesh);return{material:c,mesh:i}},Ve=Object.freeze({texture:T,beat:!1}),jt=({size:e,dpr:n,renderTargetOptions:t,isSizeUpdate:r,onBeforeInit:l})=>{const c=O(n),m=a.useMemo(()=>new o.Scene,[]),{material:i,mesh:d}=$t({scene:m,size:e,dpr:c.shader,onBeforeInit:l}),p=E(e),g=a.useMemo(()=>({scene:m,camera:p,size:e,dpr:c.fbo,isSizeUpdate:r,...t}),[m,p,e,c.fbo,r,t]),[M,u]=ne(g),[v,s]=L(Ve),f=P(i),x=A(i),b=a.useCallback((h,C)=>{s(h),x(C)},[s,x]);return[a.useCallback((h,C,_)=>{const{gl:w,clock:V,pointer:z}=h;return b(C,_),f("uPointer",z),f("uTexture",v.texture),f("uTime",v.beat||V.getElapsedTime()),u(w,({read:R})=>{f("uBackbuffer",R)})},[u,f,v,b]),b,{scene:m,mesh:d,material:i,camera:p,renderTarget:M,output:M.read.texture}]};var Wt=`precision highp float; - -varying vec2 vUv; -#usf - -#usf - -void main() { - vec4 usf_Position = vec4(position,1.); - vUv = uv; - - #usf
- - gl_Position = usf_Position; -}`,qt=`precision highp float; - -varying vec2 vUv; -#usf - -uniform vec2 uResolution; - -#usf - -void main() { - vec4 usf_FragColor = vec4(1.); - - #usf
- - gl_FragColor = usf_FragColor; -}`;const Nt=({scene:e,size:n,dpr:t,onBeforeInit:r})=>{const l=a.useMemo(()=>new o.PlaneGeometry(2,2),[]),c=a.useMemo(()=>new o.ShaderMaterial({...F({uniforms:{uResolution:{value:new o.Vector2}},vertexShader:Wt,fragmentShader:qt},r),...I}),[r]),m=N(n,t);P(c)("uResolution",m.clone());const i=B(e,l,c,o.Mesh);return{material:c,mesh:i}},Gt=Object.freeze({}),Ht=({size:e,dpr:n,renderTargetOptions:t,isSizeUpdate:r,onBeforeInit:l})=>{const c=O(n),m=a.useMemo(()=>new o.Scene,[]),{material:i,mesh:d}=Nt({scene:m,size:e,dpr:c.shader,onBeforeInit:l}),p=E(e),g=a.useMemo(()=>({scene:m,camera:p,size:e,dpr:c.fbo,isSizeUpdate:r,...t}),[m,p,e,c.fbo,r,t]),[M,u]=k(g),v=A(i),s=a.useCallback((x,b)=>{v(b)},[v]);return[a.useCallback((x,b,y)=>{const{gl:h}=x;return s(b,y),u(h)},[u,s]),s,{scene:m,mesh:d,material:i,camera:p,renderTarget:M,output:M.texture}]},Kt=({scene:e,geometry:n,material:t})=>{const r=B(e,n,t,o.Points),l=B(e,a.useMemo(()=>n.clone(),[n]),a.useMemo(()=>t.clone(),[t]),o.Mesh);return l.visible=!1,{points:r,interactiveMesh:l}};var Xt=`uniform vec2 uResolution; -uniform float uMorphProgress; -uniform float uPointSize; - -uniform sampler2D uPicture; -uniform bool uIsPicture; -uniform sampler2D uAlphaPicture; -uniform bool uIsAlphaPicture; - -uniform vec3 uColor0; -uniform vec3 uColor1; -uniform vec3 uColor2; -uniform vec3 uColor3; - -uniform float uTime; - -uniform float uWobblePositionFrequency; -uniform float uWobbleTimeFrequency; -uniform float uWobbleStrength; -uniform float uWarpPositionFrequency; -uniform float uWarpTimeFrequency; -uniform float uWarpStrength; - -uniform sampler2D uDisplacement; -uniform bool uIsDisplacement; -uniform float uDisplacementIntensity; - -uniform float uSizeRandomIntensity; -uniform float uSizeRandomTimeFrequency; -uniform float uSizeRandomMin; -uniform float uSizeRandomMax; - -uniform float uMapArrayLength; - -uniform float uDivergence; -uniform vec3 uDivergencePoint; - -varying vec3 vColor; -varying float vPictureAlpha; -varying vec3 vDisplacementColor; -varying float vDisplacementIntensity; -varying float vMapArrayIndex; - -#usf - -#usf - -#usf - -float random3D(vec3 co) { - return fract(sin(dot(co.xyz ,vec3(12.9898, 78.233, 45.764))) * 43758.5453); -} - -void main() { - vec3 newPosition = position; - vec2 newUv = uv; - - #usf - #usf - - - vec3 displacement = uIsDisplacement ? texture2D(uDisplacement, newUv).rgb : vec3(0.0); - float displacementIntensity = smoothstep(0., 1., displacement.g); - vDisplacementColor = displacement; - vDisplacementIntensity = displacementIntensity; - - - displacement = displacement * 2.-1.; - displacement *= displacementIntensity * uDisplacementIntensity; - newPosition += displacement; - - - vec3 divergenceDir = newPosition - uDivergencePoint; - if (uDivergence > 0.0) { - newPosition += normalize(divergenceDir) * uDivergence; - } else if (uDivergence < 0.0) { - newPosition -= normalize(divergenceDir) * abs(uDivergence); - } - - - vec4 modelPosition = modelMatrix * vec4(newPosition, 1.0); - vec4 viewPosition = viewMatrix * modelPosition; - vec4 projectedPosition = projectionMatrix * viewPosition; - - - float wobble = uWobbleStrength > 0. ? getWobble(projectedPosition.xyz) : 0.0; - - gl_Position = projectedPosition += wobble; - - - vColor = uIsPicture ? texture2D(uPicture, newUv).rgb : mix(mix(uColor0, uColor1, newPosition.x), mix(uColor2, uColor3, newPosition.y), newPosition.z); - - - vPictureAlpha = uIsAlphaPicture ? texture2D(uAlphaPicture, newUv).g : 1.; - - - - float sizeRand = uSizeRandomIntensity > 0. ? mix(uSizeRandomMin,uSizeRandomMax,(simplexNoise4d(vec4(newPosition,uTime * uSizeRandomTimeFrequency))*.5+.5)) * uSizeRandomIntensity : 1.; - gl_PointSize = uPointSize * vPictureAlpha * uResolution.y * sizeRand; - gl_PointSize *= (1.0 / - viewPosition.z); - - - vMapArrayIndex = uMapArrayLength > 0. ? floor(random3D(position) * uMapArrayLength) : 0.; -}`,Yt=`precision highp float; -precision highp int; - -varying vec3 vColor; -varying float vPictureAlpha; -varying vec3 vDisplacementColor; -varying float vDisplacementIntensity; -varying float vMapArrayIndex; - -uniform float uBlurAlpha; -uniform float uBlurRadius; -uniform sampler2D uMap; -uniform bool uIsMap; -uniform sampler2D uAlphaMap; -uniform bool uIsAlphaMap; -uniform float uDisplacementColorIntensity; -uniform float uPointAlpha; - -#usf - -void main() { - vec2 uv = gl_PointCoord; - uv.y = 1.0 - uv.y; - - - float distanceToCenter = length(uv - .5); - float alpha = clamp(uBlurRadius / distanceToCenter - (1.-uBlurAlpha) , 0. , 1.); - - - vec4 mapArrayColor; - #usf - vec4 mapColor = isMapArray ? mapArrayColor : uIsMap ? texture2D(uMap,uv) : vec4(1.); - vec3 finalColor = isMapArray || uIsMap ? mapColor.rgb : vColor; - - - float mixIntensity = clamp(uDisplacementColorIntensity * vDisplacementIntensity,0.,1.); - finalColor = vDisplacementIntensity > 0. ? mix(finalColor,vDisplacementColor,mixIntensity) : finalColor; - - - float alphaMap = uIsAlphaMap ? texture2D(uAlphaMap,uv).g : 1.; - - gl_FragColor = vec4(finalColor,alpha * vPictureAlpha * alphaMap * mapColor.a * uPointAlpha); -}`;const Ie=(e,n,t,r,l)=>{var g;const c=t==="position"?"positionTarget":"uvTarget",m=t==="position"?"#usf ":"#usf ",i=t==="position"?"#usf ":"#usf ",d=t==="position"?"positionsList":"uvsList",p=t==="position"?` - float scaledProgress = uMorphProgress * ${e.length-1}.; - int baseIndex = int(floor(scaledProgress)); - baseIndex = clamp(baseIndex, 0, ${e.length-1}); - float progress = fract(scaledProgress); - int nextIndex = baseIndex + 1; - newPosition = mix(positionsList[baseIndex], positionsList[nextIndex], progress); - `:"newUv = mix(uvsList[baseIndex], uvsList[nextIndex], progress);";if(e.length>0){n.deleteAttribute(t),n.setAttribute(t,new o.BufferAttribute(e[0],l));let M="",u="";e.forEach((v,s)=>{n.setAttribute(`${c}${s}`,new o.BufferAttribute(v,l)),M+=`attribute vec${l} ${c}${s}; -`,s===0?u+=`${c}${s}`:u+=`,${c}${s}`}),r=r.replace(`${m}`,M),r=r.replace(`${i}`,`vec${l} ${d}[${e.length}] = vec${l}[](${u}); - ${p} - `)}else r=r.replace(`${m}`,""),r=r.replace(`${i}`,""),(g=n==null?void 0:n.attributes[t])!=null&&g.array||we&&console.error(`use-shader-fx:geometry.attributes.${t}.array is not found`);return r},ze=(e,n,t,r)=>{var c;let l=[];if(e&&e.length>0){(c=n==null?void 0:n.attributes[t])!=null&&c.array?l=[n.attributes[t].array,...e]:l=e;const m=Math.max(...l.map(i=>i.length));l.forEach((i,d)=>{if(i.length{let t="";const r={};let l="mapArrayColor = ";return e&&e.length>0?(e.forEach((m,i)=>{const d=`vMapArrayIndex < ${i}.1`,p=`texture2D(uMapArray${i}, uv)`;l+=`( ${d} ) ? ${p} : `,t+=` - uniform sampler2D uMapArray${i}; - `,r[`uMapArray${i}`]={value:m}}),l+="vec4(1.);",t+="bool isMapArray = true;",r.uMapArrayLength={value:e.length}):(l+="vec4(1.0);",t+="bool isMapArray = false;",r.uMapArrayLength={value:0}),{rewritedFragmentShader:n.replace("#usf ",l).replace("#usf ",t),mapArrayUniforms:r}},Zt=({size:e,dpr:n,geometry:t,positions:r,uvs:l,mapArray:c,onBeforeInit:m})=>{const i=a.useMemo(()=>ze(r,t,"position",3),[r,t]),d=a.useMemo(()=>ze(l,t,"uv",2),[l,t]),p=a.useMemo(()=>{i.length!==d.length&&we&&console.log("use-shader-fx:positions and uvs are not matched");const M=Ie(d,t,"uv",Ie(i,t,"position",Xt,3),2),{rewritedFragmentShader:u,mapArrayUniforms:v}=Qt(c,Yt);return new o.ShaderMaterial({...F({uniforms:{uResolution:{value:new o.Vector2(0,0)},uMorphProgress:{value:U.morphProgress},uBlurAlpha:{value:U.blurAlpha},uBlurRadius:{value:U.blurRadius},uPointSize:{value:U.pointSize},uPointAlpha:{value:U.pointAlpha},uPicture:{value:T},uIsPicture:{value:!1},uAlphaPicture:{value:T},uIsAlphaPicture:{value:!1},uColor0:{value:U.color0},uColor1:{value:U.color1},uColor2:{value:U.color2},uColor3:{value:U.color3},uMap:{value:T},uIsMap:{value:!1},uAlphaMap:{value:T},uIsAlphaMap:{value:!1},uTime:{value:0},uWobblePositionFrequency:{value:U.wobblePositionFrequency},uWobbleTimeFrequency:{value:U.wobbleTimeFrequency},uWobbleStrength:{value:U.wobbleStrength},uWarpPositionFrequency:{value:U.warpPositionFrequency},uWarpTimeFrequency:{value:U.warpTimeFrequency},uWarpStrength:{value:U.warpStrength},uDisplacement:{value:T},uIsDisplacement:{value:!1},uDisplacementIntensity:{value:U.displacementIntensity},uDisplacementColorIntensity:{value:U.displacementColorIntensity},uSizeRandomIntensity:{value:U.sizeRandomIntensity},uSizeRandomTimeFrequency:{value:U.sizeRandomTimeFrequency},uSizeRandomMin:{value:U.sizeRandomMin},uSizeRandomMax:{value:U.sizeRandomMax},uDivergence:{value:U.divergence},uDivergencePoint:{value:U.divergencePoint},...v},vertexShader:M,fragmentShader:u},m),...I,blending:o.AdditiveBlending,transparent:!0})},[t,i,d,c,m]),g=N(e,n);return P(p)("uResolution",g.clone()),{material:p,modifiedPositions:i,modifiedUvs:d}},Oe=({size:e,dpr:n,scene:t=!1,geometry:r,positions:l,uvs:c,mapArray:m,onBeforeInit:i})=>{const d=O(n),p=a.useMemo(()=>{const y=r||new o.SphereGeometry(1,32,32);return y.setIndex(null),y.deleteAttribute("normal"),y},[r]),{material:g,modifiedPositions:M,modifiedUvs:u}=Zt({size:e,dpr:d.shader,geometry:p,positions:l,uvs:c,mapArray:m,onBeforeInit:i}),{points:v,interactiveMesh:s}=Kt({scene:t,geometry:p,material:g}),f=P(g),x=A(g);return[a.useCallback((y,h,C)=>{y&&f("uTime",(h==null?void 0:h.beat)||y.clock.getElapsedTime()),h!==void 0&&(f("uMorphProgress",h.morphProgress),f("uBlurAlpha",h.blurAlpha),f("uBlurRadius",h.blurRadius),f("uPointSize",h.pointSize),f("uPointAlpha",h.pointAlpha),h.picture?(f("uPicture",h.picture),f("uIsPicture",!0)):h.picture===!1&&f("uIsPicture",!1),h.alphaPicture?(f("uAlphaPicture",h.alphaPicture),f("uIsAlphaPicture",!0)):h.alphaPicture===!1&&f("uIsAlphaPicture",!1),f("uColor0",h.color0),f("uColor1",h.color1),f("uColor2",h.color2),f("uColor3",h.color3),h.map?(f("uMap",h.map),f("uIsMap",!0)):h.map===!1&&f("uIsMap",!1),h.alphaMap?(f("uAlphaMap",h.alphaMap),f("uIsAlphaMap",!0)):h.alphaMap===!1&&f("uIsAlphaMap",!1),f("uWobbleStrength",h.wobbleStrength),f("uWobblePositionFrequency",h.wobblePositionFrequency),f("uWobbleTimeFrequency",h.wobbleTimeFrequency),f("uWarpStrength",h.warpStrength),f("uWarpPositionFrequency",h.warpPositionFrequency),f("uWarpTimeFrequency",h.warpTimeFrequency),h.displacement?(f("uDisplacement",h.displacement),f("uIsDisplacement",!0)):h.displacement===!1&&f("uIsDisplacement",!1),f("uDisplacementIntensity",h.displacementIntensity),f("uDisplacementColorIntensity",h.displacementColorIntensity),f("uSizeRandomIntensity",h.sizeRandomIntensity),f("uSizeRandomTimeFrequency",h.sizeRandomTimeFrequency),f("uSizeRandomMin",h.sizeRandomMin),f("uSizeRandomMax",h.sizeRandomMax),f("uDivergence",h.divergence),f("uDivergencePoint",h.divergencePoint),x(C))},[f,x]),{points:v,interactiveMesh:s,positions:M,uvs:u}]},U=Object.freeze({morphProgress:0,blurAlpha:.9,blurRadius:.05,pointSize:.05,pointAlpha:1,picture:!1,alphaPicture:!1,color0:new o.Color(16711680),color1:new o.Color(65280),color2:new o.Color(255),color3:new o.Color(16776960),map:!1,alphaMap:!1,wobbleStrength:0,wobblePositionFrequency:.5,wobbleTimeFrequency:.5,warpStrength:0,warpPositionFrequency:.5,warpTimeFrequency:.5,displacement:!1,displacementIntensity:1,displacementColorIntensity:0,sizeRandomIntensity:0,sizeRandomTimeFrequency:.2,sizeRandomMin:.5,sizeRandomMax:1.5,divergence:0,divergencePoint:new o.Vector3(0),beat:!1}),Jt=({size:e,dpr:n,isSizeUpdate:t,renderTargetOptions:r,camera:l,geometry:c,positions:m,uvs:i,onBeforeInit:d})=>{const p=O(n),g=a.useMemo(()=>new o.Scene,[]),[M,{points:u,interactiveMesh:v,positions:s,uvs:f}]=Oe({scene:g,size:e,dpr:n,geometry:c,positions:m,uvs:i,onBeforeInit:d}),[x,b]=k({scene:g,camera:l,size:e,dpr:p.fbo,isSizeUpdate:t,depthBuffer:!0,...r}),y=a.useCallback((C,_,w)=>(M(C,_,w),b(C.gl)),[b,M]),h=a.useCallback((C,_)=>{M(null,C,_)},[M]);return[y,h,{scene:g,points:u,interactiveMesh:v,renderTarget:x,output:x.texture,positions:s,uvs:f}]},Ue=e=>{const n=e.shaderType==="MeshDepthMaterial";e.vertexShader=e.vertexShader.replace("#include ",` - vec3 objectNormal = usf_Normal; - #ifdef USE_TANGENT - vec3 objectTangent = vec3( tangent.xyz ); - #endif - `),e.vertexShader=e.vertexShader.replace("#include ",` - vec3 transformed = usf_Position; - #ifdef USE_ALPHAHASH - vPosition = vec3( position ); - #endif - `),e.vertexShader=e.vertexShader.replace("void main() {",` - uniform float uTime; - uniform float uWobblePositionFrequency; - uniform float uWobbleTimeFrequency; - uniform float uWobbleStrength; - uniform float uWarpPositionFrequency; - uniform float uWarpTimeFrequency; - uniform float uWarpStrength; - - ${n?"attribute vec4 tangent;":""} - - varying float vWobble; - varying vec2 vPosition; - - // edge - varying vec3 vEdgeNormal; - varying vec3 vEdgeViewPosition; - - #usf - - void main() { - - vec3 usf_Position = position; - vec3 usf_Normal = normal; - vec3 biTangent = cross(normal, tangent.xyz); - - // Neighbours positions - float shift = 0.01; - vec3 positionA = usf_Position + tangent.xyz * shift; - vec3 positionB = usf_Position + biTangent * shift; - - // wobble - float wobble = (uWobbleStrength > 0.) ? getWobble(usf_Position) : 0.0; - float wobblePositionA = (uWobbleStrength > 0.) ? getWobble(positionA) : 0.0; - float wobblePositionB = (uWobbleStrength > 0.) ? getWobble(positionB) : 0.0; - - usf_Position += wobble * normal; - positionA += wobblePositionA * normal; - positionB += wobblePositionB * normal; - - // Compute normal - vec3 toA = normalize(positionA - usf_Position); - vec3 toB = normalize(positionB - usf_Position); - usf_Normal = cross(toA, toB); - - // Varying - vPosition = usf_Position.xy; - vWobble = wobble/uWobbleStrength; - - vEdgeNormal = normalize(normalMatrix * usf_Normal); - vec4 viewPosition = viewMatrix * modelMatrix * vec4(usf_Position, 1.0); - vEdgeViewPosition = normalize(viewPosition.xyz); - `)},er=e=>{e.fragmentShader=e.fragmentShader.replace("#include ",` - #include - - if (uEdgeThreshold > 0.0) { - float edgeThreshold = dot(vEdgeNormal, -vEdgeViewPosition); - diffuseColor = edgeThreshold < uEdgeThreshold ? vec4(uEdgeColor, 1.0) : mix(diffuseColor, usf_DiffuseColor, uColorMix); - } else { - diffuseColor = mix(diffuseColor, usf_DiffuseColor, uColorMix); - } - `),e.fragmentShader=e.fragmentShader.replace("void main() {",` - uniform vec3 uColor0; - uniform vec3 uColor1; - uniform vec3 uColor2; - uniform vec3 uColor3; - uniform float uColorMix; - uniform float uEdgeThreshold; - uniform vec3 uEdgeColor; - - // transmission - uniform float uChromaticAberration; - uniform float uAnisotropicBlur; - uniform float uTime; - uniform float uDistortion; - uniform float uDistortionScale; - uniform float uTemporalDistortion; - uniform float uRefractionSamples; - - float rand(float n){return fract(sin(n) * 43758.5453123);} - - #usf - - varying float vWobble; - varying vec2 vPosition; - varying vec3 vEdgeNormal; - varying vec3 vEdgeViewPosition; - - void main(){ - - vec4 usf_DiffuseColor = vec4(1.0); - float colorWobbleMix = smoothstep(-1.,1.,vWobble); - vec2 colorPosMix = vec2(smoothstep(-1.,1.,vPosition.x),smoothstep(-1.,1.,vPosition.y)); - - usf_DiffuseColor.rgb = mix(mix(uColor0, uColor1, colorPosMix.x), mix(uColor2, uColor3, colorPosMix.y), colorWobbleMix); - `)};var nr=`#ifdef USE_TRANSMISSION - - - - - uniform float _transmission; - uniform float thickness; - uniform float attenuationDistance; - uniform vec3 attenuationColor; - - #ifdef USE_TRANSMISSIONMAP - - uniform sampler2D transmissionMap; - - #endif - - #ifdef USE_THICKNESSMAP - - uniform sampler2D thicknessMap; - - #endif - - uniform vec2 transmissionSamplerSize; - uniform sampler2D transmissionSamplerMap; - - uniform mat4 modelMatrix; - uniform mat4 projectionMatrix; - - varying vec3 vWorldPosition; - - - - - float w0( float a ) { - - return ( 1.0 / 6.0 ) * ( a * ( a * ( - a + 3.0 ) - 3.0 ) + 1.0 ); - - } - - float w1( float a ) { - - return ( 1.0 / 6.0 ) * ( a * a * ( 3.0 * a - 6.0 ) + 4.0 ); - - } - - float w2( float a ){ - - return ( 1.0 / 6.0 ) * ( a * ( a * ( - 3.0 * a + 3.0 ) + 3.0 ) + 1.0 ); - - } - - float w3( float a ) { - - return ( 1.0 / 6.0 ) * ( a * a * a ); - - } - - - float g0( float a ) { - - return w0( a ) + w1( a ); - - } - - float g1( float a ) { - - return w2( a ) + w3( a ); - - } - - - float h0( float a ) { - - return - 1.0 + w1( a ) / ( w0( a ) + w1( a ) ); - - } - - float h1( float a ) { - - return 1.0 + w3( a ) / ( w2( a ) + w3( a ) ); - - } - - vec4 bicubic( sampler2D tex, vec2 uv, vec4 texelSize, float lod ) { - - uv = uv * texelSize.zw + 0.5; - - vec2 iuv = floor( uv ); - vec2 fuv = fract( uv ); - - float g0x = g0( fuv.x ); - float g1x = g1( fuv.x ); - float h0x = h0( fuv.x ); - float h1x = h1( fuv.x ); - float h0y = h0( fuv.y ); - float h1y = h1( fuv.y ); - - vec2 p0 = ( vec2( iuv.x + h0x, iuv.y + h0y ) - 0.5 ) * texelSize.xy; - vec2 p1 = ( vec2( iuv.x + h1x, iuv.y + h0y ) - 0.5 ) * texelSize.xy; - vec2 p2 = ( vec2( iuv.x + h0x, iuv.y + h1y ) - 0.5 ) * texelSize.xy; - vec2 p3 = ( vec2( iuv.x + h1x, iuv.y + h1y ) - 0.5 ) * texelSize.xy; - - return g0( fuv.y ) * ( g0x * textureLod( tex, p0, lod ) + g1x * textureLod( tex, p1, lod ) ) + - g1( fuv.y ) * ( g0x * textureLod( tex, p2, lod ) + g1x * textureLod( tex, p3, lod ) ); - - } - - vec4 textureBicubic( sampler2D sampler, vec2 uv, float lod ) { - - vec2 fLodSize = vec2( textureSize( sampler, int( lod ) ) ); - vec2 cLodSize = vec2( textureSize( sampler, int( lod + 1.0 ) ) ); - vec2 fLodSizeInv = 1.0 / fLodSize; - vec2 cLodSizeInv = 1.0 / cLodSize; - vec4 fSample = bicubic( sampler, uv, vec4( fLodSizeInv, fLodSize ), floor( lod ) ); - vec4 cSample = bicubic( sampler, uv, vec4( cLodSizeInv, cLodSize ), ceil( lod ) ); - return mix( fSample, cSample, fract( lod ) ); - - } - - vec3 getVolumeTransmissionRay( const in vec3 n, const in vec3 v, const in float thickness, const in float ior, const in mat4 modelMatrix ) { - - - vec3 refractionVector = refract( - v, normalize( n ), 1.0 / ior ); - - - vec3 modelScale; - modelScale.x = length( vec3( modelMatrix[ 0 ].xyz ) ); - modelScale.y = length( vec3( modelMatrix[ 1 ].xyz ) ); - modelScale.z = length( vec3( modelMatrix[ 2 ].xyz ) ); - - - return normalize( refractionVector ) * thickness * modelScale; - - } - - float applyIorToRoughness( const in float roughness, const in float ior ) { - - - - return roughness * clamp( ior * 2.0 - 2.0, 0.0, 1.0 ); - - } - - vec4 getTransmissionSample( const in vec2 fragCoord, const in float roughness, const in float ior ) { - - float lod = log2( transmissionSamplerSize.x ) * applyIorToRoughness( roughness, ior ); - return textureBicubic( transmissionSamplerMap, fragCoord.xy, lod ); - - } - - vec3 volumeAttenuation( const in float transmissionDistance, const in vec3 attenuationColor, const in float attenuationDistance ) { - - if ( isinf( attenuationDistance ) ) { - - - return vec3( 1.0 ); - - } else { - - - vec3 attenuationCoefficient = -log( attenuationColor ) / attenuationDistance; - vec3 transmittance = exp( - attenuationCoefficient * transmissionDistance ); - return transmittance; - - } - - } - - vec4 getIBLVolumeRefraction( const in vec3 n, const in vec3 v, const in float roughness, const in vec3 diffuseColor, - const in vec3 specularColor, const in float specularF90, const in vec3 position, const in mat4 modelMatrix, - const in mat4 viewMatrix, const in mat4 projMatrix, const in float ior, const in float thickness, - const in vec3 attenuationColor, const in float attenuationDistance ) { - - vec3 transmissionRay = getVolumeTransmissionRay( n, v, thickness, ior, modelMatrix ); - vec3 refractedRayExit = position + transmissionRay; - - - vec4 ndcPos = projMatrix * viewMatrix * vec4( refractedRayExit, 1.0 ); - vec2 refractionCoords = ndcPos.xy / ndcPos.w; - refractionCoords += 1.0; - refractionCoords /= 2.0; - - - vec4 transmittedLight = getTransmissionSample( refractionCoords, roughness, ior ); - - vec3 transmittance = diffuseColor * volumeAttenuation( length( transmissionRay ), attenuationColor, attenuationDistance ); - vec3 attenuatedColor = transmittance * transmittedLight.rgb; - - - vec3 F = EnvironmentBRDF( n, v, specularColor, specularF90, roughness ); - - - - float transmittanceFactor = ( transmittance.r + transmittance.g + transmittance.b ) / 3.0; - - return vec4( ( 1.0 - F ) * attenuatedColor, 1.0 - ( 1.0 - transmittedLight.a ) * transmittanceFactor ); - - } -#endif`,tr=`#ifdef USE_TRANSMISSION - -material.transmission = _transmission; -material.transmissionAlpha = 1.0; -material.thickness = thickness; -material.attenuationDistance = attenuationDistance; -material.attenuationColor = attenuationColor; - -#ifdef USE_TRANSMISSIONMAP - - material.transmission *= texture2D( transmissionMap, vTransmissionMapUv ).r; - -#endif - -#ifdef USE_THICKNESSMAP - - material.thickness *= texture2D( thicknessMap, vThicknessMapUv ).g; - -#endif - -vec3 pos = vWorldPosition; - -vec3 v = normalize( cameraPosition - pos ); -vec3 n = inverseTransformDirection( normal, viewMatrix ); - -vec4 transmitted = getIBLVolumeRefraction( - n, v, material.roughness, material.diffuseColor, material.specularColor, material.specularF90, - pos, modelMatrix, viewMatrix, projectionMatrix, material.ior, material.thickness, - material.attenuationColor, material.attenuationDistance ); - -material.transmissionAlpha = mix( material.transmissionAlpha, transmitted.a, material.transmission ); - -float runningSeed = 0.0; -vec3 transmission = vec3(0.0); -float transmissionR, transmissionB, transmissionG; -float randomCoords = rand(runningSeed++); -float thickness_smear = thickness * max(pow(roughnessFactor, 0.33), uAnisotropicBlur); -vec3 distortionNormal = vec3(0.0); -vec3 temporalOffset = vec3(uTime, -uTime, -uTime) * uTemporalDistortion; - -if (uDistortion > 0.0) { - distortionNormal = uDistortion * vec3(snoiseFractal(vec3((pos * uDistortionScale + temporalOffset))), snoiseFractal(vec3(pos.zxy * uDistortionScale - temporalOffset)), snoiseFractal(vec3(pos.yxz * uDistortionScale + temporalOffset))); -} - -for (float i = 0.0; i < uRefractionSamples; i ++) { - vec3 sampleNorm = normalize(n + roughnessFactor * roughnessFactor * 2.0 * normalize(vec3(rand(runningSeed++) - 0.5, rand(runningSeed++) - 0.5, rand(runningSeed++) - 0.5)) * pow(rand(runningSeed++), 0.33) + distortionNormal); - - transmissionR = getIBLVolumeRefraction( - sampleNorm, v, material.roughness, material.diffuseColor, material.specularColor, material.specularF90, - pos, modelMatrix, viewMatrix, projectionMatrix, material.ior, material.thickness + thickness_smear * (i + randomCoords) / uRefractionSamples, - material.attenuationColor, material.attenuationDistance - ).r; - transmissionG = getIBLVolumeRefraction( - sampleNorm, v, material.roughness, material.diffuseColor, material.specularColor, material.specularF90, - pos, modelMatrix, viewMatrix, projectionMatrix, material.ior * (1.0 + uChromaticAberration * (i + randomCoords) / uRefractionSamples) , material.thickness + thickness_smear * (i + randomCoords) / uRefractionSamples, - material.attenuationColor, material.attenuationDistance - ).g; - transmissionB = getIBLVolumeRefraction( - sampleNorm, v, material.roughness, material.diffuseColor, material.specularColor, material.specularF90, - pos, modelMatrix, viewMatrix, projectionMatrix, material.ior * (1.0 + 2.0 * uChromaticAberration * (i + randomCoords) / uRefractionSamples), material.thickness + thickness_smear * (i + randomCoords) / uRefractionSamples, - material.attenuationColor, material.attenuationDistance - ).b; - transmission.r += transmissionR; - transmission.g += transmissionG; - transmission.b += transmissionB; -} - -transmission /= uRefractionSamples; - -totalDiffuse = mix( totalDiffuse, transmission.rgb, material.transmission ); - -#endif`;const rr=({mat:e,isCustomTransmission:n,parameters:t})=>{e.type==="MeshPhysicalMaterial"&&n&&(t.fragmentShader=t.fragmentShader.replace("#include ",`${nr}`),t.fragmentShader=t.fragmentShader.replace("#include ",`${tr}`)),e.normalMap||(t.vertexShader=t.vertexShader.replace("void main() {",` - attribute vec4 tangent; - - void main() { - `))},or=({baseMaterial:e,materialParameters:n,isCustomTransmission:t=!1,onBeforeInit:r,depthOnBeforeInit:l,depth:c=!1})=>{const{material:m,depthMaterial:i}=a.useMemo(()=>{const d=new(e||o.MeshPhysicalMaterial)(n||{});Object.assign(d.userData,{uniforms:{uTime:{value:0},uWobblePositionFrequency:{value:$.wobblePositionFrequency},uWobbleTimeFrequency:{value:$.wobbleTimeFrequency},uWobbleStrength:{value:$.wobbleStrength},uWarpPositionFrequency:{value:$.warpPositionFrequency},uWarpTimeFrequency:{value:$.warpTimeFrequency},uWarpStrength:{value:$.warpStrength},uColor0:{value:$.color0},uColor1:{value:$.color1},uColor2:{value:$.color2},uColor3:{value:$.color3},uColorMix:{value:$.colorMix},uEdgeThreshold:{value:$.edgeThreshold},uEdgeColor:{value:$.edgeColor},uChromaticAberration:{value:$.chromaticAberration},uAnisotropicBlur:{value:$.anisotropicBlur},uDistortion:{value:$.distortion},uDistortionScale:{value:$.distortionScale},uTemporalDistortion:{value:$.temporalDistortion},uRefractionSamples:{value:$.refractionSamples},transmission:{value:0},_transmission:{value:1},transmissionMap:{value:null}}}),d.onBeforeCompile=g=>{Ue(g),er(g),rr({parameters:g,mat:d,isCustomTransmission:t});const M=F({fragmentShader:g.fragmentShader,vertexShader:g.vertexShader,uniforms:d.userData.uniforms},r);g.fragmentShader=M.fragmentShader,g.vertexShader=M.vertexShader,Object.assign(g.uniforms,M.uniforms)},d.needsUpdate=!0;let p=null;return c&&(p=new o.MeshDepthMaterial({depthPacking:o.RGBADepthPacking}),p.onBeforeCompile=g=>{Object.assign(g.uniforms,d.userData.uniforms),Ue(g),F(g,l)},p.needsUpdate=!0),{material:d,depthMaterial:p}},[n,e,r,l,t,c]);return a.useEffect(()=>()=>{i&&i.dispose()},[i]),{material:m,depthMaterial:i}},Be=({scene:e=!1,geometry:n,isCustomTransmission:t,baseMaterial:r,materialParameters:l,depth:c,onBeforeInit:m,depthOnBeforeInit:i})=>{const d=a.useMemo(()=>{let x=n||new o.IcosahedronGeometry(2,20);return x=$e.mergeVertices(x),x.computeTangents(),x},[n]),{material:p,depthMaterial:g}=or({baseMaterial:r,materialParameters:l,isCustomTransmission:t,onBeforeInit:m,depthOnBeforeInit:i,depth:c}),M=B(e,d,p,o.Mesh),u=p.userData,v=P(u),s=A(u);return[a.useCallback((x,b,y)=>{x&&v("uTime",(b==null?void 0:b.beat)||x.clock.getElapsedTime()),b!==void 0&&(v("uWobbleStrength",b.wobbleStrength),v("uWobblePositionFrequency",b.wobblePositionFrequency),v("uWobbleTimeFrequency",b.wobbleTimeFrequency),v("uWarpStrength",b.warpStrength),v("uWarpPositionFrequency",b.warpPositionFrequency),v("uWarpTimeFrequency",b.warpTimeFrequency),v("uColor0",b.color0),v("uColor1",b.color1),v("uColor2",b.color2),v("uColor3",b.color3),v("uColorMix",b.colorMix),v("uEdgeThreshold",b.edgeThreshold),v("uEdgeColor",b.edgeColor),v("uChromaticAberration",b.chromaticAberration),v("uAnisotropicBlur",b.anisotropicBlur),v("uDistortion",b.distortion),v("uDistortionScale",b.distortionScale),v("uRefractionSamples",b.refractionSamples),v("uTemporalDistortion",b.temporalDistortion),s(y))},[v,s]),{mesh:M,depthMaterial:g}]},$=Object.freeze({wobbleStrength:.3,wobblePositionFrequency:.3,wobbleTimeFrequency:.3,warpStrength:.3,warpPositionFrequency:.3,warpTimeFrequency:.3,color0:new o.Color(16711680),color1:new o.Color(65280),color2:new o.Color(255),color3:new o.Color(16776960),colorMix:1,edgeThreshold:0,edgeColor:new o.Color(0),chromaticAberration:.1,anisotropicBlur:.1,distortion:0,distortionScale:.1,temporalDistortion:0,refractionSamples:6,beat:!1}),ar=({size:e,dpr:n,renderTargetOptions:t,isSizeUpdate:r,camera:l,geometry:c,baseMaterial:m,materialParameters:i,isCustomTransmission:d,onBeforeInit:p,depthOnBeforeInit:g,depth:M})=>{const u=O(n),v=a.useMemo(()=>new o.Scene,[]),[s,{mesh:f,depthMaterial:x}]=Be({baseMaterial:m,materialParameters:i,scene:v,geometry:c,isCustomTransmission:d,onBeforeInit:p,depthOnBeforeInit:g,depth:M}),[b,y]=k({scene:v,camera:l,size:e,dpr:u.fbo,isSizeUpdate:r,depthBuffer:!0,...t}),h=a.useCallback((_,w,V)=>(s(_,w,V),y(_.gl)),[y,s]),C=a.useCallback((_,w)=>{s(null,_,w)},[s]);return[h,C,{scene:v,mesh:f,depthMaterial:x,renderTarget:b,output:b.texture}]},ur=(e,n,t)=>{const r=a.useMemo(()=>{const l=new o.Mesh(n,t);return e.add(l),l},[n,t,e]);return a.useEffect(()=>()=>{e.remove(r),n.dispose(),t.dispose()},[e,n,t,r]),r},ir=(e,n,t,r,l,c)=>{const m=et+l||n>r+l;return c==="smaller"&&m||c==="larger"&&i||c==="both"&&(m||i)},sr=({size:e,boundFor:n,threshold:t})=>{const r=a.useRef(e);return a.useMemo(()=>{const{width:c,height:m}=e,{width:i,height:d}=r.current,p=ir(c,m,i,d,t,n);return p&&(r.current=e),p},[e,n,t])},de=Object.freeze({easeInSine(e){return 1-Math.cos(e*Math.PI/2)},easeOutSine(e){return Math.sin(e*Math.PI/2)},easeInOutSine(e){return-(Math.cos(Math.PI*e)-1)/2},easeInQuad(e){return e*e},easeOutQuad(e){return 1-(1-e)*(1-e)},easeInOutQuad(e){return e<.5?2*e*e:1-Math.pow(-2*e+2,2)/2},easeInCubic(e){return e*e*e},easeOutCubic(e){return 1-Math.pow(1-e,3)},easeInOutCubic(e){return e<.5?4*e*e*e:1-Math.pow(-2*e+2,3)/2},easeInQuart(e){return e*e*e*e},easeOutQuart(e){return 1-Math.pow(1-e,4)},easeInOutQuart(e){return e<.5?8*e*e*e*e:1-Math.pow(-2*e+2,4)/2},easeInQuint(e){return e*e*e*e*e},easeOutQuint(e){return 1-Math.pow(1-e,5)},easeInOutQuint(e){return e<.5?16*e*e*e*e*e:1-Math.pow(-2*e+2,5)/2},easeInExpo(e){return e===0?0:Math.pow(2,10*e-10)},easeOutExpo(e){return e===1?1:1-Math.pow(2,-10*e)},easeInOutExpo(e){return e===0?0:e===1?1:e<.5?Math.pow(2,20*e-10)/2:(2-Math.pow(2,-20*e+10))/2},easeInCirc(e){return 1-Math.sqrt(1-Math.pow(e,2))},easeOutCirc(e){return Math.sqrt(1-Math.pow(e-1,2))},easeInOutCirc(e){return e<.5?(1-Math.sqrt(1-Math.pow(2*e,2)))/2:(Math.sqrt(1-Math.pow(-2*e+2,2))+1)/2},easeInBack(e){return 2.70158*e*e*e-1.70158*e*e},easeOutBack(e){return 1+2.70158*Math.pow(e-1,3)+1.70158*Math.pow(e-1,2)},easeInOutBack(e){const t=2.5949095;return e<.5?Math.pow(2*e,2)*((t+1)*2*e-t)/2:(Math.pow(2*e-2,2)*((t+1)*(e*2-2)+t)+2)/2},easeInElastic(e){const n=2*Math.PI/3;return e===0?0:e===1?1:-Math.pow(2,10*e-10)*Math.sin((e*10-10.75)*n)},easeOutElastic(e){const n=2*Math.PI/3;return e===0?0:e===1?1:Math.pow(2,-10*e)*Math.sin((e*10-.75)*n)+1},easeInOutElastic(e){const n=2*Math.PI/4.5;return e===0?0:e===1?1:e<.5?-(Math.pow(2,20*e-10)*Math.sin((20*e-11.125)*n))/2:Math.pow(2,-20*e+10)*Math.sin((20*e-11.125)*n)/2+1},easeInBounce(e){return 1-de.easeOutBounce(1-e)},easeOutBounce(e){return e<1/2.75?7.5625*e*e:e<2/2.75?7.5625*(e-=1.5/2.75)*e+.75:e<2.5/2.75?7.5625*(e-=2.25/2.75)*e+.9375:7.5625*(e-=2.625/2.75)*e+.984375},easeInOutBounce(e){return e<.5?(1-de.easeOutBounce(1-2*e))/2:(1+de.easeOutBounce(2*e-1))/2}});function lr(e){let n=Math.sin(e*12.9898)*43758.5453;return n-Math.floor(n)}const cr=(e,n="easeOutQuart")=>{const t=e/60,r=de[n];return a.useCallback(c=>{let m=c.getElapsedTime()*t;const i=Math.floor(m),d=r(m-i);m=d+i;const p=lr(i);return{beat:m,floor:i,fract:d,hash:p}},[t,r])},mr=(e=60)=>{const n=a.useMemo(()=>1/Math.max(Math.min(e,60),1),[e]),t=a.useRef(null);return a.useCallback(l=>{const c=l.getElapsedTime();return t.current===null||c-t.current>=n?(t.current=c,!0):!1},[n])},vr=e=>{var r,l;const n=(r=e.dom)==null?void 0:r.length,t=(l=e.texture)==null?void 0:l.length;return!n||!t||n!==t};var fr=`varying vec2 vUv; - -void main() { - vUv = uv; - gl_Position = projectionMatrix * viewMatrix * modelMatrix * vec4(position, 1.0); -}`,pr=`precision highp float; - -varying vec2 vUv; -uniform sampler2D u_texture; -uniform vec2 u_textureResolution; -uniform vec2 u_resolution; -uniform float u_borderRadius; - -void main() { - - float screenAspect = u_resolution.x / u_resolution.y; - float textureAspect = u_textureResolution.x / u_textureResolution.y; - vec2 ratio = vec2( - min(screenAspect / textureAspect, 1.0), - min(textureAspect / screenAspect, 1.0) - ); - - vec2 adjustedUv = vUv * ratio + (1.0 - ratio) * 0.5; - vec3 textureColor = texture2D(u_texture, adjustedUv).rgb; - float textureAlpha = texture2D(u_texture, adjustedUv).a; - - - float maxSide = max(u_resolution.x, u_resolution.y); - float minSide = min(u_resolution.x, u_resolution.y); - vec2 aspect = u_resolution / maxSide; - vec2 alphaUv = vUv - 0.5; - - float borderRadius = min(u_borderRadius, minSide * 0.5); - vec2 offset = vec2(borderRadius) / u_resolution; - vec2 alphaXY = smoothstep(vec2(0.5 - offset), vec2(0.5 - offset - 0.001), abs(alphaUv)); - float alpha = min(1.0, alphaXY.x + alphaXY.y); - - vec2 alphaUv2 = abs(vUv - 0.5); - float radius = borderRadius / maxSide; - alphaUv2 = (alphaUv2 - 0.5) * aspect + radius; - float roundAlpha = smoothstep(radius + 0.001, radius, length(alphaUv2)); - - alpha = min(1.0, alpha + roundAlpha); - - - alpha *= textureAlpha; - - gl_FragColor = vec4(textureColor, alpha); -}`;const dr=({params:e,scene:n,onBeforeInit:t})=>{n.children.length>0&&(n.children.forEach(r=>{r instanceof o.Mesh&&(r.geometry.dispose(),r.material.dispose())}),n.remove(...n.children)),e.texture.forEach((r,l)=>{const c=new o.ShaderMaterial({...F({uniforms:{u_texture:{value:r},u_textureResolution:{value:new o.Vector2(0,0)},u_resolution:{value:new o.Vector2(0,0)},u_borderRadius:{value:e.boderRadius[l]?e.boderRadius[l]:0}},vertexShader:fr,fragmentShader:pr},t),...I,transparent:!0}),m=new o.Mesh(new o.PlaneGeometry(1,1),c);n.add(m)})},gr=()=>{const e=a.useRef([]),n=a.useRef([]);return a.useCallback(({isIntersectingRef:r,isIntersectingOnceRef:l,params:c})=>{e.current.length>0&&e.current.forEach((i,d)=>{i.unobserve(n.current[d])}),n.current=[],e.current=[];const m=new Array(c.dom.length).fill(!1);r.current=[...m],l.current=[...m],c.dom.forEach((i,d)=>{const p=M=>{M.forEach(u=>{c.onIntersect[d]&&c.onIntersect[d](u),r.current[d]=u.isIntersecting})},g=new IntersectionObserver(p,{rootMargin:"0px",threshold:0});g.observe(i),e.current.push(g),n.current.push(i)})},[])},hr=()=>{const e=a.useRef([]),n=a.useCallback(({params:t,customParams:r,size:l,resolutionRef:c,scene:m,isIntersectingRef:i})=>{m.children.length!==e.current.length&&(e.current=new Array(m.children.length)),m.children.forEach((d,p)=>{var u,v,s,f,x,b;const g=t.dom[p];if(!g)return;const M=g.getBoundingClientRect();if(e.current[p]=M,d.scale.set(M.width,M.height,1),d.position.set(M.left+M.width*.5-l.width*.5,-M.top-M.height*.5+l.height*.5,0),i.current[p]&&(t.rotation[p]&&d.rotation.copy(t.rotation[p]),d instanceof o.Mesh)){const y=d.material,h=P(y),C=A(y);h("u_texture",t.texture[p]),h("u_textureResolution",[((s=(v=(u=t.texture[p])==null?void 0:u.source)==null?void 0:v.data)==null?void 0:s.width)||0,((b=(x=(f=t.texture[p])==null?void 0:f.source)==null?void 0:x.data)==null?void 0:b.height)||0]),h("u_resolution",c.current.set(M.width,M.height)),h("u_borderRadius",t.boderRadius[p]?t.boderRadius[p]:0),C(r)}})},[]);return[e.current,n]},xr=()=>{const e=a.useRef([]),n=a.useRef([]),t=a.useCallback((r,l=!1)=>{e.current.forEach((m,i)=>{m&&(n.current[i]=!0)});const c=l?[...n.current]:[...e.current];return r<0?c:c[r]},[]);return{isIntersectingRef:e,isIntersectingOnceRef:n,isIntersecting:t}},Mr=e=>({onView:t,onHidden:r})=>{const l=a.useRef(!1);a.useEffect(()=>{let c;const m=()=>{e.current.some(i=>i)?l.current||(t&&t(),l.current=!0):l.current&&(r&&r(),l.current=!1),c=requestAnimationFrame(m)};return c=requestAnimationFrame(m),()=>{cancelAnimationFrame(c)}},[t,r])},Ee={texture:[],dom:[],boderRadius:[],rotation:[],onIntersect:[]},yr=({size:e,dpr:n,isSizeUpdate:t,renderTargetOptions:r,onBeforeInit:l},c=[])=>{const m=O(n),i=a.useMemo(()=>new o.Scene,[]),d=E(e),[p,g]=k({scene:i,camera:d,size:e,dpr:m.fbo,isSizeUpdate:t,...r}),[M,u]=L({...Ee,updateKey:performance.now()}),[v,s]=hr(),f=a.useRef(new o.Vector2(0,0)),[x,b]=a.useState(!0);a.useMemo(()=>b(!0),c);const y=a.useRef(null),h=a.useMemo(()=>T,[]),C=gr(),{isIntersectingOnceRef:_,isIntersectingRef:w,isIntersecting:V}=xr(),z=Mr(w),R=a.useMemo(()=>(D,q)=>{u(D),s({params:M,customParams:q,size:e,resolutionRef:f,scene:i,isIntersectingRef:w})},[w,u,s,e,i,M]);return[a.useCallback((D,q,H)=>{const{gl:re,size:oe}=D;if(R(q,H),vr(M))return h;if(x){if(y.current===M.updateKey)return h;y.current=M.updateKey}return x&&(dr({params:M,size:oe,scene:i,onBeforeInit:l}),C({isIntersectingRef:w,isIntersectingOnceRef:_,params:M}),b(!1)),g(re)},[g,C,l,R,x,i,M,_,w,h]),R,{scene:i,camera:d,renderTarget:p,output:p.texture,isIntersecting:V,DOMRects:v,intersections:w.current,useDomView:z}]},br=(e,n)=>{const{scene:t,camera:r,size:l,dpr:c=!1,isSizeUpdate:m=!1,depth:i=!1,...d}=e,p=a.useRef([]),g=N(l,c);p.current=a.useMemo(()=>Array.from({length:n},()=>{const u=new o.WebGLRenderTarget(g.x,g.y,{...ve,...d});return i&&(u.depthTexture=new o.DepthTexture(g.x,g.y,o.FloatType)),u}),[n]),m&&p.current.forEach(u=>u.setSize(g.x,g.y)),a.useEffect(()=>{const u=p.current;return()=>{u.forEach(v=>v.dispose())}},[n]);const M=a.useCallback((u,v,s)=>{const f=p.current[v];return he({gl:u,scene:t,camera:r,fbo:f,onBeforeRender:()=>s&&s({read:f.texture})}),f.texture},[t,r]);return[p.current,M]},Sr=Object.freeze({interpolate(e,n,t,r=1e-6){const l=e+(n-e)*t;return Math.abs(l)","precision highp float;\n\nuniform sampler2D uBuffer;\nuniform sampler2D uTexture;\nuniform bool uIsTexture;\nuniform sampler2D uMap;\nuniform bool uIsMap;\nuniform float uMapIntensity;\nuniform float uRadius;\nuniform float uDissipation;\nuniform vec2 uResolution;\nuniform float uSmudge;\nuniform vec2 uMouse;\nuniform vec2 uPrevMouse;\nuniform vec2 uVelocity;\nuniform vec3 uColor;\nuniform float uMotionBlur;\nuniform int uMotionSample;\nuniform bool uIsCursor;\nuniform float uPressureStart;\nuniform float uPressureEnd;\n\nvarying vec2 vUv;\n\nfloat isOnLine(vec2 point, vec2 start, vec2 end, float radius, float pressureStart, float pressureEnd) {\n\t\n\tfloat aspect = uResolution.x / uResolution.y;\n\n\tpoint.x *= aspect;\n\tstart.x *= aspect;\n\tend.x *= aspect;\n\n\tvec2 dir = normalize(end - start);\n\tvec2 n = vec2(dir.y, -dir.x);\n\tvec2 p0 = point - start;\n\t\n\tfloat distToLine = abs(dot(p0, n));\n\tfloat distAlongLine = dot(p0, dir);\n\tfloat totalLength = length(end - start);\n\n\tfloat progress = clamp(distAlongLine / totalLength, 0.0, 1.0);\n\tfloat pressure = mix(pressureStart, pressureEnd, progress);\n\tradius = min(radius,radius * pressure);\n\n\tfloat distFromStart = length(point - start);\n\tfloat distFromEnd = length(point - end);\n\t\n\tbool withinLine = (distToLine < radius && distAlongLine > 0.0 && distAlongLine < totalLength) || distFromStart < radius || distFromEnd < radius;\n\n\treturn float(withinLine);\n}\n\nvec4 createSmudge(vec2 uv){\n\tvec2 offsets[9];\n\toffsets[0] = vec2(-1, -1); offsets[1] = vec2( 0, -1); offsets[2] = vec2( 1, -1);\n\toffsets[3] = vec2(-1, 0); offsets[4] = vec2( 0, 0); offsets[5] = vec2( 1, 0);\n\toffsets[6] = vec2(-1, 1); offsets[7] = vec2( 0, 1); offsets[8] = vec2( 1, 1);\n\n\tfor(int i = 0; i < 9; i++) {\n\t\toffsets[i] = (offsets[i] * uSmudge) / uResolution;\n\t}\t\n\tvec4 smudgedColor = vec4(0.);\n\tfor(int i = 0; i < 9; i++) {\n\t\tsmudgedColor += texture2D(uBuffer, uv + offsets[i]);\n\t}\n\treturn smudgedColor / 9.0;\n}\n\nvec4 createMotionBlur(vec2 uv , vec4 baseColor, vec2 velocity) {\n\tvec2 scaledV = velocity * uMotionBlur;\n\tfor(int i = 1; i < uMotionSample; i++) {\n\t\tfloat t = float(i) / float(uMotionSample - 1);\n\t\tvec2 offset = t * scaledV / uResolution;\n\t\tbaseColor += texture2D(uBuffer, uv + offset);\n\t}\n\treturn baseColor / float(uMotionSample);\n}\n\nvoid main() {\n\n\tvec2 uv = vUv;\n\tif(uIsMap){\n\t\tvec2 mapColor = texture2D(uMap, uv).rg;\n\t\tvec2 normalizedMap = mapColor * 2.0 - 1.0;\n\t\tuv = uv * 2.0 - 1.0;\n\t\tuv *= mix(vec2(1.0), abs(normalizedMap.rg), uMapIntensity);\n\t\tuv = (uv + 1.0) / 2.0;\n\t}\n\tvec2 suv = uv*2.-1.;\n\n\tvec2 velocity = uVelocity * uResolution;\n\n\tfloat radius = max(0.0,uRadius);\n\t\n\tvec4 smudgedColor = uSmudge > 0. ? createSmudge(uv) : texture2D(uBuffer, uv);\n\n\tvec4 motionBlurredColor = uMotionBlur > 0. ? createMotionBlur(uv,smudgedColor, velocity) : smudgedColor;\n\n\tvec4 bufferColor = motionBlurredColor;\n\tbufferColor.a = bufferColor.a < 1e-10 ? 0.0 : bufferColor.a * uDissipation;\n\t\n\tvec4 brushColor = uIsTexture ? texture2D(uTexture, uv) : vec4(uColor,1.);\n\t\n\tfloat onLine = isOnLine(suv, uPrevMouse, uMouse, radius, uPressureStart,uPressureEnd);\n\tfloat isOnLine = length(velocity) > 0. ? onLine : uIsCursor ? onLine : 0.;\n\n\tvec4 finalColor = mix(bufferColor, brushColor, isOnLine);\n\n\tgl_FragColor = finalColor;\n}","import * as THREE from \"three\";\nimport { useMemo } from \"react\";\nimport { Size } from \"../fxs/types\";\n\n/**\n * @params dpr if dpr is set, it returns the resolution which is size multiplied by dpr.\n */\nexport const useResolution = (size: Size, dpr: number | false = false) => {\n const _width = dpr ? size.width * dpr : size.width;\n const _height = dpr ? size.height * dpr : size.height;\n\n const resolution = useMemo(\n () => new THREE.Vector2(_width, _height),\n [_width, _height]\n );\n return resolution;\n};\n","import * as THREE from \"three\";\ntype UniformValue =\n | THREE.CubeTexture\n | THREE.Texture\n | Int32Array\n | Float32Array\n | THREE.Matrix4\n | THREE.Matrix3\n | THREE.Quaternion\n | THREE.Vector4\n | THREE.Vector3\n | THREE.Vector2\n | THREE.Color\n | number\n | boolean\n | Array\n | null\n | undefined;\ntype UniformObject = { [key: string]: { value: UniformValue } };\n\nexport const setUniform =\n (material: { uniforms: T }) =>\n (key: keyof T, value: UniformValue) => {\n if (value === undefined) {\n return;\n }\n const uniforms = material.uniforms;\n if (uniforms && uniforms[key]) {\n uniforms[key].value = value;\n }\n };\n\nexport type CustomParams = { [uniform: string]: UniformValue };\nexport const setCustomUniform =\n (material: { uniforms: UniformObject }) =>\n (customParams: CustomParams | undefined) => {\n if (customParams === undefined) {\n return;\n }\n Object.keys(customParams).forEach((key) => {\n const uniforms = material.uniforms;\n if (uniforms && uniforms[key]) {\n uniforms[key].value = customParams[key];\n }\n });\n };\n","import * as THREE from \"three\";\nimport { useEffect, useMemo } from \"react\";\n\ntype Object3DConstructor = new (\n geometry: THREE.BufferGeometry,\n material: M\n) => T;\n\n/**\n * Add geometry and material to Object3D and add them to scene.\n */\nexport const useAddObject = <\n T extends THREE.Object3D,\n M extends THREE.Material\n>(\n scene: THREE.Scene | false,\n geometry: THREE.BufferGeometry,\n material: M,\n Proto: Object3DConstructor\n) => {\n const object3D = useMemo(() => {\n const obj = new Proto(geometry, material);\n scene && scene.add(obj);\n return obj;\n }, [geometry, material, Proto, scene]);\n\n useEffect(() => {\n return () => {\n scene && scene.remove(object3D);\n geometry.dispose();\n material.dispose();\n };\n }, [scene, geometry, material, object3D]);\n\n return object3D;\n};\n","import * as THREE from \"three\";\n\nexport const ISDEV = process.env.NODE_ENV === \"development\";\n\nexport const MATERIAL_BASIC_PARAMS = {\n transparent: false,\n depthTest: false,\n depthWrite: false,\n};\n\nexport const DEFAULT_TEXTURE = new THREE.DataTexture(\n new Uint8Array([0, 0, 0, 0]),\n 1,\n 1,\n THREE.RGBAFormat\n);\n","//\tSimplex 4D Noise \n//\tby Ian McEwan, Ashima Arts\n//\nvec4 permute(vec4 x){return mod(((x*34.0)+1.0)*x, 289.0);}\nfloat permute(float x){return floor(mod(((x*34.0)+1.0)*x, 289.0));}\nvec4 taylorInvSqrt(vec4 r){return 1.79284291400159 - 0.85373472095314 * r;}\nfloat taylorInvSqrt(float r){return 1.79284291400159 - 0.85373472095314 * r;}\n\nvec4 grad4(float j, vec4 ip)\n{\n\tconst vec4 ones = vec4(1.0, 1.0, 1.0, -1.0);\n\tvec4 p,s;\n\n\tp.xyz = floor( fract (vec3(j) * ip.xyz) * 7.0) * ip.z - 1.0;\n\tp.w = 1.5 - dot(abs(p.xyz), ones.xyz);\n\ts = vec4(lessThan(p, vec4(0.0)));\n\tp.xyz = p.xyz + (s.xyz*2.0 - 1.0) * s.www; \n\n\treturn p;\n}\n\nfloat simplexNoise4d(vec4 v)\n{\n\tconst vec2 C = vec2( 0.138196601125010504, // (5 - sqrt(5))/20 G4\n\t\t\t\t\t\t\t\t\t0.309016994374947451); // (sqrt(5) - 1)/4 F4\n\t// First corner\n\tvec4 i = floor(v + dot(v, C.yyyy) );\n\tvec4 x0 = v - i + dot(i, C.xxxx);\n\n\t// Other corners\n\n\t// Rank sorting originally contributed by Bill Licea-Kane, AMD (formerly ATI)\n\tvec4 i0;\n\n\tvec3 isX = step( x0.yzw, x0.xxx );\n\tvec3 isYZ = step( x0.zww, x0.yyz );\n\t// i0.x = dot( isX, vec3( 1.0 ) );\n\ti0.x = isX.x + isX.y + isX.z;\n\ti0.yzw = 1.0 - isX;\n\n\t// i0.y += dot( isYZ.xy, vec2( 1.0 ) );\n\ti0.y += isYZ.x + isYZ.y;\n\ti0.zw += 1.0 - isYZ.xy;\n\n\ti0.z += isYZ.z;\n\ti0.w += 1.0 - isYZ.z;\n\n\t// i0 now contains the unique values 0,1,2,3 in each channel\n\tvec4 i3 = clamp( i0, 0.0, 1.0 );\n\tvec4 i2 = clamp( i0-1.0, 0.0, 1.0 );\n\tvec4 i1 = clamp( i0-2.0, 0.0, 1.0 );\n\n\t// x0 = x0 - 0.0 + 0.0 * C \n\tvec4 x1 = x0 - i1 + 1.0 * C.xxxx;\n\tvec4 x2 = x0 - i2 + 2.0 * C.xxxx;\n\tvec4 x3 = x0 - i3 + 3.0 * C.xxxx;\n\tvec4 x4 = x0 - 1.0 + 4.0 * C.xxxx;\n\n\t// Permutations\n\ti = mod(i, 289.0); \n\tfloat j0 = permute( permute( permute( permute(i.w) + i.z) + i.y) + i.x);\n\tvec4 j1 = permute( permute( permute( permute (\n\t\t\t\t\ti.w + vec4(i1.w, i2.w, i3.w, 1.0 ))\n\t\t\t\t+ i.z + vec4(i1.z, i2.z, i3.z, 1.0 ))\n\t\t\t\t+ i.y + vec4(i1.y, i2.y, i3.y, 1.0 ))\n\t\t\t\t+ i.x + vec4(i1.x, i2.x, i3.x, 1.0 ));\n\t// Gradients\n\t// ( 7*7*6 points uniformly over a cube, mapped onto a 4-octahedron.)\n\t// 7*7*6 = 294, which is close to the ring size 17*17 = 289.\n\n\tvec4 ip = vec4(1.0/294.0, 1.0/49.0, 1.0/7.0, 0.0) ;\n\n\tvec4 p0 = grad4(j0, ip);\n\tvec4 p1 = grad4(j1.x, ip);\n\tvec4 p2 = grad4(j1.y, ip);\n\tvec4 p3 = grad4(j1.z, ip);\n\tvec4 p4 = grad4(j1.w, ip);\n\n\t// Normalise gradients\n\tvec4 norm = taylorInvSqrt(vec4(dot(p0,p0), dot(p1,p1), dot(p2, p2), dot(p3,p3)));\n\tp0 *= norm.x;\n\tp1 *= norm.y;\n\tp2 *= norm.z;\n\tp3 *= norm.w;\n\tp4 *= taylorInvSqrt(dot(p4,p4));\n\n\t// Mix contributions from the five corners\n\tvec3 m0 = max(0.6 - vec3(dot(x0,x0), dot(x1,x1), dot(x2,x2)), 0.0);\n\tvec2 m1 = max(0.6 - vec2(dot(x3,x3), dot(x4,x4) ), 0.0);\n\tm0 = m0 * m0;\n\tm1 = m1 * m1;\n\treturn 49.0 * ( dot(m0*m0, vec3( dot( p0, x0 ), dot( p1, x1 ), dot( p2, x2 )))\n\t\t\t\t\t\t+ dot(m1*m1, vec2( dot( p3, x3 ), dot( p4, x4 ) ) ) ) ;\n\n}\n\nfloat getWobble(vec3 position)\n{\n\tvec3 warpedPosition = position;\n\twarpedPosition += simplexNoise4d(\n\t\tvec4(\n\t\t\t\tposition * uWarpPositionFrequency,\n\t\t\t\tuTime * uWarpTimeFrequency\n\t\t)\n\t) * uWarpStrength;\n\n\treturn simplexNoise4d(vec4(\n\t\twarpedPosition * uWobblePositionFrequency, // XYZ\n\t\tuTime * uWobbleTimeFrequency // W\n\t)) * uWobbleStrength;\n}","// \n//\tby Nikita Miropolskiy\n\n/* discontinuous pseudorandom uniformly distributed in [-0.5, +0.5]^3 */\nvec3 random3(vec3 c) {\n\tfloat j = 4096.0*sin(dot(c,vec3(17.0, 59.4, 15.0)));\n\tvec3 r;\n\tr.z = fract(512.0*j);\n\tj *= .125;\n\tr.x = fract(512.0*j);\n\tj *= .125;\n\tr.y = fract(512.0*j);\n\treturn r-0.5;\n}\n\nconst float F3 = 0.3333333;\nconst float G3 = 0.1666667;\n\nfloat snoise(vec3 p) {\n\n\tvec3 s = floor(p + dot(p, vec3(F3)));\n\tvec3 x = p - s + dot(s, vec3(G3));\n\t\n\tvec3 e = step(vec3(0.0), x - x.yzx);\n\tvec3 i1 = e*(1.0 - e.zxy);\n\tvec3 i2 = 1.0 - e.zxy*(1.0 - e);\n \t\n\tvec3 x1 = x - i1 + G3;\n\tvec3 x2 = x - i2 + 2.0*G3;\n\tvec3 x3 = x - 1.0 + 3.0*G3;\n\t \n\tvec4 w, d;\n\t \n\tw.x = dot(x, x);\n\tw.y = dot(x1, x1);\n\tw.z = dot(x2, x2);\n\tw.w = dot(x3, x3);\n\t \n\tw = max(0.6 - w, 0.0);\n\t \n\td.x = dot(random3(s), x);\n\td.y = dot(random3(s + i1), x1);\n\td.z = dot(random3(s + i2), x2);\n\td.w = dot(random3(s + 1.0), x3);\n\t \n\tw *= w;\n\tw *= w;\n\td *= w;\n\t \n\treturn dot(d, vec4(52.0));\n}\n\nfloat snoiseFractal(vec3 m) {\n\treturn 0.5333333* snoise(m)\n\t\t\t\t+0.2666667* snoise(2.0*m)\n\t\t\t\t+0.1333333* snoise(4.0*m)\n\t\t\t\t+0.0666667* snoise(8.0*m);\n}","float screenAspect = uResolution.x / uResolution.y;\nfloat textureAspect = uTextureResolution.x / uTextureResolution.y;\nvec2 aspectRatio = vec2(\n\tmin(screenAspect / textureAspect, 1.0),\n\tmin(textureAspect / screenAspect, 1.0)\n);\nvec2 uv = vUv * aspectRatio + (1.0 - aspectRatio) * .5;","vec3 mapColor = texture2D(uMap, uv).rgb;\nvec3 normalizedMap = mapColor * 2.0 - 1.0;\n\nuv = uv * 2.0 - 1.0;\nuv *= mix(vec2(1.0), abs(normalizedMap.rg), uMapIntensity);\nuv = (uv + 1.0) / 2.0;","precision highp float;\n\nvarying vec2 vUv;\n\nvoid main() {\n\tvUv = uv;\n\tgl_Position = vec4(position, 1.0);\n}","varying vec2 vUv;\n\nvoid main() {\n\tvUv = uv;\n\tgl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);\n}","vec3 hsv2rgb(vec3 c)\n{\n vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);\n vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);\n return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);\n}","vec3 rgb2hsv(vec3 c)\n{\n vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);\n vec4 p = mix(vec4(c.bg, K.wz), vec4(c.gb, K.xy), step(c.b, c.g));\n vec4 q = mix(vec4(p.xyw, c.r), vec4(c.r, p.yzx), step(p.x, c.r));\n\n float d = q.x - min(q.w, q.y);\n float e = 1.0e-10;\n return vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x);\n}","import wobble3D from \"./shaderChunk/wobble3D.glsl\";\nimport snoise from \"./shaderChunk/snoise.glsl\";\nimport coverTexture from \"./shaderChunk/coverTexture.glsl\";\nimport fxBlending from \"./shaderChunk/fxBlending.glsl\";\nimport planeVertex from \"./shaderChunk/planeVertex.glsl\";\nimport defaultVertex from \"./shaderChunk/defaultVertex.glsl\";\nimport hsv2rgb from \"./shaderChunk/hsv2rgb.glsl\";\nimport rgb2hsv from \"./shaderChunk/rgb2hsv.glsl\";\n\nexport type ShaderChunkTypes =\n | \"wobble3D\"\n | \"snoise\"\n | \"coverTexture\"\n | \"fxBlending\"\n | \"planeVertex\"\n | \"defaultVertex\"\n | \"hsv2rgb\"\n | \"rgb2hsv\";\n\nexport const ShaderChunk: { [K in ShaderChunkTypes]: string } = Object.freeze({\n wobble3D,\n snoise,\n coverTexture,\n fxBlending,\n planeVertex,\n defaultVertex,\n hsv2rgb,\n rgb2hsv,\n});\n","import { ShaderChunk, ShaderChunkTypes } from \"./ShaderChunk\";\n\nconst includePattern = /^[ \\t]*#usf +<([\\w\\d./]+)>/gm;\n\nfunction includeReplacer(match: string, include: ShaderChunkTypes): string {\n return resolveIncludes(ShaderChunk[include] || \"\");\n}\n\nfunction resolveIncludes(string: string): string {\n return string.replace(includePattern, includeReplacer);\n}\n\nexport { resolveIncludes };\n","import { resolveIncludes } from \"../libs/shaders/resolveShaders\";\nimport { OnBeforeInitParameters } from \"../fxs/types\";\n\nexport const createMaterialParameters = (\n parameters: OnBeforeInitParameters,\n onBeforeInit?: (parameters: OnBeforeInitParameters) => void\n) => {\n onBeforeInit && onBeforeInit(parameters);\n parameters.vertexShader = resolveIncludes(parameters.vertexShader);\n parameters.fragmentShader = resolveIncludes(parameters.fragmentShader);\n return parameters;\n};\n","import * as THREE from \"three\";\nimport vertexShader from \"./shader/main.vert\";\nimport fragmentShader from \"./shader/main.frag\";\nimport { useMemo } from \"react\";\nimport { useResolution } from \"../../../utils/useResolution\";\nimport { setUniform } from \"../../../utils/setUniforms\";\nimport { useAddObject } from \"../../../utils/useAddObject\";\nimport { MaterialProps, Size } from \"../../types\";\nimport {\n DEFAULT_TEXTURE,\n MATERIAL_BASIC_PARAMS,\n} from \"../../../libs/constants\";\nimport { BRUSH_PARAMS } from \".\";\nimport { createMaterialParameters } from \"../../../utils/createMaterialParameters\";\n\nexport class BrushMaterial extends THREE.ShaderMaterial {\n uniforms!: {\n uBuffer: { value: THREE.Texture };\n uTexture: { value: THREE.Texture };\n uIsTexture: { value: boolean };\n uMap: { value: THREE.Texture };\n uIsMap: { value: boolean };\n uMapIntensity: { value: number };\n uResolution: { value: THREE.Vector2 };\n uRadius: { value: number };\n uSmudge: { value: number };\n uDissipation: { value: number };\n uMotionBlur: { value: number };\n uMotionSample: { value: number };\n uMouse: { value: number };\n uPrevMouse: { value: number };\n uVelocity: { value: number };\n uColor: { value: THREE.Vector3 | THREE.Color };\n uIsCursor: { value: boolean };\n uPressureStart: { value: number };\n uPressureEnd: { value: number };\n };\n}\n\nexport const useMesh = ({\n scene,\n size,\n dpr,\n onBeforeInit,\n}: {\n scene: THREE.Scene;\n size: Size;\n dpr: number | false;\n} & MaterialProps) => {\n const geometry = useMemo(() => new THREE.PlaneGeometry(2, 2), []);\n const material = useMemo(() => {\n const mat = new THREE.ShaderMaterial({\n ...createMaterialParameters(\n {\n uniforms: {\n uBuffer: { value: DEFAULT_TEXTURE },\n uResolution: { value: new THREE.Vector2(0, 0) },\n uTexture: { value: DEFAULT_TEXTURE },\n uIsTexture: { value: false },\n uMap: { value: DEFAULT_TEXTURE },\n uIsMap: { value: false },\n uMapIntensity: { value: BRUSH_PARAMS.mapIntensity },\n uRadius: { value: BRUSH_PARAMS.radius },\n uSmudge: { value: BRUSH_PARAMS.smudge },\n uDissipation: { value: BRUSH_PARAMS.dissipation },\n uMotionBlur: { value: BRUSH_PARAMS.motionBlur },\n uMotionSample: { value: BRUSH_PARAMS.motionSample },\n uMouse: { value: new THREE.Vector2(-10, -10) },\n uPrevMouse: { value: new THREE.Vector2(-10, -10) },\n uVelocity: { value: new THREE.Vector2(0, 0) },\n uColor: { value: BRUSH_PARAMS.color },\n uIsCursor: { value: false },\n uPressureStart: { value: 1.0 },\n uPressureEnd: { value: 1.0 },\n },\n vertexShader: vertexShader,\n fragmentShader: fragmentShader,\n },\n onBeforeInit\n ),\n ...MATERIAL_BASIC_PARAMS,\n // Must be transparent\n transparent: true,\n });\n\n return mat;\n }, [onBeforeInit]) as BrushMaterial;\n\n const resolution = useResolution(size, dpr);\n setUniform(material)(\"uResolution\", resolution.clone());\n\n const mesh = useAddObject(scene, geometry, material, THREE.Mesh);\n\n return { material, mesh };\n};\n","import * as THREE from \"three\";\nimport { useResolution } from \"./useResolution\";\nimport { useMemo } from \"react\";\nimport { Size } from \"../fxs/types\";\n\nconst getCameraProps = (width: number, height: number) => {\n const frustumSize = height;\n const aspect = width / height;\n const [w, h] = [(frustumSize * aspect) / 2, frustumSize / 2];\n return { width: w, height: h, near: -1000, far: 1000 };\n};\n\nexport const useCamera = (\n size: Size,\n cameraType: \"OrthographicCamera\" | \"PerspectiveCamera\" = \"OrthographicCamera\"\n) => {\n const resolution = useResolution(size);\n const { width, height, near, far } = getCameraProps(\n resolution.x,\n resolution.y\n );\n const camera = useMemo(() => {\n return cameraType === \"OrthographicCamera\"\n ? new THREE.OrthographicCamera(\n -width,\n width,\n height,\n -height,\n near,\n far\n )\n : new THREE.PerspectiveCamera(50, width / height);\n }, [width, height, near, far, cameraType]);\n return camera;\n};\n","import * as THREE from \"three\";\nimport { useCallback, useRef } from \"react\";\n\nexport type PointerValues = {\n currentPointer: THREE.Vector2;\n prevPointer: THREE.Vector2;\n diffPointer: THREE.Vector2;\n velocity: THREE.Vector2;\n isVelocityUpdate: boolean;\n};\n\ntype UpdatePointer = (currentPointer: THREE.Vector2) => PointerValues;\n\n/**\n * @description When given the pointer vector2 from r3f's RootState, it generates an update function that returns {`currentPointer`, `prevPointer`, `diffPointer`, `isVelocityUpdate`, `velocity`}.\n * @description When calling custom in a `useFrame` loop, you can avoid duplication of execution by passing `pointerValues` to the update function of a Pointer-activated fxHook, such as `useBrush`.\n * @param lerp 0~1, lerp intensity (0 to less than 1) , default : `0`\n */\nexport const usePointer = (lerp: number = 0): UpdatePointer => {\n const prevPointer = useRef(new THREE.Vector2(0, 0));\n const diffPointer = useRef(new THREE.Vector2(0, 0));\n const lerpPointer = useRef(new THREE.Vector2(0, 0));\n const lastUpdateTime = useRef(0);\n const velocity = useRef(new THREE.Vector2(0, 0));\n const isMoved = useRef(false);\n\n const updatePointer = useCallback(\n (currentPointer: THREE.Vector2) => {\n const now = performance.now();\n\n // lerp\n let current: THREE.Vector2;\n if (isMoved.current && lerp) {\n lerpPointer.current = lerpPointer.current.lerp(\n currentPointer,\n 1 - lerp\n );\n current = lerpPointer.current.clone();\n } else {\n current = currentPointer.clone();\n lerpPointer.current = current;\n }\n\n // first frame\n if (lastUpdateTime.current === 0) {\n lastUpdateTime.current = now;\n prevPointer.current = current;\n }\n const deltaTime = Math.max(1, now - lastUpdateTime.current);\n lastUpdateTime.current = now;\n\n // get velocity\n velocity.current\n .copy(current)\n .sub(prevPointer.current)\n .divideScalar(deltaTime);\n const isUpdate = velocity.current.length() > 0;\n\n //set prev temp pos\n const prevTemp = isMoved.current\n ? prevPointer.current.clone()\n : current;\n if (!isMoved.current && isUpdate) {\n isMoved.current = true;\n }\n prevPointer.current = current;\n\n return {\n currentPointer: current,\n prevPointer: prevTemp,\n diffPointer: diffPointer.current.subVectors(current, prevTemp),\n velocity: velocity.current,\n isVelocityUpdate: isUpdate,\n };\n },\n [lerp]\n );\n\n return updatePointer;\n};\n","import { useCallback, useRef } from \"react\";\n\ntype SetParams = (newParams?: Partial) => void;\ntype UseParamsReturn = [T, SetParams];\n\n/**\n * @param params Receives an initial value object. With structuredClone, deep copy and set, but if the object contains a function, just set it.\n */\nexport const useParams = (params: T): UseParamsReturn => {\n const isContainsFunctions = (obj: object): boolean =>\n Object.values(obj).some((value) => typeof value === \"function\");\n const paramsRef = useRef(\n isContainsFunctions(params) ? params : structuredClone(params)\n );\n\n const setParams = useCallback>((newParams) => {\n if (newParams === undefined) {\n return;\n }\n for (const key in newParams) {\n const paramKey = key as keyof T;\n if (\n paramKey in paramsRef.current &&\n newParams[paramKey] !== undefined &&\n newParams[paramKey] !== null\n ) {\n paramsRef.current[paramKey] = newParams[paramKey]!;\n } else {\n console.error(\n `\"${String(\n paramKey\n )}\" does not exist in the params. or \"${String(\n paramKey\n )}\" is null | undefined`\n );\n }\n }\n }, []);\n return [paramsRef.current, setParams];\n};\n","import * as THREE from \"three\";\nimport { useCallback, useEffect, useMemo, useRef } from \"react\";\nimport { useResolution } from \"./useResolution\";\nimport { Size } from \"../fxs/types\";\n\nexport const FBO_DEFAULT_OPTION: THREE.RenderTargetOptions = {\n depthBuffer: false,\n};\n\nexport type UseFboProps = {\n scene: THREE.Scene;\n camera: THREE.Camera;\n size: Size;\n /** If dpr is set, dpr will be multiplied, default : `false` */\n dpr?: number | false;\n /** Whether to resize when resizing occurs. If isDpr is true, set FBO to setSize even if dpr is changed, default : `false` */\n isSizeUpdate?: boolean;\n /** If set, the scene depth will be rendered into buffer.depthTexture. default : `false` */\n depth?: boolean;\n} & THREE.RenderTargetOptions;\n\nexport const renderFBO = ({\n gl,\n fbo,\n scene,\n camera,\n onBeforeRender,\n onSwap,\n}: {\n gl: THREE.WebGLRenderer;\n fbo: THREE.WebGLRenderTarget;\n scene: THREE.Scene;\n camera: THREE.Camera;\n onBeforeRender: () => void;\n onSwap?: () => void;\n}) => {\n gl.setRenderTarget(fbo);\n onBeforeRender();\n gl.clear();\n gl.render(scene, camera);\n onSwap && onSwap();\n gl.setRenderTarget(null);\n gl.clear();\n};\n\ntype UpdateRenderTarget = (\n gl: THREE.WebGLRenderer,\n /** call before FBO is rendered */\n onBeforeRender?: ({ read }: { read: THREE.Texture }) => void\n) => THREE.Texture;\n\ntype UseSingleFBOReturn = [THREE.WebGLRenderTarget, UpdateRenderTarget];\n\n/**\n * @param dpr If dpr is set, dpr will be multiplied, default:false\n * @param isSizeUpdate Whether to resize when resizing occurs. If isDpr is true, set FBO to setSize even if dpr is changed, default:false\n * @param depthBuffer Unlike the default in three.js, the default is `false`.\n * @returns [THREE.WebGLRenderTarget , updateFBO] -Receives the RenderTarget as the first argument and the update function as the second argument.\n */\nexport const useSingleFBO = (props: UseFboProps): UseSingleFBOReturn => {\n const {\n scene,\n camera,\n size,\n dpr = false,\n isSizeUpdate = false,\n depth = false,\n ...renderTargetOptions\n } = props;\n\n const renderTarget = useRef();\n\n const resolution = useResolution(size, dpr);\n\n renderTarget.current = useMemo(\n () => {\n const target = new THREE.WebGLRenderTarget(\n resolution.x,\n resolution.y,\n {\n ...FBO_DEFAULT_OPTION,\n ...renderTargetOptions,\n }\n );\n if (depth) {\n target.depthTexture = new THREE.DepthTexture(\n resolution.x,\n resolution.y,\n THREE.FloatType\n );\n }\n return target;\n },\n // eslint-disable-next-line react-hooks/exhaustive-deps\n []\n );\n\n if (isSizeUpdate) {\n renderTarget.current?.setSize(resolution.x, resolution.y);\n }\n\n useEffect(() => {\n const temp = renderTarget.current;\n return () => {\n temp?.dispose();\n };\n }, []);\n\n const updateRenderTarget: UpdateRenderTarget = useCallback(\n (gl, onBeforeRender) => {\n const fbo = renderTarget.current!;\n renderFBO({\n gl,\n fbo,\n scene,\n camera,\n onBeforeRender: () =>\n onBeforeRender && onBeforeRender({ read: fbo.texture }),\n });\n return fbo.texture;\n },\n [scene, camera]\n );\n\n return [renderTarget.current, updateRenderTarget];\n};\n","import * as THREE from \"three\";\nimport { useCallback, useEffect, useMemo } from \"react\";\nimport { FBO_DEFAULT_OPTION, UseFboProps, renderFBO } from \"./useSingleFBO\";\nimport { useResolution } from \"./useResolution\";\n\nexport type DoubleRenderTarget = {\n read: THREE.WebGLRenderTarget;\n write: THREE.WebGLRenderTarget;\n};\n\ninterface WebGLDoubleRenderTarget extends DoubleRenderTarget {\n swap: () => void;\n}\n\ntype FBOUpdateFunction = (\n gl: THREE.WebGLRenderer,\n /** call before FBO is rendered */\n onBeforeRender?: ({\n read,\n write,\n }: {\n read: THREE.Texture;\n write: THREE.Texture;\n }) => void\n) => THREE.Texture;\n\ntype UseDoubleFBOReturn = [\n { read: THREE.WebGLRenderTarget; write: THREE.WebGLRenderTarget },\n FBOUpdateFunction\n];\n\n/**\n * @description Custom hook for setting up double buffering with WebGL render targets.\n * @param UseFboProps same as `useSingleFBO`\n */\nexport const useDoubleFBO = (props: UseFboProps): UseDoubleFBOReturn => {\n const {\n scene,\n camera,\n size,\n dpr = false,\n isSizeUpdate = false,\n depth = false,\n ...renderTargetOptions\n } = props;\n\n const resolution = useResolution(size, dpr);\n\n const renderTarget = useMemo(() => {\n const read = new THREE.WebGLRenderTarget(resolution.x, resolution.y, {\n ...FBO_DEFAULT_OPTION,\n ...renderTargetOptions,\n });\n const write = new THREE.WebGLRenderTarget(resolution.x, resolution.y, {\n ...FBO_DEFAULT_OPTION,\n ...renderTargetOptions,\n });\n\n if (depth) {\n read.depthTexture = new THREE.DepthTexture(\n resolution.x,\n resolution.y,\n THREE.FloatType\n );\n write.depthTexture = new THREE.DepthTexture(\n resolution.x,\n resolution.y,\n THREE.FloatType\n );\n }\n\n return {\n read: read,\n write: write,\n swap: function () {\n let temp = this.read;\n this.read = this.write;\n this.write = temp;\n },\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n if (isSizeUpdate) {\n renderTarget.read?.setSize(resolution.x, resolution.y);\n renderTarget.write?.setSize(resolution.x, resolution.y);\n }\n\n useEffect(() => {\n const temp = renderTarget;\n return () => {\n temp.read?.dispose();\n temp.write?.dispose();\n };\n }, [renderTarget]);\n\n const updateRenderTarget: FBOUpdateFunction = useCallback(\n (gl, onBeforeRender) => {\n const fbo = renderTarget;\n renderFBO({\n gl,\n scene,\n camera,\n fbo: fbo.write!,\n onBeforeRender: () =>\n onBeforeRender &&\n onBeforeRender({\n read: fbo.read!.texture,\n write: fbo.write!.texture,\n }),\n onSwap: () => fbo.swap(),\n });\n return fbo.read?.texture as THREE.Texture;\n },\n [scene, camera, renderTarget]\n );\n\n return [\n { read: renderTarget.read, write: renderTarget.write },\n updateRenderTarget,\n ];\n};\n","import { Dpr } from \"../fxs/types\";\n\nexport const getDpr = (\n dpr: Dpr\n): { shader: number | false; fbo: number | false } => {\n if (typeof dpr === \"number\") {\n return { shader: dpr, fbo: dpr };\n }\n return {\n shader: dpr.shader ?? false,\n fbo: dpr.fbo ?? false,\n };\n};\n","import * as THREE from \"three\";\nimport { useMesh } from \"./useMesh\";\nimport { useCamera } from \"../../../utils/useCamera\";\nimport { useCallback, useMemo, useRef } from \"react\";\nimport { RootState } from \"@react-three/fiber\";\nimport { PointerValues, usePointer } from \"../../../misc/usePointer\";\nimport {\n CustomParams,\n setCustomUniform,\n setUniform,\n} from \"../../../utils/setUniforms\";\nimport { HooksProps, HooksReturn } from \"../../types\";\nimport { useParams } from \"../../../utils/useParams\";\nimport { DoubleRenderTarget, useDoubleFBO } from \"../../../utils/useDoubleFBO\";\nimport { getDpr } from \"../../../utils/getDpr\";\n\nexport type BrushParams = {\n /** Texture applied to the brush, If texture is true, it will take precedence over color , default : `false` */\n texture?: THREE.Texture | false;\n /** You can attach an fx map , default : `false` */\n map?: THREE.Texture | false;\n /** map intensity , default : `0.1` */\n mapIntensity?: number;\n /** size of the stamp, percentage of the size ,default : `0.05` */\n radius?: number;\n /** Strength of smudge effect , default : `0.0`*/\n smudge?: number;\n /** dissipation rate. If set to 1, it will remain. , default : `1.0` */\n dissipation?: number;\n /** Strength of motion blur , default : `0.0` */\n motionBlur?: number;\n /** Number of motion blur samples. Affects performance default : `5` */\n motionSample?: number;\n /** brush color , it accepts a function that returns THREE.Vector3.The function takes velocity:THREE.Vector2 as an argument. , default : `THREE.Vector3(1.0, 1.0, 1.0)` */\n color?:\n | ((velocity: THREE.Vector2) => THREE.Vector3)\n | THREE.Vector3\n | THREE.Color;\n /** Follows the cursor even if it loses speed , default : `false` */\n isCursor?: boolean;\n /** brush pressure (0 to 1) , default : `1.0` */\n pressure?: number;\n /** When calling usePointer in a frame loop, setting PointerValues ​​to this value prevents double calls , default : `false` */\n pointerValues?: PointerValues | false;\n};\n\nexport type BrushObject = {\n scene: THREE.Scene;\n mesh: THREE.Mesh;\n material: THREE.Material;\n camera: THREE.Camera;\n renderTarget: DoubleRenderTarget;\n output: THREE.Texture;\n};\n\nexport const BRUSH_PARAMS: BrushParams = Object.freeze({\n texture: false,\n map: false,\n mapIntensity: 0.1,\n radius: 0.05,\n smudge: 0.0,\n dissipation: 1.0,\n motionBlur: 0.0,\n motionSample: 5,\n color: new THREE.Vector3(1.0, 0.0, 0.0),\n isCursor: false,\n pressure: 1.0,\n pointerValues: false,\n});\n\n/**\n * @link https://github.com/FunTechInc/use-shader-fx?tab=readme-ov-file#usage\n */\nexport const useBrush = ({\n size,\n dpr,\n renderTargetOptions,\n isSizeUpdate,\n onBeforeInit,\n}: HooksProps): HooksReturn => {\n const _dpr = getDpr(dpr);\n\n const scene = useMemo(() => new THREE.Scene(), []);\n const { material, mesh } = useMesh({\n scene,\n size,\n dpr: _dpr.shader,\n onBeforeInit,\n });\n const camera = useCamera(size);\n const updatePointer = usePointer();\n const [renderTarget, updateRenderTarget] = useDoubleFBO({\n scene,\n camera,\n size,\n dpr: _dpr.fbo,\n isSizeUpdate,\n ...renderTargetOptions,\n });\n\n const [params, setParams] = useParams(BRUSH_PARAMS);\n\n const pressureEnd = useRef(null);\n\n const updateValue = setUniform(material);\n const updateCustomValue = setCustomUniform(material);\n\n const updateParams = useCallback(\n (newParams?: BrushParams, customParams?: CustomParams) => {\n setParams(newParams);\n updateCustomValue(customParams);\n },\n [setParams, updateCustomValue]\n );\n\n const updateFx = useCallback(\n (\n rootState: RootState,\n newParams?: BrushParams,\n customParams?: CustomParams\n ) => {\n const { gl, pointer } = rootState;\n\n updateParams(newParams, customParams);\n\n if (params.texture!) {\n updateValue(\"uIsTexture\", true);\n updateValue(\"uTexture\", params.texture!);\n } else {\n updateValue(\"uIsTexture\", false);\n }\n\n if (params.map!) {\n updateValue(\"uIsMap\", true);\n updateValue(\"uMap\", params.map!);\n updateValue(\"uMapIntensity\", params.mapIntensity!);\n } else {\n updateValue(\"uIsMap\", false);\n }\n\n updateValue(\"uRadius\", params.radius!);\n updateValue(\"uSmudge\", params.smudge!);\n updateValue(\"uDissipation\", params.dissipation!);\n updateValue(\"uMotionBlur\", params.motionBlur!);\n updateValue(\"uMotionSample\", params.motionSample!);\n\n const pointerValues = params.pointerValues! || updatePointer(pointer);\n\n if (pointerValues.isVelocityUpdate) {\n updateValue(\"uMouse\", pointerValues.currentPointer);\n updateValue(\"uPrevMouse\", pointerValues.prevPointer);\n }\n updateValue(\"uVelocity\", pointerValues.velocity);\n\n const color: THREE.Vector3 | THREE.Color =\n typeof params.color === \"function\"\n ? params.color(pointerValues.velocity)\n : params.color!;\n updateValue(\"uColor\", color);\n\n updateValue(\"uIsCursor\", params.isCursor!);\n\n // pressure\n updateValue(\"uPressureEnd\", params.pressure!);\n if (pressureEnd.current === null) {\n pressureEnd.current = params.pressure!;\n }\n updateValue(\"uPressureStart\", pressureEnd.current);\n pressureEnd.current = params.pressure!;\n\n return updateRenderTarget(gl, ({ read }) => {\n updateValue(\"uBuffer\", read);\n });\n },\n [updateValue, updatePointer, updateRenderTarget, params, updateParams]\n );\n\n return [\n updateFx,\n updateParams,\n {\n scene: scene,\n mesh: mesh,\n material: material,\n camera: camera,\n renderTarget: renderTarget,\n output: renderTarget.read.texture,\n },\n ];\n};\n","varying vec2 vUv;\nvarying vec2 vL;\nvarying vec2 vR;\nvarying vec2 vT;\nvarying vec2 vB;\nuniform vec2 texelSize;\n\nvoid main () {\n\tvUv = uv;\n\tvL = vUv - vec2(texelSize.x, 0.0);\n\tvR = vUv + vec2(texelSize.x, 0.0);\n\tvT = vUv + vec2(0.0, texelSize.y);\n\tvB = vUv - vec2(0.0, texelSize.y);\n\tgl_Position = vec4(position, 1.0);\n}","precision highp float;\n\nvoid main(){\n\tgl_FragColor = vec4(0.0);\n}","import * as THREE from \"three\";\nimport { useMemo } from \"react\";\nimport vertexShader from \"../shaders/main.vert\";\nimport fragmentShader from \"../shaders/init.frag\";\nimport { MATERIAL_BASIC_PARAMS } from \"../../../../libs/constants\";\n\nexport const useInitialMaterial = () => {\n const initialMaterial = useMemo(() => {\n const mat = new THREE.ShaderMaterial({\n vertexShader: vertexShader,\n fragmentShader: fragmentShader,\n ...MATERIAL_BASIC_PARAMS,\n });\n return mat;\n }, []);\n\n return initialMaterial as THREE.ShaderMaterial;\n};\n","precision highp float;\n\nvarying vec2 vUv;\nuniform sampler2D uVelocity;\nuniform sampler2D uSource;\nuniform vec2 texelSize;\nuniform float dt;\nuniform float dissipation;\n\nvoid main () {\n\tvec2 coord = vUv - dt * texture2D(uVelocity, vUv).xy * texelSize;\n\tgl_FragColor = vec4(dissipation * texture2D(uSource, coord).rgb,1.);\n}","import * as THREE from \"three\";\nimport { useMemo } from \"react\";\nimport vertexShader from \"../shaders/main.vert\";\nimport fragmentShader from \"../shaders/advection.frag\";\nimport { MaterialProps } from \"../../../types\";\nimport {\n DEFAULT_TEXTURE,\n MATERIAL_BASIC_PARAMS,\n} from \"../../../../libs/constants\";\nimport { DELTA_TIME } from \"..\";\nimport { createMaterialParameters } from \"../../../../utils/createMaterialParameters\";\n\nexport class AdvectionMaterial extends THREE.ShaderMaterial {\n uniforms!: {\n uVelocity: { value: THREE.Texture };\n uSource: { value: THREE.Texture };\n texelSize: { value: THREE.Vector2 };\n dt: { value: number };\n dissipation: { value: number };\n };\n}\n\nexport const useAdvectionMaterial = ({ onBeforeInit }: MaterialProps) => {\n const advectionMaterial = useMemo(() => {\n const mat = new THREE.ShaderMaterial({\n ...createMaterialParameters(\n {\n uniforms: {\n uVelocity: { value: DEFAULT_TEXTURE },\n uSource: { value: DEFAULT_TEXTURE },\n texelSize: { value: new THREE.Vector2() },\n dt: { value: DELTA_TIME },\n dissipation: { value: 0.0 },\n },\n vertexShader: vertexShader,\n fragmentShader: fragmentShader,\n },\n onBeforeInit\n ),\n ...MATERIAL_BASIC_PARAMS,\n });\n\n return mat;\n }, [onBeforeInit]);\n\n return advectionMaterial as AdvectionMaterial;\n};\n","precision highp float;\n\nvarying vec2 vUv;\nvarying vec2 vL;\nvarying vec2 vR;\nvarying vec2 vT;\nvarying vec2 vB;\nuniform sampler2D uVelocity;\n\nvec2 sampleVelocity(in vec2 uv) {\n\tvec2 clampedUV = clamp(uv, 0.0, 1.0);\n\tvec2 multiplier = vec2(1.0, 1.0);\n\tmultiplier.x = uv.x < 0.0 || uv.x > 1.0 ? -1.0 : 1.0;\n\tmultiplier.y = uv.y < 0.0 || uv.y > 1.0 ? -1.0 : 1.0;\n\treturn multiplier * texture2D(uVelocity, clampedUV).xy;\n}\n\nvoid main () {\n\tfloat L = sampleVelocity(vL).x;\n\tfloat R = sampleVelocity(vR).x;\n\tfloat T = sampleVelocity(vT).y;\n\tfloat B = sampleVelocity(vB).y;\n\tfloat div = 0.5 * (R - L + T - B);\n\tgl_FragColor = vec4(div, 0.0, 0.0, 1.0);\n}","import * as THREE from \"three\";\nimport { useMemo } from \"react\";\nimport vertexShader from \"../shaders/main.vert\";\nimport fragmentShader from \"../shaders/divergence.frag\";\nimport { MaterialProps } from \"../../../types\";\nimport { MATERIAL_BASIC_PARAMS } from \"../../../../libs/constants\";\nimport { createMaterialParameters } from \"../../../../utils/createMaterialParameters\";\n\nexport class DivergenceMaterial extends THREE.ShaderMaterial {\n uniforms!: {\n uVelocity: { value: THREE.Texture };\n texelSize: { value: THREE.Vector2 };\n };\n}\n\nexport const useDivergenceMaterial = ({ onBeforeInit }: MaterialProps) => {\n const divergenceMaterial = useMemo(() => {\n const mat = new THREE.ShaderMaterial({\n ...createMaterialParameters(\n {\n uniforms: {\n uVelocity: { value: null },\n texelSize: { value: new THREE.Vector2() },\n },\n vertexShader: vertexShader,\n fragmentShader: fragmentShader,\n },\n onBeforeInit\n ),\n ...MATERIAL_BASIC_PARAMS,\n });\n return mat;\n }, [onBeforeInit]);\n\n return divergenceMaterial as DivergenceMaterial;\n};\n","precision highp float;\n\nvarying vec2 vUv;\nvarying vec2 vL;\nvarying vec2 vR;\nvarying vec2 vT;\nvarying vec2 vB;\nuniform sampler2D uPressure;\nuniform sampler2D uDivergence;\n\nvoid main () {\n\tfloat L = texture2D(uPressure, clamp(vL,0.,1.)).x;\n\tfloat R = texture2D(uPressure, clamp(vR,0.,1.)).x;\n\tfloat T = texture2D(uPressure, clamp(vT,0.,1.)).x;\n\tfloat B = texture2D(uPressure, clamp(vB,0.,1.)).x;\n\tfloat C = texture2D(uPressure, vUv).x;\n\tfloat divergence = texture2D(uDivergence, vUv).x;\n\tfloat pressure = (L + R + B + T - divergence) * 0.25;\n\tgl_FragColor = vec4(pressure, 0.0, 0.0, 1.0);\n}","import * as THREE from \"three\";\nimport { useMemo } from \"react\";\nimport vertexShader from \"../shaders/main.vert\";\nimport fragmentShader from \"../shaders/pressure.frag\";\nimport { MaterialProps } from \"../../../types\";\nimport { MATERIAL_BASIC_PARAMS } from \"../../../../libs/constants\";\nimport { createMaterialParameters } from \"../../../../utils/createMaterialParameters\";\n\nexport class PressureMaterial extends THREE.ShaderMaterial {\n uniforms!: {\n uPressure: { value: THREE.Texture };\n uDivergence: { value: THREE.Texture };\n texelSize: { value: THREE.Vector2 };\n };\n}\n\nexport const usePressureMaterial = ({ onBeforeInit }: MaterialProps) => {\n const pressureMaterial = useMemo(() => {\n const mat = new THREE.ShaderMaterial({\n ...createMaterialParameters(\n {\n uniforms: {\n uPressure: { value: null },\n uDivergence: { value: null },\n texelSize: { value: new THREE.Vector2() },\n },\n vertexShader: vertexShader,\n fragmentShader: fragmentShader,\n },\n onBeforeInit\n ),\n ...MATERIAL_BASIC_PARAMS,\n });\n\n return mat;\n }, [onBeforeInit]);\n\n return pressureMaterial as PressureMaterial;\n};\n","precision highp float;\n\nvarying vec2 vUv;\nvarying vec2 vL;\nvarying vec2 vR;\nvarying vec2 vT;\nvarying vec2 vB;\nuniform sampler2D uVelocity;\n\nvoid main () {\n\tfloat L = texture2D(uVelocity, vL).y;\n\tfloat R = texture2D(uVelocity, vR).y;\n\tfloat T = texture2D(uVelocity, vT).x;\n\tfloat B = texture2D(uVelocity, vB).x;\n\tfloat vorticity = R - L - T + B;\n\tgl_FragColor = vec4(vorticity, 0.0, 0.0, 1.0);\n}","import * as THREE from \"three\";\nimport { useMemo } from \"react\";\nimport vertexShader from \"../shaders/main.vert\";\nimport fragmentShader from \"../shaders/curl.frag\";\nimport { MaterialProps } from \"../../../types\";\nimport { MATERIAL_BASIC_PARAMS } from \"../../../../libs/constants\";\nimport { createMaterialParameters } from \"../../../../utils/createMaterialParameters\";\n\nexport class CurlMaterial extends THREE.ShaderMaterial {\n uniforms!: {\n uVelocity: { value: THREE.Texture };\n texelSize: { value: THREE.Vector2 };\n };\n}\n\nexport const useCurlMaterial = ({ onBeforeInit }: MaterialProps) => {\n const curlMaterial = useMemo(() => {\n const mat = new THREE.ShaderMaterial({\n ...createMaterialParameters(\n {\n uniforms: {\n uVelocity: { value: null },\n texelSize: { value: new THREE.Vector2() },\n },\n vertexShader: vertexShader,\n fragmentShader: fragmentShader,\n },\n onBeforeInit\n ),\n ...MATERIAL_BASIC_PARAMS,\n });\n\n return mat;\n }, [onBeforeInit]);\n\n return curlMaterial as CurlMaterial;\n};\n","precision highp float;\n\nvarying vec2 vUv;\nvarying vec2 vT;\nvarying vec2 vB;\nuniform sampler2D uVelocity;\nuniform sampler2D uCurl;\nuniform float curl;\nuniform float dt;\n\nvoid main () {\n\tfloat T = texture2D(uCurl, vT).x;\n\tfloat B = texture2D(uCurl, vB).x;\n\tfloat C = texture2D(uCurl, vUv).x;\n\tvec2 force = vec2(abs(T) - abs(B), 0.0);\n\tforce *= 1.0 / length(force + 0.00001) * curl * C;\n\tvec2 vel = texture2D(uVelocity, vUv).xy;\n\tgl_FragColor = vec4(vel + force * dt, 0.0, 1.0);\n}","import * as THREE from \"three\";\nimport { useMemo } from \"react\";\nimport vertexShader from \"../shaders/main.vert\";\nimport fragmentShader from \"../shaders/vorticity.frag\";\nimport { MaterialProps } from \"../../../types\";\nimport { MATERIAL_BASIC_PARAMS } from \"../../../../libs/constants\";\nimport { DELTA_TIME } from \"..\";\nimport { createMaterialParameters } from \"../../../../utils/createMaterialParameters\";\n\nexport class VorticityMaterial extends THREE.ShaderMaterial {\n uniforms!: {\n uVelocity: { value: THREE.Texture };\n uCurl: { value: THREE.Texture };\n curl: { value: number };\n dt: { value: number };\n texelSize: { value: THREE.Vector2 };\n };\n}\n\nexport const useVorticityMaterial = ({ onBeforeInit }: MaterialProps) => {\n const vorticityMaterial = useMemo(() => {\n const mat = new THREE.ShaderMaterial({\n ...createMaterialParameters(\n {\n uniforms: {\n uVelocity: { value: null },\n uCurl: { value: null },\n curl: { value: 0 },\n dt: { value: DELTA_TIME },\n texelSize: { value: new THREE.Vector2() },\n },\n vertexShader: vertexShader,\n fragmentShader: fragmentShader,\n },\n onBeforeInit\n ),\n ...MATERIAL_BASIC_PARAMS,\n });\n return mat;\n }, [onBeforeInit]);\n\n return vorticityMaterial as VorticityMaterial;\n};\n","precision highp float;\n\nvarying vec2 vUv;\nuniform sampler2D uTexture;\nuniform float value;\n\nvoid main () {\n\tgl_FragColor = value * texture2D(uTexture, vUv);\n}","import * as THREE from \"three\";\nimport { useMemo } from \"react\";\nimport vertexShader from \"../shaders/main.vert\";\nimport fragmentShader from \"../shaders/clear.frag\";\nimport { MaterialProps } from \"../../../types\";\nimport {\n MATERIAL_BASIC_PARAMS,\n DEFAULT_TEXTURE,\n} from \"../../../../libs/constants\";\nimport { createMaterialParameters } from \"../../../../utils/createMaterialParameters\";\n\nexport class ClearMaterial extends THREE.ShaderMaterial {\n uniforms!: {\n uTexture: { value: THREE.Texture };\n value: { value: number };\n texelSize: { value: THREE.Vector2 };\n };\n}\n\nexport const useClearMaterial = ({ onBeforeInit }: MaterialProps) => {\n const advectionMaterial = useMemo(() => {\n const mat = new THREE.ShaderMaterial({\n ...createMaterialParameters(\n {\n uniforms: {\n uTexture: { value: DEFAULT_TEXTURE },\n value: { value: 0.0 },\n texelSize: { value: new THREE.Vector2() },\n },\n vertexShader: vertexShader,\n fragmentShader: fragmentShader,\n },\n onBeforeInit\n ),\n ...MATERIAL_BASIC_PARAMS,\n });\n\n return mat;\n }, [onBeforeInit]);\n\n return advectionMaterial as ClearMaterial;\n};\n","precision highp float;\n\nvarying vec2 vUv;\nvarying vec2 vL;\nvarying vec2 vR;\nvarying vec2 vT;\nvarying vec2 vB;\nuniform sampler2D uPressure;\nuniform sampler2D uVelocity;\n\nvoid main () {\n\tfloat L = texture2D(uPressure, clamp(vL,0.,1.)).x;\n\tfloat R = texture2D(uPressure, clamp(vR,0.,1.)).x;\n\tfloat T = texture2D(uPressure, clamp(vT,0.,1.)).x;\n\tfloat B = texture2D(uPressure, clamp(vB,0.,1.)).x;\n\tvec2 velocity = texture2D(uVelocity, vUv).xy;\n\tvelocity.xy -= vec2(R - L, T - B);\n\tgl_FragColor = vec4(velocity, 0.0, 1.0);\n}","import * as THREE from \"three\";\nimport { useMemo } from \"react\";\nimport vertexShader from \"../shaders/main.vert\";\nimport fragmentShader from \"../shaders/gradientSubtract.frag\";\nimport { MaterialProps } from \"../../../types\";\nimport {\n MATERIAL_BASIC_PARAMS,\n DEFAULT_TEXTURE,\n} from \"../../../../libs/constants\";\nimport { createMaterialParameters } from \"../../../../utils/createMaterialParameters\";\n\nexport class GradientSubtractMaterial extends THREE.ShaderMaterial {\n uniforms!: {\n uPressure: { value: THREE.Texture };\n uVelocity: { value: THREE.Texture };\n texelSize: { value: THREE.Vector2 };\n };\n}\n\nexport const useGradientSubtractMaterial = ({\n onBeforeInit,\n}: MaterialProps) => {\n const gradientSubtractMaterial = useMemo(() => {\n const mat = new THREE.ShaderMaterial({\n ...createMaterialParameters(\n {\n uniforms: {\n uPressure: { value: DEFAULT_TEXTURE },\n uVelocity: { value: DEFAULT_TEXTURE },\n texelSize: { value: new THREE.Vector2() },\n },\n vertexShader: vertexShader,\n fragmentShader: fragmentShader,\n },\n onBeforeInit\n ),\n ...MATERIAL_BASIC_PARAMS,\n });\n\n return mat;\n }, [onBeforeInit]);\n\n return gradientSubtractMaterial as GradientSubtractMaterial;\n};\n","precision highp float;\n\nvarying vec2 vUv;\nuniform sampler2D uTarget;\nuniform float aspectRatio;\nuniform vec3 color;\nuniform vec2 point;\nuniform float radius;\n\nvoid main () {\n\tvec2 nPoint = (point + vec2(1.0)) * 0.5;\n\tvec2 p = vUv - nPoint.xy;\n\tp.x *= aspectRatio;\n\tvec3 splat = exp(-dot(p, p) / radius) * color;\n\tvec3 base = texture2D(uTarget, vUv).xyz;\n\tgl_FragColor = vec4(base + splat, 1.0);\n}","import * as THREE from \"three\";\nimport { useMemo } from \"react\";\nimport vertexShader from \"../shaders/main.vert\";\nimport fragmentShader from \"../shaders/splat.frag\";\nimport { MaterialProps } from \"../../../types\";\nimport {\n MATERIAL_BASIC_PARAMS,\n DEFAULT_TEXTURE,\n} from \"../../../../libs/constants\";\nimport { createMaterialParameters } from \"../../../../utils/createMaterialParameters\";\n\nexport class SplatMaterial extends THREE.ShaderMaterial {\n uniforms!: {\n uTarget: { value: THREE.Texture };\n aspectRatio: { value: number };\n color: { value: THREE.Vector3 | THREE.Color };\n point: { value: THREE.Vector2 };\n radius: { value: number };\n texelSize: { value: THREE.Vector2 };\n };\n}\n\nexport const useSplatMaterial = ({ onBeforeInit }: MaterialProps) => {\n const splatMaterial = useMemo(() => {\n const mat = new THREE.ShaderMaterial({\n ...createMaterialParameters(\n {\n uniforms: {\n uTarget: { value: DEFAULT_TEXTURE },\n aspectRatio: { value: 0 },\n color: { value: new THREE.Vector3() },\n point: { value: new THREE.Vector2() },\n radius: { value: 0.0 },\n texelSize: { value: new THREE.Vector2() },\n },\n vertexShader: vertexShader,\n fragmentShader: fragmentShader,\n },\n onBeforeInit\n ),\n ...MATERIAL_BASIC_PARAMS,\n });\n\n return mat;\n }, [onBeforeInit]);\n\n return splatMaterial as SplatMaterial;\n};\n","import * as THREE from \"three\";\nimport { useCallback, useEffect, useMemo } from \"react\";\nimport { useInitialMaterial } from \"./materials/useInitialMaterial\";\nimport {\n AdvectionMaterial,\n useAdvectionMaterial,\n} from \"./materials/useAdvectionMaterial\";\nimport {\n DivergenceMaterial,\n useDivergenceMaterial,\n} from \"./materials/useDivergenceMaterial\";\nimport {\n PressureMaterial,\n usePressureMaterial,\n} from \"./materials/usePressureMaterial\";\nimport { CurlMaterial, useCurlMaterial } from \"./materials/useCurlMaterial\";\nimport {\n VorticityMaterial,\n useVorticityMaterial,\n} from \"./materials/useVorticityMaterial\";\nimport { useResolution } from \"../../../utils/useResolution\";\nimport { ClearMaterial, useClearMaterial } from \"./materials/useClearMaterial\";\nimport {\n GradientSubtractMaterial,\n useGradientSubtractMaterial,\n} from \"./materials/useGradientSubtractMaterial\";\nimport { SplatMaterial, useSplatMaterial } from \"./materials/useSplatMaterial\";\nimport { CustomParams, setUniform } from \"../../../utils/setUniforms\";\nimport { useAddObject } from \"../../../utils/useAddObject\";\nimport { MaterialProps, Size } from \"../../types\";\n\ntype TMaterials =\n | AdvectionMaterial\n | DivergenceMaterial\n | CurlMaterial\n | PressureMaterial\n | ClearMaterial\n | GradientSubtractMaterial\n | SplatMaterial;\n\nexport type FluidMaterials = {\n vorticityMaterial: VorticityMaterial;\n curlMaterial: CurlMaterial;\n advectionMaterial: AdvectionMaterial;\n divergenceMaterial: DivergenceMaterial;\n pressureMaterial: PressureMaterial;\n clearMaterial: ClearMaterial;\n gradientSubtractMaterial: GradientSubtractMaterial;\n splatMaterial: SplatMaterial;\n};\n\nexport type CustomizableKeys =\n | \"advection\"\n | \"splat\"\n | \"curl\"\n | \"vorticity\"\n | \"divergence\"\n | \"clear\"\n | \"pressure\"\n | \"gradientSubtract\";\n\nexport type CustomFluidProps = {\n [K in CustomizableKeys]?: MaterialProps;\n};\nexport type CustomFluidParams = {\n [K in CustomizableKeys]?: CustomParams;\n};\n\nconst useCustomMaterial = (\n materialHook: (materialProps: MaterialProps) => T,\n materialProps?: MaterialProps\n) => {\n return materialHook(materialProps ?? {});\n};\n\n/**\n * Returns the material update function in the second argument\n */\nexport const useMesh = ({\n scene,\n size,\n dpr,\n customFluidProps,\n}: {\n scene: THREE.Scene;\n size: Size;\n dpr: number | false;\n customFluidProps?: CustomFluidProps;\n}) => {\n const geometry = useMemo(() => new THREE.PlaneGeometry(2, 2), []);\n\n const {\n curl,\n vorticity,\n advection,\n divergence,\n pressure,\n clear,\n gradientSubtract,\n splat,\n } = customFluidProps ?? {};\n\n const initialMaterial = useCustomMaterial(useInitialMaterial);\n const updateMaterial = initialMaterial.clone();\n const curlMaterial = useCustomMaterial(useCurlMaterial, curl);\n const vorticityMaterial = useCustomMaterial(useVorticityMaterial, vorticity);\n const advectionMaterial = useCustomMaterial(useAdvectionMaterial, advection);\n const divergenceMaterial = useCustomMaterial(\n useDivergenceMaterial,\n divergence\n );\n const pressureMaterial = useCustomMaterial(usePressureMaterial, pressure);\n const clearMaterial = useCustomMaterial(useClearMaterial, clear);\n const gradientSubtractMaterial = useCustomMaterial(\n useGradientSubtractMaterial,\n gradientSubtract\n );\n const splatMaterial = useCustomMaterial(useSplatMaterial, splat);\n const materials = useMemo(\n () => ({\n vorticityMaterial,\n curlMaterial,\n advectionMaterial,\n divergenceMaterial,\n pressureMaterial,\n clearMaterial,\n gradientSubtractMaterial,\n splatMaterial,\n }),\n [\n vorticityMaterial,\n curlMaterial,\n advectionMaterial,\n divergenceMaterial,\n pressureMaterial,\n clearMaterial,\n gradientSubtractMaterial,\n splatMaterial,\n ]\n );\n\n const resolution = useResolution(size, dpr);\n useMemo(() => {\n setUniform(materials.splatMaterial)(\n \"aspectRatio\",\n resolution.x / resolution.y\n );\n for (const material of Object.values(materials)) {\n setUniform(material)(\n \"texelSize\",\n new THREE.Vector2(1.0 / resolution.x, 1.0 / resolution.y)\n );\n }\n }, [resolution, materials]);\n\n const mesh = useAddObject(scene, geometry, initialMaterial, THREE.Mesh);\n\n useMemo(() => {\n initialMaterial.dispose();\n mesh.material = updateMaterial;\n }, [initialMaterial, mesh, updateMaterial]);\n\n useEffect(() => {\n return () => {\n for (const material of Object.values(materials)) {\n material.dispose();\n }\n };\n }, [materials]);\n\n const setMeshMaterial = useCallback(\n (material: TMaterials) => {\n mesh.material = material;\n mesh.material.needsUpdate = true;\n },\n [mesh]\n );\n\n return { materials, setMeshMaterial, mesh };\n};\n","import * as THREE from \"three\";\nimport {\n CustomizableKeys,\n FluidMaterials,\n CustomFluidProps,\n CustomFluidParams,\n useMesh,\n} from \"./useMesh\";\nimport { useCamera } from \"../../../utils/useCamera\";\nimport { useCallback, useMemo, useRef } from \"react\";\nimport { PointerValues, usePointer } from \"../../../misc/usePointer\";\nimport { RootState } from \"@react-three/fiber\";\nimport { useSingleFBO } from \"../../../utils/useSingleFBO\";\nimport {\n CustomParams,\n setCustomUniform,\n setUniform,\n} from \"../../../utils/setUniforms\";\nimport { HooksProps, HooksReturn } from \"../../types\";\nimport { useParams } from \"../../../utils/useParams\";\nimport { UseFboProps } from \"../../../utils/useSingleFBO\";\nimport { DoubleRenderTarget, useDoubleFBO } from \"../../../utils/useDoubleFBO\";\nimport { getDpr } from \"../../../utils/getDpr\";\n\nexport const DELTA_TIME = 0.016;\n\nexport type FluidParams = {\n /** density disspation , default : `0.98` */\n densityDissipation?: number;\n /** velocity dissipation , default : `0.99` */\n velocityDissipation?: number;\n /** velocity acceleration , default : `10.0` */\n velocityAcceleration?: number;\n /** pressure dissipation , default : `0.9` */\n pressureDissipation?: number;\n /** pressure iterations. affects performance , default : `20` */\n pressureIterations?: number;\n /** curl_strength , default : `35` */\n curlStrength?: number;\n /** splat radius , default : `0.002` */\n splatRadius?: number;\n /** Fluid Color.THREE.Vector3 Alternatively, it accepts a function that returns THREE.Vector3.The function takes velocity:THREE.Vector2 as an argument. , default : `THREE.Vector3(1.0, 1.0, 1.0)` */\n fluidColor?:\n | ((velocity: THREE.Vector2) => THREE.Vector3)\n | THREE.Vector3\n | THREE.Color;\n /** When calling usePointer in a frame loop, setting PointerValues ​​to this value prevents double calls , default : `false` */\n pointerValues?: PointerValues | false;\n};\n\nexport type FluidObject = {\n scene: THREE.Scene;\n mesh: THREE.Mesh;\n materials: FluidMaterials;\n camera: THREE.Camera;\n renderTarget: {\n velocity: DoubleRenderTarget;\n density: DoubleRenderTarget;\n curl: THREE.WebGLRenderTarget;\n divergence: THREE.WebGLRenderTarget;\n pressure: DoubleRenderTarget;\n };\n output: THREE.Texture;\n};\n\nexport const FLUID_PARAMS: FluidParams = Object.freeze({\n densityDissipation: 0.98,\n velocityDissipation: 0.99,\n velocityAcceleration: 10.0,\n pressureDissipation: 0.9,\n pressureIterations: 20,\n curlStrength: 35,\n splatRadius: 0.002,\n fluidColor: new THREE.Vector3(1.0, 1.0, 1.0),\n pointerValues: false,\n});\n\n/**\n * @link https://github.com/FunTechInc/use-shader-fx?tab=readme-ov-file#usage\n */\nexport const useFluid = ({\n size,\n dpr,\n renderTargetOptions,\n isSizeUpdate,\n customFluidProps,\n}: {\n /** you can add `onBeforeInit` of the next material.`initial`,`curl`,`vorticity`,`advection`,`divergence`,`pressure`,`clear`,`gradientSubtract`,`splat` \n\t * ```ts\n\t * customFluidProps: {\n vorticity: {\n onBeforeInit: (parameters) => console.log(parameters),\n },\n },\n\t * ```\n\t*/\n customFluidProps?: CustomFluidProps;\n} & HooksProps): HooksReturn => {\n const _dpr = getDpr(dpr);\n\n const scene = useMemo(() => new THREE.Scene(), []);\n const { materials, setMeshMaterial, mesh } = useMesh({\n scene,\n size,\n dpr: _dpr.shader,\n customFluidProps,\n });\n const camera = useCamera(size);\n const updatePointer = usePointer();\n\n const fboProps = useMemo(\n () => ({\n scene,\n camera,\n dpr: _dpr.fbo,\n size,\n isSizeUpdate,\n type: THREE.HalfFloatType,\n ...renderTargetOptions,\n }),\n [scene, camera, size, _dpr.fbo, isSizeUpdate, renderTargetOptions]\n );\n const [velocityFBO, updateVelocityFBO] = useDoubleFBO(fboProps);\n const [densityFBO, updateDensityFBO] = useDoubleFBO(fboProps);\n const [curlFBO, updateCurlFBO] = useSingleFBO(fboProps);\n const [divergenceFBO, updateDivergenceFBO] = useSingleFBO(fboProps);\n const [pressureFBO, updatePressureFBO] = useDoubleFBO(fboProps);\n\n const scaledDiffVec = useRef(new THREE.Vector2(0, 0));\n const spaltVec = useRef(new THREE.Vector3(0, 0, 0));\n\n const [params, setParams] = useParams(FLUID_PARAMS);\n\n // setUniform\n const updateParamsList = useMemo(\n () => ({\n advection: setUniform(materials.advectionMaterial),\n splat: setUniform(materials.splatMaterial),\n curl: setUniform(materials.curlMaterial),\n vorticity: setUniform(materials.vorticityMaterial),\n divergence: setUniform(materials.divergenceMaterial),\n clear: setUniform(materials.clearMaterial),\n pressure: setUniform(materials.pressureMaterial),\n gradientSubtract: setUniform(materials.gradientSubtractMaterial),\n }),\n [materials]\n );\n // customSetUniform\n const updateCustomParamsList = useMemo<{\n [K in CustomizableKeys]: (customParams: CustomParams | undefined) => void;\n }>(\n () => ({\n advection: setCustomUniform(materials.advectionMaterial),\n splat: setCustomUniform(materials.splatMaterial),\n curl: setCustomUniform(materials.curlMaterial),\n vorticity: setCustomUniform(materials.vorticityMaterial),\n divergence: setCustomUniform(materials.divergenceMaterial),\n clear: setCustomUniform(materials.clearMaterial),\n pressure: setCustomUniform(materials.pressureMaterial),\n gradientSubtract: setCustomUniform(materials.gradientSubtractMaterial),\n }),\n [materials]\n );\n\n const updateParams = useCallback(\n (newParams?: FluidParams, customParams?: CustomFluidParams) => {\n setParams(newParams);\n if (customParams) {\n Object.keys(customParams).forEach((key) => {\n updateCustomParamsList[key as CustomizableKeys](\n customParams[key as CustomizableKeys]\n );\n });\n }\n },\n [setParams, updateCustomParamsList]\n );\n\n const updateFx = useCallback(\n (\n rootState: RootState,\n newParams?: FluidParams,\n customParams?: CustomFluidParams\n ) => {\n const { gl, pointer, size } = rootState;\n\n updateParams(newParams, customParams);\n\n const velocityTex = updateVelocityFBO(gl, ({ read }) => {\n setMeshMaterial(materials.advectionMaterial);\n updateParamsList.advection(\"uVelocity\", read);\n updateParamsList.advection(\"uSource\", read);\n updateParamsList.advection(\n \"dissipation\",\n params.velocityDissipation!\n );\n });\n\n const densityTex = updateDensityFBO(gl, ({ read }) => {\n setMeshMaterial(materials.advectionMaterial);\n updateParamsList.advection(\"uVelocity\", velocityTex);\n updateParamsList.advection(\"uSource\", read);\n updateParamsList.advection(\n \"dissipation\",\n params.densityDissipation!\n );\n });\n\n const pointerValues = params.pointerValues! || updatePointer(pointer);\n\n if (pointerValues.isVelocityUpdate) {\n updateVelocityFBO(gl, ({ read }) => {\n setMeshMaterial(materials.splatMaterial);\n updateParamsList.splat(\"uTarget\", read);\n updateParamsList.splat(\"point\", pointerValues.currentPointer);\n const scaledDiff = pointerValues.diffPointer.multiply(\n scaledDiffVec.current\n .set(size.width, size.height)\n .multiplyScalar(params.velocityAcceleration!)\n );\n updateParamsList.splat(\n \"color\",\n spaltVec.current.set(scaledDiff.x, scaledDiff.y, 1.0)\n );\n updateParamsList.splat(\"radius\", params.splatRadius!);\n });\n updateDensityFBO(gl, ({ read }) => {\n setMeshMaterial(materials.splatMaterial);\n updateParamsList.splat(\"uTarget\", read);\n const color: THREE.Vector3 | THREE.Color =\n typeof params.fluidColor === \"function\"\n ? params.fluidColor(pointerValues.velocity)\n : params.fluidColor!;\n updateParamsList.splat(\"color\", color);\n });\n }\n\n const curlTex = updateCurlFBO(gl, () => {\n setMeshMaterial(materials.curlMaterial);\n updateParamsList.curl(\"uVelocity\", velocityTex);\n });\n\n updateVelocityFBO(gl, ({ read }) => {\n setMeshMaterial(materials.vorticityMaterial);\n updateParamsList.vorticity(\"uVelocity\", read);\n updateParamsList.vorticity(\"uCurl\", curlTex);\n updateParamsList.vorticity(\"curl\", params.curlStrength!);\n });\n\n const divergenceTex = updateDivergenceFBO(gl, () => {\n setMeshMaterial(materials.divergenceMaterial);\n updateParamsList.divergence(\"uVelocity\", velocityTex);\n });\n\n updatePressureFBO(gl, ({ read }) => {\n setMeshMaterial(materials.clearMaterial);\n updateParamsList.clear(\"uTexture\", read);\n updateParamsList.clear(\"value\", params.pressureDissipation!);\n });\n\n setMeshMaterial(materials.pressureMaterial);\n updateParamsList.pressure(\"uDivergence\", divergenceTex);\n let pressureTexTemp: THREE.Texture;\n for (let i = 0; i < params.pressureIterations!; i++) {\n pressureTexTemp = updatePressureFBO(gl, ({ read }) => {\n updateParamsList.pressure(\"uPressure\", read);\n });\n }\n\n updateVelocityFBO(gl, ({ read }) => {\n setMeshMaterial(materials.gradientSubtractMaterial);\n updateParamsList.gradientSubtract(\"uPressure\", pressureTexTemp);\n updateParamsList.gradientSubtract(\"uVelocity\", read);\n });\n\n return densityTex;\n },\n [\n materials,\n updateParamsList,\n setMeshMaterial,\n updateCurlFBO,\n updateDensityFBO,\n updateDivergenceFBO,\n updatePointer,\n updatePressureFBO,\n updateVelocityFBO,\n params,\n updateParams,\n ]\n );\n return [\n updateFx,\n updateParams,\n {\n scene: scene,\n mesh: mesh,\n materials: materials,\n camera: camera,\n renderTarget: {\n velocity: velocityFBO,\n density: densityFBO,\n curl: curlFBO,\n divergence: divergenceFBO,\n pressure: pressureFBO,\n },\n output: densityFBO.read.texture,\n },\n ];\n};\n","#usf ","precision highp float;\n\nuniform sampler2D uMap;\nuniform float uOpacity;\n\nvarying vec2 vUv;\n\nvoid main() {\n\tvec2 uv = vUv;\n\tvec3 color = texture2D(uMap, uv).rgb;\n\tgl_FragColor = vec4(color,uOpacity);\n}","import * as THREE from \"three\";\nimport { useEffect, useMemo } from \"react\";\nimport vertexShader from \"./shader/main.vert\";\nimport fragmentShader from \"./shader/main.frag\";\nimport { MaterialProps } from \"../../types\";\nimport {\n DEFAULT_TEXTURE,\n MATERIAL_BASIC_PARAMS,\n} from \"../../../libs/constants\";\nimport { createMaterialParameters } from \"../../../utils/createMaterialParameters\";\n\ntype UseMeshProps = {\n scale: number;\n max: number;\n scene: THREE.Scene;\n texture?: THREE.Texture;\n};\n\nexport const useMesh = ({\n scale,\n max,\n texture,\n scene,\n onBeforeInit,\n}: UseMeshProps & MaterialProps) => {\n const geometry = useMemo(\n () => new THREE.PlaneGeometry(scale, scale),\n [scale]\n );\n\n const material = useMemo(() => {\n const mat = new THREE.ShaderMaterial({\n ...createMaterialParameters(\n {\n uniforms: {\n uOpacity: { value: 0.0 },\n uMap: { value: texture || DEFAULT_TEXTURE },\n },\n vertexShader: vertexShader,\n fragmentShader: fragmentShader,\n },\n onBeforeInit\n ),\n blending: THREE.AdditiveBlending,\n ...MATERIAL_BASIC_PARAMS,\n // Must be transparent.\n transparent: true,\n });\n return mat;\n }, [texture, onBeforeInit]);\n\n const meshArr = useMemo(() => {\n const temp = [];\n for (let i = 0; i < max; i++) {\n const clonedMat = material.clone();\n const mesh = new THREE.Mesh(geometry.clone(), clonedMat);\n mesh.rotateZ(2 * Math.PI * Math.random());\n mesh.visible = false;\n scene.add(mesh);\n temp.push(mesh);\n }\n return temp;\n }, [geometry, material, scene, max]);\n\n useEffect(() => {\n return () => {\n meshArr.forEach((mesh) => {\n mesh.geometry.dispose();\n if (Array.isArray(mesh.material)) {\n mesh.material.forEach((material) => material.dispose());\n } else {\n mesh.material.dispose();\n }\n scene.remove(mesh);\n });\n };\n }, [scene, meshArr]);\n\n return meshArr;\n};\n","import { useCallback, useMemo, useRef } from \"react\";\nimport * as THREE from \"three\";\nimport { useMesh } from \"./useMesh\";\nimport { useCamera } from \"../../../utils/useCamera\";\nimport { RootState } from \"@react-three/fiber\";\nimport { useSingleFBO } from \"../../../utils/useSingleFBO\";\nimport { usePointer, PointerValues } from \"../../../misc/usePointer\";\nimport { HooksProps, HooksReturn } from \"../../types\";\nimport { useParams } from \"../../../utils/useParams\";\nimport { getDpr } from \"../../../utils/getDpr\";\nimport {\n CustomParams,\n setCustomUniform,\n setUniform,\n} from \"../../../utils/setUniforms\";\n\nexport type RippleParams = {\n /** How often ripples appear, default : `0.01` */\n frequency?: number;\n /** rotation rate, default : `0.05` */\n rotation?: number;\n /** fadeout speed, default : `0.9` */\n fadeoutSpeed?: number;\n /** scale rate, default : `0.3` */\n scale?: number;\n /** alpha, default : `0.6` */\n alpha?: number;\n /** When calling usePointer in a frame loop, setting PointerValues ​​to this value prevents double calls , default : `false` */\n pointerValues?: PointerValues | false;\n};\n\nexport type RippleObject = {\n scene: THREE.Scene;\n meshArr: THREE.Mesh[];\n camera: THREE.Camera;\n renderTarget: THREE.WebGLRenderTarget;\n output: THREE.Texture;\n};\n\nexport const RIPPLE_PARAMS: RippleParams = Object.freeze({\n frequency: 0.01,\n rotation: 0.05,\n fadeoutSpeed: 0.9,\n scale: 0.3,\n alpha: 0.6,\n pointerValues: false,\n});\n\ninterface UseRippleProps extends HooksProps {\n /** texture applied to ripple */\n texture?: THREE.Texture;\n /** ripple size, default:64 */\n scale?: number;\n /** ripple max length, default:100 */\n max?: number;\n}\n\n/**\n * @link https://github.com/FunTechInc/use-shader-fx?tab=readme-ov-file#usage\n */\nexport const useRipple = ({\n texture,\n scale = 64,\n max = 100,\n size,\n dpr,\n renderTargetOptions,\n isSizeUpdate,\n onBeforeInit,\n}: UseRippleProps): HooksReturn => {\n const _dpr = getDpr(dpr);\n const scene = useMemo(() => new THREE.Scene(), []);\n const meshArr = useMesh({\n scale: scale,\n max: max,\n texture,\n scene,\n onBeforeInit,\n });\n const camera = useCamera(size);\n const updatePointer = usePointer();\n const [renderTarget, updateRenderTarget] = useSingleFBO({\n scene,\n camera,\n size,\n dpr: _dpr.fbo,\n isSizeUpdate,\n ...renderTargetOptions,\n });\n\n const [params, setParams] = useParams(RIPPLE_PARAMS);\n\n const currentWave = useRef(0);\n\n const updateParams = useMemo(() => {\n return (newParams?: RippleParams, customParams?: CustomParams) => {\n setParams(newParams);\n meshArr.forEach((mesh) => {\n if (mesh.visible) {\n const material = mesh.material as THREE.ShaderMaterial;\n mesh.rotation.z += params.rotation!;\n mesh.scale.x =\n params.fadeoutSpeed! * mesh.scale.x + params.scale!;\n mesh.scale.y = mesh.scale.x;\n const opacity = material.uniforms.uOpacity.value;\n setUniform(material)(\"uOpacity\", opacity * params.fadeoutSpeed!);\n if (opacity < 0.001) mesh.visible = false;\n }\n setCustomUniform(mesh.material)(customParams);\n });\n };\n }, [meshArr, params, setParams]);\n\n const updateFx = useCallback(\n (\n rootState: RootState,\n newParams?: RippleParams,\n customParams?: CustomParams\n ) => {\n const { gl, pointer, size } = rootState;\n\n updateParams(newParams, customParams);\n\n const pointerValues = params.pointerValues! || updatePointer(pointer);\n\n if (params.frequency! < pointerValues.diffPointer.length()) {\n const mesh = meshArr[currentWave.current];\n const material = mesh.material as THREE.ShaderMaterial;\n mesh.visible = true;\n mesh.position.set(\n pointerValues.currentPointer.x * (size.width / 2),\n pointerValues.currentPointer.y * (size.height / 2),\n 0\n );\n mesh.scale.x = mesh.scale.y = 0.0;\n setUniform(material)(\"uOpacity\", params.alpha!);\n currentWave.current = (currentWave.current + 1) % max;\n }\n\n return updateRenderTarget(gl);\n },\n [updateRenderTarget, meshArr, updatePointer, max, params, updateParams]\n );\n return [\n updateFx,\n updateParams,\n {\n scene: scene,\n camera: camera,\n meshArr: meshArr,\n renderTarget: renderTarget,\n output: renderTarget.texture,\n },\n ];\n};\n","#usf ","precision highp float;\nprecision highp int;\n\nvarying vec2 vUv;\nuniform float uTime;\nuniform float timeStrength;\nuniform int noiseOctaves;\nuniform int fbmOctaves;\nuniform int warpOctaves;\nuniform vec2 warpDirection;\nuniform float warpStrength;\nuniform float scale;\n\nconst float per = 0.5;\nconst float PI = 3.14159265359;\n\nfloat rnd(vec2 n) {\n\tfloat a = 0.129898;\n\tfloat b = 0.78233;\n\tfloat c = 437.585453;\n\tfloat dt= dot(n ,vec2(a, b));\n\tfloat sn= mod(dt, PI);\n\treturn fract(sin(sn) * c);\n}\n\nfloat interpolate(float a, float b, float x){\n float f = (1.0 - cos(x * PI)) * 0.5;\n return a * (1.0 - f) + b * f;\n}\n\nfloat irnd(vec2 p){\n\tvec2 i = floor(p);\n\tvec2 f = fract(p);\n\tvec4 v = vec4(rnd(vec2(i.x,i.y)),rnd(vec2(i.x + 1.0,i.y)),rnd(vec2(i.x,i.y + 1.0)),rnd(vec2(i.x + 1.0, i.y + 1.0)));\n\treturn interpolate(interpolate(v.x, v.y, f.x), interpolate(v.z, v.w, f.x), f.y);\n}\n\n// Based on The Book of Shaders\n// https://thebookofshaders.com/13/\nfloat noise(vec2 p, float time){\n\tfloat t = 0.0;\n\tfor(int i = 0; i < noiseOctaves; i++){\n\t\tfloat freq = pow(2.0, float(i));\n\t\tfloat amp = pow(per, float(noiseOctaves - i));\n\t\tt += irnd(vec2(p.y / freq + time, p.x / freq + time)) * amp;\n\t}\n\treturn t;\n}\n\nfloat fbm(vec2 x, float time) {\n\tfloat v = 0.0;\n\tfloat a = 0.5;\n\tvec2 shift = vec2(100);\n\tmat2 rot = mat2(cos(0.5), sin(0.5), -sin(0.5), cos(0.5));\n\tfloat sign = 1.0;\n\tfor (int i = 0; i < fbmOctaves; ++i) {\n\t\tv += a * noise(x, time * sign);\n\t\tx = rot * x * 2.0 + shift;\n\t\ta *= 0.5;\n\t\tsign *= -1.0;\n\t}\n\treturn v;\n}\n\nfloat warp(vec2 x, float g,float time){\n\tfloat val = 0.0;\n\tfor (int i = 0; i < warpOctaves; i++){\n\t\tval = fbm(x + g * vec2(cos(warpDirection.x * val), sin(warpDirection.y * val)), time);\n\t}\n\treturn val;\n}\n\nvoid main() {\n\tfloat noise = warp(gl_FragCoord.xy * scale ,warpStrength,uTime * timeStrength);\n\tgl_FragColor = vec4(vec3(noise),1.0);\n}","import { useMemo } from \"react\";\nimport * as THREE from \"three\";\nimport vertexShader from \"./shader/main.vert\";\nimport fragmentShader from \"./shader/main.frag\";\nimport { useAddObject } from \"../../../utils/useAddObject\";\nimport { MaterialProps } from \"../../types\";\nimport { MATERIAL_BASIC_PARAMS } from \"../../../libs/constants\";\nimport { NOISE_PARAMS } from \".\";\nimport { createMaterialParameters } from \"../../../utils/createMaterialParameters\";\n\nexport class NoiseMaterial extends THREE.ShaderMaterial {\n uniforms!: {\n uTime: { value: number };\n scale: { value: number };\n timeStrength: { value: number };\n noiseOctaves: { value: number };\n fbmOctaves: { value: number };\n warpOctaves: { value: number };\n warpDirection: { value: THREE.Vector2 };\n warpStrength: { value: number };\n };\n}\n\nexport const useMesh = ({\n scene,\n onBeforeInit,\n}: { scene: THREE.Scene } & MaterialProps) => {\n const geometry = useMemo(() => new THREE.PlaneGeometry(2, 2), []);\n const material = useMemo(() => {\n const mat = new THREE.ShaderMaterial({\n ...createMaterialParameters(\n {\n uniforms: {\n uTime: { value: 0.0 },\n scale: { value: NOISE_PARAMS.scale },\n timeStrength: { value: NOISE_PARAMS.timeStrength },\n noiseOctaves: { value: NOISE_PARAMS.noiseOctaves },\n fbmOctaves: { value: NOISE_PARAMS.fbmOctaves },\n warpOctaves: { value: NOISE_PARAMS.warpOctaves },\n warpDirection: { value: NOISE_PARAMS.warpDirection },\n warpStrength: { value: NOISE_PARAMS.warpStrength },\n },\n vertexShader: vertexShader,\n fragmentShader: fragmentShader,\n },\n onBeforeInit\n ),\n ...MATERIAL_BASIC_PARAMS,\n });\n return mat;\n }, [onBeforeInit]) as NoiseMaterial;\n const mesh = useAddObject(scene, geometry, material, THREE.Mesh);\n return { material, mesh };\n};\n","import { useCallback, useMemo } from \"react\";\nimport * as THREE from \"three\";\nimport { useMesh } from \"./useMesh\";\nimport { RootState } from \"@react-three/fiber\";\nimport { useCamera } from \"../../../utils/useCamera\";\nimport { useSingleFBO } from \"../../../utils/useSingleFBO\";\nimport {\n CustomParams,\n setCustomUniform,\n setUniform,\n} from \"../../../utils/setUniforms\";\nimport { useParams } from \"../../../utils/useParams\";\nimport { HooksProps, HooksReturn } from \"../../types\";\nimport { getDpr } from \"../../../utils/getDpr\";\n\nexport type NoiseParams = {\n /** noise scale , default : `0.004` */\n scale?: number;\n /** time factor default : `0.3` */\n timeStrength?: number;\n /** noiseOctaves, affects performance default : `2` */\n noiseOctaves?: number;\n /** fbmOctaves, affects performance default : `2` */\n fbmOctaves?: number;\n /** domain warping octaves , affects performance default : `2` */\n warpOctaves?: number;\n /** direction of domain warping , default : `(2.0,2,0)` */\n warpDirection?: THREE.Vector2;\n /** strength of domain warping , default : `8.0` */\n warpStrength?: number;\n /** you can get into the rhythm ♪ , default : `false` */\n beat?: number | false;\n};\n\nexport type NoiseObject = {\n scene: THREE.Scene;\n mesh: THREE.Mesh;\n material: THREE.Material;\n camera: THREE.Camera;\n renderTarget: THREE.WebGLRenderTarget;\n output: THREE.Texture;\n};\n\nexport const NOISE_PARAMS: NoiseParams = Object.freeze({\n scale: 0.004,\n timeStrength: 0.3,\n noiseOctaves: 2,\n fbmOctaves: 2,\n warpOctaves: 2,\n warpDirection: new THREE.Vector2(2.0, 2.0),\n warpStrength: 8.0,\n beat: false,\n});\n\n/**\n * @link https://github.com/FunTechInc/use-shader-fx?tab=readme-ov-file#usage\n *\n * It is a basic value noise with `fbm` and `domain warping`\n */\nexport const useNoise = ({\n size,\n dpr,\n renderTargetOptions,\n isSizeUpdate,\n onBeforeInit,\n}: HooksProps): HooksReturn => {\n const _dpr = getDpr(dpr);\n\n const scene = useMemo(() => new THREE.Scene(), []);\n const { material, mesh } = useMesh({ scene, onBeforeInit });\n const camera = useCamera(size);\n const [renderTarget, updateRenderTarget] = useSingleFBO({\n scene,\n camera,\n size,\n dpr: _dpr.fbo,\n isSizeUpdate,\n ...renderTargetOptions,\n });\n\n const [params, setParams] = useParams(NOISE_PARAMS);\n\n const updateValue = setUniform(material);\n const updateCustomValue = setCustomUniform(material);\n\n const updateParams = useCallback(\n (newParams?: NoiseParams, customParams?: CustomParams) => {\n setParams(newParams);\n updateCustomValue(customParams);\n },\n [setParams, updateCustomValue]\n );\n\n const updateFx = useCallback(\n (\n rootState: RootState,\n newParams?: NoiseParams,\n customParams?: CustomParams\n ) => {\n const { gl, clock } = rootState;\n\n updateParams(newParams, customParams);\n\n updateValue(\"scale\", params.scale!);\n updateValue(\"timeStrength\", params.timeStrength!);\n updateValue(\"noiseOctaves\", params.noiseOctaves!);\n updateValue(\"fbmOctaves\", params.fbmOctaves!);\n updateValue(\"warpOctaves\", params.warpOctaves!);\n updateValue(\"warpDirection\", params.warpDirection!);\n updateValue(\"warpStrength\", params.warpStrength!);\n updateValue(\"uTime\", params.beat || clock.getElapsedTime());\n\n return updateRenderTarget(gl);\n },\n [updateRenderTarget, updateValue, params, updateParams]\n );\n\n return [\n updateFx,\n updateParams,\n {\n scene: scene,\n mesh: mesh,\n material: material,\n camera: camera,\n renderTarget: renderTarget,\n output: renderTarget.texture,\n },\n ];\n};\n","#usf ","precision highp float;\nvarying vec2 vUv;\n\nuniform sampler2D uTexture;\nuniform bool isTexture;\nuniform sampler2D noise;\nuniform bool isNoise;\nuniform vec2 noiseStrength;\nuniform float laminateLayer;\nuniform vec2 laminateInterval;\nuniform vec2 laminateDetail;\nuniform vec2 distortion;\nuniform vec3 colorFactor;\nuniform float uTime;\nuniform vec2 timeStrength;\nuniform float scale;\n\nvoid main() {\n\tvec2 uv = vUv;\n\n\tvec2 pos = isTexture ? texture2D(uTexture, uv).rg : uv * scale;\n\tvec2 noise = isNoise ? texture2D(noise, uv).rg : vec2(0.0);\n\tfloat alpha = isTexture ? texture2D(uTexture, uv).a : 1.0;\n\t\n\t// Avoid floating point bugs caused by GPU drivers.\n\talpha = (alpha < 1e-10) ? 0.0 : alpha;\n\n\tvec3 col;\n\tfor(float j = 0.0; j < 3.0; j++){\n\t\tfor(float i = 1.0; i < laminateLayer; i++){\n\t\t\tfloat timeNoiseSin = sin(uTime / (i + j)) * timeStrength.x + noise.r * noiseStrength.x;\n\t\t\tfloat timeNoiseCos = cos(uTime / (i + j)) * timeStrength.y + noise.g * noiseStrength.y;\n\t\t\tpos.x += laminateInterval.x / (i + j) * cos(i * distortion.x * pos.y + timeNoiseSin + sin(i + j));\n\t\t\tpos.y += laminateInterval.y / (i + j) * cos(i * distortion.y * pos.x + timeNoiseCos + sin(i + j));\n\t\t}\n\t\tcol[int(j)] = sin(pow(pos.x, 2.) * pow(laminateDetail.x, 2.)) + sin(pow(pos.y, 2.) * pow(laminateDetail.y, 2.));\n\t}\n\n\tcol *= colorFactor * alpha;\n\tcol = clamp(col, 0.0, 1.0);\n\t\n\tgl_FragColor = vec4(col, alpha);\n}","import { useMemo } from \"react\";\nimport * as THREE from \"three\";\nimport vertexShader from \"./shader/main.vert\";\nimport fragmentShader from \"./shader/main.frag\";\nimport { useAddObject } from \"../../../utils/useAddObject\";\nimport { MaterialProps } from \"../../types\";\nimport {\n MATERIAL_BASIC_PARAMS,\n DEFAULT_TEXTURE,\n} from \"../../../libs/constants\";\nimport { COLORSTRATA_PARAMS } from \".\";\nimport { createMaterialParameters } from \"../../../utils/createMaterialParameters\";\n\nexport class ColorStrataMaterial extends THREE.ShaderMaterial {\n uniforms!: {\n uTexture: { value: THREE.Texture };\n isTexture: { value: boolean };\n scale: { value: number };\n noise: { value: THREE.Texture };\n noiseStrength: { value: THREE.Vector2 };\n isNoise: { value: boolean };\n laminateLayer: { value: number };\n laminateInterval: { value: THREE.Vector2 };\n laminateDetail: { value: THREE.Vector2 };\n distortion: { value: THREE.Vector2 };\n colorFactor: { value: THREE.Vector3 };\n uTime: { value: number };\n timeStrength: { value: THREE.Vector2 };\n };\n}\n\nexport const useMesh = ({\n scene,\n onBeforeInit,\n}: { scene: THREE.Scene } & MaterialProps) => {\n const geometry = useMemo(() => new THREE.PlaneGeometry(2, 2), []);\n const material = useMemo(() => {\n const mat = new THREE.ShaderMaterial({\n ...createMaterialParameters(\n {\n uniforms: {\n uTexture: { value: DEFAULT_TEXTURE },\n isTexture: { value: false },\n scale: { value: COLORSTRATA_PARAMS.scale },\n noise: { value: DEFAULT_TEXTURE },\n noiseStrength: { value: COLORSTRATA_PARAMS.noiseStrength },\n isNoise: { value: false },\n laminateLayer: { value: COLORSTRATA_PARAMS.laminateLayer },\n laminateInterval: {\n value: COLORSTRATA_PARAMS.laminateInterval,\n },\n laminateDetail: { value: COLORSTRATA_PARAMS.laminateDetail },\n distortion: { value: COLORSTRATA_PARAMS.distortion },\n colorFactor: { value: COLORSTRATA_PARAMS.colorFactor },\n uTime: { value: 0 },\n timeStrength: { value: COLORSTRATA_PARAMS.timeStrength },\n },\n vertexShader: vertexShader,\n fragmentShader: fragmentShader,\n },\n onBeforeInit\n ),\n ...MATERIAL_BASIC_PARAMS,\n });\n\n return mat;\n }, [onBeforeInit]) as ColorStrataMaterial;\n\n const mesh = useAddObject(scene, geometry, material, THREE.Mesh);\n\n return { material, mesh };\n};\n","import { useCallback, useMemo } from \"react\";\nimport * as THREE from \"three\";\nimport { useMesh } from \"./useMesh\";\nimport { useCamera } from \"../../../utils/useCamera\";\nimport { RootState } from \"@react-three/fiber\";\nimport { useSingleFBO } from \"../../../utils/useSingleFBO\";\nimport {\n CustomParams,\n setCustomUniform,\n setUniform,\n} from \"../../../utils/setUniforms\";\nimport { HooksProps, HooksReturn } from \"../../types\";\nimport { useParams } from \"../../../utils/useParams\";\nimport { getDpr } from \"../../../utils/getDpr\";\n\nexport type ColorStrataParams = {\n /** default : `null` */\n texture?: THREE.Texture | false;\n /** Valid when texture is false. default : `1` */\n scale?: number;\n /** default : `1.0` */\n laminateLayer?: number;\n /** default : `(0.1, 0.1)` */\n laminateInterval?: THREE.Vector2;\n /** default : `(1.0, 1.0)` */\n laminateDetail?: THREE.Vector2;\n /** default : `(0.0, 0.0)` */\n distortion?: THREE.Vector2;\n /** default : `(1.0, 1.0, 1.0)` */\n colorFactor?: THREE.Vector3;\n /** default : `(0.0, 0.0)` */\n timeStrength?: THREE.Vector2;\n /** default : `false` */\n noise?: THREE.Texture | false;\n /** default : `(0.0,0.0)` */\n noiseStrength?: THREE.Vector2;\n /** you can get into the rhythm ♪ , default : `false` */\n beat?: number | false;\n};\n\nexport type ColorStrataObject = {\n scene: THREE.Scene;\n mesh: THREE.Mesh;\n material: THREE.Material;\n camera: THREE.Camera;\n renderTarget: THREE.WebGLRenderTarget;\n output: THREE.Texture;\n};\n\nexport const COLORSTRATA_PARAMS: ColorStrataParams = Object.freeze({\n texture: false,\n scale: 1.0,\n laminateLayer: 1.0,\n laminateInterval: new THREE.Vector2(0.1, 0.1),\n laminateDetail: new THREE.Vector2(1, 1),\n distortion: new THREE.Vector2(0, 0),\n colorFactor: new THREE.Vector3(1, 1, 1),\n timeStrength: new THREE.Vector2(0, 0),\n noise: false,\n noiseStrength: new THREE.Vector2(0, 0),\n beat: false,\n});\n\n/**\n * @link https://github.com/FunTechInc/use-shader-fx?tab=readme-ov-file#usage\n */\nexport const useColorStrata = ({\n size,\n dpr,\n renderTargetOptions,\n isSizeUpdate,\n onBeforeInit,\n}: HooksProps): HooksReturn<\n ColorStrataParams,\n ColorStrataObject,\n CustomParams\n> => {\n const _dpr = getDpr(dpr);\n\n const scene = useMemo(() => new THREE.Scene(), []);\n const { material, mesh } = useMesh({ scene, onBeforeInit });\n const camera = useCamera(size);\n const [renderTarget, updateRenderTarget] = useSingleFBO({\n scene,\n camera,\n size,\n dpr: _dpr.fbo,\n isSizeUpdate,\n ...renderTargetOptions,\n });\n\n const [params, setParams] = useParams(COLORSTRATA_PARAMS);\n\n const updateValue = setUniform(material);\n const updateCustomValue = setCustomUniform(material);\n\n const updateParams = useCallback(\n (newParams?: ColorStrataParams, customParams?: CustomParams) => {\n setParams(newParams);\n updateCustomValue(customParams);\n },\n [setParams, updateCustomValue]\n );\n\n const updateFx = useCallback(\n (\n rootState: RootState,\n newParams?: ColorStrataParams,\n customParams?: CustomParams\n ) => {\n const { gl, clock } = rootState;\n\n updateParams(newParams, customParams);\n\n if (params.texture) {\n updateValue(\"uTexture\", params.texture);\n updateValue(\"isTexture\", true);\n } else {\n updateValue(\"isTexture\", false);\n updateValue(\"scale\", params.scale!);\n }\n\n if (params.noise) {\n updateValue(\"noise\", params.noise);\n updateValue(\"isNoise\", true);\n updateValue(\"noiseStrength\", params.noiseStrength!);\n } else {\n updateValue(\"isNoise\", false);\n }\n\n updateValue(\"uTime\", params.beat || clock.getElapsedTime());\n\n updateValue(\"laminateLayer\", params.laminateLayer!);\n updateValue(\"laminateInterval\", params.laminateInterval!);\n updateValue(\"laminateDetail\", params.laminateDetail!);\n updateValue(\"distortion\", params.distortion!);\n updateValue(\"colorFactor\", params.colorFactor!);\n updateValue(\"timeStrength\", params.timeStrength!);\n\n return updateRenderTarget(gl);\n },\n [updateRenderTarget, updateValue, params, updateParams]\n );\n\n return [\n updateFx,\n updateParams,\n {\n scene: scene,\n mesh: mesh,\n material: material,\n camera: camera,\n renderTarget: renderTarget,\n output: renderTarget.texture,\n },\n ];\n};\n","#usf ","precision highp float;\n\nvarying vec2 vUv;\nuniform float u_time;\nuniform float u_pattern;\nuniform float u_complexity;\nuniform float u_complexityAttenuation;\nuniform float u_iterations;\nuniform float u_timeStrength;\nuniform float u_scale;\n\nvec3 marble(vec3 p){\n\tvec4 n;\n\tfor(float i;i {\n const geometry = useMemo(() => new THREE.PlaneGeometry(2, 2), []);\n const material = useMemo(() => {\n const mat = new THREE.ShaderMaterial({\n ...createMaterialParameters(\n {\n uniforms: {\n u_time: { value: 0 },\n u_pattern: { value: MARBLE_PARAMS.pattern },\n u_complexity: { value: MARBLE_PARAMS.complexity },\n u_complexityAttenuation: {\n value: MARBLE_PARAMS.complexityAttenuation,\n },\n u_iterations: { value: MARBLE_PARAMS.iterations },\n u_timeStrength: { value: MARBLE_PARAMS.timeStrength },\n u_scale: { value: MARBLE_PARAMS.scale },\n },\n vertexShader: vertexShader,\n fragmentShader: fragmentShader,\n },\n onBeforeInit\n ),\n ...MATERIAL_BASIC_PARAMS,\n });\n\n return mat;\n }, [onBeforeInit]) as MarbleMaterial;\n const mesh = useAddObject(scene, geometry, material, THREE.Mesh);\n return { material, mesh };\n};\n","import { useCallback, useMemo } from \"react\";\nimport * as THREE from \"three\";\nimport { useMesh } from \"./useMesh\";\nimport { useCamera } from \"../../../utils/useCamera\";\nimport { RootState } from \"@react-three/fiber\";\nimport { useSingleFBO } from \"../../../utils/useSingleFBO\";\nimport {\n CustomParams,\n setCustomUniform,\n setUniform,\n} from \"../../../utils/setUniforms\";\nimport { HooksProps, HooksReturn } from \"../../types\";\nimport { useParams } from \"../../../utils/useParams\";\nimport { getDpr } from \"../../../utils/getDpr\";\n\nexport type MarbleParams = {\n /** You can add random patterns to noise by passing random numbers ,default : `0` */\n pattern?: number;\n /** default : `2` */\n complexity?: number;\n /** default : `0.2` */\n complexityAttenuation?: number;\n /** default : `8` */\n iterations?: number;\n /** default : `0.2` */\n timeStrength?: number;\n /** default : `0.002` */\n scale?: number;\n /** you can get into the rhythm ♪ , default : `false` */\n beat?: number | false;\n};\n\nexport type MarbleObject = {\n scene: THREE.Scene;\n mesh: THREE.Mesh;\n material: THREE.Material;\n camera: THREE.Camera;\n renderTarget: THREE.WebGLRenderTarget;\n output: THREE.Texture;\n};\n\nexport const MARBLE_PARAMS: MarbleParams = Object.freeze({\n pattern: 0,\n complexity: 2,\n complexityAttenuation: 0.2,\n iterations: 8,\n timeStrength: 0.2,\n scale: 0.002,\n beat: false,\n});\n\n/**\n * @link https://github.com/FunTechInc/use-shader-fx?tab=readme-ov-file#usage\n */\nexport const useMarble = ({\n size,\n dpr,\n renderTargetOptions,\n isSizeUpdate,\n onBeforeInit,\n}: HooksProps): HooksReturn => {\n const _dpr = getDpr(dpr);\n const scene = useMemo(() => new THREE.Scene(), []);\n const { material, mesh } = useMesh({ scene, onBeforeInit });\n const camera = useCamera(size);\n const [renderTarget, updateRenderTarget] = useSingleFBO({\n scene,\n camera,\n size,\n dpr: _dpr.fbo,\n isSizeUpdate,\n ...renderTargetOptions,\n });\n\n const [params, setParams] = useParams(MARBLE_PARAMS);\n\n const updateValue = setUniform(material);\n const updateCustomValue = setCustomUniform(material);\n\n const updateParams = useCallback(\n (newParams?: MarbleParams, customParams?: CustomParams) => {\n setParams(newParams);\n updateCustomValue(customParams);\n },\n [setParams, updateCustomValue]\n );\n\n const updateFx = useCallback(\n (\n rootState: RootState,\n newParams?: MarbleParams,\n customParams?: CustomParams\n ) => {\n const { gl, clock } = rootState;\n\n updateParams(newParams, customParams);\n\n updateValue(\"u_pattern\", params.pattern!);\n updateValue(\"u_complexity\", params.complexity!);\n updateValue(\"u_complexityAttenuation\", params.complexityAttenuation!);\n updateValue(\"u_iterations\", params.iterations!);\n updateValue(\"u_timeStrength\", params.timeStrength!);\n updateValue(\"u_scale\", params.scale!);\n updateValue(\"u_time\", params.beat || clock.getElapsedTime());\n\n return updateRenderTarget(gl);\n },\n [updateRenderTarget, updateValue, params, updateParams]\n );\n\n return [\n updateFx,\n updateParams,\n {\n scene: scene,\n mesh: mesh,\n material: material,\n camera: camera,\n renderTarget: renderTarget,\n output: renderTarget.texture,\n },\n ];\n};\n","#usf ","precision highp float;\nprecision highp int;\n\nvarying vec2 vUv;\nuniform sampler2D uTexture;\nuniform vec3 uColor1;\nuniform vec3 uColor2;\nuniform vec3 uColor3;\nuniform vec3 uColor4;\nuniform vec3 uRgbWeight;\n\n\n// Based on glsl-cos-palette by Erkaman\n// https://github.com/Erkaman/glsl-cos-palette\nvec3 cosPalette( float t, vec3 color1, vec3 color2, vec3 color3, vec3 color4 ){\n return color1 + color2 * cos( 6.28318 * ( color3 * t + color4) );\n}\n\nvoid main() {\n\n\tvec4 tex = texture2D(uTexture, vUv);\n\tfloat gray = dot(tex.rgb, uRgbWeight);\t\t\n\n\tvec3 outColor = cosPalette(\n\t\tgray,\n\t\tuColor1,\n\t\tuColor2,\n\t\tuColor3,\n\t\tuColor4\n\t);\n\n\tgl_FragColor = vec4(outColor, tex.a);\n}","import { useMemo } from \"react\";\nimport * as THREE from \"three\";\nimport vertexShader from \"./shader/main.vert\";\nimport fragmentShader from \"./shader/main.frag\";\nimport { useAddObject } from \"../../../utils/useAddObject\";\nimport { MaterialProps } from \"../../types\";\nimport {\n MATERIAL_BASIC_PARAMS,\n DEFAULT_TEXTURE,\n} from \"../../../libs/constants\";\nimport { COSPALETTE_PARAMS } from \".\";\nimport { createMaterialParameters } from \"../../../utils/createMaterialParameters\";\n\nexport class CosPaletteMaterial extends THREE.ShaderMaterial {\n uniforms!: {\n uTexture: { value: THREE.Texture };\n uRgbWeight: { value: THREE.Vector3 };\n uColor1: { value: THREE.Color };\n uColor2: { value: THREE.Color };\n uColor3: { value: THREE.Color };\n uColor4: { value: THREE.Color };\n };\n}\n\nexport const useMesh = ({\n scene,\n onBeforeInit,\n}: { scene: THREE.Scene } & MaterialProps) => {\n const geometry = useMemo(() => new THREE.PlaneGeometry(2, 2), []);\n const material = useMemo(() => {\n const mat = new THREE.ShaderMaterial({\n ...createMaterialParameters(\n {\n uniforms: {\n uTexture: { value: DEFAULT_TEXTURE },\n uRgbWeight: { value: COSPALETTE_PARAMS.rgbWeight },\n uColor1: { value: COSPALETTE_PARAMS.color1 },\n uColor2: { value: COSPALETTE_PARAMS.color2 },\n uColor3: { value: COSPALETTE_PARAMS.color3 },\n uColor4: { value: COSPALETTE_PARAMS.color4 },\n },\n vertexShader: vertexShader,\n fragmentShader: fragmentShader,\n },\n onBeforeInit\n ),\n ...MATERIAL_BASIC_PARAMS,\n });\n\n return mat;\n }, [onBeforeInit]) as CosPaletteMaterial;\n const mesh = useAddObject(scene, geometry, material, THREE.Mesh);\n return { material, mesh };\n};\n","import { useCallback, useMemo } from \"react\";\nimport * as THREE from \"three\";\nimport { useMesh } from \"./useMesh\";\nimport { RootState } from \"@react-three/fiber\";\nimport { useCamera } from \"../../../utils/useCamera\";\nimport { useSingleFBO } from \"../../../utils/useSingleFBO\";\nimport {\n CustomParams,\n setCustomUniform,\n setUniform,\n} from \"../../../utils/setUniforms\";\nimport { useParams } from \"../../../utils/useParams\";\nimport { HooksProps, HooksReturn } from \"../../types\";\nimport { getDpr } from \"../../../utils/getDpr\";\nimport { DEFAULT_TEXTURE } from \"../../../libs/constants\";\n\nexport type CosPaletteParams = {\n /** color1, default : `rgb(50%, 50%, 50%)` */\n color1?: THREE.Color;\n /** color2, default : `rgb(50%, 50%, 50%)` */\n color2?: THREE.Color;\n /** color3, default : `rgb(100%, 100%, 100%)` */\n color3?: THREE.Color;\n /** color4, default : `rgb(0%, 10%, 20%)` */\n color4?: THREE.Color;\n /** texture to be used as a palette */\n texture?: THREE.Texture;\n /** weight of the rgb, default : `THREE.Vector3(1.0,0.0,0.0)` */\n rgbWeight?: THREE.Vector3;\n};\n\nexport type ColorPaletteObject = {\n scene: THREE.Scene;\n mesh: THREE.Mesh;\n material: THREE.Material;\n camera: THREE.Camera;\n renderTarget: THREE.WebGLRenderTarget;\n output: THREE.Texture;\n};\n\nexport const COSPALETTE_PARAMS: CosPaletteParams = Object.freeze({\n texture: DEFAULT_TEXTURE,\n color1: new THREE.Color().set(0.5, 0.5, 0.5),\n color2: new THREE.Color().set(0.5, 0.5, 0.5),\n color3: new THREE.Color().set(1, 1, 1),\n color4: new THREE.Color().set(0, 0.1, 0.2),\n rgbWeight: new THREE.Vector3(0.299, 0.587, 0.114),\n});\n\n/**\n * @link https://github.com/FunTechInc/use-shader-fx?tab=readme-ov-file#usage\n */\nexport const useCosPalette = ({\n size,\n dpr,\n renderTargetOptions,\n isSizeUpdate,\n onBeforeInit,\n}: HooksProps): HooksReturn<\n CosPaletteParams,\n ColorPaletteObject,\n CustomParams\n> => {\n const _dpr = getDpr(dpr);\n\n const scene = useMemo(() => new THREE.Scene(), []);\n const { material, mesh } = useMesh({ scene, onBeforeInit });\n const camera = useCamera(size);\n const [renderTarget, updateRenderTarget] = useSingleFBO({\n scene,\n camera,\n size,\n dpr: _dpr.fbo,\n isSizeUpdate,\n ...renderTargetOptions,\n });\n\n const [params, setParams] = useParams(COSPALETTE_PARAMS);\n\n const updateValue = setUniform(material);\n const updateCustomValue = setCustomUniform(material);\n\n const updateParams = useCallback(\n (newParams?: CosPaletteParams, customParams?: CustomParams) => {\n setParams(newParams);\n updateCustomValue(customParams);\n },\n [setParams, updateCustomValue]\n );\n\n const updateFx = useCallback(\n (\n rootState: RootState,\n newParams?: CosPaletteParams,\n customParams?: CustomParams\n ) => {\n const { gl } = rootState;\n\n updateParams(newParams, customParams);\n\n updateValue(\"uTexture\", params.texture!);\n updateValue(\"uColor1\", params.color1!);\n updateValue(\"uColor2\", params.color2!);\n updateValue(\"uColor3\", params.color3!);\n updateValue(\"uColor4\", params.color4!);\n updateValue(\"uRgbWeight\", params.rgbWeight!);\n\n return updateRenderTarget(gl);\n },\n [updateRenderTarget, updateValue, params, updateParams]\n );\n\n return [\n updateFx,\n updateParams,\n {\n scene: scene,\n mesh: mesh,\n material: material,\n camera: camera,\n renderTarget: renderTarget,\n output: renderTarget.texture,\n },\n ];\n};\n","#usf ","precision highp float;\n\nvarying vec2 vUv;\nuniform sampler2D uTexture;\n\nuniform vec3 uColor0;\nuniform vec3 uColor1;\n\nvoid main() {\n\tvec2 uv = vUv;\n\tvec4 texColor = texture2D(uTexture, uv);\n\tfloat grayscale = dot(texColor.rgb, vec3(0.299, 0.587, 0.114));\n\tvec3 duotone = mix(uColor0, uColor1, grayscale);\n\tgl_FragColor = vec4(duotone, texColor.a);\n}","import { useMemo } from \"react\";\nimport * as THREE from \"three\";\nimport vertexShader from \"./shader/main.vert\";\nimport fragmentShader from \"./shader/main.frag\";\nimport { useAddObject } from \"../../../utils/useAddObject\";\nimport { MaterialProps } from \"../../types\";\nimport {\n MATERIAL_BASIC_PARAMS,\n DEFAULT_TEXTURE,\n} from \"../../../libs/constants\";\nimport { DUOTONE_PARAMS } from \".\";\nimport { createMaterialParameters } from \"../../../utils/createMaterialParameters\";\n\nexport class DuoToneMaterial extends THREE.ShaderMaterial {\n uniforms!: {\n uTexture: { value: THREE.Texture };\n uColor0: { value: THREE.Color };\n uColor1: { value: THREE.Color };\n };\n}\n\nexport const useMesh = ({\n scene,\n onBeforeInit,\n}: { scene: THREE.Scene } & MaterialProps) => {\n const geometry = useMemo(() => new THREE.PlaneGeometry(2, 2), []);\n const material = useMemo(() => {\n const mat = new THREE.ShaderMaterial({\n ...createMaterialParameters(\n {\n uniforms: {\n uTexture: { value: DEFAULT_TEXTURE },\n uColor0: { value: DUOTONE_PARAMS.color0 },\n uColor1: { value: DUOTONE_PARAMS.color1 },\n },\n vertexShader: vertexShader,\n fragmentShader: fragmentShader,\n },\n onBeforeInit\n ),\n ...MATERIAL_BASIC_PARAMS,\n });\n return mat;\n }, [onBeforeInit]) as DuoToneMaterial;\n const mesh = useAddObject(scene, geometry, material, THREE.Mesh);\n return { material, mesh };\n};\n","import { useCallback, useMemo } from \"react\";\nimport * as THREE from \"three\";\nimport { DuoToneMaterial, useMesh } from \"./useMesh\";\nimport { useCamera } from \"../../../utils/useCamera\";\nimport { RootState } from \"@react-three/fiber\";\nimport { useSingleFBO } from \"../../../utils/useSingleFBO\";\nimport {\n CustomParams,\n setCustomUniform,\n setUniform,\n} from \"../../../utils/setUniforms\";\nimport { HooksProps, HooksReturn } from \"../../types\";\nimport { useParams } from \"../../../utils/useParams\";\nimport { getDpr } from \"../../../utils/getDpr\";\nimport { DEFAULT_TEXTURE } from \"../../../libs/constants\";\n\nexport type DuoToneParams = {\n /** Make this texture duotone , Default : `THREE.Texture()` */\n texture?: THREE.Texture;\n /** 1st color , Default : `THREE.Color(0xffffff)` */\n color0?: THREE.Color;\n /** 2nd color , Default : `THREE.Color(0x000000)` */\n color1?: THREE.Color;\n};\n\nexport type DuoToneObject = {\n scene: THREE.Scene;\n mesh: THREE.Mesh;\n material: DuoToneMaterial;\n camera: THREE.Camera;\n renderTarget: THREE.WebGLRenderTarget;\n output: THREE.Texture;\n};\n\nexport const DUOTONE_PARAMS: DuoToneParams = Object.freeze({\n texture: DEFAULT_TEXTURE,\n color0: new THREE.Color(0xffffff),\n color1: new THREE.Color(0x000000),\n});\n\n/**\n * @link https://github.com/FunTechInc/use-shader-fx?tab=readme-ov-file#usage\n */\nexport const useDuoTone = ({\n size,\n dpr,\n renderTargetOptions,\n isSizeUpdate,\n onBeforeInit,\n}: HooksProps): HooksReturn => {\n const _dpr = getDpr(dpr);\n\n const scene = useMemo(() => new THREE.Scene(), []);\n const { material, mesh } = useMesh({ scene, onBeforeInit });\n const camera = useCamera(size);\n const [renderTarget, updateRenderTarget] = useSingleFBO({\n scene,\n camera,\n size,\n dpr: _dpr.fbo,\n isSizeUpdate,\n ...renderTargetOptions,\n });\n\n const [params, setParams] = useParams(DUOTONE_PARAMS);\n\n const updateValue = setUniform(material);\n const updateCustomValue = setCustomUniform(material);\n\n const updateParams = useCallback(\n (newParams?: DuoToneParams, customParams?: CustomParams) => {\n setParams(newParams);\n updateCustomValue(customParams);\n },\n [setParams, updateCustomValue]\n );\n\n const updateFx = useCallback(\n (\n rootState: RootState,\n newParams?: DuoToneParams,\n customParams?: CustomParams\n ) => {\n const { gl } = rootState;\n\n updateParams(newParams, customParams);\n\n updateValue(\"uTexture\", params.texture!);\n updateValue(\"uColor0\", params.color0!);\n updateValue(\"uColor1\", params.color1!);\n\n return updateRenderTarget(gl);\n },\n [updateRenderTarget, updateValue, params, updateParams]\n );\n\n return [\n updateFx,\n updateParams,\n {\n scene: scene,\n mesh: mesh,\n material: material,\n camera: camera,\n renderTarget: renderTarget,\n output: renderTarget.texture,\n },\n ];\n};\n","#usf ","precision highp float;\n\nvarying vec2 vUv;\nuniform sampler2D u_texture;\nuniform sampler2D uMap;\nuniform bool u_isAlphaMap;\nuniform sampler2D u_alphaMap;\nuniform float uMapIntensity;\nuniform vec3 u_brightness;\nuniform float u_min;\nuniform float u_max;\nuniform vec3 u_dodgeColor;\nuniform bool u_isDodgeColor;\n\nvoid main() {\n\tvec2 uv = vUv;\n\n\t#usf \n\n\t// color blending\n\tfloat brightness = dot(mapColor,u_brightness);\n\tvec4 textureMap = texture2D(u_texture, uv);\n\tfloat blendValue = smoothstep(u_min, u_max, brightness);\n\n\t// set dodge color\n\tvec3 dodgeColor = u_isDodgeColor ? u_dodgeColor : mapColor;\n\tvec3 outputColor = blendValue * dodgeColor + (1.0 - blendValue) * textureMap.rgb;\n\t\n\t// alpha blending\n\tfloat alpha = u_isAlphaMap ? texture2D(u_alphaMap, uv).a : textureMap.a;\n\tfloat mixValue = u_isAlphaMap ? alpha : 0.0;\n\tvec3 alphaColor = vec3(mix(outputColor,mapColor,mixValue));\n\n\tgl_FragColor = vec4(alphaColor,alpha);\n}","import { useMemo } from \"react\";\nimport * as THREE from \"three\";\nimport vertexShader from \"./shader/main.vert\";\nimport fragmentShader from \"./shader/main.frag\";\nimport { useAddObject } from \"../../../utils/useAddObject\";\nimport { MaterialProps } from \"../../types\";\nimport {\n DEFAULT_TEXTURE,\n MATERIAL_BASIC_PARAMS,\n} from \"../../../libs/constants\";\nimport { BLENDING_PARAMS } from \".\";\nimport { createMaterialParameters } from \"../../../utils/createMaterialParameters\";\n\nexport class BlendingMaterial extends THREE.ShaderMaterial {\n uniforms!: {\n u_texture: { value: THREE.Texture };\n uMap: { value: THREE.Texture };\n u_alphaMap: { value: THREE.Texture };\n u_isAlphaMap: { value: boolean };\n uMapIntensity: { value: number };\n u_brightness: { value: THREE.Vector3 };\n u_min: { value: number };\n u_max: { value: number };\n u_dodgeColor: { value: THREE.Color };\n u_isDodgeColor: { value: boolean };\n };\n}\n\nexport const useMesh = ({\n scene,\n onBeforeInit,\n}: { scene: THREE.Scene } & MaterialProps) => {\n const geometry = useMemo(() => new THREE.PlaneGeometry(2, 2), []);\n const material = useMemo(() => {\n const mat = new THREE.ShaderMaterial({\n ...createMaterialParameters(\n {\n uniforms: {\n u_texture: { value: DEFAULT_TEXTURE },\n uMap: { value: DEFAULT_TEXTURE },\n u_alphaMap: { value: DEFAULT_TEXTURE },\n u_isAlphaMap: { value: false },\n uMapIntensity: { value: BLENDING_PARAMS.mapIntensity },\n u_brightness: { value: BLENDING_PARAMS.brightness },\n u_min: { value: BLENDING_PARAMS.min },\n u_max: { value: BLENDING_PARAMS.max },\n u_dodgeColor: { value: new THREE.Color() },\n u_isDodgeColor: { value: false },\n },\n vertexShader: vertexShader,\n fragmentShader: fragmentShader,\n },\n onBeforeInit\n ),\n ...MATERIAL_BASIC_PARAMS,\n });\n\n return mat;\n }, [onBeforeInit]) as BlendingMaterial;\n const mesh = useAddObject(scene, geometry, material, THREE.Mesh);\n return { material, mesh };\n};\n","import { useCallback, useMemo } from \"react\";\nimport * as THREE from \"three\";\nimport { useMesh } from \"./useMesh\";\nimport { useCamera } from \"../../../utils/useCamera\";\nimport { RootState } from \"@react-three/fiber\";\nimport { useSingleFBO } from \"../../../utils/useSingleFBO\";\nimport {\n CustomParams,\n setCustomUniform,\n setUniform,\n} from \"../../../utils/setUniforms\";\nimport { HooksProps, HooksReturn } from \"../../types\";\nimport { useParams } from \"../../../utils/useParams\";\nimport { getDpr } from \"../../../utils/getDpr\";\nimport { DEFAULT_TEXTURE } from \"../../../libs/constants\";\n\nexport type BlendingParams = {\n /** Make this texture Blending , default : `THREE.Texture` */\n texture?: THREE.Texture;\n /** map texture, default : `THREE.Texture` */\n map?: THREE.Texture;\n /** map strength , r,g value are affecting , default : `0.3` */\n mapIntensity?: number;\n /** Alpha blending is performed using the alpha of the set texture. , default : `false` */\n alphaMap?: THREE.Texture | false;\n /** default : `(0.5,0.5,0.5)` */\n brightness?: THREE.Vector3;\n /** default : `0.0` */\n min?: number;\n /** default : `1.0` */\n max?: number;\n /** If set, this value will apply color dodge , default : `false` */\n dodgeColor?: THREE.Color | false;\n};\n\nexport type BlendingObject = {\n scene: THREE.Scene;\n mesh: THREE.Mesh;\n material: THREE.Material;\n camera: THREE.Camera;\n renderTarget: THREE.WebGLRenderTarget;\n output: THREE.Texture;\n};\n\nexport const BLENDING_PARAMS: BlendingParams = Object.freeze({\n texture: DEFAULT_TEXTURE,\n map: DEFAULT_TEXTURE,\n alphaMap: false,\n mapIntensity: 0.3,\n brightness: new THREE.Vector3(0.5, 0.5, 0.5),\n min: 0.0,\n max: 1.0,\n dodgeColor: false,\n});\n\n/**\n * Blend map to texture. You can set the threshold for blending with brightness. You can set the dodge color by setting color. \nIf you don't want to reflect the map's color, you can use useFxBlending instead.\n * @link https://github.com/FunTechInc/use-shader-fx?tab=readme-ov-file#usage\n */\nexport const useBlending = ({\n size,\n dpr,\n renderTargetOptions,\n isSizeUpdate,\n onBeforeInit,\n}: HooksProps): HooksReturn => {\n const _dpr = getDpr(dpr);\n\n const scene = useMemo(() => new THREE.Scene(), []);\n const { material, mesh } = useMesh({ scene, onBeforeInit });\n const camera = useCamera(size);\n const [renderTarget, updateRenderTarget] = useSingleFBO({\n scene,\n camera,\n size,\n dpr: _dpr.fbo,\n isSizeUpdate,\n ...renderTargetOptions,\n });\n\n const [params, setParams] = useParams(BLENDING_PARAMS);\n\n const updateValue = setUniform(material);\n const updateCustomValue = setCustomUniform(material);\n\n const updateParams = useCallback(\n (newParams?: BlendingParams, customParams?: CustomParams) => {\n setParams(newParams);\n updateCustomValue(customParams);\n },\n [setParams, updateCustomValue]\n );\n\n const updateFx = useCallback(\n (\n rootState: RootState,\n newParams?: BlendingParams,\n customParams?: CustomParams\n ) => {\n const { gl } = rootState;\n\n updateParams(newParams, customParams);\n\n updateValue(\"u_texture\", params.texture!);\n updateValue(\"uMap\", params.map!);\n updateValue(\"uMapIntensity\", params.mapIntensity!);\n if (params.alphaMap) {\n updateValue(\"u_alphaMap\", params.alphaMap!);\n updateValue(\"u_isAlphaMap\", true);\n } else {\n updateValue(\"u_isAlphaMap\", false);\n }\n updateValue(\"u_brightness\", params.brightness!);\n updateValue(\"u_min\", params.min!);\n updateValue(\"u_max\", params.max!);\n if (params.dodgeColor) {\n updateValue(\"u_dodgeColor\", params.dodgeColor);\n updateValue(\"u_isDodgeColor\", true);\n } else {\n updateValue(\"u_isDodgeColor\", false);\n }\n\n return updateRenderTarget(gl);\n },\n [updateRenderTarget, updateValue, params, updateParams]\n );\n\n return [\n updateFx,\n updateParams,\n {\n scene: scene,\n mesh: mesh,\n material: material,\n camera: camera,\n renderTarget: renderTarget,\n output: renderTarget.texture,\n },\n ];\n};\n","#usf ","precision highp float;\n\nvarying vec2 vUv;\nuniform vec2 uResolution;\nuniform vec2 uTextureResolution;\nuniform sampler2D uTexture0;\nuniform sampler2D uTexture1;\nuniform sampler2D uMap;\nuniform float mapIntensity;\nuniform float edgeIntensity;\nuniform float progress;\nuniform float dirX;\nuniform float dirY;\nuniform vec2 epicenter;\nuniform float padding;\n\nbool isInPaddingArea(vec2 uv) {\n return uv.x < padding || uv.x > 1.0 - padding || uv.y < padding || uv.y > 1.0 - padding;\n}\n\nvoid main() {\n\t#usf \n\n\t// fx map\n\tvec2 map = texture2D(uMap, uv).rg;\n\tvec2 normalizedMap = map * 2.0 - 1.0;\n\n\t// multiply edge fx\n\tuv = uv * 2.0 - 1.0;\n\tuv *= map * distance(epicenter, uv) * edgeIntensity + 1.0;\n\tuv = (uv + 1.0) / 2.0;\n\n\t// padding\n\tif (isInPaddingArea(uv)) {\n\t\tgl_FragColor = vec4(0.0, 0.0, 0.0, 0.0);\n\t\treturn;\n\t}\n\tvec2 paddedUV = uv * (1.0 - 2.0 * padding * -1.) + padding * -1.;\n\n\t// centered uv\n\tvec2 centeredUV = paddedUV - vec2(0.5);\n\n\t// multiply map fx\n\tcenteredUV *= normalizedMap * map * mapIntensity + 1.0;\n\n\t// texture 0\n\tfloat xOffsetTexture0 = 0.5 - dirX * progress;\n\tfloat yOffsetTexture0 = 0.5 - dirY * progress;\n\tvec2 samplePosTexture0 = vec2(xOffsetTexture0, yOffsetTexture0) + centeredUV;\n\n\t//texture 1\n\tfloat xOffsetTexture1 = 0.5 + dirX * (1.0 - progress);\n\tfloat yOffsetTexture1 = 0.5 + dirY * (1.0 - progress);\n\tvec2 samplePosTexture1 = vec2(xOffsetTexture1, yOffsetTexture1) + centeredUV;\n\n\tvec4 color0 = texture2D(uTexture0, samplePosTexture0);\n\tvec4 color1 = texture2D(uTexture1, samplePosTexture1);\n\n\tgl_FragColor = mix(color0, color1, progress);\n\n}","import { useMemo } from \"react\";\nimport * as THREE from \"three\";\nimport { useResolution } from \"../../../utils/useResolution\";\nimport vertexShader from \"./shader/main.vert\";\nimport fragmentShader from \"./shader/main.frag\";\nimport { setUniform } from \"../../../utils/setUniforms\";\nimport { useAddObject } from \"../../../utils/useAddObject\";\nimport { MaterialProps, Size } from \"../../types\";\nimport {\n MATERIAL_BASIC_PARAMS,\n DEFAULT_TEXTURE,\n} from \"../../../libs/constants\";\nimport { FXTEXTURE_PARAMS } from \".\";\nimport { createMaterialParameters } from \"../../../utils/createMaterialParameters\";\n\nexport class FxTextureMaterial extends THREE.ShaderMaterial {\n uniforms!: {\n uResolution: { value: THREE.Vector2 };\n uTextureResolution: { value: THREE.Vector2 };\n uTexture0: { value: THREE.Texture };\n uTexture1: { value: THREE.Texture };\n padding: { value: number };\n uMap: { value: THREE.Texture };\n edgeIntensity: { value: number };\n mapIntensity: { value: number };\n epicenter: { value: THREE.Vector2 };\n progress: { value: number };\n dirX: { value: number };\n dirY: { value: number };\n };\n}\n\nexport const useMesh = ({\n scene,\n size,\n dpr,\n onBeforeInit,\n}: {\n scene: THREE.Scene;\n size: Size;\n dpr: number | false;\n} & MaterialProps) => {\n const geometry = useMemo(() => new THREE.PlaneGeometry(2, 2), []);\n const material = useMemo(() => {\n const mat = new THREE.ShaderMaterial({\n ...createMaterialParameters(\n {\n uniforms: {\n uResolution: { value: new THREE.Vector2() },\n uTextureResolution: { value: new THREE.Vector2() },\n uTexture0: { value: DEFAULT_TEXTURE },\n uTexture1: { value: DEFAULT_TEXTURE },\n padding: { value: FXTEXTURE_PARAMS.padding },\n uMap: { value: DEFAULT_TEXTURE },\n edgeIntensity: { value: FXTEXTURE_PARAMS.edgeIntensity },\n mapIntensity: { value: FXTEXTURE_PARAMS.mapIntensity },\n epicenter: { value: FXTEXTURE_PARAMS.epicenter },\n progress: { value: FXTEXTURE_PARAMS.progress },\n dirX: { value: FXTEXTURE_PARAMS.dir?.x },\n dirY: { value: FXTEXTURE_PARAMS.dir?.y },\n },\n vertexShader: vertexShader,\n fragmentShader: fragmentShader,\n },\n onBeforeInit\n ),\n ...MATERIAL_BASIC_PARAMS,\n });\n return mat;\n }, [onBeforeInit]) as FxTextureMaterial;\n\n const resolution = useResolution(size, dpr);\n setUniform(material)(\"uResolution\", resolution.clone());\n\n const mesh = useAddObject(scene, geometry, material, THREE.Mesh);\n\n return { material, mesh };\n};\n","import * as THREE from \"three\";\nimport { useCallback, useMemo } from \"react\";\nimport { useMesh } from \"./useMesh\";\nimport { useCamera } from \"../../../utils/useCamera\";\nimport { RootState } from \"@react-three/fiber\";\nimport { useSingleFBO } from \"../../../utils/useSingleFBO\";\nimport {\n CustomParams,\n setCustomUniform,\n setUniform,\n} from \"../../../utils/setUniforms\";\nimport { HooksProps, HooksReturn } from \"../../types\";\nimport { useParams } from \"../../../utils/useParams\";\nimport { getDpr } from \"../../../utils/getDpr\";\nimport { DEFAULT_TEXTURE } from \"../../../libs/constants\";\n\nexport type FxTextureParams = {\n /** 1st texture , default : `THREE.Texture()` */\n texture0?: THREE.Texture;\n /** 2nd texture , default : `THREE.Texture()` */\n texture1?: THREE.Texture;\n /** add transparent padding, 0.0 ~ 1.0 , default : `0.0` */\n padding?: number;\n /** The color map. The uv value is affected according to this rbg , default : `THREE.Texture()` */\n map?: THREE.Texture;\n /** intensity of map , r,g value are affecting , default : `0.0` */\n mapIntensity?: number;\n /** Intensity of effect on edges , default : `0.0` */\n edgeIntensity?: number;\n /** epicenter of fx, -1 ~ 1 , default : `vec2(0.0,0.0)` */\n epicenter?: THREE.Vector2;\n /** Switch value to switch between texture0 and texture1 , 0 ~ 1 , default : `0` */\n progress?: number;\n /** direction of transition , default: `THREE.Vector2(0, 0)` */\n dir?: THREE.Vector2;\n};\n\nexport type FxTextureObject = {\n scene: THREE.Scene;\n mesh: THREE.Mesh;\n material: THREE.Material;\n camera: THREE.Camera;\n renderTarget: THREE.WebGLRenderTarget;\n output: THREE.Texture;\n};\n\nexport const FXTEXTURE_PARAMS: FxTextureParams = Object.freeze({\n texture0: DEFAULT_TEXTURE,\n texture1: DEFAULT_TEXTURE,\n padding: 0.0,\n map: DEFAULT_TEXTURE,\n mapIntensity: 0.0,\n edgeIntensity: 0.0,\n epicenter: new THREE.Vector2(0, 0),\n progress: 0.0,\n dir: new THREE.Vector2(0, 0),\n});\n\n/**\n * @link https://github.com/FunTechInc/use-shader-fx?tab=readme-ov-file#usage\n */\nexport const useFxTexture = ({\n size,\n dpr,\n renderTargetOptions,\n isSizeUpdate,\n onBeforeInit,\n}: HooksProps): HooksReturn => {\n const _dpr = getDpr(dpr);\n\n const scene = useMemo(() => new THREE.Scene(), []);\n const { material, mesh } = useMesh({\n scene,\n size,\n dpr: _dpr.shader,\n onBeforeInit,\n });\n const camera = useCamera(size);\n const [renderTarget, updateRenderTarget] = useSingleFBO({\n scene,\n camera,\n dpr: _dpr.fbo,\n size,\n isSizeUpdate,\n ...renderTargetOptions,\n });\n\n const [params, setParams] = useParams(FXTEXTURE_PARAMS);\n\n const updateValue = setUniform(material);\n const updateCustomValue = setCustomUniform(material);\n\n const updateParams = useCallback(\n (newParams?: FxTextureParams, customParams?: CustomParams) => {\n setParams(newParams);\n updateCustomValue(customParams);\n },\n [setParams, updateCustomValue]\n );\n\n const updateFx = useCallback(\n (\n rootState: RootState,\n newParams?: FxTextureParams,\n customParams?: CustomParams\n ) => {\n const { gl } = rootState;\n\n updateParams(newParams, customParams);\n\n updateValue(\"uTexture0\", params.texture0!);\n updateValue(\"uTexture1\", params.texture1!);\n updateValue(\"progress\", params.progress!);\n // calculate resolution by linear interpolation.\n const tex0Res = [\n params.texture0!?.image?.width || 0,\n params.texture0!?.image?.height || 0,\n ];\n const tex1Res = [\n params.texture1!?.image?.width || 0,\n params.texture1!?.image?.height || 0,\n ];\n const interpolatedResolution = tex0Res.map((value, index) => {\n return value + (tex1Res[index] - value) * params.progress!;\n });\n updateValue(\"uTextureResolution\", interpolatedResolution);\n updateValue(\"padding\", params.padding!);\n updateValue(\"uMap\", params.map!);\n updateValue(\"mapIntensity\", params.mapIntensity!);\n updateValue(\"edgeIntensity\", params.edgeIntensity!);\n updateValue(\"epicenter\", params.epicenter!);\n updateValue(\"dirX\", params.dir!.x);\n updateValue(\"dirY\", params.dir!.y);\n\n return updateRenderTarget(gl);\n },\n [updateRenderTarget, updateValue, params, updateParams]\n );\n return [\n updateFx,\n updateParams,\n {\n scene: scene,\n mesh: mesh,\n material: material,\n camera: camera,\n renderTarget: renderTarget,\n output: renderTarget.texture,\n },\n ];\n};\n","#usf ","precision highp float;\n\nvarying vec2 vUv;\nuniform sampler2D u_texture;\nuniform vec3 u_brightness;\nuniform float u_min;\nuniform float u_max;\n\nvoid main() {\n\tvec2 uv = vUv;\n\tvec3 color = texture2D(u_texture, uv).rgb;\n\tfloat brightness = dot(color,u_brightness);\n\tfloat alpha = clamp(smoothstep(u_min, u_max, brightness),0.0,1.0);\n\tgl_FragColor = vec4(color, alpha);\n}","import * as THREE from \"three\";\nimport { useMemo } from \"react\";\nimport vertexShader from \"./shader/main.vert\";\nimport fragmentShader from \"./shader/main.frag\";\nimport { useAddObject } from \"../../../utils/useAddObject\";\nimport { MaterialProps } from \"../../types\";\nimport {\n MATERIAL_BASIC_PARAMS,\n DEFAULT_TEXTURE,\n} from \"../../../libs/constants\";\nimport { BRIGHTNESSPICKER_PARAMS } from \".\";\nimport { createMaterialParameters } from \"../../../utils/createMaterialParameters\";\n\nexport class BrightnessPickerMaterial extends THREE.ShaderMaterial {\n uniforms!: {\n u_texture: { value: THREE.Texture };\n u_brightness: { value: THREE.Vector3 };\n u_min: { value: number };\n u_max: { value: number };\n };\n}\n\nexport const useMesh = ({\n scene,\n onBeforeInit,\n}: { scene: THREE.Scene } & MaterialProps) => {\n const geometry = useMemo(() => new THREE.PlaneGeometry(2, 2), []);\n const material = useMemo(() => {\n const mat = new THREE.ShaderMaterial({\n ...createMaterialParameters(\n {\n uniforms: {\n u_texture: { value: DEFAULT_TEXTURE },\n u_brightness: { value: BRIGHTNESSPICKER_PARAMS.brightness },\n u_min: { value: BRIGHTNESSPICKER_PARAMS.min },\n u_max: { value: BRIGHTNESSPICKER_PARAMS.max },\n },\n vertexShader: vertexShader,\n fragmentShader: fragmentShader,\n },\n onBeforeInit\n ),\n ...MATERIAL_BASIC_PARAMS,\n });\n return mat;\n }, [onBeforeInit]) as BrightnessPickerMaterial;\n const mesh = useAddObject(scene, geometry, material, THREE.Mesh);\n return { material, mesh };\n};\n","import { useCallback, useMemo } from \"react\";\nimport * as THREE from \"three\";\nimport { useMesh } from \"./useMesh\";\nimport { useCamera } from \"../../../utils/useCamera\";\nimport { RootState } from \"@react-three/fiber\";\nimport { useSingleFBO } from \"../../../utils/useSingleFBO\";\nimport {\n CustomParams,\n setCustomUniform,\n setUniform,\n} from \"../../../utils/setUniforms\";\nimport { HooksProps, HooksReturn } from \"../../types\";\nimport { useParams } from \"../../../utils/useParams\";\nimport { getDpr } from \"../../../utils/getDpr\";\nimport { DEFAULT_TEXTURE } from \"../../../libs/constants\";\n\nexport type BrightnessPickerParams = {\n /** pick brightness from this texture , default : `THREE.Texture` */\n texture?: THREE.Texture;\n /** default : `(0.5,0.5,0.5)` */\n brightness?: THREE.Vector3;\n /** default : `0.0` */\n min?: number;\n /** default : `1.0` */\n max?: number;\n};\n\nexport type BrightnessPickerObject = {\n scene: THREE.Scene;\n mesh: THREE.Mesh;\n material: THREE.Material;\n camera: THREE.Camera;\n renderTarget: THREE.WebGLRenderTarget;\n output: THREE.Texture;\n};\n\nexport const BRIGHTNESSPICKER_PARAMS: BrightnessPickerParams = Object.freeze({\n texture: DEFAULT_TEXTURE,\n brightness: new THREE.Vector3(0.5, 0.5, 0.5),\n min: 0.0,\n max: 1.0,\n});\n\n/**\n * @link https://github.com/FunTechInc/use-shader-fx?tab=readme-ov-file#usage\n */\nexport const useBrightnessPicker = ({\n size,\n dpr,\n renderTargetOptions,\n isSizeUpdate,\n onBeforeInit,\n}: HooksProps): HooksReturn<\n BrightnessPickerParams,\n BrightnessPickerObject,\n CustomParams\n> => {\n const _dpr = getDpr(dpr);\n const scene = useMemo(() => new THREE.Scene(), []);\n const { material, mesh } = useMesh({ scene, onBeforeInit });\n const camera = useCamera(size);\n const [renderTarget, updateRenderTarget] = useSingleFBO({\n scene,\n camera,\n size,\n dpr: _dpr.fbo,\n isSizeUpdate,\n ...renderTargetOptions,\n });\n\n const [params, setParams] = useParams(\n BRIGHTNESSPICKER_PARAMS\n );\n\n const updateValue = setUniform(material);\n const updateCustomValue = setCustomUniform(material);\n\n const updateParams = useCallback(\n (newParams?: BrightnessPickerParams, customParams?: CustomParams) => {\n setParams(newParams);\n updateCustomValue(customParams);\n },\n [setParams, updateCustomValue]\n );\n\n const updateFx = useCallback(\n (\n rootState: RootState,\n newParams?: BrightnessPickerParams,\n customParams?: CustomParams\n ) => {\n const { gl } = rootState;\n\n updateParams(newParams, customParams);\n\n updateValue(\"u_texture\", params.texture!);\n updateValue(\"u_brightness\", params.brightness!);\n updateValue(\"u_min\", params.min!);\n updateValue(\"u_max\", params.max!);\n\n return updateRenderTarget(gl);\n },\n [updateRenderTarget, updateValue, params, updateParams]\n );\n\n return [\n updateFx,\n updateParams,\n {\n scene: scene,\n mesh: mesh,\n material: material,\n camera: camera,\n renderTarget: renderTarget,\n output: renderTarget.texture,\n },\n ];\n};\n","#usf ","precision highp float;\n\nvarying vec2 vUv;\nuniform sampler2D u_texture;\nuniform sampler2D uMap;\nuniform float uMapIntensity;\n\nvoid main() {\n\tvec2 uv = vUv;\n\n\t#usf \n\n\tgl_FragColor = texture2D(u_texture, uv);\n}","import { useMemo } from \"react\";\nimport * as THREE from \"three\";\nimport vertexShader from \"./shader/main.vert\";\nimport fragmentShader from \"./shader/main.frag\";\nimport { useAddObject } from \"../../../utils/useAddObject\";\nimport { MaterialProps } from \"../../types\";\nimport {\n MATERIAL_BASIC_PARAMS,\n DEFAULT_TEXTURE,\n} from \"../../../libs/constants\";\nimport { FXBLENDING_PARAMS } from \".\";\nimport { createMaterialParameters } from \"../../../utils/createMaterialParameters\";\n\nexport class FxBlendingMaterial extends THREE.ShaderMaterial {\n uniforms!: {\n u_texture: { value: THREE.Texture };\n uMap: { value: THREE.Texture };\n uMapIntensity: { value: number };\n };\n}\n\nexport const useMesh = ({\n scene,\n onBeforeInit,\n}: { scene: THREE.Scene } & MaterialProps) => {\n const geometry = useMemo(() => new THREE.PlaneGeometry(2, 2), []);\n const material = useMemo(() => {\n const mat = new THREE.ShaderMaterial({\n ...createMaterialParameters(\n {\n uniforms: {\n u_texture: { value: DEFAULT_TEXTURE },\n uMap: { value: DEFAULT_TEXTURE },\n uMapIntensity: { value: FXBLENDING_PARAMS.mapIntensity },\n },\n vertexShader: vertexShader,\n fragmentShader: fragmentShader,\n },\n onBeforeInit\n ),\n ...MATERIAL_BASIC_PARAMS,\n });\n return mat;\n }, [onBeforeInit]) as FxBlendingMaterial;\n\n const mesh = useAddObject(scene, geometry, material, THREE.Mesh);\n return { material, mesh };\n};\n","import { useCallback, useMemo } from \"react\";\nimport * as THREE from \"three\";\nimport { useMesh } from \"./useMesh\";\nimport { useCamera } from \"../../../utils/useCamera\";\nimport { RootState } from \"@react-three/fiber\";\nimport { useSingleFBO } from \"../../../utils/useSingleFBO\";\nimport {\n CustomParams,\n setCustomUniform,\n setUniform,\n} from \"../../../utils/setUniforms\";\nimport { HooksProps, HooksReturn } from \"../../types\";\nimport { useParams } from \"../../../utils/useParams\";\nimport { getDpr } from \"../../../utils/getDpr\";\nimport { DEFAULT_TEXTURE } from \"../../../libs/constants\";\n\nexport type FxBlendingParams = {\n /** Make this texture Blending , default : `THREE.Texture` */\n texture?: THREE.Texture;\n /** map texture, default : `THREE.Texture` */\n map?: THREE.Texture;\n /** map strength , r,g value are affecting , default : `0.3` */\n mapIntensity?: number;\n};\n\nexport type FxBlendingObject = {\n scene: THREE.Scene;\n mesh: THREE.Mesh;\n material: THREE.Material;\n camera: THREE.Camera;\n renderTarget: THREE.WebGLRenderTarget;\n output: THREE.Texture;\n};\n\nexport const FXBLENDING_PARAMS: FxBlendingParams = Object.freeze({\n texture: DEFAULT_TEXTURE,\n map: DEFAULT_TEXTURE,\n mapIntensity: 0.3,\n});\n\n/**\n * Blend map to texture. You can change the intensity of fx applied by the rg value of map. Unlike \"useBlending\", the map color is not reflected.\n * @link https://github.com/FunTechInc/use-shader-fx?tab=readme-ov-file#usage\n */\nexport const useFxBlending = ({\n size,\n dpr,\n renderTargetOptions,\n isSizeUpdate,\n onBeforeInit,\n}: HooksProps): HooksReturn<\n FxBlendingParams,\n FxBlendingObject,\n CustomParams\n> => {\n const _dpr = getDpr(dpr);\n\n const scene = useMemo(() => new THREE.Scene(), []);\n const { material, mesh } = useMesh({ scene, onBeforeInit });\n const camera = useCamera(size);\n const [renderTarget, updateRenderTarget] = useSingleFBO({\n scene,\n camera,\n size,\n dpr: _dpr.fbo,\n isSizeUpdate,\n ...renderTargetOptions,\n });\n\n const [params, setParams] = useParams(FXBLENDING_PARAMS);\n\n const updateValue = setUniform(material);\n const updateCustomValue = setCustomUniform(material);\n\n const updateParams = useCallback(\n (newParams?: FxBlendingParams, customParams?: CustomParams) => {\n setParams(newParams);\n updateCustomValue(customParams);\n },\n [setParams, updateCustomValue]\n );\n\n const updateFx = useCallback(\n (\n rootState: RootState,\n newParams?: FxBlendingParams,\n customParams?: CustomParams\n ) => {\n const { gl } = rootState;\n\n updateParams(newParams, customParams);\n\n updateValue(\"u_texture\", params.texture!);\n updateValue(\"uMap\", params.map!);\n updateValue(\"uMapIntensity\", params.mapIntensity!);\n\n return updateRenderTarget(gl);\n },\n [updateRenderTarget, updateValue, params, updateParams]\n );\n\n return [\n updateFx,\n updateParams,\n {\n scene: scene,\n mesh: mesh,\n material: material,\n camera: camera,\n renderTarget: renderTarget,\n output: renderTarget.texture,\n },\n ];\n};\n","#usf ","precision highp float;\n\nuniform sampler2D uTexture;\nuniform sampler2D uMap;\n\nvarying vec2 vUv;\n\nvoid main() {\n\tvec2 uv = vUv;\n\tvec4 tex = texture2D(uTexture, uv);\n\tvec4 map = texture2D(uMap, uv);\n\tgl_FragColor = mix(tex,map,map.a);\n}\n\n","import * as THREE from \"three\";\nimport vertexShader from \"./shader/main.vert\";\nimport fragmentShader from \"./shader/main.frag\";\nimport { useMemo } from \"react\";\nimport { useAddObject } from \"../../../utils/useAddObject\";\nimport { MaterialProps, Size } from \"../../types\";\nimport {\n DEFAULT_TEXTURE,\n MATERIAL_BASIC_PARAMS,\n} from \"../../../libs/constants\";\nimport { createMaterialParameters } from \"../../../utils/createMaterialParameters\";\n\nexport class AlphaBlendingMaterial extends THREE.ShaderMaterial {\n uniforms!: {\n uTexture: { value: THREE.Texture };\n uMap: { value: THREE.Texture };\n };\n}\n\nexport const useMesh = ({\n scene,\n onBeforeInit,\n}: {\n scene: THREE.Scene;\n size: Size;\n} & MaterialProps) => {\n const geometry = useMemo(() => new THREE.PlaneGeometry(2, 2), []);\n const material = useMemo(() => {\n const mat = new THREE.ShaderMaterial({\n ...createMaterialParameters(\n {\n uniforms: {\n uTexture: { value: DEFAULT_TEXTURE },\n uMap: { value: DEFAULT_TEXTURE },\n },\n vertexShader: vertexShader,\n fragmentShader: fragmentShader,\n },\n onBeforeInit\n ),\n ...MATERIAL_BASIC_PARAMS,\n });\n\n return mat;\n }, [onBeforeInit]) as AlphaBlendingMaterial;\n\n const mesh = useAddObject(scene, geometry, material, THREE.Mesh);\n\n return { material, mesh };\n};\n","import * as THREE from \"three\";\nimport { useMesh } from \"./useMesh\";\nimport { useCamera } from \"../../../utils/useCamera\";\nimport { useCallback, useMemo } from \"react\";\nimport { RootState } from \"@react-three/fiber\";\nimport {\n CustomParams,\n setCustomUniform,\n setUniform,\n} from \"../../../utils/setUniforms\";\nimport { HooksProps, HooksReturn } from \"../../types\";\nimport { useParams } from \"../../../utils/useParams\";\nimport { useSingleFBO } from \"../../../utils/useSingleFBO\";\nimport { getDpr } from \"../../../utils/getDpr\";\nimport { DEFAULT_TEXTURE } from \"../../../libs/constants\";\n\nexport type AlphaBlendingParams = {\n /** default : `THREE.Texture()` */\n texture?: THREE.Texture;\n /** alpha map , default : `THREE.Texture()` */\n map?: THREE.Texture;\n};\n\nexport type AlphaBlendingObject = {\n scene: THREE.Scene;\n mesh: THREE.Mesh;\n material: THREE.Material;\n camera: THREE.Camera;\n renderTarget: THREE.WebGLRenderTarget;\n output: THREE.Texture;\n};\n\nexport const ALPHABLENDING_PARAMS: AlphaBlendingParams = Object.freeze({\n texture: DEFAULT_TEXTURE,\n map: DEFAULT_TEXTURE,\n});\n\n/**\n * @link https://github.com/FunTechInc/use-shader-fx?tab=readme-ov-file#usage\n */\nexport const useAlphaBlending = ({\n size,\n dpr,\n renderTargetOptions,\n isSizeUpdate,\n onBeforeInit,\n}: HooksProps): HooksReturn<\n AlphaBlendingParams,\n AlphaBlendingObject,\n CustomParams\n> => {\n const _dpr = getDpr(dpr);\n\n const scene = useMemo(() => new THREE.Scene(), []);\n const { material, mesh } = useMesh({\n scene,\n size,\n onBeforeInit,\n });\n const camera = useCamera(size);\n\n const [renderTarget, updateRenderTarget] = useSingleFBO({\n scene,\n camera,\n size,\n dpr: _dpr.fbo,\n isSizeUpdate,\n ...renderTargetOptions,\n });\n\n const [params, setParams] =\n useParams(ALPHABLENDING_PARAMS);\n\n const updateValue = setUniform(material);\n const updateCustomValue = setCustomUniform(material);\n\n const updateParams = useCallback(\n (newParams?: AlphaBlendingParams, customParams?: CustomParams) => {\n setParams(newParams);\n updateCustomValue(customParams);\n },\n [setParams, updateCustomValue]\n );\n\n const updateFx = useCallback(\n (\n rootState: RootState,\n newParams?: AlphaBlendingParams,\n customParams?: CustomParams\n ) => {\n const { gl } = rootState;\n\n updateParams(newParams, customParams);\n\n updateValue(\"uTexture\", params.texture!);\n updateValue(\"uMap\", params.map!);\n\n return updateRenderTarget(gl);\n },\n [updateValue, updateRenderTarget, params, updateParams]\n );\n\n return [\n updateFx,\n updateParams,\n {\n scene: scene,\n mesh: mesh,\n material: material,\n camera: camera,\n renderTarget: renderTarget,\n output: renderTarget.texture,\n },\n ];\n};\n","#usf ","precision highp float;\n\nvarying vec2 vUv;\nuniform sampler2D u_texture;\nuniform float u_brightness;\nuniform float u_saturation;\n\n#usf \n\n#usf \n\nvoid main() {\n\tvec4 tex = texture2D(u_texture, vUv);\n\tvec3 hsv = rgb2hsv(tex.rgb);\n\thsv.y *= u_saturation;\n\thsv.z *= u_brightness;\n\tvec3 final = hsv2rgb(hsv);\n\tgl_FragColor = vec4(final, tex.a);\n}\n\n","import * as THREE from \"three\";\nimport vertexShader from \"./shader/main.vert\";\nimport fragmentShader from \"./shader/main.frag\";\nimport { useMemo } from \"react\";\nimport { useAddObject } from \"../../../utils/useAddObject\";\nimport { MaterialProps, Size } from \"../../types\";\nimport {\n MATERIAL_BASIC_PARAMS,\n DEFAULT_TEXTURE,\n} from \"../../../libs/constants\";\nimport { HSV_PARAMS } from \".\";\nimport { createMaterialParameters } from \"../../../utils/createMaterialParameters\";\n\nexport class HSVMaterial extends THREE.ShaderMaterial {\n uniforms!: {\n u_texture: { value: THREE.Texture };\n u_brightness: { value: number };\n u_saturation: { value: number };\n };\n}\n\nexport const useMesh = ({\n scene,\n onBeforeInit,\n}: {\n scene: THREE.Scene;\n size: Size;\n} & MaterialProps) => {\n const geometry = useMemo(() => new THREE.PlaneGeometry(2, 2), []);\n const material = useMemo(() => {\n const mat = new THREE.ShaderMaterial({\n ...createMaterialParameters(\n {\n uniforms: {\n u_texture: { value: DEFAULT_TEXTURE },\n u_brightness: { value: HSV_PARAMS.brightness },\n u_saturation: { value: HSV_PARAMS.saturation },\n },\n vertexShader: vertexShader,\n fragmentShader: fragmentShader,\n },\n onBeforeInit\n ),\n ...MATERIAL_BASIC_PARAMS,\n });\n return mat;\n }, [onBeforeInit]) as HSVMaterial;\n const mesh = useAddObject(scene, geometry, material, THREE.Mesh);\n return { material, mesh };\n};\n","import * as THREE from \"three\";\nimport { useMesh } from \"./useMesh\";\nimport { useCamera } from \"../../../utils/useCamera\";\nimport { useCallback, useMemo } from \"react\";\nimport { RootState } from \"@react-three/fiber\";\nimport {\n CustomParams,\n setCustomUniform,\n setUniform,\n} from \"../../../utils/setUniforms\";\nimport { HooksProps, HooksReturn } from \"../../types\";\nimport { useParams } from \"../../../utils/useParams\";\nimport { useSingleFBO } from \"../../../utils/useSingleFBO\";\nimport { getDpr } from \"../../../utils/getDpr\";\nimport { DEFAULT_TEXTURE } from \"../../../libs/constants\";\n\nexport type HSVParams = {\n /** default : `THREE.Texture()` */\n texture?: THREE.Texture;\n /** default : `1` */\n brightness?: number;\n /** default : `1` */\n saturation?: number;\n};\n\nexport type HSVObject = {\n scene: THREE.Scene;\n mesh: THREE.Mesh;\n material: THREE.Material;\n camera: THREE.Camera;\n renderTarget: THREE.WebGLRenderTarget;\n output: THREE.Texture;\n};\n\nexport const HSV_PARAMS: HSVParams = Object.freeze({\n texture: DEFAULT_TEXTURE,\n brightness: 1,\n saturation: 1,\n});\n\n/**\n * @link https://github.com/FunTechInc/use-shader-fx?tab=readme-ov-file#usage\n */\nexport const useHSV = ({\n size,\n dpr,\n renderTargetOptions,\n isSizeUpdate,\n onBeforeInit,\n}: HooksProps): HooksReturn => {\n const _dpr = getDpr(dpr);\n\n const scene = useMemo(() => new THREE.Scene(), []);\n const { material, mesh } = useMesh({\n scene,\n size,\n onBeforeInit,\n });\n const camera = useCamera(size);\n\n const [renderTarget, updateRenderTarget] = useSingleFBO({\n scene,\n camera,\n size,\n dpr: _dpr.fbo,\n isSizeUpdate,\n ...renderTargetOptions,\n });\n\n const [params, setParams] = useParams(HSV_PARAMS);\n\n const updateValue = setUniform(material);\n const updateCustomValue = setCustomUniform(material);\n\n const updateParams = useCallback(\n (newParams?: HSVParams, customParams?: CustomParams) => {\n setParams(newParams);\n updateCustomValue(customParams);\n },\n [setParams, updateCustomValue]\n );\n\n const updateFx = useCallback(\n (\n rootState: RootState,\n newParams?: HSVParams,\n customParams?: CustomParams\n ) => {\n const { gl } = rootState;\n\n updateParams(newParams, customParams);\n\n updateValue(\"u_texture\", params.texture!);\n updateValue(\"u_brightness\", params.brightness!);\n updateValue(\"u_saturation\", params.saturation!);\n\n return updateRenderTarget(gl);\n },\n [updateValue, updateRenderTarget, params, updateParams]\n );\n\n return [\n updateFx,\n updateParams,\n {\n scene: scene,\n mesh: mesh,\n material: material,\n camera: camera,\n renderTarget: renderTarget,\n output: renderTarget.texture,\n },\n ];\n};\n","#usf ","precision highp float;\n\nvarying vec2 vUv;\nuniform vec2 uResolution;\nuniform vec2 uTextureResolution;\nuniform sampler2D uTexture;\n\nvoid main() {\n\t#usf \n\t\n\tgl_FragColor = texture2D(uTexture, uv);\n}\n\n","import { useMemo } from \"react\";\nimport * as THREE from \"three\";\nimport { useResolution } from \"../../../utils/useResolution\";\nimport vertexShader from \"./shader/main.vert\";\nimport fragmentShader from \"./shader/main.frag\";\nimport { setUniform } from \"../../../utils/setUniforms\";\nimport { useAddObject } from \"../../../utils/useAddObject\";\nimport { MaterialProps, Size } from \"../../types\";\nimport {\n MATERIAL_BASIC_PARAMS,\n DEFAULT_TEXTURE,\n} from \"../../../libs/constants\";\nimport { createMaterialParameters } from \"../../../utils/createMaterialParameters\";\n\nexport class FxTextureMaterial extends THREE.ShaderMaterial {\n uniforms!: {\n uResolution: { value: THREE.Vector2 };\n uTextureResolution: { value: THREE.Vector2 };\n uTexture: { value: THREE.Texture };\n };\n}\n\nexport const useMesh = ({\n scene,\n size,\n dpr,\n onBeforeInit,\n}: {\n scene: THREE.Scene;\n size: Size;\n dpr: number | false;\n} & MaterialProps) => {\n const geometry = useMemo(() => new THREE.PlaneGeometry(2, 2), []);\n const material = useMemo(() => {\n const mat = new THREE.ShaderMaterial({\n ...createMaterialParameters(\n {\n uniforms: {\n uResolution: { value: new THREE.Vector2() },\n uTextureResolution: { value: new THREE.Vector2() },\n uTexture: { value: DEFAULT_TEXTURE },\n },\n vertexShader: vertexShader,\n fragmentShader: fragmentShader,\n },\n onBeforeInit\n ),\n ...MATERIAL_BASIC_PARAMS,\n });\n return mat;\n }, [onBeforeInit]) as FxTextureMaterial;\n\n const resolution = useResolution(size, dpr);\n setUniform(material)(\"uResolution\", resolution.clone());\n\n const mesh = useAddObject(scene, geometry, material, THREE.Mesh);\n\n return { material, mesh };\n};\n","import * as THREE from \"three\";\nimport { useCallback, useMemo } from \"react\";\nimport { useMesh } from \"./useMesh\";\nimport { useCamera } from \"../../../utils/useCamera\";\nimport { RootState } from \"@react-three/fiber\";\nimport { useSingleFBO } from \"../../../utils/useSingleFBO\";\nimport {\n CustomParams,\n setCustomUniform,\n setUniform,\n} from \"../../../utils/setUniforms\";\nimport { HooksProps, HooksReturn } from \"../../types\";\nimport { useParams } from \"../../../utils/useParams\";\nimport { getDpr } from \"../../../utils/getDpr\";\nimport { DEFAULT_TEXTURE } from \"../../../libs/constants\";\n\nexport type CoverTextureParams = {\n /** Textures that you want to display exactly on the screen , default : `THREE.Texture()` */\n texture?: THREE.Texture;\n};\n\nexport type CoverTextureObject = {\n scene: THREE.Scene;\n mesh: THREE.Mesh;\n material: THREE.Material;\n camera: THREE.Camera;\n renderTarget: THREE.WebGLRenderTarget;\n output: THREE.Texture;\n};\n\nexport const COVERTEXTURE_PARAMS: CoverTextureParams = Object.freeze({\n texture: DEFAULT_TEXTURE,\n});\n\n/**\n * @link https://github.com/FunTechInc/use-shader-fx?tab=readme-ov-file#usage\n */\nexport const useCoverTexture = ({\n size,\n dpr,\n renderTargetOptions,\n isSizeUpdate,\n onBeforeInit,\n}: HooksProps): HooksReturn<\n CoverTextureParams,\n CoverTextureObject,\n CustomParams\n> => {\n const _dpr = getDpr(dpr);\n\n const scene = useMemo(() => new THREE.Scene(), []);\n const { material, mesh } = useMesh({\n scene,\n size,\n dpr: _dpr.shader,\n onBeforeInit,\n });\n const camera = useCamera(size);\n const [renderTarget, updateRenderTarget] = useSingleFBO({\n scene,\n camera,\n dpr: _dpr.fbo,\n size,\n isSizeUpdate,\n ...renderTargetOptions,\n });\n\n const [params, setParams] =\n useParams(COVERTEXTURE_PARAMS);\n\n const updateValue = setUniform(material);\n const updateCustomValue = setCustomUniform(material);\n\n const updateParams = useCallback(\n (newParams?: CoverTextureParams, customParams?: CustomParams) => {\n setParams(newParams);\n updateCustomValue(customParams);\n },\n [setParams, updateCustomValue]\n );\n\n const updateFx = useCallback(\n (\n rootState: RootState,\n newParams?: CoverTextureParams,\n customParams?: CustomParams\n ) => {\n const { gl } = rootState;\n\n updateParams(newParams, customParams);\n\n updateValue(\"uTexture\", params.texture!);\n updateValue(\"uTextureResolution\", [\n params.texture!?.source?.data?.width || 0,\n params.texture!?.source?.data?.height || 0,\n ]);\n\n return updateRenderTarget(gl);\n },\n [updateRenderTarget, updateValue, params, updateParams]\n );\n return [\n updateFx,\n updateParams,\n {\n scene: scene,\n mesh: mesh,\n material: material,\n camera: camera,\n renderTarget: renderTarget,\n output: renderTarget.texture,\n },\n ];\n};\n","#usf ","precision highp float;\n\nvarying vec2 vUv;\nuniform sampler2D uTexture;\nuniform vec2 uResolution;\nuniform float uBlurSize;\n\nvoid main() {\n\tvec2 uv = vUv;\t\n\tvec2 perDivSize = uBlurSize / uResolution;\n\n\t// calc average color value from adjacent point\n\tvec4 outColor = vec4(\n\t\ttexture2D(uTexture, uv + perDivSize * vec2(-1.0, -1.0)) +\n\t\ttexture2D(uTexture, uv + perDivSize * vec2(0.0, -1.0)) + \n\t\ttexture2D(uTexture, uv + perDivSize * vec2(1.0, -1.0)) + \n\t\ttexture2D(uTexture, uv + perDivSize * vec2(-1.0, 0.0)) + \n\t\ttexture2D(uTexture, uv + perDivSize * vec2(0.0, 0.0)) + \n\t\ttexture2D(uTexture, uv + perDivSize * vec2(1.0, 0.0)) + \n\t\ttexture2D(uTexture, uv + perDivSize * vec2(-1.0, 1.0)) + \n\t\ttexture2D(uTexture, uv + perDivSize * vec2(0.0, 1.0)) + \n\t\ttexture2D(uTexture, uv + perDivSize * vec2(1.0, 1.0))\n\t\t) / 9.0;\n\t\n\tgl_FragColor = outColor;\n}","import { useMemo } from \"react\";\nimport * as THREE from \"three\";\nimport vertexShader from \"./shader/main.vert\";\nimport fragmentShader from \"./shader/main.frag\";\nimport { useAddObject } from \"../../../utils/useAddObject\";\nimport { SIMPLEBLUR_PARAMS } from \".\";\nimport { MaterialProps } from \"../../types\";\nimport {\n MATERIAL_BASIC_PARAMS,\n DEFAULT_TEXTURE,\n} from \"../../../libs/constants\";\nimport { createMaterialParameters } from \"../../../utils/createMaterialParameters\";\n\nexport class SampleMaterial extends THREE.ShaderMaterial {\n uniforms!: {\n uTexture: { value: THREE.Texture };\n uResolution: { value: THREE.Vector2 };\n uBlurSize: { value: number };\n };\n}\n\nexport const useMesh = ({\n scene,\n onBeforeInit,\n}: { scene: THREE.Scene } & MaterialProps) => {\n const geometry = useMemo(() => new THREE.PlaneGeometry(2, 2), []);\n const material = useMemo(() => {\n const mat = new THREE.ShaderMaterial({\n ...createMaterialParameters(\n {\n uniforms: {\n uTexture: { value: DEFAULT_TEXTURE },\n uResolution: { value: new THREE.Vector2(0, 0) },\n uBlurSize: { value: SIMPLEBLUR_PARAMS.blurSize },\n },\n vertexShader: vertexShader,\n fragmentShader: fragmentShader,\n },\n onBeforeInit\n ),\n ...MATERIAL_BASIC_PARAMS,\n });\n\n return mat;\n }, [onBeforeInit]) as SampleMaterial;\n\n const mesh = useAddObject(scene, geometry, material, THREE.Mesh);\n\n return { material, mesh };\n};\n","import { useCallback, useMemo } from \"react\";\nimport * as THREE from \"three\";\nimport { RootState } from \"@react-three/fiber\";\nimport { useMesh } from \"./useMesh\";\nimport { useCamera } from \"../../../utils/useCamera\";\nimport { useDoubleFBO, DoubleRenderTarget } from \"../../../utils/useDoubleFBO\";\nimport {\n CustomParams,\n setCustomUniform,\n setUniform,\n} from \"../../../utils/setUniforms\";\nimport { useParams } from \"../../../utils/useParams\";\nimport type { HooksProps, HooksReturn } from \"../../types\";\nimport { getDpr } from \"../../../utils/getDpr\";\nimport { UseFboProps } from \"../../..\";\nimport { DEFAULT_TEXTURE } from \"../../../libs/constants\";\n\nexport type SimpleBlurParams = {\n /** Make this texture blur , default : `THREE.Texture()` */\n texture?: THREE.Texture;\n /** blurSize, default : `3` */\n blurSize?: number;\n /** blurPower, affects performance default : `5` */\n blurPower?: number;\n};\n\nexport type SimpleBlurObject = {\n scene: THREE.Scene;\n mesh: THREE.Mesh;\n material: THREE.Material;\n camera: THREE.Camera;\n renderTarget: DoubleRenderTarget;\n output: THREE.Texture;\n};\n\nexport const SIMPLEBLUR_PARAMS: SimpleBlurParams = Object.freeze({\n texture: DEFAULT_TEXTURE,\n blurSize: 3,\n blurPower: 5,\n});\n\n/**\n * @link https://github.com/FunTechInc/use-shader-fx?tab=readme-ov-file#usage\n */\nexport const useSimpleBlur = ({\n size,\n dpr,\n renderTargetOptions,\n isSizeUpdate,\n onBeforeInit,\n}: HooksProps): HooksReturn<\n SimpleBlurParams,\n SimpleBlurObject,\n CustomParams\n> => {\n const _dpr = getDpr(dpr);\n const scene = useMemo(() => new THREE.Scene(), []);\n const { material, mesh } = useMesh({ scene, onBeforeInit });\n const camera = useCamera(size);\n\n const fboProps = useMemo(\n () => ({\n scene,\n camera,\n size,\n dpr: _dpr.fbo,\n isSizeUpdate,\n ...renderTargetOptions,\n }),\n [scene, camera, size, _dpr.fbo, isSizeUpdate, renderTargetOptions]\n ) as UseFboProps;\n\n const [renderTarget, updateTempTexture] = useDoubleFBO(fboProps);\n const [params, setParams] = useParams(SIMPLEBLUR_PARAMS);\n\n const updateValue = setUniform(material);\n const updateCustomValue = setCustomUniform(material);\n\n const updateParams = useCallback(\n (newParams?: SimpleBlurParams, customParams?: CustomParams) => {\n setParams(newParams);\n updateCustomValue(customParams);\n },\n [setParams, updateCustomValue]\n );\n\n const updateFx = useCallback(\n (\n rootState: RootState,\n newParams?: SimpleBlurParams,\n customParams?: CustomParams\n ) => {\n const { gl } = rootState;\n\n updateParams(newParams, customParams);\n\n updateValue(\"uTexture\", params.texture!);\n updateValue(\"uResolution\", [\n params.texture!?.source?.data?.width || 0,\n params.texture!?.source?.data?.height || 0,\n ]);\n updateValue(\"uBlurSize\", params.blurSize!);\n\n let _tempTexture: THREE.Texture = updateTempTexture(gl);\n\n for (let i = 0; i < params.blurPower!; i++) {\n updateValue(\"uTexture\", _tempTexture);\n _tempTexture = updateTempTexture(gl);\n }\n\n return _tempTexture;\n },\n [updateTempTexture, updateValue, params, updateParams]\n );\n\n return [\n updateFx,\n updateParams,\n {\n scene: scene,\n mesh: mesh,\n material: material,\n camera: camera,\n renderTarget: renderTarget,\n output: renderTarget.read.texture,\n },\n ];\n};\n","#usf ","precision highp float;\n\nvarying vec2 vUv;\nuniform sampler2D uTexture;\nuniform sampler2D uBackbuffer;\nuniform vec2 uBegin;\nuniform vec2 uEnd;\nuniform float uStrength;\n\nvoid main() {\n\tvec2 uv = vUv;\t\n\tvec4 current = texture2D(uTexture, uv + uBegin*.1);\n\tvec4 back = texture2D(uBackbuffer, uv + uEnd*.1);\n\tvec4 mixed = mix(current,back,uStrength);\n\tgl_FragColor = mixed;\n}","import { useMemo } from \"react\";\nimport * as THREE from \"three\";\nimport vertexShader from \"./shader/main.vert\";\nimport fragmentShader from \"./shader/main.frag\";\nimport { useAddObject } from \"../../../utils/useAddObject\";\nimport { MOTIONBLUR_PARAMS } from \".\";\nimport { MaterialProps } from \"../../types\";\nimport {\n MATERIAL_BASIC_PARAMS,\n DEFAULT_TEXTURE,\n} from \"../../../libs/constants\";\nimport { createMaterialParameters } from \"../../../utils/createMaterialParameters\";\n\nexport class MotionBlurMaterial extends THREE.ShaderMaterial {\n uniforms!: {\n uTexture: { value: THREE.Texture };\n uBackbuffer: { value: THREE.Texture };\n uBegin: { value: THREE.Vector2 };\n uEnd: { value: THREE.Vector2 };\n uStrength: { value: number };\n };\n}\n\nexport const useMesh = ({\n scene,\n onBeforeInit,\n}: { scene: THREE.Scene } & MaterialProps) => {\n const geometry = useMemo(() => new THREE.PlaneGeometry(2, 2), []);\n const material = useMemo(() => {\n const mat = new THREE.ShaderMaterial({\n ...createMaterialParameters(\n {\n uniforms: {\n uTexture: { value: DEFAULT_TEXTURE },\n uBackbuffer: { value: DEFAULT_TEXTURE },\n uBegin: { value: MOTIONBLUR_PARAMS.begin },\n uEnd: { value: MOTIONBLUR_PARAMS.end },\n uStrength: { value: MOTIONBLUR_PARAMS.strength },\n },\n vertexShader: vertexShader,\n fragmentShader: fragmentShader,\n },\n onBeforeInit\n ),\n ...MATERIAL_BASIC_PARAMS,\n });\n return mat;\n }, [onBeforeInit]) as MotionBlurMaterial;\n\n const mesh = useAddObject(scene, geometry, material, THREE.Mesh);\n\n return { material, mesh };\n};\n","import { useCallback, useMemo } from \"react\";\nimport * as THREE from \"three\";\nimport { RootState } from \"@react-three/fiber\";\nimport { useMesh } from \"./useMesh\";\nimport { useCamera } from \"../../../utils/useCamera\";\nimport { useDoubleFBO, DoubleRenderTarget } from \"../../../utils/useDoubleFBO\";\nimport {\n CustomParams,\n setCustomUniform,\n setUniform,\n} from \"../../../utils/setUniforms\";\nimport { useParams } from \"../../../utils/useParams\";\nimport type { HooksProps, HooksReturn } from \"../../types\";\nimport { getDpr } from \"../../../utils/getDpr\";\nimport { UseFboProps } from \"../../..\";\nimport { DEFAULT_TEXTURE } from \"../../../libs/constants\";\n\nexport type MotionBlurParams = {\n /** Make this texture blur, default : `THREE.Texture()` */\n texture?: THREE.Texture;\n /** motion begin, default : `THREE.Vector2(0, 0)` */\n begin?: THREE.Vector2;\n /** motion end, default : `THREE.Vector2(0, 0)` */\n end?: THREE.Vector2;\n /** motion strength, default : `0.9` */\n strength?: number;\n};\n\nexport type MotionBlurObject = {\n scene: THREE.Scene;\n mesh: THREE.Mesh;\n material: THREE.Material;\n camera: THREE.Camera;\n renderTarget: DoubleRenderTarget;\n output: THREE.Texture;\n};\n\nexport const MOTIONBLUR_PARAMS: MotionBlurParams = Object.freeze({\n texture: DEFAULT_TEXTURE,\n begin: new THREE.Vector2(0, 0),\n end: new THREE.Vector2(0, 0),\n strength: 0.9,\n});\n\n/**\n * @link https://github.com/FunTechInc/use-shader-fx?tab=readme-ov-file#usage\n */\nexport const useMotionBlur = ({\n size,\n dpr,\n renderTargetOptions,\n isSizeUpdate,\n onBeforeInit,\n}: HooksProps): HooksReturn<\n MotionBlurParams,\n MotionBlurObject,\n CustomParams\n> => {\n const _dpr = getDpr(dpr);\n\n const scene = useMemo(() => new THREE.Scene(), []);\n const { material, mesh } = useMesh({ scene, onBeforeInit });\n const camera = useCamera(size);\n\n const fboProps = useMemo(\n () => ({\n scene,\n camera,\n size,\n dpr: _dpr.fbo,\n isSizeUpdate,\n ...renderTargetOptions,\n }),\n [scene, camera, size, _dpr.fbo, isSizeUpdate, renderTargetOptions]\n ) as UseFboProps;\n\n const [renderTarget, updateRenderTarget] = useDoubleFBO(fboProps);\n\n const [params, setParams] = useParams(MOTIONBLUR_PARAMS);\n\n const updateValue = setUniform(material);\n const updateCustomValue = setCustomUniform(material);\n\n const updateParams = useCallback(\n (newParams?: MotionBlurParams, customParams?: CustomParams) => {\n setParams(newParams);\n updateCustomValue(customParams);\n },\n [setParams, updateCustomValue]\n );\n\n const updateFx = useCallback(\n (\n rootState: RootState,\n newParams?: MotionBlurParams,\n customParams?: CustomParams\n ) => {\n const { gl } = rootState;\n\n updateParams(newParams, customParams);\n\n updateValue(\"uTexture\", params.texture!);\n updateValue(\"uBegin\", params.begin!);\n updateValue(\"uEnd\", params.end!);\n updateValue(\"uStrength\", params.strength!);\n\n return updateRenderTarget(gl, ({ read }) => {\n updateValue(\"uBackbuffer\", read);\n });\n },\n [updateRenderTarget, updateValue, updateParams, params]\n );\n\n return [\n updateFx,\n updateParams,\n {\n scene: scene,\n mesh: mesh,\n material: material,\n camera: camera,\n renderTarget: renderTarget,\n output: renderTarget.read.texture,\n },\n ];\n};\n","#usf ","precision highp float;\n\nvarying vec2 vUv;\nuniform float uProgress;\nuniform float uStrength;\nuniform float uWidth;\nuniform vec2 uEpicenter;\nuniform int uMode;\n\nfloat PI = 3.141592653589;\n\nvoid main() {\n\n\tvec2 uv = vUv;\n\n\tfloat progress = min(uProgress, 1.0);\n\tfloat progressFactor = sin(progress * PI);\n\n\tfloat border = progress - progress * progressFactor * uWidth;\n\tfloat blur = uStrength * progressFactor;\n\t\n\t// 0 ~ 1\n\tvec2 normalizeCenter = (uEpicenter + 1.0) / 2.0;\n\n\t// 0:center 1:horizontal 2:vertical\n\tfloat dist = uMode == 0 ? length(uv - normalizeCenter) : uMode == 1 ? length(uv.x - normalizeCenter.x) : length(uv.y - normalizeCenter.y);\n\n\t// Calculate the maximum distance to the four corners of the screen\n\tfloat maxDistance = max(\n\t\tlength(vec2(0.0, 0.0) - normalizeCenter),\n\t\tmax(\n\t\t\t\tlength(vec2(1.0, 0.0) - normalizeCenter),\n\t\t\t\tmax(\n\t\t\t\t\tlength(vec2(0.0, 1.0) - normalizeCenter),\n\t\t\t\t\tlength(vec2(1.0, 1.0) - normalizeCenter)\n\t\t\t\t)\n\t\t)\n\t);\n\n\t// Scale distance so that waves extend to the edge of the screen\n\tdist = maxDistance > 0.0 ? dist / maxDistance : dist;\n\n\tvec3 color = vec3(smoothstep(border - blur, border, dist) -\n smoothstep(progress, progress + blur, dist));\n\t\n\t// Ensure color is 0 when progress is 0,1\n\tcolor *= progressFactor;\n\n\tgl_FragColor = vec4(color, 1.0);\n}\n\n","import * as THREE from \"three\";\nimport { useMemo } from \"react\";\nimport vertexShader from \"./shader/main.vert\";\nimport fragmentShader from \"./shader/main.frag\";\nimport { WAVE_PARAMS } from \".\";\nimport { useAddObject } from \"../../../utils/useAddObject\";\nimport { MaterialProps } from \"../../types\";\nimport { MATERIAL_BASIC_PARAMS } from \"../../../libs/constants\";\nimport { createMaterialParameters } from \"../../../utils/createMaterialParameters\";\n\nexport class WaveMaterial extends THREE.ShaderMaterial {\n uniforms!: {\n uEpicenter: { value: THREE.Vector2 };\n uProgress: { value: number };\n uStrength: { value: number };\n uWidth: { value: number };\n uMode: { value: number };\n };\n}\n\nexport const useMesh = ({\n scene,\n onBeforeInit,\n}: { scene: THREE.Scene } & MaterialProps) => {\n const geometry = useMemo(() => new THREE.PlaneGeometry(2, 2), []);\n const material = useMemo(() => {\n const mat = new THREE.ShaderMaterial({\n ...createMaterialParameters(\n {\n uniforms: {\n uEpicenter: { value: WAVE_PARAMS.epicenter },\n uProgress: { value: WAVE_PARAMS.progress },\n uStrength: { value: WAVE_PARAMS.strength },\n uWidth: { value: WAVE_PARAMS.width },\n uMode: { value: 0 },\n },\n vertexShader: vertexShader,\n fragmentShader: fragmentShader,\n },\n onBeforeInit\n ),\n ...MATERIAL_BASIC_PARAMS,\n });\n\n return mat;\n }, [onBeforeInit]) as WaveMaterial;\n\n const mesh = useAddObject(scene, geometry, material, THREE.Mesh);\n\n return { material, mesh };\n};\n","import * as THREE from \"three\";\nimport { useCallback, useMemo } from \"react\";\nimport { useMesh } from \"./useMesh\";\nimport { RootState } from \"@react-three/fiber\";\nimport { useCamera } from \"../../../utils/useCamera\";\nimport { useSingleFBO } from \"../../../utils/useSingleFBO\";\nimport {\n CustomParams,\n setCustomUniform,\n setUniform,\n} from \"../../../utils/setUniforms\";\nimport { useParams } from \"../../../utils/useParams\";\nimport { HooksProps, HooksReturn } from \"../../types\";\nimport { getDpr } from \"../../../utils/getDpr\";\n\nexport type WaveParams = {\n /** -1.0 ~ 1.0 , default : `vec2(0.0,0.0)` */\n epicenter?: THREE.Vector2;\n /** 0.0 ~ 1.0 , default : `0.0` */\n progress?: number;\n /** default : `0.0` */\n width?: number;\n /** default : `0.0` */\n strength?: number;\n /** default : `center` */\n mode?: \"center\" | \"horizontal\" | \"vertical\";\n};\n\nexport type WaveObject = {\n scene: THREE.Scene;\n mesh: THREE.Mesh;\n material: THREE.Material;\n camera: THREE.Camera;\n renderTarget: THREE.WebGLRenderTarget;\n output: THREE.Texture;\n};\n\nexport const WAVE_PARAMS: WaveParams = Object.freeze({\n epicenter: new THREE.Vector2(0.0, 0.0),\n progress: 0.0,\n width: 0.0,\n strength: 0.0,\n mode: \"center\",\n});\n\n/**\n * @link https://github.com/FunTechInc/use-shader-fx\n */\nexport const useWave = ({\n size,\n dpr,\n renderTargetOptions,\n isSizeUpdate,\n onBeforeInit,\n}: HooksProps): HooksReturn => {\n const _dpr = getDpr(dpr);\n const scene = useMemo(() => new THREE.Scene(), []);\n const { material, mesh } = useMesh({ scene, onBeforeInit });\n const camera = useCamera(size);\n const [renderTarget, updateRenderTarget] = useSingleFBO({\n scene,\n camera,\n size,\n dpr: _dpr.fbo,\n isSizeUpdate,\n ...renderTargetOptions,\n });\n\n const [params, setParams] = useParams(WAVE_PARAMS);\n\n const updateValue = setUniform(material);\n const updateCustomValue = setCustomUniform(material);\n\n const updateParams = useCallback(\n (newParams?: WaveParams, customParams?: CustomParams) => {\n setParams(newParams);\n updateCustomValue(customParams);\n },\n [setParams, updateCustomValue]\n );\n\n const updateFx = useCallback(\n (\n rootState: RootState,\n newParams?: WaveParams,\n customParams?: CustomParams\n ) => {\n const { gl } = rootState;\n\n updateParams(newParams, customParams);\n\n updateValue(\"uEpicenter\", params.epicenter!);\n updateValue(\"uProgress\", params.progress!);\n updateValue(\"uWidth\", params.width!);\n updateValue(\"uStrength\", params.strength!);\n updateValue(\n \"uMode\",\n params.mode! === \"center\"\n ? 0\n : params.mode! === \"horizontal\"\n ? 1\n : 2\n );\n\n return updateRenderTarget(gl);\n },\n [updateRenderTarget, updateValue, params, updateParams]\n );\n\n return [\n updateFx,\n updateParams,\n {\n scene: scene,\n mesh: mesh,\n material: material,\n camera: camera,\n renderTarget: renderTarget,\n output: renderTarget.texture,\n },\n ];\n};\n","#usf ","precision highp float;\nvarying vec2 vUv;\n\nuniform sampler2D u_texture;\nuniform vec2 u_resolution;\nuniform vec3 u_keyColor;\nuniform float u_similarity;\nuniform float u_smoothness;\nuniform float u_spill;\n\nuniform vec4 u_color;\nuniform float u_contrast;\nuniform float u_brightness;\nuniform float u_gamma;\n\n// From https://github.com/libretro/glsl-shaders/blob/master/nnedi3/shaders/rgb-to-yuv.glsl\nvec2 RGBtoUV(vec3 rgb) {\n return vec2(\n rgb.r * -0.169 + rgb.g * -0.331 + rgb.b * 0.5 + 0.5,\n rgb.r * 0.5 + rgb.g * -0.419 + rgb.b * -0.081 + 0.5\n );\n}\nfloat getChromeDist(vec3 texColor){\n\tfloat chromaDist = distance(RGBtoUV(texColor), RGBtoUV(u_keyColor));\n\treturn chromaDist;\n}\n\nfloat getBoxFilteredChromaDist(vec3 rgb, vec2 uv)\n{\n\tvec2 pixel_size = vec2(1.) / u_resolution;\n\tvec2 h_pixel_size = pixel_size / 2.0;\n\tvec2 point_0 = vec2(pixel_size.x, h_pixel_size.y);\n\tvec2 point_1 = vec2(h_pixel_size.x, -pixel_size.y);\n\tfloat distVal = getChromeDist(texture2D(u_texture,uv-point_0).rgb);\n\tdistVal += getChromeDist(texture2D(u_texture,uv+point_0).rgb);\n\tdistVal += getChromeDist(texture2D(u_texture,uv-point_1).rgb);\n\tdistVal += getChromeDist(texture2D(u_texture,uv+point_1).rgb);\n\tdistVal *= 2.0;\n\tdistVal += getChromeDist(rgb);\n\treturn distVal / 9.0;\n}\n\nvec4 CalcColor(vec4 rgba)\n{\n\treturn vec4(pow(rgba.rgb, vec3(u_gamma, u_gamma, u_gamma)) * u_contrast + u_brightness, rgba.a);\n}\n\nvoid main() {\n\n\tvec2 uv = vUv;\n\n\tvec4 texColor = texture2D(u_texture, uv);\n\ttexColor.rgb *= (texColor.a > 0.) ? (1. / texColor.a) : 0.;\n\n\tfloat chromaDist = getBoxFilteredChromaDist(texColor.rgb,uv);\n\t\n\tfloat baseMask = chromaDist - u_similarity;\n\tfloat fullMask = pow(clamp(baseMask / u_smoothness, 0., 1.), 1.5);\n\t\n\ttexColor.rgba *= u_color;\n\ttexColor.a = fullMask;\n\n\tfloat spillVal = pow(clamp(baseMask / u_spill, 0., 1.), 1.5);\n\tfloat desat = clamp(texColor.r * 0.2126 + texColor.g * 0.7152 + texColor.b * 0.0722, 0., 1.);\n\ttexColor.rgb = mix(vec3(desat, desat, desat), texColor.rgb, spillVal);\n\n\tvec4 finColor = CalcColor(texColor);\n\n\tgl_FragColor = finColor;\n}","import { useMemo } from \"react\";\nimport * as THREE from \"three\";\nimport vertexShader from \"./shader/main.vert\";\nimport fragmentShader from \"./shader/main.frag\";\nimport { setUniform } from \"../../../utils/setUniforms\";\nimport { useResolution } from \"../../../utils/useResolution\";\nimport { useAddObject } from \"../../../utils/useAddObject\";\nimport { MaterialProps, Size } from \"../../types\";\nimport {\n MATERIAL_BASIC_PARAMS,\n DEFAULT_TEXTURE,\n} from \"../../../libs/constants\";\nimport { CHROMAKEY_PARAMS } from \".\";\nimport { createMaterialParameters } from \"../../../utils/createMaterialParameters\";\n\nexport class ChromaKeyMaterial extends THREE.ShaderMaterial {\n uniforms!: {\n u_texture: { value: THREE.Texture };\n u_resolution: { value: THREE.Vector2 };\n u_keyColor: { value: THREE.Color };\n u_similarity: { value: number };\n u_smoothness: { value: number };\n u_spill: { value: number };\n u_color: { value: THREE.Vector4 };\n u_contrast: { value: number };\n u_brightness: { value: number };\n u_gamma: { value: number };\n };\n}\n\nexport const useMesh = ({\n scene,\n size,\n dpr,\n onBeforeInit,\n}: {\n scene: THREE.Scene;\n size: Size;\n dpr: number | false;\n} & MaterialProps) => {\n const geometry = useMemo(() => new THREE.PlaneGeometry(2, 2), []);\n const material = useMemo(() => {\n const mat = new THREE.ShaderMaterial({\n ...createMaterialParameters(\n {\n uniforms: {\n u_texture: { value: DEFAULT_TEXTURE },\n u_resolution: { value: new THREE.Vector2() },\n u_keyColor: { value: CHROMAKEY_PARAMS.color },\n u_similarity: { value: CHROMAKEY_PARAMS.similarity },\n u_smoothness: { value: CHROMAKEY_PARAMS.smoothness },\n u_spill: { value: CHROMAKEY_PARAMS.spill },\n u_color: { value: CHROMAKEY_PARAMS.color },\n u_contrast: { value: CHROMAKEY_PARAMS.contrast },\n u_brightness: { value: CHROMAKEY_PARAMS.brightness },\n u_gamma: { value: CHROMAKEY_PARAMS.gamma },\n },\n vertexShader: vertexShader,\n fragmentShader: fragmentShader,\n },\n onBeforeInit\n ),\n ...MATERIAL_BASIC_PARAMS,\n });\n\n return mat;\n }, [onBeforeInit]) as ChromaKeyMaterial;\n\n const resolution = useResolution(size, dpr);\n setUniform(material)(\"u_resolution\", resolution.clone());\n\n const mesh = useAddObject(scene, geometry, material, THREE.Mesh);\n\n return { material, mesh };\n};\n","import { useCallback, useMemo } from \"react\";\nimport * as THREE from \"three\";\nimport { useMesh } from \"./useMesh\";\nimport { useCamera } from \"../../../utils/useCamera\";\nimport { RootState } from \"@react-three/fiber\";\nimport { useSingleFBO } from \"../../../utils/useSingleFBO\";\nimport {\n CustomParams,\n setCustomUniform,\n setUniform,\n} from \"../../../utils/setUniforms\";\nimport { HooksProps, HooksReturn } from \"../../types\";\nimport { useParams } from \"../../../utils/useParams\";\nimport { getDpr } from \"../../../utils/getDpr\";\nimport { DEFAULT_TEXTURE } from \"../../../libs/constants\";\n\nexport type ChromaKeyParams = {\n /** Process this texture with chroma key , default : `THREE.Texture` */\n texture?: THREE.Texture;\n /** key color for chromakey processing , default: `THREE.Color(0x00ff00)` */\n keyColor?: THREE.Color;\n /** If the similarity with the key color exceeds this value, it becomes transparent. , default : `0.2` */\n similarity?: number;\n /** smoothness , default : `0.1` */\n smoothness?: number;\n /** spill , default : `0.2` */\n spill?: number;\n /** tone correction , default : `THREE.Vector4(1.0, 1.0, 1.0, 1.0)` */\n color?: THREE.Vector4;\n /** contrast , default : `1.0` */\n contrast?: number;\n /** brightness , default : `0.0` */\n brightness?: number;\n /** gamma correction , default : `1.0` */\n gamma?: number;\n};\n\nexport type ChromaKeyObject = {\n scene: THREE.Scene;\n mesh: THREE.Mesh;\n material: THREE.Material;\n camera: THREE.Camera;\n renderTarget: THREE.WebGLRenderTarget;\n output: THREE.Texture;\n};\n\nexport const CHROMAKEY_PARAMS: ChromaKeyParams = Object.freeze({\n texture: DEFAULT_TEXTURE,\n keyColor: new THREE.Color(0x00ff00),\n similarity: 0.2,\n smoothness: 0.1,\n spill: 0.2,\n color: new THREE.Vector4(1.0, 1.0, 1.0, 1.0),\n contrast: 1.0,\n brightness: 0.0,\n gamma: 1.0,\n});\n\n/**\n * @link https://github.com/FunTechInc/use-shader-fx?tab=readme-ov-file#usage\n */\nexport const useChromaKey = ({\n size,\n dpr,\n renderTargetOptions,\n isSizeUpdate,\n onBeforeInit,\n}: HooksProps): HooksReturn => {\n const _dpr = getDpr(dpr);\n\n const scene = useMemo(() => new THREE.Scene(), []);\n const { material, mesh } = useMesh({\n scene,\n size,\n dpr: _dpr.shader,\n onBeforeInit,\n });\n const camera = useCamera(size);\n const [renderTarget, updateRenderTarget] = useSingleFBO({\n scene,\n camera,\n size,\n dpr: _dpr.fbo,\n isSizeUpdate,\n ...renderTargetOptions,\n });\n\n const [params, setParams] = useParams(CHROMAKEY_PARAMS);\n\n const updateValue = setUniform(material);\n const updateCustomValue = setCustomUniform(material);\n\n const updateParams = useCallback(\n (newParams?: ChromaKeyParams, customParams?: CustomParams) => {\n setParams(newParams);\n updateCustomValue(customParams);\n },\n [setParams, updateCustomValue]\n );\n\n const updateFx = useCallback(\n (\n rootState: RootState,\n newParams?: ChromaKeyParams,\n customParams?: CustomParams\n ) => {\n const { gl } = rootState;\n\n updateParams(newParams, customParams);\n\n updateValue(\"u_texture\", params.texture!);\n updateValue(\"u_keyColor\", params.keyColor!);\n updateValue(\"u_similarity\", params.similarity!);\n updateValue(\"u_smoothness\", params.smoothness!);\n updateValue(\"u_spill\", params.spill!);\n updateValue(\"u_color\", params.color!);\n updateValue(\"u_contrast\", params.contrast!);\n updateValue(\"u_brightness\", params.brightness!);\n updateValue(\"u_gamma\", params.gamma!);\n\n return updateRenderTarget(gl);\n },\n [updateRenderTarget, updateValue, params, updateParams]\n );\n\n return [\n updateFx,\n updateParams,\n {\n scene: scene,\n mesh: mesh,\n material: material,\n camera: camera,\n renderTarget: renderTarget,\n output: renderTarget.texture,\n },\n ];\n};\n","precision highp float;\n\nvarying vec2 vUv;\n#usf \n\n#usf \n\nvoid main() {\n\tvec4 usf_Position = vec4(position,1.);\n\tvUv = uv;\n\n\t#usf
\n\t\n\tgl_Position = usf_Position;\n}","precision highp float;\n\nvarying vec2 vUv;\n#usf \n\nuniform sampler2D uTexture;\nuniform sampler2D uBackbuffer;\nuniform float uTime;\nuniform vec2 uPointer;\nuniform vec2 uResolution;\n\n#usf \n\nvoid main() {\n\tvec4 usf_FragColor = vec4(1.);\n\n\t#usf
\n\t\n\tgl_FragColor = usf_FragColor;\n}","import { useMemo } from \"react\";\nimport * as THREE from \"three\";\nimport vertexShader from \"./shader/main.vert\";\nimport fragmentShader from \"./shader/main.frag\";\nimport { useAddObject } from \"../../../utils/useAddObject\";\nimport { MaterialProps, Size } from \"../../types\";\nimport { setUniform, useResolution } from \"../../..\";\nimport {\n MATERIAL_BASIC_PARAMS,\n DEFAULT_TEXTURE,\n} from \"../../../libs/constants\";\nimport { createMaterialParameters } from \"../../../utils/createMaterialParameters\";\n\nexport class BlankMaterial extends THREE.ShaderMaterial {\n uniforms!: {\n uTexture: { value: THREE.Texture };\n uBackbuffer: { value: THREE.Texture };\n uTime: { value: number };\n uPointer: { value: THREE.Vector2 };\n uResolution: { value: THREE.Vector2 };\n };\n}\nexport const useMesh = ({\n scene,\n size,\n dpr,\n onBeforeInit,\n}: {\n scene: THREE.Scene;\n size: Size;\n dpr: number | false;\n} & MaterialProps) => {\n const geometry = useMemo(() => new THREE.PlaneGeometry(2, 2), []);\n const material = useMemo(() => {\n const mat = new THREE.ShaderMaterial({\n ...createMaterialParameters(\n {\n uniforms: {\n uTexture: { value: DEFAULT_TEXTURE },\n uBackbuffer: { value: DEFAULT_TEXTURE },\n uTime: { value: 0 },\n uPointer: { value: new THREE.Vector2() },\n uResolution: { value: new THREE.Vector2() },\n },\n vertexShader: vertexShader,\n fragmentShader: fragmentShader,\n },\n onBeforeInit\n ),\n ...MATERIAL_BASIC_PARAMS,\n });\n return mat;\n }, [onBeforeInit]) as BlankMaterial;\n\n const resolution = useResolution(size, dpr);\n setUniform(material)(\"uResolution\", resolution.clone());\n\n const mesh = useAddObject(scene, geometry, material, THREE.Mesh);\n\n return { material, mesh };\n};\n","import { useCallback, useMemo } from \"react\";\nimport * as THREE from \"three\";\nimport { RootState } from \"@react-three/fiber\";\nimport { BlankMaterial, useMesh } from \"./useMesh\";\nimport { useCamera } from \"../../../utils/useCamera\";\nimport { useDoubleFBO, DoubleRenderTarget } from \"../../../utils/useDoubleFBO\";\nimport {\n CustomParams,\n setCustomUniform,\n setUniform,\n} from \"../../../utils/setUniforms\";\nimport { useParams } from \"../../../utils/useParams\";\nimport type { HooksProps, HooksReturn } from \"../../types\";\nimport { getDpr } from \"../../../utils/getDpr\";\nimport { UseFboProps } from \"../../..\";\nimport { DEFAULT_TEXTURE } from \"../../../libs/constants\";\n\nexport type BlankParams = {\n /** texture, default : `THREE.Texture()` */\n texture?: THREE.Texture;\n /** you can get into the rhythm ♪ , default : `false` */\n beat?: number | false;\n};\n\nexport type BlankObject = {\n scene: THREE.Scene;\n mesh: THREE.Mesh<\n THREE.BufferGeometry,\n BlankMaterial\n >;\n material: BlankMaterial;\n camera: THREE.Camera;\n renderTarget: DoubleRenderTarget;\n output: THREE.Texture;\n};\n\nexport const BLANK_PARAMS: BlankParams = Object.freeze({\n texture: DEFAULT_TEXTURE,\n beat: false,\n});\n\n/**\n * By default, it is a blank canvas with nothing drawn on it. You can customise the shaders using `onBeforeCompile`.\n * Fragment shaders have `uTexture`,`uBackbuffer`,`uTime`,`uPointer` and `uResolution` as default uniforms.\n *\n * ※ `usf_FragColor` overrides `gl_FragColor`\n *\n * ※ `usf_Position` overrides `gl_Position`\n * @link https://github.com/FunTechInc/use-shader-fx?tab=readme-ov-file#usage\n */\nexport const useBlank = ({\n size,\n dpr,\n renderTargetOptions,\n isSizeUpdate,\n onBeforeInit,\n}: HooksProps): HooksReturn => {\n const _dpr = getDpr(dpr);\n\n const scene = useMemo(() => new THREE.Scene(), []);\n\n const { material, mesh } = useMesh({\n scene,\n size,\n dpr: _dpr.shader,\n onBeforeInit,\n });\n\n const camera = useCamera(size);\n\n const fboProps = useMemo(\n () => ({\n scene,\n camera,\n size,\n dpr: _dpr.fbo,\n isSizeUpdate,\n ...renderTargetOptions,\n }),\n [scene, camera, size, _dpr.fbo, isSizeUpdate, renderTargetOptions]\n ) as UseFboProps;\n\n const [renderTarget, updateRenderTarget] = useDoubleFBO(fboProps);\n\n const [params, setParams] = useParams(BLANK_PARAMS);\n\n const updateValue = setUniform(material);\n const updateCustomValue = setCustomUniform(material);\n\n const updateParams = useCallback(\n (newParams?: BlankParams, customParams?: CustomParams) => {\n setParams(newParams);\n updateCustomValue(customParams);\n },\n [setParams, updateCustomValue]\n );\n\n const updateFx = useCallback(\n (\n rootState: RootState,\n newParams?: BlankParams,\n customParams?: CustomParams\n ) => {\n const { gl, clock, pointer } = rootState;\n\n updateParams(newParams, customParams);\n\n updateValue(\"uPointer\", pointer);\n updateValue(\"uTexture\", params.texture!);\n updateValue(\"uTime\", params.beat || clock.getElapsedTime());\n\n return updateRenderTarget(gl, ({ read }) => {\n updateValue(\"uBackbuffer\", read);\n });\n },\n [updateRenderTarget, updateValue, params, updateParams]\n );\n\n return [\n updateFx,\n updateParams,\n {\n scene: scene,\n mesh: mesh,\n material: material,\n camera: camera,\n renderTarget: renderTarget,\n output: renderTarget.read.texture,\n },\n ];\n};\n","precision highp float;\n\nvarying vec2 vUv;\n#usf \n\n#usf \n\nvoid main() {\n\tvec4 usf_Position = vec4(position,1.);\n\tvUv = uv;\n\n\t#usf
\n\t\n\tgl_Position = usf_Position;\n}","precision highp float;\n\nvarying vec2 vUv;\n#usf \n\nuniform vec2 uResolution;\n\n#usf \n\nvoid main() {\n\tvec4 usf_FragColor = vec4(1.);\n\n\t#usf
\n\t\n\tgl_FragColor = usf_FragColor;\n}","import { useMemo } from \"react\";\nimport * as THREE from \"three\";\nimport vertexShader from \"./shader/main.vert\";\nimport fragmentShader from \"./shader/main.frag\";\nimport { useAddObject } from \"../../../utils/useAddObject\";\nimport { MaterialProps, Size } from \"../../types\";\nimport { setUniform, useResolution } from \"../../..\";\nimport { MATERIAL_BASIC_PARAMS } from \"../../../libs/constants\";\nimport { createMaterialParameters } from \"../../../utils/createMaterialParameters\";\n\nexport class RawBlankMaterial extends THREE.ShaderMaterial {\n uniforms!: {\n uResolution: { value: THREE.Vector2 };\n };\n}\nexport const useMesh = ({\n scene,\n size,\n dpr,\n onBeforeInit,\n}: {\n scene: THREE.Scene;\n size: Size;\n dpr: number | false;\n} & MaterialProps) => {\n const geometry = useMemo(() => new THREE.PlaneGeometry(2, 2), []);\n const material = useMemo(() => {\n const mat = new THREE.ShaderMaterial({\n ...createMaterialParameters(\n {\n uniforms: {\n uResolution: { value: new THREE.Vector2() },\n },\n vertexShader: vertexShader,\n fragmentShader: fragmentShader,\n },\n onBeforeInit\n ),\n ...MATERIAL_BASIC_PARAMS,\n });\n return mat;\n }, [onBeforeInit]) as RawBlankMaterial;\n\n const resolution = useResolution(size, dpr);\n setUniform(material)(\"uResolution\", resolution.clone());\n\n const mesh = useAddObject(scene, geometry, material, THREE.Mesh);\n\n return { material, mesh };\n};\n","import { useCallback, useMemo } from \"react\";\nimport * as THREE from \"three\";\nimport { RootState } from \"@react-three/fiber\";\nimport { RawBlankMaterial, useMesh } from \"./useMesh\";\nimport { useCamera } from \"../../../utils/useCamera\";\nimport { CustomParams, setCustomUniform } from \"../../../utils/setUniforms\";\nimport type { HooksProps, HooksReturn } from \"../../types\";\nimport { getDpr } from \"../../../utils/getDpr\";\nimport { UseFboProps, useSingleFBO } from \"../../../utils/useSingleFBO\";\n\nexport type RawBlankParams = {};\n\nexport type RawBlankObject = {\n scene: THREE.Scene;\n mesh: THREE.Mesh<\n THREE.BufferGeometry,\n RawBlankMaterial\n >;\n material: RawBlankMaterial;\n camera: THREE.Camera;\n renderTarget: THREE.WebGLRenderTarget;\n output: THREE.Texture;\n};\n\nexport const RAWBLANK_PARAMS: RawBlankParams = Object.freeze({});\n\n/**\n * By default, it is a blank canvas with nothing drawn on it. You can customise the shaders using `onBeforeCompile`.\n * Fragment shaders have `uResolution` as default uniforms.\n *\n * ※ `usf_FragColor` overrides `gl_FragColor`\n *\n * ※ `usf_Position` overrides `gl_Position`\n * \n * `RawBlankParams` is an empty object. so you can't pass any parameters to second argument. Nothing will happen if you pass them.\n * ```tsx\n * useFrame((state) => {\n update(\n state,\n {},\n {\n uTime: state.clock.getElapsedTime(),\n }\n );\n });\n * ```\n * @link https://github.com/FunTechInc/use-shader-fx?tab=readme-ov-file#usage\n */\nexport const useRawBlank = ({\n size,\n dpr,\n renderTargetOptions,\n isSizeUpdate,\n onBeforeInit,\n}: HooksProps): HooksReturn => {\n const _dpr = getDpr(dpr);\n\n const scene = useMemo(() => new THREE.Scene(), []);\n\n const { material, mesh } = useMesh({\n scene,\n size,\n dpr: _dpr.shader,\n onBeforeInit,\n });\n\n const camera = useCamera(size);\n\n const fboProps = useMemo(\n () => ({\n scene,\n camera,\n size,\n dpr: _dpr.fbo,\n isSizeUpdate,\n ...renderTargetOptions,\n }),\n [scene, camera, size, _dpr.fbo, isSizeUpdate, renderTargetOptions]\n ) as UseFboProps;\n\n const [renderTarget, updateRenderTarget] = useSingleFBO(fboProps);\n\n const updateCustomValue = setCustomUniform(material);\n\n const updateParams = useCallback(\n (newParams?: RawBlankParams, customParams?: CustomParams) => {\n updateCustomValue(customParams);\n },\n [updateCustomValue]\n );\n\n const updateFx = useCallback(\n (\n rootState: RootState,\n newParams?: RawBlankParams,\n customParams?: CustomParams\n ) => {\n const { gl } = rootState;\n updateParams(newParams, customParams);\n return updateRenderTarget(gl);\n },\n [updateRenderTarget, updateParams]\n );\n\n return [\n updateFx,\n updateParams,\n {\n scene: scene,\n mesh: mesh,\n material: material,\n camera: camera,\n renderTarget: renderTarget,\n output: renderTarget.texture,\n },\n ];\n};\n","import * as THREE from \"three\";\nimport { useMemo } from \"react\";\nimport { useAddObject } from \"../../../../utils/useAddObject\";\n\ntype UseCreateObjectProps = {\n scene: THREE.Scene | false;\n geometry: THREE.BufferGeometry;\n material: THREE.ShaderMaterial;\n};\n\nexport type MorphParticlePoints = THREE.Points<\n THREE.BufferGeometry,\n THREE.ShaderMaterial\n>;\nexport type InteractiveMesh = THREE.Mesh<\n THREE.BufferGeometry,\n THREE.ShaderMaterial\n>;\n\nexport const useCreateObject = ({\n scene,\n geometry,\n material,\n}: UseCreateObjectProps) => {\n const points = useAddObject(\n scene,\n geometry,\n material,\n THREE.Points\n ) as MorphParticlePoints;\n\n // Generate a mesh for pointer\n const interactiveMesh = useAddObject(\n scene,\n useMemo(() => geometry.clone(), [geometry]),\n useMemo(() => material.clone(), [material]),\n THREE.Mesh\n ) as InteractiveMesh;\n interactiveMesh.visible = false;\n\n return {\n points,\n interactiveMesh,\n };\n};\n","uniform vec2 uResolution;\nuniform float uMorphProgress;\nuniform float uPointSize;\n\nuniform sampler2D uPicture;\nuniform bool uIsPicture;\nuniform sampler2D uAlphaPicture;\nuniform bool uIsAlphaPicture;\n\nuniform vec3 uColor0;\nuniform vec3 uColor1;\nuniform vec3 uColor2;\nuniform vec3 uColor3;\n\nuniform float uTime;\n\nuniform float uWobblePositionFrequency;\nuniform float uWobbleTimeFrequency;\nuniform float uWobbleStrength;\nuniform float uWarpPositionFrequency;\nuniform float uWarpTimeFrequency;\nuniform float uWarpStrength;\n\nuniform sampler2D uDisplacement;\nuniform bool uIsDisplacement;\nuniform float uDisplacementIntensity;\n\nuniform float uSizeRandomIntensity;\nuniform float uSizeRandomTimeFrequency;\nuniform float uSizeRandomMin;\nuniform float uSizeRandomMax;\n\nuniform float uMapArrayLength;\n\nuniform float uDivergence;\nuniform vec3 uDivergencePoint;\n\nvarying vec3 vColor;\nvarying float vPictureAlpha;\nvarying vec3 vDisplacementColor;\nvarying float vDisplacementIntensity;\nvarying float vMapArrayIndex;\n\n#usf \n\n#usf \n\n#usf \n\nfloat random3D(vec3 co) {\n\treturn fract(sin(dot(co.xyz ,vec3(12.9898, 78.233, 45.764))) * 43758.5453);\n}\n\nvoid main() {\n\tvec3 newPosition = position;\n\tvec2 newUv = uv;\n\t\n\t#usf \n\t#usf \n\n\t// displacement for `newPosition`\n\tvec3 displacement = uIsDisplacement ? texture2D(uDisplacement, newUv).rgb : vec3(0.0);\n\tfloat displacementIntensity = smoothstep(0., 1., displacement.g);\n\tvDisplacementColor = displacement;\n\tvDisplacementIntensity = displacementIntensity;\n\n\t// At this point displacement is 0 ~ 1, so normalize it to -1 ~ 1\n\tdisplacement = displacement * 2.-1.;\n\tdisplacement *= displacementIntensity * uDisplacementIntensity;\n\tnewPosition += displacement;\n\n\t// divergence\n\tvec3 divergenceDir = newPosition - uDivergencePoint;\n\tif (uDivergence > 0.0) {\n\t\tnewPosition += normalize(divergenceDir) * uDivergence;\n\t} else if (uDivergence < 0.0) {\n\t\tnewPosition -= normalize(divergenceDir) * abs(uDivergence);\n\t}\n\n\t// Final position\n\tvec4 modelPosition = modelMatrix * vec4(newPosition, 1.0);\n\tvec4 viewPosition = viewMatrix * modelPosition;\n\tvec4 projectedPosition = projectionMatrix * viewPosition;\n\n\t// wobble ※Do not calculate noise if uWobbleStrength is 0\n\tfloat wobble = uWobbleStrength > 0. ? getWobble(projectedPosition.xyz) : 0.0;\n\n\tgl_Position = projectedPosition += wobble;\n\t\n\t// If picture is true then display picture, otherwise 4 color linear interpolation\n\tvColor = uIsPicture ? texture2D(uPicture, newUv).rgb : mix(mix(uColor0, uColor1, newPosition.x), mix(uColor2, uColor3, newPosition.y), newPosition.z);\n\n\t// Set Alpha on picture's g channel\n\tvPictureAlpha = uIsAlphaPicture ? texture2D(uAlphaPicture, newUv).g : 1.;\n\n\t// Multiply the point size by picturAalpha. The size can also be adjusted with alphaMap.\n\t// If uSizeRandomTimeFrequency is greater than 0, the size will be randomly changed\n\tfloat sizeRand = uSizeRandomIntensity > 0. ? mix(uSizeRandomMin,uSizeRandomMax,(simplexNoise4d(vec4(newPosition,uTime * uSizeRandomTimeFrequency))*.5+.5)) * uSizeRandomIntensity : 1.;\n\tgl_PointSize = uPointSize * vPictureAlpha * uResolution.y * sizeRand;\n\tgl_PointSize *= (1.0 / - viewPosition.z);\n\n\t// mapArrayIndex\n\tvMapArrayIndex = uMapArrayLength > 0. ? floor(random3D(position) * uMapArrayLength) : 0.;\n}","precision highp float;\nprecision highp int;\n\nvarying vec3 vColor;\nvarying float vPictureAlpha;\nvarying vec3 vDisplacementColor;\nvarying float vDisplacementIntensity;\nvarying float vMapArrayIndex;\n\nuniform float uBlurAlpha;\nuniform float uBlurRadius;\nuniform sampler2D uMap;\nuniform bool uIsMap;\nuniform sampler2D uAlphaMap;\nuniform bool uIsAlphaMap;\nuniform float uDisplacementColorIntensity;\nuniform float uPointAlpha;\n\n#usf \n\nvoid main() { \n\tvec2 uv = gl_PointCoord;\n\tuv.y = 1.0 - uv.y;\n \n\t// make it a circle\n\tfloat distanceToCenter = length(uv - .5);\n\tfloat alpha = clamp(uBlurRadius / distanceToCenter - (1.-uBlurAlpha) , 0. , 1.);\n\n\t// Map if there is a map\t\n\tvec4 mapArrayColor;\n\t#usf \n\tvec4 mapColor = isMapArray ? mapArrayColor : uIsMap ? texture2D(uMap,uv) : vec4(1.);\n\tvec3 finalColor = isMapArray || uIsMap ? mapColor.rgb : vColor;\n\n\t// Mix with finalColor if displacement is true\n\tfloat mixIntensity = clamp(uDisplacementColorIntensity * vDisplacementIntensity,0.,1.);\n\tfinalColor = vDisplacementIntensity > 0. ? mix(finalColor,vDisplacementColor,mixIntensity) : finalColor;\n\n\t// get alpha map\n\tfloat alphaMap = uIsAlphaMap ? texture2D(uAlphaMap,uv).g : 1.;\n\n\tgl_FragColor = vec4(finalColor,alpha * vPictureAlpha * alphaMap * mapColor.a * uPointAlpha);\n}\n","import * as THREE from \"three\";\nimport { ISDEV } from \"../../../../libs/constants\";\n\nexport const rewriteVertexShader = (\n modifeidAttributes: Float32Array[],\n targetGeometry: THREE.BufferGeometry,\n targetAttibute: \"position\" | \"uv\",\n vertexShader: string,\n itemSize: number\n) => {\n const vTargetName =\n targetAttibute === \"position\" ? \"positionTarget\" : \"uvTarget\";\n const vAttributeRewriteKey =\n targetAttibute === \"position\"\n ? \"#usf \"\n : \"#usf \";\n const vTransitionRewriteKey =\n targetAttibute === \"position\"\n ? \"#usf \"\n : \"#usf \";\n const vListName =\n targetAttibute === \"position\" ? \"positionsList\" : \"uvsList\";\n const vMorphTransition =\n targetAttibute === \"position\"\n ? `\n\t\t\t\tfloat scaledProgress = uMorphProgress * ${modifeidAttributes.length - 1}.;\n\t\t\t\tint baseIndex = int(floor(scaledProgress));\t\t\n\t\t\t\tbaseIndex = clamp(baseIndex, 0, ${modifeidAttributes.length - 1});\t\t\n\t\t\t\tfloat progress = fract(scaledProgress);\n\t\t\t\tint nextIndex = baseIndex + 1;\n\t\t\t\tnewPosition = mix(positionsList[baseIndex], positionsList[nextIndex], progress);\n\t\t\t`\n : \"newUv = mix(uvsList[baseIndex], uvsList[nextIndex], progress);\";\n\n if (modifeidAttributes.length > 0) {\n // Delete the position at initialization and add the position after normalization\n targetGeometry.deleteAttribute(targetAttibute);\n targetGeometry.setAttribute(\n targetAttibute,\n new THREE.BufferAttribute(modifeidAttributes[0], itemSize)\n );\n\n let stringToAddToMorphAttibutes = \"\";\n let stringToAddToMorphAttibutesList = \"\";\n\n modifeidAttributes.forEach((target, index) => {\n targetGeometry.setAttribute(\n `${vTargetName}${index}`,\n new THREE.BufferAttribute(target, itemSize)\n );\n stringToAddToMorphAttibutes += `attribute vec${itemSize} ${vTargetName}${index};\\n`;\n if (index === 0) {\n stringToAddToMorphAttibutesList += `${vTargetName}${index}`;\n } else {\n stringToAddToMorphAttibutesList += `,${vTargetName}${index}`;\n }\n });\n\n vertexShader = vertexShader.replace(\n `${vAttributeRewriteKey}`,\n stringToAddToMorphAttibutes\n );\n vertexShader = vertexShader.replace(\n `${vTransitionRewriteKey}`,\n `vec${itemSize} ${vListName}[${modifeidAttributes.length}] = vec${itemSize}[](${stringToAddToMorphAttibutesList});\n\t\t\t\t${vMorphTransition}\n\t\t\t`\n );\n } else {\n vertexShader = vertexShader.replace(`${vAttributeRewriteKey}`, \"\");\n vertexShader = vertexShader.replace(`${vTransitionRewriteKey}`, \"\");\n if (!targetGeometry?.attributes[targetAttibute]?.array) {\n ISDEV &&\n console.error(\n `use-shader-fx:geometry.attributes.${targetAttibute}.array is not found`\n );\n }\n }\n\n return vertexShader;\n};\n","import * as THREE from \"three\";\n\n/**\n * Calculate the maximum length of attribute (position and uv) to match the length of all lists. Randomly map missing attributes when matching to maximum length\n * */\nexport const modifyAttributes = (\n attribute: Float32Array[] | undefined,\n targetGeometry: THREE.BufferGeometry,\n targetAttibute: \"position\" | \"uv\",\n itemSize: number\n) => {\n let modifiedAttribute: Float32Array[] = [];\n if (attribute && attribute.length > 0) {\n if (targetGeometry?.attributes[targetAttibute]?.array) {\n modifiedAttribute = [\n targetGeometry.attributes[targetAttibute].array as Float32Array,\n ...attribute,\n ];\n } else {\n modifiedAttribute = attribute;\n }\n\n const maxLength = Math.max(...modifiedAttribute.map((arr) => arr.length));\n\n modifiedAttribute.forEach((arr, i) => {\n if (arr.length < maxLength) {\n const diff = (maxLength - arr.length) / itemSize;\n const addArray = [];\n const oldArray = Array.from(arr);\n for (let i = 0; i < diff; i++) {\n const randomIndex =\n Math.floor((arr.length / itemSize) * Math.random()) *\n itemSize;\n for (let j = 0; j < itemSize; j++) {\n addArray.push(oldArray[randomIndex + j]);\n }\n }\n modifiedAttribute[i] = new Float32Array([...oldArray, ...addArray]);\n }\n });\n }\n return modifiedAttribute;\n};\n","import * as THREE from \"three\";\n\nexport const rewriteFragmentShader = (\n mapArray: THREE.Texture[] | undefined,\n fragmentShader: string\n) => {\n let mapArrayShader = \"\";\n const mapArrayUniforms: any = {};\n let textureSwitcherCode = \"mapArrayColor = \";\n\n if (mapArray && mapArray.length > 0) {\n mapArray.forEach((map, index) => {\n const condition = `vMapArrayIndex < ${index}.1`; // Comparison with a number with .1 added as the handling of floating points may vary between GPU drivers\n const action = `texture2D(uMapArray${index}, uv)`;\n textureSwitcherCode += `( ${condition} ) ? ${action} : `;\n mapArrayShader += `\n uniform sampler2D uMapArray${index};\n `;\n mapArrayUniforms[`uMapArray${index}`] = { value: map };\n });\n textureSwitcherCode += \"vec4(1.);\";\n mapArrayShader += `bool isMapArray = true;`;\n mapArrayUniforms[\"uMapArrayLength\"] = { value: mapArray.length };\n } else {\n textureSwitcherCode += \"vec4(1.0);\";\n mapArrayShader += `bool isMapArray = false;`;\n mapArrayUniforms[\"uMapArrayLength\"] = { value: 0 };\n }\n const rewritedFragmentShader = fragmentShader\n .replace(`#usf `, textureSwitcherCode)\n .replace(`#usf `, mapArrayShader);\n\n return { rewritedFragmentShader, mapArrayUniforms };\n};\n","import * as THREE from \"three\";\nimport { useMemo } from \"react\";\nimport { useResolution } from \"../../../../utils/useResolution\";\nimport { setUniform } from \"../../../../utils/setUniforms\";\nimport vertexShader from \"../shaders/main.vert\";\nimport fragmentShader from \"../shaders/main.frag\";\nimport { MORPHPARTICLES_PARAMS } from \"..\";\nimport {\n DEFAULT_TEXTURE,\n ISDEV,\n MATERIAL_BASIC_PARAMS,\n} from \"../../../../libs/constants\";\nimport { rewriteVertexShader } from \"./rewriteVertexShader\";\nimport { modifyAttributes } from \"./modifyAttributes\";\nimport { rewriteFragmentShader } from \"./rewriteFragmentShader\";\nimport { MaterialProps, Size } from \"../../../types\";\nimport { createMaterialParameters } from \"../../../../utils/createMaterialParameters\";\n\nexport class MorphParticlesMaterial extends THREE.ShaderMaterial {\n uniforms!: {\n uResolution: { value: THREE.Vector2 };\n uMorphProgress: { value: number };\n uBlurAlpha: { value: number };\n uBlurRadius: { value: number };\n uPointSize: { value: number };\n uPointAlpha: { value: number };\n uPicture: { value: THREE.Texture };\n uIsPicture: { value: boolean };\n uAlphaPicture: { value: THREE.Texture };\n uIsAlphaPicture: { value: boolean };\n uColor0: { value: THREE.Color };\n uColor1: { value: THREE.Color };\n uColor2: { value: THREE.Color };\n uColor3: { value: THREE.Color };\n uMap: { value: THREE.Texture };\n uIsMap: { value: boolean };\n uAlphaMap: { value: THREE.Texture };\n uIsAlphaMap: { value: boolean };\n uTime: { value: number };\n uWobblePositionFrequency: { value: number };\n uWobbleTimeFrequency: { value: number };\n uWobbleStrength: { value: number };\n uWarpPositionFrequency: { value: number };\n uWarpTimeFrequency: { value: number };\n uWarpStrength: { value: number };\n uDisplacement: { value: THREE.Texture };\n uIsDisplacement: { value: boolean };\n uDisplacementIntensity: { value: number };\n uDisplacementColorIntensity: { value: number };\n uSizeRandomIntensity: { value: number };\n uSizeRandomTimeFrequency: { value: number };\n uSizeRandomMin: { value: number };\n uSizeRandomMax: { value: number };\n uDivergence: { value: number };\n uDivergencePoint: { value: THREE.Vector3 };\n };\n}\n\nexport const useMaterial = ({\n size,\n dpr,\n geometry,\n positions,\n uvs,\n mapArray,\n onBeforeInit,\n}: {\n size: Size;\n dpr: number | false;\n geometry: THREE.BufferGeometry;\n positions?: Float32Array[];\n uvs?: Float32Array[];\n mapArray?: THREE.Texture[];\n} & MaterialProps) => {\n const modifiedPositions = useMemo(\n () => modifyAttributes(positions, geometry, \"position\", 3),\n [positions, geometry]\n );\n\n const modifiedUvs = useMemo(\n () => modifyAttributes(uvs, geometry, \"uv\", 2),\n [uvs, geometry]\n );\n\n const material = useMemo(() => {\n if (modifiedPositions.length !== modifiedUvs.length) {\n ISDEV &&\n console.log(\"use-shader-fx:positions and uvs are not matched\");\n }\n\n // vertex\n const rewritedVertexShader = rewriteVertexShader(\n modifiedUvs,\n geometry,\n \"uv\",\n rewriteVertexShader(\n modifiedPositions,\n geometry,\n \"position\",\n vertexShader,\n 3\n ),\n 2\n );\n\n // fragment\n const { rewritedFragmentShader, mapArrayUniforms } =\n rewriteFragmentShader(mapArray, fragmentShader);\n\n const mat = new THREE.ShaderMaterial({\n ...createMaterialParameters(\n {\n uniforms: {\n uResolution: { value: new THREE.Vector2(0, 0) },\n uMorphProgress: {\n value: MORPHPARTICLES_PARAMS.morphProgress,\n },\n uBlurAlpha: { value: MORPHPARTICLES_PARAMS.blurAlpha },\n uBlurRadius: { value: MORPHPARTICLES_PARAMS.blurRadius },\n uPointSize: { value: MORPHPARTICLES_PARAMS.pointSize },\n uPointAlpha: { value: MORPHPARTICLES_PARAMS.pointAlpha },\n uPicture: { value: DEFAULT_TEXTURE },\n uIsPicture: { value: false },\n uAlphaPicture: { value: DEFAULT_TEXTURE },\n uIsAlphaPicture: { value: false },\n uColor0: { value: MORPHPARTICLES_PARAMS.color0 },\n uColor1: { value: MORPHPARTICLES_PARAMS.color1 },\n uColor2: { value: MORPHPARTICLES_PARAMS.color2 },\n uColor3: { value: MORPHPARTICLES_PARAMS.color3 },\n uMap: { value: DEFAULT_TEXTURE },\n uIsMap: { value: false },\n uAlphaMap: { value: DEFAULT_TEXTURE },\n uIsAlphaMap: { value: false },\n uTime: { value: 0 },\n uWobblePositionFrequency: {\n value: MORPHPARTICLES_PARAMS.wobblePositionFrequency,\n },\n uWobbleTimeFrequency: {\n value: MORPHPARTICLES_PARAMS.wobbleTimeFrequency,\n },\n uWobbleStrength: {\n value: MORPHPARTICLES_PARAMS.wobbleStrength,\n },\n uWarpPositionFrequency: {\n value: MORPHPARTICLES_PARAMS.warpPositionFrequency,\n },\n uWarpTimeFrequency: {\n value: MORPHPARTICLES_PARAMS.warpTimeFrequency,\n },\n uWarpStrength: { value: MORPHPARTICLES_PARAMS.warpStrength },\n uDisplacement: { value: DEFAULT_TEXTURE },\n uIsDisplacement: { value: false },\n uDisplacementIntensity: {\n value: MORPHPARTICLES_PARAMS.displacementIntensity,\n },\n uDisplacementColorIntensity: {\n value: MORPHPARTICLES_PARAMS.displacementColorIntensity,\n },\n uSizeRandomIntensity: {\n value: MORPHPARTICLES_PARAMS.sizeRandomIntensity,\n },\n uSizeRandomTimeFrequency: {\n value: MORPHPARTICLES_PARAMS.sizeRandomTimeFrequency,\n },\n uSizeRandomMin: {\n value: MORPHPARTICLES_PARAMS.sizeRandomMin,\n },\n uSizeRandomMax: {\n value: MORPHPARTICLES_PARAMS.sizeRandomMax,\n },\n uDivergence: { value: MORPHPARTICLES_PARAMS.divergence },\n uDivergencePoint: {\n value: MORPHPARTICLES_PARAMS.divergencePoint,\n },\n ...mapArrayUniforms,\n },\n vertexShader: rewritedVertexShader,\n fragmentShader: rewritedFragmentShader,\n },\n onBeforeInit\n ),\n ...MATERIAL_BASIC_PARAMS,\n blending: THREE.AdditiveBlending,\n // Must be transparent\n transparent: true,\n });\n\n return mat;\n }, [\n geometry,\n modifiedPositions,\n modifiedUvs,\n mapArray,\n onBeforeInit,\n ]) as MorphParticlesMaterial;\n\n const resolution = useResolution(size, dpr);\n setUniform(material)(\"uResolution\", resolution.clone());\n\n return { material, modifiedPositions, modifiedUvs };\n};\n","import * as THREE from \"three\";\nimport { RootState } from \"@react-three/fiber\";\nimport {\n InteractiveMesh,\n MorphParticlePoints,\n useCreateObject,\n} from \"./utils/useCreateObject\";\nimport { useMaterial } from \"./utils/useMaterial\";\nimport { MorphParticlesParams } from \".\";\nimport {\n setUniform,\n CustomParams,\n setCustomUniform,\n} from \"../../../utils/setUniforms\";\nimport { useCallback, useMemo } from \"react\";\nimport { Create3DHooksProps } from \"../types\";\nimport { Dpr, Size } from \"../../types\";\nimport { getDpr } from \"../../../utils/getDpr\";\n\nexport type UseCreateMorphParticlesProps = {\n size: Size;\n dpr: Dpr;\n /** default : `THREE.SphereGeometry(1, 32, 32)` */\n geometry?: THREE.BufferGeometry;\n positions?: Float32Array[];\n uvs?: Float32Array[];\n /** Array of textures to map to points. Mapped at random. */\n mapArray?: THREE.Texture[];\n};\n\ntype UpdateUniform = (\n rootState: RootState | null,\n newParams?: MorphParticlesParams,\n customParams?: CustomParams\n) => void;\n\ntype UseCreateMorphParticlesReturn = [\n UpdateUniform,\n {\n points: MorphParticlePoints;\n interactiveMesh: InteractiveMesh;\n positions: Float32Array[];\n uvs: Float32Array[];\n }\n];\n\nexport const useCreateMorphParticles = ({\n size,\n dpr,\n scene = false,\n geometry,\n positions,\n uvs,\n mapArray,\n onBeforeInit,\n}: Create3DHooksProps &\n UseCreateMorphParticlesProps): UseCreateMorphParticlesReturn => {\n const _dpr = getDpr(dpr);\n\n const morphGeometry = useMemo(() => {\n const geo = geometry || new THREE.SphereGeometry(1, 32, 32);\n geo.setIndex(null);\n // Since it is a particle, normal is not necessary\n geo.deleteAttribute(\"normal\");\n return geo;\n }, [geometry]);\n\n const { material, modifiedPositions, modifiedUvs } = useMaterial({\n size,\n dpr: _dpr.shader,\n geometry: morphGeometry,\n positions,\n uvs,\n mapArray,\n onBeforeInit,\n });\n\n const { points, interactiveMesh } = useCreateObject({\n scene,\n geometry: morphGeometry,\n material,\n });\n\n const updateValue = setUniform(material);\n const updateCustomValue = setCustomUniform(material);\n\n const updateUniform = useCallback(\n (rootState, newParams, customParams) => {\n if (rootState) {\n updateValue(\n \"uTime\",\n newParams?.beat || rootState.clock.getElapsedTime()\n );\n }\n if (newParams === undefined) {\n return;\n }\n updateValue(\"uMorphProgress\", newParams.morphProgress);\n updateValue(\"uBlurAlpha\", newParams.blurAlpha);\n updateValue(\"uBlurRadius\", newParams.blurRadius);\n updateValue(\"uPointSize\", newParams.pointSize);\n updateValue(\"uPointAlpha\", newParams.pointAlpha);\n if (newParams.picture) {\n updateValue(\"uPicture\", newParams.picture);\n updateValue(\"uIsPicture\", true);\n } else if (newParams.picture === false) {\n updateValue(\"uIsPicture\", false);\n }\n if (newParams.alphaPicture) {\n updateValue(\"uAlphaPicture\", newParams.alphaPicture);\n updateValue(\"uIsAlphaPicture\", true);\n } else if (newParams.alphaPicture === false) {\n updateValue(\"uIsAlphaPicture\", false);\n }\n updateValue(\"uColor0\", newParams.color0);\n updateValue(\"uColor1\", newParams.color1);\n updateValue(\"uColor2\", newParams.color2);\n updateValue(\"uColor3\", newParams.color3);\n if (newParams.map) {\n updateValue(\"uMap\", newParams.map);\n updateValue(\"uIsMap\", true);\n } else if (newParams.map === false) {\n updateValue(\"uIsMap\", false);\n }\n if (newParams.alphaMap) {\n updateValue(\"uAlphaMap\", newParams.alphaMap);\n updateValue(\"uIsAlphaMap\", true);\n } else if (newParams.alphaMap === false) {\n updateValue(\"uIsAlphaMap\", false);\n }\n updateValue(\"uWobbleStrength\", newParams.wobbleStrength);\n updateValue(\n \"uWobblePositionFrequency\",\n newParams.wobblePositionFrequency\n );\n updateValue(\"uWobbleTimeFrequency\", newParams.wobbleTimeFrequency);\n updateValue(\"uWarpStrength\", newParams.warpStrength);\n updateValue(\"uWarpPositionFrequency\", newParams.warpPositionFrequency);\n updateValue(\"uWarpTimeFrequency\", newParams.warpTimeFrequency);\n if (newParams.displacement) {\n updateValue(\"uDisplacement\", newParams.displacement);\n updateValue(\"uIsDisplacement\", true);\n } else if (newParams.displacement === false) {\n updateValue(\"uIsDisplacement\", false);\n }\n updateValue(\"uDisplacementIntensity\", newParams.displacementIntensity);\n updateValue(\n \"uDisplacementColorIntensity\",\n newParams.displacementColorIntensity\n );\n updateValue(\"uSizeRandomIntensity\", newParams.sizeRandomIntensity);\n updateValue(\n \"uSizeRandomTimeFrequency\",\n newParams.sizeRandomTimeFrequency\n );\n updateValue(\"uSizeRandomMin\", newParams.sizeRandomMin);\n updateValue(\"uSizeRandomMax\", newParams.sizeRandomMax);\n updateValue(\"uDivergence\", newParams.divergence);\n updateValue(\"uDivergencePoint\", newParams.divergencePoint);\n\n updateCustomValue(customParams);\n },\n [updateValue, updateCustomValue]\n );\n\n return [\n updateUniform,\n {\n points,\n interactiveMesh,\n positions: modifiedPositions,\n uvs: modifiedUvs,\n },\n ];\n};\n","import * as THREE from \"three\";\nimport { useCallback, useMemo } from \"react\";\nimport { RootState } from \"@react-three/fiber\";\nimport { useSingleFBO } from \"../../../utils/useSingleFBO\";\nimport { HooksReturn } from \"../../types\";\nimport {\n useCreateMorphParticles,\n UseCreateMorphParticlesProps,\n} from \"./useCreateMorphParticles\";\nimport { HooksProps3D } from \"../types\";\nimport { InteractiveMesh, MorphParticlePoints } from \"./utils/useCreateObject\";\nimport { getDpr } from \"../../../utils/getDpr\";\nimport { CustomParams } from \"../../../utils/setUniforms\";\n\nexport type MorphParticlesParams = {\n /** progress value to morph vertices,0~1 */\n morphProgress?: number;\n blurAlpha?: number;\n blurRadius?: number;\n pointSize?: number;\n /** default : `1` */\n pointAlpha?: number;\n /** Since the color is extracted based on the attribute `uv`, the intended behavior will not occur if there is no uv in the attribute. */\n picture?: THREE.Texture | false;\n /** The alpha map is a grayscale texture that controls the opacity across the surface (black: fully transparent; white: fully opaque). use the green channel when sampling this texture. It also affects the size of the point. default : `false` */\n alphaPicture?: THREE.Texture | false;\n color0?: THREE.Color;\n color1?: THREE.Color;\n color2?: THREE.Color;\n color3?: THREE.Color;\n /** This maps to point,texture */\n map?: THREE.Texture | false;\n /** The alpha map is a grayscale texture that controls the opacity across the surface (black: fully transparent; white: fully opaque). use the green channel when sampling this texture. default : `false` */\n alphaMap?: THREE.Texture | false;\n /** If ​​wobbleStrength is set to 0, wobble will stop. It will also affect noise calculation, default : `0` */\n wobbleStrength?: number;\n wobblePositionFrequency?: number;\n wobbleTimeFrequency?: number;\n /** default : `0` */\n warpStrength?: number;\n warpPositionFrequency?: number;\n warpTimeFrequency?: number;\n /** Manipulate the vertices using the color channels of this texture. The strength of the displacement changes depending on the g channel of this texture */\n displacement?: THREE.Texture | false;\n /** Strength of displacement. The strength of displacement depends on g ch, but is the value multiplied by it , default : `1` */\n displacementIntensity?: number;\n /** Strength to reflect color ch of displacement texture */\n displacementColorIntensity?: number;\n /** If set to 0, noise calculation stops, default : `0` */\n sizeRandomIntensity?: number;\n sizeRandomTimeFrequency?: number;\n sizeRandomMin?: number;\n sizeRandomMax?: number;\n /** Divergence rate of a point. Negative cases are dense, positive cases are divergent, default : `0` */\n divergence?: number;\n /** Divergence centre point, default : `THREE.Vector3(0)` */\n divergencePoint?: THREE.Vector3;\n /** you can get into the rhythm ♪ , default : `false` */\n beat?: number | false;\n};\n\nexport type MorphParticlesObject = {\n scene: THREE.Scene;\n points: MorphParticlePoints;\n interactiveMesh: InteractiveMesh;\n renderTarget: THREE.WebGLRenderTarget;\n output: THREE.Texture;\n positions: Float32Array[];\n uvs: Float32Array[];\n};\n\nexport const MORPHPARTICLES_PARAMS: MorphParticlesParams = Object.freeze({\n morphProgress: 0,\n blurAlpha: 0.9,\n blurRadius: 0.05,\n pointSize: 0.05,\n pointAlpha: 1,\n picture: false,\n alphaPicture: false,\n color0: new THREE.Color(0xff0000),\n color1: new THREE.Color(0x00ff00),\n color2: new THREE.Color(0x0000ff),\n color3: new THREE.Color(0xffff00),\n map: false,\n alphaMap: false,\n wobbleStrength: 0.0,\n wobblePositionFrequency: 0.5,\n wobbleTimeFrequency: 0.5,\n warpStrength: 0.0,\n warpPositionFrequency: 0.5,\n warpTimeFrequency: 0.5,\n displacement: false,\n displacementIntensity: 1,\n displacementColorIntensity: 0,\n sizeRandomIntensity: 0,\n sizeRandomTimeFrequency: 0.2,\n sizeRandomMin: 0.5,\n sizeRandomMax: 1.5,\n divergence: 0,\n divergencePoint: new THREE.Vector3(0),\n beat: false,\n});\n\n/**\n * @link https://github.com/FunTechInc/use-shader-fx\n */\nexport const useMorphParticles = ({\n size,\n dpr,\n isSizeUpdate,\n renderTargetOptions,\n camera,\n geometry,\n positions,\n uvs,\n onBeforeInit,\n}: HooksProps3D & UseCreateMorphParticlesProps): HooksReturn<\n MorphParticlesParams,\n MorphParticlesObject,\n CustomParams\n> => {\n const _dpr = getDpr(dpr);\n\n const scene = useMemo(() => new THREE.Scene(), []);\n\n const [\n updateUniform,\n {\n points,\n interactiveMesh,\n positions: generatedPositions,\n uvs: generatedUvs,\n },\n ] = useCreateMorphParticles({\n scene,\n size,\n dpr,\n geometry,\n positions,\n uvs,\n onBeforeInit,\n });\n\n const [renderTarget, updateRenderTarget] = useSingleFBO({\n scene,\n camera,\n size,\n dpr: _dpr.fbo,\n isSizeUpdate,\n depthBuffer: true,\n ...renderTargetOptions,\n });\n\n const updateFx = useCallback(\n (\n rootState: RootState,\n newParams?: MorphParticlesParams,\n customParams?: CustomParams\n ) => {\n updateUniform(rootState, newParams, customParams);\n return updateRenderTarget(rootState.gl);\n },\n [updateRenderTarget, updateUniform]\n );\n\n const updateParams = useCallback(\n (newParams?: MorphParticlesParams, customParams?: CustomParams) => {\n updateUniform(null, newParams, customParams);\n },\n [updateUniform]\n );\n\n return [\n updateFx,\n updateParams,\n {\n scene,\n points,\n interactiveMesh,\n renderTarget,\n output: renderTarget.texture,\n positions: generatedPositions,\n uvs: generatedUvs,\n },\n ];\n};\n","import * as THREE from \"three\";\n\nexport const rewriteVertexShader = (\n parameters: THREE.WebGLProgramParametersWithUniforms\n) => {\n const isDepth = parameters.shaderType === \"MeshDepthMaterial\";\n\n parameters.vertexShader = parameters.vertexShader.replace(\n \"#include \",\n `\n\t\t\tvec3 objectNormal = usf_Normal;\n\t\t\t#ifdef USE_TANGENT\n\t\t\tvec3 objectTangent = vec3( tangent.xyz );\n\t\t\t#endif\n\t\t`\n );\n\n parameters.vertexShader = parameters.vertexShader.replace(\n \"#include \",\n `\n\t\t\tvec3 transformed = usf_Position;\n\t\t\t#ifdef USE_ALPHAHASH\n\t\t\tvPosition = vec3( position );\n\t\t\t#endif\n\t\t`\n );\n\n parameters.vertexShader = parameters.vertexShader.replace(\n \"void main() {\",\n `\n\t\tuniform float uTime;\n\t\tuniform float uWobblePositionFrequency;\n\t\tuniform float uWobbleTimeFrequency;\n\t\tuniform float uWobbleStrength;\n\t\tuniform float uWarpPositionFrequency;\n\t\tuniform float uWarpTimeFrequency;\n\t\tuniform float uWarpStrength;\n\n\t\t${isDepth ? \"attribute vec4 tangent;\" : \"\"}\n\t\t\n\t\tvarying float vWobble;\n\t\tvarying vec2 vPosition;\n\t\t\n\t\t// edge\n\t\tvarying vec3 vEdgeNormal;\n\t\tvarying vec3 vEdgeViewPosition;\n\n\t\t#usf \n\n\t\tvoid main() {\n\t\t\n\t\t\tvec3 usf_Position = position;\n\t\t\tvec3 usf_Normal = normal;\n\t\t\tvec3 biTangent = cross(normal, tangent.xyz);\n\t\t\t\n\t\t\t// Neighbours positions\n\t\t\tfloat shift = 0.01;\n\t\t\tvec3 positionA = usf_Position + tangent.xyz * shift;\n\t\t\tvec3 positionB = usf_Position + biTangent * shift;\n\t\t\t\n\t\t\t// wobble\n\t\t\tfloat wobble = (uWobbleStrength > 0.) ? getWobble(usf_Position) : 0.0;\n\t\t\tfloat wobblePositionA = (uWobbleStrength > 0.) ? getWobble(positionA) : 0.0;\n\t\t\tfloat wobblePositionB = (uWobbleStrength > 0.) ? getWobble(positionB) : 0.0;\n\t\t\t\n\t\t\tusf_Position += wobble * normal;\n\t\t\tpositionA += wobblePositionA * normal;\n\t\t\tpositionB += wobblePositionB * normal;\n\n\t\t\t// Compute normal\n\t\t\tvec3 toA = normalize(positionA - usf_Position);\n\t\t\tvec3 toB = normalize(positionB - usf_Position);\n\t\t\tusf_Normal = cross(toA, toB);\n\t\t\t\n\t\t\t// Varying\n\t\t\tvPosition = usf_Position.xy;\n\t\t\tvWobble = wobble/uWobbleStrength;\n\t\t\t\n\t\t\tvEdgeNormal = normalize(normalMatrix * usf_Normal);\n\t\t\tvec4 viewPosition = viewMatrix * modelMatrix * vec4(usf_Position, 1.0);\n\t\t\tvEdgeViewPosition = normalize(viewPosition.xyz);\n\t\t`\n );\n};\n","import * as THREE from \"three\";\n\nexport const rewriteFragmentShader = (\n parameters: THREE.WebGLProgramParametersWithUniforms\n) => {\n // diffuse color , Manipulate color mixing ratio with `uColorMix`\n parameters.fragmentShader = parameters.fragmentShader.replace(\n \"#include \",\n `\n\t\t\t#include \n\n\t\t\tif (uEdgeThreshold > 0.0) {\n\t\t\t\tfloat edgeThreshold = dot(vEdgeNormal, -vEdgeViewPosition);\n\t\t\t\tdiffuseColor = edgeThreshold < uEdgeThreshold ? vec4(uEdgeColor, 1.0) : mix(diffuseColor, usf_DiffuseColor, uColorMix);\n\t\t\t} else {\n\t\t\t\tdiffuseColor = mix(diffuseColor, usf_DiffuseColor, uColorMix);\n\t\t\t}\n\t\t`\n );\n\n parameters.fragmentShader = parameters.fragmentShader.replace(\n \"void main() {\",\n `\n\t\t\tuniform vec3 uColor0;\n\t\t\tuniform vec3 uColor1;\n\t\t\tuniform vec3 uColor2;\n\t\t\tuniform vec3 uColor3;\n\t\t\tuniform float uColorMix;\n\t\t\tuniform float uEdgeThreshold;\n\t\t\tuniform vec3 uEdgeColor;\n\t\t\t\n\t\t\t// transmission\n\t\t\tuniform float uChromaticAberration; \n\t\t\tuniform float uAnisotropicBlur; \n\t\t\tuniform float uTime;\n\t\t\tuniform float uDistortion;\n\t\t\tuniform float uDistortionScale;\n\t\t\tuniform float uTemporalDistortion;\n\t\t\tuniform float uRefractionSamples;\n\t\t\t\n\t\t\tfloat rand(float n){return fract(sin(n) * 43758.5453123);}\n\t\t\t\n\t\t\t#usf \n\n\t\t\tvarying float vWobble;\n\t\t\tvarying vec2 vPosition;\n\t\t\tvarying vec3 vEdgeNormal;\n\t\t\tvarying vec3 vEdgeViewPosition;\n\t\t\t\n\t\t\tvoid main(){\n\t\t\t\t\n\t\t\t\tvec4 usf_DiffuseColor = vec4(1.0);\n\t\t\t\tfloat colorWobbleMix = smoothstep(-1.,1.,vWobble);\n\t\t\t\tvec2 colorPosMix = vec2(smoothstep(-1.,1.,vPosition.x),smoothstep(-1.,1.,vPosition.y));\n\t\t\t\n\t\t\t\tusf_DiffuseColor.rgb = mix(mix(uColor0, uColor1, colorPosMix.x), mix(uColor2, uColor3, colorPosMix.y), colorWobbleMix);\n\t\t`\n );\n};\n","#ifdef USE_TRANSMISSION\n\n\t// Transmission code is based on glTF-Sampler-Viewer\n\t// https://github.com/KhronosGroup/glTF-Sample-Viewer\n\n\tuniform float _transmission;\n\tuniform float thickness;\n\tuniform float attenuationDistance;\n\tuniform vec3 attenuationColor;\n\n\t#ifdef USE_TRANSMISSIONMAP\n\n\t\tuniform sampler2D transmissionMap;\n\n\t#endif\n\n\t#ifdef USE_THICKNESSMAP\n\n\t\tuniform sampler2D thicknessMap;\n\n\t#endif\n\n\tuniform vec2 transmissionSamplerSize;\n\tuniform sampler2D transmissionSamplerMap;\n\n\tuniform mat4 modelMatrix;\n\tuniform mat4 projectionMatrix;\n\n\tvarying vec3 vWorldPosition;\n\n\t// Mipped Bicubic Texture Filtering by N8\n\t// https://www.shadertoy.com/view/Dl2SDW\n\n\tfloat w0( float a ) {\n\n\t\treturn ( 1.0 / 6.0 ) * ( a * ( a * ( - a + 3.0 ) - 3.0 ) + 1.0 );\n\n\t}\n\n\tfloat w1( float a ) {\n\n\t\treturn ( 1.0 / 6.0 ) * ( a * a * ( 3.0 * a - 6.0 ) + 4.0 );\n\n\t}\n\n\tfloat w2( float a ){\n\n\t\treturn ( 1.0 / 6.0 ) * ( a * ( a * ( - 3.0 * a + 3.0 ) + 3.0 ) + 1.0 );\n\n\t}\n\n\tfloat w3( float a ) {\n\n\t\treturn ( 1.0 / 6.0 ) * ( a * a * a );\n\n\t}\n\n\t// g0 and g1 are the two amplitude functions\n\tfloat g0( float a ) {\n\n\t\treturn w0( a ) + w1( a );\n\n\t}\n\n\tfloat g1( float a ) {\n\n\t\treturn w2( a ) + w3( a );\n\n\t}\n\n\t// h0 and h1 are the two offset functions\n\tfloat h0( float a ) {\n\n\t\treturn - 1.0 + w1( a ) / ( w0( a ) + w1( a ) );\n\n\t}\n\n\tfloat h1( float a ) {\n\n\t\treturn 1.0 + w3( a ) / ( w2( a ) + w3( a ) );\n\n\t}\n\n\tvec4 bicubic( sampler2D tex, vec2 uv, vec4 texelSize, float lod ) {\n\n\t\tuv = uv * texelSize.zw + 0.5;\n\n\t\tvec2 iuv = floor( uv );\n\t\tvec2 fuv = fract( uv );\n\n\t\tfloat g0x = g0( fuv.x );\n\t\tfloat g1x = g1( fuv.x );\n\t\tfloat h0x = h0( fuv.x );\n\t\tfloat h1x = h1( fuv.x );\n\t\tfloat h0y = h0( fuv.y );\n\t\tfloat h1y = h1( fuv.y );\n\n\t\tvec2 p0 = ( vec2( iuv.x + h0x, iuv.y + h0y ) - 0.5 ) * texelSize.xy;\n\t\tvec2 p1 = ( vec2( iuv.x + h1x, iuv.y + h0y ) - 0.5 ) * texelSize.xy;\n\t\tvec2 p2 = ( vec2( iuv.x + h0x, iuv.y + h1y ) - 0.5 ) * texelSize.xy;\n\t\tvec2 p3 = ( vec2( iuv.x + h1x, iuv.y + h1y ) - 0.5 ) * texelSize.xy;\n\n\t\treturn g0( fuv.y ) * ( g0x * textureLod( tex, p0, lod ) + g1x * textureLod( tex, p1, lod ) ) +\n\t\t\tg1( fuv.y ) * ( g0x * textureLod( tex, p2, lod ) + g1x * textureLod( tex, p3, lod ) );\n\n\t}\n\n\tvec4 textureBicubic( sampler2D sampler, vec2 uv, float lod ) {\n\n\t\tvec2 fLodSize = vec2( textureSize( sampler, int( lod ) ) );\n\t\tvec2 cLodSize = vec2( textureSize( sampler, int( lod + 1.0 ) ) );\n\t\tvec2 fLodSizeInv = 1.0 / fLodSize;\n\t\tvec2 cLodSizeInv = 1.0 / cLodSize;\n\t\tvec4 fSample = bicubic( sampler, uv, vec4( fLodSizeInv, fLodSize ), floor( lod ) );\n\t\tvec4 cSample = bicubic( sampler, uv, vec4( cLodSizeInv, cLodSize ), ceil( lod ) );\n\t\treturn mix( fSample, cSample, fract( lod ) );\n\n\t}\n\n\tvec3 getVolumeTransmissionRay( const in vec3 n, const in vec3 v, const in float thickness, const in float ior, const in mat4 modelMatrix ) {\n\n\t\t// Direction of refracted light.\n\t\tvec3 refractionVector = refract( - v, normalize( n ), 1.0 / ior );\n\n\t\t// Compute rotation-independant scaling of the model matrix.\n\t\tvec3 modelScale;\n\t\tmodelScale.x = length( vec3( modelMatrix[ 0 ].xyz ) );\n\t\tmodelScale.y = length( vec3( modelMatrix[ 1 ].xyz ) );\n\t\tmodelScale.z = length( vec3( modelMatrix[ 2 ].xyz ) );\n\n\t\t// The thickness is specified in local space.\n\t\treturn normalize( refractionVector ) * thickness * modelScale;\n\n\t}\n\n\tfloat applyIorToRoughness( const in float roughness, const in float ior ) {\n\n\t\t// Scale roughness with IOR so that an IOR of 1.0 results in no microfacet refraction and\n\t\t// an IOR of 1.5 results in the default amount of microfacet refraction.\n\t\treturn roughness * clamp( ior * 2.0 - 2.0, 0.0, 1.0 );\n\n\t}\n\n\tvec4 getTransmissionSample( const in vec2 fragCoord, const in float roughness, const in float ior ) {\n\n\t\tfloat lod = log2( transmissionSamplerSize.x ) * applyIorToRoughness( roughness, ior );\n\t\treturn textureBicubic( transmissionSamplerMap, fragCoord.xy, lod );\n\n\t}\n\n\tvec3 volumeAttenuation( const in float transmissionDistance, const in vec3 attenuationColor, const in float attenuationDistance ) {\n\n\t\tif ( isinf( attenuationDistance ) ) {\n\n\t\t\t// Attenuation distance is +∞, i.e. the transmitted color is not attenuated at all.\n\t\t\treturn vec3( 1.0 );\n\n\t\t} else {\n\n\t\t\t// Compute light attenuation using Beer's law.\n\t\t\tvec3 attenuationCoefficient = -log( attenuationColor ) / attenuationDistance;\n\t\t\tvec3 transmittance = exp( - attenuationCoefficient * transmissionDistance ); // Beer's law\n\t\t\treturn transmittance;\n\n\t\t}\n\n\t}\n\n\tvec4 getIBLVolumeRefraction( const in vec3 n, const in vec3 v, const in float roughness, const in vec3 diffuseColor,\n\t\tconst in vec3 specularColor, const in float specularF90, const in vec3 position, const in mat4 modelMatrix,\n\t\tconst in mat4 viewMatrix, const in mat4 projMatrix, const in float ior, const in float thickness,\n\t\tconst in vec3 attenuationColor, const in float attenuationDistance ) {\n\n\t\tvec3 transmissionRay = getVolumeTransmissionRay( n, v, thickness, ior, modelMatrix );\n\t\tvec3 refractedRayExit = position + transmissionRay;\n\n\t\t// Project refracted vector on the framebuffer, while mapping to normalized device coordinates.\n\t\tvec4 ndcPos = projMatrix * viewMatrix * vec4( refractedRayExit, 1.0 );\n\t\tvec2 refractionCoords = ndcPos.xy / ndcPos.w;\n\t\trefractionCoords += 1.0;\n\t\trefractionCoords /= 2.0;\n\n\t\t// Sample framebuffer to get pixel the refracted ray hits.\n\t\tvec4 transmittedLight = getTransmissionSample( refractionCoords, roughness, ior );\n\n\t\tvec3 transmittance = diffuseColor * volumeAttenuation( length( transmissionRay ), attenuationColor, attenuationDistance );\n\t\tvec3 attenuatedColor = transmittance * transmittedLight.rgb;\n\n\t\t// Get the specular component.\n\t\tvec3 F = EnvironmentBRDF( n, v, specularColor, specularF90, roughness );\n\n\t\t// As less light is transmitted, the opacity should be increased. This simple approximation does a decent job \n\t\t// of modulating a CSS background, and has no effect when the buffer is opaque, due to a solid object or clear color.\n\t\tfloat transmittanceFactor = ( transmittance.r + transmittance.g + transmittance.b ) / 3.0;\n\n\t\treturn vec4( ( 1.0 - F ) * attenuatedColor, 1.0 - ( 1.0 - transmittedLight.a ) * transmittanceFactor );\n\n\t}\n#endif","#ifdef USE_TRANSMISSION\n\nmaterial.transmission = _transmission;\nmaterial.transmissionAlpha = 1.0;\nmaterial.thickness = thickness;\nmaterial.attenuationDistance = attenuationDistance;\nmaterial.attenuationColor = attenuationColor;\n\n#ifdef USE_TRANSMISSIONMAP\n\n\tmaterial.transmission *= texture2D( transmissionMap, vTransmissionMapUv ).r;\n\n#endif\n\n#ifdef USE_THICKNESSMAP\n\n\tmaterial.thickness *= texture2D( thicknessMap, vThicknessMapUv ).g;\n\n#endif\n\nvec3 pos = vWorldPosition;\n\nvec3 v = normalize( cameraPosition - pos );\nvec3 n = inverseTransformDirection( normal, viewMatrix );\n\nvec4 transmitted = getIBLVolumeRefraction(\n\tn, v, material.roughness, material.diffuseColor, material.specularColor, material.specularF90,\n\tpos, modelMatrix, viewMatrix, projectionMatrix, material.ior, material.thickness,\n\tmaterial.attenuationColor, material.attenuationDistance );\n\nmaterial.transmissionAlpha = mix( material.transmissionAlpha, transmitted.a, material.transmission );\n\n// Custom from here\nfloat runningSeed = 0.0;\nvec3 transmission = vec3(0.0);\nfloat transmissionR, transmissionB, transmissionG;\nfloat randomCoords = rand(runningSeed++);\nfloat thickness_smear = thickness * max(pow(roughnessFactor, 0.33), uAnisotropicBlur);\nvec3 distortionNormal = vec3(0.0);\nvec3 temporalOffset = vec3(uTime, -uTime, -uTime) * uTemporalDistortion;\n\nif (uDistortion > 0.0) {\n\tdistortionNormal = uDistortion * vec3(snoiseFractal(vec3((pos * uDistortionScale + temporalOffset))), snoiseFractal(vec3(pos.zxy * uDistortionScale - temporalOffset)), snoiseFractal(vec3(pos.yxz * uDistortionScale + temporalOffset)));\n}\n\nfor (float i = 0.0; i < uRefractionSamples; i ++) {\n\tvec3 sampleNorm = normalize(n + roughnessFactor * roughnessFactor * 2.0 * normalize(vec3(rand(runningSeed++) - 0.5, rand(runningSeed++) - 0.5, rand(runningSeed++) - 0.5)) * pow(rand(runningSeed++), 0.33) + distortionNormal);\n\t\n\ttransmissionR = getIBLVolumeRefraction(\n\t\tsampleNorm, v, material.roughness, material.diffuseColor, material.specularColor, material.specularF90,\n\t\tpos, modelMatrix, viewMatrix, projectionMatrix, material.ior, material.thickness + thickness_smear * (i + randomCoords) / uRefractionSamples,\n\t\tmaterial.attenuationColor, material.attenuationDistance\n\t).r;\n\ttransmissionG = getIBLVolumeRefraction(\n\t\tsampleNorm, v, material.roughness, material.diffuseColor, material.specularColor, material.specularF90,\n\t\tpos, modelMatrix, viewMatrix, projectionMatrix, material.ior * (1.0 + uChromaticAberration * (i + randomCoords) / uRefractionSamples) , material.thickness + thickness_smear * (i + randomCoords) / uRefractionSamples,\n\t\tmaterial.attenuationColor, material.attenuationDistance\n\t).g;\n\ttransmissionB = getIBLVolumeRefraction(\n\t\tsampleNorm, v, material.roughness, material.diffuseColor, material.specularColor, material.specularF90,\n\t\tpos, modelMatrix, viewMatrix, projectionMatrix, material.ior * (1.0 + 2.0 * uChromaticAberration * (i + randomCoords) / uRefractionSamples), material.thickness + thickness_smear * (i + randomCoords) / uRefractionSamples,\n\t\tmaterial.attenuationColor, material.attenuationDistance\n\t).b;\n\ttransmission.r += transmissionR;\n\ttransmission.g += transmissionG;\n\ttransmission.b += transmissionB;\n}\n\ntransmission /= uRefractionSamples;\n// to here\n\ntotalDiffuse = mix( totalDiffuse, transmission.rgb, material.transmission );\n\n#endif","import * as THREE from \"three\";\nimport transmission_pars_fragment from \"../shaders/transmission_pars_fragment.glsl\";\nimport transmission_fragment from \"../shaders/transmission_fragment.glsl\";\n\nexport const resolveEachMaterial = ({\n mat,\n isCustomTransmission,\n parameters,\n}: {\n mat: THREE.Material;\n isCustomTransmission: boolean;\n parameters: THREE.WebGLProgramParametersWithUniforms;\n}) => {\n // custom transmission\n if (mat.type === \"MeshPhysicalMaterial\" && isCustomTransmission) {\n parameters.fragmentShader = parameters.fragmentShader.replace(\n \"#include \",\n `${transmission_pars_fragment}`\n );\n\n parameters.fragmentShader = parameters.fragmentShader.replace(\n \"#include \",\n `${transmission_fragment}`\n );\n }\n\n // if normalMap is defined, don't add tangent attribute\n if (!(mat as any).normalMap) {\n parameters.vertexShader = parameters.vertexShader.replace(\n \"void main() {\",\n `\n\t\t\t\tattribute vec4 tangent;\n\t\t\t\t\n\t\t\t\tvoid main() {\n\t\t\t`\n );\n }\n};\n","import * as THREE from \"three\";\nimport { useEffect, useMemo } from \"react\";\nimport { WOBBLE3D_PARAMS } from \".\";\nimport { MaterialProps, OnBeforeInitParameters } from \"../../types\";\nimport { createMaterialParameters } from \"../../../utils/createMaterialParameters\";\nimport { rewriteVertexShader } from \"./utils/rewriteVertexShader\";\nimport { rewriteFragmentShader } from \"./utils/rewriteFragmentShader\";\nimport { resolveEachMaterial } from \"./utils/resolveEachMaterial\";\n\nexport class Wobble3DMaterial extends THREE.Material {\n uniforms!: {\n uTime: { value: number };\n uWobblePositionFrequency: { value: number };\n uWobbleTimeFrequency: { value: number };\n uWobbleStrength: { value: number };\n uWarpPositionFrequency: { value: number };\n uWarpTimeFrequency: { value: number };\n uWarpStrength: { value: number };\n uColor0: { value: THREE.Color };\n uColor1: { value: THREE.Color };\n uColor2: { value: THREE.Color };\n uColor3: { value: THREE.Color };\n uColorMix: { value: number };\n uEdgeThreshold: { value: number };\n uEdgeColor: { value: THREE.Color };\n uChromaticAberration: { value: number };\n uAnisotropicBlur: { value: number };\n uDistortion: { value: number };\n uDistortionScale: { value: number };\n uTemporalDistortion: { value: number };\n uRefractionSamples: { value: number };\n };\n}\n\nexport type WobbleMaterialConstructor = new (opts: {\n [key: string]: any;\n}) => THREE.Material;\n\ntype WobbleMaterialParams =\n ConstructorParameters[0];\n\nexport interface WobbleMaterialProps\n extends MaterialProps {\n /** default:THREE.MeshPhysicalMaterial */\n baseMaterial?: T;\n materialParameters?: WobbleMaterialParams;\n depthOnBeforeInit?: (parameters: OnBeforeInitParameters) => void;\n /**\n * Whether to apply more advanced `transmission` or not. valid only for `MeshPhysicalMaterial`. This is a function referring to `drei/MeshTransmissionMaterial`, default : `false`\n * @link https://github.com/pmndrs/drei?tab=readme-ov-file#meshtransmissionmaterial\n * */\n isCustomTransmission?: boolean;\n /** Whether to initialise `MeshDepthMaterial` or not , default : `false` */\n depth?: boolean;\n}\n\nexport const useMaterial = ({\n baseMaterial,\n materialParameters,\n isCustomTransmission = false,\n onBeforeInit,\n depthOnBeforeInit,\n depth = false,\n}: WobbleMaterialProps) => {\n const { material, depthMaterial } = useMemo(() => {\n const mat = new (baseMaterial || THREE.MeshPhysicalMaterial)(\n materialParameters || {}\n );\n\n Object.assign(mat.userData, {\n uniforms: {\n uTime: { value: 0 },\n uWobblePositionFrequency: {\n value: WOBBLE3D_PARAMS.wobblePositionFrequency,\n },\n uWobbleTimeFrequency: {\n value: WOBBLE3D_PARAMS.wobbleTimeFrequency,\n },\n uWobbleStrength: { value: WOBBLE3D_PARAMS.wobbleStrength },\n uWarpPositionFrequency: {\n value: WOBBLE3D_PARAMS.warpPositionFrequency,\n },\n uWarpTimeFrequency: { value: WOBBLE3D_PARAMS.warpTimeFrequency },\n uWarpStrength: { value: WOBBLE3D_PARAMS.warpStrength },\n uColor0: { value: WOBBLE3D_PARAMS.color0 },\n uColor1: { value: WOBBLE3D_PARAMS.color1 },\n uColor2: { value: WOBBLE3D_PARAMS.color2 },\n uColor3: { value: WOBBLE3D_PARAMS.color3 },\n uColorMix: { value: WOBBLE3D_PARAMS.colorMix },\n uEdgeThreshold: { value: WOBBLE3D_PARAMS.edgeThreshold },\n uEdgeColor: { value: WOBBLE3D_PARAMS.edgeColor },\n uChromaticAberration: {\n value: WOBBLE3D_PARAMS.chromaticAberration,\n },\n uAnisotropicBlur: { value: WOBBLE3D_PARAMS.anisotropicBlur },\n uDistortion: { value: WOBBLE3D_PARAMS.distortion },\n uDistortionScale: { value: WOBBLE3D_PARAMS.distortionScale },\n uTemporalDistortion: { value: WOBBLE3D_PARAMS.temporalDistortion },\n uRefractionSamples: { value: WOBBLE3D_PARAMS.refractionSamples },\n transmission: { value: 0 },\n _transmission: { value: 1 },\n transmissionMap: { value: null },\n },\n });\n\n mat.onBeforeCompile = (parameters) => {\n rewriteVertexShader(parameters);\n\n rewriteFragmentShader(parameters);\n\n resolveEachMaterial({\n parameters,\n mat,\n isCustomTransmission,\n });\n\n const cutomizedParams = createMaterialParameters(\n {\n fragmentShader: parameters.fragmentShader,\n vertexShader: parameters.vertexShader,\n // Because wobble3D uses userData to update uniforms.\n uniforms: mat.userData.uniforms,\n },\n onBeforeInit\n );\n parameters.fragmentShader = cutomizedParams.fragmentShader;\n parameters.vertexShader = cutomizedParams.vertexShader;\n Object.assign(parameters.uniforms, cutomizedParams.uniforms);\n };\n mat.needsUpdate = true;\n\n /*===============================================\n\t\tdepthMaterial\n\t\t===============================================*/\n let depthMat = null;\n if (depth) {\n depthMat = new THREE.MeshDepthMaterial({\n depthPacking: THREE.RGBADepthPacking,\n });\n depthMat.onBeforeCompile = (parameters) => {\n Object.assign(parameters.uniforms, mat.userData.uniforms);\n rewriteVertexShader(parameters);\n createMaterialParameters(parameters, depthOnBeforeInit);\n };\n depthMat.needsUpdate = true;\n }\n\n return { material: mat, depthMaterial: depthMat };\n }, [\n materialParameters,\n baseMaterial,\n onBeforeInit,\n depthOnBeforeInit,\n isCustomTransmission,\n depth,\n ]);\n\n // Only the depthMaterial is disposed of because the material is disposed of by useAddObject.\n useEffect(() => {\n return () => {\n if (depthMaterial) depthMaterial.dispose();\n };\n }, [depthMaterial]);\n\n return {\n material: material as Wobble3DMaterial,\n depthMaterial,\n };\n};\n","import * as THREE from \"three\";\nimport { RootState } from \"@react-three/fiber\";\nimport { mergeVertices } from \"three-stdlib\";\nimport {\n useMaterial,\n Wobble3DMaterial,\n WobbleMaterialProps,\n WobbleMaterialConstructor,\n} from \"./useMaterial\";\nimport { Wobble3DParams } from \".\";\nimport {\n setUniform,\n setCustomUniform,\n CustomParams,\n} from \"../../../utils/setUniforms\";\nimport { useCallback, useMemo } from \"react\";\nimport { useAddObject } from \"../../../utils/useAddObject\";\nimport { Create3DHooksProps } from \"../types\";\n\nexport type UseCreateWobble3DProps = {\n /** default : `THREE.IcosahedronGeometry(2,20)` */\n geometry?: THREE.BufferGeometry;\n};\n\ntype UpdateUniform = (\n rootState: RootState | null,\n newParams?: Wobble3DParams,\n customParams?: CustomParams\n) => void;\n\ntype UseCreateWobble3DReturn = [\n UpdateUniform,\n {\n mesh: THREE.Mesh;\n depthMaterial: THREE.MeshDepthMaterial | null;\n }\n];\n\nexport const useCreateWobble3D = ({\n scene = false,\n geometry,\n isCustomTransmission,\n baseMaterial,\n materialParameters,\n depth,\n onBeforeInit,\n depthOnBeforeInit,\n}: UseCreateWobble3DProps &\n Create3DHooksProps &\n WobbleMaterialProps): UseCreateWobble3DReturn => {\n const wobbleGeometry = useMemo(() => {\n let geo = geometry || new THREE.IcosahedronGeometry(2, 20);\n geo = mergeVertices(geo);\n geo.computeTangents();\n return geo;\n }, [geometry]);\n const { material, depthMaterial } = useMaterial({\n baseMaterial,\n materialParameters,\n isCustomTransmission,\n onBeforeInit,\n depthOnBeforeInit,\n depth,\n });\n\n const mesh = useAddObject(scene, wobbleGeometry, material, THREE.Mesh);\n\n const userData = material.userData as Wobble3DMaterial;\n\n const updateValue = setUniform(userData);\n const updateCustomValue = setCustomUniform(userData);\n\n const updateUniform = useCallback(\n (rootState, newParams, customParams) => {\n if (rootState) {\n updateValue(\n \"uTime\",\n newParams?.beat || rootState.clock.getElapsedTime()\n );\n }\n if (newParams === undefined) {\n return;\n }\n updateValue(\"uWobbleStrength\", newParams.wobbleStrength);\n updateValue(\n \"uWobblePositionFrequency\",\n newParams.wobblePositionFrequency\n );\n updateValue(\"uWobbleTimeFrequency\", newParams.wobbleTimeFrequency);\n updateValue(\"uWarpStrength\", newParams.warpStrength);\n updateValue(\"uWarpPositionFrequency\", newParams.warpPositionFrequency);\n updateValue(\"uWarpTimeFrequency\", newParams.warpTimeFrequency);\n updateValue(\"uColor0\", newParams.color0);\n updateValue(\"uColor1\", newParams.color1);\n updateValue(\"uColor2\", newParams.color2);\n updateValue(\"uColor3\", newParams.color3);\n updateValue(\"uColorMix\", newParams.colorMix);\n updateValue(\"uEdgeThreshold\", newParams.edgeThreshold);\n updateValue(\"uEdgeColor\", newParams.edgeColor);\n updateValue(\"uChromaticAberration\", newParams.chromaticAberration);\n updateValue(\"uAnisotropicBlur\", newParams.anisotropicBlur);\n updateValue(\"uDistortion\", newParams.distortion);\n updateValue(\"uDistortionScale\", newParams.distortionScale);\n updateValue(\"uRefractionSamples\", newParams.refractionSamples);\n updateValue(\"uTemporalDistortion\", newParams.temporalDistortion);\n\n updateCustomValue(customParams);\n },\n [updateValue, updateCustomValue]\n );\n\n return [\n updateUniform,\n {\n mesh,\n depthMaterial,\n },\n ];\n};\n","import * as THREE from \"three\";\nimport { useCallback, useMemo } from \"react\";\nimport { RootState } from \"@react-three/fiber\";\nimport { useSingleFBO } from \"../../../utils/useSingleFBO\";\nimport { HooksReturn } from \"../../types\";\nimport { useCreateWobble3D, UseCreateWobble3DProps } from \"./useCreateWobble3D\";\nimport { WobbleMaterialProps, WobbleMaterialConstructor } from \"./useMaterial\";\nimport { HooksProps3D } from \"../types\";\nimport { getDpr } from \"../../../utils/getDpr\";\nimport { CustomParams } from \"../../../utils/setUniforms\";\n\nexport type Wobble3DParams = {\n /** default : `0.3` */\n wobbleStrength?: number;\n /** default : `0.3` */\n wobblePositionFrequency?: number;\n /** default : `0.3` */\n wobbleTimeFrequency?: number;\n /** default : `0.3` */\n warpStrength?: number;\n /** default : `0.3` */\n warpPositionFrequency?: number;\n /** default : `0.3` */\n warpTimeFrequency?: number;\n color0?: THREE.Color;\n color1?: THREE.Color;\n color2?: THREE.Color;\n color3?: THREE.Color;\n /** Mixing ratio with the material's original output color, 0~1 , defaulat : `1` */\n colorMix?: number;\n /** Threshold of edge. 0 for edge disabled, default : `0` */\n edgeThreshold?: number;\n /** Color of edge. default : `0x000000` */\n edgeColor?: THREE.Color;\n /** you can get into the rhythm ♪ , default : `false` */\n beat?: number | false;\n /** valid only for `MeshPhysicalMaterial` && `isCustomTransmission:true` , default : `0.1` */\n chromaticAberration?: number;\n /** valid only for `MeshPhysicalMaterial` && `isCustomTransmission:true` , default : `0.1` */\n anisotropicBlur?: number;\n /** valid only for `MeshPhysicalMaterial` && `isCustomTransmission:true` , default : `0.0` */\n distortion?: number;\n /** valid only for `MeshPhysicalMaterial` && `isCustomTransmission:true` , default : `0.1` */\n distortionScale?: number;\n /** valid only for `MeshPhysicalMaterial` && `isCustomTransmission:true` , default : `0.0` */\n temporalDistortion?: number;\n /** valid only for `MeshPhysicalMaterial` && `isCustomTransmission:true` , default : `6` */\n refractionSamples?: number;\n};\n\nexport type Wobble3DObject = {\n scene: THREE.Scene;\n mesh: THREE.Mesh;\n depthMaterial: THREE.MeshDepthMaterial | null;\n renderTarget: THREE.WebGLRenderTarget;\n output: THREE.Texture;\n};\n\nexport const WOBBLE3D_PARAMS: Wobble3DParams = Object.freeze({\n wobbleStrength: 0.3,\n wobblePositionFrequency: 0.3,\n wobbleTimeFrequency: 0.3,\n warpStrength: 0.3,\n warpPositionFrequency: 0.3,\n warpTimeFrequency: 0.3,\n color0: new THREE.Color(0xff0000),\n color1: new THREE.Color(0x00ff00),\n color2: new THREE.Color(0x0000ff),\n color3: new THREE.Color(0xffff00),\n colorMix: 1,\n edgeThreshold: 0.0,\n edgeColor: new THREE.Color(0x000000),\n chromaticAberration: 0.1,\n anisotropicBlur: 0.1,\n distortion: 0.0,\n distortionScale: 0.1,\n temporalDistortion: 0.0,\n refractionSamples: 6,\n beat: false,\n});\n\n/**\n * @link https://github.com/FunTechInc/use-shader-fx\n */\nexport const useWobble3D = ({\n size,\n dpr,\n renderTargetOptions,\n isSizeUpdate,\n camera,\n geometry,\n baseMaterial,\n materialParameters,\n isCustomTransmission,\n onBeforeInit,\n depthOnBeforeInit,\n depth,\n}: HooksProps3D & UseCreateWobble3DProps & WobbleMaterialProps): HooksReturn<\n Wobble3DParams,\n Wobble3DObject,\n CustomParams\n> => {\n const _dpr = getDpr(dpr);\n\n const scene = useMemo(() => new THREE.Scene(), []);\n\n const [updateUniform, { mesh, depthMaterial }] = useCreateWobble3D({\n baseMaterial,\n materialParameters,\n scene,\n geometry,\n isCustomTransmission,\n onBeforeInit,\n depthOnBeforeInit,\n depth,\n });\n\n const [renderTarget, updateRenderTarget] = useSingleFBO({\n scene,\n camera,\n size,\n dpr: _dpr.fbo,\n isSizeUpdate,\n depthBuffer: true,\n ...renderTargetOptions,\n });\n\n const updateFx = useCallback(\n (\n RootState: RootState,\n newParams?: Wobble3DParams,\n customParams?: CustomParams\n ) => {\n updateUniform(RootState, newParams, customParams);\n return updateRenderTarget(RootState.gl);\n },\n [updateRenderTarget, updateUniform]\n );\n\n const updateParams = useCallback(\n (newParams?: Wobble3DParams, customParams?: CustomParams) => {\n updateUniform(null, newParams, customParams);\n },\n [updateUniform]\n );\n\n return [\n updateFx,\n updateParams,\n {\n scene,\n mesh,\n depthMaterial,\n renderTarget,\n output: renderTarget.texture,\n },\n ];\n};\n","import * as THREE from \"three\";\nimport { useEffect, useMemo } from \"react\";\n\n/** Generate mesh from geometry and material and add to scene */\nexport const useAddMesh = (\n scene: THREE.Scene,\n geometry: THREE.BufferGeometry,\n material: THREE.Material\n) => {\n const mesh = useMemo(() => {\n const mesh = new THREE.Mesh(geometry, material);\n scene.add(mesh);\n return mesh;\n }, [geometry, material, scene]);\n\n useEffect(() => {\n return () => {\n scene.remove(mesh);\n geometry.dispose();\n material.dispose();\n };\n }, [scene, geometry, material, mesh]);\n\n return mesh;\n};\n","import { useMemo, useRef } from \"react\";\nimport { Size } from \"../fxs/types\";\n\nconst checkUpdate = (\n currentW: number,\n currentH: number,\n memoW: number,\n memoH: number,\n threshold: number,\n boundFor: \"smaller\" | \"larger\" | \"both\"\n) => {\n const isSmaller =\n currentW < memoW - threshold || currentH < memoH - threshold;\n const isLarger =\n currentW > memoW + threshold || currentH > memoH + threshold;\n\n return (\n (boundFor === \"smaller\" && isSmaller) ||\n (boundFor === \"larger\" && isLarger) ||\n (boundFor === \"both\" && (isSmaller || isLarger))\n );\n};\n\nexport const useResizeBoundary = ({\n size,\n boundFor,\n threshold,\n}: {\n size: Size;\n boundFor: \"smaller\" | \"larger\" | \"both\";\n threshold: number;\n}) => {\n const memorizedSize = useRef(size);\n\n const isBeyondBoundary = useMemo(() => {\n const { width: currentW, height: currentH } = size;\n const { width: memoW, height: memoH } = memorizedSize.current;\n\n const isUpdate = checkUpdate(\n currentW,\n currentH,\n memoW,\n memoH,\n threshold,\n boundFor\n );\n\n if (isUpdate) {\n memorizedSize.current = size;\n }\n return isUpdate;\n }, [size, boundFor, threshold]);\n\n return isBeyondBoundary;\n};\n","export type EasingTypes =\n | \"easeInSine\"\n | \"easeOutSine\"\n | \"easeInOutSine\"\n | \"easeInQuad\"\n | \"easeOutQuad\"\n | \"easeInOutQuad\"\n | \"easeInCubic\"\n | \"easeOutCubic\"\n | \"easeInOutCubic\"\n | \"easeInQuart\"\n | \"easeOutQuart\"\n | \"easeInOutQuart\"\n | \"easeInQuint\"\n | \"easeOutQuint\"\n | \"easeInOutQuint\"\n | \"easeInExpo\"\n | \"easeOutExpo\"\n | \"easeInOutExpo\"\n | \"easeInCirc\"\n | \"easeOutCirc\"\n | \"easeInOutCirc\"\n | \"easeInBack\"\n | \"easeOutBack\"\n | \"easeInOutBack\"\n | \"easeInElastic\"\n | \"easeOutElastic\"\n | \"easeInOutElastic\"\n | \"easeInBounce\"\n | \"easeOutBounce\"\n | \"easeInOutBounce\";\n\ntype EasingFunctions = {\n [K in EasingTypes]: (x: number) => number;\n};\n\n/**\n * from https://github.com/ai/easings.net\n */\nexport const Easing: EasingFunctions = Object.freeze({\n easeInSine(x: number): number {\n return 1 - Math.cos((x * Math.PI) / 2);\n },\n easeOutSine(x: number): number {\n return Math.sin((x * Math.PI) / 2);\n },\n easeInOutSine(x: number): number {\n return -(Math.cos(Math.PI * x) - 1) / 2;\n },\n easeInQuad(x: number): number {\n return x * x;\n },\n easeOutQuad(x: number): number {\n return 1 - (1 - x) * (1 - x);\n },\n easeInOutQuad(x: number): number {\n return x < 0.5 ? 2 * x * x : 1 - Math.pow(-2 * x + 2, 2) / 2;\n },\n easeInCubic(x: number): number {\n return x * x * x;\n },\n easeOutCubic(x: number): number {\n return 1 - Math.pow(1 - x, 3);\n },\n easeInOutCubic(x: number): number {\n return x < 0.5 ? 4 * x * x * x : 1 - Math.pow(-2 * x + 2, 3) / 2;\n },\n easeInQuart(x: number): number {\n return x * x * x * x;\n },\n easeOutQuart(x: number): number {\n return 1 - Math.pow(1 - x, 4);\n },\n easeInOutQuart(x: number): number {\n return x < 0.5 ? 8 * x * x * x * x : 1 - Math.pow(-2 * x + 2, 4) / 2;\n },\n easeInQuint(x: number): number {\n return x * x * x * x * x;\n },\n easeOutQuint(x: number): number {\n return 1 - Math.pow(1 - x, 5);\n },\n easeInOutQuint(x: number): number {\n return x < 0.5 ? 16 * x * x * x * x * x : 1 - Math.pow(-2 * x + 2, 5) / 2;\n },\n easeInExpo(x: number): number {\n return x === 0 ? 0 : Math.pow(2, 10 * x - 10);\n },\n easeOutExpo(x: number): number {\n return x === 1 ? 1 : 1 - Math.pow(2, -10 * x);\n },\n easeInOutExpo(x: number): number {\n return x === 0\n ? 0\n : x === 1\n ? 1\n : x < 0.5\n ? Math.pow(2, 20 * x - 10) / 2\n : (2 - Math.pow(2, -20 * x + 10)) / 2;\n },\n easeInCirc(x: number): number {\n return 1 - Math.sqrt(1 - Math.pow(x, 2));\n },\n easeOutCirc(x: number): number {\n return Math.sqrt(1 - Math.pow(x - 1, 2));\n },\n easeInOutCirc(x: number): number {\n return x < 0.5\n ? (1 - Math.sqrt(1 - Math.pow(2 * x, 2))) / 2\n : (Math.sqrt(1 - Math.pow(-2 * x + 2, 2)) + 1) / 2;\n },\n easeInBack(x: number): number {\n const c1 = 1.70158;\n const c3 = c1 + 1;\n\n return c3 * x * x * x - c1 * x * x;\n },\n easeOutBack(x: number): number {\n const c1 = 1.70158;\n const c3 = c1 + 1;\n\n return 1 + c3 * Math.pow(x - 1, 3) + c1 * Math.pow(x - 1, 2);\n },\n easeInOutBack(x: number): number {\n const c1 = 1.70158;\n const c2 = c1 * 1.525;\n\n return x < 0.5\n ? (Math.pow(2 * x, 2) * ((c2 + 1) * 2 * x - c2)) / 2\n : (Math.pow(2 * x - 2, 2) * ((c2 + 1) * (x * 2 - 2) + c2) + 2) / 2;\n },\n easeInElastic(x: number): number {\n const c4 = (2 * Math.PI) / 3;\n\n return x === 0\n ? 0\n : x === 1\n ? 1\n : -Math.pow(2, 10 * x - 10) * Math.sin((x * 10 - 10.75) * c4);\n },\n easeOutElastic(x: number): number {\n const c4 = (2 * Math.PI) / 3;\n\n return x === 0\n ? 0\n : x === 1\n ? 1\n : Math.pow(2, -10 * x) * Math.sin((x * 10 - 0.75) * c4) + 1;\n },\n easeInOutElastic(x: number): number {\n const c5 = (2 * Math.PI) / 4.5;\n\n return x === 0\n ? 0\n : x === 1\n ? 1\n : x < 0.5\n ? -(Math.pow(2, 20 * x - 10) * Math.sin((20 * x - 11.125) * c5)) / 2\n : (Math.pow(2, -20 * x + 10) * Math.sin((20 * x - 11.125) * c5)) / 2 +\n 1;\n },\n easeInBounce(x: number): number {\n return 1 - Easing.easeOutBounce(1 - x);\n },\n easeOutBounce(x: number): number {\n const n1 = 7.5625;\n const d1 = 2.75;\n\n if (x < 1 / d1) {\n return n1 * x * x;\n } else if (x < 2 / d1) {\n return n1 * (x -= 1.5 / d1) * x + 0.75;\n } else if (x < 2.5 / d1) {\n return n1 * (x -= 2.25 / d1) * x + 0.9375;\n } else {\n return n1 * (x -= 2.625 / d1) * x + 0.984375;\n }\n },\n easeInOutBounce(x: number): number {\n return x < 0.5\n ? (1 - Easing.easeOutBounce(1 - 2 * x)) / 2\n : (1 + Easing.easeOutBounce(2 * x - 1)) / 2;\n },\n});\n","import * as THREE from \"three\";\nimport { Easing, EasingTypes } from \"../libs/Easings\";\nimport { useCallback } from \"react\";\n\n/** Returns a unique hash specific to the beat */\nfunction getHash(input: number) {\n let n = Math.sin(input * 12.9898) * 43758.5453;\n return n - Math.floor(n);\n}\n\ntype BeatValues = {\n beat: number;\n floor: number;\n fract: number;\n /** unique hash specific to the beat */\n hash: number;\n};\n\n/**\n * @param ease easing functions are referenced from https://github.com/ai/easings.net , default : \"easeOutQuart\"\n */\nexport const useBeat = (bpm: number, ease: EasingTypes = \"easeOutQuart\") => {\n const rhythm = bpm / 60;\n const easing = Easing[ease];\n const updateBeat = useCallback(\n (clock: THREE.Clock) => {\n let beat = clock.getElapsedTime() * rhythm;\n const floor = Math.floor(beat);\n const fract = easing(beat - floor);\n beat = fract + floor;\n const hash = getHash(floor);\n return {\n beat,\n floor,\n fract,\n hash,\n } as BeatValues;\n },\n [rhythm, easing]\n );\n return updateBeat;\n};\n","import * as THREE from \"three\";\nimport { useCallback, useMemo, useRef } from \"react\";\n\n/**\n * @param fps FPS you want to limit , default : `60`\n *\n * ```tsx\n * const limiter = useFPSLimiter(fps);\n * useFrame((props) => {\n * if (limiter(props.clock)) {\n *\t\t //some code\n * }\n * });\n * ```\n */\nexport const useFPSLimiter = (fps: number = 60) => {\n const interval = useMemo(() => 1 / Math.max(Math.min(fps, 60), 1), [fps]);\n const prevTime = useRef(null);\n\n const limiter = useCallback(\n (clock: THREE.Clock) => {\n const tick = clock.getElapsedTime();\n if (prevTime.current === null) {\n prevTime.current = tick;\n return true;\n }\n const deltaTime = tick - prevTime.current;\n if (deltaTime >= interval) {\n prevTime.current = tick;\n return true;\n }\n return false;\n },\n [interval]\n );\n\n return limiter;\n};\n","import { DomSyncerParams } from \"..\";\n\nexport const errorHandler = (params: DomSyncerParams) => {\n const domLength = params.dom?.length;\n const textureLength = params.texture?.length;\n\n if (!domLength || !textureLength) {\n return true;\n }\n\n if (domLength !== textureLength) {\n return true;\n }\n\n return false;\n};\n","varying vec2 vUv;\n\nvoid main() {\n\tvUv = uv;\n\tgl_Position = projectionMatrix * viewMatrix * modelMatrix * vec4(position, 1.0);\n}","precision highp float;\n\nvarying vec2 vUv;\nuniform sampler2D u_texture;\nuniform vec2 u_textureResolution;\nuniform vec2 u_resolution;\nuniform float u_borderRadius;\n\nvoid main() {\n\t// texuture color\n\tfloat screenAspect = u_resolution.x / u_resolution.y;\n\tfloat textureAspect = u_textureResolution.x / u_textureResolution.y;\n\tvec2 ratio = vec2(\n\t\tmin(screenAspect / textureAspect, 1.0),\n\t\tmin(textureAspect / screenAspect, 1.0)\n\t);\n\n\tvec2 adjustedUv = vUv * ratio + (1.0 - ratio) * 0.5;\n\tvec3 textureColor = texture2D(u_texture, adjustedUv).rgb;\n\tfloat textureAlpha = texture2D(u_texture, adjustedUv).a;\n\n\t// Based on https://mofu-dev.com/en/blog/three-dom-alignment/\n\tfloat maxSide = max(u_resolution.x, u_resolution.y);\n\tfloat minSide = min(u_resolution.x, u_resolution.y);\n\tvec2 aspect = u_resolution / maxSide;\n\tvec2 alphaUv = vUv - 0.5;\n\n\tfloat borderRadius = min(u_borderRadius, minSide * 0.5);\n\tvec2 offset = vec2(borderRadius) / u_resolution;\n\tvec2 alphaXY = smoothstep(vec2(0.5 - offset), vec2(0.5 - offset - 0.001), abs(alphaUv));\n\tfloat alpha = min(1.0, alphaXY.x + alphaXY.y);\n\n\tvec2 alphaUv2 = abs(vUv - 0.5);\n\tfloat radius = borderRadius / maxSide;\n\talphaUv2 = (alphaUv2 - 0.5) * aspect + radius;\n\tfloat roundAlpha = smoothstep(radius + 0.001, radius, length(alphaUv2));\n\n\talpha = min(1.0, alpha + roundAlpha);\n\n\t// multiply texture alpha\n\talpha *= textureAlpha;\n\n\tgl_FragColor = vec4(textureColor, alpha);\n}\n","import * as THREE from \"three\";\nimport { DomSyncerParams } from \"../\";\nimport vertexShader from \"../shader/main.vert\";\nimport fragmentShader from \"../shader/main.frag\";\nimport { MaterialProps, Size } from \"../../../fxs/types\";\nimport { MATERIAL_BASIC_PARAMS } from \"../../../libs/constants\";\nimport { createMaterialParameters } from \"../../../utils/createMaterialParameters\";\n\nexport class DomSyncerMaterial extends THREE.ShaderMaterial {\n uniforms!: {\n u_texture: { value: THREE.Texture };\n u_textureResolution: { value: THREE.Vector2 };\n u_resolution: { value: THREE.Vector2 };\n u_borderRadius: { value: number };\n };\n}\n\nexport const createMesh = ({\n params,\n scene,\n onBeforeInit,\n}: {\n params: DomSyncerParams;\n size: Size;\n scene: THREE.Scene;\n} & MaterialProps) => {\n if (scene.children.length > 0) {\n scene.children.forEach((child) => {\n if (child instanceof THREE.Mesh) {\n child.geometry.dispose();\n child.material.dispose();\n }\n });\n scene.remove(...scene.children);\n }\n\n params.texture!.forEach((texture, i) => {\n const mat = new THREE.ShaderMaterial({\n ...createMaterialParameters(\n {\n uniforms: {\n u_texture: { value: texture },\n u_textureResolution: {\n value: new THREE.Vector2(0, 0),\n },\n u_resolution: { value: new THREE.Vector2(0, 0) },\n u_borderRadius: {\n value: params.boderRadius![i]\n ? params.boderRadius![i]\n : 0.0,\n },\n },\n vertexShader: vertexShader,\n fragmentShader: fragmentShader,\n },\n onBeforeInit\n ),\n ...MATERIAL_BASIC_PARAMS,\n // Must be transparent.\n transparent: true,\n });\n\n const mesh = new THREE.Mesh(new THREE.PlaneGeometry(1, 1), mat);\n scene.add(mesh);\n });\n};\n","import { useCallback, useRef } from \"react\";\nimport { DomSyncerParams } from \"..\";\n\nexport const useIntersectionHandler = () => {\n const intersectionObserverRef = useRef([]);\n const intersectionDomRef = useRef<(HTMLElement | Element | null)[]>([]);\n\n const intersectionHandler = useCallback(\n ({\n isIntersectingRef,\n isIntersectingOnceRef,\n params,\n }: {\n isIntersectingRef: React.MutableRefObject;\n isIntersectingOnceRef: React.MutableRefObject;\n params: DomSyncerParams;\n }) => {\n if (intersectionObserverRef.current.length > 0) {\n intersectionObserverRef.current.forEach((observer, i) => {\n observer.unobserve(intersectionDomRef.current[i]!);\n });\n }\n\n intersectionDomRef.current = [];\n intersectionObserverRef.current = [];\n\n const newArr = new Array(params.dom!.length).fill(false);\n isIntersectingRef.current = [...newArr];\n isIntersectingOnceRef.current = [...newArr];\n\n params.dom!.forEach((dom, i) => {\n const callback = (entries: IntersectionObserverEntry[]) => {\n entries.forEach((entry) => {\n params.onIntersect![i] && params.onIntersect![i](entry);\n // Update the judgment after execution so that the judgment of isIntersectin can be used when executing onIntersect\n isIntersectingRef.current[i] = entry.isIntersecting;\n });\n };\n const observer = new IntersectionObserver(callback, {\n rootMargin: \"0px\",\n threshold: 0,\n });\n observer.observe(dom!);\n intersectionObserverRef.current.push(observer);\n intersectionDomRef.current.push(dom!);\n });\n },\n []\n );\n\n return intersectionHandler;\n};\n","import * as THREE from \"three\";\nimport { DomSyncerParams } from \"..\";\nimport {\n CustomParams,\n setCustomUniform,\n setUniform,\n} from \"../../../utils/setUniforms\";\nimport { DomSyncerMaterial } from \"./createMesh\";\nimport { useCallback, useRef } from \"react\";\nimport { Size } from \"../../../fxs/types\";\n\ntype UpdateDomRect = ({\n params,\n customParams,\n size,\n resolutionRef,\n scene,\n isIntersectingRef,\n}: {\n params: DomSyncerParams;\n customParams?: CustomParams;\n size: Size;\n resolutionRef: React.MutableRefObject;\n scene: THREE.Scene;\n isIntersectingRef: React.MutableRefObject;\n}) => void;\n\ntype UseUpdateDomRectReturn = [DOMRect[], UpdateDomRect];\n\nexport const useUpdateDomRect = (): UseUpdateDomRectReturn => {\n const domRects = useRef([]);\n\n const updateDomRects: UpdateDomRect = useCallback(\n ({\n params,\n customParams,\n size,\n resolutionRef,\n scene,\n isIntersectingRef,\n }) => {\n // Initialize domRects if the number of children in the scene is different from the number of DOMRect\n if (scene.children.length !== domRects.current!.length) {\n domRects.current = new Array(scene.children.length);\n }\n\n scene.children.forEach((mesh, i) => {\n const domElement = params.dom![i];\n if (!domElement) {\n return;\n }\n\n // DOMRect is updated even outside the intersection\n const rect = domElement.getBoundingClientRect();\n domRects.current[i] = rect;\n\n // Intersection cannot be determined accurately depending on the mobile navigation bar, so it seems better to update it constantly\n mesh.scale.set(rect.width, rect.height, 1.0);\n mesh.position.set(\n rect.left + rect.width * 0.5 - size.width * 0.5,\n -rect.top - rect.height * 0.5 + size.height * 0.5,\n 0.0\n );\n\n if (isIntersectingRef.current[i]) {\n if (params.rotation![i]) {\n mesh.rotation.copy(params.rotation![i]);\n }\n\n if (mesh instanceof THREE.Mesh) {\n const material: DomSyncerMaterial = mesh.material;\n const updateValue = setUniform(material);\n const updateCustomValue = setCustomUniform(material);\n updateValue(\"u_texture\", params.texture![i]);\n updateValue(\"u_textureResolution\", [\n params.texture![i]?.source?.data?.width || 0,\n params.texture![i]?.source?.data?.height || 0,\n ]);\n updateValue(\n \"u_resolution\",\n resolutionRef.current.set(rect.width, rect.height)\n );\n updateValue(\n \"u_borderRadius\",\n params.boderRadius![i] ? params.boderRadius![i] : 0.0\n );\n updateCustomValue(customParams);\n }\n }\n });\n },\n []\n );\n\n return [domRects.current, updateDomRects];\n};\n","import { useCallback, useRef } from \"react\";\n\nexport type IsIntersecting = (\n index: number,\n once?: boolean\n) => boolean[] | boolean;\n\nexport const useIsIntersecting = () => {\n const isIntersectingRef = useRef([]);\n const isIntersectingOnceRef = useRef([]);\n\n const isIntersecting: IsIntersecting = useCallback((index, once = false) => {\n isIntersectingRef.current.forEach((value, i) => {\n if (value) {\n isIntersectingOnceRef.current[i] = true;\n }\n });\n const temp = once\n ? [...isIntersectingOnceRef.current]\n : [...isIntersectingRef.current];\n return index < 0 ? temp : temp[index];\n }, []);\n\n return {\n isIntersectingRef,\n isIntersectingOnceRef,\n isIntersecting,\n };\n};\n","import { useEffect, useRef } from \"react\";\n\nexport type UseDomViewProps = {\n onView?: () => void;\n onHidden?: () => void;\n};\n\nexport type UseDomView = (props: UseDomViewProps) => void;\n\nexport const createUseDomView = (\n isIntersectingRef: React.MutableRefObject\n): UseDomView => {\n const useDomView = ({ onView, onHidden }: UseDomViewProps) => {\n const isView = useRef(false);\n useEffect(() => {\n let id: number;\n const filterIntersection = () => {\n if (isIntersectingRef.current.some((item) => item)) {\n if (!isView.current) {\n onView && onView();\n isView.current = true;\n }\n } else {\n if (isView.current) {\n onHidden && onHidden();\n isView.current = false;\n }\n }\n id = requestAnimationFrame(filterIntersection);\n };\n id = requestAnimationFrame(filterIntersection);\n return () => {\n cancelAnimationFrame(id);\n };\n }, [onView, onHidden]);\n };\n return useDomView;\n};\n","import * as THREE from \"three\";\nimport { useCallback, useMemo, useRef, useState, Key } from \"react\";\nimport { useCamera } from \"../../utils/useCamera\";\nimport { RootState } from \"@react-three/fiber\";\nimport { useSingleFBO } from \"../../utils/useSingleFBO\";\nimport { HooksProps, HooksReturn } from \"../../fxs/types\";\nimport { useParams } from \"../../utils/useParams\";\nimport { errorHandler } from \"./utils/errorHandler\";\nimport { createMesh } from \"./utils/createMesh\";\nimport { useIntersectionHandler } from \"./utils/useIntersectionHandler\";\nimport { useUpdateDomRect } from \"./utils/useUpdateDomRect\";\nimport { useIsIntersecting, IsIntersecting } from \"./utils/useIsIntersecting\";\nimport { UseDomView, createUseDomView } from \"./utils/createUseDomView\";\nimport { getDpr } from \"../../utils/getDpr\";\nimport { CustomParams } from \"../../utils/setUniforms\";\nimport { DEFAULT_TEXTURE } from \"../../libs/constants\";\n\nexport type DomSyncerParams = {\n /** DOM array you want to synchronize */\n dom?: (HTMLElement | Element | null)[];\n /** Texture array that you want to synchronize with the DOM rectangle */\n texture?: THREE.Texture[];\n /** default : `0.0[]` */\n boderRadius?: number[];\n /** the angle you want to rotate */\n rotation?: THREE.Euler[];\n /** Array of callback functions when crossed */\n onIntersect?: ((entry: IntersectionObserverEntry) => void)[];\n /** Because DOM rendering and React updates occur asynchronously, there may be a lag between updating dependent arrays and setting DOM arrays. That's what the Key is for. If the dependent array is updated but the Key is not, the loop will skip and return an empty texture. By updating the timing key when DOM acquisition is complete, you can perfectly synchronize DOM and Mesh updates.updateKey must be a unique value for each update, for example `performance.now()`.*/\n updateKey?: Key;\n};\n\nexport type DomSyncerObject = {\n scene: THREE.Scene;\n camera: THREE.Camera;\n renderTarget: THREE.WebGLRenderTarget;\n output: THREE.Texture;\n /**\n * A function that returns a determination whether the DOM intersects or not.\n * The boolean will be updated after executing the onIntersect function.\n * @param index - Index of the dom for which you want to return an intersection decision. -1 will return the entire array.\n * @param once - If set to true, it will continue to return true once crossed.\n */\n isIntersecting: IsIntersecting;\n /** target's DOMRect[] */\n DOMRects: DOMRect[];\n /** target's intersetions boolean[] */\n intersections: boolean[];\n /** You can set callbacks for when at least one DOM is visible and when it is completely hidden. */\n useDomView: UseDomView;\n};\n\nexport const DOMSYNCER_PARAMS: DomSyncerParams = {\n texture: [],\n dom: [],\n boderRadius: [],\n rotation: [],\n onIntersect: [],\n};\n\n/**\n * @link https://github.com/FunTechInc/use-shader-fx?tab=readme-ov-file#usedomsyncer\n * @param dependencies - When this dependency array is changed, the mesh and intersection judgment will be updated according to the passed DOM array.\n */\nexport const useDomSyncer = (\n { size, dpr, isSizeUpdate, renderTargetOptions, onBeforeInit }: HooksProps,\n dependencies: React.DependencyList = []\n): HooksReturn => {\n const _dpr = getDpr(dpr);\n\n const scene = useMemo(() => new THREE.Scene(), []);\n const camera = useCamera(size);\n const [renderTarget, updateRenderTarget] = useSingleFBO({\n scene,\n camera,\n size,\n dpr: _dpr.fbo,\n isSizeUpdate,\n ...renderTargetOptions,\n });\n const [params, setParams] = useParams({\n ...DOMSYNCER_PARAMS,\n updateKey: performance.now(),\n });\n\n const [DOMRects, updateDomRects] = useUpdateDomRect();\n\n // Avoid instancing vec2 every frame\n const resolutionRef = useRef(new THREE.Vector2(0, 0));\n\n // Update monitored doms according to the dependency array\n const [refreshTrigger, setRefreshTrigger] = useState(true);\n useMemo(\n () => setRefreshTrigger(true),\n // eslint-disable-next-line react-hooks/exhaustive-deps\n dependencies\n );\n\n // If the dependencies have been updated but the key has not been updated, skip processing and return an empty texture\n const updateKey = useRef(null);\n const emptyTexture = useMemo(() => DEFAULT_TEXTURE, []);\n\n // set intersection\n const intersectionHandler = useIntersectionHandler();\n const { isIntersectingOnceRef, isIntersectingRef, isIntersecting } =\n useIsIntersecting();\n\n // create useDomView\n const useDomView = createUseDomView(isIntersectingRef);\n\n const updateParams = useMemo(() => {\n return (newParams?: DomSyncerParams, customParams?: CustomParams) => {\n setParams(newParams);\n updateDomRects({\n params,\n customParams,\n size,\n resolutionRef,\n scene,\n isIntersectingRef,\n });\n };\n }, [isIntersectingRef, setParams, updateDomRects, size, scene, params]);\n\n const updateFx = useCallback(\n (\n rootState: RootState,\n newParams?: DomSyncerParams,\n customParams?: CustomParams\n ) => {\n const { gl, size } = rootState;\n\n updateParams(newParams, customParams);\n\n if (errorHandler(params)) {\n return emptyTexture;\n }\n\n if (refreshTrigger) {\n if (updateKey.current === params.updateKey) {\n return emptyTexture;\n } else {\n updateKey.current = params.updateKey!;\n }\n }\n\n if (refreshTrigger) {\n createMesh({\n params,\n size,\n scene,\n onBeforeInit,\n });\n\n intersectionHandler({\n isIntersectingRef,\n isIntersectingOnceRef,\n params,\n });\n\n setRefreshTrigger(false);\n }\n\n return updateRenderTarget(gl);\n },\n [\n updateRenderTarget,\n intersectionHandler,\n onBeforeInit,\n updateParams,\n refreshTrigger,\n scene,\n params,\n isIntersectingOnceRef,\n isIntersectingRef,\n emptyTexture,\n ]\n );\n\n return [\n updateFx,\n updateParams,\n {\n scene,\n camera,\n renderTarget,\n output: renderTarget.texture,\n isIntersecting,\n DOMRects,\n intersections: isIntersectingRef.current,\n useDomView,\n },\n ];\n};\n","import * as THREE from \"three\";\nimport { useCallback, useEffect, useMemo, useRef } from \"react\";\nimport { useResolution } from \"../utils/useResolution\";\nimport {\n UseFboProps,\n renderFBO,\n FBO_DEFAULT_OPTION,\n} from \"../utils/useSingleFBO\";\n\ntype UpdateCopyFunction = (\n gl: THREE.WebGLRenderer,\n index: number,\n /** call before FBO is rendered */\n onBeforeRender?: ({ read }: { read: THREE.Texture }) => void\n) => THREE.Texture;\n\ntype UseCopyTextureReturn = [THREE.WebGLRenderTarget[], UpdateCopyFunction];\n\n/**\n * Generate an FBO array to copy the texture.\n * @param dpr If dpr is set, dpr will be multiplied, default : `false`\n * @param isSizeUpdate Whether to resize when resizing occurs. If isDpr is true, set FBO to setSize even if dpr is changed, default : `false`\n * @param length The number of FBOs to create\n * @returns [THREE.WebGLRenderTarget[] , updateCopyTexture] - Receives the RenderTarget array as the first argument and the update function as the second argument. `updateCopyTexture()` receives gl as the first argument and the index of the texture you want to copy as the second argument.\n */\nexport const useCopyTexture = (\n props: UseFboProps,\n length: number\n): UseCopyTextureReturn => {\n const {\n scene,\n camera,\n size,\n dpr = false,\n isSizeUpdate = false,\n depth = false,\n ...targetSettings\n } = props;\n\n const renderTargetArr = useRef([]);\n const resolution = useResolution(size, dpr);\n\n renderTargetArr.current = useMemo(() => {\n return Array.from({ length }, () => {\n const target = new THREE.WebGLRenderTarget(\n resolution.x,\n resolution.y,\n {\n ...FBO_DEFAULT_OPTION,\n ...targetSettings,\n }\n );\n if (depth) {\n target.depthTexture = new THREE.DepthTexture(\n resolution.x,\n resolution.y,\n THREE.FloatType\n );\n }\n return target;\n });\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [length]);\n\n if (isSizeUpdate) {\n renderTargetArr.current.forEach((fbo) =>\n fbo.setSize(resolution.x, resolution.y)\n );\n }\n\n useEffect(() => {\n const temp = renderTargetArr.current;\n return () => {\n temp.forEach((fbo) => fbo.dispose());\n };\n }, [length]);\n\n const updateCopyTexture: UpdateCopyFunction = useCallback(\n (gl, index, onBeforeRender) => {\n const fbo = renderTargetArr.current[index];\n renderFBO({\n gl,\n scene,\n camera,\n fbo,\n onBeforeRender: () =>\n onBeforeRender && onBeforeRender({ read: fbo.texture }),\n });\n return fbo.texture;\n },\n [scene, camera]\n );\n\n return [renderTargetArr.current, updateCopyTexture];\n};\n","type Utils = {\n interpolate: (\n startValue: number,\n endValue: number,\n progress: number,\n threshold?: number\n ) => number;\n smoothstep: (edge0: number, edge1: number, x: number) => number;\n};\n\nexport const Utils: Utils = Object.freeze({\n interpolate(startValue, endValue, progress, threshold = 1e-6): number {\n const t = startValue + (endValue - startValue) * progress;\n return Math.abs(t) < threshold ? 0 : t;\n },\n smoothstep(edge0, edge1, x) {\n const t = Math.min(Math.max((x - edge0) / (edge1 - edge0), 0), 1);\n return t * t * (3 - 2 * t);\n },\n});\n"],"names":["main_default","useResolution","size","dpr","_width","_height","useMemo","THREE","setUniform","material","key","value","uniforms","setCustomUniform","customParams","useAddObject","scene","geometry","Proto","object3D","obj","useEffect","ISDEV","MATERIAL_BASIC_PARAMS","DEFAULT_TEXTURE","wobble3D_default","snoise_default","coverTexture_default","fxBlending_default","planeVertex_default","defaultVertex_default","hsv2rgb_default","rgb2hsv_default","ShaderChunk","wobble3D","snoise","coverTexture","fxBlending","planeVertex","defaultVertex","hsv2rgb","rgb2hsv","includePattern","includeReplacer","match","include","resolveIncludes","string","createMaterialParameters","parameters","onBeforeInit","useMesh","BRUSH_PARAMS","vertexShader","fragmentShader","resolution","mesh","getCameraProps","width","height","frustumSize","aspect","w","h","useCamera","cameraType","near","far","usePointer","lerp","prevPointer","useRef","diffPointer","lerpPointer","lastUpdateTime","velocity","isMoved","useCallback","currentPointer","now","current","deltaTime","isUpdate","prevTemp","useParams","params","isContainsFunctions","paramsRef","setParams","newParams","paramKey","FBO_DEFAULT_OPTION","renderFBO","gl","fbo","camera","onBeforeRender","onSwap","useSingleFBO","props","isSizeUpdate","depth","renderTargetOptions","renderTarget","target","_a","temp","updateRenderTarget","useDoubleFBO","read","write","_b","getDpr","useBrush","_dpr","updatePointer","pressureEnd","updateValue","updateCustomValue","updateParams","rootState","pointer","pointerValues","color","init_default","useInitialMaterial","advection_default","useAdvectionMaterial","DELTA_TIME","divergence_default","useDivergenceMaterial","pressure_default","usePressureMaterial","curl_default","useCurlMaterial","vorticity_default","useVorticityMaterial","clear_default","useClearMaterial","gradientSubtract_default","useGradientSubtractMaterial","splat_default","useSplatMaterial","useCustomMaterial","materialHook","materialProps","customFluidProps","curl","vorticity","advection","divergence","pressure","clear","gradientSubtract","splat","initialMaterial","updateMaterial","curlMaterial","vorticityMaterial","advectionMaterial","divergenceMaterial","pressureMaterial","clearMaterial","gradientSubtractMaterial","splatMaterial","materials","setMeshMaterial","FLUID_PARAMS","useFluid","fboProps","velocityFBO","updateVelocityFBO","densityFBO","updateDensityFBO","curlFBO","updateCurlFBO","divergenceFBO","updateDivergenceFBO","pressureFBO","updatePressureFBO","scaledDiffVec","spaltVec","updateParamsList","updateCustomParamsList","velocityTex","densityTex","scaledDiff","curlTex","divergenceTex","pressureTexTemp","i","scale","max","texture","meshArr","clonedMat","RIPPLE_PARAMS","useRipple","currentWave","opacity","NOISE_PARAMS","useNoise","clock","COLORSTRATA_PARAMS","useColorStrata","MARBLE_PARAMS","useMarble","COSPALETTE_PARAMS","useCosPalette","DUOTONE_PARAMS","useDuoTone","BLENDING_PARAMS","useBlending","FXTEXTURE_PARAMS","useFxTexture","tex0Res","_d","_c","tex1Res","_f","_e","_h","_g","interpolatedResolution","index","BRIGHTNESSPICKER_PARAMS","useBrightnessPicker","FXBLENDING_PARAMS","useFxBlending","ALPHABLENDING_PARAMS","useAlphaBlending","HSV_PARAMS","useHSV","COVERTEXTURE_PARAMS","useCoverTexture","SIMPLEBLUR_PARAMS","useSimpleBlur","updateTempTexture","_tempTexture","MOTIONBLUR_PARAMS","useMotionBlur","WAVE_PARAMS","useWave","CHROMAKEY_PARAMS","useChromaKey","BLANK_PARAMS","useBlank","RAWBLANK_PARAMS","useRawBlank","useCreateObject","points","interactiveMesh","rewriteVertexShader","modifeidAttributes","targetGeometry","targetAttibute","itemSize","vTargetName","vAttributeRewriteKey","vTransitionRewriteKey","vListName","vMorphTransition","stringToAddToMorphAttibutes","stringToAddToMorphAttibutesList","modifyAttributes","attribute","modifiedAttribute","maxLength","arr","diff","addArray","oldArray","randomIndex","j","rewriteFragmentShader","mapArray","mapArrayShader","mapArrayUniforms","textureSwitcherCode","map","condition","action","useMaterial","positions","uvs","modifiedPositions","modifiedUvs","rewritedVertexShader","rewritedFragmentShader","MORPHPARTICLES_PARAMS","useCreateMorphParticles","morphGeometry","geo","useMorphParticles","updateUniform","generatedPositions","generatedUvs","updateFx","isDepth","transmission_pars_fragment_default","transmission_fragment_default","resolveEachMaterial","mat","isCustomTransmission","transmission_pars_fragment","transmission_fragment","baseMaterial","materialParameters","depthOnBeforeInit","depthMaterial","WOBBLE3D_PARAMS","cutomizedParams","depthMat","useCreateWobble3D","wobbleGeometry","mergeVertices","userData","useWobble3D","RootState","useAddMesh","checkUpdate","currentW","currentH","memoW","memoH","threshold","boundFor","isSmaller","isLarger","useResizeBoundary","memorizedSize","Easing","x","c2","c4","c5","getHash","input","useBeat","bpm","ease","rhythm","easing","beat","floor","fract","hash","useFPSLimiter","fps","interval","prevTime","tick","errorHandler","domLength","textureLength","createMesh","child","useIntersectionHandler","intersectionObserverRef","intersectionDomRef","isIntersectingRef","isIntersectingOnceRef","observer","newArr","dom","callback","entries","entry","useUpdateDomRect","domRects","updateDomRects","resolutionRef","domElement","rect","useIsIntersecting","isIntersecting","once","createUseDomView","onView","onHidden","isView","id","filterIntersection","item","DOMSYNCER_PARAMS","useDomSyncer","dependencies","DOMRects","refreshTrigger","setRefreshTrigger","useState","updateKey","emptyTexture","intersectionHandler","useDomView","useCopyTexture","length","targetSettings","renderTargetArr","updateCopyTexture","Utils","startValue","endValue","progress","t","edge0","edge1"],"mappings":"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"} \ No newline at end of file diff --git a/packages/use-shader-fx/src/fxs/3D/types/index.ts b/packages/use-shader-fx/legacy/fxs/3D/types/index.ts similarity index 100% rename from packages/use-shader-fx/src/fxs/3D/types/index.ts rename to packages/use-shader-fx/legacy/fxs/3D/types/index.ts diff --git a/packages/use-shader-fx/src/fxs/3D/useMorphParticles/index.ts b/packages/use-shader-fx/legacy/fxs/3D/useMorphParticles/index.ts similarity index 100% rename from packages/use-shader-fx/src/fxs/3D/useMorphParticles/index.ts rename to packages/use-shader-fx/legacy/fxs/3D/useMorphParticles/index.ts diff --git a/packages/use-shader-fx/src/fxs/3D/useMorphParticles/shaders/main.frag b/packages/use-shader-fx/legacy/fxs/3D/useMorphParticles/shaders/main.frag similarity index 100% rename from packages/use-shader-fx/src/fxs/3D/useMorphParticles/shaders/main.frag rename to packages/use-shader-fx/legacy/fxs/3D/useMorphParticles/shaders/main.frag diff --git a/packages/use-shader-fx/src/fxs/3D/useMorphParticles/shaders/main.vert b/packages/use-shader-fx/legacy/fxs/3D/useMorphParticles/shaders/main.vert similarity index 100% rename from packages/use-shader-fx/src/fxs/3D/useMorphParticles/shaders/main.vert rename to packages/use-shader-fx/legacy/fxs/3D/useMorphParticles/shaders/main.vert diff --git a/packages/use-shader-fx/src/fxs/3D/useMorphParticles/useCreateMorphParticles.ts b/packages/use-shader-fx/legacy/fxs/3D/useMorphParticles/useCreateMorphParticles.ts similarity index 100% rename from packages/use-shader-fx/src/fxs/3D/useMorphParticles/useCreateMorphParticles.ts rename to packages/use-shader-fx/legacy/fxs/3D/useMorphParticles/useCreateMorphParticles.ts diff --git a/packages/use-shader-fx/src/fxs/3D/useMorphParticles/utils/modifyAttributes.ts b/packages/use-shader-fx/legacy/fxs/3D/useMorphParticles/utils/modifyAttributes.ts similarity index 100% rename from packages/use-shader-fx/src/fxs/3D/useMorphParticles/utils/modifyAttributes.ts rename to packages/use-shader-fx/legacy/fxs/3D/useMorphParticles/utils/modifyAttributes.ts diff --git a/packages/use-shader-fx/src/fxs/3D/useMorphParticles/utils/rewriteFragmentShader.ts b/packages/use-shader-fx/legacy/fxs/3D/useMorphParticles/utils/rewriteFragmentShader.ts similarity index 100% rename from packages/use-shader-fx/src/fxs/3D/useMorphParticles/utils/rewriteFragmentShader.ts rename to packages/use-shader-fx/legacy/fxs/3D/useMorphParticles/utils/rewriteFragmentShader.ts diff --git a/packages/use-shader-fx/src/fxs/3D/useMorphParticles/utils/rewriteVertexShader.ts b/packages/use-shader-fx/legacy/fxs/3D/useMorphParticles/utils/rewriteVertexShader.ts similarity index 100% rename from packages/use-shader-fx/src/fxs/3D/useMorphParticles/utils/rewriteVertexShader.ts rename to packages/use-shader-fx/legacy/fxs/3D/useMorphParticles/utils/rewriteVertexShader.ts diff --git a/packages/use-shader-fx/src/fxs/3D/useMorphParticles/utils/useCreateObject.ts b/packages/use-shader-fx/legacy/fxs/3D/useMorphParticles/utils/useCreateObject.ts similarity index 100% rename from packages/use-shader-fx/src/fxs/3D/useMorphParticles/utils/useCreateObject.ts rename to packages/use-shader-fx/legacy/fxs/3D/useMorphParticles/utils/useCreateObject.ts diff --git a/packages/use-shader-fx/src/fxs/3D/useMorphParticles/utils/useMaterial.ts b/packages/use-shader-fx/legacy/fxs/3D/useMorphParticles/utils/useMaterial.ts similarity index 100% rename from packages/use-shader-fx/src/fxs/3D/useMorphParticles/utils/useMaterial.ts rename to packages/use-shader-fx/legacy/fxs/3D/useMorphParticles/utils/useMaterial.ts diff --git a/packages/use-shader-fx/src/fxs/3D/useWobble3D/index.ts b/packages/use-shader-fx/legacy/fxs/3D/useWobble3D/index.ts similarity index 100% rename from packages/use-shader-fx/src/fxs/3D/useWobble3D/index.ts rename to packages/use-shader-fx/legacy/fxs/3D/useWobble3D/index.ts diff --git a/packages/use-shader-fx/src/fxs/3D/useWobble3D/shaders/transmission_fragment.glsl b/packages/use-shader-fx/legacy/fxs/3D/useWobble3D/shaders/transmission_fragment.glsl similarity index 100% rename from packages/use-shader-fx/src/fxs/3D/useWobble3D/shaders/transmission_fragment.glsl rename to packages/use-shader-fx/legacy/fxs/3D/useWobble3D/shaders/transmission_fragment.glsl diff --git a/packages/use-shader-fx/src/fxs/3D/useWobble3D/shaders/transmission_pars_fragment.glsl b/packages/use-shader-fx/legacy/fxs/3D/useWobble3D/shaders/transmission_pars_fragment.glsl similarity index 100% rename from packages/use-shader-fx/src/fxs/3D/useWobble3D/shaders/transmission_pars_fragment.glsl rename to packages/use-shader-fx/legacy/fxs/3D/useWobble3D/shaders/transmission_pars_fragment.glsl diff --git a/packages/use-shader-fx/src/fxs/3D/useWobble3D/useCreateWobble3D.ts b/packages/use-shader-fx/legacy/fxs/3D/useWobble3D/useCreateWobble3D.ts similarity index 100% rename from packages/use-shader-fx/src/fxs/3D/useWobble3D/useCreateWobble3D.ts rename to packages/use-shader-fx/legacy/fxs/3D/useWobble3D/useCreateWobble3D.ts diff --git a/packages/use-shader-fx/src/fxs/3D/useWobble3D/useMaterial.ts b/packages/use-shader-fx/legacy/fxs/3D/useWobble3D/useMaterial.ts similarity index 100% rename from packages/use-shader-fx/src/fxs/3D/useWobble3D/useMaterial.ts rename to packages/use-shader-fx/legacy/fxs/3D/useWobble3D/useMaterial.ts diff --git a/packages/use-shader-fx/src/fxs/3D/useWobble3D/utils/resolveEachMaterial.ts b/packages/use-shader-fx/legacy/fxs/3D/useWobble3D/utils/resolveEachMaterial.ts similarity index 100% rename from packages/use-shader-fx/src/fxs/3D/useWobble3D/utils/resolveEachMaterial.ts rename to packages/use-shader-fx/legacy/fxs/3D/useWobble3D/utils/resolveEachMaterial.ts diff --git a/packages/use-shader-fx/src/fxs/3D/useWobble3D/utils/rewriteFragmentShader.ts b/packages/use-shader-fx/legacy/fxs/3D/useWobble3D/utils/rewriteFragmentShader.ts similarity index 100% rename from packages/use-shader-fx/src/fxs/3D/useWobble3D/utils/rewriteFragmentShader.ts rename to packages/use-shader-fx/legacy/fxs/3D/useWobble3D/utils/rewriteFragmentShader.ts diff --git a/packages/use-shader-fx/src/fxs/3D/useWobble3D/utils/rewriteVertexShader.ts b/packages/use-shader-fx/legacy/fxs/3D/useWobble3D/utils/rewriteVertexShader.ts similarity index 100% rename from packages/use-shader-fx/src/fxs/3D/useWobble3D/utils/rewriteVertexShader.ts rename to packages/use-shader-fx/legacy/fxs/3D/useWobble3D/utils/rewriteVertexShader.ts diff --git a/packages/use-shader-fx/src/fxs/blank/useBlank/index.ts b/packages/use-shader-fx/legacy/fxs/blank/useBlank/index.ts similarity index 100% rename from packages/use-shader-fx/src/fxs/blank/useBlank/index.ts rename to packages/use-shader-fx/legacy/fxs/blank/useBlank/index.ts diff --git a/packages/use-shader-fx/src/fxs/blank/useBlank/shader/main.frag b/packages/use-shader-fx/legacy/fxs/blank/useBlank/shader/main.frag similarity index 100% rename from packages/use-shader-fx/src/fxs/blank/useBlank/shader/main.frag rename to packages/use-shader-fx/legacy/fxs/blank/useBlank/shader/main.frag diff --git a/packages/use-shader-fx/src/fxs/blank/useBlank/shader/main.vert b/packages/use-shader-fx/legacy/fxs/blank/useBlank/shader/main.vert similarity index 100% rename from packages/use-shader-fx/src/fxs/blank/useBlank/shader/main.vert rename to packages/use-shader-fx/legacy/fxs/blank/useBlank/shader/main.vert diff --git a/packages/use-shader-fx/src/fxs/blank/useBlank/useMesh.ts b/packages/use-shader-fx/legacy/fxs/blank/useBlank/useMesh.ts similarity index 100% rename from packages/use-shader-fx/src/fxs/blank/useBlank/useMesh.ts rename to packages/use-shader-fx/legacy/fxs/blank/useBlank/useMesh.ts diff --git a/packages/use-shader-fx/src/fxs/blank/useRawBlank/index.ts b/packages/use-shader-fx/legacy/fxs/blank/useRawBlank/index.ts similarity index 100% rename from packages/use-shader-fx/src/fxs/blank/useRawBlank/index.ts rename to packages/use-shader-fx/legacy/fxs/blank/useRawBlank/index.ts diff --git a/packages/use-shader-fx/src/fxs/blank/useRawBlank/shader/main.frag b/packages/use-shader-fx/legacy/fxs/blank/useRawBlank/shader/main.frag similarity index 100% rename from packages/use-shader-fx/src/fxs/blank/useRawBlank/shader/main.frag rename to packages/use-shader-fx/legacy/fxs/blank/useRawBlank/shader/main.frag diff --git a/packages/use-shader-fx/src/fxs/blank/useRawBlank/shader/main.vert b/packages/use-shader-fx/legacy/fxs/blank/useRawBlank/shader/main.vert similarity index 100% rename from packages/use-shader-fx/src/fxs/blank/useRawBlank/shader/main.vert rename to packages/use-shader-fx/legacy/fxs/blank/useRawBlank/shader/main.vert diff --git a/packages/use-shader-fx/src/fxs/blank/useRawBlank/useMesh.ts b/packages/use-shader-fx/legacy/fxs/blank/useRawBlank/useMesh.ts similarity index 100% rename from packages/use-shader-fx/src/fxs/blank/useRawBlank/useMesh.ts rename to packages/use-shader-fx/legacy/fxs/blank/useRawBlank/useMesh.ts diff --git a/packages/use-shader-fx/src/fxs/effects/useMotionBlur/index.ts b/packages/use-shader-fx/legacy/fxs/effects/useMotionBlur/index.ts similarity index 100% rename from packages/use-shader-fx/src/fxs/effects/useMotionBlur/index.ts rename to packages/use-shader-fx/legacy/fxs/effects/useMotionBlur/index.ts diff --git a/packages/use-shader-fx/src/fxs/effects/useMotionBlur/shader/main.frag b/packages/use-shader-fx/legacy/fxs/effects/useMotionBlur/shader/main.frag similarity index 100% rename from packages/use-shader-fx/src/fxs/effects/useMotionBlur/shader/main.frag rename to packages/use-shader-fx/legacy/fxs/effects/useMotionBlur/shader/main.frag diff --git a/packages/use-shader-fx/src/fxs/effects/useMotionBlur/shader/main.vert b/packages/use-shader-fx/legacy/fxs/effects/useMotionBlur/shader/main.vert similarity index 100% rename from packages/use-shader-fx/src/fxs/effects/useMotionBlur/shader/main.vert rename to packages/use-shader-fx/legacy/fxs/effects/useMotionBlur/shader/main.vert diff --git a/packages/use-shader-fx/src/fxs/effects/useMotionBlur/useMesh.ts b/packages/use-shader-fx/legacy/fxs/effects/useMotionBlur/useMesh.ts similarity index 100% rename from packages/use-shader-fx/src/fxs/effects/useMotionBlur/useMesh.ts rename to packages/use-shader-fx/legacy/fxs/effects/useMotionBlur/useMesh.ts diff --git a/packages/use-shader-fx/src/fxs/effects/useSimpleBlur/index.ts b/packages/use-shader-fx/legacy/fxs/effects/useSimpleBlur/index.ts similarity index 100% rename from packages/use-shader-fx/src/fxs/effects/useSimpleBlur/index.ts rename to packages/use-shader-fx/legacy/fxs/effects/useSimpleBlur/index.ts diff --git a/packages/use-shader-fx/src/fxs/effects/useSimpleBlur/shader/main.frag b/packages/use-shader-fx/legacy/fxs/effects/useSimpleBlur/shader/main.frag similarity index 100% rename from packages/use-shader-fx/src/fxs/effects/useSimpleBlur/shader/main.frag rename to packages/use-shader-fx/legacy/fxs/effects/useSimpleBlur/shader/main.frag diff --git a/packages/use-shader-fx/src/fxs/effects/useSimpleBlur/shader/main.vert b/packages/use-shader-fx/legacy/fxs/effects/useSimpleBlur/shader/main.vert similarity index 100% rename from packages/use-shader-fx/src/fxs/effects/useSimpleBlur/shader/main.vert rename to packages/use-shader-fx/legacy/fxs/effects/useSimpleBlur/shader/main.vert diff --git a/packages/use-shader-fx/src/fxs/effects/useSimpleBlur/useMesh.ts b/packages/use-shader-fx/legacy/fxs/effects/useSimpleBlur/useMesh.ts similarity index 100% rename from packages/use-shader-fx/src/fxs/effects/useSimpleBlur/useMesh.ts rename to packages/use-shader-fx/legacy/fxs/effects/useSimpleBlur/useMesh.ts diff --git a/packages/use-shader-fx/src/fxs/effects/useWave/index.ts b/packages/use-shader-fx/legacy/fxs/effects/useWave/index.ts similarity index 100% rename from packages/use-shader-fx/src/fxs/effects/useWave/index.ts rename to packages/use-shader-fx/legacy/fxs/effects/useWave/index.ts diff --git a/packages/use-shader-fx/src/fxs/effects/useWave/shader/main.frag b/packages/use-shader-fx/legacy/fxs/effects/useWave/shader/main.frag similarity index 100% rename from packages/use-shader-fx/src/fxs/effects/useWave/shader/main.frag rename to packages/use-shader-fx/legacy/fxs/effects/useWave/shader/main.frag diff --git a/packages/use-shader-fx/src/fxs/effects/useWave/shader/main.vert b/packages/use-shader-fx/legacy/fxs/effects/useWave/shader/main.vert similarity index 100% rename from packages/use-shader-fx/src/fxs/effects/useWave/shader/main.vert rename to packages/use-shader-fx/legacy/fxs/effects/useWave/shader/main.vert diff --git a/packages/use-shader-fx/src/fxs/effects/useWave/useMesh.ts b/packages/use-shader-fx/legacy/fxs/effects/useWave/useMesh.ts similarity index 100% rename from packages/use-shader-fx/src/fxs/effects/useWave/useMesh.ts rename to packages/use-shader-fx/legacy/fxs/effects/useWave/useMesh.ts diff --git a/packages/use-shader-fx/src/fxs/interactions/useBrush/index.ts b/packages/use-shader-fx/legacy/fxs/interactions/useBrush/index.ts similarity index 100% rename from packages/use-shader-fx/src/fxs/interactions/useBrush/index.ts rename to packages/use-shader-fx/legacy/fxs/interactions/useBrush/index.ts diff --git a/packages/use-shader-fx/src/fxs/interactions/useBrush/shader/main.frag b/packages/use-shader-fx/legacy/fxs/interactions/useBrush/shader/main.frag similarity index 100% rename from packages/use-shader-fx/src/fxs/interactions/useBrush/shader/main.frag rename to packages/use-shader-fx/legacy/fxs/interactions/useBrush/shader/main.frag diff --git a/packages/use-shader-fx/src/fxs/interactions/useBrush/shader/main.vert b/packages/use-shader-fx/legacy/fxs/interactions/useBrush/shader/main.vert similarity index 100% rename from packages/use-shader-fx/src/fxs/interactions/useBrush/shader/main.vert rename to packages/use-shader-fx/legacy/fxs/interactions/useBrush/shader/main.vert diff --git a/packages/use-shader-fx/src/fxs/interactions/useBrush/useMesh.ts b/packages/use-shader-fx/legacy/fxs/interactions/useBrush/useMesh.ts similarity index 100% rename from packages/use-shader-fx/src/fxs/interactions/useBrush/useMesh.ts rename to packages/use-shader-fx/legacy/fxs/interactions/useBrush/useMesh.ts diff --git a/packages/use-shader-fx/src/fxs/misc/useChromaKey/index.ts b/packages/use-shader-fx/legacy/fxs/misc/useChromaKey/index.ts similarity index 100% rename from packages/use-shader-fx/src/fxs/misc/useChromaKey/index.ts rename to packages/use-shader-fx/legacy/fxs/misc/useChromaKey/index.ts diff --git a/packages/use-shader-fx/src/fxs/misc/useChromaKey/shader/main.frag b/packages/use-shader-fx/legacy/fxs/misc/useChromaKey/shader/main.frag similarity index 100% rename from packages/use-shader-fx/src/fxs/misc/useChromaKey/shader/main.frag rename to packages/use-shader-fx/legacy/fxs/misc/useChromaKey/shader/main.frag diff --git a/packages/use-shader-fx/src/fxs/misc/useChromaKey/shader/main.vert b/packages/use-shader-fx/legacy/fxs/misc/useChromaKey/shader/main.vert similarity index 100% rename from packages/use-shader-fx/src/fxs/misc/useChromaKey/shader/main.vert rename to packages/use-shader-fx/legacy/fxs/misc/useChromaKey/shader/main.vert diff --git a/packages/use-shader-fx/src/fxs/misc/useChromaKey/useMesh.ts b/packages/use-shader-fx/legacy/fxs/misc/useChromaKey/useMesh.ts similarity index 100% rename from packages/use-shader-fx/src/fxs/misc/useChromaKey/useMesh.ts rename to packages/use-shader-fx/legacy/fxs/misc/useChromaKey/useMesh.ts diff --git a/packages/use-shader-fx/src/fxs/noises/useColorStrata/index.ts b/packages/use-shader-fx/legacy/fxs/noises/useColorStrata/index.ts similarity index 100% rename from packages/use-shader-fx/src/fxs/noises/useColorStrata/index.ts rename to packages/use-shader-fx/legacy/fxs/noises/useColorStrata/index.ts diff --git a/packages/use-shader-fx/src/fxs/noises/useColorStrata/shader/main.frag b/packages/use-shader-fx/legacy/fxs/noises/useColorStrata/shader/main.frag similarity index 100% rename from packages/use-shader-fx/src/fxs/noises/useColorStrata/shader/main.frag rename to packages/use-shader-fx/legacy/fxs/noises/useColorStrata/shader/main.frag diff --git a/packages/use-shader-fx/src/fxs/noises/useColorStrata/shader/main.vert b/packages/use-shader-fx/legacy/fxs/noises/useColorStrata/shader/main.vert similarity index 100% rename from packages/use-shader-fx/src/fxs/noises/useColorStrata/shader/main.vert rename to packages/use-shader-fx/legacy/fxs/noises/useColorStrata/shader/main.vert diff --git a/packages/use-shader-fx/src/fxs/noises/useColorStrata/useMesh.ts b/packages/use-shader-fx/legacy/fxs/noises/useColorStrata/useMesh.ts similarity index 100% rename from packages/use-shader-fx/src/fxs/noises/useColorStrata/useMesh.ts rename to packages/use-shader-fx/legacy/fxs/noises/useColorStrata/useMesh.ts diff --git a/packages/use-shader-fx/src/fxs/noises/useCosPalette/index.ts b/packages/use-shader-fx/legacy/fxs/noises/useCosPalette/index.ts similarity index 100% rename from packages/use-shader-fx/src/fxs/noises/useCosPalette/index.ts rename to packages/use-shader-fx/legacy/fxs/noises/useCosPalette/index.ts diff --git a/packages/use-shader-fx/src/fxs/noises/useCosPalette/shader/main.frag b/packages/use-shader-fx/legacy/fxs/noises/useCosPalette/shader/main.frag similarity index 100% rename from packages/use-shader-fx/src/fxs/noises/useCosPalette/shader/main.frag rename to packages/use-shader-fx/legacy/fxs/noises/useCosPalette/shader/main.frag diff --git a/packages/use-shader-fx/src/fxs/noises/useCosPalette/shader/main.vert b/packages/use-shader-fx/legacy/fxs/noises/useCosPalette/shader/main.vert similarity index 100% rename from packages/use-shader-fx/src/fxs/noises/useCosPalette/shader/main.vert rename to packages/use-shader-fx/legacy/fxs/noises/useCosPalette/shader/main.vert diff --git a/packages/use-shader-fx/src/fxs/noises/useCosPalette/useMesh.ts b/packages/use-shader-fx/legacy/fxs/noises/useCosPalette/useMesh.ts similarity index 100% rename from packages/use-shader-fx/src/fxs/noises/useCosPalette/useMesh.ts rename to packages/use-shader-fx/legacy/fxs/noises/useCosPalette/useMesh.ts diff --git a/packages/use-shader-fx/src/fxs/noises/useMarble/index.ts b/packages/use-shader-fx/legacy/fxs/noises/useMarble/index.ts similarity index 100% rename from packages/use-shader-fx/src/fxs/noises/useMarble/index.ts rename to packages/use-shader-fx/legacy/fxs/noises/useMarble/index.ts diff --git a/packages/use-shader-fx/src/fxs/noises/useMarble/shader/main.frag b/packages/use-shader-fx/legacy/fxs/noises/useMarble/shader/main.frag similarity index 100% rename from packages/use-shader-fx/src/fxs/noises/useMarble/shader/main.frag rename to packages/use-shader-fx/legacy/fxs/noises/useMarble/shader/main.frag diff --git a/packages/use-shader-fx/src/fxs/noises/useMarble/shader/main.vert b/packages/use-shader-fx/legacy/fxs/noises/useMarble/shader/main.vert similarity index 100% rename from packages/use-shader-fx/src/fxs/noises/useMarble/shader/main.vert rename to packages/use-shader-fx/legacy/fxs/noises/useMarble/shader/main.vert diff --git a/packages/use-shader-fx/src/fxs/noises/useMarble/useMesh.ts b/packages/use-shader-fx/legacy/fxs/noises/useMarble/useMesh.ts similarity index 100% rename from packages/use-shader-fx/src/fxs/noises/useMarble/useMesh.ts rename to packages/use-shader-fx/legacy/fxs/noises/useMarble/useMesh.ts diff --git a/packages/use-shader-fx/src/fxs/noises/useNoise/index.ts b/packages/use-shader-fx/legacy/fxs/noises/useNoise/index.ts similarity index 100% rename from packages/use-shader-fx/src/fxs/noises/useNoise/index.ts rename to packages/use-shader-fx/legacy/fxs/noises/useNoise/index.ts diff --git a/packages/use-shader-fx/src/fxs/noises/useNoise/shader/main.frag b/packages/use-shader-fx/legacy/fxs/noises/useNoise/shader/main.frag similarity index 100% rename from packages/use-shader-fx/src/fxs/noises/useNoise/shader/main.frag rename to packages/use-shader-fx/legacy/fxs/noises/useNoise/shader/main.frag diff --git a/packages/use-shader-fx/src/fxs/noises/useNoise/shader/main.vert b/packages/use-shader-fx/legacy/fxs/noises/useNoise/shader/main.vert similarity index 100% rename from packages/use-shader-fx/src/fxs/noises/useNoise/shader/main.vert rename to packages/use-shader-fx/legacy/fxs/noises/useNoise/shader/main.vert diff --git a/packages/use-shader-fx/src/fxs/noises/useNoise/useMesh.ts b/packages/use-shader-fx/legacy/fxs/noises/useNoise/useMesh.ts similarity index 100% rename from packages/use-shader-fx/src/fxs/noises/useNoise/useMesh.ts rename to packages/use-shader-fx/legacy/fxs/noises/useNoise/useMesh.ts diff --git a/packages/use-shader-fx/src/fxs/simulations/useFluid/index.ts b/packages/use-shader-fx/legacy/fxs/simulations/useFluid/index.ts similarity index 100% rename from packages/use-shader-fx/src/fxs/simulations/useFluid/index.ts rename to packages/use-shader-fx/legacy/fxs/simulations/useFluid/index.ts diff --git a/packages/use-shader-fx/src/fxs/simulations/useFluid/materials/useAdvectionMaterial.ts b/packages/use-shader-fx/legacy/fxs/simulations/useFluid/materials/useAdvectionMaterial.ts similarity index 100% rename from packages/use-shader-fx/src/fxs/simulations/useFluid/materials/useAdvectionMaterial.ts rename to packages/use-shader-fx/legacy/fxs/simulations/useFluid/materials/useAdvectionMaterial.ts diff --git a/packages/use-shader-fx/src/fxs/simulations/useFluid/materials/useClearMaterial.ts b/packages/use-shader-fx/legacy/fxs/simulations/useFluid/materials/useClearMaterial.ts similarity index 100% rename from packages/use-shader-fx/src/fxs/simulations/useFluid/materials/useClearMaterial.ts rename to packages/use-shader-fx/legacy/fxs/simulations/useFluid/materials/useClearMaterial.ts diff --git a/packages/use-shader-fx/src/fxs/simulations/useFluid/materials/useCurlMaterial.ts b/packages/use-shader-fx/legacy/fxs/simulations/useFluid/materials/useCurlMaterial.ts similarity index 100% rename from packages/use-shader-fx/src/fxs/simulations/useFluid/materials/useCurlMaterial.ts rename to packages/use-shader-fx/legacy/fxs/simulations/useFluid/materials/useCurlMaterial.ts diff --git a/packages/use-shader-fx/src/fxs/simulations/useFluid/materials/useDivergenceMaterial.ts b/packages/use-shader-fx/legacy/fxs/simulations/useFluid/materials/useDivergenceMaterial.ts similarity index 100% rename from packages/use-shader-fx/src/fxs/simulations/useFluid/materials/useDivergenceMaterial.ts rename to packages/use-shader-fx/legacy/fxs/simulations/useFluid/materials/useDivergenceMaterial.ts diff --git a/packages/use-shader-fx/src/fxs/simulations/useFluid/materials/useGradientSubtractMaterial.ts b/packages/use-shader-fx/legacy/fxs/simulations/useFluid/materials/useGradientSubtractMaterial.ts similarity index 100% rename from packages/use-shader-fx/src/fxs/simulations/useFluid/materials/useGradientSubtractMaterial.ts rename to packages/use-shader-fx/legacy/fxs/simulations/useFluid/materials/useGradientSubtractMaterial.ts diff --git a/packages/use-shader-fx/src/fxs/simulations/useFluid/materials/useInitialMaterial.ts b/packages/use-shader-fx/legacy/fxs/simulations/useFluid/materials/useInitialMaterial.ts similarity index 100% rename from packages/use-shader-fx/src/fxs/simulations/useFluid/materials/useInitialMaterial.ts rename to packages/use-shader-fx/legacy/fxs/simulations/useFluid/materials/useInitialMaterial.ts diff --git a/packages/use-shader-fx/src/fxs/simulations/useFluid/materials/usePressureMaterial.ts b/packages/use-shader-fx/legacy/fxs/simulations/useFluid/materials/usePressureMaterial.ts similarity index 100% rename from packages/use-shader-fx/src/fxs/simulations/useFluid/materials/usePressureMaterial.ts rename to packages/use-shader-fx/legacy/fxs/simulations/useFluid/materials/usePressureMaterial.ts diff --git a/packages/use-shader-fx/src/fxs/simulations/useFluid/materials/useSplatMaterial.ts b/packages/use-shader-fx/legacy/fxs/simulations/useFluid/materials/useSplatMaterial.ts similarity index 100% rename from packages/use-shader-fx/src/fxs/simulations/useFluid/materials/useSplatMaterial.ts rename to packages/use-shader-fx/legacy/fxs/simulations/useFluid/materials/useSplatMaterial.ts diff --git a/packages/use-shader-fx/src/fxs/simulations/useFluid/materials/useVorticityMaterial.ts b/packages/use-shader-fx/legacy/fxs/simulations/useFluid/materials/useVorticityMaterial.ts similarity index 100% rename from packages/use-shader-fx/src/fxs/simulations/useFluid/materials/useVorticityMaterial.ts rename to packages/use-shader-fx/legacy/fxs/simulations/useFluid/materials/useVorticityMaterial.ts diff --git a/packages/use-shader-fx/src/fxs/simulations/useFluid/shaders/advection.frag b/packages/use-shader-fx/legacy/fxs/simulations/useFluid/shaders/advection.frag similarity index 100% rename from packages/use-shader-fx/src/fxs/simulations/useFluid/shaders/advection.frag rename to packages/use-shader-fx/legacy/fxs/simulations/useFluid/shaders/advection.frag diff --git a/packages/use-shader-fx/src/fxs/simulations/useFluid/shaders/clear.frag b/packages/use-shader-fx/legacy/fxs/simulations/useFluid/shaders/clear.frag similarity index 100% rename from packages/use-shader-fx/src/fxs/simulations/useFluid/shaders/clear.frag rename to packages/use-shader-fx/legacy/fxs/simulations/useFluid/shaders/clear.frag diff --git a/packages/use-shader-fx/src/fxs/simulations/useFluid/shaders/curl.frag b/packages/use-shader-fx/legacy/fxs/simulations/useFluid/shaders/curl.frag similarity index 100% rename from packages/use-shader-fx/src/fxs/simulations/useFluid/shaders/curl.frag rename to packages/use-shader-fx/legacy/fxs/simulations/useFluid/shaders/curl.frag diff --git a/packages/use-shader-fx/src/fxs/simulations/useFluid/shaders/divergence.frag b/packages/use-shader-fx/legacy/fxs/simulations/useFluid/shaders/divergence.frag similarity index 100% rename from packages/use-shader-fx/src/fxs/simulations/useFluid/shaders/divergence.frag rename to packages/use-shader-fx/legacy/fxs/simulations/useFluid/shaders/divergence.frag diff --git a/packages/use-shader-fx/src/fxs/simulations/useFluid/shaders/gradientSubtract.frag b/packages/use-shader-fx/legacy/fxs/simulations/useFluid/shaders/gradientSubtract.frag similarity index 100% rename from packages/use-shader-fx/src/fxs/simulations/useFluid/shaders/gradientSubtract.frag rename to packages/use-shader-fx/legacy/fxs/simulations/useFluid/shaders/gradientSubtract.frag diff --git a/packages/use-shader-fx/src/fxs/simulations/useFluid/shaders/init.frag b/packages/use-shader-fx/legacy/fxs/simulations/useFluid/shaders/init.frag similarity index 100% rename from packages/use-shader-fx/src/fxs/simulations/useFluid/shaders/init.frag rename to packages/use-shader-fx/legacy/fxs/simulations/useFluid/shaders/init.frag diff --git a/packages/use-shader-fx/src/fxs/simulations/useFluid/shaders/main.vert b/packages/use-shader-fx/legacy/fxs/simulations/useFluid/shaders/main.vert similarity index 100% rename from packages/use-shader-fx/src/fxs/simulations/useFluid/shaders/main.vert rename to packages/use-shader-fx/legacy/fxs/simulations/useFluid/shaders/main.vert diff --git a/packages/use-shader-fx/src/fxs/simulations/useFluid/shaders/pressure.frag b/packages/use-shader-fx/legacy/fxs/simulations/useFluid/shaders/pressure.frag similarity index 100% rename from packages/use-shader-fx/src/fxs/simulations/useFluid/shaders/pressure.frag rename to packages/use-shader-fx/legacy/fxs/simulations/useFluid/shaders/pressure.frag diff --git a/packages/use-shader-fx/src/fxs/simulations/useFluid/shaders/splat.frag b/packages/use-shader-fx/legacy/fxs/simulations/useFluid/shaders/splat.frag similarity index 100% rename from packages/use-shader-fx/src/fxs/simulations/useFluid/shaders/splat.frag rename to packages/use-shader-fx/legacy/fxs/simulations/useFluid/shaders/splat.frag diff --git a/packages/use-shader-fx/src/fxs/simulations/useFluid/shaders/vorticity.frag b/packages/use-shader-fx/legacy/fxs/simulations/useFluid/shaders/vorticity.frag similarity index 100% rename from packages/use-shader-fx/src/fxs/simulations/useFluid/shaders/vorticity.frag rename to packages/use-shader-fx/legacy/fxs/simulations/useFluid/shaders/vorticity.frag diff --git a/packages/use-shader-fx/src/fxs/simulations/useFluid/useMesh.ts b/packages/use-shader-fx/legacy/fxs/simulations/useFluid/useMesh.ts similarity index 100% rename from packages/use-shader-fx/src/fxs/simulations/useFluid/useMesh.ts rename to packages/use-shader-fx/legacy/fxs/simulations/useFluid/useMesh.ts diff --git a/packages/use-shader-fx/src/fxs/simulations/useRipple/index.ts b/packages/use-shader-fx/legacy/fxs/simulations/useRipple/index.ts similarity index 100% rename from packages/use-shader-fx/src/fxs/simulations/useRipple/index.ts rename to packages/use-shader-fx/legacy/fxs/simulations/useRipple/index.ts diff --git a/packages/use-shader-fx/src/fxs/simulations/useRipple/shader/main.frag b/packages/use-shader-fx/legacy/fxs/simulations/useRipple/shader/main.frag similarity index 100% rename from packages/use-shader-fx/src/fxs/simulations/useRipple/shader/main.frag rename to packages/use-shader-fx/legacy/fxs/simulations/useRipple/shader/main.frag diff --git a/packages/use-shader-fx/src/fxs/simulations/useRipple/shader/main.vert b/packages/use-shader-fx/legacy/fxs/simulations/useRipple/shader/main.vert similarity index 100% rename from packages/use-shader-fx/src/fxs/simulations/useRipple/shader/main.vert rename to packages/use-shader-fx/legacy/fxs/simulations/useRipple/shader/main.vert diff --git a/packages/use-shader-fx/src/fxs/simulations/useRipple/useMesh.ts b/packages/use-shader-fx/legacy/fxs/simulations/useRipple/useMesh.ts similarity index 100% rename from packages/use-shader-fx/src/fxs/simulations/useRipple/useMesh.ts rename to packages/use-shader-fx/legacy/fxs/simulations/useRipple/useMesh.ts diff --git a/packages/use-shader-fx/legacy/fxs/types/index.ts b/packages/use-shader-fx/legacy/fxs/types/index.ts new file mode 100644 index 00000000..381ec33b --- /dev/null +++ b/packages/use-shader-fx/legacy/fxs/types/index.ts @@ -0,0 +1,71 @@ +import * as THREE from "three"; +import { RootState } from "@react-three/fiber"; + +export type Size = { width: number; height: number }; + +export type Dpr = + | number + | { + /** you can set whether `dpr` affects `shader`. default : `false` */ + shader?: false | number; + /** you can set whether `dpr` affects `fbo`. default : `false` */ + fbo?: false | number; + }; + +export type OnBeforeInitParameters = { + uniforms: { [uniform: string]: THREE.IUniform }; + fragmentShader: string; + vertexShader: string; +}; + +export type MaterialProps = { + /** + * An optional callback that is executed immediately before the shader program is initialised. This function is called with the shader source code as a parameter. Useful for the modification of built-in materials. + * @param parameters {fragmentShader, vertexShader, uniforms} + */ + onBeforeInit?: (parameters: OnBeforeInitParameters) => void; +}; + +export interface HooksProps extends MaterialProps { + /** Width,Height in pixels, or `size` from r3f */ + size: Size; + /** Pixel-ratio, use `window.devicePixelRatio` or viewport.dpr from r3f */ + dpr: Dpr; + /** Whether to `setSize` the FBO when updating size or dpr. default : `false` */ + isSizeUpdate?: boolean; + /** + * @type `THREE.RenderTargetOptions` + * @param depthBuffer Unlike the default in three.js, the default is `false`. + */ + renderTargetOptions?: THREE.RenderTargetOptions; +} + +/** + * @returns {HooksReturn} + * updateFx - Functions to update parameters and render. + * updateParams - Function to update parameters only. + * fxObject - An object containing various FX components such as scene, camera, material, and render target. + * + * @template T The type for the parameters of the hooks. + * @template O The type for the FX object. + * @template C The type for the custom parameters. + */ +export type HooksReturn = [ + /** + * Functions to update parameters and render. + * @param rootState RootState + * @param newParams params of fxHooks + * @param customParams custom params, added to `uniforms` during initialisation + */ + (rootState: RootState, newParams?: T, customParams?: C) => THREE.Texture, + /** + * Function to update parameters only. + * @param newParams params of fxHooks + * @param customParams custom params, added to `uniforms` during initialisation + */ + (newParams?: T, customParams?: C) => void, + /** + * Contains each part of FX such as scene, camera, material, render target, etc. + */ + O +]; diff --git a/packages/use-shader-fx/src/fxs/utils/useAlphaBlending/index.ts b/packages/use-shader-fx/legacy/fxs/utils/useAlphaBlending/index.ts similarity index 100% rename from packages/use-shader-fx/src/fxs/utils/useAlphaBlending/index.ts rename to packages/use-shader-fx/legacy/fxs/utils/useAlphaBlending/index.ts diff --git a/packages/use-shader-fx/src/fxs/utils/useAlphaBlending/shader/main.frag b/packages/use-shader-fx/legacy/fxs/utils/useAlphaBlending/shader/main.frag similarity index 100% rename from packages/use-shader-fx/src/fxs/utils/useAlphaBlending/shader/main.frag rename to packages/use-shader-fx/legacy/fxs/utils/useAlphaBlending/shader/main.frag diff --git a/packages/use-shader-fx/src/fxs/utils/useAlphaBlending/shader/main.vert b/packages/use-shader-fx/legacy/fxs/utils/useAlphaBlending/shader/main.vert similarity index 100% rename from packages/use-shader-fx/src/fxs/utils/useAlphaBlending/shader/main.vert rename to packages/use-shader-fx/legacy/fxs/utils/useAlphaBlending/shader/main.vert diff --git a/packages/use-shader-fx/src/fxs/utils/useAlphaBlending/useMesh.ts b/packages/use-shader-fx/legacy/fxs/utils/useAlphaBlending/useMesh.ts similarity index 100% rename from packages/use-shader-fx/src/fxs/utils/useAlphaBlending/useMesh.ts rename to packages/use-shader-fx/legacy/fxs/utils/useAlphaBlending/useMesh.ts diff --git a/packages/use-shader-fx/src/fxs/utils/useBlending/index.ts b/packages/use-shader-fx/legacy/fxs/utils/useBlending/index.ts similarity index 100% rename from packages/use-shader-fx/src/fxs/utils/useBlending/index.ts rename to packages/use-shader-fx/legacy/fxs/utils/useBlending/index.ts diff --git a/packages/use-shader-fx/src/fxs/utils/useBlending/shader/main.frag b/packages/use-shader-fx/legacy/fxs/utils/useBlending/shader/main.frag similarity index 100% rename from packages/use-shader-fx/src/fxs/utils/useBlending/shader/main.frag rename to packages/use-shader-fx/legacy/fxs/utils/useBlending/shader/main.frag diff --git a/packages/use-shader-fx/src/fxs/utils/useBlending/shader/main.vert b/packages/use-shader-fx/legacy/fxs/utils/useBlending/shader/main.vert similarity index 100% rename from packages/use-shader-fx/src/fxs/utils/useBlending/shader/main.vert rename to packages/use-shader-fx/legacy/fxs/utils/useBlending/shader/main.vert diff --git a/packages/use-shader-fx/src/fxs/utils/useBlending/useMesh.ts b/packages/use-shader-fx/legacy/fxs/utils/useBlending/useMesh.ts similarity index 100% rename from packages/use-shader-fx/src/fxs/utils/useBlending/useMesh.ts rename to packages/use-shader-fx/legacy/fxs/utils/useBlending/useMesh.ts diff --git a/packages/use-shader-fx/src/fxs/utils/useBrightnessPicker/index.ts b/packages/use-shader-fx/legacy/fxs/utils/useBrightnessPicker/index.ts similarity index 100% rename from packages/use-shader-fx/src/fxs/utils/useBrightnessPicker/index.ts rename to packages/use-shader-fx/legacy/fxs/utils/useBrightnessPicker/index.ts diff --git a/packages/use-shader-fx/src/fxs/utils/useBrightnessPicker/shader/main.frag b/packages/use-shader-fx/legacy/fxs/utils/useBrightnessPicker/shader/main.frag similarity index 100% rename from packages/use-shader-fx/src/fxs/utils/useBrightnessPicker/shader/main.frag rename to packages/use-shader-fx/legacy/fxs/utils/useBrightnessPicker/shader/main.frag diff --git a/packages/use-shader-fx/src/fxs/utils/useBrightnessPicker/shader/main.vert b/packages/use-shader-fx/legacy/fxs/utils/useBrightnessPicker/shader/main.vert similarity index 100% rename from packages/use-shader-fx/src/fxs/utils/useBrightnessPicker/shader/main.vert rename to packages/use-shader-fx/legacy/fxs/utils/useBrightnessPicker/shader/main.vert diff --git a/packages/use-shader-fx/src/fxs/utils/useBrightnessPicker/useMesh.ts b/packages/use-shader-fx/legacy/fxs/utils/useBrightnessPicker/useMesh.ts similarity index 100% rename from packages/use-shader-fx/src/fxs/utils/useBrightnessPicker/useMesh.ts rename to packages/use-shader-fx/legacy/fxs/utils/useBrightnessPicker/useMesh.ts diff --git a/packages/use-shader-fx/src/fxs/utils/useCoverTexture/index.ts b/packages/use-shader-fx/legacy/fxs/utils/useCoverTexture/index.ts similarity index 100% rename from packages/use-shader-fx/src/fxs/utils/useCoverTexture/index.ts rename to packages/use-shader-fx/legacy/fxs/utils/useCoverTexture/index.ts diff --git a/packages/use-shader-fx/src/fxs/utils/useCoverTexture/shader/main.frag b/packages/use-shader-fx/legacy/fxs/utils/useCoverTexture/shader/main.frag similarity index 100% rename from packages/use-shader-fx/src/fxs/utils/useCoverTexture/shader/main.frag rename to packages/use-shader-fx/legacy/fxs/utils/useCoverTexture/shader/main.frag diff --git a/packages/use-shader-fx/src/fxs/utils/useCoverTexture/shader/main.vert b/packages/use-shader-fx/legacy/fxs/utils/useCoverTexture/shader/main.vert similarity index 100% rename from packages/use-shader-fx/src/fxs/utils/useCoverTexture/shader/main.vert rename to packages/use-shader-fx/legacy/fxs/utils/useCoverTexture/shader/main.vert diff --git a/packages/use-shader-fx/src/fxs/utils/useCoverTexture/useMesh.ts b/packages/use-shader-fx/legacy/fxs/utils/useCoverTexture/useMesh.ts similarity index 100% rename from packages/use-shader-fx/src/fxs/utils/useCoverTexture/useMesh.ts rename to packages/use-shader-fx/legacy/fxs/utils/useCoverTexture/useMesh.ts diff --git a/packages/use-shader-fx/src/fxs/utils/useDuoTone/index.ts b/packages/use-shader-fx/legacy/fxs/utils/useDuoTone/index.ts similarity index 100% rename from packages/use-shader-fx/src/fxs/utils/useDuoTone/index.ts rename to packages/use-shader-fx/legacy/fxs/utils/useDuoTone/index.ts diff --git a/packages/use-shader-fx/src/fxs/utils/useDuoTone/shader/main.frag b/packages/use-shader-fx/legacy/fxs/utils/useDuoTone/shader/main.frag similarity index 100% rename from packages/use-shader-fx/src/fxs/utils/useDuoTone/shader/main.frag rename to packages/use-shader-fx/legacy/fxs/utils/useDuoTone/shader/main.frag diff --git a/packages/use-shader-fx/src/fxs/utils/useDuoTone/shader/main.vert b/packages/use-shader-fx/legacy/fxs/utils/useDuoTone/shader/main.vert similarity index 100% rename from packages/use-shader-fx/src/fxs/utils/useDuoTone/shader/main.vert rename to packages/use-shader-fx/legacy/fxs/utils/useDuoTone/shader/main.vert diff --git a/packages/use-shader-fx/src/fxs/utils/useDuoTone/useMesh.ts b/packages/use-shader-fx/legacy/fxs/utils/useDuoTone/useMesh.ts similarity index 100% rename from packages/use-shader-fx/src/fxs/utils/useDuoTone/useMesh.ts rename to packages/use-shader-fx/legacy/fxs/utils/useDuoTone/useMesh.ts diff --git a/packages/use-shader-fx/src/fxs/utils/useFxBlending/index.ts b/packages/use-shader-fx/legacy/fxs/utils/useFxBlending/index.ts similarity index 100% rename from packages/use-shader-fx/src/fxs/utils/useFxBlending/index.ts rename to packages/use-shader-fx/legacy/fxs/utils/useFxBlending/index.ts diff --git a/packages/use-shader-fx/src/fxs/utils/useFxBlending/shader/main.frag b/packages/use-shader-fx/legacy/fxs/utils/useFxBlending/shader/main.frag similarity index 100% rename from packages/use-shader-fx/src/fxs/utils/useFxBlending/shader/main.frag rename to packages/use-shader-fx/legacy/fxs/utils/useFxBlending/shader/main.frag diff --git a/packages/use-shader-fx/src/fxs/utils/useFxBlending/shader/main.vert b/packages/use-shader-fx/legacy/fxs/utils/useFxBlending/shader/main.vert similarity index 100% rename from packages/use-shader-fx/src/fxs/utils/useFxBlending/shader/main.vert rename to packages/use-shader-fx/legacy/fxs/utils/useFxBlending/shader/main.vert diff --git a/packages/use-shader-fx/src/fxs/utils/useFxBlending/useMesh.ts b/packages/use-shader-fx/legacy/fxs/utils/useFxBlending/useMesh.ts similarity index 100% rename from packages/use-shader-fx/src/fxs/utils/useFxBlending/useMesh.ts rename to packages/use-shader-fx/legacy/fxs/utils/useFxBlending/useMesh.ts diff --git a/packages/use-shader-fx/src/fxs/utils/useFxTexture/index.ts b/packages/use-shader-fx/legacy/fxs/utils/useFxTexture/index.ts similarity index 100% rename from packages/use-shader-fx/src/fxs/utils/useFxTexture/index.ts rename to packages/use-shader-fx/legacy/fxs/utils/useFxTexture/index.ts diff --git a/packages/use-shader-fx/src/fxs/utils/useFxTexture/shader/main.frag b/packages/use-shader-fx/legacy/fxs/utils/useFxTexture/shader/main.frag similarity index 100% rename from packages/use-shader-fx/src/fxs/utils/useFxTexture/shader/main.frag rename to packages/use-shader-fx/legacy/fxs/utils/useFxTexture/shader/main.frag diff --git a/packages/use-shader-fx/src/fxs/utils/useFxTexture/shader/main.vert b/packages/use-shader-fx/legacy/fxs/utils/useFxTexture/shader/main.vert similarity index 100% rename from packages/use-shader-fx/src/fxs/utils/useFxTexture/shader/main.vert rename to packages/use-shader-fx/legacy/fxs/utils/useFxTexture/shader/main.vert diff --git a/packages/use-shader-fx/src/fxs/utils/useFxTexture/useMesh.ts b/packages/use-shader-fx/legacy/fxs/utils/useFxTexture/useMesh.ts similarity index 100% rename from packages/use-shader-fx/src/fxs/utils/useFxTexture/useMesh.ts rename to packages/use-shader-fx/legacy/fxs/utils/useFxTexture/useMesh.ts diff --git a/packages/use-shader-fx/src/fxs/utils/useHSV/index.ts b/packages/use-shader-fx/legacy/fxs/utils/useHSV/index.ts similarity index 100% rename from packages/use-shader-fx/src/fxs/utils/useHSV/index.ts rename to packages/use-shader-fx/legacy/fxs/utils/useHSV/index.ts diff --git a/packages/use-shader-fx/src/fxs/utils/useHSV/shader/main.frag b/packages/use-shader-fx/legacy/fxs/utils/useHSV/shader/main.frag similarity index 100% rename from packages/use-shader-fx/src/fxs/utils/useHSV/shader/main.frag rename to packages/use-shader-fx/legacy/fxs/utils/useHSV/shader/main.frag diff --git a/packages/use-shader-fx/src/fxs/utils/useHSV/shader/main.vert b/packages/use-shader-fx/legacy/fxs/utils/useHSV/shader/main.vert similarity index 100% rename from packages/use-shader-fx/src/fxs/utils/useHSV/shader/main.vert rename to packages/use-shader-fx/legacy/fxs/utils/useHSV/shader/main.vert diff --git a/packages/use-shader-fx/src/fxs/utils/useHSV/useMesh.ts b/packages/use-shader-fx/legacy/fxs/utils/useHSV/useMesh.ts similarity index 100% rename from packages/use-shader-fx/src/fxs/utils/useHSV/useMesh.ts rename to packages/use-shader-fx/legacy/fxs/utils/useHSV/useMesh.ts diff --git a/packages/use-shader-fx/types/index.d.ts b/packages/use-shader-fx/legacy/index.js similarity index 69% rename from packages/use-shader-fx/types/index.d.ts rename to packages/use-shader-fx/legacy/index.js index 1b96d681..be08983b 100644 --- a/packages/use-shader-fx/types/index.d.ts +++ b/packages/use-shader-fx/legacy/index.js @@ -1,10 +1,20 @@ +/*=============================================== +FXs +===============================================*/ +// interactions export * from "./fxs/interactions/useBrush"; + +// simulations export * from "./fxs/simulations/useFluid"; export * from "./fxs/simulations/useRipple"; + +// noises export * from "./fxs/noises/useNoise"; export * from "./fxs/noises/useColorStrata"; export * from "./fxs/noises/useMarble"; export * from "./fxs/noises/useCosPalette"; + +// utils export * from "./fxs/utils/useDuoTone"; export * from "./fxs/utils/useBlending"; export * from "./fxs/utils/useFxTexture"; @@ -13,16 +23,28 @@ export * from "./fxs/utils/useFxBlending"; export * from "./fxs/utils/useAlphaBlending"; export * from "./fxs/utils/useHSV"; export * from "./fxs/utils/useCoverTexture"; + +// effects export * from "./fxs/effects/useSimpleBlur"; export * from "./fxs/effects/useMotionBlur"; export * from "./fxs/effects/useWave"; + +// misc export * from "./fxs/misc/useChromaKey"; + +// blank export * from "./fxs/blank/useBlank"; export * from "./fxs/blank/useRawBlank"; + +// 3D export * from "./fxs/3D/useMorphParticles"; export * from "./fxs/3D/useMorphParticles/useCreateMorphParticles"; export * from "./fxs/3D/useWobble3D"; export * from "./fxs/3D/useWobble3D/useCreateWobble3D"; + +/*=============================================== +utils +===============================================*/ export * from "./utils/setUniforms"; export * from "./utils/useAddMesh"; export * from "./utils/useCamera"; @@ -31,11 +53,27 @@ export * from "./utils/useParams"; export * from "./utils/useResolution"; export * from "./utils/useSingleFBO"; export * from "./utils/useResizeBoundary"; + +/*=============================================== +misc +===============================================*/ export * from "./misc/usePointer"; export * from "./misc/useBeat"; export * from "./misc/useFPSLimiter"; export * from "./misc/useDomSyncer"; export * from "./misc/useCopyTexture"; + +/*=============================================== +Easing +===============================================*/ export * from "./libs/Easings"; + +/*=============================================== +Utils +===============================================*/ export * from "./libs/Utils"; + +/*=============================================== +ShaderChunk +===============================================*/ export * from "./libs/shaders/ShaderChunk"; diff --git a/packages/use-shader-fx/legacy/libs/Easings.ts b/packages/use-shader-fx/legacy/libs/Easings.ts new file mode 100644 index 00000000..86bf755b --- /dev/null +++ b/packages/use-shader-fx/legacy/libs/Easings.ts @@ -0,0 +1,184 @@ +export type EasingTypes = + | "easeInSine" + | "easeOutSine" + | "easeInOutSine" + | "easeInQuad" + | "easeOutQuad" + | "easeInOutQuad" + | "easeInCubic" + | "easeOutCubic" + | "easeInOutCubic" + | "easeInQuart" + | "easeOutQuart" + | "easeInOutQuart" + | "easeInQuint" + | "easeOutQuint" + | "easeInOutQuint" + | "easeInExpo" + | "easeOutExpo" + | "easeInOutExpo" + | "easeInCirc" + | "easeOutCirc" + | "easeInOutCirc" + | "easeInBack" + | "easeOutBack" + | "easeInOutBack" + | "easeInElastic" + | "easeOutElastic" + | "easeInOutElastic" + | "easeInBounce" + | "easeOutBounce" + | "easeInOutBounce"; + +type EasingFunctions = { + [K in EasingTypes]: (x: number) => number; +}; + +/** + * from https://github.com/ai/easings.net + */ +export const Easing: EasingFunctions = Object.freeze({ + easeInSine(x: number): number { + return 1 - Math.cos((x * Math.PI) / 2); + }, + easeOutSine(x: number): number { + return Math.sin((x * Math.PI) / 2); + }, + easeInOutSine(x: number): number { + return -(Math.cos(Math.PI * x) - 1) / 2; + }, + easeInQuad(x: number): number { + return x * x; + }, + easeOutQuad(x: number): number { + return 1 - (1 - x) * (1 - x); + }, + easeInOutQuad(x: number): number { + return x < 0.5 ? 2 * x * x : 1 - Math.pow(-2 * x + 2, 2) / 2; + }, + easeInCubic(x: number): number { + return x * x * x; + }, + easeOutCubic(x: number): number { + return 1 - Math.pow(1 - x, 3); + }, + easeInOutCubic(x: number): number { + return x < 0.5 ? 4 * x * x * x : 1 - Math.pow(-2 * x + 2, 3) / 2; + }, + easeInQuart(x: number): number { + return x * x * x * x; + }, + easeOutQuart(x: number): number { + return 1 - Math.pow(1 - x, 4); + }, + easeInOutQuart(x: number): number { + return x < 0.5 ? 8 * x * x * x * x : 1 - Math.pow(-2 * x + 2, 4) / 2; + }, + easeInQuint(x: number): number { + return x * x * x * x * x; + }, + easeOutQuint(x: number): number { + return 1 - Math.pow(1 - x, 5); + }, + easeInOutQuint(x: number): number { + return x < 0.5 ? 16 * x * x * x * x * x : 1 - Math.pow(-2 * x + 2, 5) / 2; + }, + easeInExpo(x: number): number { + return x === 0 ? 0 : Math.pow(2, 10 * x - 10); + }, + easeOutExpo(x: number): number { + return x === 1 ? 1 : 1 - Math.pow(2, -10 * x); + }, + easeInOutExpo(x: number): number { + return x === 0 + ? 0 + : x === 1 + ? 1 + : x < 0.5 + ? Math.pow(2, 20 * x - 10) / 2 + : (2 - Math.pow(2, -20 * x + 10)) / 2; + }, + easeInCirc(x: number): number { + return 1 - Math.sqrt(1 - Math.pow(x, 2)); + }, + easeOutCirc(x: number): number { + return Math.sqrt(1 - Math.pow(x - 1, 2)); + }, + easeInOutCirc(x: number): number { + return x < 0.5 + ? (1 - Math.sqrt(1 - Math.pow(2 * x, 2))) / 2 + : (Math.sqrt(1 - Math.pow(-2 * x + 2, 2)) + 1) / 2; + }, + easeInBack(x: number): number { + const c1 = 1.70158; + const c3 = c1 + 1; + + return c3 * x * x * x - c1 * x * x; + }, + easeOutBack(x: number): number { + const c1 = 1.70158; + const c3 = c1 + 1; + + return 1 + c3 * Math.pow(x - 1, 3) + c1 * Math.pow(x - 1, 2); + }, + easeInOutBack(x: number): number { + const c1 = 1.70158; + const c2 = c1 * 1.525; + + return x < 0.5 + ? (Math.pow(2 * x, 2) * ((c2 + 1) * 2 * x - c2)) / 2 + : (Math.pow(2 * x - 2, 2) * ((c2 + 1) * (x * 2 - 2) + c2) + 2) / 2; + }, + easeInElastic(x: number): number { + const c4 = (2 * Math.PI) / 3; + + return x === 0 + ? 0 + : x === 1 + ? 1 + : -Math.pow(2, 10 * x - 10) * Math.sin((x * 10 - 10.75) * c4); + }, + easeOutElastic(x: number): number { + const c4 = (2 * Math.PI) / 3; + + return x === 0 + ? 0 + : x === 1 + ? 1 + : Math.pow(2, -10 * x) * Math.sin((x * 10 - 0.75) * c4) + 1; + }, + easeInOutElastic(x: number): number { + const c5 = (2 * Math.PI) / 4.5; + + return x === 0 + ? 0 + : x === 1 + ? 1 + : x < 0.5 + ? -(Math.pow(2, 20 * x - 10) * Math.sin((20 * x - 11.125) * c5)) / 2 + : (Math.pow(2, -20 * x + 10) * Math.sin((20 * x - 11.125) * c5)) / 2 + + 1; + }, + easeInBounce(x: number): number { + return 1 - Easing.easeOutBounce(1 - x); + }, + easeOutBounce(x: number): number { + const n1 = 7.5625; + const d1 = 2.75; + + if (x < 1 / d1) { + return n1 * x * x; + } else if (x < 2 / d1) { + return n1 * (x -= 1.5 / d1) * x + 0.75; + } else if (x < 2.5 / d1) { + return n1 * (x -= 2.25 / d1) * x + 0.9375; + } else { + return n1 * (x -= 2.625 / d1) * x + 0.984375; + } + }, + easeInOutBounce(x: number): number { + return x < 0.5 + ? (1 - Easing.easeOutBounce(1 - 2 * x)) / 2 + : (1 + Easing.easeOutBounce(2 * x - 1)) / 2; + }, +}); diff --git a/packages/use-shader-fx/src/libs/Utils.ts b/packages/use-shader-fx/legacy/libs/Utils.ts similarity index 100% rename from packages/use-shader-fx/src/libs/Utils.ts rename to packages/use-shader-fx/legacy/libs/Utils.ts diff --git a/packages/use-shader-fx/legacy/libs/constants.ts b/packages/use-shader-fx/legacy/libs/constants.ts new file mode 100644 index 00000000..ab338087 --- /dev/null +++ b/packages/use-shader-fx/legacy/libs/constants.ts @@ -0,0 +1,16 @@ +import * as THREE from "three"; + +export const ISDEV = process.env.NODE_ENV === "development"; + +export const MATERIAL_BASIC_PARAMS = { + transparent: false, + depthTest: false, + depthWrite: false, +}; + +export const DEFAULT_TEXTURE = new THREE.DataTexture( + new Uint8Array([0, 0, 0, 0]), + 1, + 1, + THREE.RGBAFormat +); diff --git a/packages/use-shader-fx/legacy/libs/shaders/ShaderChunk.ts b/packages/use-shader-fx/legacy/libs/shaders/ShaderChunk.ts new file mode 100644 index 00000000..910f4b07 --- /dev/null +++ b/packages/use-shader-fx/legacy/libs/shaders/ShaderChunk.ts @@ -0,0 +1,29 @@ +import wobble3D from "./shaderChunk/wobble3D.glsl"; +import snoise from "./shaderChunk/snoise.glsl"; +import coverTexture from "./shaderChunk/coverTexture.glsl"; +import fxBlending from "./shaderChunk/fxBlending.glsl"; +import planeVertex from "./shaderChunk/planeVertex.glsl"; +import defaultVertex from "./shaderChunk/defaultVertex.glsl"; +import hsv2rgb from "./shaderChunk/hsv2rgb.glsl"; +import rgb2hsv from "./shaderChunk/rgb2hsv.glsl"; + +export type ShaderChunkTypes = + | "wobble3D" + | "snoise" + | "coverTexture" + | "fxBlending" + | "planeVertex" + | "defaultVertex" + | "hsv2rgb" + | "rgb2hsv"; + +export const ShaderChunk: { [K in ShaderChunkTypes]: string } = Object.freeze({ + wobble3D, + snoise, + coverTexture, + fxBlending, + planeVertex, + defaultVertex, + hsv2rgb, + rgb2hsv, +}); diff --git a/packages/use-shader-fx/src/libs/shaders/resolveShaders.ts b/packages/use-shader-fx/legacy/libs/shaders/resolveShaders.ts similarity index 100% rename from packages/use-shader-fx/src/libs/shaders/resolveShaders.ts rename to packages/use-shader-fx/legacy/libs/shaders/resolveShaders.ts diff --git a/packages/use-shader-fx/legacy/libs/shaders/shaderChunk/coverTexture.glsl b/packages/use-shader-fx/legacy/libs/shaders/shaderChunk/coverTexture.glsl new file mode 100644 index 00000000..765bfc93 --- /dev/null +++ b/packages/use-shader-fx/legacy/libs/shaders/shaderChunk/coverTexture.glsl @@ -0,0 +1,7 @@ +float screenAspect = uResolution.x / uResolution.y; +float textureAspect = uTextureResolution.x / uTextureResolution.y; +vec2 aspectRatio = vec2( + min(screenAspect / textureAspect, 1.0), + min(textureAspect / screenAspect, 1.0) +); +vec2 uv = vUv * aspectRatio + (1.0 - aspectRatio) * .5; \ No newline at end of file diff --git a/packages/use-shader-fx/legacy/libs/shaders/shaderChunk/defaultVertex.glsl b/packages/use-shader-fx/legacy/libs/shaders/shaderChunk/defaultVertex.glsl new file mode 100644 index 00000000..fb20d32c --- /dev/null +++ b/packages/use-shader-fx/legacy/libs/shaders/shaderChunk/defaultVertex.glsl @@ -0,0 +1,6 @@ +varying vec2 vUv; + +void main() { + vUv = uv; + gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0); +} \ No newline at end of file diff --git a/packages/use-shader-fx/legacy/libs/shaders/shaderChunk/fxBlending.glsl b/packages/use-shader-fx/legacy/libs/shaders/shaderChunk/fxBlending.glsl new file mode 100644 index 00000000..b7d0916a --- /dev/null +++ b/packages/use-shader-fx/legacy/libs/shaders/shaderChunk/fxBlending.glsl @@ -0,0 +1,6 @@ +vec3 mapColor = texture2D(uMap, uv).rgb; +vec3 normalizedMap = mapColor * 2.0 - 1.0; + +uv = uv * 2.0 - 1.0; +uv *= mix(vec2(1.0), abs(normalizedMap.rg), uMapIntensity); +uv = (uv + 1.0) / 2.0; \ No newline at end of file diff --git a/packages/use-shader-fx/legacy/libs/shaders/shaderChunk/hsv2rgb.glsl b/packages/use-shader-fx/legacy/libs/shaders/shaderChunk/hsv2rgb.glsl new file mode 100644 index 00000000..89f859a6 --- /dev/null +++ b/packages/use-shader-fx/legacy/libs/shaders/shaderChunk/hsv2rgb.glsl @@ -0,0 +1,6 @@ +vec3 hsv2rgb(vec3 c) +{ + vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0); + vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www); + return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y); +} \ No newline at end of file diff --git a/packages/use-shader-fx/legacy/libs/shaders/shaderChunk/planeVertex.glsl b/packages/use-shader-fx/legacy/libs/shaders/shaderChunk/planeVertex.glsl new file mode 100644 index 00000000..304094df --- /dev/null +++ b/packages/use-shader-fx/legacy/libs/shaders/shaderChunk/planeVertex.glsl @@ -0,0 +1,8 @@ +precision highp float; + +varying vec2 vUv; + +void main() { + vUv = uv; + gl_Position = vec4(position, 1.0); +} \ No newline at end of file diff --git a/packages/use-shader-fx/legacy/libs/shaders/shaderChunk/rgb2hsv.glsl b/packages/use-shader-fx/legacy/libs/shaders/shaderChunk/rgb2hsv.glsl new file mode 100644 index 00000000..deb954f4 --- /dev/null +++ b/packages/use-shader-fx/legacy/libs/shaders/shaderChunk/rgb2hsv.glsl @@ -0,0 +1,10 @@ +vec3 rgb2hsv(vec3 c) +{ + vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0); + vec4 p = mix(vec4(c.bg, K.wz), vec4(c.gb, K.xy), step(c.b, c.g)); + vec4 q = mix(vec4(p.xyw, c.r), vec4(c.r, p.yzx), step(p.x, c.r)); + + float d = q.x - min(q.w, q.y); + float e = 1.0e-10; + return vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x); +} \ No newline at end of file diff --git a/packages/use-shader-fx/legacy/libs/shaders/shaderChunk/snoise.glsl b/packages/use-shader-fx/legacy/libs/shaders/shaderChunk/snoise.glsl new file mode 100644 index 00000000..4c34f6e3 --- /dev/null +++ b/packages/use-shader-fx/legacy/libs/shaders/shaderChunk/snoise.glsl @@ -0,0 +1,58 @@ +// +// by Nikita Miropolskiy + +/* discontinuous pseudorandom uniformly distributed in [-0.5, +0.5]^3 */ +vec3 random3(vec3 c) { + float j = 4096.0*sin(dot(c,vec3(17.0, 59.4, 15.0))); + vec3 r; + r.z = fract(512.0*j); + j *= .125; + r.x = fract(512.0*j); + j *= .125; + r.y = fract(512.0*j); + return r-0.5; +} + +const float F3 = 0.3333333; +const float G3 = 0.1666667; + +float snoise(vec3 p) { + + vec3 s = floor(p + dot(p, vec3(F3))); + vec3 x = p - s + dot(s, vec3(G3)); + + vec3 e = step(vec3(0.0), x - x.yzx); + vec3 i1 = e*(1.0 - e.zxy); + vec3 i2 = 1.0 - e.zxy*(1.0 - e); + + vec3 x1 = x - i1 + G3; + vec3 x2 = x - i2 + 2.0*G3; + vec3 x3 = x - 1.0 + 3.0*G3; + + vec4 w, d; + + w.x = dot(x, x); + w.y = dot(x1, x1); + w.z = dot(x2, x2); + w.w = dot(x3, x3); + + w = max(0.6 - w, 0.0); + + d.x = dot(random3(s), x); + d.y = dot(random3(s + i1), x1); + d.z = dot(random3(s + i2), x2); + d.w = dot(random3(s + 1.0), x3); + + w *= w; + w *= w; + d *= w; + + return dot(d, vec4(52.0)); +} + +float snoiseFractal(vec3 m) { + return 0.5333333* snoise(m) + +0.2666667* snoise(2.0*m) + +0.1333333* snoise(4.0*m) + +0.0666667* snoise(8.0*m); +} \ No newline at end of file diff --git a/packages/use-shader-fx/legacy/libs/shaders/shaderChunk/wobble3D.glsl b/packages/use-shader-fx/legacy/libs/shaders/shaderChunk/wobble3D.glsl new file mode 100644 index 00000000..31df8df9 --- /dev/null +++ b/packages/use-shader-fx/legacy/libs/shaders/shaderChunk/wobble3D.glsl @@ -0,0 +1,111 @@ +// Simplex 4D Noise +// by Ian McEwan, Ashima Arts +// +vec4 permute(vec4 x){return mod(((x*34.0)+1.0)*x, 289.0);} +float permute(float x){return floor(mod(((x*34.0)+1.0)*x, 289.0));} +vec4 taylorInvSqrt(vec4 r){return 1.79284291400159 - 0.85373472095314 * r;} +float taylorInvSqrt(float r){return 1.79284291400159 - 0.85373472095314 * r;} + +vec4 grad4(float j, vec4 ip) +{ + const vec4 ones = vec4(1.0, 1.0, 1.0, -1.0); + vec4 p,s; + + p.xyz = floor( fract (vec3(j) * ip.xyz) * 7.0) * ip.z - 1.0; + p.w = 1.5 - dot(abs(p.xyz), ones.xyz); + s = vec4(lessThan(p, vec4(0.0))); + p.xyz = p.xyz + (s.xyz*2.0 - 1.0) * s.www; + + return p; +} + +float simplexNoise4d(vec4 v) +{ + const vec2 C = vec2( 0.138196601125010504, // (5 - sqrt(5))/20 G4 + 0.309016994374947451); // (sqrt(5) - 1)/4 F4 + // First corner + vec4 i = floor(v + dot(v, C.yyyy) ); + vec4 x0 = v - i + dot(i, C.xxxx); + + // Other corners + + // Rank sorting originally contributed by Bill Licea-Kane, AMD (formerly ATI) + vec4 i0; + + vec3 isX = step( x0.yzw, x0.xxx ); + vec3 isYZ = step( x0.zww, x0.yyz ); + // i0.x = dot( isX, vec3( 1.0 ) ); + i0.x = isX.x + isX.y + isX.z; + i0.yzw = 1.0 - isX; + + // i0.y += dot( isYZ.xy, vec2( 1.0 ) ); + i0.y += isYZ.x + isYZ.y; + i0.zw += 1.0 - isYZ.xy; + + i0.z += isYZ.z; + i0.w += 1.0 - isYZ.z; + + // i0 now contains the unique values 0,1,2,3 in each channel + vec4 i3 = clamp( i0, 0.0, 1.0 ); + vec4 i2 = clamp( i0-1.0, 0.0, 1.0 ); + vec4 i1 = clamp( i0-2.0, 0.0, 1.0 ); + + // x0 = x0 - 0.0 + 0.0 * C + vec4 x1 = x0 - i1 + 1.0 * C.xxxx; + vec4 x2 = x0 - i2 + 2.0 * C.xxxx; + vec4 x3 = x0 - i3 + 3.0 * C.xxxx; + vec4 x4 = x0 - 1.0 + 4.0 * C.xxxx; + + // Permutations + i = mod(i, 289.0); + float j0 = permute( permute( permute( permute(i.w) + i.z) + i.y) + i.x); + vec4 j1 = permute( permute( permute( permute ( + i.w + vec4(i1.w, i2.w, i3.w, 1.0 )) + + i.z + vec4(i1.z, i2.z, i3.z, 1.0 )) + + i.y + vec4(i1.y, i2.y, i3.y, 1.0 )) + + i.x + vec4(i1.x, i2.x, i3.x, 1.0 )); + // Gradients + // ( 7*7*6 points uniformly over a cube, mapped onto a 4-octahedron.) + // 7*7*6 = 294, which is close to the ring size 17*17 = 289. + + vec4 ip = vec4(1.0/294.0, 1.0/49.0, 1.0/7.0, 0.0) ; + + vec4 p0 = grad4(j0, ip); + vec4 p1 = grad4(j1.x, ip); + vec4 p2 = grad4(j1.y, ip); + vec4 p3 = grad4(j1.z, ip); + vec4 p4 = grad4(j1.w, ip); + + // Normalise gradients + vec4 norm = taylorInvSqrt(vec4(dot(p0,p0), dot(p1,p1), dot(p2, p2), dot(p3,p3))); + p0 *= norm.x; + p1 *= norm.y; + p2 *= norm.z; + p3 *= norm.w; + p4 *= taylorInvSqrt(dot(p4,p4)); + + // Mix contributions from the five corners + vec3 m0 = max(0.6 - vec3(dot(x0,x0), dot(x1,x1), dot(x2,x2)), 0.0); + vec2 m1 = max(0.6 - vec2(dot(x3,x3), dot(x4,x4) ), 0.0); + m0 = m0 * m0; + m1 = m1 * m1; + return 49.0 * ( dot(m0*m0, vec3( dot( p0, x0 ), dot( p1, x1 ), dot( p2, x2 ))) + + dot(m1*m1, vec2( dot( p3, x3 ), dot( p4, x4 ) ) ) ) ; + +} + +float getWobble(vec3 position) +{ + vec3 warpedPosition = position; + warpedPosition += simplexNoise4d( + vec4( + position * uWarpPositionFrequency, + uTime * uWarpTimeFrequency + ) + ) * uWarpStrength; + + return simplexNoise4d(vec4( + warpedPosition * uWobblePositionFrequency, // XYZ + uTime * uWobbleTimeFrequency // W + )) * uWobbleStrength; +} \ No newline at end of file diff --git a/packages/use-shader-fx/legacy/misc/useBeat.ts b/packages/use-shader-fx/legacy/misc/useBeat.ts new file mode 100644 index 00000000..73c98953 --- /dev/null +++ b/packages/use-shader-fx/legacy/misc/useBeat.ts @@ -0,0 +1,42 @@ +import * as THREE from "three"; +import { Easing, EasingTypes } from "../libs/Easings"; +import { useCallback } from "react"; + +/** Returns a unique hash specific to the beat */ +function getHash(input: number) { + let n = Math.sin(input * 12.9898) * 43758.5453; + return n - Math.floor(n); +} + +type BeatValues = { + beat: number; + floor: number; + fract: number; + /** unique hash specific to the beat */ + hash: number; +}; + +/** + * @param ease easing functions are referenced from https://github.com/ai/easings.net , default : "easeOutQuart" + */ +export const useBeat = (bpm: number, ease: EasingTypes = "easeOutQuart") => { + const rhythm = bpm / 60; + const easing = Easing[ease]; + const updateBeat = useCallback( + (clock: THREE.Clock) => { + let beat = clock.getElapsedTime() * rhythm; + const floor = Math.floor(beat); + const fract = easing(beat - floor); + beat = fract + floor; + const hash = getHash(floor); + return { + beat, + floor, + fract, + hash, + } as BeatValues; + }, + [rhythm, easing] + ); + return updateBeat; +}; diff --git a/packages/use-shader-fx/src/misc/useCopyTexture.ts b/packages/use-shader-fx/legacy/misc/useCopyTexture.ts similarity index 100% rename from packages/use-shader-fx/src/misc/useCopyTexture.ts rename to packages/use-shader-fx/legacy/misc/useCopyTexture.ts diff --git a/packages/use-shader-fx/src/misc/useDomSyncer/index.ts b/packages/use-shader-fx/legacy/misc/useDomSyncer/index.ts similarity index 100% rename from packages/use-shader-fx/src/misc/useDomSyncer/index.ts rename to packages/use-shader-fx/legacy/misc/useDomSyncer/index.ts diff --git a/packages/use-shader-fx/src/misc/useDomSyncer/shader/main.frag b/packages/use-shader-fx/legacy/misc/useDomSyncer/shader/main.frag similarity index 100% rename from packages/use-shader-fx/src/misc/useDomSyncer/shader/main.frag rename to packages/use-shader-fx/legacy/misc/useDomSyncer/shader/main.frag diff --git a/packages/use-shader-fx/src/misc/useDomSyncer/shader/main.vert b/packages/use-shader-fx/legacy/misc/useDomSyncer/shader/main.vert similarity index 100% rename from packages/use-shader-fx/src/misc/useDomSyncer/shader/main.vert rename to packages/use-shader-fx/legacy/misc/useDomSyncer/shader/main.vert diff --git a/packages/use-shader-fx/src/misc/useDomSyncer/utils/createMesh.ts b/packages/use-shader-fx/legacy/misc/useDomSyncer/utils/createMesh.ts similarity index 100% rename from packages/use-shader-fx/src/misc/useDomSyncer/utils/createMesh.ts rename to packages/use-shader-fx/legacy/misc/useDomSyncer/utils/createMesh.ts diff --git a/packages/use-shader-fx/src/misc/useDomSyncer/utils/createUseDomView.ts b/packages/use-shader-fx/legacy/misc/useDomSyncer/utils/createUseDomView.ts similarity index 100% rename from packages/use-shader-fx/src/misc/useDomSyncer/utils/createUseDomView.ts rename to packages/use-shader-fx/legacy/misc/useDomSyncer/utils/createUseDomView.ts diff --git a/packages/use-shader-fx/src/misc/useDomSyncer/utils/errorHandler.ts b/packages/use-shader-fx/legacy/misc/useDomSyncer/utils/errorHandler.ts similarity index 100% rename from packages/use-shader-fx/src/misc/useDomSyncer/utils/errorHandler.ts rename to packages/use-shader-fx/legacy/misc/useDomSyncer/utils/errorHandler.ts diff --git a/packages/use-shader-fx/src/misc/useDomSyncer/utils/useIntersectionHandler.ts b/packages/use-shader-fx/legacy/misc/useDomSyncer/utils/useIntersectionHandler.ts similarity index 100% rename from packages/use-shader-fx/src/misc/useDomSyncer/utils/useIntersectionHandler.ts rename to packages/use-shader-fx/legacy/misc/useDomSyncer/utils/useIntersectionHandler.ts diff --git a/packages/use-shader-fx/src/misc/useDomSyncer/utils/useIsIntersecting.ts b/packages/use-shader-fx/legacy/misc/useDomSyncer/utils/useIsIntersecting.ts similarity index 100% rename from packages/use-shader-fx/src/misc/useDomSyncer/utils/useIsIntersecting.ts rename to packages/use-shader-fx/legacy/misc/useDomSyncer/utils/useIsIntersecting.ts diff --git a/packages/use-shader-fx/src/misc/useDomSyncer/utils/useUpdateDomRect.ts b/packages/use-shader-fx/legacy/misc/useDomSyncer/utils/useUpdateDomRect.ts similarity index 100% rename from packages/use-shader-fx/src/misc/useDomSyncer/utils/useUpdateDomRect.ts rename to packages/use-shader-fx/legacy/misc/useDomSyncer/utils/useUpdateDomRect.ts diff --git a/packages/use-shader-fx/src/misc/useFPSLimiter.ts b/packages/use-shader-fx/legacy/misc/useFPSLimiter.ts similarity index 100% rename from packages/use-shader-fx/src/misc/useFPSLimiter.ts rename to packages/use-shader-fx/legacy/misc/useFPSLimiter.ts diff --git a/packages/use-shader-fx/legacy/misc/usePointer.ts b/packages/use-shader-fx/legacy/misc/usePointer.ts new file mode 100644 index 00000000..dc8482ed --- /dev/null +++ b/packages/use-shader-fx/legacy/misc/usePointer.ts @@ -0,0 +1,80 @@ +import * as THREE from "three"; +import { useCallback, useRef } from "react"; + +export type PointerValues = { + currentPointer: THREE.Vector2; + prevPointer: THREE.Vector2; + diffPointer: THREE.Vector2; + velocity: THREE.Vector2; + isVelocityUpdate: boolean; +}; + +type UpdatePointer = (currentPointer: THREE.Vector2) => PointerValues; + +/** + * @description When given the pointer vector2 from r3f's RootState, it generates an update function that returns {`currentPointer`, `prevPointer`, `diffPointer`, `isVelocityUpdate`, `velocity`}. + * @description When calling custom in a `useFrame` loop, you can avoid duplication of execution by passing `pointerValues` to the update function of a Pointer-activated fxHook, such as `useBrush`. + * @param lerp 0~1, lerp intensity (0 to less than 1) , default : `0` + */ +export const usePointer = (lerp: number = 0): UpdatePointer => { + const prevPointer = useRef(new THREE.Vector2(0, 0)); + const diffPointer = useRef(new THREE.Vector2(0, 0)); + const lerpPointer = useRef(new THREE.Vector2(0, 0)); + const lastUpdateTime = useRef(0); + const velocity = useRef(new THREE.Vector2(0, 0)); + const isMoved = useRef(false); + + const updatePointer = useCallback( + (currentPointer: THREE.Vector2) => { + const now = performance.now(); + + // lerp + let current: THREE.Vector2; + if (isMoved.current && lerp) { + lerpPointer.current = lerpPointer.current.lerp( + currentPointer, + 1 - lerp + ); + current = lerpPointer.current.clone(); + } else { + current = currentPointer.clone(); + lerpPointer.current = current; + } + + // first frame + if (lastUpdateTime.current === 0) { + lastUpdateTime.current = now; + prevPointer.current = current; + } + const deltaTime = Math.max(1, now - lastUpdateTime.current); + lastUpdateTime.current = now; + + // get velocity + velocity.current + .copy(current) + .sub(prevPointer.current) + .divideScalar(deltaTime); + const isUpdate = velocity.current.length() > 0; + + //set prev temp pos + const prevTemp = isMoved.current + ? prevPointer.current.clone() + : current; + if (!isMoved.current && isUpdate) { + isMoved.current = true; + } + prevPointer.current = current; + + return { + currentPointer: current, + prevPointer: prevTemp, + diffPointer: diffPointer.current.subVectors(current, prevTemp), + velocity: velocity.current, + isVelocityUpdate: isUpdate, + }; + }, + [lerp] + ); + + return updatePointer; +}; diff --git a/packages/use-shader-fx/src/utils/createMaterialParameters.ts b/packages/use-shader-fx/legacy/utils/createMaterialParameters.ts similarity index 100% rename from packages/use-shader-fx/src/utils/createMaterialParameters.ts rename to packages/use-shader-fx/legacy/utils/createMaterialParameters.ts diff --git a/packages/use-shader-fx/legacy/utils/getDpr.ts b/packages/use-shader-fx/legacy/utils/getDpr.ts new file mode 100644 index 00000000..88caeef8 --- /dev/null +++ b/packages/use-shader-fx/legacy/utils/getDpr.ts @@ -0,0 +1,13 @@ +import { Dpr } from "../fxs/types"; + +export const getDpr = ( + dpr: Dpr +): { shader: number | false; fbo: number | false } => { + if (typeof dpr === "number") { + return { shader: dpr, fbo: dpr }; + } + return { + shader: dpr.shader ?? false, + fbo: dpr.fbo ?? false, + }; +}; diff --git a/packages/use-shader-fx/src/utils/setUniforms.ts b/packages/use-shader-fx/legacy/utils/setUniforms.ts similarity index 100% rename from packages/use-shader-fx/src/utils/setUniforms.ts rename to packages/use-shader-fx/legacy/utils/setUniforms.ts diff --git a/packages/use-shader-fx/src/utils/useAddMesh.ts b/packages/use-shader-fx/legacy/utils/useAddMesh.ts similarity index 100% rename from packages/use-shader-fx/src/utils/useAddMesh.ts rename to packages/use-shader-fx/legacy/utils/useAddMesh.ts diff --git a/packages/use-shader-fx/legacy/utils/useAddObject.ts b/packages/use-shader-fx/legacy/utils/useAddObject.ts new file mode 100644 index 00000000..591f6921 --- /dev/null +++ b/packages/use-shader-fx/legacy/utils/useAddObject.ts @@ -0,0 +1,36 @@ +import * as THREE from "three"; +import { useEffect, useMemo } from "react"; + +type Object3DConstructor = new ( + geometry: THREE.BufferGeometry, + material: M +) => T; + +/** + * Add geometry and material to Object3D and add them to scene. + */ +export const useAddObject = < + T extends THREE.Object3D, + M extends THREE.Material +>( + scene: THREE.Scene | false, + geometry: THREE.BufferGeometry, + material: M, + Proto: Object3DConstructor +) => { + const object3D = useMemo(() => { + const obj = new Proto(geometry, material); + scene && scene.add(obj); + return obj; + }, [geometry, material, Proto, scene]); + + useEffect(() => { + return () => { + scene && scene.remove(object3D); + geometry.dispose(); + material.dispose(); + }; + }, [scene, geometry, material, object3D]); + + return object3D; +}; diff --git a/packages/use-shader-fx/legacy/utils/useCamera.ts b/packages/use-shader-fx/legacy/utils/useCamera.ts new file mode 100644 index 00000000..8da37f48 --- /dev/null +++ b/packages/use-shader-fx/legacy/utils/useCamera.ts @@ -0,0 +1,35 @@ +import * as THREE from "three"; +import { useResolution } from "./useResolution"; +import { useMemo } from "react"; +import { Size } from "../fxs/types"; + +const getCameraProps = (width: number, height: number) => { + const frustumSize = height; + const aspect = width / height; + const [w, h] = [(frustumSize * aspect) / 2, frustumSize / 2]; + return { width: w, height: h, near: -1000, far: 1000 }; +}; + +export const useCamera = ( + size: Size, + cameraType: "OrthographicCamera" | "PerspectiveCamera" = "OrthographicCamera" +) => { + const resolution = useResolution(size); + const { width, height, near, far } = getCameraProps( + resolution.x, + resolution.y + ); + const camera = useMemo(() => { + return cameraType === "OrthographicCamera" + ? new THREE.OrthographicCamera( + -width, + width, + height, + -height, + near, + far + ) + : new THREE.PerspectiveCamera(50, width / height); + }, [width, height, near, far, cameraType]); + return camera; +}; diff --git a/packages/use-shader-fx/legacy/utils/useDoubleFBO.ts b/packages/use-shader-fx/legacy/utils/useDoubleFBO.ts new file mode 100644 index 00000000..ddfb11d0 --- /dev/null +++ b/packages/use-shader-fx/legacy/utils/useDoubleFBO.ts @@ -0,0 +1,122 @@ +import * as THREE from "three"; +import { useCallback, useEffect, useMemo } from "react"; +import { FBO_DEFAULT_OPTION, UseFboProps, renderFBO } from "./useSingleFBO"; +import { useResolution } from "./useResolution"; + +export type DoubleRenderTarget = { + read: THREE.WebGLRenderTarget; + write: THREE.WebGLRenderTarget; +}; + +interface WebGLDoubleRenderTarget extends DoubleRenderTarget { + swap: () => void; +} + +type FBOUpdateFunction = ( + gl: THREE.WebGLRenderer, + /** call before FBO is rendered */ + onBeforeRender?: ({ + read, + write, + }: { + read: THREE.Texture; + write: THREE.Texture; + }) => void +) => THREE.Texture; + +type UseDoubleFBOReturn = [ + { read: THREE.WebGLRenderTarget; write: THREE.WebGLRenderTarget }, + FBOUpdateFunction +]; + +/** + * @description Custom hook for setting up double buffering with WebGL render targets. + * @param UseFboProps same as `useSingleFBO` + */ +export const useDoubleFBO = (props: UseFboProps): UseDoubleFBOReturn => { + const { + scene, + camera, + size, + dpr = false, + isSizeUpdate = false, + depth = false, + ...renderTargetOptions + } = props; + + const resolution = useResolution(size, dpr); + + const renderTarget = useMemo(() => { + const read = new THREE.WebGLRenderTarget(resolution.x, resolution.y, { + ...FBO_DEFAULT_OPTION, + ...renderTargetOptions, + }); + const write = new THREE.WebGLRenderTarget(resolution.x, resolution.y, { + ...FBO_DEFAULT_OPTION, + ...renderTargetOptions, + }); + + if (depth) { + read.depthTexture = new THREE.DepthTexture( + resolution.x, + resolution.y, + THREE.FloatType + ); + write.depthTexture = new THREE.DepthTexture( + resolution.x, + resolution.y, + THREE.FloatType + ); + } + + return { + read: read, + write: write, + swap: function () { + let temp = this.read; + this.read = this.write; + this.write = temp; + }, + }; + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); + + if (isSizeUpdate) { + renderTarget.read?.setSize(resolution.x, resolution.y); + renderTarget.write?.setSize(resolution.x, resolution.y); + } + + useEffect(() => { + const temp = renderTarget; + return () => { + temp.read?.dispose(); + temp.write?.dispose(); + }; + }, [renderTarget]); + + const updateRenderTarget: FBOUpdateFunction = useCallback( + (gl, onBeforeRender) => { + const fbo = renderTarget; + renderFBO({ + gl, + scene, + camera, + fbo: fbo.write!, + onBeforeRender: () => + onBeforeRender && + onBeforeRender({ + read: fbo.read!.texture, + write: fbo.write!.texture, + }), + onSwap: () => fbo.swap(), + }); + return fbo.read?.texture as THREE.Texture; + }, + [scene, camera, renderTarget] + ); + + return [ + { read: renderTarget.read, write: renderTarget.write }, + updateRenderTarget, + ]; +}; diff --git a/packages/use-shader-fx/src/utils/useParams.ts b/packages/use-shader-fx/legacy/utils/useParams.ts similarity index 100% rename from packages/use-shader-fx/src/utils/useParams.ts rename to packages/use-shader-fx/legacy/utils/useParams.ts diff --git a/packages/use-shader-fx/src/utils/useResizeBoundary.ts b/packages/use-shader-fx/legacy/utils/useResizeBoundary.ts similarity index 100% rename from packages/use-shader-fx/src/utils/useResizeBoundary.ts rename to packages/use-shader-fx/legacy/utils/useResizeBoundary.ts diff --git a/packages/use-shader-fx/legacy/utils/useResolution.ts b/packages/use-shader-fx/legacy/utils/useResolution.ts new file mode 100644 index 00000000..1ae2c633 --- /dev/null +++ b/packages/use-shader-fx/legacy/utils/useResolution.ts @@ -0,0 +1,17 @@ +import * as THREE from "three"; +import { useMemo } from "react"; +import { Size } from "../fxs/types"; + +/** + * @params dpr if dpr is set, it returns the resolution which is size multiplied by dpr. + */ +export const useResolution = (size: Size, dpr: number | false = false) => { + const _width = dpr ? size.width * dpr : size.width; + const _height = dpr ? size.height * dpr : size.height; + + const resolution = useMemo( + () => new THREE.Vector2(_width, _height), + [_width, _height] + ); + return resolution; +}; diff --git a/packages/use-shader-fx/legacy/utils/useSingleFBO.ts b/packages/use-shader-fx/legacy/utils/useSingleFBO.ts new file mode 100644 index 00000000..8dc8f6fc --- /dev/null +++ b/packages/use-shader-fx/legacy/utils/useSingleFBO.ts @@ -0,0 +1,126 @@ +import * as THREE from "three"; +import { useCallback, useEffect, useMemo, useRef } from "react"; +import { useResolution } from "./useResolution"; +import { Size } from "../fxs/types"; + +export const FBO_DEFAULT_OPTION: THREE.RenderTargetOptions = { + depthBuffer: false, +}; + +export type UseFboProps = { + scene: THREE.Scene; + camera: THREE.Camera; + size: Size; + /** If dpr is set, dpr will be multiplied, default : `false` */ + dpr?: number | false; + /** Whether to resize when resizing occurs. If isDpr is true, set FBO to setSize even if dpr is changed, default : `false` */ + isSizeUpdate?: boolean; + /** If set, the scene depth will be rendered into buffer.depthTexture. default : `false` */ + depth?: boolean; +} & THREE.RenderTargetOptions; + +export const renderFBO = ({ + gl, + fbo, + scene, + camera, + onBeforeRender, + onSwap, +}: { + gl: THREE.WebGLRenderer; + fbo: THREE.WebGLRenderTarget; + scene: THREE.Scene; + camera: THREE.Camera; + onBeforeRender: () => void; + onSwap?: () => void; +}) => { + gl.setRenderTarget(fbo); + onBeforeRender(); + gl.clear(); + gl.render(scene, camera); + onSwap && onSwap(); + gl.setRenderTarget(null); + gl.clear(); +}; + +type UpdateRenderTarget = ( + gl: THREE.WebGLRenderer, + /** call before FBO is rendered */ + onBeforeRender?: ({ read }: { read: THREE.Texture }) => void +) => THREE.Texture; + +type UseSingleFBOReturn = [THREE.WebGLRenderTarget, UpdateRenderTarget]; + +/** + * @param dpr If dpr is set, dpr will be multiplied, default:false + * @param isSizeUpdate Whether to resize when resizing occurs. If isDpr is true, set FBO to setSize even if dpr is changed, default:false + * @param depthBuffer Unlike the default in three.js, the default is `false`. + * @returns [THREE.WebGLRenderTarget , updateFBO] -Receives the RenderTarget as the first argument and the update function as the second argument. + */ +export const useSingleFBO = (props: UseFboProps): UseSingleFBOReturn => { + const { + scene, + camera, + size, + dpr = false, + isSizeUpdate = false, + depth = false, + ...renderTargetOptions + } = props; + + const renderTarget = useRef(); + + const resolution = useResolution(size, dpr); + + renderTarget.current = useMemo( + () => { + const target = new THREE.WebGLRenderTarget( + resolution.x, + resolution.y, + { + ...FBO_DEFAULT_OPTION, + ...renderTargetOptions, + } + ); + if (depth) { + target.depthTexture = new THREE.DepthTexture( + resolution.x, + resolution.y, + THREE.FloatType + ); + } + return target; + }, + // eslint-disable-next-line react-hooks/exhaustive-deps + [] + ); + + if (isSizeUpdate) { + renderTarget.current?.setSize(resolution.x, resolution.y); + } + + useEffect(() => { + const temp = renderTarget.current; + return () => { + temp?.dispose(); + }; + }, []); + + const updateRenderTarget: UpdateRenderTarget = useCallback( + (gl, onBeforeRender) => { + const fbo = renderTarget.current!; + renderFBO({ + gl, + fbo, + scene, + camera, + onBeforeRender: () => + onBeforeRender && onBeforeRender({ read: fbo.texture }), + }); + return fbo.texture; + }, + [scene, camera] + ); + + return [renderTarget.current, updateRenderTarget]; +}; diff --git a/packages/use-shader-fx/src/fxs/materials/FxMaterial.ts b/packages/use-shader-fx/src/fxs/materials/FxMaterial.ts new file mode 100644 index 00000000..855d9a1e --- /dev/null +++ b/packages/use-shader-fx/src/fxs/materials/FxMaterial.ts @@ -0,0 +1,42 @@ +import * as THREE from "three"; + +export class FxMaterial extends THREE.ShaderMaterial { + setUniformValues(values: any) { + if (values === undefined) return; + + for (const key in values) { + const newValue = values[key]; + + if (newValue === undefined) { + console.warn( + `use-shader-fx: parameter '${key}' has value of undefined.` + ); + continue; + } + + const curretUniform = this.uniforms[key]; + + if (curretUniform === undefined) { + console.warn( + `use-shader-fx: '${key}' is not a uniform property of ${this.type}.` + ); + return; + } + + const currentValue = curretUniform.value; + + if (currentValue && currentValue.isColor) { + currentValue.set(newValue); + } else if ( + currentValue && + currentValue.isVector3 && + newValue && + newValue.isVector3 + ) { + currentValue.copy(newValue); + } else { + curretUniform.value = newValue; + } + } + } +} diff --git a/packages/use-shader-fx/src/fxs/types/index.ts b/packages/use-shader-fx/src/fxs/types/index.ts index 381ec33b..4cd4befc 100644 --- a/packages/use-shader-fx/src/fxs/types/index.ts +++ b/packages/use-shader-fx/src/fxs/types/index.ts @@ -1,5 +1,4 @@ import * as THREE from "three"; -import { RootState } from "@react-three/fiber"; export type Size = { width: number; height: number }; @@ -12,27 +11,24 @@ export type Dpr = fbo?: false | number; }; -export type OnBeforeInitParameters = { - uniforms: { [uniform: string]: THREE.IUniform }; - fragmentShader: string; - vertexShader: string; -}; - -export type MaterialProps = { - /** - * An optional callback that is executed immediately before the shader program is initialised. This function is called with the shader source code as a parameter. Useful for the modification of built-in materials. - * @param parameters {fragmentShader, vertexShader, uniforms} - */ - onBeforeInit?: (parameters: OnBeforeInitParameters) => void; +export type RootState = { + /** The instance of the renderer */ + gl: THREE.WebGLRenderer; + /** Default clock */ + clock: THREE.Clock; + /** Normalized event coordinates */ + pointer: THREE.Vector2; + /** Reactive pixel-size of the canvas */ + size: Size; }; -export interface HooksProps extends MaterialProps { +export interface HooksProps { /** Width,Height in pixels, or `size` from r3f */ size: Size; /** Pixel-ratio, use `window.devicePixelRatio` or viewport.dpr from r3f */ dpr: Dpr; /** Whether to `setSize` the FBO when updating size or dpr. default : `false` */ - isSizeUpdate?: boolean; + sizeUpdate?: boolean; /** * @type `THREE.RenderTargetOptions` * @param depthBuffer Unlike the default in three.js, the default is `false`. @@ -40,32 +36,32 @@ export interface HooksProps extends MaterialProps { renderTargetOptions?: THREE.RenderTargetOptions; } +export type OnInit = (material: T) => void; + /** * @returns {HooksReturn} - * updateFx - Functions to update parameters and render. - * updateParams - Function to update parameters only. - * fxObject - An object containing various FX components such as scene, camera, material, and render target. + * render - Functions to update parameters and render. + * setValues - Function to update parameters only. + * texture - テクスチャー + * material - material + * scene - scene * - * @template T The type for the parameters of the hooks. - * @template O The type for the FX object. - * @template C The type for the custom parameters. + * @template V The type for the FX parameters. + * @template O The type for the material. */ -export type HooksReturn = [ +export type HooksReturn = { /** * Functions to update parameters and render. * @param rootState RootState - * @param newParams params of fxHooks - * @param customParams custom params, added to `uniforms` during initialisation + * @param newValues params of fxHooks */ - (rootState: RootState, newParams?: T, customParams?: C) => THREE.Texture, + render: (rootState: RootState, newValues?: V) => THREE.Texture; /** * Function to update parameters only. - * @param newParams params of fxHooks - * @param customParams custom params, added to `uniforms` during initialisation - */ - (newParams?: T, customParams?: C) => void, - /** - * Contains each part of FX such as scene, camera, material, render target, etc. + * @param newValues params of fxHooks */ - O -]; + setValues: (newValues: V) => void; + texture: THREE.Texture; + material: M; + scene: THREE.Scene; +}; diff --git a/packages/use-shader-fx/src/fxs/useFluid/index.ts b/packages/use-shader-fx/src/fxs/useFluid/index.ts new file mode 100644 index 00000000..51a31e29 --- /dev/null +++ b/packages/use-shader-fx/src/fxs/useFluid/index.ts @@ -0,0 +1,124 @@ +import * as THREE from "three"; +import { useCallback, useMemo } from "react"; +import { useCamera } from "../../utils/useCamera"; +import { UseFboProps, useSingleFBO } from "../../utils/useSingleFBO"; +import { HooksProps, HooksReturn } from "../types"; +import { getDpr } from "../../utils/getDpr"; +import { OnInit, RootState } from "../types"; +import { useAddObject } from "../../utils/useAddObject"; +import { useDoubleFBO } from "../../utils/useDoubleFBO"; +import { useAdvection } from "./useAdvection"; +import { useSplat } from "./useSplat"; +import { useDivergence } from "./useDivergence"; +import { usePoisson } from "./usePoisson"; +import { usePressure } from "./usePressure"; + +export type FluidValues = {}; + +/*=============================================== +- mause周りの修正 +- 境界の作成 +- リファクタリング + - vertexShader、普通でいいのでは? + +useAddObject を useObject3Dに +sceneにいれたり、useObject3Dをする部分を、useSceneにまとめる + +===============================================*/ + +/** + * @link https://github.com/FunTechInc/use-shader-fx?tab=readme-ov-file#usage + * + * It is a basic value noise with `fbm` and `domain warping` + */ +export const useFluid = ( + { + size, + dpr, + sizeUpdate, + renderTargetOptions, + ...values + }: HooksProps & FluidValues, + onInit?: OnInit +): HooksReturn => { + const _dpr = getDpr(dpr); + + const fboProps = useMemo( + () => ({ + dpr: _dpr.fbo, + size, + sizeUpdate, + type: THREE.FloatType, + ...renderTargetOptions, + }), + [size, _dpr.fbo, renderTargetOptions, sizeUpdate] + ); + const [velocity_0, updateVelocity_0] = useSingleFBO(fboProps); + const [velocity_1, updateVelocity_1] = useSingleFBO(fboProps); + const [divergenceFBO, updateDivergenceFBO] = useSingleFBO(fboProps); + const [pressureFBO, updatePressureFBO] = useDoubleFBO(fboProps); + + const updateAdvection = useAdvection({ + size, + dpr: _dpr.shader, + velocity: velocity_0.texture, + updateRenderTarget: updateVelocity_1, + }); + const updateSplat = useSplat({ + size, + dpr: _dpr.shader, + updateRenderTarget: updateVelocity_1, + }); + const updateDivergence = useDivergence({ + size, + dpr: _dpr.shader, + velocity: velocity_1.texture, + updateRenderTarget: updateDivergenceFBO, + }); + const updatePoisson = usePoisson({ + size, + dpr: _dpr.shader, + divergence: divergenceFBO.texture, + updateRenderTarget: updatePressureFBO, + }); + const updatePressure = usePressure({ + size, + dpr: _dpr.shader, + velocity: velocity_1.texture, + pressure: pressureFBO.read.texture, + updateRenderTarget: updateVelocity_0, + }); + + const setValues = useCallback((newValues: FluidValues) => { + // material.setUniformValues(newValues); + }, []); + + const render = useCallback( + (rootState: RootState, newValues?: FluidValues) => { + updateAdvection(rootState); + updateSplat(rootState); + updateDivergence(rootState); + for (let i = 0; i < 32; i++) { + updatePoisson(rootState); + } + updatePressure(rootState); + return velocity_0.texture; + }, + [ + updateAdvection, + updateDivergence, + updatePoisson, + updatePressure, + updateSplat, + velocity_0.texture, + ] + ); + + return { + render, + setValues, + texture: velocity_0.texture, + // material, + // scene, + }; +}; diff --git a/packages/use-shader-fx/src/fxs/useFluid/materials/AdvectionMaterial.ts b/packages/use-shader-fx/src/fxs/useFluid/materials/AdvectionMaterial.ts new file mode 100644 index 00000000..67204095 --- /dev/null +++ b/packages/use-shader-fx/src/fxs/useFluid/materials/AdvectionMaterial.ts @@ -0,0 +1,37 @@ +import * as THREE from "three"; +import vertex from "./shaders/face.vert"; +import fragment from "./shaders/advection.frag"; +import { FxMaterial } from "../../materials/FxMaterial"; +import { DEFAULT_TEXTURE } from "../../../libs/constants"; + +export class AdvectionMaterial extends FxMaterial { + static get type() { + return "AdvectionMaterial"; + } + + uniforms: { + texelsize: { value: THREE.Vector2 }; + ratio: { value: THREE.Vector2 }; + velocity: { value: THREE.Texture }; + dt: { value: number }; + }; + + constructor(uniformValues = {}, parameters = {}) { + super(); + + this.type = AdvectionMaterial.type; + + this.uniforms = { + texelsize: { value: new THREE.Vector2() }, + ratio: { value: new THREE.Vector2() }, + velocity: { value: DEFAULT_TEXTURE }, + dt: { value: 0.014 }, + }; + + this.vertexShader = vertex; + this.fragmentShader = fragment; + + this.setUniformValues(uniformValues); + this.setValues(parameters); + } +} diff --git a/packages/use-shader-fx/src/fxs/useFluid/materials/DivergenceMaterial.ts b/packages/use-shader-fx/src/fxs/useFluid/materials/DivergenceMaterial.ts new file mode 100644 index 00000000..f1862963 --- /dev/null +++ b/packages/use-shader-fx/src/fxs/useFluid/materials/DivergenceMaterial.ts @@ -0,0 +1,35 @@ +import * as THREE from "three"; +import vertex from "./shaders/face.vert"; +import fragment from "./shaders/divergence.frag"; +import { FxMaterial } from "../../materials/FxMaterial"; +import { DEFAULT_TEXTURE } from "../../../libs/constants"; + +export class DivergenceMaterial extends FxMaterial { + static get type() { + return "DivergenceMaterial"; + } + + uniforms: { + texelsize: { value: THREE.Vector2 }; + velocity: { value: THREE.Texture }; + dt: { value: number }; + }; + + constructor(uniformValues = {}, parameters = {}) { + super(); + + this.type = DivergenceMaterial.type; + + this.uniforms = { + texelsize: { value: new THREE.Vector2() }, + velocity: { value: DEFAULT_TEXTURE }, + dt: { value: 0.014 }, + }; + + this.vertexShader = vertex; + this.fragmentShader = fragment; + + this.setUniformValues(uniformValues); + this.setValues(parameters); + } +} diff --git a/packages/use-shader-fx/src/fxs/useFluid/materials/PoissonMaterial.ts b/packages/use-shader-fx/src/fxs/useFluid/materials/PoissonMaterial.ts new file mode 100644 index 00000000..02b370ef --- /dev/null +++ b/packages/use-shader-fx/src/fxs/useFluid/materials/PoissonMaterial.ts @@ -0,0 +1,35 @@ +import * as THREE from "three"; +import vertex from "./shaders/face.vert"; +import fragment from "./shaders/poisson.frag"; +import { FxMaterial } from "../../materials/FxMaterial"; +import { DEFAULT_TEXTURE } from "../../../libs/constants"; + +export class PoissonMaterial extends FxMaterial { + static get type() { + return "PoissonMaterial"; + } + + uniforms: { + texelsize: { value: THREE.Vector2 }; + pressure: { value: THREE.Texture }; + divergence: { value: THREE.Texture }; + }; + + constructor(uniformValues = {}, parameters = {}) { + super(); + + this.type = PoissonMaterial.type; + + this.uniforms = { + texelsize: { value: new THREE.Vector2() }, + pressure: { value: DEFAULT_TEXTURE }, + divergence: { value: DEFAULT_TEXTURE }, + }; + + this.vertexShader = vertex; + this.fragmentShader = fragment; + + this.setUniformValues(uniformValues); + this.setValues(parameters); + } +} diff --git a/packages/use-shader-fx/src/fxs/useFluid/materials/PressureMaterial.ts b/packages/use-shader-fx/src/fxs/useFluid/materials/PressureMaterial.ts new file mode 100644 index 00000000..d826b63d --- /dev/null +++ b/packages/use-shader-fx/src/fxs/useFluid/materials/PressureMaterial.ts @@ -0,0 +1,37 @@ +import * as THREE from "three"; +import vertex from "./shaders/face.vert"; +import fragment from "./shaders/pressure.frag"; +import { FxMaterial } from "../../materials/FxMaterial"; +import { DEFAULT_TEXTURE } from "../../../libs/constants"; + +export class PressureMaterial extends FxMaterial { + static get type() { + return "PressureMaterial"; + } + + uniforms: { + texelsize: { value: THREE.Vector2 }; + pressure: { value: THREE.Texture }; + velocity: { value: THREE.Texture }; + dt: { value: number }; + }; + + constructor(uniformValues = {}, parameters = {}) { + super(); + + this.type = PressureMaterial.type; + + this.uniforms = { + texelsize: { value: new THREE.Vector2() }, + pressure: { value: DEFAULT_TEXTURE }, + velocity: { value: DEFAULT_TEXTURE }, + dt: { value: 0.014 }, + }; + + this.vertexShader = vertex; + this.fragmentShader = fragment; + + this.setUniformValues(uniformValues); + this.setValues(parameters); + } +} diff --git a/packages/use-shader-fx/src/fxs/useFluid/materials/SplatMaterial.ts b/packages/use-shader-fx/src/fxs/useFluid/materials/SplatMaterial.ts new file mode 100644 index 00000000..701d326c --- /dev/null +++ b/packages/use-shader-fx/src/fxs/useFluid/materials/SplatMaterial.ts @@ -0,0 +1,39 @@ +import * as THREE from "three"; +import vertex from "./shaders/splat.vert"; +import fragment from "./shaders/splat.frag"; +import { FxMaterial } from "../../materials/FxMaterial"; +import { DEFAULT_TEXTURE } from "../../../libs/constants"; + +export class SplatMaterial extends FxMaterial { + static get type() { + return "SplatMaterial"; + } + + uniforms: { + texelsize: { value: THREE.Vector2 }; + force: { value: THREE.Vector2 }; + center: { value: THREE.Vector2 }; + scale: { value: THREE.Vector2 }; + }; + + constructor(uniformValues = {}, parameters = {}) { + super(); + + this.type = SplatMaterial.type; + + this.uniforms = { + texelsize: { value: new THREE.Vector2() }, + force: { value: new THREE.Vector2(10, 10) }, + center: { value: new THREE.Vector2(0, 0) }, + scale: { value: new THREE.Vector2(100, 100) }, + }; + + this.vertexShader = vertex; + this.fragmentShader = fragment; + + this.blending = THREE.AdditiveBlending; + + this.setUniformValues(uniformValues); + this.setValues(parameters); + } +} diff --git a/packages/use-shader-fx/src/fxs/useFluid/materials/shaders/advection.frag b/packages/use-shader-fx/src/fxs/useFluid/materials/shaders/advection.frag new file mode 100644 index 00000000..9bb56987 --- /dev/null +++ b/packages/use-shader-fx/src/fxs/useFluid/materials/shaders/advection.frag @@ -0,0 +1,16 @@ +precision highp float; + +uniform sampler2D velocity; +uniform float dt; +uniform vec2 ratio; +uniform vec2 texelsize; +varying vec2 vUv; + +void main(){ + vec2 aspectratio = max(ratio.x, ratio.y) / ratio; + + vec2 vel = texture2D(velocity, vUv).xy; + vec2 uv2 = vUv - vel * dt * aspectratio; + vec2 newVel = texture2D(velocity, uv2).xy; + gl_FragColor = vec4(newVel, 0.0, 0.0); +} diff --git a/packages/use-shader-fx/src/fxs/useFluid/materials/shaders/divergence.frag b/packages/use-shader-fx/src/fxs/useFluid/materials/shaders/divergence.frag new file mode 100644 index 00000000..1d56e84a --- /dev/null +++ b/packages/use-shader-fx/src/fxs/useFluid/materials/shaders/divergence.frag @@ -0,0 +1,16 @@ +precision highp float; + +uniform sampler2D velocity; +uniform float dt; +uniform vec2 texelsize; +varying vec2 vUv; + +void main(){ + float x0 = texture2D(velocity, vUv-vec2(texelsize.x, 0)).x; + float x1 = texture2D(velocity, vUv+vec2(texelsize.x, 0)).x; + float y0 = texture2D(velocity, vUv-vec2(0, texelsize.y)).y; + float y1 = texture2D(velocity, vUv+vec2(0, texelsize.y)).y; + float divergence = (x1-x0 + y1-y0) / 2.0; + + gl_FragColor = vec4(divergence / dt); +} diff --git a/packages/use-shader-fx/src/fxs/useFluid/materials/shaders/face.vert b/packages/use-shader-fx/src/fxs/useFluid/materials/shaders/face.vert new file mode 100644 index 00000000..173af906 --- /dev/null +++ b/packages/use-shader-fx/src/fxs/useFluid/materials/shaders/face.vert @@ -0,0 +1,17 @@ +precision highp float; + +uniform vec2 texelsize; +varying vec2 vUv; + +void main(){ + vec3 pos = position; + vec2 scale = 1.0 - texelsize * 2.0; + pos.xy = pos.xy * scale; + vUv = vec2(0.5)+(pos.xy)*0.5; + gl_Position = vec4(pos, 1.0); + + + // vUv = uv; + // gl_Position = vec4(position, 1.0); + +} diff --git a/packages/use-shader-fx/src/fxs/useFluid/materials/shaders/poisson.frag b/packages/use-shader-fx/src/fxs/useFluid/materials/shaders/poisson.frag new file mode 100644 index 00000000..93f76222 --- /dev/null +++ b/packages/use-shader-fx/src/fxs/useFluid/materials/shaders/poisson.frag @@ -0,0 +1,17 @@ +precision highp float; +uniform sampler2D pressure; +uniform sampler2D divergence; +uniform vec2 texelsize; +varying vec2 vUv; + +void main(){ + + float p0 = texture2D(pressure, vUv+vec2(texelsize.x * 2.0, 0)).r; + float p1 = texture2D(pressure, vUv-vec2(texelsize.x * 2.0, 0)).r; + float p2 = texture2D(pressure, vUv+vec2(0, texelsize.y * 2.0 )).r; + float p3 = texture2D(pressure, vUv-vec2(0, texelsize.y * 2.0 )).r; + float div = texture2D(divergence, vUv).r; + + float newP = (p0 + p1 + p2 + p3) / 4.0 - div; + gl_FragColor = vec4(newP); +} diff --git a/packages/use-shader-fx/src/fxs/useFluid/materials/shaders/pressure.frag b/packages/use-shader-fx/src/fxs/useFluid/materials/shaders/pressure.frag new file mode 100644 index 00000000..e08aa858 --- /dev/null +++ b/packages/use-shader-fx/src/fxs/useFluid/materials/shaders/pressure.frag @@ -0,0 +1,21 @@ +precision highp float; + +uniform sampler2D pressure; +uniform sampler2D velocity; +uniform vec2 texelsize; +uniform float dt; +varying vec2 vUv; + +void main(){ + float step = 1.0; + + float p0 = texture2D(pressure, vUv+vec2(texelsize.x * step, 0)).r; + float p1 = texture2D(pressure, vUv-vec2(texelsize.x * step, 0)).r; + float p2 = texture2D(pressure, vUv+vec2(0, texelsize.y * step)).r; + float p3 = texture2D(pressure, vUv-vec2(0, texelsize.y * step)).r; + + vec2 v = texture2D(velocity, vUv).xy; + vec2 gradP = vec2(p0 - p1, p2 - p3) * 0.5; + v = v - gradP * dt; + gl_FragColor = vec4(v, 0.0, 1.0); +} \ No newline at end of file diff --git a/packages/use-shader-fx/src/fxs/useFluid/materials/shaders/splat.frag b/packages/use-shader-fx/src/fxs/useFluid/materials/shaders/splat.frag new file mode 100644 index 00000000..c3ab0ab4 --- /dev/null +++ b/packages/use-shader-fx/src/fxs/useFluid/materials/shaders/splat.frag @@ -0,0 +1,12 @@ +precision highp float; + +uniform vec2 force; +uniform vec2 center; +varying vec2 vUv; + +void main(){ + vec2 circle = (vUv - 0.5) * 2.0; + float d = 1.0-min(length(circle), 1.0); + d *= d; + gl_FragColor = vec4(force * d, 0., 1.); +} \ No newline at end of file diff --git a/packages/use-shader-fx/src/fxs/useFluid/materials/shaders/splat.vert b/packages/use-shader-fx/src/fxs/useFluid/materials/shaders/splat.vert new file mode 100644 index 00000000..62e25891 --- /dev/null +++ b/packages/use-shader-fx/src/fxs/useFluid/materials/shaders/splat.vert @@ -0,0 +1,12 @@ +precision highp float; + +uniform vec2 center; +uniform vec2 scale; +uniform vec2 texelsize; +varying vec2 vUv; + +void main(){ + vec2 pos = position.xy * scale * 2.0 * texelsize + center; + vUv = uv; + gl_Position = vec4(pos, 0.0, 1.0); +} \ No newline at end of file diff --git a/packages/use-shader-fx/src/fxs/useFluid/useAdvection.ts b/packages/use-shader-fx/src/fxs/useFluid/useAdvection.ts new file mode 100644 index 00000000..d3b3f988 --- /dev/null +++ b/packages/use-shader-fx/src/fxs/useFluid/useAdvection.ts @@ -0,0 +1,51 @@ +import * as THREE from "three"; +/*=============================================== +- boundaryつくってsceneにaddする +===============================================*/ +import { useCallback, useMemo } from "react"; +import { useCamera } from "../../utils/useCamera"; +import { Dpr, RootState, Size } from "../types"; +import { AdvectionMaterial } from "./materials/AdvectionMaterial"; +import { useAddObject } from "../../utils/useAddObject"; +import { SingleFBOUpdateFunction } from "../../utils/useSingleFBO"; +import { useResolution } from "../../utils/useResolution"; + +type AdvectionValues = { + velocity: THREE.Texture; +}; + +export const useAdvection = ({ + size, + dpr, + updateRenderTarget, + ...values +}: { + size: Size; + dpr: number | false; + updateRenderTarget: SingleFBOUpdateFunction; +} & AdvectionValues) => { + const scene = useMemo(() => new THREE.Scene(), []); + const camera = useCamera(size); + const geometry = useMemo(() => new THREE.PlaneGeometry(2, 2), []); + + const material = useMemo(() => { + const _mat = new AdvectionMaterial(values); + return _mat; + }, [values]); + + useAddObject(scene, geometry, material, THREE.Mesh); + + const resolution = useResolution(size, dpr); + material.uniforms.texelsize.value.set(1 / resolution.x, 1 / resolution.y); + material.uniforms.ratio.value.copy(resolution); + + const render = useCallback( + (rootState: RootState) => { + const { gl } = rootState; + updateRenderTarget({ gl, scene, camera }); + }, + [updateRenderTarget, scene, camera] + ); + + return render; +}; diff --git a/packages/use-shader-fx/src/fxs/useFluid/useDivergence.ts b/packages/use-shader-fx/src/fxs/useFluid/useDivergence.ts new file mode 100644 index 00000000..5afd6f59 --- /dev/null +++ b/packages/use-shader-fx/src/fxs/useFluid/useDivergence.ts @@ -0,0 +1,47 @@ +import * as THREE from "three"; +import { useCallback, useMemo } from "react"; +import { useCamera } from "../../utils/useCamera"; +import { Dpr, RootState, Size } from "../types"; +import { useAddObject } from "../../utils/useAddObject"; +import { SingleFBOUpdateFunction } from "../../utils/useSingleFBO"; +import { useResolution } from "../../utils/useResolution"; +import { DivergenceMaterial } from "./materials/DivergenceMaterial"; + +type DivergenceValues = { + velocity: THREE.Texture; +}; + +export const useDivergence = ({ + size, + dpr, + updateRenderTarget, + ...values +}: { + size: Size; + dpr: number | false; + updateRenderTarget: SingleFBOUpdateFunction; +} & DivergenceValues) => { + const scene = useMemo(() => new THREE.Scene(), []); + const camera = useCamera(size); + const geometry = useMemo(() => new THREE.PlaneGeometry(2, 2), []); + + const material = useMemo(() => { + const _mat = new DivergenceMaterial(values); + return _mat; + }, [values]); + + const resolution = useResolution(size, dpr); + material.uniforms.texelsize.value.set(1 / resolution.x, 1 / resolution.y); + + useAddObject(scene, geometry, material, THREE.Mesh); + + const render = useCallback( + (rootState: RootState) => { + const { gl } = rootState; + updateRenderTarget({ gl, scene, camera }); + }, + [updateRenderTarget, scene, camera] + ); + + return render; +}; diff --git a/packages/use-shader-fx/src/fxs/useFluid/usePoisson.ts b/packages/use-shader-fx/src/fxs/useFluid/usePoisson.ts new file mode 100644 index 00000000..2ba0fead --- /dev/null +++ b/packages/use-shader-fx/src/fxs/useFluid/usePoisson.ts @@ -0,0 +1,50 @@ +import * as THREE from "three"; +import { useCallback, useMemo } from "react"; +import { useCamera } from "../../utils/useCamera"; +import { Dpr, RootState, Size } from "../types"; +import { AdvectionMaterial } from "./materials/AdvectionMaterial"; +import { useAddObject } from "../../utils/useAddObject"; +import { SingleFBOUpdateFunction } from "../../utils/useSingleFBO"; +import { useResolution } from "../../utils/useResolution"; +import { PoissonMaterial } from "./materials/PoissonMaterial"; + +type PoissonValues = { + divergence: THREE.Texture; +}; + +export const usePoisson = ({ + size, + dpr, + updateRenderTarget, + ...values +}: { + size: Size; + dpr: number | false; + updateRenderTarget: SingleFBOUpdateFunction; +} & PoissonValues) => { + const scene = useMemo(() => new THREE.Scene(), []); + const camera = useCamera(size); + const geometry = useMemo(() => new THREE.PlaneGeometry(2, 2), []); + + const material = useMemo(() => { + const _mat = new PoissonMaterial(values); + return _mat; + }, [values]); + + const resolution = useResolution(size, dpr); + material.uniforms.texelsize.value.set(1 / resolution.x, 1 / resolution.y); + + useAddObject(scene, geometry, material, THREE.Mesh); + + const render = useCallback( + (rootState: RootState) => { + const { gl } = rootState; + updateRenderTarget({ gl, scene, camera }, ({ read }) => { + material.uniforms.pressure.value = read; + }); + }, + [updateRenderTarget, material, scene, camera] + ); + + return render; +}; diff --git a/packages/use-shader-fx/src/fxs/useFluid/usePressure.ts b/packages/use-shader-fx/src/fxs/useFluid/usePressure.ts new file mode 100644 index 00000000..530eb5a1 --- /dev/null +++ b/packages/use-shader-fx/src/fxs/useFluid/usePressure.ts @@ -0,0 +1,48 @@ +import * as THREE from "three"; +import { useCallback, useMemo } from "react"; +import { useCamera } from "../../utils/useCamera"; +import { RootState, Size } from "../types"; +import { useAddObject } from "../../utils/useAddObject"; +import { SingleFBOUpdateFunction } from "../../utils/useSingleFBO"; +import { useResolution } from "../../utils/useResolution"; +import { PressureMaterial } from "./materials/PressureMaterial"; + +type PressureValues = { + velocity: THREE.Texture; + pressure: THREE.Texture; +}; + +export const usePressure = ({ + size, + dpr, + updateRenderTarget, + ...values +}: { + size: Size; + dpr: number | false; + updateRenderTarget: SingleFBOUpdateFunction; +} & PressureValues) => { + const scene = useMemo(() => new THREE.Scene(), []); + const camera = useCamera(size); + const geometry = useMemo(() => new THREE.PlaneGeometry(2, 2), []); + + const material = useMemo(() => { + const _mat = new PressureMaterial(values); + return _mat; + }, [values]); + + const resolution = useResolution(size, dpr); + material.uniforms.texelsize.value.set(1 / resolution.x, 1 / resolution.y); + + useAddObject(scene, geometry, material, THREE.Mesh); + + const render = useCallback( + (rootState: RootState) => { + const { gl } = rootState; + updateRenderTarget({ gl, scene, camera }); + }, + [updateRenderTarget, scene, camera] + ); + + return render; +}; diff --git a/packages/use-shader-fx/src/fxs/useFluid/useSplat.ts b/packages/use-shader-fx/src/fxs/useFluid/useSplat.ts new file mode 100644 index 00000000..54bcf488 --- /dev/null +++ b/packages/use-shader-fx/src/fxs/useFluid/useSplat.ts @@ -0,0 +1,49 @@ +import * as THREE from "three"; +import { useCallback, useMemo } from "react"; +import { useCamera } from "../../utils/useCamera"; +import { RootState, Size } from "../types"; +import { useAddObject } from "../../utils/useAddObject"; +import { SingleFBOUpdateFunction } from "../../utils/useSingleFBO"; +import { useResolution } from "../../utils/useResolution"; +import { SplatMaterial } from "./materials/SplatMaterial"; +import { usePointer } from "../../misc/usePointer"; + +export const useSplat = ({ + size, + dpr, + updateRenderTarget, +}: { + size: Size; + dpr: number | false; + updateRenderTarget: SingleFBOUpdateFunction; +}) => { + const scene = useMemo(() => new THREE.Scene(), []); + const camera = useCamera(size); + const geometry = useMemo(() => new THREE.PlaneGeometry(1, 1), []); + + const material = useMemo(() => { + const _mat = new SplatMaterial(); + return _mat; + }, []); + + const resolution = useResolution(size, dpr); + material.uniforms.texelsize.value.set(1 / resolution.x, 1 / resolution.y); + + useAddObject(scene, geometry, material, THREE.Mesh); + + const updatePointer = usePointer(); + + const render = useCallback( + (rootState: RootState) => { + const { gl, pointer } = rootState; + + const { currentPointer } = updatePointer(pointer); + material.uniforms.center.value.copy(currentPointer); + + updateRenderTarget({ gl, scene, camera, clear: false }); + }, + [updateRenderTarget, material, updatePointer, scene, camera] + ); + + return render; +}; diff --git a/packages/use-shader-fx/src/fxs/useNoise/NoiseMaterial.ts b/packages/use-shader-fx/src/fxs/useNoise/NoiseMaterial.ts new file mode 100644 index 00000000..b3cf0a22 --- /dev/null +++ b/packages/use-shader-fx/src/fxs/useNoise/NoiseMaterial.ts @@ -0,0 +1,45 @@ +import * as THREE from "three"; +import { ShaderChunk } from "../../libs/shaders/ShaderChunk"; +import fragment from "./noise.frag"; +import { FxMaterial } from "../materials/FxMaterial"; +import { NoiseValues } from "."; + +export class NoiseMaterial extends FxMaterial { + static get type() { + return "NoiseMaterial"; + } + + uniforms: { + uTime: { value: number }; + scale: { value: number }; + timeStrength: { value: number }; + noiseOctaves: { value: number }; + fbmOctaves: { value: number }; + warpOctaves: { value: number }; + warpDirection: { value: THREE.Vector2 }; + warpStrength: { value: number }; + }; + + constructor(uniformValues?: NoiseValues, parameters = {}) { + super(); + + this.type = NoiseMaterial.type; + + this.uniforms = { + uTime: { value: 0.0 }, + scale: { value: 0.03 }, + timeStrength: { value: 0.3 }, + noiseOctaves: { value: 2 }, + fbmOctaves: { value: 2 }, + warpOctaves: { value: 2 }, + warpDirection: { value: new THREE.Vector2(2.0, 2.0) }, + warpStrength: { value: 8 }, + }; + + this.vertexShader = ShaderChunk.planeVertex; + this.fragmentShader = fragment; + + this.setUniformValues(uniformValues); + this.setValues(parameters); + } +} diff --git a/packages/use-shader-fx/src/fxs/useNoise/index.ts b/packages/use-shader-fx/src/fxs/useNoise/index.ts new file mode 100644 index 00000000..16d17d4c --- /dev/null +++ b/packages/use-shader-fx/src/fxs/useNoise/index.ts @@ -0,0 +1,95 @@ +import * as THREE from "three"; +import { useCallback, useMemo } from "react"; +import { useCamera } from "../../utils/useCamera"; +import { useSingleFBO } from "../../utils/useSingleFBO"; +import { HooksProps, HooksReturn } from "../types"; +import { getDpr } from "../../utils/getDpr"; +import { OnInit, RootState } from "../types"; +import { useAddObject } from "../../utils/useAddObject"; +import { NoiseMaterial } from "./NoiseMaterial"; + +export type NoiseValues = { + /** noise scale , default : `0.004` */ + scale?: number; + /** time factor default : `0.3` */ + timeStrength?: number; + /** noiseOctaves, affects performance default : `2` */ + noiseOctaves?: number; + /** fbmOctaves, affects performance default : `2` */ + fbmOctaves?: number; + /** domain warping octaves , affects performance default : `2` */ + warpOctaves?: number; + /** direction of domain warping , default : `(2.0,2,0)` */ + warpDirection?: THREE.Vector2; + /** strength of domain warping , default : `8.0` */ + warpStrength?: number; + /** you can get into the rhythm ♪ , default : `false` */ + beat?: number | false; +}; + +/** + * @link https://github.com/FunTechInc/use-shader-fx?tab=readme-ov-file#usage + * + * It is a basic value noise with `fbm` and `domain warping` + */ +export const useNoise = ( + { + size, + dpr, + sizeUpdate, + renderTargetOptions, + ...values + }: HooksProps & NoiseValues, + onInit?: OnInit +): HooksReturn => { + const _dpr = getDpr(dpr); + + const scene = useMemo(() => new THREE.Scene(), []); + + const camera = useCamera(size); + + const geometry = useMemo(() => new THREE.PlaneGeometry(2, 2), []); + + const material = useMemo(() => { + const _mat = new NoiseMaterial(values); + onInit && onInit(_mat); + return _mat; + }, [onInit, values]); + + useAddObject(scene, geometry, material, THREE.Mesh); + + const [renderTarget, updateRenderTarget] = useSingleFBO({ + scene, + camera, + size, + dpr: _dpr.fbo, + sizeUpdate, + ...renderTargetOptions, + }); + + const setValues = useCallback( + (newValues: NoiseValues) => { + material.setUniformValues(newValues); + }, + [material] + ); + + const render = useCallback( + (rootState: RootState, newValues?: NoiseValues) => { + const { gl, clock } = rootState; + newValues && setValues(newValues); + material.uniforms.uTime.value = + newValues?.beat || clock.getElapsedTime(); + return updateRenderTarget(gl); + }, + [setValues, updateRenderTarget, material] + ); + + return { + render, + setValues, + texture: renderTarget.texture, + material, + scene, + }; +}; diff --git a/packages/use-shader-fx/src/fxs/useNoise/noise.frag b/packages/use-shader-fx/src/fxs/useNoise/noise.frag new file mode 100644 index 00000000..39e96e23 --- /dev/null +++ b/packages/use-shader-fx/src/fxs/useNoise/noise.frag @@ -0,0 +1,76 @@ +precision highp float; +precision highp int; + +varying vec2 vUv; +uniform float uTime; +uniform float timeStrength; +uniform int noiseOctaves; +uniform int fbmOctaves; +uniform int warpOctaves; +uniform vec2 warpDirection; +uniform float warpStrength; +uniform float scale; + +const float per = 0.5; +const float PI = 3.14159265359; + +float rnd(vec2 n) { + float a = 0.129898; + float b = 0.78233; + float c = 437.585453; + float dt= dot(n ,vec2(a, b)); + float sn= mod(dt, PI); + return fract(sin(sn) * c); +} + +float interpolate(float a, float b, float x){ + float f = (1.0 - cos(x * PI)) * 0.5; + return a * (1.0 - f) + b * f; +} + +float irnd(vec2 p){ + vec2 i = floor(p); + vec2 f = fract(p); + vec4 v = vec4(rnd(vec2(i.x,i.y)),rnd(vec2(i.x + 1.0,i.y)),rnd(vec2(i.x,i.y + 1.0)),rnd(vec2(i.x + 1.0, i.y + 1.0))); + return interpolate(interpolate(v.x, v.y, f.x), interpolate(v.z, v.w, f.x), f.y); +} + +// Based on The Book of Shaders +// https://thebookofshaders.com/13/ +float noise(vec2 p, float time){ + float t = 0.0; + for(int i = 0; i < noiseOctaves; i++){ + float freq = pow(2.0, float(i)); + float amp = pow(per, float(noiseOctaves - i)); + t += irnd(vec2(p.y / freq + time, p.x / freq + time)) * amp; + } + return t; +} + +float fbm(vec2 x, float time) { + float v = 0.0; + float a = 0.5; + vec2 shift = vec2(100); + mat2 rot = mat2(cos(0.5), sin(0.5), -sin(0.5), cos(0.5)); + float sign = 1.0; + for (int i = 0; i < fbmOctaves; ++i) { + v += a * noise(x, time * sign); + x = rot * x * 2.0 + shift; + a *= 0.5; + sign *= -1.0; + } + return v; +} + +float warp(vec2 x, float g,float time){ + float val = 0.0; + for (int i = 0; i < warpOctaves; i++){ + val = fbm(x + g * vec2(cos(warpDirection.x * val), sin(warpDirection.y * val)), time); + } + return val; +} + +void main() { + float noise = warp(gl_FragCoord.xy * scale ,warpStrength,uTime * timeStrength); + gl_FragColor = vec4(vec3(noise),1.0); +} \ No newline at end of file diff --git a/packages/use-shader-fx/src/index.js b/packages/use-shader-fx/src/index.js index be08983b..ed03505b 100644 --- a/packages/use-shader-fx/src/index.js +++ b/packages/use-shader-fx/src/index.js @@ -1,79 +1,5 @@ /*=============================================== FXs ===============================================*/ -// interactions -export * from "./fxs/interactions/useBrush"; - -// simulations -export * from "./fxs/simulations/useFluid"; -export * from "./fxs/simulations/useRipple"; - -// noises -export * from "./fxs/noises/useNoise"; -export * from "./fxs/noises/useColorStrata"; -export * from "./fxs/noises/useMarble"; -export * from "./fxs/noises/useCosPalette"; - -// utils -export * from "./fxs/utils/useDuoTone"; -export * from "./fxs/utils/useBlending"; -export * from "./fxs/utils/useFxTexture"; -export * from "./fxs/utils/useBrightnessPicker"; -export * from "./fxs/utils/useFxBlending"; -export * from "./fxs/utils/useAlphaBlending"; -export * from "./fxs/utils/useHSV"; -export * from "./fxs/utils/useCoverTexture"; - -// effects -export * from "./fxs/effects/useSimpleBlur"; -export * from "./fxs/effects/useMotionBlur"; -export * from "./fxs/effects/useWave"; - -// misc -export * from "./fxs/misc/useChromaKey"; - -// blank -export * from "./fxs/blank/useBlank"; -export * from "./fxs/blank/useRawBlank"; - -// 3D -export * from "./fxs/3D/useMorphParticles"; -export * from "./fxs/3D/useMorphParticles/useCreateMorphParticles"; -export * from "./fxs/3D/useWobble3D"; -export * from "./fxs/3D/useWobble3D/useCreateWobble3D"; - -/*=============================================== -utils -===============================================*/ -export * from "./utils/setUniforms"; -export * from "./utils/useAddMesh"; -export * from "./utils/useCamera"; -export * from "./utils/useDoubleFBO"; -export * from "./utils/useParams"; -export * from "./utils/useResolution"; -export * from "./utils/useSingleFBO"; -export * from "./utils/useResizeBoundary"; - -/*=============================================== -misc -===============================================*/ -export * from "./misc/usePointer"; -export * from "./misc/useBeat"; -export * from "./misc/useFPSLimiter"; -export * from "./misc/useDomSyncer"; -export * from "./misc/useCopyTexture"; - -/*=============================================== -Easing -===============================================*/ -export * from "./libs/Easings"; - -/*=============================================== -Utils -===============================================*/ -export * from "./libs/Utils"; - -/*=============================================== -ShaderChunk -===============================================*/ -export * from "./libs/shaders/ShaderChunk"; +export * from "./fxs/useNoise"; +export * from "./fxs/useFluid"; diff --git a/packages/use-shader-fx/src/utils/useDoubleFBO.ts b/packages/use-shader-fx/src/utils/useDoubleFBO.ts index ddfb11d0..0249a388 100644 --- a/packages/use-shader-fx/src/utils/useDoubleFBO.ts +++ b/packages/use-shader-fx/src/utils/useDoubleFBO.ts @@ -1,6 +1,11 @@ import * as THREE from "three"; import { useCallback, useEffect, useMemo } from "react"; -import { FBO_DEFAULT_OPTION, UseFboProps, renderFBO } from "./useSingleFBO"; +import { + FBO_DEFAULT_OPTION, + UseFboProps, + renderFBO, + RenderProps, +} from "./useSingleFBO"; import { useResolution } from "./useResolution"; export type DoubleRenderTarget = { @@ -12,8 +17,8 @@ interface WebGLDoubleRenderTarget extends DoubleRenderTarget { swap: () => void; } -type FBOUpdateFunction = ( - gl: THREE.WebGLRenderer, +export type DoubleFBOUpdateFunction = ( + renderProps: RenderProps, /** call before FBO is rendered */ onBeforeRender?: ({ read, @@ -26,7 +31,7 @@ type FBOUpdateFunction = ( type UseDoubleFBOReturn = [ { read: THREE.WebGLRenderTarget; write: THREE.WebGLRenderTarget }, - FBOUpdateFunction + DoubleFBOUpdateFunction ]; /** @@ -39,7 +44,7 @@ export const useDoubleFBO = (props: UseFboProps): UseDoubleFBOReturn => { camera, size, dpr = false, - isSizeUpdate = false, + sizeUpdate = false, depth = false, ...renderTargetOptions } = props; @@ -81,7 +86,7 @@ export const useDoubleFBO = (props: UseFboProps): UseDoubleFBOReturn => { // eslint-disable-next-line react-hooks/exhaustive-deps }, []); - if (isSizeUpdate) { + if (sizeUpdate) { renderTarget.read?.setSize(resolution.x, resolution.y); renderTarget.write?.setSize(resolution.x, resolution.y); } @@ -94,17 +99,16 @@ export const useDoubleFBO = (props: UseFboProps): UseDoubleFBOReturn => { }; }, [renderTarget]); - const updateRenderTarget: FBOUpdateFunction = useCallback( - (gl, onBeforeRender) => { + const updateRenderTarget: DoubleFBOUpdateFunction = useCallback( + (renderProps, onBeforeRender) => { const fbo = renderTarget; renderFBO({ - gl, - scene, - camera, + ...renderProps, + scene: renderProps.scene || scene, + camera: renderProps.camera || camera, fbo: fbo.write!, onBeforeRender: () => - onBeforeRender && - onBeforeRender({ + onBeforeRender?.({ read: fbo.read!.texture, write: fbo.write!.texture, }), diff --git a/packages/use-shader-fx/src/utils/useSingleFBO.ts b/packages/use-shader-fx/src/utils/useSingleFBO.ts index 8dc8f6fc..53ec7178 100644 --- a/packages/use-shader-fx/src/utils/useSingleFBO.ts +++ b/packages/use-shader-fx/src/utils/useSingleFBO.ts @@ -8,52 +8,58 @@ export const FBO_DEFAULT_OPTION: THREE.RenderTargetOptions = { }; export type UseFboProps = { - scene: THREE.Scene; - camera: THREE.Camera; + scene?: THREE.Scene; + camera?: THREE.Camera; size: Size; /** If dpr is set, dpr will be multiplied, default : `false` */ dpr?: number | false; /** Whether to resize when resizing occurs. If isDpr is true, set FBO to setSize even if dpr is changed, default : `false` */ - isSizeUpdate?: boolean; + sizeUpdate?: boolean; /** If set, the scene depth will be rendered into buffer.depthTexture. default : `false` */ depth?: boolean; } & THREE.RenderTargetOptions; +export type RenderProps = { + gl: THREE.WebGLRenderer; + scene?: THREE.Scene; + camera?: THREE.Camera; + clear?: boolean; +}; + export const renderFBO = ({ gl, fbo, scene, camera, + clear = true, onBeforeRender, onSwap, }: { - gl: THREE.WebGLRenderer; fbo: THREE.WebGLRenderTarget; - scene: THREE.Scene; - camera: THREE.Camera; onBeforeRender: () => void; onSwap?: () => void; -}) => { +} & RenderProps) => { + if (!scene || !camera) return; gl.setRenderTarget(fbo); onBeforeRender(); - gl.clear(); + gl.autoClear = clear; + clear && gl.clear(); gl.render(scene, camera); onSwap && onSwap(); gl.setRenderTarget(null); - gl.clear(); }; -type UpdateRenderTarget = ( - gl: THREE.WebGLRenderer, +export type SingleFBOUpdateFunction = ( + renderProps: RenderProps, /** call before FBO is rendered */ onBeforeRender?: ({ read }: { read: THREE.Texture }) => void ) => THREE.Texture; -type UseSingleFBOReturn = [THREE.WebGLRenderTarget, UpdateRenderTarget]; +type UseSingleFBOReturn = [THREE.WebGLRenderTarget, SingleFBOUpdateFunction]; /** * @param dpr If dpr is set, dpr will be multiplied, default:false - * @param isSizeUpdate Whether to resize when resizing occurs. If isDpr is true, set FBO to setSize even if dpr is changed, default:false + * @param sizeUpdate Whether to resize when resizing occurs. If isDpr is true, set FBO to setSize even if dpr is changed, default:false * @param depthBuffer Unlike the default in three.js, the default is `false`. * @returns [THREE.WebGLRenderTarget , updateFBO] -Receives the RenderTarget as the first argument and the update function as the second argument. */ @@ -63,7 +69,7 @@ export const useSingleFBO = (props: UseFboProps): UseSingleFBOReturn => { camera, size, dpr = false, - isSizeUpdate = false, + sizeUpdate = false, depth = false, ...renderTargetOptions } = props; @@ -95,7 +101,7 @@ export const useSingleFBO = (props: UseFboProps): UseSingleFBOReturn => { [] ); - if (isSizeUpdate) { + if (sizeUpdate) { renderTarget.current?.setSize(resolution.x, resolution.y); } @@ -106,16 +112,15 @@ export const useSingleFBO = (props: UseFboProps): UseSingleFBOReturn => { }; }, []); - const updateRenderTarget: UpdateRenderTarget = useCallback( - (gl, onBeforeRender) => { + const updateRenderTarget: SingleFBOUpdateFunction = useCallback( + (renderProps, onBeforeRender) => { const fbo = renderTarget.current!; renderFBO({ - gl, + ...renderProps, + scene: renderProps.scene || scene, + camera: renderProps.camera || camera, fbo, - scene, - camera, - onBeforeRender: () => - onBeforeRender && onBeforeRender({ read: fbo.texture }), + onBeforeRender: () => onBeforeRender?.({ read: fbo.texture }), }); return fbo.texture; }, diff --git a/packages/use-shader-fx/types/fxs/3D/types/index.d.ts b/packages/use-shader-fx/types/fxs/3D/types/index.d.ts deleted file mode 100644 index 1af2ca28..00000000 --- a/packages/use-shader-fx/types/fxs/3D/types/index.d.ts +++ /dev/null @@ -1,10 +0,0 @@ -import * as THREE from "three"; -import { HooksProps, MaterialProps } from "../../types"; -export interface HooksProps3D extends HooksProps { - /** For 3D series, you should use the r3f camera as it is as the camera passed to renderTarget. */ - camera: THREE.Camera; -} -export interface Create3DHooksProps extends MaterialProps { - /** You can put the r3f scene in, or if you don't want to add to any scene, you can pass nothing and it will just return the object without putting it in the scene, default : `false` */ - scene?: THREE.Scene | false; -} diff --git a/packages/use-shader-fx/types/fxs/3D/useMorphParticles/index.d.ts b/packages/use-shader-fx/types/fxs/3D/useMorphParticles/index.d.ts deleted file mode 100644 index 00a6fb0b..00000000 --- a/packages/use-shader-fx/types/fxs/3D/useMorphParticles/index.d.ts +++ /dev/null @@ -1,66 +0,0 @@ -import * as THREE from "three"; -import { HooksReturn } from "../../types"; -import { UseCreateMorphParticlesProps } from "./useCreateMorphParticles"; -import { HooksProps3D } from "../types"; -import { InteractiveMesh, MorphParticlePoints } from "./utils/useCreateObject"; -import { CustomParams } from "../../../utils/setUniforms"; -export type MorphParticlesParams = { - /** progress value to morph vertices,0~1 */ - morphProgress?: number; - blurAlpha?: number; - blurRadius?: number; - pointSize?: number; - /** default : `1` */ - pointAlpha?: number; - /** Since the color is extracted based on the attribute `uv`, the intended behavior will not occur if there is no uv in the attribute. */ - picture?: THREE.Texture | false; - /** The alpha map is a grayscale texture that controls the opacity across the surface (black: fully transparent; white: fully opaque). use the green channel when sampling this texture. It also affects the size of the point. default : `false` */ - alphaPicture?: THREE.Texture | false; - color0?: THREE.Color; - color1?: THREE.Color; - color2?: THREE.Color; - color3?: THREE.Color; - /** This maps to point,texture */ - map?: THREE.Texture | false; - /** The alpha map is a grayscale texture that controls the opacity across the surface (black: fully transparent; white: fully opaque). use the green channel when sampling this texture. default : `false` */ - alphaMap?: THREE.Texture | false; - /** If ​​wobbleStrength is set to 0, wobble will stop. It will also affect noise calculation, default : `0` */ - wobbleStrength?: number; - wobblePositionFrequency?: number; - wobbleTimeFrequency?: number; - /** default : `0` */ - warpStrength?: number; - warpPositionFrequency?: number; - warpTimeFrequency?: number; - /** Manipulate the vertices using the color channels of this texture. The strength of the displacement changes depending on the g channel of this texture */ - displacement?: THREE.Texture | false; - /** Strength of displacement. The strength of displacement depends on g ch, but is the value multiplied by it , default : `1` */ - displacementIntensity?: number; - /** Strength to reflect color ch of displacement texture */ - displacementColorIntensity?: number; - /** If set to 0, noise calculation stops, default : `0` */ - sizeRandomIntensity?: number; - sizeRandomTimeFrequency?: number; - sizeRandomMin?: number; - sizeRandomMax?: number; - /** Divergence rate of a point. Negative cases are dense, positive cases are divergent, default : `0` */ - divergence?: number; - /** Divergence centre point, default : `THREE.Vector3(0)` */ - divergencePoint?: THREE.Vector3; - /** you can get into the rhythm ♪ , default : `false` */ - beat?: number | false; -}; -export type MorphParticlesObject = { - scene: THREE.Scene; - points: MorphParticlePoints; - interactiveMesh: InteractiveMesh; - renderTarget: THREE.WebGLRenderTarget; - output: THREE.Texture; - positions: Float32Array[]; - uvs: Float32Array[]; -}; -export declare const MORPHPARTICLES_PARAMS: MorphParticlesParams; -/** - * @link https://github.com/FunTechInc/use-shader-fx - */ -export declare const useMorphParticles: ({ size, dpr, isSizeUpdate, renderTargetOptions, camera, geometry, positions, uvs, onBeforeInit, }: HooksProps3D & UseCreateMorphParticlesProps) => HooksReturn; diff --git a/packages/use-shader-fx/types/fxs/3D/useMorphParticles/useCreateMorphParticles.d.ts b/packages/use-shader-fx/types/fxs/3D/useMorphParticles/useCreateMorphParticles.d.ts deleted file mode 100644 index 6c36a5da..00000000 --- a/packages/use-shader-fx/types/fxs/3D/useMorphParticles/useCreateMorphParticles.d.ts +++ /dev/null @@ -1,29 +0,0 @@ -import * as THREE from "three"; -import { RootState } from "@react-three/fiber"; -import { InteractiveMesh, MorphParticlePoints } from "./utils/useCreateObject"; -import { MorphParticlesParams } from "."; -import { CustomParams } from "../../../utils/setUniforms"; -import { Create3DHooksProps } from "../types"; -import { Dpr, Size } from "../../types"; -export type UseCreateMorphParticlesProps = { - size: Size; - dpr: Dpr; - /** default : `THREE.SphereGeometry(1, 32, 32)` */ - geometry?: THREE.BufferGeometry; - positions?: Float32Array[]; - uvs?: Float32Array[]; - /** Array of textures to map to points. Mapped at random. */ - mapArray?: THREE.Texture[]; -}; -type UpdateUniform = (rootState: RootState | null, newParams?: MorphParticlesParams, customParams?: CustomParams) => void; -type UseCreateMorphParticlesReturn = [ - UpdateUniform, - { - points: MorphParticlePoints; - interactiveMesh: InteractiveMesh; - positions: Float32Array[]; - uvs: Float32Array[]; - } -]; -export declare const useCreateMorphParticles: ({ size, dpr, scene, geometry, positions, uvs, mapArray, onBeforeInit, }: Create3DHooksProps & UseCreateMorphParticlesProps) => UseCreateMorphParticlesReturn; -export {}; diff --git a/packages/use-shader-fx/types/fxs/3D/useMorphParticles/utils/modifyAttributes.d.ts b/packages/use-shader-fx/types/fxs/3D/useMorphParticles/utils/modifyAttributes.d.ts deleted file mode 100644 index 241902bc..00000000 --- a/packages/use-shader-fx/types/fxs/3D/useMorphParticles/utils/modifyAttributes.d.ts +++ /dev/null @@ -1,5 +0,0 @@ -import * as THREE from "three"; -/** - * Calculate the maximum length of attribute (position and uv) to match the length of all lists. Randomly map missing attributes when matching to maximum length - * */ -export declare const modifyAttributes: (attribute: Float32Array[] | undefined, targetGeometry: THREE.BufferGeometry, targetAttibute: "position" | "uv", itemSize: number) => Float32Array[]; diff --git a/packages/use-shader-fx/types/fxs/3D/useMorphParticles/utils/rewriteFragmentShader.d.ts b/packages/use-shader-fx/types/fxs/3D/useMorphParticles/utils/rewriteFragmentShader.d.ts deleted file mode 100644 index c46d824e..00000000 --- a/packages/use-shader-fx/types/fxs/3D/useMorphParticles/utils/rewriteFragmentShader.d.ts +++ /dev/null @@ -1,5 +0,0 @@ -import * as THREE from "three"; -export declare const rewriteFragmentShader: (mapArray: THREE.Texture[] | undefined, fragmentShader: string) => { - rewritedFragmentShader: string; - mapArrayUniforms: any; -}; diff --git a/packages/use-shader-fx/types/fxs/3D/useMorphParticles/utils/rewriteVertexShader.d.ts b/packages/use-shader-fx/types/fxs/3D/useMorphParticles/utils/rewriteVertexShader.d.ts deleted file mode 100644 index 90866e6c..00000000 --- a/packages/use-shader-fx/types/fxs/3D/useMorphParticles/utils/rewriteVertexShader.d.ts +++ /dev/null @@ -1,2 +0,0 @@ -import * as THREE from "three"; -export declare const rewriteVertexShader: (modifeidAttributes: Float32Array[], targetGeometry: THREE.BufferGeometry, targetAttibute: "position" | "uv", vertexShader: string, itemSize: number) => string; diff --git a/packages/use-shader-fx/types/fxs/3D/useMorphParticles/utils/useCreateObject.d.ts b/packages/use-shader-fx/types/fxs/3D/useMorphParticles/utils/useCreateObject.d.ts deleted file mode 100644 index b3ff18d9..00000000 --- a/packages/use-shader-fx/types/fxs/3D/useMorphParticles/utils/useCreateObject.d.ts +++ /dev/null @@ -1,13 +0,0 @@ -import * as THREE from "three"; -type UseCreateObjectProps = { - scene: THREE.Scene | false; - geometry: THREE.BufferGeometry; - material: THREE.ShaderMaterial; -}; -export type MorphParticlePoints = THREE.Points, THREE.ShaderMaterial>; -export type InteractiveMesh = THREE.Mesh, THREE.ShaderMaterial>; -export declare const useCreateObject: ({ scene, geometry, material, }: UseCreateObjectProps) => { - points: MorphParticlePoints; - interactiveMesh: InteractiveMesh; -}; -export {}; diff --git a/packages/use-shader-fx/types/fxs/3D/useMorphParticles/utils/useMaterial.d.ts b/packages/use-shader-fx/types/fxs/3D/useMorphParticles/utils/useMaterial.d.ts deleted file mode 100644 index 8f0ec7e1..00000000 --- a/packages/use-shader-fx/types/fxs/3D/useMorphParticles/utils/useMaterial.d.ts +++ /dev/null @@ -1,123 +0,0 @@ -import * as THREE from "three"; -import { MaterialProps, Size } from "../../../types"; -export declare class MorphParticlesMaterial extends THREE.ShaderMaterial { - uniforms: { - uResolution: { - value: THREE.Vector2; - }; - uMorphProgress: { - value: number; - }; - uBlurAlpha: { - value: number; - }; - uBlurRadius: { - value: number; - }; - uPointSize: { - value: number; - }; - uPointAlpha: { - value: number; - }; - uPicture: { - value: THREE.Texture; - }; - uIsPicture: { - value: boolean; - }; - uAlphaPicture: { - value: THREE.Texture; - }; - uIsAlphaPicture: { - value: boolean; - }; - uColor0: { - value: THREE.Color; - }; - uColor1: { - value: THREE.Color; - }; - uColor2: { - value: THREE.Color; - }; - uColor3: { - value: THREE.Color; - }; - uMap: { - value: THREE.Texture; - }; - uIsMap: { - value: boolean; - }; - uAlphaMap: { - value: THREE.Texture; - }; - uIsAlphaMap: { - value: boolean; - }; - uTime: { - value: number; - }; - uWobblePositionFrequency: { - value: number; - }; - uWobbleTimeFrequency: { - value: number; - }; - uWobbleStrength: { - value: number; - }; - uWarpPositionFrequency: { - value: number; - }; - uWarpTimeFrequency: { - value: number; - }; - uWarpStrength: { - value: number; - }; - uDisplacement: { - value: THREE.Texture; - }; - uIsDisplacement: { - value: boolean; - }; - uDisplacementIntensity: { - value: number; - }; - uDisplacementColorIntensity: { - value: number; - }; - uSizeRandomIntensity: { - value: number; - }; - uSizeRandomTimeFrequency: { - value: number; - }; - uSizeRandomMin: { - value: number; - }; - uSizeRandomMax: { - value: number; - }; - uDivergence: { - value: number; - }; - uDivergencePoint: { - value: THREE.Vector3; - }; - }; -} -export declare const useMaterial: ({ size, dpr, geometry, positions, uvs, mapArray, onBeforeInit, }: { - size: Size; - dpr: number | false; - geometry: THREE.BufferGeometry; - positions?: Float32Array[] | undefined; - uvs?: Float32Array[] | undefined; - mapArray?: THREE.Texture[] | undefined; -} & MaterialProps) => { - material: MorphParticlesMaterial; - modifiedPositions: Float32Array[]; - modifiedUvs: Float32Array[]; -}; diff --git a/packages/use-shader-fx/types/fxs/3D/useWobble3D/index.d.ts b/packages/use-shader-fx/types/fxs/3D/useWobble3D/index.d.ts deleted file mode 100644 index f14e080e..00000000 --- a/packages/use-shader-fx/types/fxs/3D/useWobble3D/index.d.ts +++ /dev/null @@ -1,56 +0,0 @@ -import * as THREE from "three"; -import { HooksReturn } from "../../types"; -import { UseCreateWobble3DProps } from "./useCreateWobble3D"; -import { WobbleMaterialProps, WobbleMaterialConstructor } from "./useMaterial"; -import { HooksProps3D } from "../types"; -import { CustomParams } from "../../../utils/setUniforms"; -export type Wobble3DParams = { - /** default : `0.3` */ - wobbleStrength?: number; - /** default : `0.3` */ - wobblePositionFrequency?: number; - /** default : `0.3` */ - wobbleTimeFrequency?: number; - /** default : `0.3` */ - warpStrength?: number; - /** default : `0.3` */ - warpPositionFrequency?: number; - /** default : `0.3` */ - warpTimeFrequency?: number; - color0?: THREE.Color; - color1?: THREE.Color; - color2?: THREE.Color; - color3?: THREE.Color; - /** Mixing ratio with the material's original output color, 0~1 , defaulat : `1` */ - colorMix?: number; - /** Threshold of edge. 0 for edge disabled, default : `0` */ - edgeThreshold?: number; - /** Color of edge. default : `0x000000` */ - edgeColor?: THREE.Color; - /** you can get into the rhythm ♪ , default : `false` */ - beat?: number | false; - /** valid only for `MeshPhysicalMaterial` && `isCustomTransmission:true` , default : `0.1` */ - chromaticAberration?: number; - /** valid only for `MeshPhysicalMaterial` && `isCustomTransmission:true` , default : `0.1` */ - anisotropicBlur?: number; - /** valid only for `MeshPhysicalMaterial` && `isCustomTransmission:true` , default : `0.0` */ - distortion?: number; - /** valid only for `MeshPhysicalMaterial` && `isCustomTransmission:true` , default : `0.1` */ - distortionScale?: number; - /** valid only for `MeshPhysicalMaterial` && `isCustomTransmission:true` , default : `0.0` */ - temporalDistortion?: number; - /** valid only for `MeshPhysicalMaterial` && `isCustomTransmission:true` , default : `6` */ - refractionSamples?: number; -}; -export type Wobble3DObject = { - scene: THREE.Scene; - mesh: THREE.Mesh; - depthMaterial: THREE.MeshDepthMaterial | null; - renderTarget: THREE.WebGLRenderTarget; - output: THREE.Texture; -}; -export declare const WOBBLE3D_PARAMS: Wobble3DParams; -/** - * @link https://github.com/FunTechInc/use-shader-fx - */ -export declare const useWobble3D: ({ size, dpr, renderTargetOptions, isSizeUpdate, camera, geometry, baseMaterial, materialParameters, isCustomTransmission, onBeforeInit, depthOnBeforeInit, depth, }: HooksProps3D & UseCreateWobble3DProps & WobbleMaterialProps) => HooksReturn; diff --git a/packages/use-shader-fx/types/fxs/3D/useWobble3D/useCreateWobble3D.d.ts b/packages/use-shader-fx/types/fxs/3D/useWobble3D/useCreateWobble3D.d.ts deleted file mode 100644 index 193a4117..00000000 --- a/packages/use-shader-fx/types/fxs/3D/useWobble3D/useCreateWobble3D.d.ts +++ /dev/null @@ -1,20 +0,0 @@ -import * as THREE from "three"; -import { RootState } from "@react-three/fiber"; -import { WobbleMaterialProps, WobbleMaterialConstructor } from "./useMaterial"; -import { Wobble3DParams } from "."; -import { CustomParams } from "../../../utils/setUniforms"; -import { Create3DHooksProps } from "../types"; -export type UseCreateWobble3DProps = { - /** default : `THREE.IcosahedronGeometry(2,20)` */ - geometry?: THREE.BufferGeometry; -}; -type UpdateUniform = (rootState: RootState | null, newParams?: Wobble3DParams, customParams?: CustomParams) => void; -type UseCreateWobble3DReturn = [ - UpdateUniform, - { - mesh: THREE.Mesh; - depthMaterial: THREE.MeshDepthMaterial | null; - } -]; -export declare const useCreateWobble3D: ({ scene, geometry, isCustomTransmission, baseMaterial, materialParameters, depth, onBeforeInit, depthOnBeforeInit, }: UseCreateWobble3DProps & Create3DHooksProps & WobbleMaterialProps) => UseCreateWobble3DReturn; -export {}; diff --git a/packages/use-shader-fx/types/fxs/3D/useWobble3D/useMaterial.d.ts b/packages/use-shader-fx/types/fxs/3D/useWobble3D/useMaterial.d.ts deleted file mode 100644 index e5c91386..00000000 --- a/packages/use-shader-fx/types/fxs/3D/useWobble3D/useMaterial.d.ts +++ /dev/null @@ -1,88 +0,0 @@ -import * as THREE from "three"; -import { MaterialProps, OnBeforeInitParameters } from "../../types"; -export declare class Wobble3DMaterial extends THREE.Material { - uniforms: { - uTime: { - value: number; - }; - uWobblePositionFrequency: { - value: number; - }; - uWobbleTimeFrequency: { - value: number; - }; - uWobbleStrength: { - value: number; - }; - uWarpPositionFrequency: { - value: number; - }; - uWarpTimeFrequency: { - value: number; - }; - uWarpStrength: { - value: number; - }; - uColor0: { - value: THREE.Color; - }; - uColor1: { - value: THREE.Color; - }; - uColor2: { - value: THREE.Color; - }; - uColor3: { - value: THREE.Color; - }; - uColorMix: { - value: number; - }; - uEdgeThreshold: { - value: number; - }; - uEdgeColor: { - value: THREE.Color; - }; - uChromaticAberration: { - value: number; - }; - uAnisotropicBlur: { - value: number; - }; - uDistortion: { - value: number; - }; - uDistortionScale: { - value: number; - }; - uTemporalDistortion: { - value: number; - }; - uRefractionSamples: { - value: number; - }; - }; -} -export type WobbleMaterialConstructor = new (opts: { - [key: string]: any; -}) => THREE.Material; -type WobbleMaterialParams = ConstructorParameters[0]; -export interface WobbleMaterialProps extends MaterialProps { - /** default:THREE.MeshPhysicalMaterial */ - baseMaterial?: T; - materialParameters?: WobbleMaterialParams; - depthOnBeforeInit?: (parameters: OnBeforeInitParameters) => void; - /** - * Whether to apply more advanced `transmission` or not. valid only for `MeshPhysicalMaterial`. This is a function referring to `drei/MeshTransmissionMaterial`, default : `false` - * @link https://github.com/pmndrs/drei?tab=readme-ov-file#meshtransmissionmaterial - * */ - isCustomTransmission?: boolean; - /** Whether to initialise `MeshDepthMaterial` or not , default : `false` */ - depth?: boolean; -} -export declare const useMaterial: ({ baseMaterial, materialParameters, isCustomTransmission, onBeforeInit, depthOnBeforeInit, depth, }: WobbleMaterialProps) => { - material: Wobble3DMaterial; - depthMaterial: THREE.MeshDepthMaterial | null; -}; -export {}; diff --git a/packages/use-shader-fx/types/fxs/3D/useWobble3D/utils/resolveEachMaterial.d.ts b/packages/use-shader-fx/types/fxs/3D/useWobble3D/utils/resolveEachMaterial.d.ts deleted file mode 100644 index 9e4975f1..00000000 --- a/packages/use-shader-fx/types/fxs/3D/useWobble3D/utils/resolveEachMaterial.d.ts +++ /dev/null @@ -1,6 +0,0 @@ -import * as THREE from "three"; -export declare const resolveEachMaterial: ({ mat, isCustomTransmission, parameters, }: { - mat: THREE.Material; - isCustomTransmission: boolean; - parameters: THREE.WebGLProgramParametersWithUniforms; -}) => void; diff --git a/packages/use-shader-fx/types/fxs/3D/useWobble3D/utils/rewriteFragmentShader.d.ts b/packages/use-shader-fx/types/fxs/3D/useWobble3D/utils/rewriteFragmentShader.d.ts deleted file mode 100644 index 0d5994e6..00000000 --- a/packages/use-shader-fx/types/fxs/3D/useWobble3D/utils/rewriteFragmentShader.d.ts +++ /dev/null @@ -1,2 +0,0 @@ -import * as THREE from "three"; -export declare const rewriteFragmentShader: (parameters: THREE.WebGLProgramParametersWithUniforms) => void; diff --git a/packages/use-shader-fx/types/fxs/3D/useWobble3D/utils/rewriteVertexShader.d.ts b/packages/use-shader-fx/types/fxs/3D/useWobble3D/utils/rewriteVertexShader.d.ts deleted file mode 100644 index 5292a364..00000000 --- a/packages/use-shader-fx/types/fxs/3D/useWobble3D/utils/rewriteVertexShader.d.ts +++ /dev/null @@ -1,2 +0,0 @@ -import * as THREE from "three"; -export declare const rewriteVertexShader: (parameters: THREE.WebGLProgramParametersWithUniforms) => void; diff --git a/packages/use-shader-fx/types/fxs/blank/useBlank/index.d.ts b/packages/use-shader-fx/types/fxs/blank/useBlank/index.d.ts deleted file mode 100644 index 82f30972..00000000 --- a/packages/use-shader-fx/types/fxs/blank/useBlank/index.d.ts +++ /dev/null @@ -1,30 +0,0 @@ -import * as THREE from "three"; -import { BlankMaterial } from "./useMesh"; -import { DoubleRenderTarget } from "../../../utils/useDoubleFBO"; -import { CustomParams } from "../../../utils/setUniforms"; -import type { HooksProps, HooksReturn } from "../../types"; -export type BlankParams = { - /** texture, default : `THREE.Texture()` */ - texture?: THREE.Texture; - /** you can get into the rhythm ♪ , default : `false` */ - beat?: number | false; -}; -export type BlankObject = { - scene: THREE.Scene; - mesh: THREE.Mesh, BlankMaterial>; - material: BlankMaterial; - camera: THREE.Camera; - renderTarget: DoubleRenderTarget; - output: THREE.Texture; -}; -export declare const BLANK_PARAMS: BlankParams; -/** - * By default, it is a blank canvas with nothing drawn on it. You can customise the shaders using `onBeforeCompile`. - * Fragment shaders have `uTexture`,`uBackbuffer`,`uTime`,`uPointer` and `uResolution` as default uniforms. - * - * ※ `usf_FragColor` overrides `gl_FragColor` - * - * ※ `usf_Position` overrides `gl_Position` - * @link https://github.com/FunTechInc/use-shader-fx?tab=readme-ov-file#usage - */ -export declare const useBlank: ({ size, dpr, renderTargetOptions, isSizeUpdate, onBeforeInit, }: HooksProps) => HooksReturn; diff --git a/packages/use-shader-fx/types/fxs/blank/useBlank/useMesh.d.ts b/packages/use-shader-fx/types/fxs/blank/useBlank/useMesh.d.ts deleted file mode 100644 index c155da6e..00000000 --- a/packages/use-shader-fx/types/fxs/blank/useBlank/useMesh.d.ts +++ /dev/null @@ -1,29 +0,0 @@ -import * as THREE from "three"; -import { MaterialProps, Size } from "../../types"; -export declare class BlankMaterial extends THREE.ShaderMaterial { - uniforms: { - uTexture: { - value: THREE.Texture; - }; - uBackbuffer: { - value: THREE.Texture; - }; - uTime: { - value: number; - }; - uPointer: { - value: THREE.Vector2; - }; - uResolution: { - value: THREE.Vector2; - }; - }; -} -export declare const useMesh: ({ scene, size, dpr, onBeforeInit, }: { - scene: THREE.Scene; - size: Size; - dpr: number | false; -} & MaterialProps) => { - material: BlankMaterial; - mesh: THREE.Mesh, BlankMaterial, THREE.Object3DEventMap>; -}; diff --git a/packages/use-shader-fx/types/fxs/blank/useRawBlank/index.d.ts b/packages/use-shader-fx/types/fxs/blank/useRawBlank/index.d.ts deleted file mode 100644 index dba38ea9..00000000 --- a/packages/use-shader-fx/types/fxs/blank/useRawBlank/index.d.ts +++ /dev/null @@ -1,37 +0,0 @@ -import * as THREE from "three"; -import { RawBlankMaterial } from "./useMesh"; -import { CustomParams } from "../../../utils/setUniforms"; -import type { HooksProps, HooksReturn } from "../../types"; -export type RawBlankParams = {}; -export type RawBlankObject = { - scene: THREE.Scene; - mesh: THREE.Mesh, RawBlankMaterial>; - material: RawBlankMaterial; - camera: THREE.Camera; - renderTarget: THREE.WebGLRenderTarget; - output: THREE.Texture; -}; -export declare const RAWBLANK_PARAMS: RawBlankParams; -/** - * By default, it is a blank canvas with nothing drawn on it. You can customise the shaders using `onBeforeCompile`. - * Fragment shaders have `uResolution` as default uniforms. - * - * ※ `usf_FragColor` overrides `gl_FragColor` - * - * ※ `usf_Position` overrides `gl_Position` - * - * `RawBlankParams` is an empty object. so you can't pass any parameters to second argument. Nothing will happen if you pass them. - * ```tsx - * useFrame((state) => { - update( - state, - {}, - { - uTime: state.clock.getElapsedTime(), - } - ); - }); - * ``` - * @link https://github.com/FunTechInc/use-shader-fx?tab=readme-ov-file#usage - */ -export declare const useRawBlank: ({ size, dpr, renderTargetOptions, isSizeUpdate, onBeforeInit, }: HooksProps) => HooksReturn; diff --git a/packages/use-shader-fx/types/fxs/blank/useRawBlank/useMesh.d.ts b/packages/use-shader-fx/types/fxs/blank/useRawBlank/useMesh.d.ts deleted file mode 100644 index 7cb21f71..00000000 --- a/packages/use-shader-fx/types/fxs/blank/useRawBlank/useMesh.d.ts +++ /dev/null @@ -1,17 +0,0 @@ -import * as THREE from "three"; -import { MaterialProps, Size } from "../../types"; -export declare class RawBlankMaterial extends THREE.ShaderMaterial { - uniforms: { - uResolution: { - value: THREE.Vector2; - }; - }; -} -export declare const useMesh: ({ scene, size, dpr, onBeforeInit, }: { - scene: THREE.Scene; - size: Size; - dpr: number | false; -} & MaterialProps) => { - material: RawBlankMaterial; - mesh: THREE.Mesh, RawBlankMaterial, THREE.Object3DEventMap>; -}; diff --git a/packages/use-shader-fx/types/fxs/effects/useMotionBlur/index.d.ts b/packages/use-shader-fx/types/fxs/effects/useMotionBlur/index.d.ts deleted file mode 100644 index f23e6f3e..00000000 --- a/packages/use-shader-fx/types/fxs/effects/useMotionBlur/index.d.ts +++ /dev/null @@ -1,27 +0,0 @@ -import * as THREE from "three"; -import { DoubleRenderTarget } from "../../../utils/useDoubleFBO"; -import { CustomParams } from "../../../utils/setUniforms"; -import type { HooksProps, HooksReturn } from "../../types"; -export type MotionBlurParams = { - /** Make this texture blur, default : `THREE.Texture()` */ - texture?: THREE.Texture; - /** motion begin, default : `THREE.Vector2(0, 0)` */ - begin?: THREE.Vector2; - /** motion end, default : `THREE.Vector2(0, 0)` */ - end?: THREE.Vector2; - /** motion strength, default : `0.9` */ - strength?: number; -}; -export type MotionBlurObject = { - scene: THREE.Scene; - mesh: THREE.Mesh; - material: THREE.Material; - camera: THREE.Camera; - renderTarget: DoubleRenderTarget; - output: THREE.Texture; -}; -export declare const MOTIONBLUR_PARAMS: MotionBlurParams; -/** - * @link https://github.com/FunTechInc/use-shader-fx?tab=readme-ov-file#usage - */ -export declare const useMotionBlur: ({ size, dpr, renderTargetOptions, isSizeUpdate, onBeforeInit, }: HooksProps) => HooksReturn; diff --git a/packages/use-shader-fx/types/fxs/effects/useMotionBlur/useMesh.d.ts b/packages/use-shader-fx/types/fxs/effects/useMotionBlur/useMesh.d.ts deleted file mode 100644 index 03518e41..00000000 --- a/packages/use-shader-fx/types/fxs/effects/useMotionBlur/useMesh.d.ts +++ /dev/null @@ -1,27 +0,0 @@ -import * as THREE from "three"; -import { MaterialProps } from "../../types"; -export declare class MotionBlurMaterial extends THREE.ShaderMaterial { - uniforms: { - uTexture: { - value: THREE.Texture; - }; - uBackbuffer: { - value: THREE.Texture; - }; - uBegin: { - value: THREE.Vector2; - }; - uEnd: { - value: THREE.Vector2; - }; - uStrength: { - value: number; - }; - }; -} -export declare const useMesh: ({ scene, onBeforeInit, }: { - scene: THREE.Scene; -} & MaterialProps) => { - material: MotionBlurMaterial; - mesh: THREE.Mesh, MotionBlurMaterial, THREE.Object3DEventMap>; -}; diff --git a/packages/use-shader-fx/types/fxs/effects/useSimpleBlur/index.d.ts b/packages/use-shader-fx/types/fxs/effects/useSimpleBlur/index.d.ts deleted file mode 100644 index 4e495940..00000000 --- a/packages/use-shader-fx/types/fxs/effects/useSimpleBlur/index.d.ts +++ /dev/null @@ -1,25 +0,0 @@ -import * as THREE from "three"; -import { DoubleRenderTarget } from "../../../utils/useDoubleFBO"; -import { CustomParams } from "../../../utils/setUniforms"; -import type { HooksProps, HooksReturn } from "../../types"; -export type SimpleBlurParams = { - /** Make this texture blur , default : `THREE.Texture()` */ - texture?: THREE.Texture; - /** blurSize, default : `3` */ - blurSize?: number; - /** blurPower, affects performance default : `5` */ - blurPower?: number; -}; -export type SimpleBlurObject = { - scene: THREE.Scene; - mesh: THREE.Mesh; - material: THREE.Material; - camera: THREE.Camera; - renderTarget: DoubleRenderTarget; - output: THREE.Texture; -}; -export declare const SIMPLEBLUR_PARAMS: SimpleBlurParams; -/** - * @link https://github.com/FunTechInc/use-shader-fx?tab=readme-ov-file#usage - */ -export declare const useSimpleBlur: ({ size, dpr, renderTargetOptions, isSizeUpdate, onBeforeInit, }: HooksProps) => HooksReturn; diff --git a/packages/use-shader-fx/types/fxs/effects/useSimpleBlur/useMesh.d.ts b/packages/use-shader-fx/types/fxs/effects/useSimpleBlur/useMesh.d.ts deleted file mode 100644 index 0c56bfc7..00000000 --- a/packages/use-shader-fx/types/fxs/effects/useSimpleBlur/useMesh.d.ts +++ /dev/null @@ -1,21 +0,0 @@ -import * as THREE from "three"; -import { MaterialProps } from "../../types"; -export declare class SampleMaterial extends THREE.ShaderMaterial { - uniforms: { - uTexture: { - value: THREE.Texture; - }; - uResolution: { - value: THREE.Vector2; - }; - uBlurSize: { - value: number; - }; - }; -} -export declare const useMesh: ({ scene, onBeforeInit, }: { - scene: THREE.Scene; -} & MaterialProps) => { - material: SampleMaterial; - mesh: THREE.Mesh, SampleMaterial, THREE.Object3DEventMap>; -}; diff --git a/packages/use-shader-fx/types/fxs/effects/useWave/index.d.ts b/packages/use-shader-fx/types/fxs/effects/useWave/index.d.ts deleted file mode 100644 index c4321d0d..00000000 --- a/packages/use-shader-fx/types/fxs/effects/useWave/index.d.ts +++ /dev/null @@ -1,28 +0,0 @@ -import * as THREE from "three"; -import { CustomParams } from "../../../utils/setUniforms"; -import { HooksProps, HooksReturn } from "../../types"; -export type WaveParams = { - /** -1.0 ~ 1.0 , default : `vec2(0.0,0.0)` */ - epicenter?: THREE.Vector2; - /** 0.0 ~ 1.0 , default : `0.0` */ - progress?: number; - /** default : `0.0` */ - width?: number; - /** default : `0.0` */ - strength?: number; - /** default : `center` */ - mode?: "center" | "horizontal" | "vertical"; -}; -export type WaveObject = { - scene: THREE.Scene; - mesh: THREE.Mesh; - material: THREE.Material; - camera: THREE.Camera; - renderTarget: THREE.WebGLRenderTarget; - output: THREE.Texture; -}; -export declare const WAVE_PARAMS: WaveParams; -/** - * @link https://github.com/FunTechInc/use-shader-fx - */ -export declare const useWave: ({ size, dpr, renderTargetOptions, isSizeUpdate, onBeforeInit, }: HooksProps) => HooksReturn; diff --git a/packages/use-shader-fx/types/fxs/effects/useWave/useMesh.d.ts b/packages/use-shader-fx/types/fxs/effects/useWave/useMesh.d.ts deleted file mode 100644 index f0852d01..00000000 --- a/packages/use-shader-fx/types/fxs/effects/useWave/useMesh.d.ts +++ /dev/null @@ -1,27 +0,0 @@ -import * as THREE from "three"; -import { MaterialProps } from "../../types"; -export declare class WaveMaterial extends THREE.ShaderMaterial { - uniforms: { - uEpicenter: { - value: THREE.Vector2; - }; - uProgress: { - value: number; - }; - uStrength: { - value: number; - }; - uWidth: { - value: number; - }; - uMode: { - value: number; - }; - }; -} -export declare const useMesh: ({ scene, onBeforeInit, }: { - scene: THREE.Scene; -} & MaterialProps) => { - material: WaveMaterial; - mesh: THREE.Mesh, WaveMaterial, THREE.Object3DEventMap>; -}; diff --git a/packages/use-shader-fx/types/fxs/interactions/useBrush/index.d.ts b/packages/use-shader-fx/types/fxs/interactions/useBrush/index.d.ts deleted file mode 100644 index 2f5e7c6f..00000000 --- a/packages/use-shader-fx/types/fxs/interactions/useBrush/index.d.ts +++ /dev/null @@ -1,44 +0,0 @@ -import * as THREE from "three"; -import { PointerValues } from "../../../misc/usePointer"; -import { CustomParams } from "../../../utils/setUniforms"; -import { HooksProps, HooksReturn } from "../../types"; -import { DoubleRenderTarget } from "../../../utils/useDoubleFBO"; -export type BrushParams = { - /** Texture applied to the brush, If texture is true, it will take precedence over color , default : `false` */ - texture?: THREE.Texture | false; - /** You can attach an fx map , default : `false` */ - map?: THREE.Texture | false; - /** map intensity , default : `0.1` */ - mapIntensity?: number; - /** size of the stamp, percentage of the size ,default : `0.05` */ - radius?: number; - /** Strength of smudge effect , default : `0.0`*/ - smudge?: number; - /** dissipation rate. If set to 1, it will remain. , default : `1.0` */ - dissipation?: number; - /** Strength of motion blur , default : `0.0` */ - motionBlur?: number; - /** Number of motion blur samples. Affects performance default : `5` */ - motionSample?: number; - /** brush color , it accepts a function that returns THREE.Vector3.The function takes velocity:THREE.Vector2 as an argument. , default : `THREE.Vector3(1.0, 1.0, 1.0)` */ - color?: ((velocity: THREE.Vector2) => THREE.Vector3) | THREE.Vector3 | THREE.Color; - /** Follows the cursor even if it loses speed , default : `false` */ - isCursor?: boolean; - /** brush pressure (0 to 1) , default : `1.0` */ - pressure?: number; - /** When calling usePointer in a frame loop, setting PointerValues ​​to this value prevents double calls , default : `false` */ - pointerValues?: PointerValues | false; -}; -export type BrushObject = { - scene: THREE.Scene; - mesh: THREE.Mesh; - material: THREE.Material; - camera: THREE.Camera; - renderTarget: DoubleRenderTarget; - output: THREE.Texture; -}; -export declare const BRUSH_PARAMS: BrushParams; -/** - * @link https://github.com/FunTechInc/use-shader-fx?tab=readme-ov-file#usage - */ -export declare const useBrush: ({ size, dpr, renderTargetOptions, isSizeUpdate, onBeforeInit, }: HooksProps) => HooksReturn; diff --git a/packages/use-shader-fx/types/fxs/interactions/useBrush/useMesh.d.ts b/packages/use-shader-fx/types/fxs/interactions/useBrush/useMesh.d.ts deleted file mode 100644 index c7bec4a8..00000000 --- a/packages/use-shader-fx/types/fxs/interactions/useBrush/useMesh.d.ts +++ /dev/null @@ -1,71 +0,0 @@ -import * as THREE from "three"; -import { MaterialProps, Size } from "../../types"; -export declare class BrushMaterial extends THREE.ShaderMaterial { - uniforms: { - uBuffer: { - value: THREE.Texture; - }; - uTexture: { - value: THREE.Texture; - }; - uIsTexture: { - value: boolean; - }; - uMap: { - value: THREE.Texture; - }; - uIsMap: { - value: boolean; - }; - uMapIntensity: { - value: number; - }; - uResolution: { - value: THREE.Vector2; - }; - uRadius: { - value: number; - }; - uSmudge: { - value: number; - }; - uDissipation: { - value: number; - }; - uMotionBlur: { - value: number; - }; - uMotionSample: { - value: number; - }; - uMouse: { - value: number; - }; - uPrevMouse: { - value: number; - }; - uVelocity: { - value: number; - }; - uColor: { - value: THREE.Vector3 | THREE.Color; - }; - uIsCursor: { - value: boolean; - }; - uPressureStart: { - value: number; - }; - uPressureEnd: { - value: number; - }; - }; -} -export declare const useMesh: ({ scene, size, dpr, onBeforeInit, }: { - scene: THREE.Scene; - size: Size; - dpr: number | false; -} & MaterialProps) => { - material: BrushMaterial; - mesh: THREE.Mesh, BrushMaterial, THREE.Object3DEventMap>; -}; diff --git a/packages/use-shader-fx/types/fxs/misc/useChromaKey/index.d.ts b/packages/use-shader-fx/types/fxs/misc/useChromaKey/index.d.ts deleted file mode 100644 index d495d93b..00000000 --- a/packages/use-shader-fx/types/fxs/misc/useChromaKey/index.d.ts +++ /dev/null @@ -1,36 +0,0 @@ -import * as THREE from "three"; -import { CustomParams } from "../../../utils/setUniforms"; -import { HooksProps, HooksReturn } from "../../types"; -export type ChromaKeyParams = { - /** Process this texture with chroma key , default : `THREE.Texture` */ - texture?: THREE.Texture; - /** key color for chromakey processing , default: `THREE.Color(0x00ff00)` */ - keyColor?: THREE.Color; - /** If the similarity with the key color exceeds this value, it becomes transparent. , default : `0.2` */ - similarity?: number; - /** smoothness , default : `0.1` */ - smoothness?: number; - /** spill , default : `0.2` */ - spill?: number; - /** tone correction , default : `THREE.Vector4(1.0, 1.0, 1.0, 1.0)` */ - color?: THREE.Vector4; - /** contrast , default : `1.0` */ - contrast?: number; - /** brightness , default : `0.0` */ - brightness?: number; - /** gamma correction , default : `1.0` */ - gamma?: number; -}; -export type ChromaKeyObject = { - scene: THREE.Scene; - mesh: THREE.Mesh; - material: THREE.Material; - camera: THREE.Camera; - renderTarget: THREE.WebGLRenderTarget; - output: THREE.Texture; -}; -export declare const CHROMAKEY_PARAMS: ChromaKeyParams; -/** - * @link https://github.com/FunTechInc/use-shader-fx?tab=readme-ov-file#usage - */ -export declare const useChromaKey: ({ size, dpr, renderTargetOptions, isSizeUpdate, onBeforeInit, }: HooksProps) => HooksReturn; diff --git a/packages/use-shader-fx/types/fxs/misc/useChromaKey/useMesh.d.ts b/packages/use-shader-fx/types/fxs/misc/useChromaKey/useMesh.d.ts deleted file mode 100644 index 5db856df..00000000 --- a/packages/use-shader-fx/types/fxs/misc/useChromaKey/useMesh.d.ts +++ /dev/null @@ -1,44 +0,0 @@ -import * as THREE from "three"; -import { MaterialProps, Size } from "../../types"; -export declare class ChromaKeyMaterial extends THREE.ShaderMaterial { - uniforms: { - u_texture: { - value: THREE.Texture; - }; - u_resolution: { - value: THREE.Vector2; - }; - u_keyColor: { - value: THREE.Color; - }; - u_similarity: { - value: number; - }; - u_smoothness: { - value: number; - }; - u_spill: { - value: number; - }; - u_color: { - value: THREE.Vector4; - }; - u_contrast: { - value: number; - }; - u_brightness: { - value: number; - }; - u_gamma: { - value: number; - }; - }; -} -export declare const useMesh: ({ scene, size, dpr, onBeforeInit, }: { - scene: THREE.Scene; - size: Size; - dpr: number | false; -} & MaterialProps) => { - material: ChromaKeyMaterial; - mesh: THREE.Mesh, ChromaKeyMaterial, THREE.Object3DEventMap>; -}; diff --git a/packages/use-shader-fx/types/fxs/noises/useColorStrata/index.d.ts b/packages/use-shader-fx/types/fxs/noises/useColorStrata/index.d.ts deleted file mode 100644 index c3697d6c..00000000 --- a/packages/use-shader-fx/types/fxs/noises/useColorStrata/index.d.ts +++ /dev/null @@ -1,40 +0,0 @@ -import * as THREE from "three"; -import { CustomParams } from "../../../utils/setUniforms"; -import { HooksProps, HooksReturn } from "../../types"; -export type ColorStrataParams = { - /** default : `null` */ - texture?: THREE.Texture | false; - /** Valid when texture is false. default : `1` */ - scale?: number; - /** default : `1.0` */ - laminateLayer?: number; - /** default : `(0.1, 0.1)` */ - laminateInterval?: THREE.Vector2; - /** default : `(1.0, 1.0)` */ - laminateDetail?: THREE.Vector2; - /** default : `(0.0, 0.0)` */ - distortion?: THREE.Vector2; - /** default : `(1.0, 1.0, 1.0)` */ - colorFactor?: THREE.Vector3; - /** default : `(0.0, 0.0)` */ - timeStrength?: THREE.Vector2; - /** default : `false` */ - noise?: THREE.Texture | false; - /** default : `(0.0,0.0)` */ - noiseStrength?: THREE.Vector2; - /** you can get into the rhythm ♪ , default : `false` */ - beat?: number | false; -}; -export type ColorStrataObject = { - scene: THREE.Scene; - mesh: THREE.Mesh; - material: THREE.Material; - camera: THREE.Camera; - renderTarget: THREE.WebGLRenderTarget; - output: THREE.Texture; -}; -export declare const COLORSTRATA_PARAMS: ColorStrataParams; -/** - * @link https://github.com/FunTechInc/use-shader-fx?tab=readme-ov-file#usage - */ -export declare const useColorStrata: ({ size, dpr, renderTargetOptions, isSizeUpdate, onBeforeInit, }: HooksProps) => HooksReturn; diff --git a/packages/use-shader-fx/types/fxs/noises/useColorStrata/useMesh.d.ts b/packages/use-shader-fx/types/fxs/noises/useColorStrata/useMesh.d.ts deleted file mode 100644 index c37211b1..00000000 --- a/packages/use-shader-fx/types/fxs/noises/useColorStrata/useMesh.d.ts +++ /dev/null @@ -1,51 +0,0 @@ -import * as THREE from "three"; -import { MaterialProps } from "../../types"; -export declare class ColorStrataMaterial extends THREE.ShaderMaterial { - uniforms: { - uTexture: { - value: THREE.Texture; - }; - isTexture: { - value: boolean; - }; - scale: { - value: number; - }; - noise: { - value: THREE.Texture; - }; - noiseStrength: { - value: THREE.Vector2; - }; - isNoise: { - value: boolean; - }; - laminateLayer: { - value: number; - }; - laminateInterval: { - value: THREE.Vector2; - }; - laminateDetail: { - value: THREE.Vector2; - }; - distortion: { - value: THREE.Vector2; - }; - colorFactor: { - value: THREE.Vector3; - }; - uTime: { - value: number; - }; - timeStrength: { - value: THREE.Vector2; - }; - }; -} -export declare const useMesh: ({ scene, onBeforeInit, }: { - scene: THREE.Scene; -} & MaterialProps) => { - material: ColorStrataMaterial; - mesh: THREE.Mesh, ColorStrataMaterial, THREE.Object3DEventMap>; -}; diff --git a/packages/use-shader-fx/types/fxs/noises/useCosPalette/index.d.ts b/packages/use-shader-fx/types/fxs/noises/useCosPalette/index.d.ts deleted file mode 100644 index cccbfeb3..00000000 --- a/packages/use-shader-fx/types/fxs/noises/useCosPalette/index.d.ts +++ /dev/null @@ -1,30 +0,0 @@ -import * as THREE from "three"; -import { CustomParams } from "../../../utils/setUniforms"; -import { HooksProps, HooksReturn } from "../../types"; -export type CosPaletteParams = { - /** color1, default : `rgb(50%, 50%, 50%)` */ - color1?: THREE.Color; - /** color2, default : `rgb(50%, 50%, 50%)` */ - color2?: THREE.Color; - /** color3, default : `rgb(100%, 100%, 100%)` */ - color3?: THREE.Color; - /** color4, default : `rgb(0%, 10%, 20%)` */ - color4?: THREE.Color; - /** texture to be used as a palette */ - texture?: THREE.Texture; - /** weight of the rgb, default : `THREE.Vector3(1.0,0.0,0.0)` */ - rgbWeight?: THREE.Vector3; -}; -export type ColorPaletteObject = { - scene: THREE.Scene; - mesh: THREE.Mesh; - material: THREE.Material; - camera: THREE.Camera; - renderTarget: THREE.WebGLRenderTarget; - output: THREE.Texture; -}; -export declare const COSPALETTE_PARAMS: CosPaletteParams; -/** - * @link https://github.com/FunTechInc/use-shader-fx?tab=readme-ov-file#usage - */ -export declare const useCosPalette: ({ size, dpr, renderTargetOptions, isSizeUpdate, onBeforeInit, }: HooksProps) => HooksReturn; diff --git a/packages/use-shader-fx/types/fxs/noises/useCosPalette/useMesh.d.ts b/packages/use-shader-fx/types/fxs/noises/useCosPalette/useMesh.d.ts deleted file mode 100644 index 9d4f03f8..00000000 --- a/packages/use-shader-fx/types/fxs/noises/useCosPalette/useMesh.d.ts +++ /dev/null @@ -1,30 +0,0 @@ -import * as THREE from "three"; -import { MaterialProps } from "../../types"; -export declare class CosPaletteMaterial extends THREE.ShaderMaterial { - uniforms: { - uTexture: { - value: THREE.Texture; - }; - uRgbWeight: { - value: THREE.Vector3; - }; - uColor1: { - value: THREE.Color; - }; - uColor2: { - value: THREE.Color; - }; - uColor3: { - value: THREE.Color; - }; - uColor4: { - value: THREE.Color; - }; - }; -} -export declare const useMesh: ({ scene, onBeforeInit, }: { - scene: THREE.Scene; -} & MaterialProps) => { - material: CosPaletteMaterial; - mesh: THREE.Mesh, CosPaletteMaterial, THREE.Object3DEventMap>; -}; diff --git a/packages/use-shader-fx/types/fxs/noises/useMarble/index.d.ts b/packages/use-shader-fx/types/fxs/noises/useMarble/index.d.ts deleted file mode 100644 index 5516e108..00000000 --- a/packages/use-shader-fx/types/fxs/noises/useMarble/index.d.ts +++ /dev/null @@ -1,32 +0,0 @@ -import * as THREE from "three"; -import { CustomParams } from "../../../utils/setUniforms"; -import { HooksProps, HooksReturn } from "../../types"; -export type MarbleParams = { - /** You can add random patterns to noise by passing random numbers ,default : `0` */ - pattern?: number; - /** default : `2` */ - complexity?: number; - /** default : `0.2` */ - complexityAttenuation?: number; - /** default : `8` */ - iterations?: number; - /** default : `0.2` */ - timeStrength?: number; - /** default : `0.002` */ - scale?: number; - /** you can get into the rhythm ♪ , default : `false` */ - beat?: number | false; -}; -export type MarbleObject = { - scene: THREE.Scene; - mesh: THREE.Mesh; - material: THREE.Material; - camera: THREE.Camera; - renderTarget: THREE.WebGLRenderTarget; - output: THREE.Texture; -}; -export declare const MARBLE_PARAMS: MarbleParams; -/** - * @link https://github.com/FunTechInc/use-shader-fx?tab=readme-ov-file#usage - */ -export declare const useMarble: ({ size, dpr, renderTargetOptions, isSizeUpdate, onBeforeInit, }: HooksProps) => HooksReturn; diff --git a/packages/use-shader-fx/types/fxs/noises/useMarble/useMesh.d.ts b/packages/use-shader-fx/types/fxs/noises/useMarble/useMesh.d.ts deleted file mode 100644 index c0ef7e18..00000000 --- a/packages/use-shader-fx/types/fxs/noises/useMarble/useMesh.d.ts +++ /dev/null @@ -1,33 +0,0 @@ -import * as THREE from "three"; -import { MaterialProps } from "../../types"; -export declare class MarbleMaterial extends THREE.ShaderMaterial { - uniforms: { - u_time: { - value: number; - }; - u_pattern: { - value: number; - }; - u_complexity: { - value: number; - }; - u_complexityAttenuation: { - value: number; - }; - u_iterations: { - value: number; - }; - u_timeStrength: { - value: number; - }; - u_scale: { - value: number; - }; - }; -} -export declare const useMesh: ({ scene, onBeforeInit, }: { - scene: THREE.Scene; -} & MaterialProps) => { - material: MarbleMaterial; - mesh: THREE.Mesh, MarbleMaterial, THREE.Object3DEventMap>; -}; diff --git a/packages/use-shader-fx/types/fxs/noises/useNoise/index.d.ts b/packages/use-shader-fx/types/fxs/noises/useNoise/index.d.ts deleted file mode 100644 index d0075a61..00000000 --- a/packages/use-shader-fx/types/fxs/noises/useNoise/index.d.ts +++ /dev/null @@ -1,36 +0,0 @@ -import * as THREE from "three"; -import { CustomParams } from "../../../utils/setUniforms"; -import { HooksProps, HooksReturn } from "../../types"; -export type NoiseParams = { - /** noise scale , default : `0.004` */ - scale?: number; - /** time factor default : `0.3` */ - timeStrength?: number; - /** noiseOctaves, affects performance default : `2` */ - noiseOctaves?: number; - /** fbmOctaves, affects performance default : `2` */ - fbmOctaves?: number; - /** domain warping octaves , affects performance default : `2` */ - warpOctaves?: number; - /** direction of domain warping , default : `(2.0,2,0)` */ - warpDirection?: THREE.Vector2; - /** strength of domain warping , default : `8.0` */ - warpStrength?: number; - /** you can get into the rhythm ♪ , default : `false` */ - beat?: number | false; -}; -export type NoiseObject = { - scene: THREE.Scene; - mesh: THREE.Mesh; - material: THREE.Material; - camera: THREE.Camera; - renderTarget: THREE.WebGLRenderTarget; - output: THREE.Texture; -}; -export declare const NOISE_PARAMS: NoiseParams; -/** - * @link https://github.com/FunTechInc/use-shader-fx?tab=readme-ov-file#usage - * - * It is a basic value noise with `fbm` and `domain warping` - */ -export declare const useNoise: ({ size, dpr, renderTargetOptions, isSizeUpdate, onBeforeInit, }: HooksProps) => HooksReturn; diff --git a/packages/use-shader-fx/types/fxs/noises/useNoise/useMesh.d.ts b/packages/use-shader-fx/types/fxs/noises/useNoise/useMesh.d.ts deleted file mode 100644 index 4ec1ff06..00000000 --- a/packages/use-shader-fx/types/fxs/noises/useNoise/useMesh.d.ts +++ /dev/null @@ -1,36 +0,0 @@ -import * as THREE from "three"; -import { MaterialProps } from "../../types"; -export declare class NoiseMaterial extends THREE.ShaderMaterial { - uniforms: { - uTime: { - value: number; - }; - scale: { - value: number; - }; - timeStrength: { - value: number; - }; - noiseOctaves: { - value: number; - }; - fbmOctaves: { - value: number; - }; - warpOctaves: { - value: number; - }; - warpDirection: { - value: THREE.Vector2; - }; - warpStrength: { - value: number; - }; - }; -} -export declare const useMesh: ({ scene, onBeforeInit, }: { - scene: THREE.Scene; -} & MaterialProps) => { - material: NoiseMaterial; - mesh: THREE.Mesh, NoiseMaterial, THREE.Object3DEventMap>; -}; diff --git a/packages/use-shader-fx/types/fxs/simulations/useFluid/index.d.ts b/packages/use-shader-fx/types/fxs/simulations/useFluid/index.d.ts deleted file mode 100644 index ad0696cb..00000000 --- a/packages/use-shader-fx/types/fxs/simulations/useFluid/index.d.ts +++ /dev/null @@ -1,56 +0,0 @@ -import * as THREE from "three"; -import { FluidMaterials, CustomFluidProps, CustomFluidParams } from "./useMesh"; -import { PointerValues } from "../../../misc/usePointer"; -import { HooksProps, HooksReturn } from "../../types"; -import { DoubleRenderTarget } from "../../../utils/useDoubleFBO"; -export declare const DELTA_TIME = 0.016; -export type FluidParams = { - /** density disspation , default : `0.98` */ - densityDissipation?: number; - /** velocity dissipation , default : `0.99` */ - velocityDissipation?: number; - /** velocity acceleration , default : `10.0` */ - velocityAcceleration?: number; - /** pressure dissipation , default : `0.9` */ - pressureDissipation?: number; - /** pressure iterations. affects performance , default : `20` */ - pressureIterations?: number; - /** curl_strength , default : `35` */ - curlStrength?: number; - /** splat radius , default : `0.002` */ - splatRadius?: number; - /** Fluid Color.THREE.Vector3 Alternatively, it accepts a function that returns THREE.Vector3.The function takes velocity:THREE.Vector2 as an argument. , default : `THREE.Vector3(1.0, 1.0, 1.0)` */ - fluidColor?: ((velocity: THREE.Vector2) => THREE.Vector3) | THREE.Vector3 | THREE.Color; - /** When calling usePointer in a frame loop, setting PointerValues ​​to this value prevents double calls , default : `false` */ - pointerValues?: PointerValues | false; -}; -export type FluidObject = { - scene: THREE.Scene; - mesh: THREE.Mesh; - materials: FluidMaterials; - camera: THREE.Camera; - renderTarget: { - velocity: DoubleRenderTarget; - density: DoubleRenderTarget; - curl: THREE.WebGLRenderTarget; - divergence: THREE.WebGLRenderTarget; - pressure: DoubleRenderTarget; - }; - output: THREE.Texture; -}; -export declare const FLUID_PARAMS: FluidParams; -/** - * @link https://github.com/FunTechInc/use-shader-fx?tab=readme-ov-file#usage - */ -export declare const useFluid: ({ size, dpr, renderTargetOptions, isSizeUpdate, customFluidProps, }: { - /** you can add `onBeforeInit` of the next material.`initial`,`curl`,`vorticity`,`advection`,`divergence`,`pressure`,`clear`,`gradientSubtract`,`splat` - * ```ts - * customFluidProps: { - vorticity: { - onBeforeInit: (parameters) => console.log(parameters), - }, - }, - * ``` - */ - customFluidProps?: CustomFluidProps | undefined; -} & HooksProps) => HooksReturn; diff --git a/packages/use-shader-fx/types/fxs/simulations/useFluid/materials/useAdvectionMaterial.d.ts b/packages/use-shader-fx/types/fxs/simulations/useFluid/materials/useAdvectionMaterial.d.ts deleted file mode 100644 index 4063a869..00000000 --- a/packages/use-shader-fx/types/fxs/simulations/useFluid/materials/useAdvectionMaterial.d.ts +++ /dev/null @@ -1,22 +0,0 @@ -import * as THREE from "three"; -import { MaterialProps } from "../../../types"; -export declare class AdvectionMaterial extends THREE.ShaderMaterial { - uniforms: { - uVelocity: { - value: THREE.Texture; - }; - uSource: { - value: THREE.Texture; - }; - texelSize: { - value: THREE.Vector2; - }; - dt: { - value: number; - }; - dissipation: { - value: number; - }; - }; -} -export declare const useAdvectionMaterial: ({ onBeforeInit }: MaterialProps) => AdvectionMaterial; diff --git a/packages/use-shader-fx/types/fxs/simulations/useFluid/materials/useClearMaterial.d.ts b/packages/use-shader-fx/types/fxs/simulations/useFluid/materials/useClearMaterial.d.ts deleted file mode 100644 index 33100e41..00000000 --- a/packages/use-shader-fx/types/fxs/simulations/useFluid/materials/useClearMaterial.d.ts +++ /dev/null @@ -1,16 +0,0 @@ -import * as THREE from "three"; -import { MaterialProps } from "../../../types"; -export declare class ClearMaterial extends THREE.ShaderMaterial { - uniforms: { - uTexture: { - value: THREE.Texture; - }; - value: { - value: number; - }; - texelSize: { - value: THREE.Vector2; - }; - }; -} -export declare const useClearMaterial: ({ onBeforeInit }: MaterialProps) => ClearMaterial; diff --git a/packages/use-shader-fx/types/fxs/simulations/useFluid/materials/useCurlMaterial.d.ts b/packages/use-shader-fx/types/fxs/simulations/useFluid/materials/useCurlMaterial.d.ts deleted file mode 100644 index bface9d9..00000000 --- a/packages/use-shader-fx/types/fxs/simulations/useFluid/materials/useCurlMaterial.d.ts +++ /dev/null @@ -1,13 +0,0 @@ -import * as THREE from "three"; -import { MaterialProps } from "../../../types"; -export declare class CurlMaterial extends THREE.ShaderMaterial { - uniforms: { - uVelocity: { - value: THREE.Texture; - }; - texelSize: { - value: THREE.Vector2; - }; - }; -} -export declare const useCurlMaterial: ({ onBeforeInit }: MaterialProps) => CurlMaterial; diff --git a/packages/use-shader-fx/types/fxs/simulations/useFluid/materials/useDivergenceMaterial.d.ts b/packages/use-shader-fx/types/fxs/simulations/useFluid/materials/useDivergenceMaterial.d.ts deleted file mode 100644 index 87fc99a0..00000000 --- a/packages/use-shader-fx/types/fxs/simulations/useFluid/materials/useDivergenceMaterial.d.ts +++ /dev/null @@ -1,13 +0,0 @@ -import * as THREE from "three"; -import { MaterialProps } from "../../../types"; -export declare class DivergenceMaterial extends THREE.ShaderMaterial { - uniforms: { - uVelocity: { - value: THREE.Texture; - }; - texelSize: { - value: THREE.Vector2; - }; - }; -} -export declare const useDivergenceMaterial: ({ onBeforeInit }: MaterialProps) => DivergenceMaterial; diff --git a/packages/use-shader-fx/types/fxs/simulations/useFluid/materials/useGradientSubtractMaterial.d.ts b/packages/use-shader-fx/types/fxs/simulations/useFluid/materials/useGradientSubtractMaterial.d.ts deleted file mode 100644 index 06af8242..00000000 --- a/packages/use-shader-fx/types/fxs/simulations/useFluid/materials/useGradientSubtractMaterial.d.ts +++ /dev/null @@ -1,16 +0,0 @@ -import * as THREE from "three"; -import { MaterialProps } from "../../../types"; -export declare class GradientSubtractMaterial extends THREE.ShaderMaterial { - uniforms: { - uPressure: { - value: THREE.Texture; - }; - uVelocity: { - value: THREE.Texture; - }; - texelSize: { - value: THREE.Vector2; - }; - }; -} -export declare const useGradientSubtractMaterial: ({ onBeforeInit, }: MaterialProps) => GradientSubtractMaterial; diff --git a/packages/use-shader-fx/types/fxs/simulations/useFluid/materials/useInitialMaterial.d.ts b/packages/use-shader-fx/types/fxs/simulations/useFluid/materials/useInitialMaterial.d.ts deleted file mode 100644 index 6322827a..00000000 --- a/packages/use-shader-fx/types/fxs/simulations/useFluid/materials/useInitialMaterial.d.ts +++ /dev/null @@ -1,2 +0,0 @@ -import * as THREE from "three"; -export declare const useInitialMaterial: () => THREE.ShaderMaterial; diff --git a/packages/use-shader-fx/types/fxs/simulations/useFluid/materials/usePressureMaterial.d.ts b/packages/use-shader-fx/types/fxs/simulations/useFluid/materials/usePressureMaterial.d.ts deleted file mode 100644 index 798aa583..00000000 --- a/packages/use-shader-fx/types/fxs/simulations/useFluid/materials/usePressureMaterial.d.ts +++ /dev/null @@ -1,16 +0,0 @@ -import * as THREE from "three"; -import { MaterialProps } from "../../../types"; -export declare class PressureMaterial extends THREE.ShaderMaterial { - uniforms: { - uPressure: { - value: THREE.Texture; - }; - uDivergence: { - value: THREE.Texture; - }; - texelSize: { - value: THREE.Vector2; - }; - }; -} -export declare const usePressureMaterial: ({ onBeforeInit }: MaterialProps) => PressureMaterial; diff --git a/packages/use-shader-fx/types/fxs/simulations/useFluid/materials/useSplatMaterial.d.ts b/packages/use-shader-fx/types/fxs/simulations/useFluid/materials/useSplatMaterial.d.ts deleted file mode 100644 index 0a641bcc..00000000 --- a/packages/use-shader-fx/types/fxs/simulations/useFluid/materials/useSplatMaterial.d.ts +++ /dev/null @@ -1,25 +0,0 @@ -import * as THREE from "three"; -import { MaterialProps } from "../../../types"; -export declare class SplatMaterial extends THREE.ShaderMaterial { - uniforms: { - uTarget: { - value: THREE.Texture; - }; - aspectRatio: { - value: number; - }; - color: { - value: THREE.Vector3 | THREE.Color; - }; - point: { - value: THREE.Vector2; - }; - radius: { - value: number; - }; - texelSize: { - value: THREE.Vector2; - }; - }; -} -export declare const useSplatMaterial: ({ onBeforeInit }: MaterialProps) => SplatMaterial; diff --git a/packages/use-shader-fx/types/fxs/simulations/useFluid/materials/useVorticityMaterial.d.ts b/packages/use-shader-fx/types/fxs/simulations/useFluid/materials/useVorticityMaterial.d.ts deleted file mode 100644 index 71994220..00000000 --- a/packages/use-shader-fx/types/fxs/simulations/useFluid/materials/useVorticityMaterial.d.ts +++ /dev/null @@ -1,22 +0,0 @@ -import * as THREE from "three"; -import { MaterialProps } from "../../../types"; -export declare class VorticityMaterial extends THREE.ShaderMaterial { - uniforms: { - uVelocity: { - value: THREE.Texture; - }; - uCurl: { - value: THREE.Texture; - }; - curl: { - value: number; - }; - dt: { - value: number; - }; - texelSize: { - value: THREE.Vector2; - }; - }; -} -export declare const useVorticityMaterial: ({ onBeforeInit }: MaterialProps) => VorticityMaterial; diff --git a/packages/use-shader-fx/types/fxs/simulations/useFluid/useMesh.d.ts b/packages/use-shader-fx/types/fxs/simulations/useFluid/useMesh.d.ts deleted file mode 100644 index a6d2cd12..00000000 --- a/packages/use-shader-fx/types/fxs/simulations/useFluid/useMesh.d.ts +++ /dev/null @@ -1,52 +0,0 @@ -import * as THREE from "three"; -import { AdvectionMaterial } from "./materials/useAdvectionMaterial"; -import { DivergenceMaterial } from "./materials/useDivergenceMaterial"; -import { PressureMaterial } from "./materials/usePressureMaterial"; -import { CurlMaterial } from "./materials/useCurlMaterial"; -import { VorticityMaterial } from "./materials/useVorticityMaterial"; -import { ClearMaterial } from "./materials/useClearMaterial"; -import { GradientSubtractMaterial } from "./materials/useGradientSubtractMaterial"; -import { SplatMaterial } from "./materials/useSplatMaterial"; -import { CustomParams } from "../../../utils/setUniforms"; -import { MaterialProps, Size } from "../../types"; -type TMaterials = AdvectionMaterial | DivergenceMaterial | CurlMaterial | PressureMaterial | ClearMaterial | GradientSubtractMaterial | SplatMaterial; -export type FluidMaterials = { - vorticityMaterial: VorticityMaterial; - curlMaterial: CurlMaterial; - advectionMaterial: AdvectionMaterial; - divergenceMaterial: DivergenceMaterial; - pressureMaterial: PressureMaterial; - clearMaterial: ClearMaterial; - gradientSubtractMaterial: GradientSubtractMaterial; - splatMaterial: SplatMaterial; -}; -export type CustomizableKeys = "advection" | "splat" | "curl" | "vorticity" | "divergence" | "clear" | "pressure" | "gradientSubtract"; -export type CustomFluidProps = { - [K in CustomizableKeys]?: MaterialProps; -}; -export type CustomFluidParams = { - [K in CustomizableKeys]?: CustomParams; -}; -/** - * Returns the material update function in the second argument - */ -export declare const useMesh: ({ scene, size, dpr, customFluidProps, }: { - scene: THREE.Scene; - size: Size; - dpr: number | false; - customFluidProps?: CustomFluidProps | undefined; -}) => { - materials: { - vorticityMaterial: VorticityMaterial; - curlMaterial: CurlMaterial; - advectionMaterial: AdvectionMaterial; - divergenceMaterial: DivergenceMaterial; - pressureMaterial: PressureMaterial; - clearMaterial: ClearMaterial; - gradientSubtractMaterial: GradientSubtractMaterial; - splatMaterial: SplatMaterial; - }; - setMeshMaterial: (material: TMaterials) => void; - mesh: THREE.Mesh, THREE.ShaderMaterial, THREE.Object3DEventMap>; -}; -export {}; diff --git a/packages/use-shader-fx/types/fxs/simulations/useRipple/index.d.ts b/packages/use-shader-fx/types/fxs/simulations/useRipple/index.d.ts deleted file mode 100644 index f622b745..00000000 --- a/packages/use-shader-fx/types/fxs/simulations/useRipple/index.d.ts +++ /dev/null @@ -1,39 +0,0 @@ -import * as THREE from "three"; -import { PointerValues } from "../../../misc/usePointer"; -import { HooksProps, HooksReturn } from "../../types"; -import { CustomParams } from "../../../utils/setUniforms"; -export type RippleParams = { - /** How often ripples appear, default : `0.01` */ - frequency?: number; - /** rotation rate, default : `0.05` */ - rotation?: number; - /** fadeout speed, default : `0.9` */ - fadeoutSpeed?: number; - /** scale rate, default : `0.3` */ - scale?: number; - /** alpha, default : `0.6` */ - alpha?: number; - /** When calling usePointer in a frame loop, setting PointerValues ​​to this value prevents double calls , default : `false` */ - pointerValues?: PointerValues | false; -}; -export type RippleObject = { - scene: THREE.Scene; - meshArr: THREE.Mesh[]; - camera: THREE.Camera; - renderTarget: THREE.WebGLRenderTarget; - output: THREE.Texture; -}; -export declare const RIPPLE_PARAMS: RippleParams; -interface UseRippleProps extends HooksProps { - /** texture applied to ripple */ - texture?: THREE.Texture; - /** ripple size, default:64 */ - scale?: number; - /** ripple max length, default:100 */ - max?: number; -} -/** - * @link https://github.com/FunTechInc/use-shader-fx?tab=readme-ov-file#usage - */ -export declare const useRipple: ({ texture, scale, max, size, dpr, renderTargetOptions, isSizeUpdate, onBeforeInit, }: UseRippleProps) => HooksReturn; -export {}; diff --git a/packages/use-shader-fx/types/fxs/simulations/useRipple/useMesh.d.ts b/packages/use-shader-fx/types/fxs/simulations/useRipple/useMesh.d.ts deleted file mode 100644 index 1888db40..00000000 --- a/packages/use-shader-fx/types/fxs/simulations/useRipple/useMesh.d.ts +++ /dev/null @@ -1,10 +0,0 @@ -import * as THREE from "three"; -import { MaterialProps } from "../../types"; -type UseMeshProps = { - scale: number; - max: number; - scene: THREE.Scene; - texture?: THREE.Texture; -}; -export declare const useMesh: ({ scale, max, texture, scene, onBeforeInit, }: UseMeshProps & MaterialProps) => THREE.Mesh[]; -export {}; diff --git a/packages/use-shader-fx/types/fxs/types/index.d.ts b/packages/use-shader-fx/types/fxs/types/index.d.ts deleted file mode 100644 index 481c2aa0..00000000 --- a/packages/use-shader-fx/types/fxs/types/index.d.ts +++ /dev/null @@ -1,68 +0,0 @@ -import * as THREE from "three"; -import { RootState } from "@react-three/fiber"; -export type Size = { - width: number; - height: number; -}; -export type Dpr = number | { - /** you can set whether `dpr` affects `shader`. default : `false` */ - shader?: false | number; - /** you can set whether `dpr` affects `fbo`. default : `false` */ - fbo?: false | number; -}; -export type OnBeforeInitParameters = { - uniforms: { - [uniform: string]: THREE.IUniform; - }; - fragmentShader: string; - vertexShader: string; -}; -export type MaterialProps = { - /** - * An optional callback that is executed immediately before the shader program is initialised. This function is called with the shader source code as a parameter. Useful for the modification of built-in materials. - * @param parameters {fragmentShader, vertexShader, uniforms} - */ - onBeforeInit?: (parameters: OnBeforeInitParameters) => void; -}; -export interface HooksProps extends MaterialProps { - /** Width,Height in pixels, or `size` from r3f */ - size: Size; - /** Pixel-ratio, use `window.devicePixelRatio` or viewport.dpr from r3f */ - dpr: Dpr; - /** Whether to `setSize` the FBO when updating size or dpr. default : `false` */ - isSizeUpdate?: boolean; - /** - * @type `THREE.RenderTargetOptions` - * @param depthBuffer Unlike the default in three.js, the default is `false`. - */ - renderTargetOptions?: THREE.RenderTargetOptions; -} -/** - * @returns {HooksReturn} - * updateFx - Functions to update parameters and render. - * updateParams - Function to update parameters only. - * fxObject - An object containing various FX components such as scene, camera, material, and render target. - * - * @template T The type for the parameters of the hooks. - * @template O The type for the FX object. - * @template C The type for the custom parameters. - */ -export type HooksReturn = [ - /** - * Functions to update parameters and render. - * @param rootState RootState - * @param newParams params of fxHooks - * @param customParams custom params, added to `uniforms` during initialisation - */ - (rootState: RootState, newParams?: T, customParams?: C) => THREE.Texture, - /** - * Function to update parameters only. - * @param newParams params of fxHooks - * @param customParams custom params, added to `uniforms` during initialisation - */ - (newParams?: T, customParams?: C) => void, - /** - * Contains each part of FX such as scene, camera, material, render target, etc. - */ - O -]; diff --git a/packages/use-shader-fx/types/fxs/utils/useAlphaBlending/index.d.ts b/packages/use-shader-fx/types/fxs/utils/useAlphaBlending/index.d.ts deleted file mode 100644 index 9de52271..00000000 --- a/packages/use-shader-fx/types/fxs/utils/useAlphaBlending/index.d.ts +++ /dev/null @@ -1,22 +0,0 @@ -import * as THREE from "three"; -import { CustomParams } from "../../../utils/setUniforms"; -import { HooksProps, HooksReturn } from "../../types"; -export type AlphaBlendingParams = { - /** default : `THREE.Texture()` */ - texture?: THREE.Texture; - /** alpha map , default : `THREE.Texture()` */ - map?: THREE.Texture; -}; -export type AlphaBlendingObject = { - scene: THREE.Scene; - mesh: THREE.Mesh; - material: THREE.Material; - camera: THREE.Camera; - renderTarget: THREE.WebGLRenderTarget; - output: THREE.Texture; -}; -export declare const ALPHABLENDING_PARAMS: AlphaBlendingParams; -/** - * @link https://github.com/FunTechInc/use-shader-fx?tab=readme-ov-file#usage - */ -export declare const useAlphaBlending: ({ size, dpr, renderTargetOptions, isSizeUpdate, onBeforeInit, }: HooksProps) => HooksReturn; diff --git a/packages/use-shader-fx/types/fxs/utils/useAlphaBlending/useMesh.d.ts b/packages/use-shader-fx/types/fxs/utils/useAlphaBlending/useMesh.d.ts deleted file mode 100644 index a68773a1..00000000 --- a/packages/use-shader-fx/types/fxs/utils/useAlphaBlending/useMesh.d.ts +++ /dev/null @@ -1,19 +0,0 @@ -import * as THREE from "three"; -import { MaterialProps, Size } from "../../types"; -export declare class AlphaBlendingMaterial extends THREE.ShaderMaterial { - uniforms: { - uTexture: { - value: THREE.Texture; - }; - uMap: { - value: THREE.Texture; - }; - }; -} -export declare const useMesh: ({ scene, onBeforeInit, }: { - scene: THREE.Scene; - size: Size; -} & MaterialProps) => { - material: AlphaBlendingMaterial; - mesh: THREE.Mesh, AlphaBlendingMaterial, THREE.Object3DEventMap>; -}; diff --git a/packages/use-shader-fx/types/fxs/utils/useBlending/index.d.ts b/packages/use-shader-fx/types/fxs/utils/useBlending/index.d.ts deleted file mode 100644 index d1ad89e4..00000000 --- a/packages/use-shader-fx/types/fxs/utils/useBlending/index.d.ts +++ /dev/null @@ -1,36 +0,0 @@ -import * as THREE from "three"; -import { CustomParams } from "../../../utils/setUniforms"; -import { HooksProps, HooksReturn } from "../../types"; -export type BlendingParams = { - /** Make this texture Blending , default : `THREE.Texture` */ - texture?: THREE.Texture; - /** map texture, default : `THREE.Texture` */ - map?: THREE.Texture; - /** map strength , r,g value are affecting , default : `0.3` */ - mapIntensity?: number; - /** Alpha blending is performed using the alpha of the set texture. , default : `false` */ - alphaMap?: THREE.Texture | false; - /** default : `(0.5,0.5,0.5)` */ - brightness?: THREE.Vector3; - /** default : `0.0` */ - min?: number; - /** default : `1.0` */ - max?: number; - /** If set, this value will apply color dodge , default : `false` */ - dodgeColor?: THREE.Color | false; -}; -export type BlendingObject = { - scene: THREE.Scene; - mesh: THREE.Mesh; - material: THREE.Material; - camera: THREE.Camera; - renderTarget: THREE.WebGLRenderTarget; - output: THREE.Texture; -}; -export declare const BLENDING_PARAMS: BlendingParams; -/** - * Blend map to texture. You can set the threshold for blending with brightness. You can set the dodge color by setting color. -If you don't want to reflect the map's color, you can use useFxBlending instead. - * @link https://github.com/FunTechInc/use-shader-fx?tab=readme-ov-file#usage - */ -export declare const useBlending: ({ size, dpr, renderTargetOptions, isSizeUpdate, onBeforeInit, }: HooksProps) => HooksReturn; diff --git a/packages/use-shader-fx/types/fxs/utils/useBlending/useMesh.d.ts b/packages/use-shader-fx/types/fxs/utils/useBlending/useMesh.d.ts deleted file mode 100644 index eed654ff..00000000 --- a/packages/use-shader-fx/types/fxs/utils/useBlending/useMesh.d.ts +++ /dev/null @@ -1,42 +0,0 @@ -import * as THREE from "three"; -import { MaterialProps } from "../../types"; -export declare class BlendingMaterial extends THREE.ShaderMaterial { - uniforms: { - u_texture: { - value: THREE.Texture; - }; - uMap: { - value: THREE.Texture; - }; - u_alphaMap: { - value: THREE.Texture; - }; - u_isAlphaMap: { - value: boolean; - }; - uMapIntensity: { - value: number; - }; - u_brightness: { - value: THREE.Vector3; - }; - u_min: { - value: number; - }; - u_max: { - value: number; - }; - u_dodgeColor: { - value: THREE.Color; - }; - u_isDodgeColor: { - value: boolean; - }; - }; -} -export declare const useMesh: ({ scene, onBeforeInit, }: { - scene: THREE.Scene; -} & MaterialProps) => { - material: BlendingMaterial; - mesh: THREE.Mesh, BlendingMaterial, THREE.Object3DEventMap>; -}; diff --git a/packages/use-shader-fx/types/fxs/utils/useBrightnessPicker/index.d.ts b/packages/use-shader-fx/types/fxs/utils/useBrightnessPicker/index.d.ts deleted file mode 100644 index d8bfd85b..00000000 --- a/packages/use-shader-fx/types/fxs/utils/useBrightnessPicker/index.d.ts +++ /dev/null @@ -1,26 +0,0 @@ -import * as THREE from "three"; -import { CustomParams } from "../../../utils/setUniforms"; -import { HooksProps, HooksReturn } from "../../types"; -export type BrightnessPickerParams = { - /** pick brightness from this texture , default : `THREE.Texture` */ - texture?: THREE.Texture; - /** default : `(0.5,0.5,0.5)` */ - brightness?: THREE.Vector3; - /** default : `0.0` */ - min?: number; - /** default : `1.0` */ - max?: number; -}; -export type BrightnessPickerObject = { - scene: THREE.Scene; - mesh: THREE.Mesh; - material: THREE.Material; - camera: THREE.Camera; - renderTarget: THREE.WebGLRenderTarget; - output: THREE.Texture; -}; -export declare const BRIGHTNESSPICKER_PARAMS: BrightnessPickerParams; -/** - * @link https://github.com/FunTechInc/use-shader-fx?tab=readme-ov-file#usage - */ -export declare const useBrightnessPicker: ({ size, dpr, renderTargetOptions, isSizeUpdate, onBeforeInit, }: HooksProps) => HooksReturn; diff --git a/packages/use-shader-fx/types/fxs/utils/useBrightnessPicker/useMesh.d.ts b/packages/use-shader-fx/types/fxs/utils/useBrightnessPicker/useMesh.d.ts deleted file mode 100644 index f1dd1032..00000000 --- a/packages/use-shader-fx/types/fxs/utils/useBrightnessPicker/useMesh.d.ts +++ /dev/null @@ -1,24 +0,0 @@ -import * as THREE from "three"; -import { MaterialProps } from "../../types"; -export declare class BrightnessPickerMaterial extends THREE.ShaderMaterial { - uniforms: { - u_texture: { - value: THREE.Texture; - }; - u_brightness: { - value: THREE.Vector3; - }; - u_min: { - value: number; - }; - u_max: { - value: number; - }; - }; -} -export declare const useMesh: ({ scene, onBeforeInit, }: { - scene: THREE.Scene; -} & MaterialProps) => { - material: BrightnessPickerMaterial; - mesh: THREE.Mesh, BrightnessPickerMaterial, THREE.Object3DEventMap>; -}; diff --git a/packages/use-shader-fx/types/fxs/utils/useCoverTexture/index.d.ts b/packages/use-shader-fx/types/fxs/utils/useCoverTexture/index.d.ts deleted file mode 100644 index 733c456e..00000000 --- a/packages/use-shader-fx/types/fxs/utils/useCoverTexture/index.d.ts +++ /dev/null @@ -1,20 +0,0 @@ -import * as THREE from "three"; -import { CustomParams } from "../../../utils/setUniforms"; -import { HooksProps, HooksReturn } from "../../types"; -export type CoverTextureParams = { - /** Textures that you want to display exactly on the screen , default : `THREE.Texture()` */ - texture?: THREE.Texture; -}; -export type CoverTextureObject = { - scene: THREE.Scene; - mesh: THREE.Mesh; - material: THREE.Material; - camera: THREE.Camera; - renderTarget: THREE.WebGLRenderTarget; - output: THREE.Texture; -}; -export declare const COVERTEXTURE_PARAMS: CoverTextureParams; -/** - * @link https://github.com/FunTechInc/use-shader-fx?tab=readme-ov-file#usage - */ -export declare const useCoverTexture: ({ size, dpr, renderTargetOptions, isSizeUpdate, onBeforeInit, }: HooksProps) => HooksReturn; diff --git a/packages/use-shader-fx/types/fxs/utils/useCoverTexture/useMesh.d.ts b/packages/use-shader-fx/types/fxs/utils/useCoverTexture/useMesh.d.ts deleted file mode 100644 index ba9a6d88..00000000 --- a/packages/use-shader-fx/types/fxs/utils/useCoverTexture/useMesh.d.ts +++ /dev/null @@ -1,23 +0,0 @@ -import * as THREE from "three"; -import { MaterialProps, Size } from "../../types"; -export declare class FxTextureMaterial extends THREE.ShaderMaterial { - uniforms: { - uResolution: { - value: THREE.Vector2; - }; - uTextureResolution: { - value: THREE.Vector2; - }; - uTexture: { - value: THREE.Texture; - }; - }; -} -export declare const useMesh: ({ scene, size, dpr, onBeforeInit, }: { - scene: THREE.Scene; - size: Size; - dpr: number | false; -} & MaterialProps) => { - material: FxTextureMaterial; - mesh: THREE.Mesh, FxTextureMaterial, THREE.Object3DEventMap>; -}; diff --git a/packages/use-shader-fx/types/fxs/utils/useDuoTone/index.d.ts b/packages/use-shader-fx/types/fxs/utils/useDuoTone/index.d.ts deleted file mode 100644 index b83a69bb..00000000 --- a/packages/use-shader-fx/types/fxs/utils/useDuoTone/index.d.ts +++ /dev/null @@ -1,25 +0,0 @@ -import * as THREE from "three"; -import { DuoToneMaterial } from "./useMesh"; -import { CustomParams } from "../../../utils/setUniforms"; -import { HooksProps, HooksReturn } from "../../types"; -export type DuoToneParams = { - /** Make this texture duotone , Default : `THREE.Texture()` */ - texture?: THREE.Texture; - /** 1st color , Default : `THREE.Color(0xffffff)` */ - color0?: THREE.Color; - /** 2nd color , Default : `THREE.Color(0x000000)` */ - color1?: THREE.Color; -}; -export type DuoToneObject = { - scene: THREE.Scene; - mesh: THREE.Mesh; - material: DuoToneMaterial; - camera: THREE.Camera; - renderTarget: THREE.WebGLRenderTarget; - output: THREE.Texture; -}; -export declare const DUOTONE_PARAMS: DuoToneParams; -/** - * @link https://github.com/FunTechInc/use-shader-fx?tab=readme-ov-file#usage - */ -export declare const useDuoTone: ({ size, dpr, renderTargetOptions, isSizeUpdate, onBeforeInit, }: HooksProps) => HooksReturn; diff --git a/packages/use-shader-fx/types/fxs/utils/useDuoTone/useMesh.d.ts b/packages/use-shader-fx/types/fxs/utils/useDuoTone/useMesh.d.ts deleted file mode 100644 index 6806b5eb..00000000 --- a/packages/use-shader-fx/types/fxs/utils/useDuoTone/useMesh.d.ts +++ /dev/null @@ -1,21 +0,0 @@ -import * as THREE from "three"; -import { MaterialProps } from "../../types"; -export declare class DuoToneMaterial extends THREE.ShaderMaterial { - uniforms: { - uTexture: { - value: THREE.Texture; - }; - uColor0: { - value: THREE.Color; - }; - uColor1: { - value: THREE.Color; - }; - }; -} -export declare const useMesh: ({ scene, onBeforeInit, }: { - scene: THREE.Scene; -} & MaterialProps) => { - material: DuoToneMaterial; - mesh: THREE.Mesh, DuoToneMaterial, THREE.Object3DEventMap>; -}; diff --git a/packages/use-shader-fx/types/fxs/utils/useFxBlending/index.d.ts b/packages/use-shader-fx/types/fxs/utils/useFxBlending/index.d.ts deleted file mode 100644 index a7124b15..00000000 --- a/packages/use-shader-fx/types/fxs/utils/useFxBlending/index.d.ts +++ /dev/null @@ -1,25 +0,0 @@ -import * as THREE from "three"; -import { CustomParams } from "../../../utils/setUniforms"; -import { HooksProps, HooksReturn } from "../../types"; -export type FxBlendingParams = { - /** Make this texture Blending , default : `THREE.Texture` */ - texture?: THREE.Texture; - /** map texture, default : `THREE.Texture` */ - map?: THREE.Texture; - /** map strength , r,g value are affecting , default : `0.3` */ - mapIntensity?: number; -}; -export type FxBlendingObject = { - scene: THREE.Scene; - mesh: THREE.Mesh; - material: THREE.Material; - camera: THREE.Camera; - renderTarget: THREE.WebGLRenderTarget; - output: THREE.Texture; -}; -export declare const FXBLENDING_PARAMS: FxBlendingParams; -/** - * Blend map to texture. You can change the intensity of fx applied by the rg value of map. Unlike "useBlending", the map color is not reflected. - * @link https://github.com/FunTechInc/use-shader-fx?tab=readme-ov-file#usage - */ -export declare const useFxBlending: ({ size, dpr, renderTargetOptions, isSizeUpdate, onBeforeInit, }: HooksProps) => HooksReturn; diff --git a/packages/use-shader-fx/types/fxs/utils/useFxBlending/useMesh.d.ts b/packages/use-shader-fx/types/fxs/utils/useFxBlending/useMesh.d.ts deleted file mode 100644 index ddfbee3f..00000000 --- a/packages/use-shader-fx/types/fxs/utils/useFxBlending/useMesh.d.ts +++ /dev/null @@ -1,21 +0,0 @@ -import * as THREE from "three"; -import { MaterialProps } from "../../types"; -export declare class FxBlendingMaterial extends THREE.ShaderMaterial { - uniforms: { - u_texture: { - value: THREE.Texture; - }; - uMap: { - value: THREE.Texture; - }; - uMapIntensity: { - value: number; - }; - }; -} -export declare const useMesh: ({ scene, onBeforeInit, }: { - scene: THREE.Scene; -} & MaterialProps) => { - material: FxBlendingMaterial; - mesh: THREE.Mesh, FxBlendingMaterial, THREE.Object3DEventMap>; -}; diff --git a/packages/use-shader-fx/types/fxs/utils/useFxTexture/index.d.ts b/packages/use-shader-fx/types/fxs/utils/useFxTexture/index.d.ts deleted file mode 100644 index 014422ad..00000000 --- a/packages/use-shader-fx/types/fxs/utils/useFxTexture/index.d.ts +++ /dev/null @@ -1,36 +0,0 @@ -import * as THREE from "three"; -import { CustomParams } from "../../../utils/setUniforms"; -import { HooksProps, HooksReturn } from "../../types"; -export type FxTextureParams = { - /** 1st texture , default : `THREE.Texture()` */ - texture0?: THREE.Texture; - /** 2nd texture , default : `THREE.Texture()` */ - texture1?: THREE.Texture; - /** add transparent padding, 0.0 ~ 1.0 , default : `0.0` */ - padding?: number; - /** The color map. The uv value is affected according to this rbg , default : `THREE.Texture()` */ - map?: THREE.Texture; - /** intensity of map , r,g value are affecting , default : `0.0` */ - mapIntensity?: number; - /** Intensity of effect on edges , default : `0.0` */ - edgeIntensity?: number; - /** epicenter of fx, -1 ~ 1 , default : `vec2(0.0,0.0)` */ - epicenter?: THREE.Vector2; - /** Switch value to switch between texture0 and texture1 , 0 ~ 1 , default : `0` */ - progress?: number; - /** direction of transition , default: `THREE.Vector2(0, 0)` */ - dir?: THREE.Vector2; -}; -export type FxTextureObject = { - scene: THREE.Scene; - mesh: THREE.Mesh; - material: THREE.Material; - camera: THREE.Camera; - renderTarget: THREE.WebGLRenderTarget; - output: THREE.Texture; -}; -export declare const FXTEXTURE_PARAMS: FxTextureParams; -/** - * @link https://github.com/FunTechInc/use-shader-fx?tab=readme-ov-file#usage - */ -export declare const useFxTexture: ({ size, dpr, renderTargetOptions, isSizeUpdate, onBeforeInit, }: HooksProps) => HooksReturn; diff --git a/packages/use-shader-fx/types/fxs/utils/useFxTexture/useMesh.d.ts b/packages/use-shader-fx/types/fxs/utils/useFxTexture/useMesh.d.ts deleted file mode 100644 index 8294b65b..00000000 --- a/packages/use-shader-fx/types/fxs/utils/useFxTexture/useMesh.d.ts +++ /dev/null @@ -1,50 +0,0 @@ -import * as THREE from "three"; -import { MaterialProps, Size } from "../../types"; -export declare class FxTextureMaterial extends THREE.ShaderMaterial { - uniforms: { - uResolution: { - value: THREE.Vector2; - }; - uTextureResolution: { - value: THREE.Vector2; - }; - uTexture0: { - value: THREE.Texture; - }; - uTexture1: { - value: THREE.Texture; - }; - padding: { - value: number; - }; - uMap: { - value: THREE.Texture; - }; - edgeIntensity: { - value: number; - }; - mapIntensity: { - value: number; - }; - epicenter: { - value: THREE.Vector2; - }; - progress: { - value: number; - }; - dirX: { - value: number; - }; - dirY: { - value: number; - }; - }; -} -export declare const useMesh: ({ scene, size, dpr, onBeforeInit, }: { - scene: THREE.Scene; - size: Size; - dpr: number | false; -} & MaterialProps) => { - material: FxTextureMaterial; - mesh: THREE.Mesh, FxTextureMaterial, THREE.Object3DEventMap>; -}; diff --git a/packages/use-shader-fx/types/fxs/utils/useHSV/index.d.ts b/packages/use-shader-fx/types/fxs/utils/useHSV/index.d.ts deleted file mode 100644 index 6df11829..00000000 --- a/packages/use-shader-fx/types/fxs/utils/useHSV/index.d.ts +++ /dev/null @@ -1,24 +0,0 @@ -import * as THREE from "three"; -import { CustomParams } from "../../../utils/setUniforms"; -import { HooksProps, HooksReturn } from "../../types"; -export type HSVParams = { - /** default : `THREE.Texture()` */ - texture?: THREE.Texture; - /** default : `1` */ - brightness?: number; - /** default : `1` */ - saturation?: number; -}; -export type HSVObject = { - scene: THREE.Scene; - mesh: THREE.Mesh; - material: THREE.Material; - camera: THREE.Camera; - renderTarget: THREE.WebGLRenderTarget; - output: THREE.Texture; -}; -export declare const HSV_PARAMS: HSVParams; -/** - * @link https://github.com/FunTechInc/use-shader-fx?tab=readme-ov-file#usage - */ -export declare const useHSV: ({ size, dpr, renderTargetOptions, isSizeUpdate, onBeforeInit, }: HooksProps) => HooksReturn; diff --git a/packages/use-shader-fx/types/fxs/utils/useHSV/useMesh.d.ts b/packages/use-shader-fx/types/fxs/utils/useHSV/useMesh.d.ts deleted file mode 100644 index 6b47a3cd..00000000 --- a/packages/use-shader-fx/types/fxs/utils/useHSV/useMesh.d.ts +++ /dev/null @@ -1,22 +0,0 @@ -import * as THREE from "three"; -import { MaterialProps, Size } from "../../types"; -export declare class HSVMaterial extends THREE.ShaderMaterial { - uniforms: { - u_texture: { - value: THREE.Texture; - }; - u_brightness: { - value: number; - }; - u_saturation: { - value: number; - }; - }; -} -export declare const useMesh: ({ scene, onBeforeInit, }: { - scene: THREE.Scene; - size: Size; -} & MaterialProps) => { - material: HSVMaterial; - mesh: THREE.Mesh, HSVMaterial, THREE.Object3DEventMap>; -}; diff --git a/packages/use-shader-fx/types/libs/Easings.d.ts b/packages/use-shader-fx/types/libs/Easings.d.ts deleted file mode 100644 index 41ba49de..00000000 --- a/packages/use-shader-fx/types/libs/Easings.d.ts +++ /dev/null @@ -1,9 +0,0 @@ -export type EasingTypes = "easeInSine" | "easeOutSine" | "easeInOutSine" | "easeInQuad" | "easeOutQuad" | "easeInOutQuad" | "easeInCubic" | "easeOutCubic" | "easeInOutCubic" | "easeInQuart" | "easeOutQuart" | "easeInOutQuart" | "easeInQuint" | "easeOutQuint" | "easeInOutQuint" | "easeInExpo" | "easeOutExpo" | "easeInOutExpo" | "easeInCirc" | "easeOutCirc" | "easeInOutCirc" | "easeInBack" | "easeOutBack" | "easeInOutBack" | "easeInElastic" | "easeOutElastic" | "easeInOutElastic" | "easeInBounce" | "easeOutBounce" | "easeInOutBounce"; -type EasingFunctions = { - [K in EasingTypes]: (x: number) => number; -}; -/** - * from https://github.com/ai/easings.net - */ -export declare const Easing: EasingFunctions; -export {}; diff --git a/packages/use-shader-fx/types/libs/Utils.d.ts b/packages/use-shader-fx/types/libs/Utils.d.ts deleted file mode 100644 index c3c7a9f0..00000000 --- a/packages/use-shader-fx/types/libs/Utils.d.ts +++ /dev/null @@ -1,6 +0,0 @@ -type Utils = { - interpolate: (startValue: number, endValue: number, progress: number, threshold?: number) => number; - smoothstep: (edge0: number, edge1: number, x: number) => number; -}; -export declare const Utils: Utils; -export {}; diff --git a/packages/use-shader-fx/types/libs/constants.d.ts b/packages/use-shader-fx/types/libs/constants.d.ts deleted file mode 100644 index abd77be4..00000000 --- a/packages/use-shader-fx/types/libs/constants.d.ts +++ /dev/null @@ -1,8 +0,0 @@ -import * as THREE from "three"; -export declare const ISDEV: boolean; -export declare const MATERIAL_BASIC_PARAMS: { - transparent: boolean; - depthTest: boolean; - depthWrite: boolean; -}; -export declare const DEFAULT_TEXTURE: THREE.DataTexture; diff --git a/packages/use-shader-fx/types/libs/shaders/ShaderChunk.d.ts b/packages/use-shader-fx/types/libs/shaders/ShaderChunk.d.ts deleted file mode 100644 index 42a057bd..00000000 --- a/packages/use-shader-fx/types/libs/shaders/ShaderChunk.d.ts +++ /dev/null @@ -1,4 +0,0 @@ -export type ShaderChunkTypes = "wobble3D" | "snoise" | "coverTexture" | "fxBlending" | "planeVertex" | "defaultVertex" | "hsv2rgb" | "rgb2hsv"; -export declare const ShaderChunk: { - [K in ShaderChunkTypes]: string; -}; diff --git a/packages/use-shader-fx/types/libs/shaders/resolveShaders.d.ts b/packages/use-shader-fx/types/libs/shaders/resolveShaders.d.ts deleted file mode 100644 index a4f3f34b..00000000 --- a/packages/use-shader-fx/types/libs/shaders/resolveShaders.d.ts +++ /dev/null @@ -1,2 +0,0 @@ -declare function resolveIncludes(string: string): string; -export { resolveIncludes }; diff --git a/packages/use-shader-fx/types/misc/useBeat.d.ts b/packages/use-shader-fx/types/misc/useBeat.d.ts deleted file mode 100644 index aaf65a33..00000000 --- a/packages/use-shader-fx/types/misc/useBeat.d.ts +++ /dev/null @@ -1,14 +0,0 @@ -import * as THREE from "three"; -import { EasingTypes } from "../libs/Easings"; -type BeatValues = { - beat: number; - floor: number; - fract: number; - /** unique hash specific to the beat */ - hash: number; -}; -/** - * @param ease easing functions are referenced from https://github.com/ai/easings.net , default : "easeOutQuart" - */ -export declare const useBeat: (bpm: number, ease?: EasingTypes) => (clock: THREE.Clock) => BeatValues; -export {}; diff --git a/packages/use-shader-fx/types/misc/useCopyTexture.d.ts b/packages/use-shader-fx/types/misc/useCopyTexture.d.ts deleted file mode 100644 index 2ca5360f..00000000 --- a/packages/use-shader-fx/types/misc/useCopyTexture.d.ts +++ /dev/null @@ -1,17 +0,0 @@ -import * as THREE from "three"; -import { UseFboProps } from "../utils/useSingleFBO"; -type UpdateCopyFunction = (gl: THREE.WebGLRenderer, index: number, -/** call before FBO is rendered */ -onBeforeRender?: ({ read }: { - read: THREE.Texture; -}) => void) => THREE.Texture; -type UseCopyTextureReturn = [THREE.WebGLRenderTarget[], UpdateCopyFunction]; -/** - * Generate an FBO array to copy the texture. - * @param dpr If dpr is set, dpr will be multiplied, default : `false` - * @param isSizeUpdate Whether to resize when resizing occurs. If isDpr is true, set FBO to setSize even if dpr is changed, default : `false` - * @param length The number of FBOs to create - * @returns [THREE.WebGLRenderTarget[] , updateCopyTexture] - Receives the RenderTarget array as the first argument and the update function as the second argument. `updateCopyTexture()` receives gl as the first argument and the index of the texture you want to copy as the second argument. - */ -export declare const useCopyTexture: (props: UseFboProps, length: number) => UseCopyTextureReturn; -export {}; diff --git a/packages/use-shader-fx/types/misc/useDomSyncer/index.d.ts b/packages/use-shader-fx/types/misc/useDomSyncer/index.d.ts deleted file mode 100644 index 1443e756..00000000 --- a/packages/use-shader-fx/types/misc/useDomSyncer/index.d.ts +++ /dev/null @@ -1,45 +0,0 @@ -import * as THREE from "three"; -import { Key } from "react"; -import { HooksProps, HooksReturn } from "../../fxs/types"; -import { IsIntersecting } from "./utils/useIsIntersecting"; -import { UseDomView } from "./utils/createUseDomView"; -import { CustomParams } from "../../utils/setUniforms"; -export type DomSyncerParams = { - /** DOM array you want to synchronize */ - dom?: (HTMLElement | Element | null)[]; - /** Texture array that you want to synchronize with the DOM rectangle */ - texture?: THREE.Texture[]; - /** default : `0.0[]` */ - boderRadius?: number[]; - /** the angle you want to rotate */ - rotation?: THREE.Euler[]; - /** Array of callback functions when crossed */ - onIntersect?: ((entry: IntersectionObserverEntry) => void)[]; - /** Because DOM rendering and React updates occur asynchronously, there may be a lag between updating dependent arrays and setting DOM arrays. That's what the Key is for. If the dependent array is updated but the Key is not, the loop will skip and return an empty texture. By updating the timing key when DOM acquisition is complete, you can perfectly synchronize DOM and Mesh updates.updateKey must be a unique value for each update, for example `performance.now()`.*/ - updateKey?: Key; -}; -export type DomSyncerObject = { - scene: THREE.Scene; - camera: THREE.Camera; - renderTarget: THREE.WebGLRenderTarget; - output: THREE.Texture; - /** - * A function that returns a determination whether the DOM intersects or not. - * The boolean will be updated after executing the onIntersect function. - * @param index - Index of the dom for which you want to return an intersection decision. -1 will return the entire array. - * @param once - If set to true, it will continue to return true once crossed. - */ - isIntersecting: IsIntersecting; - /** target's DOMRect[] */ - DOMRects: DOMRect[]; - /** target's intersetions boolean[] */ - intersections: boolean[]; - /** You can set callbacks for when at least one DOM is visible and when it is completely hidden. */ - useDomView: UseDomView; -}; -export declare const DOMSYNCER_PARAMS: DomSyncerParams; -/** - * @link https://github.com/FunTechInc/use-shader-fx?tab=readme-ov-file#usedomsyncer - * @param dependencies - When this dependency array is changed, the mesh and intersection judgment will be updated according to the passed DOM array. - */ -export declare const useDomSyncer: ({ size, dpr, isSizeUpdate, renderTargetOptions, onBeforeInit }: HooksProps, dependencies?: import("react").DependencyList) => HooksReturn; diff --git a/packages/use-shader-fx/types/misc/useDomSyncer/utils/createMesh.d.ts b/packages/use-shader-fx/types/misc/useDomSyncer/utils/createMesh.d.ts deleted file mode 100644 index aa9e2ec5..00000000 --- a/packages/use-shader-fx/types/misc/useDomSyncer/utils/createMesh.d.ts +++ /dev/null @@ -1,24 +0,0 @@ -import * as THREE from "three"; -import { DomSyncerParams } from "../"; -import { MaterialProps, Size } from "../../../fxs/types"; -export declare class DomSyncerMaterial extends THREE.ShaderMaterial { - uniforms: { - u_texture: { - value: THREE.Texture; - }; - u_textureResolution: { - value: THREE.Vector2; - }; - u_resolution: { - value: THREE.Vector2; - }; - u_borderRadius: { - value: number; - }; - }; -} -export declare const createMesh: ({ params, scene, onBeforeInit, }: { - params: DomSyncerParams; - size: Size; - scene: THREE.Scene; -} & MaterialProps) => void; diff --git a/packages/use-shader-fx/types/misc/useDomSyncer/utils/createUseDomView.d.ts b/packages/use-shader-fx/types/misc/useDomSyncer/utils/createUseDomView.d.ts deleted file mode 100644 index 7e5535e2..00000000 --- a/packages/use-shader-fx/types/misc/useDomSyncer/utils/createUseDomView.d.ts +++ /dev/null @@ -1,6 +0,0 @@ -export type UseDomViewProps = { - onView?: () => void; - onHidden?: () => void; -}; -export type UseDomView = (props: UseDomViewProps) => void; -export declare const createUseDomView: (isIntersectingRef: React.MutableRefObject) => UseDomView; diff --git a/packages/use-shader-fx/types/misc/useDomSyncer/utils/errorHandler.d.ts b/packages/use-shader-fx/types/misc/useDomSyncer/utils/errorHandler.d.ts deleted file mode 100644 index 657c3b43..00000000 --- a/packages/use-shader-fx/types/misc/useDomSyncer/utils/errorHandler.d.ts +++ /dev/null @@ -1,2 +0,0 @@ -import { DomSyncerParams } from ".."; -export declare const errorHandler: (params: DomSyncerParams) => boolean; diff --git a/packages/use-shader-fx/types/misc/useDomSyncer/utils/useIntersectionHandler.d.ts b/packages/use-shader-fx/types/misc/useDomSyncer/utils/useIntersectionHandler.d.ts deleted file mode 100644 index cd25a98a..00000000 --- a/packages/use-shader-fx/types/misc/useDomSyncer/utils/useIntersectionHandler.d.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { DomSyncerParams } from ".."; -export declare const useIntersectionHandler: () => ({ isIntersectingRef, isIntersectingOnceRef, params, }: { - isIntersectingRef: React.MutableRefObject; - isIntersectingOnceRef: React.MutableRefObject; - params: DomSyncerParams; -}) => void; diff --git a/packages/use-shader-fx/types/misc/useDomSyncer/utils/useIsIntersecting.d.ts b/packages/use-shader-fx/types/misc/useDomSyncer/utils/useIsIntersecting.d.ts deleted file mode 100644 index ccc3f896..00000000 --- a/packages/use-shader-fx/types/misc/useDomSyncer/utils/useIsIntersecting.d.ts +++ /dev/null @@ -1,7 +0,0 @@ -/// -export type IsIntersecting = (index: number, once?: boolean) => boolean[] | boolean; -export declare const useIsIntersecting: () => { - isIntersectingRef: import("react").MutableRefObject; - isIntersectingOnceRef: import("react").MutableRefObject; - isIntersecting: IsIntersecting; -}; diff --git a/packages/use-shader-fx/types/misc/useDomSyncer/utils/useUpdateDomRect.d.ts b/packages/use-shader-fx/types/misc/useDomSyncer/utils/useUpdateDomRect.d.ts deleted file mode 100644 index 7f942ba5..00000000 --- a/packages/use-shader-fx/types/misc/useDomSyncer/utils/useUpdateDomRect.d.ts +++ /dev/null @@ -1,16 +0,0 @@ -/// -import * as THREE from "three"; -import { DomSyncerParams } from ".."; -import { CustomParams } from "../../../utils/setUniforms"; -import { Size } from "../../../fxs/types"; -type UpdateDomRect = ({ params, customParams, size, resolutionRef, scene, isIntersectingRef, }: { - params: DomSyncerParams; - customParams?: CustomParams; - size: Size; - resolutionRef: React.MutableRefObject; - scene: THREE.Scene; - isIntersectingRef: React.MutableRefObject; -}) => void; -type UseUpdateDomRectReturn = [DOMRect[], UpdateDomRect]; -export declare const useUpdateDomRect: () => UseUpdateDomRectReturn; -export {}; diff --git a/packages/use-shader-fx/types/misc/useFPSLimiter.d.ts b/packages/use-shader-fx/types/misc/useFPSLimiter.d.ts deleted file mode 100644 index d3433567..00000000 --- a/packages/use-shader-fx/types/misc/useFPSLimiter.d.ts +++ /dev/null @@ -1,14 +0,0 @@ -import * as THREE from "three"; -/** - * @param fps FPS you want to limit , default : `60` - * - * ```tsx - * const limiter = useFPSLimiter(fps); - * useFrame((props) => { - * if (limiter(props.clock)) { - * //some code - * } - * }); - * ``` - */ -export declare const useFPSLimiter: (fps?: number) => (clock: THREE.Clock) => boolean; diff --git a/packages/use-shader-fx/types/misc/usePointer.d.ts b/packages/use-shader-fx/types/misc/usePointer.d.ts deleted file mode 100644 index 3d13a115..00000000 --- a/packages/use-shader-fx/types/misc/usePointer.d.ts +++ /dev/null @@ -1,16 +0,0 @@ -import * as THREE from "three"; -export type PointerValues = { - currentPointer: THREE.Vector2; - prevPointer: THREE.Vector2; - diffPointer: THREE.Vector2; - velocity: THREE.Vector2; - isVelocityUpdate: boolean; -}; -type UpdatePointer = (currentPointer: THREE.Vector2) => PointerValues; -/** - * @description When given the pointer vector2 from r3f's RootState, it generates an update function that returns {`currentPointer`, `prevPointer`, `diffPointer`, `isVelocityUpdate`, `velocity`}. - * @description When calling custom in a `useFrame` loop, you can avoid duplication of execution by passing `pointerValues` to the update function of a Pointer-activated fxHook, such as `useBrush`. - * @param lerp 0~1, lerp intensity (0 to less than 1) , default : `0` - */ -export declare const usePointer: (lerp?: number) => UpdatePointer; -export {}; diff --git a/packages/use-shader-fx/types/utils/createMaterialParameters.d.ts b/packages/use-shader-fx/types/utils/createMaterialParameters.d.ts deleted file mode 100644 index 70f35f3f..00000000 --- a/packages/use-shader-fx/types/utils/createMaterialParameters.d.ts +++ /dev/null @@ -1,2 +0,0 @@ -import { OnBeforeInitParameters } from "../fxs/types"; -export declare const createMaterialParameters: (parameters: OnBeforeInitParameters, onBeforeInit?: ((parameters: OnBeforeInitParameters) => void) | undefined) => OnBeforeInitParameters; diff --git a/packages/use-shader-fx/types/utils/getDpr.d.ts b/packages/use-shader-fx/types/utils/getDpr.d.ts deleted file mode 100644 index fb38dcca..00000000 --- a/packages/use-shader-fx/types/utils/getDpr.d.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { Dpr } from "../fxs/types"; -export declare const getDpr: (dpr: Dpr) => { - shader: number | false; - fbo: number | false; -}; diff --git a/packages/use-shader-fx/types/utils/setUniforms.d.ts b/packages/use-shader-fx/types/utils/setUniforms.d.ts deleted file mode 100644 index 306c48b8..00000000 --- a/packages/use-shader-fx/types/utils/setUniforms.d.ts +++ /dev/null @@ -1,17 +0,0 @@ -import * as THREE from "three"; -type UniformValue = THREE.CubeTexture | THREE.Texture | Int32Array | Float32Array | THREE.Matrix4 | THREE.Matrix3 | THREE.Quaternion | THREE.Vector4 | THREE.Vector3 | THREE.Vector2 | THREE.Color | number | boolean | Array | null | undefined; -type UniformObject = { - [key: string]: { - value: UniformValue; - }; -}; -export declare const setUniform: (material: { - uniforms: T; -}) => (key: keyof T, value: UniformValue) => void; -export type CustomParams = { - [uniform: string]: UniformValue; -}; -export declare const setCustomUniform: (material: { - uniforms: UniformObject; -}) => (customParams: CustomParams | undefined) => void; -export {}; diff --git a/packages/use-shader-fx/types/utils/useAddMesh.d.ts b/packages/use-shader-fx/types/utils/useAddMesh.d.ts deleted file mode 100644 index e00d3d01..00000000 --- a/packages/use-shader-fx/types/utils/useAddMesh.d.ts +++ /dev/null @@ -1,3 +0,0 @@ -import * as THREE from "three"; -/** Generate mesh from geometry and material and add to scene */ -export declare const useAddMesh: (scene: THREE.Scene, geometry: THREE.BufferGeometry, material: THREE.Material) => THREE.Mesh, THREE.Material, THREE.Object3DEventMap>; diff --git a/packages/use-shader-fx/types/utils/useAddObject.d.ts b/packages/use-shader-fx/types/utils/useAddObject.d.ts deleted file mode 100644 index 99a407f6..00000000 --- a/packages/use-shader-fx/types/utils/useAddObject.d.ts +++ /dev/null @@ -1,7 +0,0 @@ -import * as THREE from "three"; -type Object3DConstructor = new (geometry: THREE.BufferGeometry, material: M) => T; -/** - * Add geometry and material to Object3D and add them to scene. - */ -export declare const useAddObject: , M extends THREE.Material>(scene: THREE.Scene | false, geometry: THREE.BufferGeometry, material: M, Proto: Object3DConstructor) => T; -export {}; diff --git a/packages/use-shader-fx/types/utils/useCamera.d.ts b/packages/use-shader-fx/types/utils/useCamera.d.ts deleted file mode 100644 index 4d01d7eb..00000000 --- a/packages/use-shader-fx/types/utils/useCamera.d.ts +++ /dev/null @@ -1,3 +0,0 @@ -import * as THREE from "three"; -import { Size } from "../fxs/types"; -export declare const useCamera: (size: Size, cameraType?: "OrthographicCamera" | "PerspectiveCamera") => THREE.OrthographicCamera | THREE.PerspectiveCamera; diff --git a/packages/use-shader-fx/types/utils/useDoubleFBO.d.ts b/packages/use-shader-fx/types/utils/useDoubleFBO.d.ts deleted file mode 100644 index bcd8554f..00000000 --- a/packages/use-shader-fx/types/utils/useDoubleFBO.d.ts +++ /dev/null @@ -1,25 +0,0 @@ -import * as THREE from "three"; -import { UseFboProps } from "./useSingleFBO"; -export type DoubleRenderTarget = { - read: THREE.WebGLRenderTarget; - write: THREE.WebGLRenderTarget; -}; -type FBOUpdateFunction = (gl: THREE.WebGLRenderer, -/** call before FBO is rendered */ -onBeforeRender?: ({ read, write, }: { - read: THREE.Texture; - write: THREE.Texture; -}) => void) => THREE.Texture; -type UseDoubleFBOReturn = [ - { - read: THREE.WebGLRenderTarget; - write: THREE.WebGLRenderTarget; - }, - FBOUpdateFunction -]; -/** - * @description Custom hook for setting up double buffering with WebGL render targets. - * @param UseFboProps same as `useSingleFBO` - */ -export declare const useDoubleFBO: (props: UseFboProps) => UseDoubleFBOReturn; -export {}; diff --git a/packages/use-shader-fx/types/utils/useParams.d.ts b/packages/use-shader-fx/types/utils/useParams.d.ts deleted file mode 100644 index 012d0b59..00000000 --- a/packages/use-shader-fx/types/utils/useParams.d.ts +++ /dev/null @@ -1,7 +0,0 @@ -type SetParams = (newParams?: Partial) => void; -type UseParamsReturn = [T, SetParams]; -/** - * @param params Receives an initial value object. With structuredClone, deep copy and set, but if the object contains a function, just set it. - */ -export declare const useParams: (params: T) => UseParamsReturn; -export {}; diff --git a/packages/use-shader-fx/types/utils/useResizeBoundary.d.ts b/packages/use-shader-fx/types/utils/useResizeBoundary.d.ts deleted file mode 100644 index c25f350d..00000000 --- a/packages/use-shader-fx/types/utils/useResizeBoundary.d.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { Size } from "../fxs/types"; -export declare const useResizeBoundary: ({ size, boundFor, threshold, }: { - size: Size; - boundFor: "smaller" | "larger" | "both"; - threshold: number; -}) => boolean; diff --git a/packages/use-shader-fx/types/utils/useResolution.d.ts b/packages/use-shader-fx/types/utils/useResolution.d.ts deleted file mode 100644 index 9b2c7080..00000000 --- a/packages/use-shader-fx/types/utils/useResolution.d.ts +++ /dev/null @@ -1,6 +0,0 @@ -import * as THREE from "three"; -import { Size } from "../fxs/types"; -/** - * @params dpr if dpr is set, it returns the resolution which is size multiplied by dpr. - */ -export declare const useResolution: (size: Size, dpr?: number | false) => THREE.Vector2; diff --git a/packages/use-shader-fx/types/utils/useSingleFBO.d.ts b/packages/use-shader-fx/types/utils/useSingleFBO.d.ts deleted file mode 100644 index 9c1256c1..00000000 --- a/packages/use-shader-fx/types/utils/useSingleFBO.d.ts +++ /dev/null @@ -1,36 +0,0 @@ -import * as THREE from "three"; -import { Size } from "../fxs/types"; -export declare const FBO_DEFAULT_OPTION: THREE.RenderTargetOptions; -export type UseFboProps = { - scene: THREE.Scene; - camera: THREE.Camera; - size: Size; - /** If dpr is set, dpr will be multiplied, default : `false` */ - dpr?: number | false; - /** Whether to resize when resizing occurs. If isDpr is true, set FBO to setSize even if dpr is changed, default : `false` */ - isSizeUpdate?: boolean; - /** If set, the scene depth will be rendered into buffer.depthTexture. default : `false` */ - depth?: boolean; -} & THREE.RenderTargetOptions; -export declare const renderFBO: ({ gl, fbo, scene, camera, onBeforeRender, onSwap, }: { - gl: THREE.WebGLRenderer; - fbo: THREE.WebGLRenderTarget; - scene: THREE.Scene; - camera: THREE.Camera; - onBeforeRender: () => void; - onSwap?: (() => void) | undefined; -}) => void; -type UpdateRenderTarget = (gl: THREE.WebGLRenderer, -/** call before FBO is rendered */ -onBeforeRender?: ({ read }: { - read: THREE.Texture; -}) => void) => THREE.Texture; -type UseSingleFBOReturn = [THREE.WebGLRenderTarget, UpdateRenderTarget]; -/** - * @param dpr If dpr is set, dpr will be multiplied, default:false - * @param isSizeUpdate Whether to resize when resizing occurs. If isDpr is true, set FBO to setSize even if dpr is changed, default:false - * @param depthBuffer Unlike the default in three.js, the default is `false`. - * @returns [THREE.WebGLRenderTarget , updateFBO] -Receives the RenderTarget as the first argument and the update function as the second argument. - */ -export declare const useSingleFBO: (props: UseFboProps) => UseSingleFBOReturn; -export {}; From 4afc0bd6aaa326f47267b5b55976f0ff8591d7ab Mon Sep 17 00:00:00 2001 From: takuma-hmng8 Date: Wed, 18 Sep 2024 19:27:13 +0900 Subject: [PATCH 02/60] wip --- app/v2/FxMaterial.tsx | 9 +- app/v2/Playground.tsx | 75 ++++++++- .../src/fxs/materials/FxBlendingMaterial.ts | 46 ++++++ .../src/fxs/materials/FxMaterial.ts | 15 +- packages/use-shader-fx/src/fxs/types/index.ts | 5 +- .../use-shader-fx/src/fxs/useFluid/index.ts | 147 +++++++++--------- .../useFluid/materials/AdvectionMaterial.ts | 7 +- .../useFluid/materials/DivergenceMaterial.ts | 9 +- .../fxs/useFluid/materials/PoissonMaterial.ts | 10 +- .../useFluid/materials/PressureMaterial.ts | 9 +- .../fxs/useFluid/materials/SplatMaterial.ts | 13 +- .../useFluid/materials/shaders/advection.frag | 10 +- .../materials/shaders/divergence.frag | 20 ++- .../fxs/useFluid/materials/shaders/face.vert | 17 -- .../useFluid/materials/shaders/poisson.frag | 20 ++- .../useFluid/materials/shaders/pressure.frag | 28 ++-- .../fxs/useFluid/materials/shaders/splat.frag | 1 + .../fxs/useFluid/materials/shaders/splat.vert | 12 -- .../fxs/useFluid/materials/shaders/vertex.ts | 82 ++++++++++ .../src/fxs/useFluid/scenes/useAdvection.ts | 46 ++++++ .../src/fxs/useFluid/scenes/useDivergence.ts | 41 +++++ .../src/fxs/useFluid/scenes/usePoisson.ts | 45 ++++++ .../src/fxs/useFluid/scenes/usePressure.ts | 42 +++++ .../src/fxs/useFluid/scenes/useSplat.ts | 51 ++++++ .../src/fxs/useFluid/useAdvection.ts | 51 ------ .../src/fxs/useFluid/useDivergence.ts | 47 ------ .../src/fxs/useFluid/usePoisson.ts | 50 ------ .../src/fxs/useFluid/usePressure.ts | 48 ------ .../src/fxs/useFluid/useSplat.ts | 49 ------ .../src/fxs/useNoise/NoiseMaterial.ts | 19 ++- .../use-shader-fx/src/fxs/useNoise/index.ts | 63 ++++---- .../use-shader-fx/src/fxs/useNoise/noise.frag | 16 +- .../src/libs/shaders/ShaderChunk.ts | 14 +- .../src/libs/shaders/resolveShaders.ts | 13 ++ .../shaders/shaderChunk/blendingColor.glsl | 11 ++ .../shaderChunk/blendingPlaneVertex.glsl | 21 +++ .../shaders/shaderChunk/blendingUniforms.glsl | 7 + .../libs/shaders/shaderChunk/fxBlending.glsl | 6 - .../utils/{useAddObject.ts => useObject3D.ts} | 5 +- packages/use-shader-fx/src/utils/useScene.ts | 61 ++++++++ .../use-shader-fx/src/utils/useSingleFBO.ts | 5 +- todo | 2 + 42 files changed, 776 insertions(+), 472 deletions(-) create mode 100644 packages/use-shader-fx/src/fxs/materials/FxBlendingMaterial.ts delete mode 100644 packages/use-shader-fx/src/fxs/useFluid/materials/shaders/face.vert delete mode 100644 packages/use-shader-fx/src/fxs/useFluid/materials/shaders/splat.vert create mode 100644 packages/use-shader-fx/src/fxs/useFluid/materials/shaders/vertex.ts create mode 100644 packages/use-shader-fx/src/fxs/useFluid/scenes/useAdvection.ts create mode 100644 packages/use-shader-fx/src/fxs/useFluid/scenes/useDivergence.ts create mode 100644 packages/use-shader-fx/src/fxs/useFluid/scenes/usePoisson.ts create mode 100644 packages/use-shader-fx/src/fxs/useFluid/scenes/usePressure.ts create mode 100644 packages/use-shader-fx/src/fxs/useFluid/scenes/useSplat.ts delete mode 100644 packages/use-shader-fx/src/fxs/useFluid/useAdvection.ts delete mode 100644 packages/use-shader-fx/src/fxs/useFluid/useDivergence.ts delete mode 100644 packages/use-shader-fx/src/fxs/useFluid/usePoisson.ts delete mode 100644 packages/use-shader-fx/src/fxs/useFluid/usePressure.ts delete mode 100644 packages/use-shader-fx/src/fxs/useFluid/useSplat.ts create mode 100644 packages/use-shader-fx/src/libs/shaders/resolveShaders.ts create mode 100644 packages/use-shader-fx/src/libs/shaders/shaderChunk/blendingColor.glsl create mode 100644 packages/use-shader-fx/src/libs/shaders/shaderChunk/blendingPlaneVertex.glsl create mode 100644 packages/use-shader-fx/src/libs/shaders/shaderChunk/blendingUniforms.glsl delete mode 100644 packages/use-shader-fx/src/libs/shaders/shaderChunk/fxBlending.glsl rename packages/use-shader-fx/src/utils/{useAddObject.ts => useObject3D.ts} (89%) create mode 100644 packages/use-shader-fx/src/utils/useScene.ts create mode 100644 todo diff --git a/app/v2/FxMaterial.tsx b/app/v2/FxMaterial.tsx index 80a45ce3..e8459506 100644 --- a/app/v2/FxMaterial.tsx +++ b/app/v2/FxMaterial.tsx @@ -32,17 +32,16 @@ export const FxMaterial = shaderMaterial( void main() { vec2 uv = vUv; + // vec4 color = texture2D(u_fx, uv); - // gl_FragColor = vec4(vec3(color.rgb),1.); - // // gl_FragColor.rgb = color.rgb; - // // gl_FragColor.a = color.r + color.g + color.b; + // gl_FragColor = vec4(color.rgb,1.); vec2 vel = texture2D(u_fx, uv).xy; float len = length(vel); vel = vel * 0.5 + 0.5; - vec3 color = vec3(vel.x, vel.y, 1.0); - color = mix(vec3(1.0), color, len); + vec3 color = vec3(vel.x, vel.y, len); + color = mix(vec3(0.), color, len); gl_FragColor = vec4(color, 1.0); } diff --git a/app/v2/Playground.tsx b/app/v2/Playground.tsx index 1a644f5c..39c274f7 100644 --- a/app/v2/Playground.tsx +++ b/app/v2/Playground.tsx @@ -1,30 +1,93 @@ "use client"; import * as THREE from "three"; -import { useEffect, useMemo, useRef, useState } from "react"; +import { useCallback, useEffect, useMemo, useRef, useState } from "react"; import { useFrame, useThree, extend, useLoader } from "@react-three/fiber"; import { useNoise, useFluid } from "@/packages/use-shader-fx/src"; import { FxMaterial } from "./FxMaterial"; +import { Float, OrbitControls, useVideoTexture } from "@react-three/drei"; + +/*=============================================== +# webglooの設計 + +- useFxResolverでhookを切り替える +===============================================*/ extend({ FxMaterial }); +// ここに渡すstateでレンダリングを切り替える +const useFxResolver = (test: boolean) => { + if (test) { + return useNoise; + } else { + return useFluid; + } +}; + export const Playground = () => { - const { size, gl } = useThree(); + const { size } = useThree(); + + // const currentHook = useFxResolver(true); + // const noise = currentHook({ + // size, + // dpr: 0.15, + // }); + + // const fluid = useFluid({ + // size, + // dpr: 0.5, + // }); - const fluid = useFluid({ + const funkun_mov = useVideoTexture("/FT_Ch02-comp.mp4", { + width: 1280, + height: 720, + }); + + const [gear] = useLoader(THREE.TextureLoader, [ + "/stickers/webp/sticker2.webp", + ]); + + const noise = useNoise({ size, - dpr: 0.5, + dpr: 0.1, + fxBlending: true, + fxBlendingSrc: gear, + alphaBlending: 1, + uvBlending: 0.1, + fxBlendingSrcResolution: new THREE.Vector2(1024, 1024), }); + // noise.material.warp = new THREE.Vector2(2.0, 2.0); + + // noise.material.onBeforeCompile = useCallback((shader) => { + // console.log(shader.vertexShader); + // }, []); + + // const material = useMemo(() => { + // const _mat = new THREE.MeshPhysicalMaterial(); + // _mat.color = new THREE.Color("red"); + // _mat.roughness = 1; + // return _mat; + // }, []); + // const mesh = useRef(null); + useFrame((state) => { - fluid.render(state); + // fluid.render(state); + noise.render(state); + // material.color = new THREE.Color( + // Math.sin(state.clock.getElapsedTime()), + // 1, + // 1 + // ); + // mesh.current!.rotation.x += 0.01; + // mesh.current!.rotation.y += 0.01; }); return ( <> - + ); diff --git a/packages/use-shader-fx/src/fxs/materials/FxBlendingMaterial.ts b/packages/use-shader-fx/src/fxs/materials/FxBlendingMaterial.ts new file mode 100644 index 00000000..03dea2d0 --- /dev/null +++ b/packages/use-shader-fx/src/fxs/materials/FxBlendingMaterial.ts @@ -0,0 +1,46 @@ +import * as THREE from "three"; +import { DEFAULT_TEXTURE } from "../../libs/constants"; +import { + resolveIncludes, + includePattern, +} from "../../libs/shaders/resolveShaders"; +import { FxMaterial } from "./FxMaterial"; + +export type FxBlendingUniforms = { + fxBlendingSrc: { value: THREE.Texture }; + uvBlending: { value: number }; + alphaBlending: { value: number }; + fxBlendingSrcResolution: { value: THREE.Vector2 }; + // TODO * resolutionはFXMaterialで定義しようかな。全部にあるべきだし + resolution: { value: THREE.Vector2 }; +}; + +export class FxBlendingMaterial extends FxMaterial { + fxBlending: boolean; + blendingUniforms: FxBlendingUniforms; + + constructor(parameters = {}) { + super(); + + this.fxBlending = false; + + this.blendingUniforms = { + fxBlendingSrc: { value: DEFAULT_TEXTURE }, + uvBlending: { value: 0 }, + alphaBlending: { value: 0 }, + resolution: { value: new THREE.Vector2() }, + fxBlendingSrcResolution: { value: new THREE.Vector2() }, + }; + + super.setValues(parameters); + } + + resolveBlendingShader(vertexShader: string, fragmentShader: string) { + this.vertexShader = this.fxBlending + ? resolveIncludes(vertexShader) + : vertexShader.replace(includePattern, ""); + this.fragmentShader = this.fxBlending + ? resolveIncludes(fragmentShader) + : fragmentShader.replace(includePattern, ""); + } +} diff --git a/packages/use-shader-fx/src/fxs/materials/FxMaterial.ts b/packages/use-shader-fx/src/fxs/materials/FxMaterial.ts index 855d9a1e..f12d60f1 100644 --- a/packages/use-shader-fx/src/fxs/materials/FxMaterial.ts +++ b/packages/use-shader-fx/src/fxs/materials/FxMaterial.ts @@ -23,20 +23,7 @@ export class FxMaterial extends THREE.ShaderMaterial { return; } - const currentValue = curretUniform.value; - - if (currentValue && currentValue.isColor) { - currentValue.set(newValue); - } else if ( - currentValue && - currentValue.isVector3 && - newValue && - newValue.isVector3 - ) { - currentValue.copy(newValue); - } else { - curretUniform.value = newValue; - } + curretUniform.value = newValue; } } } diff --git a/packages/use-shader-fx/src/fxs/types/index.ts b/packages/use-shader-fx/src/fxs/types/index.ts index 4cd4befc..9fd8338f 100644 --- a/packages/use-shader-fx/src/fxs/types/index.ts +++ b/packages/use-shader-fx/src/fxs/types/index.ts @@ -34,10 +34,10 @@ export interface HooksProps { * @param depthBuffer Unlike the default in three.js, the default is `false`. */ renderTargetOptions?: THREE.RenderTargetOptions; + materialParameters?: THREE.MaterialParameters; + fxBlending?: boolean; } -export type OnInit = (material: T) => void; - /** * @returns {HooksReturn} * render - Functions to update parameters and render. @@ -64,4 +64,5 @@ export type HooksReturn = { texture: THREE.Texture; material: M; scene: THREE.Scene; + camera: THREE.Camera; }; diff --git a/packages/use-shader-fx/src/fxs/useFluid/index.ts b/packages/use-shader-fx/src/fxs/useFluid/index.ts index 51a31e29..e5de41be 100644 --- a/packages/use-shader-fx/src/fxs/useFluid/index.ts +++ b/packages/use-shader-fx/src/fxs/useFluid/index.ts @@ -1,29 +1,25 @@ import * as THREE from "three"; import { useCallback, useMemo } from "react"; -import { useCamera } from "../../utils/useCamera"; import { UseFboProps, useSingleFBO } from "../../utils/useSingleFBO"; import { HooksProps, HooksReturn } from "../types"; import { getDpr } from "../../utils/getDpr"; -import { OnInit, RootState } from "../types"; -import { useAddObject } from "../../utils/useAddObject"; +import { RootState } from "../types"; import { useDoubleFBO } from "../../utils/useDoubleFBO"; -import { useAdvection } from "./useAdvection"; -import { useSplat } from "./useSplat"; -import { useDivergence } from "./useDivergence"; -import { usePoisson } from "./usePoisson"; -import { usePressure } from "./usePressure"; +import { useAdvection } from "./scenes/useAdvection"; +import { useSplat } from "./scenes/useSplat"; +import { useDivergence } from "./scenes/useDivergence"; +import { usePoisson } from "./scenes/usePoisson"; +import { usePressure } from "./scenes/usePressure"; + +export const DeltaTime = 0.015; export type FluidValues = {}; /*=============================================== -- mause周りの修正 -- 境界の作成 -- リファクタリング - - vertexShader、普通でいいのでは? - -useAddObject を useObject3Dに -sceneにいれたり、useObject3Dをする部分を、useSceneにまとめる - +- 出力でcolormapとvelocitymapを選択できるみたいな仕組みにする +- params + - velocity dissipation + - color dissipation (color map) ===============================================*/ /** @@ -31,24 +27,22 @@ sceneにいれたり、useObject3Dをする部分を、useSceneにまとめる * * It is a basic value noise with `fbm` and `domain warping` */ -export const useFluid = ( - { - size, - dpr, - sizeUpdate, - renderTargetOptions, - ...values - }: HooksProps & FluidValues, - onInit?: OnInit -): HooksReturn => { +export const useFluid = ({ + size, + dpr, + sizeUpdate, + renderTargetOptions, + ...values +}: HooksProps & FluidValues): HooksReturn => { const _dpr = getDpr(dpr); + // fbos const fboProps = useMemo( () => ({ dpr: _dpr.fbo, size, sizeUpdate, - type: THREE.FloatType, + type: THREE.HalfFloatType, ...renderTargetOptions, }), [size, _dpr.fbo, renderTargetOptions, sizeUpdate] @@ -58,58 +52,71 @@ export const useFluid = ( const [divergenceFBO, updateDivergenceFBO] = useSingleFBO(fboProps); const [pressureFBO, updatePressureFBO] = useDoubleFBO(fboProps); - const updateAdvection = useAdvection({ - size, - dpr: _dpr.shader, - velocity: velocity_0.texture, - updateRenderTarget: updateVelocity_1, - }); - const updateSplat = useSplat({ - size, - dpr: _dpr.shader, - updateRenderTarget: updateVelocity_1, - }); - const updateDivergence = useDivergence({ - size, - dpr: _dpr.shader, - velocity: velocity_1.texture, - updateRenderTarget: updateDivergenceFBO, - }); - const updatePoisson = usePoisson({ - size, - dpr: _dpr.shader, - divergence: divergenceFBO.texture, - updateRenderTarget: updatePressureFBO, - }); - const updatePressure = usePressure({ - size, - dpr: _dpr.shader, - velocity: velocity_1.texture, - pressure: pressureFBO.read.texture, - updateRenderTarget: updateVelocity_0, - }); + // scenes + const SceneSize = useMemo(() => ({ size, dpr: _dpr.shader }), [_dpr, size]); + const advection = useAdvection( + { + ...SceneSize, + velocity: velocity_0.texture, + }, + updateVelocity_1 + ); + const splat = useSplat( + { + ...SceneSize, + }, + updateVelocity_1 + ); + const divergence = useDivergence( + { + ...SceneSize, + velocity: velocity_1.texture, + }, + updateDivergenceFBO + ); + const poisson = usePoisson( + { + ...SceneSize, + divergence: divergenceFBO.texture, + }, + updatePressureFBO + ); + const pressure = usePressure( + { + ...SceneSize, + velocity: velocity_1.texture, + pressure: pressureFBO.read.texture, + }, + updateVelocity_0 + ); const setValues = useCallback((newValues: FluidValues) => { - // material.setUniformValues(newValues); + // splat.material.force = newValues.force; + // bounce の設定 + divergence.material.uniforms.isBounce.value = false; + poisson.material.uniforms.isBounce.value = false; + pressure.material.uniforms.isBounce.value = false; }, []); const render = useCallback( (rootState: RootState, newValues?: FluidValues) => { - updateAdvection(rootState); - updateSplat(rootState); - updateDivergence(rootState); - for (let i = 0; i < 32; i++) { - updatePoisson(rootState); - } - updatePressure(rootState); + newValues && setValues(newValues); + + advection.render(rootState); + splat.render(rootState); + divergence.render(rootState); + poisson.render(rootState); + pressure.render(rootState); + return velocity_0.texture; }, [ - updateAdvection, - updateDivergence, - updatePoisson, - updatePressure, - updateSplat, + setValues, + advection, + divergence, + poisson, + pressure, + splat, velocity_0.texture, ] ); diff --git a/packages/use-shader-fx/src/fxs/useFluid/materials/AdvectionMaterial.ts b/packages/use-shader-fx/src/fxs/useFluid/materials/AdvectionMaterial.ts index 67204095..c5a96397 100644 --- a/packages/use-shader-fx/src/fxs/useFluid/materials/AdvectionMaterial.ts +++ b/packages/use-shader-fx/src/fxs/useFluid/materials/AdvectionMaterial.ts @@ -1,8 +1,9 @@ import * as THREE from "three"; -import vertex from "./shaders/face.vert"; +import vertex from "./shaders/vertex"; import fragment from "./shaders/advection.frag"; import { FxMaterial } from "../../materials/FxMaterial"; import { DEFAULT_TEXTURE } from "../../../libs/constants"; +import { DeltaTime } from ".."; export class AdvectionMaterial extends FxMaterial { static get type() { @@ -25,10 +26,10 @@ export class AdvectionMaterial extends FxMaterial { texelsize: { value: new THREE.Vector2() }, ratio: { value: new THREE.Vector2() }, velocity: { value: DEFAULT_TEXTURE }, - dt: { value: 0.014 }, + dt: { value: DeltaTime }, }; - this.vertexShader = vertex; + this.vertexShader = vertex.advection; this.fragmentShader = fragment; this.setUniformValues(uniformValues); diff --git a/packages/use-shader-fx/src/fxs/useFluid/materials/DivergenceMaterial.ts b/packages/use-shader-fx/src/fxs/useFluid/materials/DivergenceMaterial.ts index f1862963..e086d200 100644 --- a/packages/use-shader-fx/src/fxs/useFluid/materials/DivergenceMaterial.ts +++ b/packages/use-shader-fx/src/fxs/useFluid/materials/DivergenceMaterial.ts @@ -1,8 +1,9 @@ import * as THREE from "three"; -import vertex from "./shaders/face.vert"; +import vertex from "./shaders/vertex"; import fragment from "./shaders/divergence.frag"; import { FxMaterial } from "../../materials/FxMaterial"; import { DEFAULT_TEXTURE } from "../../../libs/constants"; +import { DeltaTime } from ".."; export class DivergenceMaterial extends FxMaterial { static get type() { @@ -11,6 +12,7 @@ export class DivergenceMaterial extends FxMaterial { uniforms: { texelsize: { value: THREE.Vector2 }; + isBounce: { value: boolean }; velocity: { value: THREE.Texture }; dt: { value: number }; }; @@ -22,11 +24,12 @@ export class DivergenceMaterial extends FxMaterial { this.uniforms = { texelsize: { value: new THREE.Vector2() }, + isBounce: { value: true }, velocity: { value: DEFAULT_TEXTURE }, - dt: { value: 0.014 }, + dt: { value: DeltaTime }, }; - this.vertexShader = vertex; + this.vertexShader = vertex.main; this.fragmentShader = fragment; this.setUniformValues(uniformValues); diff --git a/packages/use-shader-fx/src/fxs/useFluid/materials/PoissonMaterial.ts b/packages/use-shader-fx/src/fxs/useFluid/materials/PoissonMaterial.ts index 02b370ef..d849fdc6 100644 --- a/packages/use-shader-fx/src/fxs/useFluid/materials/PoissonMaterial.ts +++ b/packages/use-shader-fx/src/fxs/useFluid/materials/PoissonMaterial.ts @@ -1,5 +1,5 @@ import * as THREE from "three"; -import vertex from "./shaders/face.vert"; +import vertex from "./shaders/vertex"; import fragment from "./shaders/poisson.frag"; import { FxMaterial } from "../../materials/FxMaterial"; import { DEFAULT_TEXTURE } from "../../../libs/constants"; @@ -11,10 +11,13 @@ export class PoissonMaterial extends FxMaterial { uniforms: { texelsize: { value: THREE.Vector2 }; + isBounce: { value: boolean }; pressure: { value: THREE.Texture }; divergence: { value: THREE.Texture }; }; + iteration: number; + constructor(uniformValues = {}, parameters = {}) { super(); @@ -22,11 +25,14 @@ export class PoissonMaterial extends FxMaterial { this.uniforms = { texelsize: { value: new THREE.Vector2() }, + isBounce: { value: true }, pressure: { value: DEFAULT_TEXTURE }, divergence: { value: DEFAULT_TEXTURE }, }; - this.vertexShader = vertex; + this.iteration = 32; + + this.vertexShader = vertex.poisson; this.fragmentShader = fragment; this.setUniformValues(uniformValues); diff --git a/packages/use-shader-fx/src/fxs/useFluid/materials/PressureMaterial.ts b/packages/use-shader-fx/src/fxs/useFluid/materials/PressureMaterial.ts index d826b63d..517357c7 100644 --- a/packages/use-shader-fx/src/fxs/useFluid/materials/PressureMaterial.ts +++ b/packages/use-shader-fx/src/fxs/useFluid/materials/PressureMaterial.ts @@ -1,8 +1,9 @@ import * as THREE from "three"; -import vertex from "./shaders/face.vert"; +import vertex from "./shaders/vertex"; import fragment from "./shaders/pressure.frag"; import { FxMaterial } from "../../materials/FxMaterial"; import { DEFAULT_TEXTURE } from "../../../libs/constants"; +import { DeltaTime } from ".."; export class PressureMaterial extends FxMaterial { static get type() { @@ -11,6 +12,7 @@ export class PressureMaterial extends FxMaterial { uniforms: { texelsize: { value: THREE.Vector2 }; + isBounce: { value: boolean }; pressure: { value: THREE.Texture }; velocity: { value: THREE.Texture }; dt: { value: number }; @@ -23,12 +25,13 @@ export class PressureMaterial extends FxMaterial { this.uniforms = { texelsize: { value: new THREE.Vector2() }, + isBounce: { value: true }, pressure: { value: DEFAULT_TEXTURE }, velocity: { value: DEFAULT_TEXTURE }, - dt: { value: 0.014 }, + dt: { value: DeltaTime }, }; - this.vertexShader = vertex; + this.vertexShader = vertex.main; this.fragmentShader = fragment; this.setUniformValues(uniformValues); diff --git a/packages/use-shader-fx/src/fxs/useFluid/materials/SplatMaterial.ts b/packages/use-shader-fx/src/fxs/useFluid/materials/SplatMaterial.ts index 701d326c..ea8af262 100644 --- a/packages/use-shader-fx/src/fxs/useFluid/materials/SplatMaterial.ts +++ b/packages/use-shader-fx/src/fxs/useFluid/materials/SplatMaterial.ts @@ -1,14 +1,15 @@ import * as THREE from "three"; -import vertex from "./shaders/splat.vert"; +import vertex from "./shaders/vertex"; import fragment from "./shaders/splat.frag"; import { FxMaterial } from "../../materials/FxMaterial"; -import { DEFAULT_TEXTURE } from "../../../libs/constants"; export class SplatMaterial extends FxMaterial { static get type() { return "SplatMaterial"; } + force: number; + uniforms: { texelsize: { value: THREE.Vector2 }; force: { value: THREE.Vector2 }; @@ -21,14 +22,16 @@ export class SplatMaterial extends FxMaterial { this.type = SplatMaterial.type; + this.force = 30; + this.uniforms = { texelsize: { value: new THREE.Vector2() }, - force: { value: new THREE.Vector2(10, 10) }, + force: { value: new THREE.Vector2(0, 0) }, center: { value: new THREE.Vector2(0, 0) }, - scale: { value: new THREE.Vector2(100, 100) }, + scale: { value: new THREE.Vector2(80, 80) }, }; - this.vertexShader = vertex; + this.vertexShader = vertex.splat; this.fragmentShader = fragment; this.blending = THREE.AdditiveBlending; diff --git a/packages/use-shader-fx/src/fxs/useFluid/materials/shaders/advection.frag b/packages/use-shader-fx/src/fxs/useFluid/materials/shaders/advection.frag index 9bb56987..193fbaf3 100644 --- a/packages/use-shader-fx/src/fxs/useFluid/materials/shaders/advection.frag +++ b/packages/use-shader-fx/src/fxs/useFluid/materials/shaders/advection.frag @@ -1,16 +1,14 @@ precision highp float; -uniform sampler2D velocity; uniform float dt; uniform vec2 ratio; -uniform vec2 texelsize; +uniform sampler2D velocity; + varying vec2 vUv; void main(){ - vec2 aspectratio = max(ratio.x, ratio.y) / ratio; - vec2 vel = texture2D(velocity, vUv).xy; - vec2 uv2 = vUv - vel * dt * aspectratio; + vec2 uv2 = vUv - vel * dt * ratio; vec2 newVel = texture2D(velocity, uv2).xy; gl_FragColor = vec4(newVel, 0.0, 0.0); -} +} \ No newline at end of file diff --git a/packages/use-shader-fx/src/fxs/useFluid/materials/shaders/divergence.frag b/packages/use-shader-fx/src/fxs/useFluid/materials/shaders/divergence.frag index 1d56e84a..d2776ffb 100644 --- a/packages/use-shader-fx/src/fxs/useFluid/materials/shaders/divergence.frag +++ b/packages/use-shader-fx/src/fxs/useFluid/materials/shaders/divergence.frag @@ -1,16 +1,20 @@ precision highp float; -uniform sampler2D velocity; uniform float dt; -uniform vec2 texelsize; +uniform sampler2D velocity; + varying vec2 vUv; +varying vec2 vL; +varying vec2 vR; +varying vec2 vT; +varying vec2 vB; void main(){ - float x0 = texture2D(velocity, vUv-vec2(texelsize.x, 0)).x; - float x1 = texture2D(velocity, vUv+vec2(texelsize.x, 0)).x; - float y0 = texture2D(velocity, vUv-vec2(0, texelsize.y)).y; - float y1 = texture2D(velocity, vUv+vec2(0, texelsize.y)).y; - float divergence = (x1-x0 + y1-y0) / 2.0; - + float L = texture2D(velocity, vL).r; + float R = texture2D(velocity, vR).r; + float B = texture2D(velocity, vB).g; + float T = texture2D(velocity, vT).g; + + float divergence = (R-L + T-B) / 2.0; gl_FragColor = vec4(divergence / dt); } diff --git a/packages/use-shader-fx/src/fxs/useFluid/materials/shaders/face.vert b/packages/use-shader-fx/src/fxs/useFluid/materials/shaders/face.vert deleted file mode 100644 index 173af906..00000000 --- a/packages/use-shader-fx/src/fxs/useFluid/materials/shaders/face.vert +++ /dev/null @@ -1,17 +0,0 @@ -precision highp float; - -uniform vec2 texelsize; -varying vec2 vUv; - -void main(){ - vec3 pos = position; - vec2 scale = 1.0 - texelsize * 2.0; - pos.xy = pos.xy * scale; - vUv = vec2(0.5)+(pos.xy)*0.5; - gl_Position = vec4(pos, 1.0); - - - // vUv = uv; - // gl_Position = vec4(position, 1.0); - -} diff --git a/packages/use-shader-fx/src/fxs/useFluid/materials/shaders/poisson.frag b/packages/use-shader-fx/src/fxs/useFluid/materials/shaders/poisson.frag index 93f76222..e56447f1 100644 --- a/packages/use-shader-fx/src/fxs/useFluid/materials/shaders/poisson.frag +++ b/packages/use-shader-fx/src/fxs/useFluid/materials/shaders/poisson.frag @@ -1,17 +1,25 @@ precision highp float; + +uniform vec2 texelsize; uniform sampler2D pressure; uniform sampler2D divergence; -uniform vec2 texelsize; + varying vec2 vUv; +varying vec2 vL; +varying vec2 vR; +varying vec2 vT; +varying vec2 vB; void main(){ - float p0 = texture2D(pressure, vUv+vec2(texelsize.x * 2.0, 0)).r; - float p1 = texture2D(pressure, vUv-vec2(texelsize.x * 2.0, 0)).r; - float p2 = texture2D(pressure, vUv+vec2(0, texelsize.y * 2.0 )).r; - float p3 = texture2D(pressure, vUv-vec2(0, texelsize.y * 2.0 )).r; + float L = texture2D(pressure, vL).r; + float R = texture2D(pressure, vR).r; + float B = texture2D(pressure, vB).r; + float T = texture2D(pressure, vT).r; + float div = texture2D(divergence, vUv).r; - float newP = (p0 + p1 + p2 + p3) / 4.0 - div; + float newP = (L + R + B + T) / 4.0 - div; + gl_FragColor = vec4(newP); } diff --git a/packages/use-shader-fx/src/fxs/useFluid/materials/shaders/pressure.frag b/packages/use-shader-fx/src/fxs/useFluid/materials/shaders/pressure.frag index e08aa858..51d18a92 100644 --- a/packages/use-shader-fx/src/fxs/useFluid/materials/shaders/pressure.frag +++ b/packages/use-shader-fx/src/fxs/useFluid/materials/shaders/pressure.frag @@ -1,21 +1,27 @@ precision highp float; -uniform sampler2D pressure; -uniform sampler2D velocity; uniform vec2 texelsize; uniform float dt; +uniform sampler2D pressure; +uniform sampler2D velocity; + varying vec2 vUv; +varying vec2 vL; +varying vec2 vR; +varying vec2 vT; +varying vec2 vB; void main(){ - float step = 1.0; - float p0 = texture2D(pressure, vUv+vec2(texelsize.x * step, 0)).r; - float p1 = texture2D(pressure, vUv-vec2(texelsize.x * step, 0)).r; - float p2 = texture2D(pressure, vUv+vec2(0, texelsize.y * step)).r; - float p3 = texture2D(pressure, vUv-vec2(0, texelsize.y * step)).r; + float L = texture2D(pressure, vL).r; + float R = texture2D(pressure, vR).r; + float B = texture2D(pressure, vB).r; + float T = texture2D(pressure, vT).r; + + vec2 v = texture2D(velocity, vUv).xy; + vec2 gradP = vec2(R - L, T - B) * 0.5; + v = v - gradP * dt; + + gl_FragColor = vec4(v, 0.0, 1.0); - vec2 v = texture2D(velocity, vUv).xy; - vec2 gradP = vec2(p0 - p1, p2 - p3) * 0.5; - v = v - gradP * dt; - gl_FragColor = vec4(v, 0.0, 1.0); } \ No newline at end of file diff --git a/packages/use-shader-fx/src/fxs/useFluid/materials/shaders/splat.frag b/packages/use-shader-fx/src/fxs/useFluid/materials/shaders/splat.frag index c3ab0ab4..74029e38 100644 --- a/packages/use-shader-fx/src/fxs/useFluid/materials/shaders/splat.frag +++ b/packages/use-shader-fx/src/fxs/useFluid/materials/shaders/splat.frag @@ -2,6 +2,7 @@ precision highp float; uniform vec2 force; uniform vec2 center; + varying vec2 vUv; void main(){ diff --git a/packages/use-shader-fx/src/fxs/useFluid/materials/shaders/splat.vert b/packages/use-shader-fx/src/fxs/useFluid/materials/shaders/splat.vert deleted file mode 100644 index 62e25891..00000000 --- a/packages/use-shader-fx/src/fxs/useFluid/materials/shaders/splat.vert +++ /dev/null @@ -1,12 +0,0 @@ -precision highp float; - -uniform vec2 center; -uniform vec2 scale; -uniform vec2 texelsize; -varying vec2 vUv; - -void main(){ - vec2 pos = position.xy * scale * 2.0 * texelsize + center; - vUv = uv; - gl_Position = vec4(pos, 0.0, 1.0); -} \ No newline at end of file diff --git a/packages/use-shader-fx/src/fxs/useFluid/materials/shaders/vertex.ts b/packages/use-shader-fx/src/fxs/useFluid/materials/shaders/vertex.ts new file mode 100644 index 00000000..8fe12846 --- /dev/null +++ b/packages/use-shader-fx/src/fxs/useFluid/materials/shaders/vertex.ts @@ -0,0 +1,82 @@ +const base = ` + precision highp float; + + uniform vec2 texelsize; + varying vec2 vUv; +`; + +const boxVarying = ` + uniform bool isBounce; + varying vec2 vL; + varying vec2 vR; + varying vec2 vT; + varying vec2 vB; +`; + +const getPosition = (isBounce: boolean = true) => { + return ` + vec3 pos = position; + vec2 scale = ${ + isBounce + ? "isBounce ? vec2(1.,1.) : 1.-texelsize*2." + : "1.-texelsize*2." + }; + pos.xy = pos.xy * scale; + vUv = vec2(.5)+(pos.xy)*.5; + `; +}; + +const getBoxCompute = (diff: string) => { + return ` + vL = vUv - vec2(texelsize.x * ${diff}, 0.0); + vR = vUv + vec2(texelsize.x * ${diff}, 0.0); + vT = vUv + vec2(0.0, texelsize.y * ${diff}); + vB = vUv - vec2(0.0, texelsize.y * ${diff}); + `; +}; + +const vertex = { + main: ` + ${base} + ${boxVarying} + + void main(){ + + ${getPosition()} + ${getBoxCompute("1.")} + + gl_Position = vec4(pos, 1.0); + } + `, + poisson: ` + ${base} + ${boxVarying} + + void main(){ + + ${getPosition()} + ${getBoxCompute("2.")} + + gl_Position = vec4(pos, 1.0); + } + `, + advection: ` + ${base} + void main(){ + ${getPosition(false)} + gl_Position = vec4(pos, 1.0); + } + `, + splat: ` + ${base} + uniform vec2 center; + uniform vec2 scale; + void main(){ + vec2 pos = position.xy * scale * 2.0 * texelsize + center; + vUv = uv; + gl_Position = vec4(pos, 0.0, 1.0); + } + `, +}; + +export default vertex; diff --git a/packages/use-shader-fx/src/fxs/useFluid/scenes/useAdvection.ts b/packages/use-shader-fx/src/fxs/useFluid/scenes/useAdvection.ts new file mode 100644 index 00000000..0b722db1 --- /dev/null +++ b/packages/use-shader-fx/src/fxs/useFluid/scenes/useAdvection.ts @@ -0,0 +1,46 @@ +import * as THREE from "three"; +import { useCallback, useMemo } from "react"; +import { useCamera } from "../../../utils/useCamera"; +import { Dpr, RootState, Size } from "../../types"; +import { AdvectionMaterial } from "../materials/AdvectionMaterial"; +import { SingleFBOUpdateFunction } from "../../../utils/useSingleFBO"; +import { useResolution } from "../../../utils/useResolution"; +import { useScene } from "../../../utils/useScene"; + +export const useAdvection = ( + { + size, + dpr, + ...values + }: { + size: Size; + dpr: number | false; + velocity: THREE.Texture; + }, + updateRenderTarget: SingleFBOUpdateFunction +) => { + const { scene, material } = useScene({ + material: AdvectionMaterial, + uniformValues: values, + }); + + const resolution = useResolution(size, dpr); + material.uniforms.texelsize.value.set(1 / resolution.x, 1 / resolution.y); + const maxAspect = Math.max(size.width, size.height); + material.uniforms.ratio.value.set( + maxAspect / resolution.x, + maxAspect / resolution.y + ); + + const camera = useCamera(size); + + const render = useCallback( + (rootState: RootState) => { + const { gl } = rootState; + updateRenderTarget({ gl, scene, camera }); + }, + [updateRenderTarget, scene, camera] + ); + + return { render, material }; +}; diff --git a/packages/use-shader-fx/src/fxs/useFluid/scenes/useDivergence.ts b/packages/use-shader-fx/src/fxs/useFluid/scenes/useDivergence.ts new file mode 100644 index 00000000..ab0c1675 --- /dev/null +++ b/packages/use-shader-fx/src/fxs/useFluid/scenes/useDivergence.ts @@ -0,0 +1,41 @@ +import * as THREE from "three"; +import { useCallback, useMemo } from "react"; +import { useCamera } from "../../../utils/useCamera"; +import { Dpr, RootState, Size } from "../../types"; +import { SingleFBOUpdateFunction } from "../../../utils/useSingleFBO"; +import { useResolution } from "../../../utils/useResolution"; +import { DivergenceMaterial } from "../materials/DivergenceMaterial"; +import { useScene } from "../../../utils/useScene"; + +export const useDivergence = ( + { + size, + dpr, + ...values + }: { + size: Size; + dpr: number | false; + velocity: THREE.Texture; + }, + updateRenderTarget: SingleFBOUpdateFunction +) => { + const { scene, material } = useScene({ + material: DivergenceMaterial, + uniformValues: values, + }); + + const resolution = useResolution(size, dpr); + material.uniforms.texelsize.value.set(1 / resolution.x, 1 / resolution.y); + + const camera = useCamera(size); + + const render = useCallback( + (rootState: RootState) => { + const { gl } = rootState; + updateRenderTarget({ gl, scene, camera }); + }, + [updateRenderTarget, scene, camera] + ); + + return { render, material }; +}; diff --git a/packages/use-shader-fx/src/fxs/useFluid/scenes/usePoisson.ts b/packages/use-shader-fx/src/fxs/useFluid/scenes/usePoisson.ts new file mode 100644 index 00000000..076d6411 --- /dev/null +++ b/packages/use-shader-fx/src/fxs/useFluid/scenes/usePoisson.ts @@ -0,0 +1,45 @@ +import * as THREE from "three"; +import { useCallback, useMemo } from "react"; +import { useCamera } from "../../../utils/useCamera"; +import { Dpr, RootState, Size } from "../../types"; +import { SingleFBOUpdateFunction } from "../../../utils/useSingleFBO"; +import { useResolution } from "../../../utils/useResolution"; +import { PoissonMaterial } from "../materials/PoissonMaterial"; +import { useScene } from "../../../utils/useScene"; + +export const usePoisson = ( + { + size, + dpr, + ...values + }: { + size: Size; + dpr: number | false; + divergence: THREE.Texture; + }, + updateRenderTarget: SingleFBOUpdateFunction +) => { + const { scene, material } = useScene({ + material: PoissonMaterial, + uniformValues: values, + }); + + const resolution = useResolution(size, dpr); + material.uniforms.texelsize.value.set(1 / resolution.x, 1 / resolution.y); + + const camera = useCamera(size); + + const render = useCallback( + (rootState: RootState) => { + const { gl } = rootState; + for (let i = 0; i < material.iteration; i++) { + updateRenderTarget({ gl, scene, camera }, ({ read }) => { + material.uniforms.pressure.value = read; + }); + } + }, + [updateRenderTarget, material, scene, camera] + ); + + return { render, material }; +}; diff --git a/packages/use-shader-fx/src/fxs/useFluid/scenes/usePressure.ts b/packages/use-shader-fx/src/fxs/useFluid/scenes/usePressure.ts new file mode 100644 index 00000000..0d5fb120 --- /dev/null +++ b/packages/use-shader-fx/src/fxs/useFluid/scenes/usePressure.ts @@ -0,0 +1,42 @@ +import * as THREE from "three"; +import { useCallback, useMemo } from "react"; +import { useCamera } from "../../../utils/useCamera"; +import { RootState, Size } from "../../types"; +import { SingleFBOUpdateFunction } from "../../../utils/useSingleFBO"; +import { useResolution } from "../../../utils/useResolution"; +import { PressureMaterial } from "../materials/PressureMaterial"; +import { useScene } from "../../../utils/useScene"; + +export const usePressure = ( + { + size, + dpr, + ...values + }: { + size: Size; + dpr: number | false; + velocity: THREE.Texture; + pressure: THREE.Texture; + }, + updateRenderTarget: SingleFBOUpdateFunction +) => { + const { scene, material } = useScene({ + material: PressureMaterial, + uniformValues: values, + }); + + const resolution = useResolution(size, dpr); + material.uniforms.texelsize.value.set(1 / resolution.x, 1 / resolution.y); + + const camera = useCamera(size); + + const render = useCallback( + (rootState: RootState) => { + const { gl } = rootState; + updateRenderTarget({ gl, scene, camera }); + }, + [updateRenderTarget, scene, camera] + ); + + return { render, material }; +}; diff --git a/packages/use-shader-fx/src/fxs/useFluid/scenes/useSplat.ts b/packages/use-shader-fx/src/fxs/useFluid/scenes/useSplat.ts new file mode 100644 index 00000000..2b3942d7 --- /dev/null +++ b/packages/use-shader-fx/src/fxs/useFluid/scenes/useSplat.ts @@ -0,0 +1,51 @@ +import * as THREE from "three"; +import { useCallback, useMemo } from "react"; +import { useCamera } from "../../../utils/useCamera"; +import { RootState, Size } from "../../types"; +import { SingleFBOUpdateFunction } from "../../../utils/useSingleFBO"; +import { useResolution } from "../../../utils/useResolution"; +import { SplatMaterial } from "../materials/SplatMaterial"; +import { usePointer } from "../../../misc/usePointer"; +import { useScene } from "../../../utils/useScene"; + +export const useSplat = ( + { + size, + dpr, + }: { + size: Size; + dpr: number | false; + }, + updateRenderTarget: SingleFBOUpdateFunction +) => { + const { scene, material } = useScene({ + material: SplatMaterial, + geometrySize: { + width: 1, + height: 1, + }, + }); + + const camera = useCamera(size); + const resolution = useResolution(size, dpr); + material.uniforms.texelsize.value.set(1 / resolution.x, 1 / resolution.y); + + const updatePointer = usePointer(); + + const render = useCallback( + (rootState: RootState) => { + const { gl, pointer } = rootState; + const { currentPointer, diffPointer } = updatePointer(pointer); + + material.uniforms.center.value.copy(currentPointer); + material.uniforms.force.value.copy( + diffPointer.multiplyScalar(material.force) + ); + + updateRenderTarget({ gl, scene, camera, clear: false }); + }, + [updateRenderTarget, material, updatePointer, scene, camera] + ); + + return { render, material }; +}; diff --git a/packages/use-shader-fx/src/fxs/useFluid/useAdvection.ts b/packages/use-shader-fx/src/fxs/useFluid/useAdvection.ts deleted file mode 100644 index d3b3f988..00000000 --- a/packages/use-shader-fx/src/fxs/useFluid/useAdvection.ts +++ /dev/null @@ -1,51 +0,0 @@ -import * as THREE from "three"; -/*=============================================== -- boundaryつくってsceneにaddする -===============================================*/ -import { useCallback, useMemo } from "react"; -import { useCamera } from "../../utils/useCamera"; -import { Dpr, RootState, Size } from "../types"; -import { AdvectionMaterial } from "./materials/AdvectionMaterial"; -import { useAddObject } from "../../utils/useAddObject"; -import { SingleFBOUpdateFunction } from "../../utils/useSingleFBO"; -import { useResolution } from "../../utils/useResolution"; - -type AdvectionValues = { - velocity: THREE.Texture; -}; - -export const useAdvection = ({ - size, - dpr, - updateRenderTarget, - ...values -}: { - size: Size; - dpr: number | false; - updateRenderTarget: SingleFBOUpdateFunction; -} & AdvectionValues) => { - const scene = useMemo(() => new THREE.Scene(), []); - const camera = useCamera(size); - const geometry = useMemo(() => new THREE.PlaneGeometry(2, 2), []); - - const material = useMemo(() => { - const _mat = new AdvectionMaterial(values); - return _mat; - }, [values]); - - useAddObject(scene, geometry, material, THREE.Mesh); - - const resolution = useResolution(size, dpr); - material.uniforms.texelsize.value.set(1 / resolution.x, 1 / resolution.y); - material.uniforms.ratio.value.copy(resolution); - - const render = useCallback( - (rootState: RootState) => { - const { gl } = rootState; - updateRenderTarget({ gl, scene, camera }); - }, - [updateRenderTarget, scene, camera] - ); - - return render; -}; diff --git a/packages/use-shader-fx/src/fxs/useFluid/useDivergence.ts b/packages/use-shader-fx/src/fxs/useFluid/useDivergence.ts deleted file mode 100644 index 5afd6f59..00000000 --- a/packages/use-shader-fx/src/fxs/useFluid/useDivergence.ts +++ /dev/null @@ -1,47 +0,0 @@ -import * as THREE from "three"; -import { useCallback, useMemo } from "react"; -import { useCamera } from "../../utils/useCamera"; -import { Dpr, RootState, Size } from "../types"; -import { useAddObject } from "../../utils/useAddObject"; -import { SingleFBOUpdateFunction } from "../../utils/useSingleFBO"; -import { useResolution } from "../../utils/useResolution"; -import { DivergenceMaterial } from "./materials/DivergenceMaterial"; - -type DivergenceValues = { - velocity: THREE.Texture; -}; - -export const useDivergence = ({ - size, - dpr, - updateRenderTarget, - ...values -}: { - size: Size; - dpr: number | false; - updateRenderTarget: SingleFBOUpdateFunction; -} & DivergenceValues) => { - const scene = useMemo(() => new THREE.Scene(), []); - const camera = useCamera(size); - const geometry = useMemo(() => new THREE.PlaneGeometry(2, 2), []); - - const material = useMemo(() => { - const _mat = new DivergenceMaterial(values); - return _mat; - }, [values]); - - const resolution = useResolution(size, dpr); - material.uniforms.texelsize.value.set(1 / resolution.x, 1 / resolution.y); - - useAddObject(scene, geometry, material, THREE.Mesh); - - const render = useCallback( - (rootState: RootState) => { - const { gl } = rootState; - updateRenderTarget({ gl, scene, camera }); - }, - [updateRenderTarget, scene, camera] - ); - - return render; -}; diff --git a/packages/use-shader-fx/src/fxs/useFluid/usePoisson.ts b/packages/use-shader-fx/src/fxs/useFluid/usePoisson.ts deleted file mode 100644 index 2ba0fead..00000000 --- a/packages/use-shader-fx/src/fxs/useFluid/usePoisson.ts +++ /dev/null @@ -1,50 +0,0 @@ -import * as THREE from "three"; -import { useCallback, useMemo } from "react"; -import { useCamera } from "../../utils/useCamera"; -import { Dpr, RootState, Size } from "../types"; -import { AdvectionMaterial } from "./materials/AdvectionMaterial"; -import { useAddObject } from "../../utils/useAddObject"; -import { SingleFBOUpdateFunction } from "../../utils/useSingleFBO"; -import { useResolution } from "../../utils/useResolution"; -import { PoissonMaterial } from "./materials/PoissonMaterial"; - -type PoissonValues = { - divergence: THREE.Texture; -}; - -export const usePoisson = ({ - size, - dpr, - updateRenderTarget, - ...values -}: { - size: Size; - dpr: number | false; - updateRenderTarget: SingleFBOUpdateFunction; -} & PoissonValues) => { - const scene = useMemo(() => new THREE.Scene(), []); - const camera = useCamera(size); - const geometry = useMemo(() => new THREE.PlaneGeometry(2, 2), []); - - const material = useMemo(() => { - const _mat = new PoissonMaterial(values); - return _mat; - }, [values]); - - const resolution = useResolution(size, dpr); - material.uniforms.texelsize.value.set(1 / resolution.x, 1 / resolution.y); - - useAddObject(scene, geometry, material, THREE.Mesh); - - const render = useCallback( - (rootState: RootState) => { - const { gl } = rootState; - updateRenderTarget({ gl, scene, camera }, ({ read }) => { - material.uniforms.pressure.value = read; - }); - }, - [updateRenderTarget, material, scene, camera] - ); - - return render; -}; diff --git a/packages/use-shader-fx/src/fxs/useFluid/usePressure.ts b/packages/use-shader-fx/src/fxs/useFluid/usePressure.ts deleted file mode 100644 index 530eb5a1..00000000 --- a/packages/use-shader-fx/src/fxs/useFluid/usePressure.ts +++ /dev/null @@ -1,48 +0,0 @@ -import * as THREE from "three"; -import { useCallback, useMemo } from "react"; -import { useCamera } from "../../utils/useCamera"; -import { RootState, Size } from "../types"; -import { useAddObject } from "../../utils/useAddObject"; -import { SingleFBOUpdateFunction } from "../../utils/useSingleFBO"; -import { useResolution } from "../../utils/useResolution"; -import { PressureMaterial } from "./materials/PressureMaterial"; - -type PressureValues = { - velocity: THREE.Texture; - pressure: THREE.Texture; -}; - -export const usePressure = ({ - size, - dpr, - updateRenderTarget, - ...values -}: { - size: Size; - dpr: number | false; - updateRenderTarget: SingleFBOUpdateFunction; -} & PressureValues) => { - const scene = useMemo(() => new THREE.Scene(), []); - const camera = useCamera(size); - const geometry = useMemo(() => new THREE.PlaneGeometry(2, 2), []); - - const material = useMemo(() => { - const _mat = new PressureMaterial(values); - return _mat; - }, [values]); - - const resolution = useResolution(size, dpr); - material.uniforms.texelsize.value.set(1 / resolution.x, 1 / resolution.y); - - useAddObject(scene, geometry, material, THREE.Mesh); - - const render = useCallback( - (rootState: RootState) => { - const { gl } = rootState; - updateRenderTarget({ gl, scene, camera }); - }, - [updateRenderTarget, scene, camera] - ); - - return render; -}; diff --git a/packages/use-shader-fx/src/fxs/useFluid/useSplat.ts b/packages/use-shader-fx/src/fxs/useFluid/useSplat.ts deleted file mode 100644 index 54bcf488..00000000 --- a/packages/use-shader-fx/src/fxs/useFluid/useSplat.ts +++ /dev/null @@ -1,49 +0,0 @@ -import * as THREE from "three"; -import { useCallback, useMemo } from "react"; -import { useCamera } from "../../utils/useCamera"; -import { RootState, Size } from "../types"; -import { useAddObject } from "../../utils/useAddObject"; -import { SingleFBOUpdateFunction } from "../../utils/useSingleFBO"; -import { useResolution } from "../../utils/useResolution"; -import { SplatMaterial } from "./materials/SplatMaterial"; -import { usePointer } from "../../misc/usePointer"; - -export const useSplat = ({ - size, - dpr, - updateRenderTarget, -}: { - size: Size; - dpr: number | false; - updateRenderTarget: SingleFBOUpdateFunction; -}) => { - const scene = useMemo(() => new THREE.Scene(), []); - const camera = useCamera(size); - const geometry = useMemo(() => new THREE.PlaneGeometry(1, 1), []); - - const material = useMemo(() => { - const _mat = new SplatMaterial(); - return _mat; - }, []); - - const resolution = useResolution(size, dpr); - material.uniforms.texelsize.value.set(1 / resolution.x, 1 / resolution.y); - - useAddObject(scene, geometry, material, THREE.Mesh); - - const updatePointer = usePointer(); - - const render = useCallback( - (rootState: RootState) => { - const { gl, pointer } = rootState; - - const { currentPointer } = updatePointer(pointer); - material.uniforms.center.value.copy(currentPointer); - - updateRenderTarget({ gl, scene, camera, clear: false }); - }, - [updateRenderTarget, material, updatePointer, scene, camera] - ); - - return render; -}; diff --git a/packages/use-shader-fx/src/fxs/useNoise/NoiseMaterial.ts b/packages/use-shader-fx/src/fxs/useNoise/NoiseMaterial.ts index b3cf0a22..54a1fe49 100644 --- a/packages/use-shader-fx/src/fxs/useNoise/NoiseMaterial.ts +++ b/packages/use-shader-fx/src/fxs/useNoise/NoiseMaterial.ts @@ -1,16 +1,19 @@ import * as THREE from "three"; import { ShaderChunk } from "../../libs/shaders/ShaderChunk"; import fragment from "./noise.frag"; -import { FxMaterial } from "../materials/FxMaterial"; +import { + FxBlendingMaterial, + FxBlendingUniforms, +} from "../materials/FxBlendingMaterial"; import { NoiseValues } from "."; -export class NoiseMaterial extends FxMaterial { +export class NoiseMaterial extends FxBlendingMaterial { static get type() { return "NoiseMaterial"; } uniforms: { - uTime: { value: number }; + tick: { value: number }; scale: { value: number }; timeStrength: { value: number }; noiseOctaves: { value: number }; @@ -18,15 +21,15 @@ export class NoiseMaterial extends FxMaterial { warpOctaves: { value: number }; warpDirection: { value: THREE.Vector2 }; warpStrength: { value: number }; - }; + } & FxBlendingUniforms; constructor(uniformValues?: NoiseValues, parameters = {}) { - super(); + super(parameters); this.type = NoiseMaterial.type; this.uniforms = { - uTime: { value: 0.0 }, + tick: { value: 0.0 }, scale: { value: 0.03 }, timeStrength: { value: 0.3 }, noiseOctaves: { value: 2 }, @@ -34,10 +37,10 @@ export class NoiseMaterial extends FxMaterial { warpOctaves: { value: 2 }, warpDirection: { value: new THREE.Vector2(2.0, 2.0) }, warpStrength: { value: 8 }, + ...this.blendingUniforms, }; - this.vertexShader = ShaderChunk.planeVertex; - this.fragmentShader = fragment; + this.resolveBlendingShader(ShaderChunk.blendingPlaneVertex, fragment); this.setUniformValues(uniformValues); this.setValues(parameters); diff --git a/packages/use-shader-fx/src/fxs/useNoise/index.ts b/packages/use-shader-fx/src/fxs/useNoise/index.ts index 16d17d4c..5d37eed5 100644 --- a/packages/use-shader-fx/src/fxs/useNoise/index.ts +++ b/packages/use-shader-fx/src/fxs/useNoise/index.ts @@ -1,12 +1,18 @@ import * as THREE from "three"; -import { useCallback, useMemo } from "react"; +import { useCallback } from "react"; import { useCamera } from "../../utils/useCamera"; import { useSingleFBO } from "../../utils/useSingleFBO"; import { HooksProps, HooksReturn } from "../types"; import { getDpr } from "../../utils/getDpr"; -import { OnInit, RootState } from "../types"; -import { useAddObject } from "../../utils/useAddObject"; +import { RootState } from "../types"; import { NoiseMaterial } from "./NoiseMaterial"; +import { useScene } from "../../utils/useScene"; + +/*=============================================== +- textureのcoverする機能とかも入れたいか + - これをvertexで処理 +- cloneUniformとmergeUniformすればいいのかも。マテリアルの継承で。 +===============================================*/ export type NoiseValues = { /** noise scale , default : `0.004` */ @@ -25,6 +31,14 @@ export type NoiseValues = { warpStrength?: number; /** you can get into the rhythm ♪ , default : `false` */ beat?: number | false; + + /*=============================================== + blending + ===============================================*/ + fxBlendingSrc?: THREE.Texture; + uvBlending?: number; + alphaBlending?: number; + fxBlendingSrcResolution?: THREE.Vector2; }; /** @@ -32,32 +46,26 @@ export type NoiseValues = { * * It is a basic value noise with `fbm` and `domain warping` */ -export const useNoise = ( - { - size, - dpr, - sizeUpdate, - renderTargetOptions, - ...values - }: HooksProps & NoiseValues, - onInit?: OnInit -): HooksReturn => { +export const useNoise = ({ + size, + dpr, + sizeUpdate, + renderTargetOptions, + fxBlending, + materialParameters, + ...values +}: HooksProps & NoiseValues): HooksReturn => { const _dpr = getDpr(dpr); - const scene = useMemo(() => new THREE.Scene(), []); + const { scene, material } = useScene({ + size, + material: NoiseMaterial, + uniformValues: values, + fxBlending, + materialParameters, + }); const camera = useCamera(size); - - const geometry = useMemo(() => new THREE.PlaneGeometry(2, 2), []); - - const material = useMemo(() => { - const _mat = new NoiseMaterial(values); - onInit && onInit(_mat); - return _mat; - }, [onInit, values]); - - useAddObject(scene, geometry, material, THREE.Mesh); - const [renderTarget, updateRenderTarget] = useSingleFBO({ scene, camera, @@ -78,9 +86,9 @@ export const useNoise = ( (rootState: RootState, newValues?: NoiseValues) => { const { gl, clock } = rootState; newValues && setValues(newValues); - material.uniforms.uTime.value = + material.uniforms.tick.value = newValues?.beat || clock.getElapsedTime(); - return updateRenderTarget(gl); + return updateRenderTarget({ gl }); }, [setValues, updateRenderTarget, material] ); @@ -91,5 +99,6 @@ export const useNoise = ( texture: renderTarget.texture, material, scene, + camera, }; }; diff --git a/packages/use-shader-fx/src/fxs/useNoise/noise.frag b/packages/use-shader-fx/src/fxs/useNoise/noise.frag index 39e96e23..000819d7 100644 --- a/packages/use-shader-fx/src/fxs/useNoise/noise.frag +++ b/packages/use-shader-fx/src/fxs/useNoise/noise.frag @@ -2,7 +2,7 @@ precision highp float; precision highp int; varying vec2 vUv; -uniform float uTime; +uniform float tick; uniform float timeStrength; uniform int noiseOctaves; uniform int fbmOctaves; @@ -70,7 +70,17 @@ float warp(vec2 x, float g,float time){ return val; } + +#usf + void main() { - float noise = warp(gl_FragCoord.xy * scale ,warpStrength,uTime * timeStrength); - gl_FragColor = vec4(vec3(noise),1.0); + float noise = warp(gl_FragCoord.xy * scale ,warpStrength,tick * timeStrength); + vec4 noiseColor = vec4(vec3(noise),1.0); + + vec4 blendingDst = noiseColor; + + #usf + + gl_FragColor = blendingDst; + } \ No newline at end of file diff --git a/packages/use-shader-fx/src/libs/shaders/ShaderChunk.ts b/packages/use-shader-fx/src/libs/shaders/ShaderChunk.ts index 910f4b07..5f25e116 100644 --- a/packages/use-shader-fx/src/libs/shaders/ShaderChunk.ts +++ b/packages/use-shader-fx/src/libs/shaders/ShaderChunk.ts @@ -1,29 +1,35 @@ import wobble3D from "./shaderChunk/wobble3D.glsl"; import snoise from "./shaderChunk/snoise.glsl"; import coverTexture from "./shaderChunk/coverTexture.glsl"; -import fxBlending from "./shaderChunk/fxBlending.glsl"; import planeVertex from "./shaderChunk/planeVertex.glsl"; import defaultVertex from "./shaderChunk/defaultVertex.glsl"; import hsv2rgb from "./shaderChunk/hsv2rgb.glsl"; import rgb2hsv from "./shaderChunk/rgb2hsv.glsl"; +import blendingColor from "./shaderChunk/blendingColor.glsl"; +import blendingUniforms from "./shaderChunk/blendingUniforms.glsl"; +import blendingPlaneVertex from "./shaderChunk/blendingPlaneVertex.glsl"; export type ShaderChunkTypes = | "wobble3D" | "snoise" | "coverTexture" - | "fxBlending" | "planeVertex" | "defaultVertex" | "hsv2rgb" - | "rgb2hsv"; + | "rgb2hsv" + | "blendingColor" + | "blendingUniforms" + | "blendingPlaneVertex"; export const ShaderChunk: { [K in ShaderChunkTypes]: string } = Object.freeze({ wobble3D, snoise, coverTexture, - fxBlending, planeVertex, defaultVertex, hsv2rgb, rgb2hsv, + blendingColor, + blendingUniforms, + blendingPlaneVertex, }); diff --git a/packages/use-shader-fx/src/libs/shaders/resolveShaders.ts b/packages/use-shader-fx/src/libs/shaders/resolveShaders.ts new file mode 100644 index 00000000..3b7ef675 --- /dev/null +++ b/packages/use-shader-fx/src/libs/shaders/resolveShaders.ts @@ -0,0 +1,13 @@ +import { ShaderChunk, ShaderChunkTypes } from "./ShaderChunk"; + +export const includePattern = /^[ \t]*#usf +<([\w\d./]+)>/gm; + +function includeReplacer(match: string, include: ShaderChunkTypes): string { + return resolveIncludes(ShaderChunk[include] || ""); +} + +function resolveIncludes(string: string): string { + return string.replace(includePattern, includeReplacer); +} + +export { resolveIncludes }; diff --git a/packages/use-shader-fx/src/libs/shaders/shaderChunk/blendingColor.glsl b/packages/use-shader-fx/src/libs/shaders/shaderChunk/blendingColor.glsl new file mode 100644 index 00000000..2862c999 --- /dev/null +++ b/packages/use-shader-fx/src/libs/shaders/shaderChunk/blendingColor.glsl @@ -0,0 +1,11 @@ +// float screenAspect = resolution.x / resolution.y; +// float blendingSrcAspect = fxBlendingSrcResolution.x / fxBlendingSrcResolution.y; +// vec2 aspectRatio = vec2( +// min(screenAspect / blendingSrcAspect, 1.0), +// min(blendingSrcAspect / screenAspect, 1.0) +// ); +// vec2 coverUV = vUv * aspectRatio + (1.0 - aspectRatio) * .5; +vec4 fxBlended = texture2D(fxBlendingSrc, mix(vCoverUv, vec2(blendingDst.g), uvBlending)); +vec4 alphaBlended = mix(blendingDst, fxBlended,fxBlended.a * alphaBlending); + +blendingDst = alphaBlended; \ No newline at end of file diff --git a/packages/use-shader-fx/src/libs/shaders/shaderChunk/blendingPlaneVertex.glsl b/packages/use-shader-fx/src/libs/shaders/shaderChunk/blendingPlaneVertex.glsl new file mode 100644 index 00000000..0014af8f --- /dev/null +++ b/packages/use-shader-fx/src/libs/shaders/shaderChunk/blendingPlaneVertex.glsl @@ -0,0 +1,21 @@ +precision highp float; + +varying vec2 vUv; +varying vec2 vCoverUv; + +uniform vec2 resolution; +uniform vec2 fxBlendingSrcResolution; + +void main() { + vUv = uv; + + float screenAspect = resolution.x / resolution.y; + float blendingSrcAspect = fxBlendingSrcResolution.x / fxBlendingSrcResolution.y; + vec2 aspectRatio = vec2( + min(screenAspect / blendingSrcAspect, 1.0), + min(blendingSrcAspect / screenAspect, 1.0) + ); + vCoverUv = vUv * aspectRatio + (1.0 - aspectRatio) * .5; + + gl_Position = vec4(position, 1.0); +} \ No newline at end of file diff --git a/packages/use-shader-fx/src/libs/shaders/shaderChunk/blendingUniforms.glsl b/packages/use-shader-fx/src/libs/shaders/shaderChunk/blendingUniforms.glsl new file mode 100644 index 00000000..9bae0da1 --- /dev/null +++ b/packages/use-shader-fx/src/libs/shaders/shaderChunk/blendingUniforms.glsl @@ -0,0 +1,7 @@ +// uniform vec2 resolution; +// uniform vec2 fxBlendingSrcResolution; + +varying vec2 vCoverUv; +uniform sampler2D fxBlendingSrc; +uniform float uvBlending; +uniform float alphaBlending; \ No newline at end of file diff --git a/packages/use-shader-fx/src/libs/shaders/shaderChunk/fxBlending.glsl b/packages/use-shader-fx/src/libs/shaders/shaderChunk/fxBlending.glsl deleted file mode 100644 index b7d0916a..00000000 --- a/packages/use-shader-fx/src/libs/shaders/shaderChunk/fxBlending.glsl +++ /dev/null @@ -1,6 +0,0 @@ -vec3 mapColor = texture2D(uMap, uv).rgb; -vec3 normalizedMap = mapColor * 2.0 - 1.0; - -uv = uv * 2.0 - 1.0; -uv *= mix(vec2(1.0), abs(normalizedMap.rg), uMapIntensity); -uv = (uv + 1.0) / 2.0; \ No newline at end of file diff --git a/packages/use-shader-fx/src/utils/useAddObject.ts b/packages/use-shader-fx/src/utils/useObject3D.ts similarity index 89% rename from packages/use-shader-fx/src/utils/useAddObject.ts rename to packages/use-shader-fx/src/utils/useObject3D.ts index 591f6921..29fd8895 100644 --- a/packages/use-shader-fx/src/utils/useAddObject.ts +++ b/packages/use-shader-fx/src/utils/useObject3D.ts @@ -9,10 +9,7 @@ type Object3DConstructor = new ( /** * Add geometry and material to Object3D and add them to scene. */ -export const useAddObject = < - T extends THREE.Object3D, - M extends THREE.Material ->( +export const useObject3D = ( scene: THREE.Scene | false, geometry: THREE.BufferGeometry, material: M, diff --git a/packages/use-shader-fx/src/utils/useScene.ts b/packages/use-shader-fx/src/utils/useScene.ts new file mode 100644 index 00000000..d3316942 --- /dev/null +++ b/packages/use-shader-fx/src/utils/useScene.ts @@ -0,0 +1,61 @@ +import { useMemo } from "react"; +import * as THREE from "three"; +import { useObject3D } from "./useObject3D"; +import { useResolution } from "./useResolution"; +import { Size } from "../fxs/types"; + +type MaterialConstructor = new ( + uniformValues: any, + materialParameters: THREE.MaterialParameters +) => M; +type GeometryConstructor = new ( + width: number, + height: number +) => THREE.BufferGeometry; + +export const useScene = ({ + size, + material, + uniformValues, + materialParameters, + fxBlending, + geometry = THREE.PlaneGeometry, + geometrySize = { width: 2, height: 2 }, +}: { + size: Size; + material: MaterialConstructor; + uniformValues?: any; + materialParameters?: THREE.MaterialParameters; + fxBlending?: boolean; + geometry?: GeometryConstructor; + geometrySize?: { + width: number; + height: number; + }; +}) => { + const scene = useMemo(() => new THREE.Scene(), []); + + const _geometry = useMemo( + () => new geometry(geometrySize.width, geometrySize.height), + [geometry, geometrySize] + ); + + const _material = useMemo( + () => + new material(uniformValues, { + ...materialParameters, + ...(fxBlending !== undefined && { fxBlending }), + }), + [material, uniformValues, materialParameters, fxBlending] + ); + + const resolution = useResolution(size); + _material.uniforms.resolution.value.copy(resolution); + + useObject3D(scene, _geometry, _material, THREE.Mesh); + + return { + scene, + material: _material, + }; +}; diff --git a/packages/use-shader-fx/src/utils/useSingleFBO.ts b/packages/use-shader-fx/src/utils/useSingleFBO.ts index 53ec7178..00cb7b8a 100644 --- a/packages/use-shader-fx/src/utils/useSingleFBO.ts +++ b/packages/use-shader-fx/src/utils/useSingleFBO.ts @@ -40,13 +40,14 @@ export const renderFBO = ({ onSwap?: () => void; } & RenderProps) => { if (!scene || !camera) return; + const clearCache = gl.autoClear; + gl.autoClear = clear; gl.setRenderTarget(fbo); onBeforeRender(); - gl.autoClear = clear; - clear && gl.clear(); gl.render(scene, camera); onSwap && onSwap(); gl.setRenderTarget(null); + gl.autoClear = clearCache; }; export type SingleFBOUpdateFunction = ( diff --git a/todo b/todo new file mode 100644 index 00000000..375d4c95 --- /dev/null +++ b/todo @@ -0,0 +1,2 @@ +- fxMaterialでblendingの仕組みをつくる + - shaderChunk的にblendingのコードをshaderに追加する仕組み \ No newline at end of file From 0c4ae47ac4e7db779d5416bb0bd39138bf93282b Mon Sep 17 00:00:00 2001 From: takuma-hmng8 Date: Fri, 20 Sep 2024 18:12:50 +0900 Subject: [PATCH 03/60] wip --- app/v2/FxMaterial.tsx | 16 +- app/v2/Playground.tsx | 66 ++++--- .../src/fxs/materials/FxBasicFxMaterial.ts | 170 ++++++++++++++++++ .../src/fxs/materials/FxBlendingMaterial.ts | 46 ----- .../src/fxs/materials/FxMaterial.ts | 31 ++++ packages/use-shader-fx/src/fxs/types/index.ts | 4 +- .../useCoverTexture/CoverTextureMaterial.ts | 40 +++++ .../fxs/useCoverTexture/coverTexture.glsl.ts | 42 +++++ .../src/fxs/useCoverTexture/index.ts | 78 ++++++++ .../src/fxs/useNoise/NoiseMaterial.ts | 64 +++---- .../use-shader-fx/src/fxs/useNoise/index.ts | 27 +-- .../use-shader-fx/src/fxs/useNoise/noise.frag | 86 --------- .../src/fxs/useNoise/noise.glsl.ts | 100 +++++++++++ packages/use-shader-fx/src/index.js | 1 + .../src/libs/shaders/ShaderChunk.ts | 63 +++---- .../ShaderChunk/default_pars_fragment.glsl | 2 + .../ShaderChunk/default_pars_vertex.glsl | 3 + .../shaders/ShaderChunk/mixDst_fragment.glsl | 9 + .../ShaderChunk/mixDst_pars_fragment.glsl | 7 + .../ShaderChunk/mixDst_pars_vertex.glsl | 4 + .../shaders/ShaderChunk/mixDst_vertex.glsl | 8 + .../ShaderChunk/mixSrc_fragment_begin.glsl | 6 + .../ShaderChunk/mixSrc_fragment_end.glsl | 7 + .../ShaderChunk/mixSrc_pars_fragment.glsl | 7 + .../ShaderChunk/mixSrc_pars_vertex.glsl | 4 + .../shaders/ShaderChunk/mixSrc_vertex.glsl | 8 + .../ShaderLib/basicFx_fragment_begin.glsl | 1 + .../ShaderLib/basicFx_fragment_end.glsl | 2 + .../ShaderLib/basicFx_pars_fragment.glsl | 5 + .../ShaderLib/basicFx_pars_vertex.glsl | 5 + .../shaders/ShaderLib/basicFx_vertex.glsl | 3 + .../src/libs/shaders/ShdaerLib.ts | 20 +++ .../shaders/shaderChunk/blendingColor.glsl | 11 -- .../shaderChunk/blendingPlaneVertex.glsl | 21 --- .../shaders/shaderChunk/blendingUniforms.glsl | 7 - .../shaders/shaderChunk/coverTexture.glsl | 7 - .../shaders/shaderChunk/defaultVertex.glsl | 6 - .../src/libs/shaders/shaderChunk/hsv2rgb.glsl | 6 - .../libs/shaders/shaderChunk/planeVertex.glsl | 8 - .../src/libs/shaders/shaderChunk/rgb2hsv.glsl | 10 -- .../src/libs/shaders/shaderChunk/snoise.glsl | 58 ------ .../libs/shaders/shaderChunk/wobble3D.glsl | 111 ------------ packages/use-shader-fx/src/utils/useScene.ts | 27 +-- public/stickers/webp/sticker0.webp | Bin 26426 -> 21246 bytes public/stickers/webp/sticker1.webp | Bin 34538 -> 16198 bytes public/stickers/webp/sticker10.webp | Bin 53594 -> 41998 bytes public/stickers/webp/sticker11.webp | Bin 0 -> 29960 bytes public/stickers/webp/sticker12.webp | Bin 0 -> 30790 bytes public/stickers/webp/sticker13.webp | Bin 0 -> 38688 bytes public/stickers/webp/sticker14.webp | Bin 0 -> 15770 bytes public/stickers/webp/sticker15.webp | Bin 0 -> 27834 bytes public/stickers/webp/sticker16.webp | Bin 0 -> 28322 bytes public/stickers/webp/sticker17.webp | Bin 0 -> 18886 bytes public/stickers/webp/sticker18.webp | Bin 0 -> 17392 bytes public/stickers/webp/sticker19.webp | Bin 0 -> 19856 bytes public/stickers/webp/sticker2.webp | Bin 88296 -> 109668 bytes public/stickers/webp/sticker3.webp | Bin 24550 -> 25236 bytes public/stickers/webp/sticker4.webp | Bin 45860 -> 48838 bytes public/stickers/webp/sticker5.webp | Bin 53294 -> 36146 bytes public/stickers/webp/sticker6.webp | Bin 31140 -> 44830 bytes public/stickers/webp/sticker7.webp | Bin 46052 -> 18668 bytes public/stickers/webp/sticker8.webp | Bin 45538 -> 30218 bytes public/stickers/webp/sticker9.webp | Bin 43318 -> 15316 bytes public/stickers/webp/wrinkle.webp | Bin 0 -> 4028 bytes public/stickers/webp/wrinkle0.webp | Bin 21078 -> 0 bytes public/stickers/webp/wrinkle1.webp | Bin 21584 -> 0 bytes todo | 18 +- 67 files changed, 702 insertions(+), 523 deletions(-) create mode 100644 packages/use-shader-fx/src/fxs/materials/FxBasicFxMaterial.ts delete mode 100644 packages/use-shader-fx/src/fxs/materials/FxBlendingMaterial.ts create mode 100644 packages/use-shader-fx/src/fxs/useCoverTexture/CoverTextureMaterial.ts create mode 100644 packages/use-shader-fx/src/fxs/useCoverTexture/coverTexture.glsl.ts create mode 100644 packages/use-shader-fx/src/fxs/useCoverTexture/index.ts delete mode 100644 packages/use-shader-fx/src/fxs/useNoise/noise.frag create mode 100644 packages/use-shader-fx/src/fxs/useNoise/noise.glsl.ts create mode 100644 packages/use-shader-fx/src/libs/shaders/ShaderChunk/default_pars_fragment.glsl create mode 100644 packages/use-shader-fx/src/libs/shaders/ShaderChunk/default_pars_vertex.glsl create mode 100644 packages/use-shader-fx/src/libs/shaders/ShaderChunk/mixDst_fragment.glsl create mode 100644 packages/use-shader-fx/src/libs/shaders/ShaderChunk/mixDst_pars_fragment.glsl create mode 100644 packages/use-shader-fx/src/libs/shaders/ShaderChunk/mixDst_pars_vertex.glsl create mode 100644 packages/use-shader-fx/src/libs/shaders/ShaderChunk/mixDst_vertex.glsl create mode 100644 packages/use-shader-fx/src/libs/shaders/ShaderChunk/mixSrc_fragment_begin.glsl create mode 100644 packages/use-shader-fx/src/libs/shaders/ShaderChunk/mixSrc_fragment_end.glsl create mode 100644 packages/use-shader-fx/src/libs/shaders/ShaderChunk/mixSrc_pars_fragment.glsl create mode 100644 packages/use-shader-fx/src/libs/shaders/ShaderChunk/mixSrc_pars_vertex.glsl create mode 100644 packages/use-shader-fx/src/libs/shaders/ShaderChunk/mixSrc_vertex.glsl create mode 100644 packages/use-shader-fx/src/libs/shaders/ShaderLib/basicFx_fragment_begin.glsl create mode 100644 packages/use-shader-fx/src/libs/shaders/ShaderLib/basicFx_fragment_end.glsl create mode 100644 packages/use-shader-fx/src/libs/shaders/ShaderLib/basicFx_pars_fragment.glsl create mode 100644 packages/use-shader-fx/src/libs/shaders/ShaderLib/basicFx_pars_vertex.glsl create mode 100644 packages/use-shader-fx/src/libs/shaders/ShaderLib/basicFx_vertex.glsl create mode 100644 packages/use-shader-fx/src/libs/shaders/ShdaerLib.ts delete mode 100644 packages/use-shader-fx/src/libs/shaders/shaderChunk/blendingColor.glsl delete mode 100644 packages/use-shader-fx/src/libs/shaders/shaderChunk/blendingPlaneVertex.glsl delete mode 100644 packages/use-shader-fx/src/libs/shaders/shaderChunk/blendingUniforms.glsl delete mode 100644 packages/use-shader-fx/src/libs/shaders/shaderChunk/coverTexture.glsl delete mode 100644 packages/use-shader-fx/src/libs/shaders/shaderChunk/defaultVertex.glsl delete mode 100644 packages/use-shader-fx/src/libs/shaders/shaderChunk/hsv2rgb.glsl delete mode 100644 packages/use-shader-fx/src/libs/shaders/shaderChunk/planeVertex.glsl delete mode 100644 packages/use-shader-fx/src/libs/shaders/shaderChunk/rgb2hsv.glsl delete mode 100644 packages/use-shader-fx/src/libs/shaders/shaderChunk/snoise.glsl delete mode 100644 packages/use-shader-fx/src/libs/shaders/shaderChunk/wobble3D.glsl mode change 100755 => 100644 public/stickers/webp/sticker0.webp mode change 100755 => 100644 public/stickers/webp/sticker1.webp mode change 100755 => 100644 public/stickers/webp/sticker10.webp create mode 100644 public/stickers/webp/sticker11.webp create mode 100644 public/stickers/webp/sticker12.webp create mode 100644 public/stickers/webp/sticker13.webp create mode 100644 public/stickers/webp/sticker14.webp create mode 100644 public/stickers/webp/sticker15.webp create mode 100644 public/stickers/webp/sticker16.webp create mode 100644 public/stickers/webp/sticker17.webp create mode 100644 public/stickers/webp/sticker18.webp create mode 100644 public/stickers/webp/sticker19.webp mode change 100755 => 100644 public/stickers/webp/sticker2.webp mode change 100755 => 100644 public/stickers/webp/sticker3.webp mode change 100755 => 100644 public/stickers/webp/sticker4.webp mode change 100755 => 100644 public/stickers/webp/sticker5.webp mode change 100755 => 100644 public/stickers/webp/sticker6.webp mode change 100755 => 100644 public/stickers/webp/sticker7.webp mode change 100755 => 100644 public/stickers/webp/sticker8.webp mode change 100755 => 100644 public/stickers/webp/sticker9.webp create mode 100644 public/stickers/webp/wrinkle.webp delete mode 100644 public/stickers/webp/wrinkle0.webp delete mode 100644 public/stickers/webp/wrinkle1.webp diff --git a/app/v2/FxMaterial.tsx b/app/v2/FxMaterial.tsx index e8459506..ba02ad34 100644 --- a/app/v2/FxMaterial.tsx +++ b/app/v2/FxMaterial.tsx @@ -33,17 +33,17 @@ export const FxMaterial = shaderMaterial( void main() { vec2 uv = vUv; - // vec4 color = texture2D(u_fx, uv); - // gl_FragColor = vec4(color.rgb,1.); + vec4 color = texture2D(u_fx, uv); + gl_FragColor = color; - vec2 vel = texture2D(u_fx, uv).xy; - float len = length(vel); - vel = vel * 0.5 + 0.5; + // vec2 vel = texture2D(u_fx, uv).xy; + // float len = length(vel); + // vel = vel * 0.5 + 0.5; - vec3 color = vec3(vel.x, vel.y, len); - color = mix(vec3(0.), color, len); + // vec3 color = vec3(vel.x, vel.y, len); + // color = mix(vec3(0.), color, len); - gl_FragColor = vec4(color, 1.0); + // gl_FragColor = vec4(color, 1.0); } ` ); diff --git a/app/v2/Playground.tsx b/app/v2/Playground.tsx index 39c274f7..a32ae1f4 100644 --- a/app/v2/Playground.tsx +++ b/app/v2/Playground.tsx @@ -3,13 +3,16 @@ import * as THREE from "three"; import { useCallback, useEffect, useMemo, useRef, useState } from "react"; import { useFrame, useThree, extend, useLoader } from "@react-three/fiber"; -import { useNoise, useFluid } from "@/packages/use-shader-fx/src"; +import { + useNoise, + useFluid, + useCoverTexture, +} from "@/packages/use-shader-fx/src"; import { FxMaterial } from "./FxMaterial"; import { Float, OrbitControls, useVideoTexture } from "@react-three/drei"; /*=============================================== # webglooの設計 - - useFxResolverでhookを切り替える ===============================================*/ @@ -24,54 +27,49 @@ const useFxResolver = (test: boolean) => { } }; +// const hooks = [useNoise, useNoise]; + export const Playground = () => { const { size } = useThree(); - // const currentHook = useFxResolver(true); - // const noise = currentHook({ - // size, - // dpr: 0.15, - // }); - - // const fluid = useFluid({ - // size, - // dpr: 0.5, - // }); - const funkun_mov = useVideoTexture("/FT_Ch02-comp.mp4", { width: 1280, height: 720, }); - const [gear] = useLoader(THREE.TextureLoader, [ - "/stickers/webp/sticker2.webp", + const [gear, smoke] = useLoader(THREE.TextureLoader, [ + "/stickers/webp/sticker17.webp", + "smoke.png", ]); const noise = useNoise({ size, - dpr: 0.1, - fxBlending: true, - fxBlendingSrc: gear, - alphaBlending: 1, - uvBlending: 0.1, - fxBlendingSrcResolution: new THREE.Vector2(1024, 1024), + dpr: 0.2, + scale: 0.01, + // mixSrc: gear, + // mixSrcResolution: new THREE.Vector2(512, 512), + // mixSrcUv: 0.9, + // mixSrcAlpha: 1, + mixDst: gear, + mixDstResolution: new THREE.Vector2(512, 512), + mixDstUv: 0.2, + mixDstAlpha: 1, + mixDstColor: 0.5, }); - // noise.material.warp = new THREE.Vector2(2.0, 2.0); - - // noise.material.onBeforeCompile = useCallback((shader) => { - // console.log(shader.vertexShader); - // }, []); - - // const material = useMemo(() => { - // const _mat = new THREE.MeshPhysicalMaterial(); - // _mat.color = new THREE.Color("red"); - // _mat.roughness = 1; - // return _mat; - // }, []); - // const mesh = useRef(null); + // const cover = useCoverTexture({ + // size, + // dpr: 1, + // src: funkun_mov, + // textureResolution: new THREE.Vector2(1280, 720), + // // mixSrc: smoke, + // mixSrcResolution: new THREE.Vector2(512, 512), + // mixSrcUv: 0.12, + // mixSrcAlpha: 0.2, + // }); useFrame((state) => { + // cover.render(state); // fluid.render(state); noise.render(state); // material.color = new THREE.Color( diff --git a/packages/use-shader-fx/src/fxs/materials/FxBasicFxMaterial.ts b/packages/use-shader-fx/src/fxs/materials/FxBasicFxMaterial.ts new file mode 100644 index 00000000..052e0917 --- /dev/null +++ b/packages/use-shader-fx/src/fxs/materials/FxBasicFxMaterial.ts @@ -0,0 +1,170 @@ +import * as THREE from "three"; +import { DefaultUniforms, FxMaterial } from "./FxMaterial"; +import { mergeUniforms } from "three/src/renderers/shaders/UniformsUtils.js"; +import { RootState } from "../types"; + +export type BasicFxUniforms = { + // mixSrc + mixSrc: { value: THREE.Texture | null }; + mixSrcResolution: { value: THREE.Vector2 }; + mixSrcUv: { value: number }; + mixSrcAlpha: { value: number }; + mixSrcColor: { value: number }; + // mixDst + mixDst: { value: THREE.Texture | null }; + mixDstResolution: { value: THREE.Vector2 }; + mixDstUv: { value: number }; + mixDstAlpha: { value: number }; + mixDstColor: { value: number }; +} & DefaultUniforms; + +export type BasicFxValues = { + // mixSrc + mixSrc?: THREE.Texture | null; + mixSrcResolution?: THREE.Vector2; + mixSrcUv?: number; + mixSrcAlpha?: number; + mixSrcColor?: number; + //mixDst + mixDst?: THREE.Texture | null; + mixDstResolution?: THREE.Vector2; + mixDstUv?: number; + mixDstAlpha?: number; + mixDstColor?: number; +}; + +type FxBasicMaterialProps = { + uniformValues?: BasicFxValues; + parameters?: {}; + vertexShader?: string; + fragmentShader?: string; +}; + +export class FxBasicFxMaterial extends FxMaterial { + basicFx: { + mixSrc: boolean; + mixDst: boolean; + }; + + uniforms: BasicFxUniforms; + + vertexShaderCache: string; + vertexPrefixCache: string; + fragmentShaderCache: string; + fragmentPrefixCache: string; + programCache: number; + + constructor({ + uniformValues, + parameters = {}, + vertexShader, + fragmentShader, + }: FxBasicMaterialProps = {}) { + super(); + + this.basicFx = { + mixSrc: uniformValues?.mixSrc ? true : false, + mixDst: uniformValues?.mixDst ? true : false, + }; + + this.uniforms = mergeUniforms([ + this.uniforms, + { + // mixSrc + mixSrc: { value: null }, + mixSrcResolution: { value: new THREE.Vector2() }, + mixSrcUv: { value: 0 }, + mixSrcAlpha: { value: 0 }, + mixSrcColor: { value: 0 }, + // mixDst + mixDst: { value: null }, + mixDstResolution: { value: new THREE.Vector2() }, + mixDstUv: { value: 0 }, + mixDstAlpha: { value: 0 }, + mixDstColor: { value: 0 }, + } as BasicFxUniforms, + ]) as BasicFxUniforms; + + this.setUniformValues(uniformValues); + this.setValues(parameters); + + this.vertexShaderCache = this.vertexShader; + this.fragmentShaderCache = this.fragmentShader; + this.vertexPrefixCache = ""; + this.fragmentPrefixCache = ""; + this.programCache = 0; + + this.setupBasicFxShaders(vertexShader, fragmentShader); + } + + update(rootState: RootState) { + this.updateDefaultValues(rootState); + this.updateBasicFx(); + } + + updateBasicFx() { + const _cache = this.programCache; + + const isMixSrc = this.uniforms.mixSrc.value ? true : false; + const isMixDst = this.uniforms.mixDst.value ? true : false; + + const { mixSrc, mixDst } = this.basicFx; + + if (mixSrc !== isMixSrc) { + this.basicFx.mixSrc = isMixSrc; + this.programCache++; + } + + if (mixDst !== isMixDst) { + this.basicFx.mixDst = isMixDst; + this.programCache++; + } + + if (_cache !== this.programCache) { + this.updateBasicFxPrefix(); + this.updateBasicFxShader(); + this.version++; // to update material + } + } + + updateBasicFxPrefix() { + const { mixSrc, mixDst } = this.basicFx; + const prefixVertex = [ + mixSrc ? "#define USF_USE_MIXSRC" : "", + mixDst ? "#define USF_USE_MIXDST" : "", + "\n", + ] + .filter(filterEmptyLine) + .join("\n"); + const prefixFragment = [ + mixSrc ? "#define USF_USE_MIXSRC" : "", + mixDst ? "#define USF_USE_MIXDST" : "", + "\n", + ] + .filter(filterEmptyLine) + .join("\n"); + this.vertexPrefixCache = prefixVertex; + this.fragmentPrefixCache = prefixFragment; + } + + updateBasicFxShader() { + this.vertexShader = this.vertexPrefixCache + this.vertexShaderCache; + this.fragmentShader = this.fragmentPrefixCache + this.fragmentShaderCache; + } + + setupBasicFxShaders(vertexShader?: string, fragmentShader?: string) { + this.updateBasicFxPrefix(); + const { vertexShader: _vertex, fragmentShader: _fragment } = + this.resolveDefaultShaders( + vertexShader || this.vertexShaderCache, + fragmentShader || this.fragmentShaderCache + ); + this.vertexShaderCache = _vertex; + this.fragmentShaderCache = _fragment; + this.updateBasicFxShader(); + } +} + +function filterEmptyLine(string: string) { + return string !== ""; +} diff --git a/packages/use-shader-fx/src/fxs/materials/FxBlendingMaterial.ts b/packages/use-shader-fx/src/fxs/materials/FxBlendingMaterial.ts deleted file mode 100644 index 03dea2d0..00000000 --- a/packages/use-shader-fx/src/fxs/materials/FxBlendingMaterial.ts +++ /dev/null @@ -1,46 +0,0 @@ -import * as THREE from "three"; -import { DEFAULT_TEXTURE } from "../../libs/constants"; -import { - resolveIncludes, - includePattern, -} from "../../libs/shaders/resolveShaders"; -import { FxMaterial } from "./FxMaterial"; - -export type FxBlendingUniforms = { - fxBlendingSrc: { value: THREE.Texture }; - uvBlending: { value: number }; - alphaBlending: { value: number }; - fxBlendingSrcResolution: { value: THREE.Vector2 }; - // TODO * resolutionはFXMaterialで定義しようかな。全部にあるべきだし - resolution: { value: THREE.Vector2 }; -}; - -export class FxBlendingMaterial extends FxMaterial { - fxBlending: boolean; - blendingUniforms: FxBlendingUniforms; - - constructor(parameters = {}) { - super(); - - this.fxBlending = false; - - this.blendingUniforms = { - fxBlendingSrc: { value: DEFAULT_TEXTURE }, - uvBlending: { value: 0 }, - alphaBlending: { value: 0 }, - resolution: { value: new THREE.Vector2() }, - fxBlendingSrcResolution: { value: new THREE.Vector2() }, - }; - - super.setValues(parameters); - } - - resolveBlendingShader(vertexShader: string, fragmentShader: string) { - this.vertexShader = this.fxBlending - ? resolveIncludes(vertexShader) - : vertexShader.replace(includePattern, ""); - this.fragmentShader = this.fxBlending - ? resolveIncludes(fragmentShader) - : fragmentShader.replace(includePattern, ""); - } -} diff --git a/packages/use-shader-fx/src/fxs/materials/FxMaterial.ts b/packages/use-shader-fx/src/fxs/materials/FxMaterial.ts index f12d60f1..6a7f3b4a 100644 --- a/packages/use-shader-fx/src/fxs/materials/FxMaterial.ts +++ b/packages/use-shader-fx/src/fxs/materials/FxMaterial.ts @@ -1,6 +1,37 @@ import * as THREE from "three"; +import { RootState } from "../types"; +import { resolveIncludes } from "../../libs/shaders/resolveShaders"; + +export type DefaultUniforms = { + resolution: { value: THREE.Vector2 }; + screenAspect: { value: number }; +}; export class FxMaterial extends THREE.ShaderMaterial { + constructor(parameters = {}) { + super(); + + this.uniforms = { + resolution: { value: new THREE.Vector2() }, + screenAspect: { value: 0 }, + } as DefaultUniforms; + + this.setValues(parameters); + } + + updateDefaultValues(rootState: RootState) { + const { size } = rootState; + this.uniforms.resolution.value.set(size.width, size.height); + this.uniforms.screenAspect.value = size.width / size.height; + } + + resolveDefaultShaders(vertexShader: string, fragmentShader: string) { + return { + vertexShader: resolveIncludes(vertexShader), + fragmentShader: resolveIncludes(fragmentShader), + }; + } + setUniformValues(values: any) { if (values === undefined) return; diff --git a/packages/use-shader-fx/src/fxs/types/index.ts b/packages/use-shader-fx/src/fxs/types/index.ts index 9fd8338f..09f2f33b 100644 --- a/packages/use-shader-fx/src/fxs/types/index.ts +++ b/packages/use-shader-fx/src/fxs/types/index.ts @@ -1,4 +1,5 @@ import * as THREE from "three"; +import { BasicFx } from "../materials/FxBasicFxMaterial"; export type Size = { width: number; height: number }; @@ -34,8 +35,7 @@ export interface HooksProps { * @param depthBuffer Unlike the default in three.js, the default is `false`. */ renderTargetOptions?: THREE.RenderTargetOptions; - materialParameters?: THREE.MaterialParameters; - fxBlending?: boolean; + materialParameters?: THREE.ShaderMaterialParameters; } /** diff --git a/packages/use-shader-fx/src/fxs/useCoverTexture/CoverTextureMaterial.ts b/packages/use-shader-fx/src/fxs/useCoverTexture/CoverTextureMaterial.ts new file mode 100644 index 00000000..5a3b2a9c --- /dev/null +++ b/packages/use-shader-fx/src/fxs/useCoverTexture/CoverTextureMaterial.ts @@ -0,0 +1,40 @@ +import * as THREE from "three"; +import { fragment, vertex } from "./coverTexture.glsl"; +import { + BasicFxUniforms, + FxBasicFxMaterial, +} from "../materials/FxBasicFxMaterial"; +import { CoverTextureValues } from "."; +import { mergeUniforms } from "three/src/renderers/shaders/UniformsUtils.js"; + +type CoverTextureUniforms = { + src: { value: THREE.Texture | null }; + textureResolution: { value: THREE.Vector2 }; +} & BasicFxUniforms; + +export class CoverTextureMaterial extends FxBasicFxMaterial { + static get type() { + return "NoiseMaterial"; + } + + uniforms: CoverTextureUniforms; + + constructor(uniformValues?: CoverTextureValues, parameters = {}) { + super(); + + this.type = CoverTextureMaterial.type; + + this.uniforms = mergeUniforms([ + this.uniforms, + { + src: { value: null }, + textureResolution: { value: new THREE.Vector2() }, + }, + ]) as CoverTextureUniforms; + + this.setUniformValues(uniformValues); + this.setValues(parameters); + + this.setupBasicFxShaders(vertex, fragment); + } +} diff --git a/packages/use-shader-fx/src/fxs/useCoverTexture/coverTexture.glsl.ts b/packages/use-shader-fx/src/fxs/useCoverTexture/coverTexture.glsl.ts new file mode 100644 index 00000000..83045de3 --- /dev/null +++ b/packages/use-shader-fx/src/fxs/useCoverTexture/coverTexture.glsl.ts @@ -0,0 +1,42 @@ +import { ShaderLib } from "../../libs/shaders/ShdaerLib"; + +export const vertex = ` + ${ShaderLib.basicFx_pars_vertex} + + uniform vec2 textureResolution; + varying vec2 vCoverTextureUv; + + void main() { + ${ShaderLib.basicFx_vertex} + + float textureAspect = textureResolution.x / textureResolution.y; + vec2 aspectRatio = vec2( + min(screenAspect / textureAspect, 1.0), + min(textureAspect / screenAspect, 1.0) + ); + vCoverTextureUv = vUv * aspectRatio + (1.0 - aspectRatio) * .5; + + gl_Position = vec4(position, 1.0); + } +`; + +export const fragment = ` + ${ShaderLib.basicFx_pars_fragment} + + uniform sampler2D src; + varying vec2 vCoverTextureUv; + + void main() { + + vec2 usf_Uv = vCoverTextureUv; + ${ShaderLib.basicFx_fragment_begin} + + vec4 texColor = texture2D(src, usf_Uv); + + vec4 usf_FragColor = texColor; + + ${ShaderLib.basicFx_fragment_end} + + gl_FragColor = usf_FragColor; + } +`; diff --git a/packages/use-shader-fx/src/fxs/useCoverTexture/index.ts b/packages/use-shader-fx/src/fxs/useCoverTexture/index.ts new file mode 100644 index 00000000..fc215f4c --- /dev/null +++ b/packages/use-shader-fx/src/fxs/useCoverTexture/index.ts @@ -0,0 +1,78 @@ +import * as THREE from "three"; +import { useCallback, useMemo } from "react"; +import { useCamera } from "../../utils/useCamera"; +import { useSingleFBO } from "../../utils/useSingleFBO"; +import { HooksProps, HooksReturn } from "../types"; +import { getDpr } from "../../utils/getDpr"; +import { RootState } from "../types"; +import { CoverTextureMaterial } from "./CoverTextureMaterial"; +import { useScene } from "../../utils/useScene"; +import { BasicFxValues } from "../materials/FxBasicFxMaterial"; + +export type CoverTextureValues = { + src?: THREE.Texture; + textureResolution?: THREE.Vector2; +} & BasicFxValues; + +/** + * @link https://github.com/FunTechInc/use-shader-fx?tab=readme-ov-file#usage + * + * It is a basic value noise with `fbm` and `domain warping` + */ +export const useCoverTexture = ({ + size, + dpr, + sizeUpdate, + renderTargetOptions, + materialParameters, + ...uniformValues +}: HooksProps & CoverTextureValues): HooksReturn< + CoverTextureValues, + CoverTextureMaterial +> => { + const _dpr = getDpr(dpr); + + const { scene, material } = useScene({ + material: CoverTextureMaterial, + uniformValues, + materialParameters, + }); + + const camera = useCamera(size); + const [renderTarget, updateRenderTarget] = useSingleFBO({ + scene, + camera, + size, + dpr: _dpr.fbo, + sizeUpdate, + ...renderTargetOptions, + }); + + const setValues = useCallback( + (newValues: CoverTextureValues) => { + material.setUniformValues(newValues); + }, + [material] + ); + + const render = useCallback( + (rootState: RootState, newValues?: CoverTextureValues) => { + const { gl } = rootState; + newValues && setValues(newValues); + + material.update(rootState); + + return updateRenderTarget({ gl }); + }, + [setValues, updateRenderTarget, material] + ); + + return { + render, + setValues, + texture: renderTarget.texture, + material, + scene, + camera, + }; +}; diff --git a/packages/use-shader-fx/src/fxs/useNoise/NoiseMaterial.ts b/packages/use-shader-fx/src/fxs/useNoise/NoiseMaterial.ts index 54a1fe49..01f7a787 100644 --- a/packages/use-shader-fx/src/fxs/useNoise/NoiseMaterial.ts +++ b/packages/use-shader-fx/src/fxs/useNoise/NoiseMaterial.ts @@ -1,48 +1,52 @@ import * as THREE from "three"; -import { ShaderChunk } from "../../libs/shaders/ShaderChunk"; -import fragment from "./noise.frag"; +import { noiseFragment, noiseVertex } from "./noise.glsl"; import { - FxBlendingMaterial, - FxBlendingUniforms, -} from "../materials/FxBlendingMaterial"; + BasicFxUniforms, + FxBasicFxMaterial, +} from "../materials/FxBasicFxMaterial"; import { NoiseValues } from "."; +import { mergeUniforms } from "three/src/renderers/shaders/UniformsUtils.js"; -export class NoiseMaterial extends FxBlendingMaterial { +type NoiseUniforms = { + tick: { value: number }; + scale: { value: number }; + timeStrength: { value: number }; + noiseOctaves: { value: number }; + fbmOctaves: { value: number }; + warpOctaves: { value: number }; + warpDirection: { value: THREE.Vector2 }; + warpStrength: { value: number }; +} & BasicFxUniforms; + +export class NoiseMaterial extends FxBasicFxMaterial { static get type() { return "NoiseMaterial"; } - uniforms: { - tick: { value: number }; - scale: { value: number }; - timeStrength: { value: number }; - noiseOctaves: { value: number }; - fbmOctaves: { value: number }; - warpOctaves: { value: number }; - warpDirection: { value: THREE.Vector2 }; - warpStrength: { value: number }; - } & FxBlendingUniforms; + uniforms: NoiseUniforms; constructor(uniformValues?: NoiseValues, parameters = {}) { - super(parameters); + super(); this.type = NoiseMaterial.type; - this.uniforms = { - tick: { value: 0.0 }, - scale: { value: 0.03 }, - timeStrength: { value: 0.3 }, - noiseOctaves: { value: 2 }, - fbmOctaves: { value: 2 }, - warpOctaves: { value: 2 }, - warpDirection: { value: new THREE.Vector2(2.0, 2.0) }, - warpStrength: { value: 8 }, - ...this.blendingUniforms, - }; - - this.resolveBlendingShader(ShaderChunk.blendingPlaneVertex, fragment); + this.uniforms = mergeUniforms([ + this.uniforms, + { + tick: { value: 0.0 }, + scale: { value: 0.03 }, + timeStrength: { value: 0.3 }, + noiseOctaves: { value: 2 }, + fbmOctaves: { value: 2 }, + warpOctaves: { value: 2 }, + warpDirection: { value: new THREE.Vector2(2.0, 2.0) }, + warpStrength: { value: 8 }, + }, + ]) as NoiseUniforms; this.setUniformValues(uniformValues); this.setValues(parameters); + + this.setupBasicFxShaders(noiseVertex, noiseFragment); } } diff --git a/packages/use-shader-fx/src/fxs/useNoise/index.ts b/packages/use-shader-fx/src/fxs/useNoise/index.ts index 5d37eed5..83c1a94f 100644 --- a/packages/use-shader-fx/src/fxs/useNoise/index.ts +++ b/packages/use-shader-fx/src/fxs/useNoise/index.ts @@ -7,12 +7,7 @@ import { getDpr } from "../../utils/getDpr"; import { RootState } from "../types"; import { NoiseMaterial } from "./NoiseMaterial"; import { useScene } from "../../utils/useScene"; - -/*=============================================== -- textureのcoverする機能とかも入れたいか - - これをvertexで処理 -- cloneUniformとmergeUniformすればいいのかも。マテリアルの継承で。 -===============================================*/ +import { BasicFxValues } from "../materials/FxBasicFxMaterial"; export type NoiseValues = { /** noise scale , default : `0.004` */ @@ -31,15 +26,7 @@ export type NoiseValues = { warpStrength?: number; /** you can get into the rhythm ♪ , default : `false` */ beat?: number | false; - - /*=============================================== - blending - ===============================================*/ - fxBlendingSrc?: THREE.Texture; - uvBlending?: number; - alphaBlending?: number; - fxBlendingSrcResolution?: THREE.Vector2; -}; +} & BasicFxValues; /** * @link https://github.com/FunTechInc/use-shader-fx?tab=readme-ov-file#usage @@ -51,17 +38,14 @@ export const useNoise = ({ dpr, sizeUpdate, renderTargetOptions, - fxBlending, materialParameters, - ...values + ...uniformValues }: HooksProps & NoiseValues): HooksReturn => { const _dpr = getDpr(dpr); const { scene, material } = useScene({ - size, material: NoiseMaterial, - uniformValues: values, - fxBlending, + uniformValues, materialParameters, }); @@ -88,6 +72,9 @@ export const useNoise = ({ newValues && setValues(newValues); material.uniforms.tick.value = newValues?.beat || clock.getElapsedTime(); + + material.update(rootState); + return updateRenderTarget({ gl }); }, [setValues, updateRenderTarget, material] diff --git a/packages/use-shader-fx/src/fxs/useNoise/noise.frag b/packages/use-shader-fx/src/fxs/useNoise/noise.frag deleted file mode 100644 index 000819d7..00000000 --- a/packages/use-shader-fx/src/fxs/useNoise/noise.frag +++ /dev/null @@ -1,86 +0,0 @@ -precision highp float; -precision highp int; - -varying vec2 vUv; -uniform float tick; -uniform float timeStrength; -uniform int noiseOctaves; -uniform int fbmOctaves; -uniform int warpOctaves; -uniform vec2 warpDirection; -uniform float warpStrength; -uniform float scale; - -const float per = 0.5; -const float PI = 3.14159265359; - -float rnd(vec2 n) { - float a = 0.129898; - float b = 0.78233; - float c = 437.585453; - float dt= dot(n ,vec2(a, b)); - float sn= mod(dt, PI); - return fract(sin(sn) * c); -} - -float interpolate(float a, float b, float x){ - float f = (1.0 - cos(x * PI)) * 0.5; - return a * (1.0 - f) + b * f; -} - -float irnd(vec2 p){ - vec2 i = floor(p); - vec2 f = fract(p); - vec4 v = vec4(rnd(vec2(i.x,i.y)),rnd(vec2(i.x + 1.0,i.y)),rnd(vec2(i.x,i.y + 1.0)),rnd(vec2(i.x + 1.0, i.y + 1.0))); - return interpolate(interpolate(v.x, v.y, f.x), interpolate(v.z, v.w, f.x), f.y); -} - -// Based on The Book of Shaders -// https://thebookofshaders.com/13/ -float noise(vec2 p, float time){ - float t = 0.0; - for(int i = 0; i < noiseOctaves; i++){ - float freq = pow(2.0, float(i)); - float amp = pow(per, float(noiseOctaves - i)); - t += irnd(vec2(p.y / freq + time, p.x / freq + time)) * amp; - } - return t; -} - -float fbm(vec2 x, float time) { - float v = 0.0; - float a = 0.5; - vec2 shift = vec2(100); - mat2 rot = mat2(cos(0.5), sin(0.5), -sin(0.5), cos(0.5)); - float sign = 1.0; - for (int i = 0; i < fbmOctaves; ++i) { - v += a * noise(x, time * sign); - x = rot * x * 2.0 + shift; - a *= 0.5; - sign *= -1.0; - } - return v; -} - -float warp(vec2 x, float g,float time){ - float val = 0.0; - for (int i = 0; i < warpOctaves; i++){ - val = fbm(x + g * vec2(cos(warpDirection.x * val), sin(warpDirection.y * val)), time); - } - return val; -} - - -#usf - -void main() { - float noise = warp(gl_FragCoord.xy * scale ,warpStrength,tick * timeStrength); - vec4 noiseColor = vec4(vec3(noise),1.0); - - vec4 blendingDst = noiseColor; - - #usf - - gl_FragColor = blendingDst; - -} \ No newline at end of file diff --git a/packages/use-shader-fx/src/fxs/useNoise/noise.glsl.ts b/packages/use-shader-fx/src/fxs/useNoise/noise.glsl.ts new file mode 100644 index 00000000..f7f93fdf --- /dev/null +++ b/packages/use-shader-fx/src/fxs/useNoise/noise.glsl.ts @@ -0,0 +1,100 @@ +import { ShaderLib } from "../../libs/shaders/ShdaerLib"; + +export const noiseVertex = ` + ${ShaderLib.basicFx_pars_vertex} + void main() { + ${ShaderLib.basicFx_vertex} + gl_Position = vec4(position, 1.0); + } +`; + +export const noiseFragment = ` + precision highp float; + precision highp int; + + ${ShaderLib.basicFx_pars_fragment} + + uniform float tick; + uniform float timeStrength; + uniform int noiseOctaves; + uniform int fbmOctaves; + uniform int warpOctaves; + uniform vec2 warpDirection; + uniform float warpStrength; + uniform float scale; + + const float per = 0.5; + const float PI = 3.14159265359; + + float rnd(vec2 n) { + float a = 0.129898; + float b = 0.78233; + float c = 437.585453; + float dt= dot(n ,vec2(a, b)); + float sn= mod(dt, PI); + return fract(sin(sn) * c); + } + + float interpolate(float a, float b, float x){ + float f = (1.0 - cos(x * PI)) * 0.5; + return a * (1.0 - f) + b * f; + } + + float irnd(vec2 p){ + vec2 i = floor(p); + vec2 f = fract(p); + vec4 v = vec4(rnd(vec2(i.x,i.y)),rnd(vec2(i.x + 1.0,i.y)),rnd(vec2(i.x,i.y + 1.0)),rnd(vec2(i.x + 1.0, i.y + 1.0))); + return interpolate(interpolate(v.x, v.y, f.x), interpolate(v.z, v.w, f.x), f.y); + } + + // Based on The Book of Shaders + // https://thebookofshaders.com/13/ + float noise(vec2 p, float time){ + float t = 0.0; + for(int i = 0; i < noiseOctaves; i++){ + float freq = pow(2.0, float(i)); + float amp = pow(per, float(noiseOctaves - i)); + t += irnd(vec2(p.y / freq + time, p.x / freq + time)) * amp; + } + return t; + } + + float fbm(vec2 x, float time) { + float v = 0.0; + float a = 0.5; + vec2 shift = vec2(100); + mat2 rot = mat2(cos(0.5), sin(0.5), -sin(0.5), cos(0.5)); + float sign = 1.0; + for (int i = 0; i < fbmOctaves; ++i) { + v += a * noise(x, time * sign); + x = rot * x * 2.0 + shift; + a *= 0.5; + sign *= -1.0; + } + return v; + } + + float warp(vec2 x, float g,float time){ + float val = 0.0; + for (int i = 0; i < warpOctaves; i++){ + val = fbm(x + g * vec2(cos(warpDirection.x * val), sin(warpDirection.y * val)), time); + } + return val; + } + + void main() { + + vec2 usf_Uv = gl_FragCoord.xy; + + ${ShaderLib.basicFx_fragment_begin} + + float noise = warp(usf_Uv * scale ,warpStrength,tick * timeStrength); + vec4 noiseColor = vec4(vec3(noise),1.0); + + vec4 usf_FragColor = noiseColor; + + ${ShaderLib.basicFx_fragment_end} + + gl_FragColor = usf_FragColor; + } +`; diff --git a/packages/use-shader-fx/src/index.js b/packages/use-shader-fx/src/index.js index ed03505b..095546d4 100644 --- a/packages/use-shader-fx/src/index.js +++ b/packages/use-shader-fx/src/index.js @@ -3,3 +3,4 @@ FXs ===============================================*/ export * from "./fxs/useNoise"; export * from "./fxs/useFluid"; +export * from "./fxs/useCoverTexture"; diff --git a/packages/use-shader-fx/src/libs/shaders/ShaderChunk.ts b/packages/use-shader-fx/src/libs/shaders/ShaderChunk.ts index 5f25e116..84f21fdd 100644 --- a/packages/use-shader-fx/src/libs/shaders/ShaderChunk.ts +++ b/packages/use-shader-fx/src/libs/shaders/ShaderChunk.ts @@ -1,35 +1,38 @@ -import wobble3D from "./shaderChunk/wobble3D.glsl"; -import snoise from "./shaderChunk/snoise.glsl"; -import coverTexture from "./shaderChunk/coverTexture.glsl"; -import planeVertex from "./shaderChunk/planeVertex.glsl"; -import defaultVertex from "./shaderChunk/defaultVertex.glsl"; -import hsv2rgb from "./shaderChunk/hsv2rgb.glsl"; -import rgb2hsv from "./shaderChunk/rgb2hsv.glsl"; -import blendingColor from "./shaderChunk/blendingColor.glsl"; -import blendingUniforms from "./shaderChunk/blendingUniforms.glsl"; -import blendingPlaneVertex from "./shaderChunk/blendingPlaneVertex.glsl"; +import default_pars_fragment from "./ShaderChunk/default_pars_fragment.glsl"; +import default_pars_vertex from "./ShaderChunk/default_pars_vertex.glsl"; +import mixSrc_fragment_begin from "./ShaderChunk/mixSrc_fragment_begin.glsl"; +import mixSrc_fragment_end from "./ShaderChunk/mixSrc_fragment_end.glsl"; +import mixSrc_pars_fragment from "./ShaderChunk/mixSrc_pars_fragment.glsl"; +import mixSrc_pars_vertex from "./ShaderChunk/mixSrc_pars_vertex.glsl"; +import mixSrc_vertex from "./ShaderChunk/mixSrc_vertex.glsl"; +import mixDst_fragment from "./ShaderChunk/mixDst_fragment.glsl"; +import mixDst_pars_fragment from "./ShaderChunk/mixDst_pars_fragment.glsl"; +import mixDst_pars_vertex from "./ShaderChunk/mixDst_pars_vertex.glsl"; +import mixDst_vertex from "./ShaderChunk/mixDst_vertex.glsl"; export type ShaderChunkTypes = - | "wobble3D" - | "snoise" - | "coverTexture" - | "planeVertex" - | "defaultVertex" - | "hsv2rgb" - | "rgb2hsv" - | "blendingColor" - | "blendingUniforms" - | "blendingPlaneVertex"; + | "default_pars_fragment" + | "default_pars_vertex" + | "mixSrc_fragment_begin" + | "mixSrc_fragment_end" + | "mixSrc_pars_fragment" + | "mixSrc_pars_vertex" + | "mixSrc_vertex" + | "mixDst_fragment" + | "mixDst_pars_fragment" + | "mixDst_pars_vertex" + | "mixDst_vertex"; export const ShaderChunk: { [K in ShaderChunkTypes]: string } = Object.freeze({ - wobble3D, - snoise, - coverTexture, - planeVertex, - defaultVertex, - hsv2rgb, - rgb2hsv, - blendingColor, - blendingUniforms, - blendingPlaneVertex, + default_pars_fragment, + default_pars_vertex, + mixSrc_fragment_begin, + mixSrc_fragment_end, + mixSrc_pars_fragment, + mixSrc_pars_vertex, + mixSrc_vertex, + mixDst_fragment, + mixDst_pars_fragment, + mixDst_pars_vertex, + mixDst_vertex, }); diff --git a/packages/use-shader-fx/src/libs/shaders/ShaderChunk/default_pars_fragment.glsl b/packages/use-shader-fx/src/libs/shaders/ShaderChunk/default_pars_fragment.glsl new file mode 100644 index 00000000..6ba21e9c --- /dev/null +++ b/packages/use-shader-fx/src/libs/shaders/ShaderChunk/default_pars_fragment.glsl @@ -0,0 +1,2 @@ +varying vec2 vUv; +uniform vec2 resolution; \ No newline at end of file diff --git a/packages/use-shader-fx/src/libs/shaders/ShaderChunk/default_pars_vertex.glsl b/packages/use-shader-fx/src/libs/shaders/ShaderChunk/default_pars_vertex.glsl new file mode 100644 index 00000000..06a6c603 --- /dev/null +++ b/packages/use-shader-fx/src/libs/shaders/ShaderChunk/default_pars_vertex.glsl @@ -0,0 +1,3 @@ +varying vec2 vUv; +uniform vec2 resolution; +uniform float screenAspect; \ No newline at end of file diff --git a/packages/use-shader-fx/src/libs/shaders/ShaderChunk/mixDst_fragment.glsl b/packages/use-shader-fx/src/libs/shaders/ShaderChunk/mixDst_fragment.glsl new file mode 100644 index 00000000..0fbee3d8 --- /dev/null +++ b/packages/use-shader-fx/src/libs/shaders/ShaderChunk/mixDst_fragment.glsl @@ -0,0 +1,9 @@ +#ifdef USF_USE_MIXDST + + vec4 mixDstMap = texture2D(mixDst, mix(vMixDstCoverUv,usf_FragColor.rg,mixDstUv)); + + usf_FragColor = mix(usf_FragColor, mixDstMap, mixDstColor); + + usf_FragColor = mix(usf_FragColor, mixDstMap, mixDstMap.a * mixDstAlpha); + +#endif \ No newline at end of file diff --git a/packages/use-shader-fx/src/libs/shaders/ShaderChunk/mixDst_pars_fragment.glsl b/packages/use-shader-fx/src/libs/shaders/ShaderChunk/mixDst_pars_fragment.glsl new file mode 100644 index 00000000..b84bb43f --- /dev/null +++ b/packages/use-shader-fx/src/libs/shaders/ShaderChunk/mixDst_pars_fragment.glsl @@ -0,0 +1,7 @@ +#ifdef USF_USE_MIXDST + varying vec2 vMixDstCoverUv; + uniform sampler2D mixDst; + uniform float mixDstUv; + uniform float mixDstAlpha; + uniform float mixDstColor; +#endif \ No newline at end of file diff --git a/packages/use-shader-fx/src/libs/shaders/ShaderChunk/mixDst_pars_vertex.glsl b/packages/use-shader-fx/src/libs/shaders/ShaderChunk/mixDst_pars_vertex.glsl new file mode 100644 index 00000000..668d3c09 --- /dev/null +++ b/packages/use-shader-fx/src/libs/shaders/ShaderChunk/mixDst_pars_vertex.glsl @@ -0,0 +1,4 @@ +#ifdef USF_USE_MIXDST + varying vec2 vMixDstCoverUv; + uniform vec2 mixDstResolution; +#endif \ No newline at end of file diff --git a/packages/use-shader-fx/src/libs/shaders/ShaderChunk/mixDst_vertex.glsl b/packages/use-shader-fx/src/libs/shaders/ShaderChunk/mixDst_vertex.glsl new file mode 100644 index 00000000..13edd83c --- /dev/null +++ b/packages/use-shader-fx/src/libs/shaders/ShaderChunk/mixDst_vertex.glsl @@ -0,0 +1,8 @@ +#ifdef USF_USE_MIXDST + float mixDstAspect = mixDstResolution.x / mixDstResolution.y; + vec2 mixDstAspectAspectRatio = vec2( + min(screenAspect / mixDstAspect, 1.0), + min(mixDstAspect / screenAspect, 1.0) + ); + vMixDstCoverUv = vUv * mixDstAspectAspectRatio + (1.0 - mixDstAspectAspectRatio) * .5; +#endif \ No newline at end of file diff --git a/packages/use-shader-fx/src/libs/shaders/ShaderChunk/mixSrc_fragment_begin.glsl b/packages/use-shader-fx/src/libs/shaders/ShaderChunk/mixSrc_fragment_begin.glsl new file mode 100644 index 00000000..d1b9355b --- /dev/null +++ b/packages/use-shader-fx/src/libs/shaders/ShaderChunk/mixSrc_fragment_begin.glsl @@ -0,0 +1,6 @@ +#ifdef USF_USE_MIXSRC + + vec4 mixSrcMap = texture2D(mixSrc, vMixSrcCoverUv); + usf_Uv = mix(usf_Uv, mixSrcMap.rg, mixSrcUv); + +#endif \ No newline at end of file diff --git a/packages/use-shader-fx/src/libs/shaders/ShaderChunk/mixSrc_fragment_end.glsl b/packages/use-shader-fx/src/libs/shaders/ShaderChunk/mixSrc_fragment_end.glsl new file mode 100644 index 00000000..8d97c8f8 --- /dev/null +++ b/packages/use-shader-fx/src/libs/shaders/ShaderChunk/mixSrc_fragment_end.glsl @@ -0,0 +1,7 @@ +#ifdef USF_USE_MIXSRC + + usf_FragColor = mix(usf_FragColor, mixSrcMap, mixSrcColor); + + usf_FragColor = mix(usf_FragColor, mixSrcMap, mixSrcMap.a * mixSrcAlpha); + +#endif \ No newline at end of file diff --git a/packages/use-shader-fx/src/libs/shaders/ShaderChunk/mixSrc_pars_fragment.glsl b/packages/use-shader-fx/src/libs/shaders/ShaderChunk/mixSrc_pars_fragment.glsl new file mode 100644 index 00000000..35fa8c27 --- /dev/null +++ b/packages/use-shader-fx/src/libs/shaders/ShaderChunk/mixSrc_pars_fragment.glsl @@ -0,0 +1,7 @@ +#ifdef USF_USE_MIXSRC + varying vec2 vMixSrcCoverUv; + uniform sampler2D mixSrc; + uniform float mixSrcUv; + uniform float mixSrcAlpha; + uniform float mixSrcColor; +#endif \ No newline at end of file diff --git a/packages/use-shader-fx/src/libs/shaders/ShaderChunk/mixSrc_pars_vertex.glsl b/packages/use-shader-fx/src/libs/shaders/ShaderChunk/mixSrc_pars_vertex.glsl new file mode 100644 index 00000000..a98019a6 --- /dev/null +++ b/packages/use-shader-fx/src/libs/shaders/ShaderChunk/mixSrc_pars_vertex.glsl @@ -0,0 +1,4 @@ +#ifdef USF_USE_MIXSRC + varying vec2 vMixSrcCoverUv; + uniform vec2 mixSrcResolution; +#endif \ No newline at end of file diff --git a/packages/use-shader-fx/src/libs/shaders/ShaderChunk/mixSrc_vertex.glsl b/packages/use-shader-fx/src/libs/shaders/ShaderChunk/mixSrc_vertex.glsl new file mode 100644 index 00000000..dd1a5873 --- /dev/null +++ b/packages/use-shader-fx/src/libs/shaders/ShaderChunk/mixSrc_vertex.glsl @@ -0,0 +1,8 @@ +#ifdef USF_USE_MIXSRC + float mixSrcAspect = mixSrcResolution.x / mixSrcResolution.y; + vec2 mixSrcAspectAspectRatio = vec2( + min(screenAspect / mixSrcAspect, 1.0), + min(mixSrcAspect / screenAspect, 1.0) + ); + vMixSrcCoverUv = vUv * mixSrcAspectAspectRatio + (1.0 - mixSrcAspectAspectRatio) * .5; +#endif \ No newline at end of file diff --git a/packages/use-shader-fx/src/libs/shaders/ShaderLib/basicFx_fragment_begin.glsl b/packages/use-shader-fx/src/libs/shaders/ShaderLib/basicFx_fragment_begin.glsl new file mode 100644 index 00000000..ae4979ef --- /dev/null +++ b/packages/use-shader-fx/src/libs/shaders/ShaderLib/basicFx_fragment_begin.glsl @@ -0,0 +1 @@ +#usf \ No newline at end of file diff --git a/packages/use-shader-fx/src/libs/shaders/ShaderLib/basicFx_fragment_end.glsl b/packages/use-shader-fx/src/libs/shaders/ShaderLib/basicFx_fragment_end.glsl new file mode 100644 index 00000000..313908db --- /dev/null +++ b/packages/use-shader-fx/src/libs/shaders/ShaderLib/basicFx_fragment_end.glsl @@ -0,0 +1,2 @@ +#usf +#usf \ No newline at end of file diff --git a/packages/use-shader-fx/src/libs/shaders/ShaderLib/basicFx_pars_fragment.glsl b/packages/use-shader-fx/src/libs/shaders/ShaderLib/basicFx_pars_fragment.glsl new file mode 100644 index 00000000..e1590e0e --- /dev/null +++ b/packages/use-shader-fx/src/libs/shaders/ShaderLib/basicFx_pars_fragment.glsl @@ -0,0 +1,5 @@ +precision highp float; + +#usf +#usf +#usf \ No newline at end of file diff --git a/packages/use-shader-fx/src/libs/shaders/ShaderLib/basicFx_pars_vertex.glsl b/packages/use-shader-fx/src/libs/shaders/ShaderLib/basicFx_pars_vertex.glsl new file mode 100644 index 00000000..13b530ee --- /dev/null +++ b/packages/use-shader-fx/src/libs/shaders/ShaderLib/basicFx_pars_vertex.glsl @@ -0,0 +1,5 @@ +precision highp float; + +#usf +#usf +#usf \ No newline at end of file diff --git a/packages/use-shader-fx/src/libs/shaders/ShaderLib/basicFx_vertex.glsl b/packages/use-shader-fx/src/libs/shaders/ShaderLib/basicFx_vertex.glsl new file mode 100644 index 00000000..2df65a30 --- /dev/null +++ b/packages/use-shader-fx/src/libs/shaders/ShaderLib/basicFx_vertex.glsl @@ -0,0 +1,3 @@ +vUv = uv; +#usf +#usf \ No newline at end of file diff --git a/packages/use-shader-fx/src/libs/shaders/ShdaerLib.ts b/packages/use-shader-fx/src/libs/shaders/ShdaerLib.ts new file mode 100644 index 00000000..60be5962 --- /dev/null +++ b/packages/use-shader-fx/src/libs/shaders/ShdaerLib.ts @@ -0,0 +1,20 @@ +import basicFx_vertex from "./ShaderLib/basicFx_vertex.glsl"; +import basicFx_fragment_begin from "./ShaderLib/basicFx_fragment_begin.glsl"; +import basicFx_fragment_end from "./ShaderLib/basicFx_fragment_end.glsl"; +import basicFx_pars_fragment from "./ShaderLib/basicFx_pars_fragment.glsl"; +import basicFx_pars_vertex from "./ShaderLib/basicFx_pars_vertex.glsl"; + +export type ShaderLibTypes = + | "basicFx_vertex" + | "basicFx_fragment_begin" + | "basicFx_fragment_end" + | "basicFx_pars_fragment" + | "basicFx_pars_vertex"; + +export const ShaderLib: { [K in ShaderLibTypes]: string } = Object.freeze({ + basicFx_vertex, + basicFx_fragment_begin, + basicFx_fragment_end, + basicFx_pars_fragment, + basicFx_pars_vertex, +}); diff --git a/packages/use-shader-fx/src/libs/shaders/shaderChunk/blendingColor.glsl b/packages/use-shader-fx/src/libs/shaders/shaderChunk/blendingColor.glsl deleted file mode 100644 index 2862c999..00000000 --- a/packages/use-shader-fx/src/libs/shaders/shaderChunk/blendingColor.glsl +++ /dev/null @@ -1,11 +0,0 @@ -// float screenAspect = resolution.x / resolution.y; -// float blendingSrcAspect = fxBlendingSrcResolution.x / fxBlendingSrcResolution.y; -// vec2 aspectRatio = vec2( -// min(screenAspect / blendingSrcAspect, 1.0), -// min(blendingSrcAspect / screenAspect, 1.0) -// ); -// vec2 coverUV = vUv * aspectRatio + (1.0 - aspectRatio) * .5; -vec4 fxBlended = texture2D(fxBlendingSrc, mix(vCoverUv, vec2(blendingDst.g), uvBlending)); -vec4 alphaBlended = mix(blendingDst, fxBlended,fxBlended.a * alphaBlending); - -blendingDst = alphaBlended; \ No newline at end of file diff --git a/packages/use-shader-fx/src/libs/shaders/shaderChunk/blendingPlaneVertex.glsl b/packages/use-shader-fx/src/libs/shaders/shaderChunk/blendingPlaneVertex.glsl deleted file mode 100644 index 0014af8f..00000000 --- a/packages/use-shader-fx/src/libs/shaders/shaderChunk/blendingPlaneVertex.glsl +++ /dev/null @@ -1,21 +0,0 @@ -precision highp float; - -varying vec2 vUv; -varying vec2 vCoverUv; - -uniform vec2 resolution; -uniform vec2 fxBlendingSrcResolution; - -void main() { - vUv = uv; - - float screenAspect = resolution.x / resolution.y; - float blendingSrcAspect = fxBlendingSrcResolution.x / fxBlendingSrcResolution.y; - vec2 aspectRatio = vec2( - min(screenAspect / blendingSrcAspect, 1.0), - min(blendingSrcAspect / screenAspect, 1.0) - ); - vCoverUv = vUv * aspectRatio + (1.0 - aspectRatio) * .5; - - gl_Position = vec4(position, 1.0); -} \ No newline at end of file diff --git a/packages/use-shader-fx/src/libs/shaders/shaderChunk/blendingUniforms.glsl b/packages/use-shader-fx/src/libs/shaders/shaderChunk/blendingUniforms.glsl deleted file mode 100644 index 9bae0da1..00000000 --- a/packages/use-shader-fx/src/libs/shaders/shaderChunk/blendingUniforms.glsl +++ /dev/null @@ -1,7 +0,0 @@ -// uniform vec2 resolution; -// uniform vec2 fxBlendingSrcResolution; - -varying vec2 vCoverUv; -uniform sampler2D fxBlendingSrc; -uniform float uvBlending; -uniform float alphaBlending; \ No newline at end of file diff --git a/packages/use-shader-fx/src/libs/shaders/shaderChunk/coverTexture.glsl b/packages/use-shader-fx/src/libs/shaders/shaderChunk/coverTexture.glsl deleted file mode 100644 index 765bfc93..00000000 --- a/packages/use-shader-fx/src/libs/shaders/shaderChunk/coverTexture.glsl +++ /dev/null @@ -1,7 +0,0 @@ -float screenAspect = uResolution.x / uResolution.y; -float textureAspect = uTextureResolution.x / uTextureResolution.y; -vec2 aspectRatio = vec2( - min(screenAspect / textureAspect, 1.0), - min(textureAspect / screenAspect, 1.0) -); -vec2 uv = vUv * aspectRatio + (1.0 - aspectRatio) * .5; \ No newline at end of file diff --git a/packages/use-shader-fx/src/libs/shaders/shaderChunk/defaultVertex.glsl b/packages/use-shader-fx/src/libs/shaders/shaderChunk/defaultVertex.glsl deleted file mode 100644 index fb20d32c..00000000 --- a/packages/use-shader-fx/src/libs/shaders/shaderChunk/defaultVertex.glsl +++ /dev/null @@ -1,6 +0,0 @@ -varying vec2 vUv; - -void main() { - vUv = uv; - gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0); -} \ No newline at end of file diff --git a/packages/use-shader-fx/src/libs/shaders/shaderChunk/hsv2rgb.glsl b/packages/use-shader-fx/src/libs/shaders/shaderChunk/hsv2rgb.glsl deleted file mode 100644 index 89f859a6..00000000 --- a/packages/use-shader-fx/src/libs/shaders/shaderChunk/hsv2rgb.glsl +++ /dev/null @@ -1,6 +0,0 @@ -vec3 hsv2rgb(vec3 c) -{ - vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0); - vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www); - return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y); -} \ No newline at end of file diff --git a/packages/use-shader-fx/src/libs/shaders/shaderChunk/planeVertex.glsl b/packages/use-shader-fx/src/libs/shaders/shaderChunk/planeVertex.glsl deleted file mode 100644 index 304094df..00000000 --- a/packages/use-shader-fx/src/libs/shaders/shaderChunk/planeVertex.glsl +++ /dev/null @@ -1,8 +0,0 @@ -precision highp float; - -varying vec2 vUv; - -void main() { - vUv = uv; - gl_Position = vec4(position, 1.0); -} \ No newline at end of file diff --git a/packages/use-shader-fx/src/libs/shaders/shaderChunk/rgb2hsv.glsl b/packages/use-shader-fx/src/libs/shaders/shaderChunk/rgb2hsv.glsl deleted file mode 100644 index deb954f4..00000000 --- a/packages/use-shader-fx/src/libs/shaders/shaderChunk/rgb2hsv.glsl +++ /dev/null @@ -1,10 +0,0 @@ -vec3 rgb2hsv(vec3 c) -{ - vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0); - vec4 p = mix(vec4(c.bg, K.wz), vec4(c.gb, K.xy), step(c.b, c.g)); - vec4 q = mix(vec4(p.xyw, c.r), vec4(c.r, p.yzx), step(p.x, c.r)); - - float d = q.x - min(q.w, q.y); - float e = 1.0e-10; - return vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x); -} \ No newline at end of file diff --git a/packages/use-shader-fx/src/libs/shaders/shaderChunk/snoise.glsl b/packages/use-shader-fx/src/libs/shaders/shaderChunk/snoise.glsl deleted file mode 100644 index 4c34f6e3..00000000 --- a/packages/use-shader-fx/src/libs/shaders/shaderChunk/snoise.glsl +++ /dev/null @@ -1,58 +0,0 @@ -// -// by Nikita Miropolskiy - -/* discontinuous pseudorandom uniformly distributed in [-0.5, +0.5]^3 */ -vec3 random3(vec3 c) { - float j = 4096.0*sin(dot(c,vec3(17.0, 59.4, 15.0))); - vec3 r; - r.z = fract(512.0*j); - j *= .125; - r.x = fract(512.0*j); - j *= .125; - r.y = fract(512.0*j); - return r-0.5; -} - -const float F3 = 0.3333333; -const float G3 = 0.1666667; - -float snoise(vec3 p) { - - vec3 s = floor(p + dot(p, vec3(F3))); - vec3 x = p - s + dot(s, vec3(G3)); - - vec3 e = step(vec3(0.0), x - x.yzx); - vec3 i1 = e*(1.0 - e.zxy); - vec3 i2 = 1.0 - e.zxy*(1.0 - e); - - vec3 x1 = x - i1 + G3; - vec3 x2 = x - i2 + 2.0*G3; - vec3 x3 = x - 1.0 + 3.0*G3; - - vec4 w, d; - - w.x = dot(x, x); - w.y = dot(x1, x1); - w.z = dot(x2, x2); - w.w = dot(x3, x3); - - w = max(0.6 - w, 0.0); - - d.x = dot(random3(s), x); - d.y = dot(random3(s + i1), x1); - d.z = dot(random3(s + i2), x2); - d.w = dot(random3(s + 1.0), x3); - - w *= w; - w *= w; - d *= w; - - return dot(d, vec4(52.0)); -} - -float snoiseFractal(vec3 m) { - return 0.5333333* snoise(m) - +0.2666667* snoise(2.0*m) - +0.1333333* snoise(4.0*m) - +0.0666667* snoise(8.0*m); -} \ No newline at end of file diff --git a/packages/use-shader-fx/src/libs/shaders/shaderChunk/wobble3D.glsl b/packages/use-shader-fx/src/libs/shaders/shaderChunk/wobble3D.glsl deleted file mode 100644 index 31df8df9..00000000 --- a/packages/use-shader-fx/src/libs/shaders/shaderChunk/wobble3D.glsl +++ /dev/null @@ -1,111 +0,0 @@ -// Simplex 4D Noise -// by Ian McEwan, Ashima Arts -// -vec4 permute(vec4 x){return mod(((x*34.0)+1.0)*x, 289.0);} -float permute(float x){return floor(mod(((x*34.0)+1.0)*x, 289.0));} -vec4 taylorInvSqrt(vec4 r){return 1.79284291400159 - 0.85373472095314 * r;} -float taylorInvSqrt(float r){return 1.79284291400159 - 0.85373472095314 * r;} - -vec4 grad4(float j, vec4 ip) -{ - const vec4 ones = vec4(1.0, 1.0, 1.0, -1.0); - vec4 p,s; - - p.xyz = floor( fract (vec3(j) * ip.xyz) * 7.0) * ip.z - 1.0; - p.w = 1.5 - dot(abs(p.xyz), ones.xyz); - s = vec4(lessThan(p, vec4(0.0))); - p.xyz = p.xyz + (s.xyz*2.0 - 1.0) * s.www; - - return p; -} - -float simplexNoise4d(vec4 v) -{ - const vec2 C = vec2( 0.138196601125010504, // (5 - sqrt(5))/20 G4 - 0.309016994374947451); // (sqrt(5) - 1)/4 F4 - // First corner - vec4 i = floor(v + dot(v, C.yyyy) ); - vec4 x0 = v - i + dot(i, C.xxxx); - - // Other corners - - // Rank sorting originally contributed by Bill Licea-Kane, AMD (formerly ATI) - vec4 i0; - - vec3 isX = step( x0.yzw, x0.xxx ); - vec3 isYZ = step( x0.zww, x0.yyz ); - // i0.x = dot( isX, vec3( 1.0 ) ); - i0.x = isX.x + isX.y + isX.z; - i0.yzw = 1.0 - isX; - - // i0.y += dot( isYZ.xy, vec2( 1.0 ) ); - i0.y += isYZ.x + isYZ.y; - i0.zw += 1.0 - isYZ.xy; - - i0.z += isYZ.z; - i0.w += 1.0 - isYZ.z; - - // i0 now contains the unique values 0,1,2,3 in each channel - vec4 i3 = clamp( i0, 0.0, 1.0 ); - vec4 i2 = clamp( i0-1.0, 0.0, 1.0 ); - vec4 i1 = clamp( i0-2.0, 0.0, 1.0 ); - - // x0 = x0 - 0.0 + 0.0 * C - vec4 x1 = x0 - i1 + 1.0 * C.xxxx; - vec4 x2 = x0 - i2 + 2.0 * C.xxxx; - vec4 x3 = x0 - i3 + 3.0 * C.xxxx; - vec4 x4 = x0 - 1.0 + 4.0 * C.xxxx; - - // Permutations - i = mod(i, 289.0); - float j0 = permute( permute( permute( permute(i.w) + i.z) + i.y) + i.x); - vec4 j1 = permute( permute( permute( permute ( - i.w + vec4(i1.w, i2.w, i3.w, 1.0 )) - + i.z + vec4(i1.z, i2.z, i3.z, 1.0 )) - + i.y + vec4(i1.y, i2.y, i3.y, 1.0 )) - + i.x + vec4(i1.x, i2.x, i3.x, 1.0 )); - // Gradients - // ( 7*7*6 points uniformly over a cube, mapped onto a 4-octahedron.) - // 7*7*6 = 294, which is close to the ring size 17*17 = 289. - - vec4 ip = vec4(1.0/294.0, 1.0/49.0, 1.0/7.0, 0.0) ; - - vec4 p0 = grad4(j0, ip); - vec4 p1 = grad4(j1.x, ip); - vec4 p2 = grad4(j1.y, ip); - vec4 p3 = grad4(j1.z, ip); - vec4 p4 = grad4(j1.w, ip); - - // Normalise gradients - vec4 norm = taylorInvSqrt(vec4(dot(p0,p0), dot(p1,p1), dot(p2, p2), dot(p3,p3))); - p0 *= norm.x; - p1 *= norm.y; - p2 *= norm.z; - p3 *= norm.w; - p4 *= taylorInvSqrt(dot(p4,p4)); - - // Mix contributions from the five corners - vec3 m0 = max(0.6 - vec3(dot(x0,x0), dot(x1,x1), dot(x2,x2)), 0.0); - vec2 m1 = max(0.6 - vec2(dot(x3,x3), dot(x4,x4) ), 0.0); - m0 = m0 * m0; - m1 = m1 * m1; - return 49.0 * ( dot(m0*m0, vec3( dot( p0, x0 ), dot( p1, x1 ), dot( p2, x2 ))) - + dot(m1*m1, vec2( dot( p3, x3 ), dot( p4, x4 ) ) ) ) ; - -} - -float getWobble(vec3 position) -{ - vec3 warpedPosition = position; - warpedPosition += simplexNoise4d( - vec4( - position * uWarpPositionFrequency, - uTime * uWarpTimeFrequency - ) - ) * uWarpStrength; - - return simplexNoise4d(vec4( - warpedPosition * uWobblePositionFrequency, // XYZ - uTime * uWobbleTimeFrequency // W - )) * uWobbleStrength; -} \ No newline at end of file diff --git a/packages/use-shader-fx/src/utils/useScene.ts b/packages/use-shader-fx/src/utils/useScene.ts index d3316942..0a050fe2 100644 --- a/packages/use-shader-fx/src/utils/useScene.ts +++ b/packages/use-shader-fx/src/utils/useScene.ts @@ -1,12 +1,10 @@ import { useMemo } from "react"; import * as THREE from "three"; import { useObject3D } from "./useObject3D"; -import { useResolution } from "./useResolution"; -import { Size } from "../fxs/types"; type MaterialConstructor = new ( - uniformValues: any, - materialParameters: THREE.MaterialParameters + uniformValues?: any, + materialParameters?: THREE.ShaderMaterialParameters ) => M; type GeometryConstructor = new ( width: number, @@ -14,19 +12,15 @@ type GeometryConstructor = new ( ) => THREE.BufferGeometry; export const useScene = ({ - size, material, uniformValues, materialParameters, - fxBlending, geometry = THREE.PlaneGeometry, - geometrySize = { width: 2, height: 2 }, + geometrySize, }: { - size: Size; material: MaterialConstructor; uniformValues?: any; - materialParameters?: THREE.MaterialParameters; - fxBlending?: boolean; + materialParameters?: THREE.ShaderMaterialParameters; geometry?: GeometryConstructor; geometrySize?: { width: number; @@ -36,22 +30,15 @@ export const useScene = ({ const scene = useMemo(() => new THREE.Scene(), []); const _geometry = useMemo( - () => new geometry(geometrySize.width, geometrySize.height), + () => new geometry(geometrySize?.width || 2, geometrySize?.height || 2), [geometry, geometrySize] ); const _material = useMemo( - () => - new material(uniformValues, { - ...materialParameters, - ...(fxBlending !== undefined && { fxBlending }), - }), - [material, uniformValues, materialParameters, fxBlending] + () => new material(uniformValues, materialParameters), + [material, uniformValues, materialParameters] ); - const resolution = useResolution(size); - _material.uniforms.resolution.value.copy(resolution); - useObject3D(scene, _geometry, _material, THREE.Mesh); return { diff --git a/public/stickers/webp/sticker0.webp b/public/stickers/webp/sticker0.webp old mode 100755 new mode 100644 index 44b8492feacddea43f73f35aa9cb721b19a4d5de..ecf35cd494d0a809f85846de5ef2fdce9eee9daf GIT binary patch literal 21246 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 diff --git a/public/stickers/webp/sticker10.webp b/public/stickers/webp/sticker10.webp old mode 100755 new mode 100644 index d4fa65f28bdc862ce66905ba69b8cd479f0b425f..46c14b258cb6ae8c41058e14de27118e0e851bd1 GIT binary patch literal 41998 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 I7#Ze&05wR3+yDRo literal 53594 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 c2$3r}#9SsAz^7WTux>ktgV+>8BHA$!o< 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 literal 0 HcmV?d00001 diff --git a/public/stickers/webp/sticker12.webp b/public/stickers/webp/sticker12.webp new file mode 100644 index 0000000000000000000000000000000000000000..8e80e20704f24188de94eb39e5b7996b8166da47 GIT binary patch literal 30790 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 Qsvr_S%YSd1AQHs?0bSiwAOHXW literal 0 HcmV?d00001 diff --git a/public/stickers/webp/sticker13.webp b/public/stickers/webp/sticker13.webp new file mode 100644 index 0000000000000000000000000000000000000000..b5538ba6b91e4687a42abcdeecffb6228ae47b01 GIT binary patch literal 38688 zcmV)MK)AnBNk&E(mjD1)MM6+kP&il$0000S000300RaC209H^qOd^#405AW+e-KrR zg8**hMknz{ZQ1P}01+_(`m1L8H3Lq7mpH#-&<=0#^bOSwKVgxS3EV)EAPL8V>FFB_ zYpRncthqK9lO2*k`T`6R28F4u76vaQAqgZQaVD~DiJt0Y07mO=Iu#Zb;sdq~UR=n| zYPqVh0G=S4(F796To@M5-K0ftf(1)0TqU5mtd?w$6hQT&Yle$9z3*ZDcHR_T`Ttf~ zv+~{)To_ltjkrVTp)hd-wC~{XT2;YV?o8RJ|dWaOy;O z#gM^Wv7d=B`7%+(75J>#pM$u#V?kz@#Ug z##y+-RP7wQf{iTPp{tH&c%)&6xVvkno#76VyW1+Fj*uxXz#%&!&N?n>*5Kly{h}O1)y49$jh7mNX`z*ijfA9C*r{8y< zx(yiB7d7pe_L8r*nVIWmD$KCW?u?e%f(q@dn0;Rzjt*4p8BnVI}kTQ{=$p<-*>YRQqE zOd&doIf@)QW@cuN0zMOnJLYys zF${nm-3ip{A%vr80?g=I1;0$7(f4ZAE;N8%Jb;Rd;!L1i)|IzaP}M4*5#VvrJ%N@P z!13XdVJ64E#!xbjnVQ?zijIuRYPur`xHx9KcM287vQ?{6kvIj8yaNbl2**Y-%HxAW z;OKKgia9Jef}lxy{_3c@1S4SU#rRc``Hfj80|7fm+O1=9L_s5u@wsG`_F0iWF7ux1mc1uOofdu*9ot?;MVVV>hEt~9X4l*nI&zL?_n2ixMTV~n zW?HI4`NZrpEtNs>M(Nm&P?X`u&>51M%brXbGX8JN83w^eW#pFxqnp2Y^o$_h2yM!Z8k;L_tWZ`1uDq< zo4i+r?C)lnhB7X}OxVuxfY=9EhnW_lPjc>?@(vgllvT%DNe+HfKb8_5)C5}yB56=b zy2%t-hePBPy#QCqEqF*?0ukPC2tLra@EV?xd#CobbQ>mU6UnCjDbvNIzj4IJP?Gct z#Il&>2B@hJF(3h?5Qbqt+<1QaV+c!OCT2lGur#VO&|eZups^T+u_)^Gdb`_Q9F2a} zMXWa95A4EaSfbS_zm)0$GiQCb1zpyZ{J}AW8MlPMo0EhafrB3d-%3>pLAlXR1OCI` zI3|DMI3|A`&x3z9{ikQSrfoY;?EA4z(eAidt(*`&3eDg%D3$f6X(F5|z@Rtc<0d6Q ztRWZXUkbijK~OGLY$w2}9|CwPmp_tO#ayUJDdS7#(=S z_w7h<8*<$Yzi5n|?!5=0_|*Ak6FvLz0jIXCn#yVjSy{sLt`*K?U{<+GSW5809CX5QjM+ zd?#_xiF`+ogm${GS37V%<)4WZ80D!kj4;0g#^J4NDWSuzW(@IhDxCZJPO8EHGAEfS zZb*VFRv@Xm`k~97QQgzWxd4xX;2dNsBL`Rw`rxC4h8=rg%8_A+)!R{q6JR7aWtbZO za6>Lf9AR%gsKak>?02*yA&tM#qIpcpEZ{LSGbuW{g#C@GkHhI(FuOK+8`?hBqoHru zFYCTOmi)MjDmtm4++N3CUQkdn2nNPLxF*ap0Qx~+I4mx5k;CEe=nn&8uF0Yc%Inz6 zGo!0d)YuM|rv)Zzby4J$96NDHek8Z!IAc~eEl`qFV6Ri2IoT0$I2;`NMz7cvwvNqU z<5&mQh*h8~EFa6mGSDts!hHfTA1nf$;~H@C)nmQb6t;ogVsCiK?|!08yS*SOV0w^I zkw6L5LT-=HiK0&>bPan<@=B7*?FEy) zngd`r*aFsupB^kO4DFyjbO3i%QPE;ixF{?VHd|?W0*~o=w&X=4wWxh`i1^f&0RXtc zQ|}T7#=REU3rb95cs7z(;H0%#_7X(m4Yz}mVUI;#rrjRhKl;SG+BEKg007BV?)b$a zt2BX3#q{Kycy}QHEEB!pyZnqLrZS9f8TxBj)6j>THAFDF+N$M`Hm3W3kyLJvKKuT# zBdiNu0svY^mAh&&C~XrYfC&o=TUOhyY2jjBYEFBuUAH*5*jS8fnw;LIBO_?F<+yVI zpa(pw^OV>#0~`XLBjJ%iXBt_rr=2%4AVR0De(a5!qH8lua}ewdCtW-MoVUnbl$Bug zYD=!&K`h>N;yQEL9l7?RHbDp%?xM;%b)lH3MLQ$EWoePS6hM#I1Kxdsz@@m+sM9Qs zTxvW)ljbiU*zxEoQhQF?JRU571)|Cwn`b0$X*;egJ5*K(Be-BcmgZJ&tG3nJ8m)U> zx31qdp&QZlv>w}sv)MW zHYK5AjG7XyZB3|}1A!cOYP#W1zFr7G!k;Y16ra4ZOYSkJg4V{O|M=pme`zv3em%5S;01y=_OEzTW zwg%wr`*oyy5^+E`TzEp%N(P}PQ%bg6^kZF?Q2RE@_@L4xyojE7n$0z3snIC zx^QoLJF?euIG*u1d6e8>+%$fwM%7pij_-|^PLeF+q;Pob#G%K-$%V)5IekHw8uW~o zj!OgPeV483$~ypv$&NMn<%=AM1{C_C zXnBZy2;Q!)umh0MNmtRjk2nmMaPwQYoON`Q()F_&wD*YC0h3G$KiP9zHm zwHw4bUMp6DeIltqB$NEE{^#1Trb&wp$zO|vjKrydKzYH_*eYy*JJrfu8BMc!&e~e< zKlRjENe9&CW8^k>j=OGa9G$yMlu?Qx2UT2#2z9E^*RQJ zQ07a1-+&`Gnf+oY%LcIaws#pUH&7=ID_oc)u(7T<)w=!XjW!@9u{9qNd9!kXKPIhQ zBw6J9$!JXs5lMGYj7L%8${Pky7@y9#YIhn5!1M222F(rBAd{|yP~pTqN6DLQKq%Eq zL|TyzYsO2qmxxL-?nW1aHI3dCxTp3J!@)07$K3(za$~1K3_2D36{Qjz@B+ z=pHqEnoTRvxwB2rQ9?0ru7J2C<9eOiVNFx!lAZbRi<6p`WbX@a2}ms>Che3QpgTQ4 z88$i9us%liNECHN^&c_!sF?4NO?;%(3iO02#65sGl{&G;nuheSC4tjhO6&vRYCtUO zDh&~ECj;fWs?*?JL$VH!+TdViN|ZHn5NXy(SU*vDv?v-vkr--497m*!oNxV?LL+ScFdffGD={u7plvAwDdr+fVsrR3|4d7gTih!Osay$vl8W;-`PfqR4NY z$-T8w)^eQ7Jqb@lyKh91CUpuiyP4cD^c8z1A zL}wSS(7Q2XbzA(Hqsvw>~taLMJ@J+emK;-3?VZHJd*b^@GQ z3^}Eh2DmWPXd6VN2Y;vUT#S3q!2D3<;JAx&aag+RpPf#9YLCoO@dpoHpfz(4c{_$U zGOBPyt1)Qdm(PFYBFtde3s6|$C2CRD%7E?Hi@Ahi$v24sGLX@NrIKh7BmwHQS(zG= z)F2jPZU)K88j)5HFSPIMwCEo5fV%56K!?H7=8!4kpkDd6v>4WqSX;U-B6R0-eQMtzrvw~xgI(He|4x)rA zywW;p!nqID2~i$wX{_)yIj%HFE9e(LJ&L?UZACT?SeU#9b3+$yr5}j$64^>|VAzGp zD3fc6rfPwxAx#O`@j&J*s{!*byN#&C{v~K=%u1l^7z{^+Mp`Ux`rQ`@)6N6fLNqnh z-DN`t?MP?0H3UwIVh548A@0t=ZFZclhmB^XMBaF;6_Z5=M3g|#9_>Wx;Q%YVEOCgN zkB*mtNY1oqh}~AFN7$H+gB~{HyCWh;B({VC5hW0QK(n!?nEOs+w^YRHS z3)ct{2{_#qi5MmtNaC=6bo8O+u(_Xh$v~_|-YC=?Hgnlc<_vY;FxfF*6fy}sz=4ny z5SHoC2ls)Y_6f-tn-+*p`z;XfB`s@V4ug@(8S_T2b0fqjP>l6MR1uW>gz|OtTBi^b zeBj=uK*3hPq@GZW{<4cR=8n`p3YO@uY9&X<;1U~N()FPn8H^< zu|_o=^>As`{27ljHch>yih50^BX1;j3cHx9$n!~!wkh*0$+6PPUovcYMBD*)Se;{e zjXh?NEVX_rWOIpI<8fa_94~TQh{c+wxysyb1#^?`b$Q@ZaKvC;*1*^S&0GQ_=H(kQ zZk(vph66#w@$|_0SnYx#I@d0Z29GsJx+&x`PjVSAi%;D=l6ow{{Cu$*X@#JRl#9rI z7=j1tngx6Ki4XXkW`9?R^b#d>=rBm(h0G=ml998BAo3RB1}~Q>93d{Pl?rK;3KK{| z?eM+)pg>^)P1mA}4hLY-sjF5C1be((^nf%G$MgGe_h1<`iTJ_90fv{=Okkl|Rt#R~ zS-d!GL&F}CDX3WsL_-Ht1hq*dm59uK=xLEU8{?2T6>I^FP&2I5uHT|~%qn=CJFRGV z)tdbAu2vopll^cc8btoo!vT@ynRUbjpNMH*mfj4<%)F3!CBNQFL*-S8$c@)0=6FUx z2hr3TnBaW}tk5D|<^DX21d*d2F2f0#ThuM1=C_TQXF-%#f&IcRf_w?2TWes5gDQ27 zZ4HQcFWvY&*s_K_W*BwfuqlKnzO>}I;}8%>v|D3TXyH*+V$|76hUP#wvj< zBFe{%9M61%-@kRm{b|BvKV0aT2#D&T9KL@n_IjEiOxv@=I{zYyHS)eV%sDY<%s9<^ zL+eq5S}@rUcUDJK--PuB6eHHOK=_2rFzIqjz1w%y`~NxvLIO-$9fY zi%W?j+m>)Egf0KSxj+jazTq+RcL3yab|qWW%)C?ZIB9`?U~%CkE!m4cA&PXvg*VhP z?{`%dBH3Zd90HlIW-^(Yhbx+exD zo7vpFO~9>@7K5YF#Ci>YT>WNr6zN3X92AKp&z1m}SIg@nhy-EYWrYQw5v2)4W!Sbj z6;BPpd7y$gB61WVM=v1COj}v>CQivj*0p(8@@fx+!mxv*9P_GeyN135FL6`2v z87le+;wXwE32-H)FL$e%ufs14d{%fKBwI;aeBiJ1DV`bwcq}^=ETKCEL$CD-)e%R! z(dl0QpJFe}%Qu=W!nb0D8QwnPi4tn#EF9Dz$ggapVhP4m4)6@>h#aue(Ivd>FX!b- z32sq>!3w89dID)3JM5zJycz|CmFJ81;~?@@X!tS9O9EmiFX7()fN~y|LYeq~9goH3 zvB9kw+BFP(#0+_fwB%Ggw&+Z;gBHi-;w^t8P9=FZy$t*;=1vDP`$efEowXma$5TV0 zZC5n3vOSb<0F#t+B=(qO_c~-LRG3%Of6L;WX8-;ey8_=nYu7*m{jUIVi*Onw9W6F`l2z9u_iamzGzQJSP^*Nr3 z?&0&49k$51P4NDIXJXw`143Q>_P;YOc|M6^V0TC=NHb+NW1~6^zt-8yop)u(>ESYoWsgXkz!rqHo z!y=1+p9RR~rP7N*U&R#W5yk`u(9>X^=T1RPd@^`fX9^vPo_jh`8D+Whu8xp5-B1+e zFqpo^vr4m@FqtjKuGY!uGMPx;ywf~--9Rc)3ic=lcD^d*94lWMxC#-^wBnn8BjrgP z(}YKm$sL~~Vv?sqk`pkSoSp`fnb=3oH8$|n_qYbjYi%eyy@O2>pKT^nB1L{t0+48G zD4&AlqwpJ7YB!meoAUk&bZvG0jcaJ&X{-lNkmdy9tbCHOMfh{?EKnW@l$i1e@<_{N z4nXryNE?_f&Xoc2)?wpge@eN=mfNu9Gp@xD70)q=+(6fOLInkB0WKdws!#Y2d1o6T z4#?S&&bry;zA|~vwPjx9B&(SVd@n$~(&>q`(qiCEJ#4!v$FSpmiOwv8IFVlf_OTx^ zyPa-;3Ze{bRV<9D5i*C!>u+e1tq~guJH)*TJeLNj?M_0)wy>Av4;n{{!)=s~7V#Qs zAq<#Ve~pkCR6a}|Vv25@k5rY8@94&91dD}J1N4p_Fw<6J=8Go`!Ei4fr^D%cI_qdah$)M*r9`aM|M~_fmt#~30b(c6O!5GYrUe{*ia*+dSfaKazMauh zSgC=6M^V(z@nQaNvrtJ|oqq(moP8A> zj5)i;i;C{E43gK=fXeIAm>bZ)9LoXs2vTB#!?A-EFJHx_5DAhVjwj4!PVoe^bUu|e z*@O3+JDbJ&tUcmqatX}eSDB!()za`YKZBBTQyxN%dT>+=aj12v8j|dQr*EN~LKSDv ziZ`S3c8%HLQD=XQ87RCck-;NK&v+xIJ%SkSiKi?v99Lo3cN$EE^qU+V3+@d}M+5nI z$9_)@9QCj|B7NIHeh1JDr?|UGT*RJa%1pPr7UUs@DjZKcbc;5d)*m_rY(&=f93~Cw zHF8pPi+a8ts*y*K)EwZkoxP3;H=v$ApG+ersvDnMuhgyGfL9X{vG zTc|+XPhm-Ts`}kj>JG>IWPAjarW0u?_;*Cu`T7(@zlE;| zOqrk=R83qzK7t9ym@LB!5L8c`n!tDD@qwgSRt}_U4FXot~}F;PizQwuL(2^4wW89nn(k?SC>J%?A=oaaRp9AVc;c}^gvik;zZ zA%2G+b0*QH5k~(^2DsD_L&UQ!M?7y4XaD{fq4dQCW)@-R`%{p!ymVkzCNJ8W3tam- zUX56XQ9g$Kp~apW3L6pnB-qV}gTp66k(Fwmq9MM9OV~sJ9zl-A8*D&jI$I?D$l>^p z-i5O@Vlp^A6@00c8Xgq=P9(%SPyEWT+K5`jVO!PWiEyBzOx*YuR@@;gW_o6-<8CYN zeZ3dSCySn(fBkAlGHZBRaNji|4qyHmizxUqc|LtnG_-{4n@_En*VShH_E{?B4K;&_JA0f>ryLH zXyUU2(KU2F-yIm^Xoz0x42ma0gSuy8=ir%h#PN?Hjw+xxh)LeI(k7UwRIw+wx<4LJ&=h5kON^Ue_{{^UY5NW0H_+vznfhVXwq#ELb z-&NVrxxD?|uL!JZhz)C9i`<0pg#{H>rsNhI4C&IwU?|Q_sVv05)zv5~`s5*Vca80? zAl;2$PdG8X0zZa?v8Og;g!;ygf?Lqhha*m-sk{kCpUTfXIBv#{qo2q$ftKxQxGf=)|{Em}^KcPANoRP$|t*tF;3~ zC{H8GE5hDTN05vFM%5*I0+F}@G2k05Mj%k2aI?j!j@k{>bf3@_;!(5=?rV92GiDvH_3g>c?35^b%6 zG+R0jigF>+^~zUbs3z25rq3yN4c^g0+*csSLDZtlPCiCqbchCy7W&HHvfSVZsv6TBo-u;c9`D!U@FszuF!zdp0paoIC5i`BT z?`WpX?J%W}WEEQ~!ZYo5mVv`JOrW%+%pC)^LN8IPzW0OoEf1sU9;fPi@I&N7@H_nr z008h=Yf1}}&S=L`;}VEGlQ6Ckq2C!L6_nN_006+92R~5I!Fi(QKGo^b74y<}>8nIc z0+BZt8$eRTEYn_1C4ydv3vs|?7L{+41EUupzEmTk?+072V~|Cc1IMS1(;F^7$*-^m z0{|O$BowqE^t)!FxEa@kFuovh3IMR$_Sf~x!;xS0nG;6iN38y<=*)RJio}n}WZ=7h zsS4RsnbVD@%uqS`Pq8K-(n_S2R^n%xI&6v&XtYTF^BpvAwze^_It2C`PGlHcq@YH4{f{6i(*!D^i#DtIpx+kY$q< zfEJ1=v>Hh-vQ@qI>O6OtZg-dewCmE>5W}CP`eWwW&zb7KW^DYP!TN)Y&+O6HGZPsl zVR`G$i*m5tD`^oK#aRnuLIhyr^#^=iPW3^W3y0!YHqj8{C9Mi~SJ@6z_V6u=zYN)w zsgOBYjd`h=N#7q(p9D*4w{VjLeH3eE4{_p|07AIccO!QSSV*0<)l#$sNut;_Z z9u3ndT=*!*s2;s2p&0WH5vnxPnURy_C2CO#44hqxBJqsc8Hz6b5CN?+D&dX{!d|mP zmawwjW#zlix0~XZMt#S&tFt*zpKq^6B){bI)iNJv(O=o#Kj{_zr(#4Hn+?>lS|A9q zzXA1E5Y+0JY#11NRG)t39?|^m&3X3RZf)9l;IP}mXP+-WtY|g%U(z5bA*zyq)!Tl` z8GJ!SHy1OS2ziML7o62a7Fp8gGIddOcKB?VGnrfqF&c=Aec`2oNrSY8c>dqMs!P0} z=16#as&Eeuv`YX$LCrDZ=es3N$qqM6K3~+J3p;F$=kv9+zOeLw4uI3pG?wXiqS%~RZzPI9ea;h{(3rYjT-j25X0xy;T4me9oei>r%&!k z0DuP#`iA|F0>^Vx1_8zQPLZOKR*X9nvSODmU`x@pwqWiq3~MQ*pEpW&0>JGh^4{i) z!xnU^pe|+C5yBY?pB&t40EmF8+fgc}T2o^7)NiLwJA>O>;^{hC$@USEVC`F;3vXvG zItFitE)#WXOeQ?4F$>?+I`8%ybfCvvl2t-oV|*co-+bz09#^kt@-8}kVzLS*7ginvhC^8et0`JJS?u5KysmDGsdc{3 z==DZQif7;A)dJin@RJ5s7VC8JKk6}}a(dD_1fHU>MFJI?>?N3di>+^Ok{+$#LwH%S z)`qJ9*O;q$W0NB3YC2DWc*OwEr44~#W_5d5$$ILUi58RV^;Yh!rUfibR$hjZIFld@ zU3me2v*paH$Q)L%QBGc+V5SXVG{6hre@bpJo(Gih`7eP*2T?564&fSzFpn*T)*5ss z4scLi>$LzK7T&ZR$sX@ksy=6ZFi9 z>E{-dw>1ha*N{vUj~f%JfnYa?nc{+;?6(L%UB~064uA*29*w9Ta0|Y$F5y^(j~mzx z3acbxp-7wB!)wMDo-+quxlbmF{S8dgF>xGWvQAj?}HkNA0BYB@lBvX{uwj*G#1+HsSFa~pKOEBXfl zV2peGTKj49QFdN$+0Rq8;G*}qiK7RQORZk+Gq+yDF2{#etX)e5oC$RR_m=Y1iL%yy zLGjIvX|0?kIIT6O42P6;^-0UbMfhH`(J*xW(~bVISs3aFRSE1_PMmxa77Ob8W5BG` z6T|Lr)!~-mH(T(k(JLJbqU`*v$Szu=mF$AojRu{_hc`^M4O@8XZv%LCa|Goq<=;d_ z6c3+Gz^k`c`bIPrrT2-=tvCyw!%Z#7+$;WEbbu`WXoZznvHd%$U%Fx**HG!%qiM}B zbXML}v!q!T@HL~;**mBG7iH&XO?Fe?z}J#UVpeI;NyFMg&l~G(ld2v?zTSftOi7f5 zRbir|qC|im1VaVY8q|AN33Y=zrX-kRBjD0xxFO))rc!n3iaEzg2Pwe)Nk?a8+CvOK zW1fp%uT*R`1+WnN0s&LS-mj%xZO=p}4ZlCYfjI2cW$Qf)3KPhhg$Gm+5J>d5lp=Wu zL!8b+ySqz*zm}+38ur|gYct?3-FsP6eTU;6bz5b+R8 z1EO&3o%j0Y5<5ES6dBWEb2=ia`qVP@=<8}|Cx|)#dV@fKA6&mOz?7-!fS=8lGINg# za~Skic@4PtGBT-(BH_ANN6JfexIcV#%!mf8Ugm2uvRgF%V2aHK^2%XhF>2GIiHBxm z8(*Yd%Tftx>Ge==5SFWy9^6wwHc=I}41oZr4Eq(4NDzmmVDAViGw-M{mqN^2p2pQK zs~wUy*Q19mmj<#KZd4nW=g;SEFaMpfx*RUH8wY3Y{hglA+pf(>COk76*tdi&x;z8= zD?C)--3etpSa7$6rV@@fX+g{{Wwz+rn+r#B%QjOswkV*K{W5f zXls3ZtJ&qsLX3z4uJ~XAF_}nM>gBS{;+&V*~pOhf`ES8@n1QrZ5LJa@nubIh%Xoy#M8>$RR36GX9fh@9C;3E_mhbX#Y(IpQx zOlWIqG@=IkWV^t5*@sQ-TdN1`QAW*@Rud&LjJT+XWL@iFLs$7tX20XHKc=ye_*TY~#xg>}rg`Hwe`j)FT_9bm0u z9yU7)8{YIWI2e|65wqd710>x_0!dXxwkki{;oBfQHa-P}X|6uzcu4VZ zHAG5qrxh_oxq?#~jH{n3bVV~k;^uTFMx!f&a`9+M zFlzcRDx1V9p}Lpf<*pJVLQ}vM-%P+1D}t`Uaz;s%gHaKeydxZ6@wq9o6Z}?rK{s{` zy8r~&BQlsFLUN}viV@%ke#{(HRT$oH-sJhDtre!?aXumv)NGtZxvKnzU2e>s)Bd|y zA4@n)sbb}8Q&&-mS&axu@Nh^eewmT(dX?zR@t%)bE>!aL)6>W%MD|c3LAUwam#^G4 zun@ElK9(af1Ix1~8J2dzoZ@#rP8f_W`LxQ{c4gKp9Sc&i@h?)il272P!f28P!$SjE zWJbE$cSa{c)Gn||6c`5sNsYK*hWO-x!+lw4otZwHK~{s;b`{`pj*?WRzDLr=vb&1s znLvm?N75$z949YnBIV+%6$8i0XJez$UmA8@Ig%F)P>{mICQu;sgS3d7NaQ%D52Tex ze~2XkIk8MXsoC@OVMA@u9F%xojPm6k^=<@R8ljv!(ysghfu=~OzY(uKR{UDNb=`hK zobk@;!DozLhOc_GejE(}0rn3I3j@@6J-qR>B>N$;P5^G=V>OFG%Fm|+`8pZWj6JcI3no%{X2_`^;4zR@@o)x)O@$_Uf}vRF1W2???&bASOJHDWGNgZ=QhH6Yij z@lW5`Sg;?ABG|If>mz|R{}ef8U@NxN{Gl=`Xk~^?mJjsB2#Ja||7meTOrUFl!FP4R zyL#>hxyeYZ;S={YIEjirE<(E4ZHZ`jWOIZTw>aU zt@F4I71CoVu#sd>2I`X*War72=NfbGVTIAR{b){Y55Vb&dyZnR}z-9%e>dW*wQZixB8xdQ zeI<5S_3?YUA|La_i7?tpmGIKdi^d*M>B`AgESh*QXA_d(EM@<4c@*a`iJ6`Ku;>Rq z{IY0};A?Ww?7to&`OvFi_hJd_GE(XCS-^FHz$sIil6~{KJA%wqWmC8?zqdsdfGwBl zx%O8i{*Umm1=(eJ5KPf2NE2Bxtt?p07E)u&W^;H_s7PRR0e!l%Dri^6>pdtiyvboy zrrI{k^MHj@TEJPjcB|7}R=!htLSaf_hZKnyy^p(~Z7MF6BH@2#CpG0OFHb!pykNpDlY`B(e?lZx zmv+}J};~ zo=KXWAjjn0iA@y=RJJNv(CgPVkr09Ldh)`i}VHTX9s353C3&m_K&a=v^NK7VTq9U9)+y0wA zn~M6T@RJ55ZEa9-dRY#@!6k_8uylABiWR;jdpLkeN5IvQMdXOXkL!|^2@XYQmO#aY z*Nw!Iu_C8H3`cPb6w`Vs@zU?-SG`!`c8xW9#_z@)`*NvVZ#6wp5JXp8MmV?_5uu7i zr%#r7JG<(|lDAYvw*2zTedKOtqF_Z8Q4o5i;wU@cLLwmvtX?>W9z1$R8OcFrQ1D>0 zdnN-6Lgkp4&<7>mDl7kK-IBAyx!O^>r4yuAf}X z*;V}xGKLtw$87c#Wk_t&Y+}=Cdw4xPX&fHb}Bjyl26C@ z9f1a&x-g50Sm9-Jyd5B`45qD>VZnW87_TQU-Vrip<>KV!ci0?Hr2lGABn(<(t83Hq z^~{9vv?+-K+1XxAq+P=;QU@Suh>yo}^U2nd^_=n+Q=%uT%BXEDBIk zxaW?Z+7j@1UJ-}k9j3^Nr}*o3W0;nREz@}HG)v?hFqB)Ttj?NCG>YQfzVd$0FF~O*dIdgB=S5SfaLBRD+(h}7!0@uM9kD3# zYGQS;f;cbv?Y`@=(u)h2gze`zc_}f6<*i*JOCq6Rv}Ja!zMh$Azdl*Zq-N4OEY`6r zUaBut_p-gTDq>sR?hY}0^Hp8n1O+C#2CNJCn^Y9?`ebQZdT?+;BJtAIlfY-PCRU?E zh_JUDv;0d&4)KLuO9*)>gQGm40`Z1kVy)zL!G@W@G&PyZZ>HSjBKJh=B|da-ANc3t_Qd>Fyghb~%3 z4F0XJ^sQX{9Jv@R3^0T{6!!3cc$*!s$k%pHuwT zB_4To@JNA%ARF((*T|^!@^+f;6#{}Tv(wx2Lv-U)D-Nf`een^^?$B&L17>v zs`Azgi-3jJSlI}@Gx|fVK5^F{X0Nzj6_8xX1XFJ=yY)yN#g9JR+muiBiU1&^&+nyF=zXUvko39DV=qmu6{~%;k=~9 zqgEikAr>pz`-wPTM2wA3gpjQ9 zEeXJHdx2}aq#CsNJqnNhuuly(KWg5EEUFJLG(^OeSb8sF=GxCLcNK+aDF&?D|IB)3 zBC3N4s>n8FKrgkgJYu$}!AEWUMCxAOLs)7DgqY5b@*q#>U08~ zo5WhR7hHxo|BMd5SaU+iEy2W)ZX)gtcLq*y)e7Eyl^hBC<=p&-`o0ELX>&HG- zDi!C$K|WD3R*JcJP~za{BTfmGPDk5SsPsADCMuneFYfq>v1Qe~veZdPwr28kvKSEo|ow<6TsOSzo~!>f5J#PlP=(Zmx8>VGoyJLOOqRQ$+w ztu&FLzdA!j$N;$altT7#8`3Bt0evCU0xF%X3D)E^ophZjgapV*AZt<9=Bb_GJ^Ez$IPxt3Lq_aEZeR(dOwFf4C6>bUf=K(SpzJCuBTSu!{yYyt#@*g92wz z>-2k~H91jFX6a~E;8V`WwyRTay(>K&5EKxSsA)2|pLRYjc@QgtInSPbRjJsk-9sfG z367OPMnty%dic5+t1!=sHY6yWb)z|7F^nbp?r<_O zDYKls_PN7kLh?ckzw>_I#K}EpuJb3e-A}UGLE%#}xgjMw!@~w)I|HOL{+|o6(6~$d zCBDi}oGl6PZazRtkioaWM@@pkRG!2?)Sv_3y@{h^XFGZ;qUaCC!&|D_KqIbALQPj}S6y zCJPz>o<5ODVOF|A-MywjTf%20{;H7+-`3=gU~%GzLq$lSC1l)=@Z1>fSG~F8*c%jJ zBjS4$9CV&!*JsWqWZXD7wiF#}Zo>m-q!6XQp?1JkHx;aId7!9(BNa*sRj^)b?(Qg|QfhY!cBn1ZKIoB=iz=Eexg39HzKosPOs$iI(OQ`Dk$ z@IRQv6YBaubK*6?6hdt4hvn?DAE$IqiOEFEs~IXYI(&>ILy$G_`yiVr73)P(Nr|*u z8<_}~8y?W-P&afCWn<4pX8t!gm}#>s^$5@heFQTjsVX+MHdH1Y-|Yo_T+e6 zj23QRl4&F4zrj5R>lnW>_5-C^gjAbXr031+=^$?a+$4)G){RsY@&0d0$Zuoby=ByK zn`~i4hSY&y2!Ldwi{eOG)n(?N1&}};YwDSaEd__XkC^@VRZl_sbzx|#{+S@b*9Ft@ zeynWIAegc^OsILEgC&Oeyv=I%EPQH&qUoPqy=kY(T zTrO1I^jt*?!_3`gJZ%m(EZtqqqR6dloi4;FoB1RE!=NG=IS!sBdp)DrYC7I~(aR6Cz zx$5eXGh&Dq0W1fTBn6~B)hLJc+KV4la-lbgHZ9CYsh@fdD2OT&a;QB zvCpH6s>1#noy6uY**-=KWj!Y*cG@1GLBf1&OGSLFD)lX@ufYh!pUC;n?^lB!eJoF8 z|Gz||9wRvD;<5(9M||eQ{;aTy^SPpo57{Y%1{>~^qryFEC`8!9y5cx`U0^kWyQU(u z`i8~(hZ;f>!}9jpqQ9~xP7Z^grCu*~UHTenS3(jJMdau!O3*iaIvnq?cHNo+09M(q zaMu_1tAY;Q5yRb9ZwgEy#LjoQtIBvzaN^hq18h{uDVRdl1zo=2j%@Hf7WP6EIe$1qCjqVDVF?gYkq!NN@}F+o_iln>gtk*}*+tLOKrgDneOKx;k>+od65; zy||dgf;o|d+e{2)0Bf@;oMBy{Lxhh9qlQxoE%n8XV^1=9mq_ zbX3;}aHDJTtt(#Rc-Y`KB13OIjj7-o0)-Bl&6y4;wC)0{sZ_>c5WQ zka~~#ZY^h4#!MQ=ibtJd8HU8{g@;B)v03LGuuG}s(ghmQ`{|-rn*!iopI;3&V;kwb<$c@cszIr2N zi(-6mi+>e}BTe{38pYxF9XicmOu89^-DyJHA2#;Cva!c936|(cB-XrYJ$#T+=us=izrJe-iEP!3cB@lP8jaB{SmN!3 zjK*~s)pcG8?nUr^(lrtV)+UwsrH4;GUA73|Q%)f6lK(T54(7qSU;H9@m#iqtzv+fV z{>MWVOzSxWeAM7QGcP*XG%t#-&e*g)?^&`&l7dNuFa z;s55jVy}~WcxsAYkwv?6@(JUJyQJCJ=0Yq|4S9Y~3t@-eGY(peo``xVMm;NuzmhA_ zeKXdxq^|PN;Shc#(x%}RQ@@>hrDGE(KSBKoYu6=Y3OxJUs#GNKKjI-`LZ1DS%cVZj z@N6n1WsK)c2QqI8IYb$lC|F-s_OZdZaU>_KU|%4Gb&z*vr@bLMb21z=2Ms}2kCc&; zKqQ{7`k9TkmC;rH+1CaelL!eeqP~;15jnhV%yII98gcd(rYBlh1gWcC@Ji0dF34NW`|ip6*KvnqAc2@ezm?EnZtHiq8V^R<|> z2`Pn(VgdMu%E+05G-+%Ne8$@!$K#;c?RUAlZn`>uO9j>vi`@f4BrV2JuUTiAq8C9m08AAk}w?? z_9=!KR zEl}wA78r`x&&a!WJci~E|FHQZkFv0ePG;GT{`&%kGs4hAH2&-l!LUhO>t_S|b0MUW zsn`y%4xPhq2)$H95&g6oOTV5=!%5>X6d8c7K1Re%Po`oPR?=}g@)^JbHwJWR4+g+1 zi+gfiJ$N)m8Bqn+4xuWi?%!n96zihn9wk^d>#Bp&1X@g>TdV7rRm@tk5ST)2ZkgCz z*;vBi=ZxOu3@T$Ty~A~p$)IIp5H|Rn7~9h~pvW+0*;=M+MbLFHc-?{^7`{>Hsei-^eH_tgvlay6SM7bko<_u-io|CngTZ z4IV3o$S`alpa*wXkV4e~(#c_P=i{&2wW7kvgN)3etfv}zweZyFg7qhGxROYaHCvpB zHzaUYvt#+efE=PSyazs}yoS}KG3bmplS6vE7#393+1e?~?~qJXU97WD%>1Ihp$WH{ zz~wvbZ>U8cBJ+UEg1^Dq6t$}dXd!$zs?Oe~F0I2NK{p+iw=^&$I93CrksJ+A1gPp# z1*jDe2;1S+8SsQqBtvi=mhsVnGmzhxcL)pJ)OkB01#ovP1P9MZr0M|1%Bl5fo^fT@nRDhS^lY z!2z)|;ee1Os0S|ao>5u1C(wX3%-MvDhkFVu%rAKGj7Jo2tsYQ@cj{A&m1oU)mvdh} z3ew|FV-OYlCF9xae&+W&Lc%iPPN*IMiFlZP!wVwBOU`=mZsKS`MVI?3YSpFiC`l6d z(GQFLK^hg1I4F2eF}APrg5Vx2j7HEcT&i%$zmYHVc82B%oHJZQ$J|Hg)$9lkKv8EX z)J%pPJSLrePB|0ujhAO};&SPnM3QjJXvw%X-F$t_ldN7%k7Di42UPt16`ILVh}Czs z{8RJ)iCzIx_;TlejOMe`9(ig{fQLv9PVgfAXLQ`L1C0w#G(p57^mSL~DDw2Vf?j!v zoDGr)$wo8IXiVsCHnu5o%h;a+W!zQ`CqTd03;_K7#p#-9&=k+V);MWu{yt@S9g>C0 zvm9-f=H)7KB_Xzp5M`V?+lg^RJVF4SATm!g4QyDN`(-Q&TkH@^^h(V=lXo;hxIPbc zkOVvUCU_W_5yMP0L9nlB7!jXQ0h3S^dZ`|dtl%v|4P9I=C(eHOTBMON2}&8a&c@*| z*eCuwAg^Vq-37oWh;RtRtUz(3 zCLY>C7PB}$y1Gw6h%X>(zcHCWR~+fmZx@J6Y8$v$U%>+`j>G^6bVIdS%*SM($+!gYE)_XYl<*;wRHWL&(>7Ytj1SXhMnf*Hdnr=qJ* z44pX5crm8SC3lisL;@IyO(Fxe@yos4$wL7m7C?xB& zIChp%#Kvsqu+|n)h7qDnkU=Phc+OZG@g>F2V(c=TA)W-Y%{B_&Ct^iIZT#>j%zlOM z#xR!m{|Nl~$ULmdbMs3 zrck#B31uuD;7q-glYej#)HKmDJTs?a7^ zp4z|W1pTeu*k8Ash6)k&&Z3B7QB~10WHA=Wm%xDXt%9w0dg$Vk4@@1d^+70zkYHGS znf5MnwEA-My1PCqGZo`#r0RbWdzo0{+vH9V2O_Njw9h6yJUgPm5N?w_N_hDHVr*sCrWs_6d7Hu*<2Ia9>EkOvKEGPPvJ)(YsXhWCg2h7}U3uG|-xOPNu`%qZ~e5 z;kkV(ypjC;9Rv8G(>0Td32xNzg$zFgO0$SRdB(rTubR%9mAPkNAw~s3*k3AOM`%KogBtiBm{_b6*e&LIK3zmqh>_@pS=;^+Z)FA)|H! z15Xp~ryM!Vfj>IHnPr)JBBgMJhW=Lvb-RP1O2J-Z$hQN&ajc-b437KlbkT!HC6p0m zVfC2os1O=!`k?5AW7R`)r0noKbT))1smdqd%jy4`9O5uK6Z(ARWrPe%g1bdNLg-I< zmvG&$b{H`cOP@;iS4e*-AdKyxHnT*o_&O=-;}FC5Vv6G|PC9hRPkBgSIJ0k{a77YM z89v@oK&}u54?6)uymA;L5q6WEH{4yy!Q&ijtBlthI`erTdGo{H-yf0$BGUgU1>u53 zp6DT;sS=uaq7>|269P`>od>|Zp}aXZs2a;e#4FfDr0IsCFKcfzh{ zy7u-Eo9GjGG2ayKIpi>j4-gDVP6eSUmgcT)_fSVLrBym@4JOc)7u!8j99iY3<`k8} zS3WelhfY$QlKIA7Av|Nc#{h(+afJB2wf`i|!YLxeZe@I$)M>F{)YiZ0ibNu2v|)+Y zJO~kV7KP4I0&SKfovgJnw@;A|Tpk~H?h(r?a7j_N$7lh`TKLmKUhJXd(NZ%1& z4>+PIE?-tg_0A4b;7uYpM+N>k#9pbmasQzl*_~f4Km&rJkBNi@`jCO?rJt!E68jqj z6sX9wmQ$;IWOp6_(2(FXRq{)r*CNVk%!@<|R)O)gQyhC!~jSN zNL<^H1W7eh^8CN>5fch=9IBpPc6746o^PqhJv|^Cut5iAU{b;c{wKwW#D0R?WM(F> z^=vJxmC!1nS2}Jsx(P9SOqj)u4OF}$2`7eJ=DK{>yRzU=R1=MPFS{7sDJzinie=<{ z>#%Wxg6hWj2qnT@dfGy2$I=I2^kl0AvWQ+BZpo#~rr!CHGER5?QAEY$gpD|!5X0Zl zPZ%?)-Zg925F83>4z!KWvms%yA`-iVTgJ0rd2-B%M2}(I=eJ-B(}qnnMDc=OMX=`y zI3i%i!kimoc02SE;Wij|LXnHeZwvzxr~#tyOks2svWIB1JfE@gyDEpNfWN9%LK&m5 zwrYVGE$scB?zBA^ne1k)BFV;*9T-r5tbjOfG5U7 zGFFbc1cc-AvI0sTAepHK@aT1ckG#0R`kNw~f`=RWK+uGM@rPA&inWuNOeA&>6*mnr z{Nzl98_K+oXDMm=h1!SD=NB+%WW} z9z7ezY!v4ikdQ7)+mKnfWErRvJ?NDPdEXv#HQqWR%O+v}eI>)6AjGR*OK>Qx{r8B? z`4UB*6|5Fgt)0)$kwJinK?kYpdn6|rOt({9b)`TuQ6u!!=I~D~kF|PaTXWd?uJ>idpX`C6 zi9O=^W)qu{CH68KZBQkL*NjhMlLfCDz11{>is=VLak1oWtNA5wwCCAqL#AD8-gG{1 zdytjm7-_^9Q?o7LA&`q7u{7?+dlhsXOxqLTQ769(L*bH;&eRH=^<$!#Ssa=VBa=jQ z^)Zt0qUO4IVnAUGhs$~)UGFN*CqI1oZhM)Q#^XU1<={LcUp>F4wRbC{+G%r~khVyq z&}wdJu4g8+_PiV#70Jx@mhcfetaw1d6kte)iFsT-R8}clFm}3nZe(k0&Vx{*&@5o` zG~riKj~I>5%LQyiwgvd2Mj)pmkECt`k`Q~qPr%Hb!eSlTBbM*DH44=|KK~G2yLWYW zj@D+g<+xQ6S*o)mBq;CO9$PIeyWCcLDX}0r7}qD{bd9Fpd%twHd`8fT4ym@zZy?tNy|$nf1KBwj``*BM9rSziqf- zLUpga$Y(xOo2B`BD+jD`vI;4OMKF!+7A$q%?KkMcBHmM55>~K;s>mTwMSPmix5q7q zD!QyGNJw&{-Xp~%`C@Mjo*t1c7wb6Q!({uOe4oNPr-G4yN#a&^Sd}MR9Z*5!;8|mk zEJWVU*}*9znS;{YTo@=OMhmSId!^%ldV3puf@b5JhCME#0Gn=lsQPX6S^mk%E#Pmi zF(QDL9mvI%)={F>birHx(K*kb+pkZ)!V8Qvm8!^^xAOTu%6dIw`A?swctt=3d42g# zO5tn9@;uV;_E``j%EB5jS#-om(pCZQK5wn7WV3=F32u!juMmS~^{le6egw{U_RCrw z3@#5&6s&6QLZX%IvLB~A?R3CxdVi+_BBmu4Bjs?kWJ~S3kfZu>R7Li_yqZa)DpF)o ztRjSB$E3tHOQ$=QW>y1rV;EoH@&3>XS9tXls8c2;gN#)b{#Ody_*x(c08HBt} z|Br-gdouBqGkRfUROuf}0kW7kfb#LDGCJ)nX-}>UmpaD0qIk$Ccy9cuh-K(6Hf9o% z1Wy*o8j^ioWu}{5i02Ss4mp(0U?SejhC{6cgGV`V#8mcLw@u}fd?43CbO9&~BxGti zV&|o-4X6H<#!MTzu^B9wjrvT9armxIsOHLADCpHIYaXd^x1WvU5bs^GCj+4Tdj#JQ zr)7lDO&cMpXO+XKqpudjJoQabG7twTtq5=*$c1d;$GD~r6N>Wsv#>dw5Pvcd0wvKK z1R@W7-#6C91l4dA2SLr`*l?6 z*v658;&Ff7?XU{Ngn-=-PT}8ooQPSbAKYiKvraCphYi&clPYb>eNbdb!g&uWZmhJ{6m##=T;PDZm z6sa9>Jkw%Cq&$I0M82~Waj0h1)%e5k!yIWM=AL3m_{EV!&JgV7JJv%yz67{0>BFtlpJd zmRe3-y50dNN*&sL)Z7lGe0+gEJ0aKXO!&MhI<|Gl_aMk7vf-@{2;tcW&CMEgjBr<= z&_%9^f4z8Yz zCLZcWAF!vDNM7q)`BbJhug|46sCvnbAvKw!tKJ{1wte(!o-S4IhsX3z$~00U{gm&R z1Fn9qvy`1$nr=){L==l2AiVY{-8&W$TR2^4L!~&1cv$QP(75ESP2$j%4U;5Fy2_vR z3SeWz(|eDCLkS-*;A^7eQShQZK&6h2YtE|FMCCokGXX2uLJ`Y=dfav*E*3Wf6!E1H z*+`jN)g`Q8zmm>u8q|33fOL*1fQL;s1X-$)hr#@_WU=@#HB4L8D^A2ys?I@C1vg&` zk%A0~k}mh3!+9qVKP7%psbwY=W6?cSZ==R^Bv zeCtdpM2i@>rAqzpHyPeNA(_UOGpn>dBB^X~j%lstmqwM8cobH?j}M)hv2oluhmf!y zRsI}9F>%nY*!8)v{Ish9iX}}!!;=8wiUJ`9BuX}Y2Tb$aQg|0^y&vzWB8DjM3l{eW zp%y59=GEgxodwu6JDeKCnx;G8j4WlGMUsgX9{lc5pgDjLRe76*xw4Jst_q2pTLtb0 z_zM-XbWHyGkWZxXZ@Mx~D7Z49fuW#yOz<$+Ij07}?h27SMdH?n%RvcJF#VU{dgq#V zP==m-PUfGL#S2j!%L{L&B9W*RU-n*;1cQ%M+<}KuM%a7cux&1!XuV)58?SeApA_%0 zZ)cbfYQuy?k&^DaK^tBPGss6y95k=H(`s({Pxk6ylXa-ablM&K;BoYm8qd6n26B@Gol%V zIy1qPf4v=ZX%nsq3N_NEMU$bkPnV#|c_A+$Wf^UkXB;C}{n|*4fW%iJp^R0tqcG0Z zClhtt9)=h`wY>xp5`>pbqk-cf6GMRspP)96Q0eS?DoWaF&R8}q7n39jSO#g4o%IlO z3Ctp8Wpufwh4>C&TLd_nGTdnMaXm$X6%b>b=#(zE6>ETjKV5FC6#sBaxjLER7F_>?#)U7zi`ldu!Oinipee1*3;Hzcu;C)5BRiewt zsrZhY&~zLj+HE&IpyD?Z&eSU%*LTvs6A4L8HqUYLBDy#hxQed#W!~<`#1(W4l>`Sf zPpPpHB}mO7WcVtW+xLj2-ZJ+=KKKv9CsK-kwtom(djA7Mv2g_;$*RQUogdbkr)Y>v ztGX1m?LZ=9^8e=qdI_LmYJ8O+U!kJf#l^kbtY}>=Ca$3KZhxX;-_%VTHj(_2Ve7y? zM3q6)eDxMk$yiqtk;vL%Lc!IKv9>LB*cd3u+$5Mn$b>R}NMOmS9(AM8fH7K_S{?tH{j`zLmkjL8?2DT)DWd83>Fa_e2-9*Jodbit8NTR!T$>%E}z|2d^(r@P_iCPkA zX}sA+UtR6LFjhRagz|u*5ZEFtI4&X#Z!Dio0><3oK4~sevxQ_nO-bsNjuq$ zJSuK5JQPs85z(|!MSDR+v3N7(Ad!1z9fXOF1Cpy-F-Ms@Ks!ia27}p`NRAc$vnx>H z5}oLE@{kN500Y7j57)KYOg|z1D*Y85dqrFo5l{!_I)CCdIeu(y84F+61P4PXhZTKz zTr@Slh-lQSdF;n=4$}xNbi*L5hACC}*5aC?#v{FmN=M8tH~7ON4d=LZlWS z$ixb8J#G~$%x>IW{!_PL$s`8iCfkU%%QIiH4O?8y$oaf&HOJ6rt%R*LgCxO|0UF|q zuUPH|Wv%;o)_x#}Btwve$CQ4NOO4bw1-F;9M!3XO7DalMEx+{6gygu(Pexz@`_Lnn zFS?SlRLYiZ>+8JRU+yzk!TdO6KonPstZHqtpAe!=ez$8g)PW5MOTV0#Y@36vT;t(_ z;*W%8ou8kRm8cM_!!$e;rSH~2Q+xy`i(`(UlkWAcqk@yE#7@O0G0+tT?>PmMvamit zbUG_K7_dW(*sienwaG;iNViZ)<|^?R;$vH}Tq-x)!JF?@XwcVoYep{MYck{<;!!mj z+8N8R#W36>%G)T^#Ull6c2g13$XkraFcZ=$a#DOG(KF%cJVTO?wNg!Q9Qw~Lsj+gO zK5^HyGr>$DB(*xk@IL{awFi@El0BIQotTdarSW^i>xOT?HaQu@DVVvC^+FcDtwmI! zD9Xu^lKL^xGG??`Er!+{+~9d*`igkJ7i+S~eHXUXGkz~H)n3I-d>FQ)l*aWY`P}CNvO)1vKY|E}A(%m{ z03CFhJ%mY~+miW;v2cVBVf)pmc%&#(lOO8!=XuW#Ms|f|9#_w|Q8m_n%JMv4V}5U| zpP*KF(XbAeT3BAqbPpH5v#%sMLITuY6RXT$;n*vfVtXt+OTM_n+T#1cUPNY^IVt0$ z2Y;ieAS%M#-2%IxxkOJia;4&>mpNvPH12=@z0T@+`|y%Gl*hm2inx}2OqSwLTj5{? zaj-^xC+Vd`l4KL#3H-g2aam)ukm5wl(cW!7(K>PaztnVi%a`LT+4EP2n}(m`e zSv7K$*QFMf_%l5G!s^M(I&?v$MhgcP=r&Lp!80i#i7i}`3y39$y{SVnr7uw-r*n_g zSc>KR-#lViZJ#z{!g7=hnJ?2dc-+V^VL>W<33sxak1Zn+-%)Xq0QZnV%iP4Hq0VHOj%>@P^6IQ=89ej3`5ccD%O6 z!-s}_uD*l9{|pi*qAyR)uAXX>YMjZTy2oEz*I;=CH6?HybFTJPsQg5EW$1@p@?3+i z;}Y6-3G8^Z5K%Iq5HN8z#k>x?1tQwXXcrneu7ZPR306aO-7P{1#F4FN>k0=$dxa)$ z*>QWQFLK*6rNzdnsLdyp$fB~H_L`x(7nZjd5h1};i7e<#XbEm2CC$#u;G2$ZuW}HR z%hav7z*@BFDD)Fl;xdd|j*fo~Ib!tDu^aQ0qk6<4d9SF01lxeT1fuI&pf7R6^r)p* z5j}WIh_mvveo^;OQD6uq$O#j-{Gy?{=QDb%u?XqnauO30b8NCD%4K^s=KOYR(?ueM zo2f7bm>Zw4uB6vuZ>n8%_~wF4YI5}Mqo9)zH6VS_A<`q%5U2$CqZ<=K3O{`a-#}28 z94NuP6m;RN__iZ0bX`|7L|o`_3E}}4ylS+VSr?g&D!VsROHY(!rbHI|)Dp9&$i)$wHhsy%nFwD9BJngXE#493J#XD;Y>D(Y<`~09z|KgoEWL^w&fmM%`MA$y^)|NO*^u z?xrKjF6-e;$k%VV1d&t_r4kw--XkHyOE%ZErBQp>$EXw zZ1PBus(Hr;15P=MkksUiuhBDk$LMzRaTt!VLQwY+QQC!E$e?KDWZH#XNZLd-^*uxj z^^KUGkWw+^b6|Q;WbJrH@F+>eayFj&!I_b$%lHw@@EU0=<>;Z)MCXXP5hQIF1}_k` zpX|~lxi0&UlL%j`HDPDUN@TeO&)H01n6wDPG`lR8UuQCzex1c4^*xxUOquw#^c!g? zw>y|K%7Vv6Ow?5eBZnb69GDGsNok96hGGI1KrNu2x*r;)M76OdmE>$C8e>1?UFoeP zP@m|X!TQs2bJ!~tSH#ucqQ;>-LhJk9oY!RfNy4oZ06bA(y3}rk%RRshiXnQUOX>x!SMks}`;_xH6bcycxif$0>H~l1}D#Y;r%^I=UAZ|CEkonm25w5R6I~G;h z2sYJzi>E?N4=RJ7w=_G6Ke~1UZYgUvnNkApThUotm}NykGC%C@>Ra=7u1K@i?MSr2 zhAtel=8$v#8aJ`Y@@mE!pZ1;bX8xY1wa*`~^yw36dG`nFYmyj!hYF_ziVZrU5D>hp zht1YSv{Ix`kj~LjWv^hYS#hW$)oy8>bL>(uZIq)XC-s`m&BixFVnq;7b|8-0vE;Ry zjcv@?f8)GV(@~Uzuh5{nF2M!ODq4P-1^5=>#EeB@TQ8=dWTxYLa;@QU^i^KSTem0G z`O4`2@zNm*Fe@)Luf4=P=jrnsrAc7SIu=9~(Mom`Pl?^ni&X-5>k7-)h*5qk9{Yq~ z&eJyJf=bFxSv9;UVvkr+qvTjD~fBdyedQ7i);-J){r%x-@e1Zx0qwFARx_enE} zm%qb`R)!b{Q&B9uV)(s{i4}pGEuTSqgF8OdC*c23H5MDA;hBv}qSKIP-GdNO5jKuY z5$h1DtSZ}QPbZuGcW37-BW0zf^l^K>CkWKLt}p;bEmRv~__H6qZZC)|4R8)o`1D(; zYm*aE?2Xj}KAF>EXv~1%(MjB-By9`sC1@&3552Tag27@k5LN;tGfL})$Le`J9?41_ zFTW+Uf)0c%jKElK#&8hcOmk#S_t=*`iJEh; zY`0O>!U5NgsKbnn--#FnW7aBlunXAx={GNX;eb(=M$D{~^?FJRLsV8kOWE_uHvpCf zloBmIu!|z;_e)XV;~F+!7D(+xq^+8mH{H)ij1i&GMhQ-Vp6G=%}yIHnRfbBcw)+7?Kw#5twj4V%tz*l>UQrs0y4aOzU;)DXk> zw3=IXxvMUh%87!>5w{TzM~sLBaqRPMHNW)KGZU(8oIvd(4S=8W$Vj)Pg#Pu5=q_d@ zimR|Cl#7{>lEQ-NEX)aI43uvks3NLB*G=*-lrdOoct&&&febLdhF~Ty+sH@Obhg8{ zMH3H$VzYr@imTJ9Z+kw1Fs*0e{y%*U-k6<-hiWDR{KmH-Z===BMp8#$bR1%oQjT4i z!xo~#v&-KIa)`8SJZ#B7r0aqy#ZR4hSpa_`Ndj=<`hk&pX2Sd$&tS3SZS+?*Rs>ct zF7}<=C0f;khMYl@!JWB?-~`Lg;YqEb0B8B3i&KJfW6eay(-0XSoloj}6I4qgGbm-H z1#2+hSEi(-2cUwe!@zb$1{2oO1#__<>Ewnx5(YXkVp2_YsP1_@je3t;EfOt^ke+SE zF{Nq_nuRuYvpG&)8uuSO9!<7H7A+wdZBbJwz;Atuz?9t2!-^24s;KhP4F;n%Uh)Vx zOq^0&aF}d`)x2On;q-+0%y$Mk%vemPD^7VTa1ROu0CkrvHIKlX9hSHH85_S3wYT}a z?VicIu>rLekryep@AMc^l2sj8E|uf2=cFTw;L~sFmEL-wJFEkM2SGl@6gk@)VrHV9 z{~_TvDZMo$2y{W$?EZ1KDx#Dnd?aG*S5~{+KZ`tG_#j0dxwJuDaqh?aAM;TGYDN!q z;t>*A?Ai>UIl_e2ON&jq2Fqi9@OLvIqBGHCv7kApGIpIGDVKzipQY`6jCYfRMb^~p z%dpusc#L!4=o*0epbrc5bl|XG9zbascBbwmyb!_lhdu)3siHkWm~>-Sc0BZwsS(!K z6uEo{E52&p$mvy{89*pMPcv+7_Dbn*zsvc|uir{rOM6k@;g_0og>S!I+52yPzYoZ~ zcmixkxll=_z|d(2{PKLaU}=xrttx2|O4YP-Ld`;ZEG#E4KLlXi?GSu1)u))Zw_&VY z5K+9~mCKDo(HNG(p7JJ{it2TlmG9ISZWB=$f@YA5L(wfR{TO+-@`!*1`$An{KEHa=PO_W!qY{9kPsXPx$j-*$sd=DFytz4qGgV3Q5LZRfo~ z+vQn{$@M2YnpzKUE;5GKjmGX(X^GVN`Jn~*fMs=m{L!=SvgnG(ycyqiE6T*Er5jb` z>F7|tDFGw4|kd9o%YC8TE01EB0oPx2mv>=M+NJGeYz#H>WO-T1CC z(?vghfOWy1OB-Z8$m&u25nI%g(1_{q{EaTt0kDNq8s!;pWyZgF4v8#Y%4DN_nmm;| zQTA-KNtZl2^dbQ)quX}9(t~oUmioFme4nvg$E+!0)Y5SJyHOyRc*1|&Z4yi-z8qgE zu%as`@l@x?dEnfetg`{Y8;S|VG_qMupHTF`OHL|H`ceSEtLjz$j}OFg6#2;0;g*IQ z&q}c1VOdO+IPEk$lHe1~DQ~vHNB#vqJE`yP^}+xzJAHi3=z>yY3P#tApFRns%w9g_g9csWZ9HSR zV6l-si)KFI=VRf$3NA_pgewtn9N|j6iq&A@Qe>KMqv-tmr%`?S2O27$``~$x zb-Q&#?e>=2LB8n@`Au*6MIOUrBt2o`Wjr%tFxQZna&A&-W)%*Z*@cLGgo2Qzk0J#Y zrU|k=0l=<{$o{SJGD`?$@u{w$Pd`B#B@L4<<20TO@pSh2v2XWrkZ$*J5%>9oh^rps zW&H3%gIg__Tbypl?SDi#>R6k`eknu-1&@Mo9SZ$2U5KT&C{aktdvmaXCj0-R20P1c z9B*9DnOj_Jzb&CO+#|!Wf91L9UM`J)p>XEaBY_{(!IlLwA(vVyAxq@CC8@#0 zQ|Tx}PHOp-u&PT9KyDtPZF<7#S0Oi_284pWMbrV?{Xzhl5nl#74B zsYFzvns;|>zQeC4nD3DCR3=~xot8c-$>@`0bk$82j-Zk&c-LIn5cVhfd-eD462 z$Zqj`+-p#epn`9Ql`VJp-R)^&mZDOTmAfnJ)|3GWdJ!S~s}a@!KeHrVMc6+ChoBp& ziBuUDK7K{t;h9zZ3~WgwsvbryNrMsS#LY%iiER(GfHiiVf~SEjE7_R7=p&?l%f*)E zV50J}>@f)`v@*=PF;7MrUb<6>n8L}>Nr)?UkhKz{ zT!5H>C3$!=sIbyv9M=oo*b7o3q$12jq}=#11(njHh028<4k#B{O^=hjJlG7@;3Og{ zdHl4*4y6Xwj>S|vQfkI9&Bw4Zk~RS35M|@s5zqiuoqADA5u0NkLX;_bmLEhJ^E5q7 zj87RMh2V|gKEzB$x!Hx+!%S$Rax+qy%;AgP4C48m=dG(H;^~>%&+F;Ulsbue5lIUE zk~Xny_Jhc+1`7rd@$?@lWAPzM9SL6otr?l4(6(om0xP1Yxk1<{-8x?!FW0COmBAG4 z3-PJbN=hbBrNk)*Fs7s=`kk<~&j;iPXMo}yKDQOE`tl64(GaDPpn@}CgeiG=jfm%A z?;PO--E~f8D(YEy8U(pEIk)WGMFJSJju8jfh#batTYS?H{E*jy0v3|uP*>uY+1G9-KjbmTPB9@al|M|eHSOpbDPs?S^M6==x);^|W^E`kmgu|Bz zVZd3{W9J++^AaU50Jc{nsDX&lP6jbi4b#%$Q(?v)N>BsB=Lim$@12?Lw>6%5`!rzw zGFcN*tpXWmE5YYcVMY$8zq|(Y>g(#tkizbG$qU)j#HFGRU#_d+u_R9|D1q{t6b_#+ z@ys;ehJKpmI%GE?azx@zlLW&}uE(3IKn90pDW$C$C}b4z)_56;?iw`5Bc(}AaunlV z9~emiA+R3M)c{(O4obiFjA>X*Rs0Gz|NPnx6p#AFfwGo;(~-lC6+*=Rrc=jRzmH=U z$`d4A0juDBg_~8yHbN(6vFxXy4PU#_>Oj1CdHtdwtwb=6JuHPGAIP=?G7j^i;Z}K+ zSH(EuCZ>*(?gqtKULr>>uKsGu(@KQnKzfc@h*t~A6VKxZQt<90Y+l{3p8Xp`7tX3N zsoh||5MyQn4$fi2rlSwV#C2F)k00nHB5VOleYNi00U`cXYiei2r|u60!p3fsPb-gd z4(eq&3K849e3-SkjiAMH&Tv%fUXh>bU^gtyndcH=HskfF3)WCo;3b1N;!tDTWgU6L zlT(R!xx%gy@-763W5iPP@E?^V37d%gmaQAHrZPq*Go(^vzKh5`AdBYB#sjJ`c^fNY zu(5RBq`7PKbk0VISzI`Hv0~tNFE0s*FagT}oN1S-+|Rj#_jLI-xM;$*q8Dtv@G0TIUUz};=B zjvZPgNT-<@H^ak(SaYl8pSp$+m)WS)&YM2nn znj0xcu_=(*FBXd?=|qY6vx18Gmu0r7wa+tpKEt>6q5tt)+NEq?UTqKUgRHzQ*%r_T z<9J<5w^iCd@iRZ*KYYjX@qV*Im;Uq2UuvYx4sH>2hM8e7lv#u*W!D=N2Yg&JTwj$4#RT%rSI&v{7p~{pFVzB`O%=^wB@a1pm zNzOccs%xp{8SZohMfAQ2XfX5MOScLngccQ=;qJ5O8hwK2iZb1li#quPk2hdFf%YSy z&`Jqe((HgtF@{Vq`^=}?wyfF!0FAOkF;Q8UrBz*bI9%J;9zA*|B4PA|FiN71K`>en zy?3KC!stCgWW`!_cBWKE?V>wy+s!-_}u%u-~D~xInQ&}yVrTwyVl9n%gyCaUwdN$AuALZX3TEz<`i^0ik&IEqhHM5fMX zk~;c#NG;Ev#AMkSFdla zgMLc+yoF!S6!Rl#jMh-4$m(2T`N3f_c`N|mtW{&uqEi-_ois)LSZ`NJI17+JRx;0D zR}(iM)@pWM!p9XzUg4h$y5$^A<+cd`62?{;9EeTmpOzLjTp$d_8?>BS)QIQS{yWqRL zkdxm-`8sAChC&q6ep$6i1_~}rwWp6n8twA4U0d&QVnl1d5ps6ZV|j1w-?H*hubg}n z$Cq<^@F_xEV4g(j8SN)!ku>|OH*8-U_kIM6Xfq`6gZxsgeNy7sSjCk!BN_5Cd!(w9 zod+)GJ)1NKwzv&=X1>J3HZJ|?W2@IfkKKyW8(+NjVRJmgOzf^b>K-g4?yl4LeQ*JYMX!?43PQ1mH7(P?SQ+!-VNLdG-fihdFs zftbt{HGI|*jl3M58u)`WpdFQ8=j9^)@Fm_9Y8UFSg504UE(OofL6s%lh?y!pRyx6_+a6eHvI3Nh`PYP z|8YD#s-AAV#ju{yVe}gjKuFGDlyX-9Xl9uZr^71bn zth2jo>r8mC5jZ{xx%-=Kc`aK}q|d7w<^upa*n0ApcI>_TV>Pgrv{(6d$#fvLzH#y3 z!e+q@@4;YupOMylkl4pYN=$Q}KnmxSH?h)u`7D;ahQiQSLc=PB6`RP1)ejFDG>kBf z`K&x>R<4Cd#6XX1Z=_Jdtm;p>nC#)ju^HDkxe50Z!**Pj6fVaB>#9H@A+92$@p`XU zAr*o=0tU@{*1)5Srlv6)K?`YvXtwSfwj2ZTBb&_S38o*UZI7EV8(wBt@?Rx;t9Xn= z9ysUA6%~9gzT1x_)V<%H#rmZN2kkh>oWoFwh~7Eh;=-G|*qw)lF}6xvP}qXXY>7fg zG@l#R&u2aZ^0^5G>47$}(Czz^ylMefW@}2Snvc}@Q6H)D7oJrVls}hZNr{%h3P~}R z$DE>!8!nKv4=cUy?TxYshut42z;-#{$mA+$a9v+D`;vp**aYMsk+V-(dl7Vuylb8KvDr z8Z?ps!-`o0W7?|JD=Xel>;o(INe$$}J|F|v^IdK`@(coGp1bmO?{jb^Bqh`8 z$z%J6FFO~Y3#d4~m$A5G=j*dC|Qe{UbkBN}I8J)-N%ruI(=ZW3=mG}-&1s5jhDE7LV4 zJ8kjN8Bl4(oIpi=zR%52t^|r=p4q)`Twer;dz^GTQWuG1g$&27(Px3ysennhm4YCfEWC5$~o9`g>>bN2Bw2|b?L=t7%k46)v;>lgC1QlNwvQ=yT)iUNdr zjh?vR7$2PnBUS4#zmV@b;c3S@b`<$uu?h^K2lO#Sirn2%0zHO+*ZnWAg&SPNTe+_psd zM1w0!3dLTzF7LqYTvbS|s9aBzLRT7NrMp|6N~)qU?vC@CYqJNhQ;i&)rKtnKems7gy_dZA?ioG8Fpr^9>mL_n@4WAG2IWTCgpXO`Mq=+fA3K zRcgyKMqXiRcGPYp5l_7+r+J%gZ1m#11l^Hv3!JF4wj#V=aVz9qHHjB`_ulzdKub#( z648dVe$V<>I#C&(-&^$UIA<6l)hX6oWq+?wRLo6Uj%)RI(Y7&N#O*OYmwN8W$R;}1 zx`U2>lgHFOpXL7I?$|zU@J_s8iA4BsYp2wv0Wxv7Tc2wJpF-O=gR1ihw7AzbOjl~| zLIWJ2Y$KUl+q1H?>(7I)d@ow(mNNYz5?B1v_Tt%v`<3onN1y73C(SAuFfJbyizq<# zWK!z0k9E-p+ol_2LaoM?vi{L3gapJ|DP0Pm7B6TaMh$cK*uM2^UyKM38aqVAe6^ zSYZ;V`c|7dvYsokTFYzj9^&Dg#IN7FQwNYZIp#rk@x4ySg~0n7(95V==naSXPnnDO z>mV@5S(I$FNk|jFcPVD{!Ls~AnO>f~@dsp)@nU0Mp+r#_hI0aiK8VTCx+25o_iCUU z4OT#_DHR3J$dfT*b*YzeVxttV&G=3^8D@St)_`X{m`(DnI+Q)I4jYH8E8zq3eNsbuLw~0e9 z32j;U#4<5~9-+!#nUTSfhvno1jZ@(!zk-d~TvFInwRVcx-V*mDr!&P}jCC?hJ4c*w z&=|xr`5#DtcEiKHd@h3}Yeve8E@^QC05Nh|t;YnTE9 z?;{Q+EDa74EFYj2wR3$q*c`H?q1*bomAZ0!F{quQHb+Y1Kij=MN&COUb-OuDn2M2sc_|89d*&Y0%IoxkawobbxordYqEIhJ7aW3dmRc+4PIX15cLv(7LX~2jB)CWp1A+ zMHI}FNA(`s83&f9rI%w+dxE>=8G>FtoU<0u4TZ2&B#-QOHCh<26i70V^tKPzwC4`A zm13{@lGbn!PeU5|OI0+4azl>0yQ?1I&KBPDZm5hXGPQfQBs5`u@cj!(E5@{{KHlKG z#ovh^?%#bFC_$*5z9*OCo3r-4`*i&CmiMdQ9~)KEXfw#(7jxQ2P! z|3UGbsCn^nO7VqerbGjLxI3GB^z~-ozmZ-e@=C3i)s z$c59`&QL4UZbniU)~7AfcRJC}$nyNg#mEwp9LwY#@KuQ#JGi(hjB33rd^ruL*wmIh zv|+2<6ZC3CyqWdjuf@2TTN?Tr*VJ{gKaFn~H$OADtYJbemw4Z=3kMKR3TB9`JQr}u zE_62(QaXvg@LA%sMx`WUJLzBXR3{HEKL3WA$|a8n-9ykBga--p1^vu^O5YzQ)w!fb zRm|o>;pkg=!5xpQynS-lnG>nBYbz8LH<*k}84nL$4Z}0?S;XC}o~Zw(&N+Yok}y_Tk`*U=M<$vb4$|H9_j&1)0R- z`8{ru9@HpFxATS2uoeAnZ9Cgf!#zl4NlH~E`X?EW$*0M1AN;#rhhN|4imcky+KIuf z3w{EES!Qt&4B?wrhe-a4AEESe=FpqV3s5e^5 z6R~)kv<*GwOB&?B?9&gFL(hIhVKdjRQ78OTe`A*mdgq++wiT< zpJ<8DUG}q#N?PO<8bVcsf};G0uK{3NBEyH z#!t*5K5Vf+G8rO+z0vIn_iqTbGyE|C>pds4#z*GP2_o#U=E|HOl-UO@Y9UaVR{bO4mTi{f?}+mC>cCF1p-VA{!rO-GAt~e3tKUumm99g>Q?Ww8Go|ueeTwdHJWka4%NARYA0cG`3 z80{kZl*4(LIx!CBRL8@yqI#>rqv==T@SIlT$i%dAkuw2Zi>GqFtXCS8MiJ4%l4YIF z$C%f%`I}k28RM$lSjtj{JJ#o__rmE|foAYWro;{dKzUv)7Yf~0a-ln(_n7I_o;If` zop~%J5l^*Pqaq?0tAd&(qG|ddK@n!R$}*dR2h^nh!NF;mF7He}(LfpHVDUu$)5heL zA>h@j8ZSq79l!0>Z_c9YAQ6XgyBTEL>_FuM<{A#+=Iz+l7iFd=$g$LOTdN7)xB|Gf zlPbDW@uGC=@~8`{foU~8Vrc2>I)GsT6Pa^5t7>JFGj&!=eD?r>gMK&M0c^b;QjEMH z?;9Qd4eZw=N4fatQtUkx3Q9e9--0LI;36~*;0QUlSD4?Dvzln8!*FOPj}(x1kbuDAst$sy?) zOh-HC>sQ_Tj3;AF_)b)}J&*o0a(FftWQ%mf;2xRtG3%h=!W~{@U3BEYPG;qZL1aE!0EW4?KIzp#c?h0{YyNlhsHMV??k*`>*P(~jEm)m zVZZ)P=Ax3%csW(X`usOM)VZRbbBlmp>=~p@!CMHvKIk8sC(zk6l#pmJM1ret0^KVs zL=0#7qsF4%gd{JC4hGs0#*{WDHGh>3zHSfU+4ye$UH!K@LCNKZxkJ4EqXqS%Yjx?N zw}{ygm*;i+VX}JHx89pY$k2&eQI^?ZeVK}2z?yQ>IZpyktUf7?nYeE_4$Y>2z=(r= zzeF4t1%b{&gv~}20-vPtn}U1hK$`}7X$qQL(l9W!*=94S`1uFZ8o(&XsJ(%aC_YT? zJRPp4DAP?BS^aC0W3!CC+t5IShEAHYEfM)HQumbz*ur}@%KVhE-mm6$9=)KG;8E-T z29G-_6u|55!8`bqR7#t2fknd_%DLNZ5`vi(1L>0$ z=QN5%lr;8OVsL_qh7CV=pvswlee_3ef5~*jQd@eFsUK0nvO(TGAWkpBRyKez1Gypb z+op>o6}7J|K83X$13vFF7Rv+U-(Hf;c8})MdO}bT0q2H7&H!hjp4haJDRe3VmMb zCjApwe3A2RaF5Xr!*48_&nE7#9|7T2m{a>O1nwa0{S_X9TRQ{SpQluLS7q(d=MwCq z5Y$I6$(?__R{GGU58~-eo6K|1W7U2o0L*ni1Z0i5$eklf59M(^L#b`blfh*feQ$UJ zNa|06P5=Y@OC6&Y9pbrVT|J##ecx*N=RRO0)*whlwLg&N!`^$dVmDKtNnlM+0RVuiDuDaW+ymfY zQ2}u75Z2udz;rI79&Ob=}MiWK-Q^!w{8M0oJn)$3x0%PE`_2MhfdGT5cP+d#!qyFxt z(z2Z?y!7}0$YGA2KK!nn&1z@H%Wa&lWmN5a&r1Jt%WYK4yxE%DYGu(0}|0R zy<<9}W*vcpH|WZezj;{{*9 zj%%60DLm%?vn@`U%Vm6_+ns#6@GmBHCj98b#IOP*wu6C7>cT`BiBsw$1>#H1(wSNbARiG%2 z{AONMp}hHo;5uWw)hWq%ArdsMZ(@o`Pu~uBkmN?>L6;jvZ@0veO)ekCtmT zOe?BP;yV}9DrS?XTsjOhs1ch_8&F)PD1xHL8q5$6>D3=#6v3{LS~S6XMeq{Ml=8YhG>_Z7+M}uR=|~ENgK``Q*a(!w&K;hApEk zb)w+ryJrJDu;YfI>TyS}KNhmiM;*e>-NQ2^wa{c5%;~w}>54bUB|W40jOo`Q ze#>5-lfMP~*kq!ISD=onnO+_vp)qv;;ABw~~HeoI}M7e9j3 z9DA!n_u? z59q5eE;5c#>JUU&3pSJ-R4NLQ_UMN$v8}A^fD9$3d(#*eSrj^t4J8ZKAn*vmI6A3|%-!A-auF zmpj@8FTg(~yk0V`x}-OefvEG+i7wc*C})|H>~AvJrp!*Xmo3lq5UZ%ToVRaD|N85x zRGYg<5tvt-e?yY4vx0p5r@#jBADe`krx)6e^QdYfz~)UaS?b}j%S)&#d{2FD^fbg^2;wM5IVrO(-D^O zd};-Ew-UQ0!L(CJ5c>2j$2Bquq>?(3~c{+?s1@V-R^8K(p zTq#j$e}Q1yxh%Ga{$P&oFqpc&{-JV&BYHgRjL5rD60z3!V!@b_cD3xXTr!rn&~RRP zkZwRnQXcl**R`>%v;@={M7klJI6~+XkLAI^V_NG%%)hz>1}13)(^vAlRWK<(L}Fte z92T>z9JE+5YOI78R-zsu^FjDy4c@{PmUTJr(tK`1`HU=BW8!TmzIZhwVD2pS>`li& z)_D_ilfznY)=I{0X(_1XFq;vRi6B`xJ{Tk3HNTfuxPtOmv{Y&g+D7KGy}Yx$a;luk znM8ErR$`rHFk#KNmhPOAGPYD<`})4ZXG=iE$OuYgNXFY7g{!2Vh@Qmq86)g@ML7cQ zaW!?0oxn6k`11|Vr>!#agur1Vz6gVC5ZS_0g<)Aa^0@CMe|n;VuFVj$2AH^Pu{ldk z+6d&4>Y)2^upC`8%iAwVLSG1{Ks>I+bNCcvX=R zF^HCsSiLyNeOQ70!V;y(YGe;(2+Ns6+=5KZSp_PCgz#M$>Qr4&qjp|%8f}tnG8!`a zkU2`pL#}dc2#P;_hFn+vB6=;(8}DJI?UQ9#qb$-{75}%aUa@)ctMm zr)mQ=-w#xj#^^3Cr?nd~{IJy)>b~!~2S%gIx4NyZ!g8I5uG^+zq`z8@CVx}221Pgq zaY}RHrLz;z(nan9h<|I`D#e>X1xFA>X)Gwt;K_{MMuDgII(x8H>Uve|$rz~SWGq{K z2U}AVl%#3!rA3BQl7*y2i8xajXT&iQDhEeNF;r@cxFE7lnKJIfWroFcz20lPF zpT9HI6h_wisAn_24PY9b7u+Ny3_k9J31RF$FSL<%SIRtOV1MyawXG-rjUa#p!!oz< z@`z)6xAnHg`4gtruT%K=YXj%RnUEOx%;Ua=-A*!2M-=8O-~GM@AmQ;xP|!o{Np3eZ z-);Wz%k+rQx5RvbXATe<|IAEC1GS(bv64^e7+ex-EF!s~nez9Md^W-#ZRUFGH)_WA z$BkO;vNc#SC0&MTv3SPQ39g%`pg;R<>h+Z@{3D^IFZB#buzP+A55Qm4pR#{0@yC>N z7~|E|BeP=J7*f5x6Qcv;h0*=oicxgr#^B(01`pzL0!f2Fyle6rbj9k$x;AS2`sI`D zz|)!XatcupLsyMNZ*1HAW$gZ#_4zv#1;D^udqC4$NAEJ!QYl*+4KN>mrU3BH7zRHt zat;NskUm>}R^gRMO&U#L<_uK%yFo?;XCkPgY?j=_EvhrBwi^SL!4WR%G%M5*p+KjX zc-1l7G>hZ>J9#`pRJbP31Awk+*E}ButN^di;1L%2Npns}-WR+NHjh$A{zJm<7#jFZ zfq}f>Vv#@YU3{N$P_sa!|R$m=9kyol^N-BbpZY~3!dB4PB;ZI#MYC=FRaOT-h zL*0;@Jg#u}SssWug2GS@W6rG9-)E2w_taE!yb17m`r zCkLrL-e^wO*R7te)a+`uRRksYonIb8YzxlruWUv%iYWeMQp>VIVGAIXCE*WcZiM!f z)-7r+3lN*Y1fFVSai*}C8H6RZqo8um5uKzP7|=?AgP3SodrF5i`$dTpsbV70&UQP- zCg6p^Q5ZZbPaBua@hJLWg>#FBOAtE38~u)c#b1znjw_BYjO;9f2nS?LDhSAUwzv*M zyWEH51bwL^C884KBZzjx=KV^50s9z%4TneSrFhj}swrWu#ph4vKJf&wfyoICy@*l6 zqXS`F)u1gkN}vQ7o#YQyixorz*Nk?-u@9K&7u6lRbpt0#J5OFL^$UxG|D;I=o%&_8!WvaILM%%_C|I%LEbgI zLtri=VIG=nAy?CNaSlW8K3-@fkC;(no@MU>bd-kA-c#xaR;# zPN8+%*i}_)BQaw3PGLGQizA)IB1nKCN}{G#hHU-~12p&AJMGL5i>p+ct35Gt%}Zb9 zdTbO$i2@`=m3q1o$}k=rFe{f6n*fxqbiP!^Zk@ii=QGntKo^Zz9%a@SNq&$;LTu_P zzjKBDko}5#C$6*BSXmLK#jEqtb`$%RZkx@557Jd+NWwdZj=Y{IOqIWOj?^$9eMKtO zCgK3)2bpfLO(8M(1?<-;e4fsLlEBi)`PCFeJSk>|2AEuE9P)3{I?iuUrQN#`4i<%G zK#O;DTp$8YkO7_xj#^5945S38F*=dJF4RG5Co-=L6-uE#Zw3)lxn3l(K&AVXCWz3e zuRu+nJeeS@nV5IA*{d-A6NFo6-oNRv6fN8nVNo{>fzQXE_Ukat_DL@eEiwOFy2`M3 z)3Ki(i2P5#NppSp)tFOS^N5~6A5(_{qbgdmw7ISPuj$&R+B+V}D+-?|3Kp_TT z0`qn%J2aq=dA>{mu(H-|<3#WK)FG8ZV$|tbTZ!R1oAfs^np4$4ZQx2WjEte;Ag zED-AU??j|HZqV0ms1{&Au6?!^&Et~r4!oV$^@p z6@R~hrDvU+Ny;#HdVN#;IYFI9h~#gS8Z2mWvvP?fG441)E$N8`1$*xuR*mT}#7v|w z6_n30f{r!l*Py%FC?~pPUk@7kw%Jf)r|93n3v=;HXj3>Wlehpd7=Li z_7MRItK8G*&TmN;;RezLpUzMKD|>gC#rTDy-XCH|UO*-to&SP8<;#d1nHUWQe>c)16MYlNB;)gXQu`dLVQRbbWxyLAcBY+JbgLd zr;*FGqx?^=JxUtW&KoP}Jsly7lgRC>B0Rj9d`jdr__4Vs7H~h$JC-tc#7CZJz|rvS z5t>?yNog%XGDfyYij)Q-($;RWL!HS{CT00Xix8(bVHrlIps)Pf&4aDIegjshO=RY- zhhXFv3rO6KnEN0FBCC0dgrMD?oF!2FxDbQ!tOqgK!u#aDkU)E{!edjboCJxQKA6Bw zMPOxXi7Ti`TJ&D0BlfN{8kFAhm;M2q?9 z3JkqzI9j9=cbg}K@gFJ%w;Z#{u_<+k`mXX1#A>c_T1fUqIqfK|3IP??HH{pzN(nJb zXMqlE{^kp1VL(+JsV)kWV;$X0>7*7Q2&q-v?jP@D4vRLVJshh`IAf@}aMu;KAhd+h zLEmjv>?OJlq~Xc^kwGyHVPTxb#7?WLEuMtY3WSl5)o$1-(0<^wE-xyUJTlW9k)@i_ znD&&Jo5Y7 zZ$_7pl}C8KWhj;EoFobv#2`JwR_kvYYVIr$5u9;P<#E2GUH4Y>xhlsgC|Z01yiY~)XkY$c&(r8>hPsa9?nsr}T( zr&Hy7ph+emNRVMnn@$)T`5yxB49dsB9B{^%KWan1V=bUUPK4fI?D!+u%9(%$p2@dI zj542mqaSyW$XnG_5_$fl{>~2uuX`U@!#2L9CUVXnRgtzmcA7VBztqa9?VNFlcwGv3 zik3@}F+l>EyRGY$pgLIS&5{B9I=Vg&hNH-HXPYdkj;3Fob&-s;2msKTHqrk9r5JY` z8+71?wx9o!h#>?#fTz4#HM@=!z$$oE?I~=e-B2YNGA?qCoqx>XwnF@+DsUg;IxU&n)E~^&6YrO}YK)DBNi#k@$@=jDh|3 zlQhUiw!j*SF#$*9XJMQWvLC6m&OZ-b3_t@fk(iU`C5g{&E!~WWE;DNki61h(C@95@cs$DcML?jbq)PHjsp0j(YIdVUzL zx{v`{$6}3VHzNW2L^HE_Vm*vur&9>Rcravaq^X4PK^3_a&>+`CcRV7{i7z22_?{b;o9vkeVFD8eibk#$HON{($*X8VbAxCoIXQr@C1>XJaxL&)guUIig?Z}5s6b4@!XPUUk6;V*rg z{6g551@)~RZ^!0s${}xTFhAW;!PA;oBFj1wp#Oe?r05OR&!~L`u;TVD#@|q}^OoyJ zKV3ATGzDbi1y6Z`9~6pAe8-j1j2Z~;gGCA7dp3JLXKBfPAt>@z<*Jec_l@1(`r!8r zXpW9;r5NU?2r;dqXbMOQ(Q{k*=2NBOt(7X$_5f>E#dD6GKA5dSGS1UTV&rskXGq(* zr?}kNaC+wmVV?sJqn2(n<-CQ_#xB==O+j+o{*>|0o!6!vT^IhV=v&tTY zcQiaD8g`h-G)^dRQ&gk$&33Nb0g36PzYqY`RIFUovKhdB%a8Dc$LH3KmomaE+)LU9 z3EBqZc~Ij0qunl~eIoa~w>3yo8c5{;LcIb+@nJ@?JE?SbZV^7A(dAqiAOs|T=>WfM z`U9#tMJ!xDD2T4t!3(+tzoa(XSX1&uypD&(JT!IxYFy$m?R)$6Vj2qpNlke#>2q>? z%SSivf*D0fhr)C-3J!1Wgs^pgSs6Zc05G0F@8IJdvW)d&YjTv0Vv3U^+}(dQs9P?e z2W~#eu*g@7%db?xnqdh3y^QHyS(;HumTPpGoZ%}WK186v3HFuUaZO&8p+zLn>o_%OPSll%r)LcdeEGnyJcH=$fs?V1h4Rmq%LWd?~icrH*QpA9LD zKju27aEGpTk&#OdDlbP*K#D{ zbI^ZNgw5GXV=Q-m4|P2&v4D_lDzCAhnM9f$&iZ#(_hsvzOUU?Pec=8G?>T2fPoea} zp;>2QY$*+A`s$w!Cc;Hcrg>IH#t@~;2I|VUwzSNQ&H@urZl`HXBMWmNS+WjO*wQ*V z!<~ABR0n$u0PE;wN4%u;YRCQ~D!};~&nW(-iP88&Mp7CH)1~P+dKs{SM@H-c9d7Y+ zKh5C0I5bj|>qr(Z|LBt+6xYUC=df|l9RjLnM5n#OzHB6q`Vo=oG(E=f{g>pf_RkN9 zWwM?f)2)b1>3r$djbS|e!ZJ`BA(Sb)YiB6KAVz~eCFm+H2XQnKoTleE!C}c zlU~ab&1*GI%*Ic(faZc4Ntn*;S##8Z=Pz-HbpZ8CpwEwELl-n;+KsG5B8KOPCV!?O z^(VrMuT?wQ5C6*C?WGCYt5iw|&7YQ>;4jJ#O8iuO%y>@H)ZJ^9-q%(fxE`>~Mn+_2 zP&viQPLRrY8aR_JD8q%T!!6D#h=vuEhA76Hm@dPWT{0!{3ldIeU{S5Ka>2@U#&dn0 zq^gSqlaAZUn~%MJ2&}1M7g)n$Xt-<06Di!h+Zr@1o7^SjngJyY69OTNH*I-Kmqr%L z1-F&fFS>LM_ARLtIi_Av_k=X_H`!Sj$K9E;E0iDTGbhO2AEps)?<0V5In+@;HE(Ax zD!D=^`vH(W+t4DCUvUU1L74Uobasj_6R3bh(W6+3ERZ#KNa5w|vjg!k+E^%T;%M67 zRMRS-DPl$9n!9ckJ;>aJfM&^<6jD7`x~v_L;jRI0kurEug@6plz|XwQy=+Pb>j(2F zu!RL}deb^KFCEnOBcE}99DkC=lg~<}_S)V7BPeU+2vCbE1>2X`6tztl`E%$A!mj%J zx1&H5r$%b25uEKxAccp*IfqE+{ay@RPfBA_Ji!w#mV?W($Ajqbi8)mD;m+s*IRV1Q z?(e>N!cfWB08bJ>D6&0W5i(1;YWiH@*)z z37~c7Jq0HId%lK5Qiwd`hAaZu7%LqD-kFJ;+Z+1!basdN7(f-#DOvItA|h_Qm=7gq znoVh=sK&8bjSgWHq8jmnM;P1AU_b$ zelL0k1p<85Kb60RjmGnbDu=py6S`>r<%xnCs8Ot@yMYZ^G%_)zF!iVIfXeA845Rc^ zg<qH-9$RZ%!<*p{1vKaNJMVLavywAwm00I!WYpeoxULWt`5RudiksdA$$ zA}C=!5;|oiGTZ>G{#g^zG`*p<;k&eo>uP}CZk9|ejBd0wkUS? z<8c2o0WYEwzuyF3*N0qQ+#$;kLTO1yU~Q!jMoD8H^*&R49fvTU+vOgM3!JVPlLayl z9)jQLazL}4>QRsbaulA0X(;VxEe2l@Lo=efC%cZ&N%B9Xb0caQu699p2bB~xH{*(VO z(XjCPy6d3E3;h-DZ)9w3L6ZrSnGl$VrT2f;AP2DNe5s_m|yw;gD-?; zJA;X;(7G5la&n-OFg}9A5>Jk3Vi8Rby>LoFeo`?hXxOC}_ZbXIuvIepiJD)_QbhmS z(!dE!*=CG>>kO1JwuoOEx~7X{c=FFQsAn3(d*!0j%VHJm%%d#NSy@9g=eI#UY}_d9 zkyY?U7!NDcG>U8h)^{Iip$G07S`_NZUDxJL)!^iFCl%QZnovo0ouMiuUH!^iLbl_w zRG1YC0nIzHAAA9!?K%0Bv@~QhLEH@a7WhhB<;G>e70qMx!JC#t!y?q?mhsG5i9uBa zghb)!-04+M!Fq0hN`#RW%rra2W)Jo?DzJ>}v!67k(b%fDs2z9oy;bHEWCrlob!rg(I zQCd9Jx9AC=pFMNR@|1JOhH96JzM}-dC=>3j6gN!q5n|j|Ef%{wy*h^|7v#!TsIWMh z)R7bSw;#%qlpMmID%A;nRxy8Ht#x{D&h0tYtW?t= zqaDSGJAX1y$|kE`nmDNG4!UyR_jnk)W;CVsb!-7gx<7jgGgp=GGE5=-6%7gyRE zWNC>6U=5-azlF~X`O8VC4+}rM9eo_)z6=f$G#Ty^N!SGF2!XL}M(&f~M;;hD9WuGO zp}vFH$B_)l`dJ}DJ~$IP=coM@x@j+!jDR#%{tE|jlkFgq-MKXyR z2DtvCVFeg?>KsY9ZAALdM=H1&u@Dcqq-c@fARKtrezOGzgA3p9F}$uJSLB2D3Pd~V z#TGB4Z{=T{Y^2KxiUruA%wO(pC57K)U^^Cv=yoxcT&LCC8xkv=mR8GX(nX4X=Aad z!w>M|%Dzc6pcF)rGfGu{R@yGZ`X`AIhJw!NH((f>sJ8Ef)HO*>Ir@G6TRsEb4%@HK z@TfkDD@5yTzDE0rLNTqS5`gf9(@<61au{tuM}Yv~)<_y5F_zzqW<$U+ru4!zCx{dh z>gTwiaho=qbsUj!W6$rBcy17hTV%;30c2pYtZ?}`?o=cLfC7a=tYi^$T~qo&rbuV?1ie{aIF9_yM+GxPqo z%=15@C2Y*e5QjAT2i{agRhqD`>d&vxDQ;8usS zb$@_c5qRvhey!L2)av-Nc5T@|R*pt{_2dCwMN>9HE|g@?&=5Xi{XTNO%^#3qvY0!3 z>t!vD8Rgc1NuATQxXakwShbl zEb&Axu296@+>FkAZk2>kXTqtt6~Ijg>M-*02YR!@Tf{U>3Y!v3 zo5LN>L!Rv7w_m~FFI50230*9C4<#?Y*xz@j{T)?y-1#ub3tnuJY%eNw6zYUgPTD?y zT>E+rW4y&32f!biiq)KKQ%GtG1!~J1&2HTl(EI@#Ihsnq_XHC3QOUVU**| z9{3wR%S{0ME>D8uP!#KzUwa*W@tN9l)#BWYRPQ&7uNInLUjbyvn4<+oH2N#~C#(9H zZ?6A0NEMn|1YhR`ksB?xVwe8+iNPw!U4vs{CL$^ zivHKYH&>N~vx8tE#iCEF!)vlLDDfxa7>nq-XM~So;=^G`O@!ZMA3Te4YyM5KdHf0k z)DQCGvY%m-bH%Ad3oX)a(zPUCJd(@8{7hT-4BI9=5Ps>qUS5RIh&Nc9?g3_^{k}^7 z)5~nu7J;ao5@5zsmMLQfs`-B7M+!neYD8;PT2L^o|12^M%F_FKo*M!G|ni?1daeJ zWa=ZY@h@5x@?r5DvsO;21EKRv)mNm}0^8CYFvJ zZ#|=maZqUzEH)b!<56pc`0Ge%3ZgJZC^v!o&&i@O!NBdUVBN8@i=+>^+B~^W8&(#S zNIJ>LEZnk45LeW_7mQVCW%W4ZK$Zd;^8y+n7NPgLr<8e`nFZ>NMkg4;eS&AyJsTem!P!g2NYfadQAN8>6I zn{Hcz&Thu8iL7aSTjBdfVmXj5KC@?d2-XE>Em{pi?{H#n>udR7CY6MiL^NBR#bI+4 zSgW_V((hfXmkm*nguS4Qknk&0P_-No`U(`LYN$DS?2w-U%JbZ#t6fo$Fntak)W7f| zSxLDNQ?^!o;@qX-^L^IgW)<6Qr#b-92+MTcZq$KQZgkVHD)1`PP3ZHA185buIl*@{%na|s-)}Ew#H2WtM)Q;0I`9TdfWw4Uuve` zlpc?2Q8Z9{$->OeGuq20K`04&7jl(tBqdR;wcKEtKdCEklz&gL#v^+3kvu{Paehve z8E1(T()vhbiw%tYZm7Cdp^^MLSwLp-a z@4t5gp;5wn!r@zz4Xm!YB?ftd#dEf44Vq@=XMOw^i$fEo(<-P15W5_f&9=Mlq}Jg! z5lQe(#&-XeI=uW5=wz!bz4mZ(l6UliNSAv5I@1nnqt9wu*2GpXV!oLAO_ z-$YcsQnBdYPQg>SbxcZqc_Bg(ChU5|Tz+f_%sMhbQmjq=%3WAv7p07$ZgGZebNg556U5?y zN*+gbDM6Xh>c(3`#Tq2D2$DbY=aGf-XKoh^Eng^-Rdd{Yvu9tLMy;zTyr>)1>%{$# zD8|ly;0h|LTd;a9+d_*4soFT65JMy}Xcv^JMu%7(f&SSCLH>3{{@Ja(iBg5UGt%mg z9o;dnGP4DJcP z|9QS8BE{#D?jLNs;HexwN%$7I+?Nxv7uMqF`h`=Aay0beTNJ4D8!fx$`LWzp$Ps8~ zG+ZBZk=gju2|V^*(1sN3FI}v+zbnYP$T3KW^yi8i*&){y$CRozU5=yLMAYsE0tFz#ulYBovR0X{MGmT zEV02RJ*(v9#4f(88AoGbP#K$9*QlejA};)Xu%T;NuNU+3TeOWIxPVvFeX5+vo@$Md zod4T<;UZE?1fRfG_z4CqOu#jM<8!~Ep~_gYQ&ZS(=QJd}jn0lTeA!EkT-i zmB=F?fyanq+4JCyB(S-2a9C)X^JJF|q?LVQ^Xje0A~q0GPXwQ*hrQ4dCf=dVLA|1J zkk6n4K=JHIZdBKuNg|{fUA=XCTZDyyR(LjFVW*s-*bWgm?YUr0b^_(%ker)bzEIDY zFz_O4_YdRhFWl()FMQhT=EsnHM+ERp7b|@87F8Lu;#}k*qM(04dJnVfs}iwH_&`Oo znx$)soRCwHg*UaCR$j*CvfOhA7MfOI^(a=DIHedMXW27C&p(b3Mqjr zH);o6L#Dcea}FJY0w56#GEB*y-rf_X94JE+HyAA(#>IsVzyffw+Fsn@Q>(+lweTK6 z7U!L}O86ow)RBfHdRvP(o*@&8QD@#(xmmj0TWUGb*HsVRKY1I^>>i(V5q zN%8~#_S)J}sm;OzF0Fq5jBpY9d}}9fI=pNqDjG94{AR^+j}-RR)3K$Dg^p;u=A^iE zMvudXPPGB$jKwP43w5(brNnVNFgork`7#Euz26HADmTCl?ALc!wFyFh{xQqeTGN0p zQu$<1j!K1IYCQ6%<)$D>aw*TIP=&@TvD`kH&xBL3lg|?}NQ%G)mI`&h4o=0hl=&lw zNn%BtR|_9qRLU~xk;G-#bX!p;Z>}o(vT>hmS{oXoqHtJ$C*yPVEm$zB1JyIJV!6QH z@t{tz=Ie`TVJ%d41mlRKSp4Z|w%Wo*{T(fa?KJ!|0=QsPtE6ok&lnZBgFh<3+UX1` zaK=J1j`Y^P8y-6E?wk()K=cX2{_a8X$&6V3Rhmsi_?N^Hv~Z_6YD(qfaga;(N3wYF zOA!dcs?@PtI50w0v}iLLUcyE2o`NY~oI)y)B9KR!d`JZ$>xMZ_3B1EBO_i2uIO$;N z*oqR@#(Bji*4ENv6iY998|qlec-s|TMisOL^h)&tKW z3wJ0R+O3+NkhDBZLxoQveK_SwHkt3M7UAgmf3jBXGq8#Xy<)I)Ro;?7qr6%Pi(W$` zan?9$I8Gw1wd?QIX$zMWGZuo1tprm6<~eEhh^$V&pHtX&omI_EWt3h0#F*W5>5P=v z>6{mzza)fstUa?X9g|IlO_2cx=Np=!bJkYVpF1RA^#Pa!Gq$H2Si2mU#a-LrSXoPB zc0XxdEW*&V!$@@@+BU1?jq8EwIO-yW8twWWDjKhfQgGUtKanE7N9_%5VKUm|Dnh=s zm`V%}iZ$-Sf!UVmk+#MBH3uaF+EVrYI|-XCCgMuT$162kUcbfFFsM_XdcL7?R1(bK zD-D7MB@z5ph(;l>i!>~ssm*=%=MxZyf7>M%de*m3>Ze7pMxTg#LNpl$*&~u*Y_qOx zAZ31XYab08YU!T(X7rmsseE;qhDe6K>oFtuaO?6ZE#Ui{C$c%}jMJT*IUZC?=&^-@ zIeq8dGU#^UtjuMpwyt+9ERJ7k?D;cKUH1#}E%5dJV(yx`$J5JKAqv6uYrWaT&DO;G zqIX3=NmpDSg;x!8Y^{Ezp^tL=vVmNXRh=S<;$JJbkOer95)Cd{4%l|2-Wc zIC<-JZ;%K|ua=B<$N@?puO3m%)f+g9|1haN8XMgM4GCTSFF#evIR&$!bB==)^9$P{XlL3){MA6M{sL3?^PT=*%f^&pLlf z*ksKHs+mI_$<|?xX~x;vP1zr|$I}~b@4~|^k)Qx8CH`r9r2u$)a_r^L!(;(Yk&{Fs zfoGP}9t&mod5XeM#))^sPj0Sd9v7W4uCd*@Wq|e_F+)vmKidX-Q<{C^(C`95Xe#a2 zQeKY$^4rS*+K}XKI**E)fDyKVe=7qphy_ao1V*bpxguS<_(TL-UxGbECa)J&Q_?U} z#HMGNwhDoy+4U2uMbv74PfaI-^Oqi=+?`P~u( zLk8$t<55<4joF*2e`RonG;W3spP63&{&QYLGN#s`!)e<&lcFsKC+fP7_&I;^(|rXc?Kx3z7iXRT0?UXwvtNr=oG%d`T>5xyx1r8z=L*|F>(WY!Uj)b^x_C= zz6bbbZc2kt5X`)42#61^XRyEKJWl|6E0%*hiwjQgOyEHFP4_&E5VDy1!f7blsP};c zoy=V2AGUayegKiMVj&U4-mjWd;1^#Ar@_Q^mXEaAmtT-gg~h|3Ywd}zo`@eo6+bC5 zCYs{|ZL69{#t_f|p7u21sMaGv9#@790e#e;*yD5~wYxaOPM?Av*F?!EkzKKBK!%6=^b))xy+-9x-wUuP;Cb0f7Dxf> zqbjk-z3P*JfmyDN*OPp@q70oRq+f=+BH-Bw75P`!EbS~(BU~{!Fz)S0Ne*LZ*CS9) zK)T!0u-o6=yWvCgIZCg?>Bz8!^$sGGLuMdI_fxH_znSj`=y~d2`-NQepKP_mrz!da zm9#es!<`^+Yd}S=c8;VFzp8*_xn+27YExR!#RRaj&QQuXfOEY$i%I4(5V!0cNEzz| zy4SVle-;m)--@Vy2|Ak1T?_K7zl+Rrz@)hJw3WL{*8C*SUD{WwiLX$~EW}vH_MC0} zYr9O!VzUnr>2nEFJ~T;#0U9oHdQS74%G|9hGV>xmOqme`SAQe^tw0p%|AO`FUAnC( zoPO+gEl~mU4kz57va$n0Jn%n;kjOPvIZJkfZ94)@7OMX6v1ucWOgZ@5YLb!jq~;P0 z*zFO~+jhfP@^hc;d3K51U_xYtZh%$~7hO#EfJ-&Y&hXsQlgCe8 zqN3q~z4B1*r~iVP>+6}U*WxqZ#Dh~)tF&CK%Ry}WF07M zGL@@W@_?_KjD8#quCF@5Lq!(AG2~-4dED9G* z>aKsAJNoaU+pmmvIDUThWAz-D?Yxo3BqJXEs={oX*j6z@C_~Gv{XCf&4(99V8iqlvIFkfu2Q9Gz?b%qOSj^TWZ7DDEGx39$G=o- zj7}dV(V7+o1G_C_Q;(rkpEj>#YNkDzkMhL1W{E|fOAKVFcC;yb(9phaLVJ0PjF2$X zG~L^v7Ci#{Z5F^?nInKIc8V?nEVy3-CfSY(vq-*DgP=%h-aCfnCY$1(j9k=9hd%6 z^BT#x)uIaNI4{=v{1$fIb>`KsD7I3s!00GHZMYlC#6WW@sW%^qF)KUSC1+~^rWB~_ zeY{jabVpjXZ-X;YiQV38es(Lq?SmK0c)*sz5~z*nTEcoZXz;DAtq}1Na`%}xuBzEy zf2=WTgZG`qk^dX7IJor{2`jjYe2c&`uDkMR?HxA%3lE-V?J=sfA;Uf^N7T0KJVNT8 zCQxCdY6qlx4Lx7wdWbkTQJM_xT!zV zcrRNjX8_)XuQ7ddjFTh&7IMr&uJIJU`0*p!%N0! ztyR*6?Wl#xOSQGbC8Dc3FXJz{&1*NjSJZAvt@r2CEzIu16AsMVd+cv7yHYKi^#@g12%bl0Vz}U{vgzJa? z51XEd;J-wit$2z4OUcgBgn*5XfsTQQ51N30fXC6;luJoO?0?jMe(@5SJ3HHR(bK!R zxzV{X)7d$i(KB*#a?&#}(K9j8{z%X|dDuD|xYOD?5&yT5|6@nQ#L39f!rs}!&X(Xm zb`1>eT%37{i2mc~f4Bdxr?Z9W|Mg_+ME75nrZcj$q5sc6^o(>2^#5!7N0sM4TrPP> w3zHwu|FO@<$n#&4|3BXU_~D`dkMsYhGXH(1|Hb_|RX%7Q`v1Lbe9(aZ4{b>o{Qv*} literal 0 HcmV?d00001 diff --git a/public/stickers/webp/sticker15.webp b/public/stickers/webp/sticker15.webp new file mode 100644 index 0000000000000000000000000000000000000000..31a8f2a2794c2c220e1f8311c80f423500c3896d GIT binary patch literal 27834 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 Aq5uE@ literal 0 HcmV?d00001 diff --git a/public/stickers/webp/sticker16.webp b/public/stickers/webp/sticker16.webp new file mode 100644 index 0000000000000000000000000000000000000000..f847edba0958870813a3c94ec0dc04b473fc4527 GIT binary patch literal 28322 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 A!2kdN literal 0 HcmV?d00001 diff --git a/public/stickers/webp/sticker18.webp b/public/stickers/webp/sticker18.webp new file mode 100644 index 0000000000000000000000000000000000000000..57c09e8c076a83d24366b265249a91d25258b95c GIT binary patch literal 17392 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 literal 0 HcmV?d00001 diff --git a/public/stickers/webp/sticker19.webp b/public/stickers/webp/sticker19.webp new file mode 100644 index 0000000000000000000000000000000000000000..930dadd90ec6a4dca0b5e6b167f19b6189ea6957 GIT binary patch literal 19856 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 literal 0 HcmV?d00001 diff --git a/public/stickers/webp/sticker2.webp b/public/stickers/webp/sticker2.webp old mode 100755 new mode 100644 index b42d4e04b569e8ebbfa27f05f631b20a39a2b254..782bb398a53363b1b28b3ded8e44282d92c0f8d3 GIT binary patch literal 109668 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 z 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 nv5u)DNXN+GoB#j-000000000000000000000000000000-LCq* diff --git a/public/stickers/webp/sticker4.webp b/public/stickers/webp/sticker4.webp old mode 100755 new mode 100644 index 325071126683f21fc61b005f9d0f8b4bdf5c7656..801cd138075dd21864a7fdd7b371662fc9918ef2 GIT binary patch literal 48838 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 literal 53294 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%0D=$J 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

f!k2c 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 AyZ`_I diff --git a/public/stickers/webp/sticker6.webp b/public/stickers/webp/sticker6.webp old mode 100755 new mode 100644 index 515c9be7daa7caa6d7ab185023b293b4b0ea9247..e85560783cafad28eb88fc2649cccbe17f1f29e1 GIT binary patch literal 44830 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 literal 31140 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 JW3!P4{sH$09<=}f literal 46052 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 diff --git a/public/stickers/webp/sticker8.webp b/public/stickers/webp/sticker8.webp old mode 100755 new mode 100644 index 56c5a55ffff42def2101dd9964aa6d21cb2d4d8f..39e2bd20d8ebea828f1cf705276ab9347c03b410 GIT binary patch literal 30218 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%0ATN!r38 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 literal 43318 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 A4*&oF diff --git a/public/stickers/webp/wrinkle.webp b/public/stickers/webp/wrinkle.webp new file mode 100644 index 0000000000000000000000000000000000000000..c3e49e7e643056a6c00c2b1dbee5eb0e517ac785 GIT binary patch literal 4028 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%0Dnc9$p4s2B_sl(ai4OB~9L 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 diff --git a/todo b/todo index 375d4c95..71e76fc9 100644 --- a/todo +++ b/todo @@ -1,2 +1,16 @@ -- fxMaterialでblendingの仕組みをつくる - - shaderChunk的にblendingのコードをshaderに追加する仕組み \ No newline at end of file +- coverTextureつくる +- noiseをbaseFxにいれる +- fluidを整える + +- srcBlending, dstBlendingをつくる + - blend srcでこのhookでblendingする + - このhookでblend dstをblendingする + - たぶん、basic_begin_fragmentとbasic_end_fragmentを作ればいいかな + - fxBlendingをmixSrc/mixDstに変更する + + +- updateBasicFxでneedsUpdateしなくても更新できるはず。 + - 実態はthis.versionを++してるだけだった! + + +- ShaderのmixDstMap、mixSrcMapの命名が気持ちわるい \ No newline at end of file From 83cecfacab34e243f6b62b7d635245fb19a1197e Mon Sep 17 00:00:00 2001 From: takuma-hmng8 Date: Tue, 24 Sep 2024 10:45:06 +0900 Subject: [PATCH 04/60] update --- app/v2/FxMaterial.tsx | 6 +- app/v2/Playground.tsx | 49 ++++++++------- .../shaders/shaderChunk/coverTexture.glsl | 6 +- .../legacy/misc/useDomSyncer/shader/main.frag | 6 +- .../src/fxs/materials/FxBasicFxMaterial.ts | 59 ++++++++----------- .../src/fxs/materials/FxMaterial.ts | 26 ++++---- .../useCoverTexture/CoverTextureMaterial.ts | 2 +- .../fxs/useCoverTexture/coverTexture.glsl.ts | 6 +- .../src/fxs/useCoverTexture/index.ts | 4 +- .../use-shader-fx/src/fxs/useFluid/index.ts | 32 ++++------ .../useFluid/materials/AdvectionMaterial.ts | 31 +++++----- .../useFluid/materials/DivergenceMaterial.ts | 33 ++++++----- .../fxs/useFluid/materials/PoissonMaterial.ts | 33 ++++++----- .../useFluid/materials/PressureMaterial.ts | 37 ++++++------ .../fxs/useFluid/materials/SplatMaterial.ts | 33 ++++++----- .../useFluid/materials/shaders/advection.frag | 7 +-- .../materials/shaders/divergence.frag | 3 +- .../useFluid/materials/shaders/poisson.frag | 4 +- .../useFluid/materials/shaders/pressure.frag | 4 +- .../fxs/useFluid/materials/shaders/splat.frag | 4 +- .../fxs/useFluid/materials/shaders/vertex.ts | 19 +++--- .../src/fxs/useFluid/scenes/useAdvection.ts | 15 ++--- .../src/fxs/useFluid/scenes/useDivergence.ts | 6 +- .../src/fxs/useFluid/scenes/usePoisson.ts | 6 +- .../src/fxs/useFluid/scenes/usePressure.ts | 6 +- .../src/fxs/useFluid/scenes/useSplat.ts | 5 +- .../use-shader-fx/src/fxs/useNoise/index.ts | 4 +- .../ShaderChunk/default_pars_fragment.glsl | 7 ++- .../ShaderChunk/default_pars_vertex.glsl | 6 +- .../shaders/ShaderChunk/mixDst_fragment.glsl | 6 +- .../ShaderChunk/mixDst_pars_fragment.glsl | 6 +- .../shaders/ShaderChunk/mixDst_vertex.glsl | 4 +- .../ShaderChunk/mixSrc_fragment_begin.glsl | 4 +- .../ShaderChunk/mixSrc_fragment_end.glsl | 4 +- .../ShaderChunk/mixSrc_pars_fragment.glsl | 6 +- .../shaders/ShaderChunk/mixSrc_vertex.glsl | 4 +- .../ShaderLib/basicFx_pars_fragment.glsl | 2 - .../ShaderLib/basicFx_pars_vertex.glsl | 2 - packages/use-shader-fx/src/utils/useScene.ts | 14 ++++- todo | 18 ++---- 40 files changed, 261 insertions(+), 268 deletions(-) diff --git a/app/v2/FxMaterial.tsx b/app/v2/FxMaterial.tsx index ba02ad34..1da7f98f 100644 --- a/app/v2/FxMaterial.tsx +++ b/app/v2/FxMaterial.tsx @@ -40,10 +40,10 @@ export const FxMaterial = shaderMaterial( // float len = length(vel); // vel = vel * 0.5 + 0.5; - // vec3 color = vec3(vel.x, vel.y, len); - // color = mix(vec3(0.), color, len); + // vec3 color = vec3(vel.x, vel.y, 1.); + // color = mix(vec3(1.), color, len); - // gl_FragColor = vec4(color, 1.0); + // gl_FragColor = vec4(color, 1.0); } ` ); diff --git a/app/v2/Playground.tsx b/app/v2/Playground.tsx index a32ae1f4..0a03d683 100644 --- a/app/v2/Playground.tsx +++ b/app/v2/Playground.tsx @@ -45,32 +45,39 @@ export const Playground = () => { const noise = useNoise({ size, dpr: 0.2, - scale: 0.01, + scale: 0.02, // mixSrc: gear, // mixSrcResolution: new THREE.Vector2(512, 512), - // mixSrcUv: 0.9, - // mixSrcAlpha: 1, - mixDst: gear, - mixDstResolution: new THREE.Vector2(512, 512), - mixDstUv: 0.2, - mixDstAlpha: 1, - mixDstColor: 0.5, + // mixSrcUvFactor: 0.2, + // mixSrcAlphaFactor: 0.1, + // mixSrcColorFactor: 0.4, + // mixDst: gear, + // mixDstResolution: new THREE.Vector2(512, 512), + // mixDstUvFactor: 0.3, + // mixDstAlphaFactor: 1, + // mixDstColorFactor: 0, }); - // const cover = useCoverTexture({ - // size, - // dpr: 1, - // src: funkun_mov, - // textureResolution: new THREE.Vector2(1280, 720), - // // mixSrc: smoke, - // mixSrcResolution: new THREE.Vector2(512, 512), - // mixSrcUv: 0.12, - // mixSrcAlpha: 0.2, - // }); + const fluid = useFluid({ + size, + dpr: 0.15, + }); + + const cover = useCoverTexture({ + size, + dpr: 2, + src: funkun_mov, + textureResolution: new THREE.Vector2(1280, 720), + mixSrc: fluid.texture, + // mixSrcResolution: new THREE.Vector2(512, 512), + mixSrcUvFactor: 0.05, + // mixSrcAlphaFactor: 0.1, + // mixSrcColorFactor: 0.0, + }); useFrame((state) => { - // cover.render(state); - // fluid.render(state); + cover.render(state); + fluid.render(state); noise.render(state); // material.color = new THREE.Color( // Math.sin(state.clock.getElapsedTime()), @@ -85,7 +92,7 @@ export const Playground = () => { <> - + ); diff --git a/packages/use-shader-fx/legacy/libs/shaders/shaderChunk/coverTexture.glsl b/packages/use-shader-fx/legacy/libs/shaders/shaderChunk/coverTexture.glsl index 765bfc93..9d4d5243 100644 --- a/packages/use-shader-fx/legacy/libs/shaders/shaderChunk/coverTexture.glsl +++ b/packages/use-shader-fx/legacy/libs/shaders/shaderChunk/coverTexture.glsl @@ -1,7 +1,7 @@ -float screenAspect = uResolution.x / uResolution.y; +float aspectRatio = uResolution.x / uResolution.y; float textureAspect = uTextureResolution.x / uTextureResolution.y; vec2 aspectRatio = vec2( - min(screenAspect / textureAspect, 1.0), - min(textureAspect / screenAspect, 1.0) + min(aspectRatio / textureAspect, 1.0), + min(textureAspect / aspectRatio, 1.0) ); vec2 uv = vUv * aspectRatio + (1.0 - aspectRatio) * .5; \ No newline at end of file diff --git a/packages/use-shader-fx/legacy/misc/useDomSyncer/shader/main.frag b/packages/use-shader-fx/legacy/misc/useDomSyncer/shader/main.frag index 67922351..f5f84c39 100644 --- a/packages/use-shader-fx/legacy/misc/useDomSyncer/shader/main.frag +++ b/packages/use-shader-fx/legacy/misc/useDomSyncer/shader/main.frag @@ -8,11 +8,11 @@ uniform float u_borderRadius; void main() { // texuture color - float screenAspect = u_resolution.x / u_resolution.y; + float aspectRatio = u_resolution.x / u_resolution.y; float textureAspect = u_textureResolution.x / u_textureResolution.y; vec2 ratio = vec2( - min(screenAspect / textureAspect, 1.0), - min(textureAspect / screenAspect, 1.0) + min(aspectRatio / textureAspect, 1.0), + min(textureAspect / aspectRatio, 1.0) ); vec2 adjustedUv = vUv * ratio + (1.0 - ratio) * 0.5; diff --git a/packages/use-shader-fx/src/fxs/materials/FxBasicFxMaterial.ts b/packages/use-shader-fx/src/fxs/materials/FxBasicFxMaterial.ts index 052e0917..a94269eb 100644 --- a/packages/use-shader-fx/src/fxs/materials/FxBasicFxMaterial.ts +++ b/packages/use-shader-fx/src/fxs/materials/FxBasicFxMaterial.ts @@ -1,36 +1,35 @@ import * as THREE from "three"; import { DefaultUniforms, FxMaterial } from "./FxMaterial"; import { mergeUniforms } from "three/src/renderers/shaders/UniformsUtils.js"; -import { RootState } from "../types"; export type BasicFxUniforms = { // mixSrc mixSrc: { value: THREE.Texture | null }; mixSrcResolution: { value: THREE.Vector2 }; - mixSrcUv: { value: number }; - mixSrcAlpha: { value: number }; - mixSrcColor: { value: number }; + mixSrcUvFactor: { value: number }; + mixSrcAlphaFactor: { value: number }; + mixSrcColorFactor: { value: number }; // mixDst mixDst: { value: THREE.Texture | null }; mixDstResolution: { value: THREE.Vector2 }; - mixDstUv: { value: number }; - mixDstAlpha: { value: number }; - mixDstColor: { value: number }; + mixDstUvFactor: { value: number }; + mixDstAlphaFactor: { value: number }; + mixDstColorFactor: { value: number }; } & DefaultUniforms; export type BasicFxValues = { // mixSrc mixSrc?: THREE.Texture | null; mixSrcResolution?: THREE.Vector2; - mixSrcUv?: number; - mixSrcAlpha?: number; - mixSrcColor?: number; + mixSrcUvFactor?: number; + mixSrcAlphaFactor?: number; + mixSrcColorFactor?: number; //mixDst mixDst?: THREE.Texture | null; mixDstResolution?: THREE.Vector2; - mixDstUv?: number; - mixDstAlpha?: number; - mixDstColor?: number; + mixDstUvFactor?: number; + mixDstAlphaFactor?: number; + mixDstColorFactor?: number; }; type FxBasicMaterialProps = { @@ -46,7 +45,7 @@ export class FxBasicFxMaterial extends FxMaterial { mixDst: boolean; }; - uniforms: BasicFxUniforms; + uniforms!: BasicFxUniforms; vertexShaderCache: string; vertexPrefixCache: string; @@ -73,15 +72,15 @@ export class FxBasicFxMaterial extends FxMaterial { // mixSrc mixSrc: { value: null }, mixSrcResolution: { value: new THREE.Vector2() }, - mixSrcUv: { value: 0 }, - mixSrcAlpha: { value: 0 }, - mixSrcColor: { value: 0 }, + mixSrcUvFactor: { value: 0 }, + mixSrcAlphaFactor: { value: 0 }, + mixSrcColorFactor: { value: 0 }, // mixDst mixDst: { value: null }, mixDstResolution: { value: new THREE.Vector2() }, - mixDstUv: { value: 0 }, - mixDstAlpha: { value: 0 }, - mixDstColor: { value: 0 }, + mixDstUvFactor: { value: 0 }, + mixDstAlphaFactor: { value: 0 }, + mixDstColorFactor: { value: 0 }, } as BasicFxUniforms, ]) as BasicFxUniforms; @@ -97,11 +96,6 @@ export class FxBasicFxMaterial extends FxMaterial { this.setupBasicFxShaders(vertexShader, fragmentShader); } - update(rootState: RootState) { - this.updateDefaultValues(rootState); - this.updateBasicFx(); - } - updateBasicFx() { const _cache = this.programCache; @@ -123,7 +117,7 @@ export class FxBasicFxMaterial extends FxMaterial { if (_cache !== this.programCache) { this.updateBasicFxPrefix(); this.updateBasicFxShader(); - this.version++; // to update material + this.needsUpdate = true; // same as this.version++ } } @@ -154,13 +148,12 @@ export class FxBasicFxMaterial extends FxMaterial { setupBasicFxShaders(vertexShader?: string, fragmentShader?: string) { this.updateBasicFxPrefix(); - const { vertexShader: _vertex, fragmentShader: _fragment } = - this.resolveDefaultShaders( - vertexShader || this.vertexShaderCache, - fragmentShader || this.fragmentShaderCache - ); - this.vertexShaderCache = _vertex; - this.fragmentShaderCache = _fragment; + this.resolveDefaultShaders( + vertexShader || this.vertexShaderCache, + fragmentShader || this.fragmentShaderCache + ); + this.vertexShaderCache = this.vertexShader; + this.fragmentShaderCache = this.fragmentShader; this.updateBasicFxShader(); } } diff --git a/packages/use-shader-fx/src/fxs/materials/FxMaterial.ts b/packages/use-shader-fx/src/fxs/materials/FxMaterial.ts index 6a7f3b4a..eea9d017 100644 --- a/packages/use-shader-fx/src/fxs/materials/FxMaterial.ts +++ b/packages/use-shader-fx/src/fxs/materials/FxMaterial.ts @@ -1,10 +1,11 @@ import * as THREE from "three"; -import { RootState } from "../types"; import { resolveIncludes } from "../../libs/shaders/resolveShaders"; export type DefaultUniforms = { resolution: { value: THREE.Vector2 }; - screenAspect: { value: number }; + texelSize: { value: THREE.Vector2 }; + aspectRatio: { value: number }; + maxAspect: { value: THREE.Vector2 }; }; export class FxMaterial extends THREE.ShaderMaterial { @@ -13,23 +14,26 @@ export class FxMaterial extends THREE.ShaderMaterial { this.uniforms = { resolution: { value: new THREE.Vector2() }, - screenAspect: { value: 0 }, + texelSize: { value: new THREE.Vector2() }, + aspectRatio: { value: 0 }, + maxAspect: { value: new THREE.Vector2() }, } as DefaultUniforms; this.setValues(parameters); } - updateDefaultValues(rootState: RootState) { - const { size } = rootState; - this.uniforms.resolution.value.set(size.width, size.height); - this.uniforms.screenAspect.value = size.width / size.height; + updateResolution(resolution: THREE.Vector2) { + const { width, height } = resolution; + const maxAspect = Math.max(width, height); + this.uniforms.resolution.value.set(width, height); + this.uniforms.texelSize.value.set(1 / width, 1 / height); + this.uniforms.aspectRatio.value = width / height; + this.uniforms.maxAspect.value.set(maxAspect / width, maxAspect / height); } resolveDefaultShaders(vertexShader: string, fragmentShader: string) { - return { - vertexShader: resolveIncludes(vertexShader), - fragmentShader: resolveIncludes(fragmentShader), - }; + this.vertexShader = resolveIncludes(vertexShader); + this.fragmentShader = resolveIncludes(fragmentShader); } setUniformValues(values: any) { diff --git a/packages/use-shader-fx/src/fxs/useCoverTexture/CoverTextureMaterial.ts b/packages/use-shader-fx/src/fxs/useCoverTexture/CoverTextureMaterial.ts index 5a3b2a9c..e7368722 100644 --- a/packages/use-shader-fx/src/fxs/useCoverTexture/CoverTextureMaterial.ts +++ b/packages/use-shader-fx/src/fxs/useCoverTexture/CoverTextureMaterial.ts @@ -17,7 +17,7 @@ export class CoverTextureMaterial extends FxBasicFxMaterial { return "NoiseMaterial"; } - uniforms: CoverTextureUniforms; + uniforms!: CoverTextureUniforms; constructor(uniformValues?: CoverTextureValues, parameters = {}) { super(); diff --git a/packages/use-shader-fx/src/fxs/useCoverTexture/coverTexture.glsl.ts b/packages/use-shader-fx/src/fxs/useCoverTexture/coverTexture.glsl.ts index 83045de3..a0e3e3a2 100644 --- a/packages/use-shader-fx/src/fxs/useCoverTexture/coverTexture.glsl.ts +++ b/packages/use-shader-fx/src/fxs/useCoverTexture/coverTexture.glsl.ts @@ -11,8 +11,8 @@ export const vertex = ` float textureAspect = textureResolution.x / textureResolution.y; vec2 aspectRatio = vec2( - min(screenAspect / textureAspect, 1.0), - min(textureAspect / screenAspect, 1.0) + min(aspectRatio / textureAspect, 1.0), + min(textureAspect / aspectRatio, 1.0) ); vCoverTextureUv = vUv * aspectRatio + (1.0 - aspectRatio) * .5; @@ -36,7 +36,7 @@ export const fragment = ` vec4 usf_FragColor = texColor; ${ShaderLib.basicFx_fragment_end} - + gl_FragColor = usf_FragColor; } `; diff --git a/packages/use-shader-fx/src/fxs/useCoverTexture/index.ts b/packages/use-shader-fx/src/fxs/useCoverTexture/index.ts index fc215f4c..b7e98b63 100644 --- a/packages/use-shader-fx/src/fxs/useCoverTexture/index.ts +++ b/packages/use-shader-fx/src/fxs/useCoverTexture/index.ts @@ -33,6 +33,8 @@ export const useCoverTexture = ({ const _dpr = getDpr(dpr); const { scene, material } = useScene({ + size, + dpr: _dpr.shader, material: CoverTextureMaterial, uniformValues, materialParameters, @@ -60,7 +62,7 @@ export const useCoverTexture = ({ const { gl } = rootState; newValues && setValues(newValues); - material.update(rootState); + material.updateBasicFx(); return updateRenderTarget({ gl }); }, diff --git a/packages/use-shader-fx/src/fxs/useFluid/index.ts b/packages/use-shader-fx/src/fxs/useFluid/index.ts index e5de41be..8d7f9700 100644 --- a/packages/use-shader-fx/src/fxs/useFluid/index.ts +++ b/packages/use-shader-fx/src/fxs/useFluid/index.ts @@ -53,7 +53,7 @@ export const useFluid = ({ const [pressureFBO, updatePressureFBO] = useDoubleFBO(fboProps); // scenes - const SceneSize = useMemo(() => ({ size, dpr: _dpr.shader }), [_dpr, size]); + const SceneSize = useMemo(() => ({ size, dpr: _dpr.shader }), [size, _dpr]); const advection = useAdvection( { ...SceneSize, @@ -61,12 +61,7 @@ export const useFluid = ({ }, updateVelocity_1 ); - const splat = useSplat( - { - ...SceneSize, - }, - updateVelocity_1 - ); + const splat = useSplat(SceneSize, updateVelocity_1); const divergence = useDivergence( { ...SceneSize, @@ -90,6 +85,11 @@ export const useFluid = ({ updateVelocity_0 ); + const fluidShaders = useMemo( + () => [advection, splat, divergence, poisson, pressure], + [advection, splat, divergence, poisson, pressure] + ); + const setValues = useCallback((newValues: FluidValues) => { // splat.material.force = newValues.force; // bounce の設定 @@ -102,23 +102,13 @@ export const useFluid = ({ (rootState: RootState, newValues?: FluidValues) => { newValues && setValues(newValues); - advection.render(rootState); - splat.render(rootState); - divergence.render(rootState); - poisson.render(rootState); - pressure.render(rootState); + fluidShaders.forEach((shader) => { + shader.render(rootState); + }); return velocity_0.texture; }, - [ - setValues, - advection, - divergence, - poisson, - pressure, - splat, - velocity_0.texture, - ] + [setValues, fluidShaders, velocity_0.texture] ); return { diff --git a/packages/use-shader-fx/src/fxs/useFluid/materials/AdvectionMaterial.ts b/packages/use-shader-fx/src/fxs/useFluid/materials/AdvectionMaterial.ts index c5a96397..3c95a903 100644 --- a/packages/use-shader-fx/src/fxs/useFluid/materials/AdvectionMaterial.ts +++ b/packages/use-shader-fx/src/fxs/useFluid/materials/AdvectionMaterial.ts @@ -1,36 +1,37 @@ import * as THREE from "three"; import vertex from "./shaders/vertex"; import fragment from "./shaders/advection.frag"; -import { FxMaterial } from "../../materials/FxMaterial"; +import { FxMaterial, DefaultUniforms } from "../../materials/FxMaterial"; import { DEFAULT_TEXTURE } from "../../../libs/constants"; import { DeltaTime } from ".."; +import { mergeUniforms } from "three/src/renderers/shaders/UniformsUtils.js"; + +type AdvectionUniforms = { + velocity: { value: THREE.Texture }; + dt: { value: number }; +} & DefaultUniforms; export class AdvectionMaterial extends FxMaterial { static get type() { return "AdvectionMaterial"; } - uniforms: { - texelsize: { value: THREE.Vector2 }; - ratio: { value: THREE.Vector2 }; - velocity: { value: THREE.Texture }; - dt: { value: number }; - }; + uniforms!: AdvectionUniforms; constructor(uniformValues = {}, parameters = {}) { super(); this.type = AdvectionMaterial.type; - this.uniforms = { - texelsize: { value: new THREE.Vector2() }, - ratio: { value: new THREE.Vector2() }, - velocity: { value: DEFAULT_TEXTURE }, - dt: { value: DeltaTime }, - }; + this.uniforms = mergeUniforms([ + this.uniforms, + { + velocity: { value: DEFAULT_TEXTURE }, + dt: { value: DeltaTime }, + }, + ]) as AdvectionUniforms; - this.vertexShader = vertex.advection; - this.fragmentShader = fragment; + this.resolveDefaultShaders(vertex.advection, fragment); this.setUniformValues(uniformValues); this.setValues(parameters); diff --git a/packages/use-shader-fx/src/fxs/useFluid/materials/DivergenceMaterial.ts b/packages/use-shader-fx/src/fxs/useFluid/materials/DivergenceMaterial.ts index e086d200..016c5b4b 100644 --- a/packages/use-shader-fx/src/fxs/useFluid/materials/DivergenceMaterial.ts +++ b/packages/use-shader-fx/src/fxs/useFluid/materials/DivergenceMaterial.ts @@ -1,36 +1,39 @@ import * as THREE from "three"; import vertex from "./shaders/vertex"; import fragment from "./shaders/divergence.frag"; -import { FxMaterial } from "../../materials/FxMaterial"; +import { FxMaterial, DefaultUniforms } from "../../materials/FxMaterial"; import { DEFAULT_TEXTURE } from "../../../libs/constants"; import { DeltaTime } from ".."; +import { mergeUniforms } from "three/src/renderers/shaders/UniformsUtils.js"; + +type DivergenceUniforms = { + isBounce: { value: boolean }; + velocity: { value: THREE.Texture }; + dt: { value: number }; +} & DefaultUniforms; export class DivergenceMaterial extends FxMaterial { static get type() { return "DivergenceMaterial"; } - uniforms: { - texelsize: { value: THREE.Vector2 }; - isBounce: { value: boolean }; - velocity: { value: THREE.Texture }; - dt: { value: number }; - }; + uniforms!: DivergenceUniforms; constructor(uniformValues = {}, parameters = {}) { super(); this.type = DivergenceMaterial.type; - this.uniforms = { - texelsize: { value: new THREE.Vector2() }, - isBounce: { value: true }, - velocity: { value: DEFAULT_TEXTURE }, - dt: { value: DeltaTime }, - }; + this.uniforms = mergeUniforms([ + this.uniforms, + { + isBounce: { value: true }, + velocity: { value: DEFAULT_TEXTURE }, + dt: { value: DeltaTime }, + }, + ]) as DivergenceUniforms; - this.vertexShader = vertex.main; - this.fragmentShader = fragment; + this.resolveDefaultShaders(vertex.main, fragment); this.setUniformValues(uniformValues); this.setValues(parameters); diff --git a/packages/use-shader-fx/src/fxs/useFluid/materials/PoissonMaterial.ts b/packages/use-shader-fx/src/fxs/useFluid/materials/PoissonMaterial.ts index d849fdc6..9cd5736a 100644 --- a/packages/use-shader-fx/src/fxs/useFluid/materials/PoissonMaterial.ts +++ b/packages/use-shader-fx/src/fxs/useFluid/materials/PoissonMaterial.ts @@ -1,20 +1,22 @@ import * as THREE from "three"; import vertex from "./shaders/vertex"; import fragment from "./shaders/poisson.frag"; -import { FxMaterial } from "../../materials/FxMaterial"; +import { DefaultUniforms, FxMaterial } from "../../materials/FxMaterial"; import { DEFAULT_TEXTURE } from "../../../libs/constants"; +import { mergeUniforms } from "three/src/renderers/shaders/UniformsUtils.js"; + +type PoissonUniforms = { + isBounce: { value: boolean }; + pressure: { value: THREE.Texture }; + divergence: { value: THREE.Texture }; +} & DefaultUniforms; export class PoissonMaterial extends FxMaterial { static get type() { return "PoissonMaterial"; } - uniforms: { - texelsize: { value: THREE.Vector2 }; - isBounce: { value: boolean }; - pressure: { value: THREE.Texture }; - divergence: { value: THREE.Texture }; - }; + uniforms!: PoissonUniforms; iteration: number; @@ -23,17 +25,18 @@ export class PoissonMaterial extends FxMaterial { this.type = PoissonMaterial.type; - this.uniforms = { - texelsize: { value: new THREE.Vector2() }, - isBounce: { value: true }, - pressure: { value: DEFAULT_TEXTURE }, - divergence: { value: DEFAULT_TEXTURE }, - }; + this.uniforms = mergeUniforms([ + this.uniforms, + { + isBounce: { value: true }, + pressure: { value: DEFAULT_TEXTURE }, + divergence: { value: DEFAULT_TEXTURE }, + }, + ]) as PoissonUniforms; this.iteration = 32; - this.vertexShader = vertex.poisson; - this.fragmentShader = fragment; + this.resolveDefaultShaders(vertex.poisson, fragment); this.setUniformValues(uniformValues); this.setValues(parameters); diff --git a/packages/use-shader-fx/src/fxs/useFluid/materials/PressureMaterial.ts b/packages/use-shader-fx/src/fxs/useFluid/materials/PressureMaterial.ts index 517357c7..ff12abc0 100644 --- a/packages/use-shader-fx/src/fxs/useFluid/materials/PressureMaterial.ts +++ b/packages/use-shader-fx/src/fxs/useFluid/materials/PressureMaterial.ts @@ -1,38 +1,41 @@ import * as THREE from "three"; import vertex from "./shaders/vertex"; import fragment from "./shaders/pressure.frag"; -import { FxMaterial } from "../../materials/FxMaterial"; +import { FxMaterial, DefaultUniforms } from "../../materials/FxMaterial"; import { DEFAULT_TEXTURE } from "../../../libs/constants"; import { DeltaTime } from ".."; +import { mergeUniforms } from "three/src/renderers/shaders/UniformsUtils.js"; + +type PressureUniforms = { + isBounce: { value: boolean }; + pressure: { value: THREE.Texture }; + velocity: { value: THREE.Texture }; + dt: { value: number }; +} & DefaultUniforms; export class PressureMaterial extends FxMaterial { static get type() { return "PressureMaterial"; } - uniforms: { - texelsize: { value: THREE.Vector2 }; - isBounce: { value: boolean }; - pressure: { value: THREE.Texture }; - velocity: { value: THREE.Texture }; - dt: { value: number }; - }; + uniforms!: PressureUniforms; constructor(uniformValues = {}, parameters = {}) { super(); this.type = PressureMaterial.type; - this.uniforms = { - texelsize: { value: new THREE.Vector2() }, - isBounce: { value: true }, - pressure: { value: DEFAULT_TEXTURE }, - velocity: { value: DEFAULT_TEXTURE }, - dt: { value: DeltaTime }, - }; + this.uniforms = mergeUniforms([ + this.uniforms, + { + isBounce: { value: true }, + pressure: { value: DEFAULT_TEXTURE }, + velocity: { value: DEFAULT_TEXTURE }, + dt: { value: DeltaTime }, + }, + ]) as PressureUniforms; - this.vertexShader = vertex.main; - this.fragmentShader = fragment; + this.resolveDefaultShaders(vertex.main, fragment); this.setUniformValues(uniformValues); this.setValues(parameters); diff --git a/packages/use-shader-fx/src/fxs/useFluid/materials/SplatMaterial.ts b/packages/use-shader-fx/src/fxs/useFluid/materials/SplatMaterial.ts index ea8af262..b5387fb9 100644 --- a/packages/use-shader-fx/src/fxs/useFluid/materials/SplatMaterial.ts +++ b/packages/use-shader-fx/src/fxs/useFluid/materials/SplatMaterial.ts @@ -1,7 +1,14 @@ import * as THREE from "three"; import vertex from "./shaders/vertex"; import fragment from "./shaders/splat.frag"; -import { FxMaterial } from "../../materials/FxMaterial"; +import { DefaultUniforms, FxMaterial } from "../../materials/FxMaterial"; +import { mergeUniforms } from "three/src/renderers/shaders/UniformsUtils.js"; + +type SplatUniforms = { + force: { value: THREE.Vector2 }; + center: { value: THREE.Vector2 }; + scale: { value: THREE.Vector2 }; +} & DefaultUniforms; export class SplatMaterial extends FxMaterial { static get type() { @@ -10,12 +17,7 @@ export class SplatMaterial extends FxMaterial { force: number; - uniforms: { - texelsize: { value: THREE.Vector2 }; - force: { value: THREE.Vector2 }; - center: { value: THREE.Vector2 }; - scale: { value: THREE.Vector2 }; - }; + uniforms!: SplatUniforms; constructor(uniformValues = {}, parameters = {}) { super(); @@ -24,15 +26,16 @@ export class SplatMaterial extends FxMaterial { this.force = 30; - this.uniforms = { - texelsize: { value: new THREE.Vector2() }, - force: { value: new THREE.Vector2(0, 0) }, - center: { value: new THREE.Vector2(0, 0) }, - scale: { value: new THREE.Vector2(80, 80) }, - }; + this.uniforms = mergeUniforms([ + this.uniforms, + { + force: { value: new THREE.Vector2(0, 0) }, + center: { value: new THREE.Vector2(0, 0) }, + scale: { value: new THREE.Vector2(20, 20) }, + }, + ]) as SplatUniforms; - this.vertexShader = vertex.splat; - this.fragmentShader = fragment; + this.resolveDefaultShaders(vertex.splat, fragment); this.blending = THREE.AdditiveBlending; diff --git a/packages/use-shader-fx/src/fxs/useFluid/materials/shaders/advection.frag b/packages/use-shader-fx/src/fxs/useFluid/materials/shaders/advection.frag index 193fbaf3..0349cef5 100644 --- a/packages/use-shader-fx/src/fxs/useFluid/materials/shaders/advection.frag +++ b/packages/use-shader-fx/src/fxs/useFluid/materials/shaders/advection.frag @@ -1,14 +1,11 @@ -precision highp float; +#usf uniform float dt; -uniform vec2 ratio; uniform sampler2D velocity; -varying vec2 vUv; - void main(){ vec2 vel = texture2D(velocity, vUv).xy; - vec2 uv2 = vUv - vel * dt * ratio; + vec2 uv2 = vUv - vel * dt * maxAspect; vec2 newVel = texture2D(velocity, uv2).xy; gl_FragColor = vec4(newVel, 0.0, 0.0); } \ No newline at end of file diff --git a/packages/use-shader-fx/src/fxs/useFluid/materials/shaders/divergence.frag b/packages/use-shader-fx/src/fxs/useFluid/materials/shaders/divergence.frag index d2776ffb..155d4d6e 100644 --- a/packages/use-shader-fx/src/fxs/useFluid/materials/shaders/divergence.frag +++ b/packages/use-shader-fx/src/fxs/useFluid/materials/shaders/divergence.frag @@ -1,9 +1,8 @@ -precision highp float; +#usf uniform float dt; uniform sampler2D velocity; -varying vec2 vUv; varying vec2 vL; varying vec2 vR; varying vec2 vT; diff --git a/packages/use-shader-fx/src/fxs/useFluid/materials/shaders/poisson.frag b/packages/use-shader-fx/src/fxs/useFluid/materials/shaders/poisson.frag index e56447f1..147776ed 100644 --- a/packages/use-shader-fx/src/fxs/useFluid/materials/shaders/poisson.frag +++ b/packages/use-shader-fx/src/fxs/useFluid/materials/shaders/poisson.frag @@ -1,10 +1,8 @@ -precision highp float; +#usf -uniform vec2 texelsize; uniform sampler2D pressure; uniform sampler2D divergence; -varying vec2 vUv; varying vec2 vL; varying vec2 vR; varying vec2 vT; diff --git a/packages/use-shader-fx/src/fxs/useFluid/materials/shaders/pressure.frag b/packages/use-shader-fx/src/fxs/useFluid/materials/shaders/pressure.frag index 51d18a92..bfcb441a 100644 --- a/packages/use-shader-fx/src/fxs/useFluid/materials/shaders/pressure.frag +++ b/packages/use-shader-fx/src/fxs/useFluid/materials/shaders/pressure.frag @@ -1,11 +1,9 @@ -precision highp float; +#usf -uniform vec2 texelsize; uniform float dt; uniform sampler2D pressure; uniform sampler2D velocity; -varying vec2 vUv; varying vec2 vL; varying vec2 vR; varying vec2 vT; diff --git a/packages/use-shader-fx/src/fxs/useFluid/materials/shaders/splat.frag b/packages/use-shader-fx/src/fxs/useFluid/materials/shaders/splat.frag index 74029e38..c1ac4c1f 100644 --- a/packages/use-shader-fx/src/fxs/useFluid/materials/shaders/splat.frag +++ b/packages/use-shader-fx/src/fxs/useFluid/materials/shaders/splat.frag @@ -1,10 +1,8 @@ -precision highp float; +#usf uniform vec2 force; uniform vec2 center; -varying vec2 vUv; - void main(){ vec2 circle = (vUv - 0.5) * 2.0; float d = 1.0-min(length(circle), 1.0); diff --git a/packages/use-shader-fx/src/fxs/useFluid/materials/shaders/vertex.ts b/packages/use-shader-fx/src/fxs/useFluid/materials/shaders/vertex.ts index 8fe12846..7f7f5ca1 100644 --- a/packages/use-shader-fx/src/fxs/useFluid/materials/shaders/vertex.ts +++ b/packages/use-shader-fx/src/fxs/useFluid/materials/shaders/vertex.ts @@ -1,8 +1,5 @@ const base = ` - precision highp float; - - uniform vec2 texelsize; - varying vec2 vUv; + #usf `; const boxVarying = ` @@ -18,8 +15,8 @@ const getPosition = (isBounce: boolean = true) => { vec3 pos = position; vec2 scale = ${ isBounce - ? "isBounce ? vec2(1.,1.) : 1.-texelsize*2." - : "1.-texelsize*2." + ? "isBounce ? vec2(1.,1.) : 1.-texelSize*2." + : "1.-texelSize*2." }; pos.xy = pos.xy * scale; vUv = vec2(.5)+(pos.xy)*.5; @@ -28,10 +25,10 @@ const getPosition = (isBounce: boolean = true) => { const getBoxCompute = (diff: string) => { return ` - vL = vUv - vec2(texelsize.x * ${diff}, 0.0); - vR = vUv + vec2(texelsize.x * ${diff}, 0.0); - vT = vUv + vec2(0.0, texelsize.y * ${diff}); - vB = vUv - vec2(0.0, texelsize.y * ${diff}); + vL = vUv - vec2(texelSize.x * ${diff}, 0.0); + vR = vUv + vec2(texelSize.x * ${diff}, 0.0); + vT = vUv + vec2(0.0, texelSize.y * ${diff}); + vB = vUv - vec2(0.0, texelSize.y * ${diff}); `; }; @@ -72,7 +69,7 @@ const vertex = { uniform vec2 center; uniform vec2 scale; void main(){ - vec2 pos = position.xy * scale * 2.0 * texelsize + center; + vec2 pos = position.xy * scale * 2.0 * texelSize + center; vUv = uv; gl_Position = vec4(pos, 0.0, 1.0); } diff --git a/packages/use-shader-fx/src/fxs/useFluid/scenes/useAdvection.ts b/packages/use-shader-fx/src/fxs/useFluid/scenes/useAdvection.ts index 0b722db1..248ce00d 100644 --- a/packages/use-shader-fx/src/fxs/useFluid/scenes/useAdvection.ts +++ b/packages/use-shader-fx/src/fxs/useFluid/scenes/useAdvection.ts @@ -1,10 +1,9 @@ import * as THREE from "three"; -import { useCallback, useMemo } from "react"; +import { useCallback } from "react"; import { useCamera } from "../../../utils/useCamera"; -import { Dpr, RootState, Size } from "../../types"; +import { RootState, Size } from "../../types"; import { AdvectionMaterial } from "../materials/AdvectionMaterial"; import { SingleFBOUpdateFunction } from "../../../utils/useSingleFBO"; -import { useResolution } from "../../../utils/useResolution"; import { useScene } from "../../../utils/useScene"; export const useAdvection = ( @@ -20,18 +19,12 @@ export const useAdvection = ( updateRenderTarget: SingleFBOUpdateFunction ) => { const { scene, material } = useScene({ + size, + dpr, material: AdvectionMaterial, uniformValues: values, }); - const resolution = useResolution(size, dpr); - material.uniforms.texelsize.value.set(1 / resolution.x, 1 / resolution.y); - const maxAspect = Math.max(size.width, size.height); - material.uniforms.ratio.value.set( - maxAspect / resolution.x, - maxAspect / resolution.y - ); - const camera = useCamera(size); const render = useCallback( diff --git a/packages/use-shader-fx/src/fxs/useFluid/scenes/useDivergence.ts b/packages/use-shader-fx/src/fxs/useFluid/scenes/useDivergence.ts index ab0c1675..5ce3fe00 100644 --- a/packages/use-shader-fx/src/fxs/useFluid/scenes/useDivergence.ts +++ b/packages/use-shader-fx/src/fxs/useFluid/scenes/useDivergence.ts @@ -3,7 +3,6 @@ import { useCallback, useMemo } from "react"; import { useCamera } from "../../../utils/useCamera"; import { Dpr, RootState, Size } from "../../types"; import { SingleFBOUpdateFunction } from "../../../utils/useSingleFBO"; -import { useResolution } from "../../../utils/useResolution"; import { DivergenceMaterial } from "../materials/DivergenceMaterial"; import { useScene } from "../../../utils/useScene"; @@ -20,13 +19,12 @@ export const useDivergence = ( updateRenderTarget: SingleFBOUpdateFunction ) => { const { scene, material } = useScene({ + size, + dpr, material: DivergenceMaterial, uniformValues: values, }); - const resolution = useResolution(size, dpr); - material.uniforms.texelsize.value.set(1 / resolution.x, 1 / resolution.y); - const camera = useCamera(size); const render = useCallback( diff --git a/packages/use-shader-fx/src/fxs/useFluid/scenes/usePoisson.ts b/packages/use-shader-fx/src/fxs/useFluid/scenes/usePoisson.ts index 076d6411..89e35578 100644 --- a/packages/use-shader-fx/src/fxs/useFluid/scenes/usePoisson.ts +++ b/packages/use-shader-fx/src/fxs/useFluid/scenes/usePoisson.ts @@ -3,7 +3,6 @@ import { useCallback, useMemo } from "react"; import { useCamera } from "../../../utils/useCamera"; import { Dpr, RootState, Size } from "../../types"; import { SingleFBOUpdateFunction } from "../../../utils/useSingleFBO"; -import { useResolution } from "../../../utils/useResolution"; import { PoissonMaterial } from "../materials/PoissonMaterial"; import { useScene } from "../../../utils/useScene"; @@ -20,13 +19,12 @@ export const usePoisson = ( updateRenderTarget: SingleFBOUpdateFunction ) => { const { scene, material } = useScene({ + size, + dpr, material: PoissonMaterial, uniformValues: values, }); - const resolution = useResolution(size, dpr); - material.uniforms.texelsize.value.set(1 / resolution.x, 1 / resolution.y); - const camera = useCamera(size); const render = useCallback( diff --git a/packages/use-shader-fx/src/fxs/useFluid/scenes/usePressure.ts b/packages/use-shader-fx/src/fxs/useFluid/scenes/usePressure.ts index 0d5fb120..21f26a89 100644 --- a/packages/use-shader-fx/src/fxs/useFluid/scenes/usePressure.ts +++ b/packages/use-shader-fx/src/fxs/useFluid/scenes/usePressure.ts @@ -3,7 +3,6 @@ import { useCallback, useMemo } from "react"; import { useCamera } from "../../../utils/useCamera"; import { RootState, Size } from "../../types"; import { SingleFBOUpdateFunction } from "../../../utils/useSingleFBO"; -import { useResolution } from "../../../utils/useResolution"; import { PressureMaterial } from "../materials/PressureMaterial"; import { useScene } from "../../../utils/useScene"; @@ -21,13 +20,12 @@ export const usePressure = ( updateRenderTarget: SingleFBOUpdateFunction ) => { const { scene, material } = useScene({ + size, + dpr, material: PressureMaterial, uniformValues: values, }); - const resolution = useResolution(size, dpr); - material.uniforms.texelsize.value.set(1 / resolution.x, 1 / resolution.y); - const camera = useCamera(size); const render = useCallback( diff --git a/packages/use-shader-fx/src/fxs/useFluid/scenes/useSplat.ts b/packages/use-shader-fx/src/fxs/useFluid/scenes/useSplat.ts index 2b3942d7..67904f98 100644 --- a/packages/use-shader-fx/src/fxs/useFluid/scenes/useSplat.ts +++ b/packages/use-shader-fx/src/fxs/useFluid/scenes/useSplat.ts @@ -3,7 +3,6 @@ import { useCallback, useMemo } from "react"; import { useCamera } from "../../../utils/useCamera"; import { RootState, Size } from "../../types"; import { SingleFBOUpdateFunction } from "../../../utils/useSingleFBO"; -import { useResolution } from "../../../utils/useResolution"; import { SplatMaterial } from "../materials/SplatMaterial"; import { usePointer } from "../../../misc/usePointer"; import { useScene } from "../../../utils/useScene"; @@ -19,6 +18,8 @@ export const useSplat = ( updateRenderTarget: SingleFBOUpdateFunction ) => { const { scene, material } = useScene({ + size, + dpr, material: SplatMaterial, geometrySize: { width: 1, @@ -27,8 +28,6 @@ export const useSplat = ( }); const camera = useCamera(size); - const resolution = useResolution(size, dpr); - material.uniforms.texelsize.value.set(1 / resolution.x, 1 / resolution.y); const updatePointer = usePointer(); diff --git a/packages/use-shader-fx/src/fxs/useNoise/index.ts b/packages/use-shader-fx/src/fxs/useNoise/index.ts index 83c1a94f..7efc77c7 100644 --- a/packages/use-shader-fx/src/fxs/useNoise/index.ts +++ b/packages/use-shader-fx/src/fxs/useNoise/index.ts @@ -44,6 +44,8 @@ export const useNoise = ({ const _dpr = getDpr(dpr); const { scene, material } = useScene({ + size, + dpr: _dpr.shader, material: NoiseMaterial, uniformValues, materialParameters, @@ -73,7 +75,7 @@ export const useNoise = ({ material.uniforms.tick.value = newValues?.beat || clock.getElapsedTime(); - material.update(rootState); + material.updateBasicFx(); return updateRenderTarget({ gl }); }, diff --git a/packages/use-shader-fx/src/libs/shaders/ShaderChunk/default_pars_fragment.glsl b/packages/use-shader-fx/src/libs/shaders/ShaderChunk/default_pars_fragment.glsl index 6ba21e9c..b251fdeb 100644 --- a/packages/use-shader-fx/src/libs/shaders/ShaderChunk/default_pars_fragment.glsl +++ b/packages/use-shader-fx/src/libs/shaders/ShaderChunk/default_pars_fragment.glsl @@ -1,2 +1,7 @@ +precision highp float; + varying vec2 vUv; -uniform vec2 resolution; \ No newline at end of file +uniform vec2 resolution; +uniform vec2 texelSize; +uniform float aspectRatio; +uniform vec2 maxAspect; \ No newline at end of file diff --git a/packages/use-shader-fx/src/libs/shaders/ShaderChunk/default_pars_vertex.glsl b/packages/use-shader-fx/src/libs/shaders/ShaderChunk/default_pars_vertex.glsl index 06a6c603..b251fdeb 100644 --- a/packages/use-shader-fx/src/libs/shaders/ShaderChunk/default_pars_vertex.glsl +++ b/packages/use-shader-fx/src/libs/shaders/ShaderChunk/default_pars_vertex.glsl @@ -1,3 +1,7 @@ +precision highp float; + varying vec2 vUv; uniform vec2 resolution; -uniform float screenAspect; \ No newline at end of file +uniform vec2 texelSize; +uniform float aspectRatio; +uniform vec2 maxAspect; \ No newline at end of file diff --git a/packages/use-shader-fx/src/libs/shaders/ShaderChunk/mixDst_fragment.glsl b/packages/use-shader-fx/src/libs/shaders/ShaderChunk/mixDst_fragment.glsl index 0fbee3d8..28b78a3f 100644 --- a/packages/use-shader-fx/src/libs/shaders/ShaderChunk/mixDst_fragment.glsl +++ b/packages/use-shader-fx/src/libs/shaders/ShaderChunk/mixDst_fragment.glsl @@ -1,9 +1,9 @@ #ifdef USF_USE_MIXDST - vec4 mixDstMap = texture2D(mixDst, mix(vMixDstCoverUv,usf_FragColor.rg,mixDstUv)); + vec4 mixDstColor = texture2D(mixDst, mix(vMixDstCoverUv,usf_FragColor.rg,mixDstUvFactor)); - usf_FragColor = mix(usf_FragColor, mixDstMap, mixDstColor); + usf_FragColor = mix(usf_FragColor, mixDstColor, mixDstColorFactor); - usf_FragColor = mix(usf_FragColor, mixDstMap, mixDstMap.a * mixDstAlpha); + usf_FragColor = mix(usf_FragColor, mixDstColor, mixDstColor.a * mixDstAlphaFactor); #endif \ No newline at end of file diff --git a/packages/use-shader-fx/src/libs/shaders/ShaderChunk/mixDst_pars_fragment.glsl b/packages/use-shader-fx/src/libs/shaders/ShaderChunk/mixDst_pars_fragment.glsl index b84bb43f..c8e1277c 100644 --- a/packages/use-shader-fx/src/libs/shaders/ShaderChunk/mixDst_pars_fragment.glsl +++ b/packages/use-shader-fx/src/libs/shaders/ShaderChunk/mixDst_pars_fragment.glsl @@ -1,7 +1,7 @@ #ifdef USF_USE_MIXDST varying vec2 vMixDstCoverUv; uniform sampler2D mixDst; - uniform float mixDstUv; - uniform float mixDstAlpha; - uniform float mixDstColor; + uniform float mixDstUvFactor; + uniform float mixDstAlphaFactor; + uniform float mixDstColorFactor; #endif \ No newline at end of file diff --git a/packages/use-shader-fx/src/libs/shaders/ShaderChunk/mixDst_vertex.glsl b/packages/use-shader-fx/src/libs/shaders/ShaderChunk/mixDst_vertex.glsl index 13edd83c..e70c3b50 100644 --- a/packages/use-shader-fx/src/libs/shaders/ShaderChunk/mixDst_vertex.glsl +++ b/packages/use-shader-fx/src/libs/shaders/ShaderChunk/mixDst_vertex.glsl @@ -1,8 +1,8 @@ #ifdef USF_USE_MIXDST float mixDstAspect = mixDstResolution.x / mixDstResolution.y; vec2 mixDstAspectAspectRatio = vec2( - min(screenAspect / mixDstAspect, 1.0), - min(mixDstAspect / screenAspect, 1.0) + min(aspectRatio / mixDstAspect, 1.0), + min(mixDstAspect / aspectRatio, 1.0) ); vMixDstCoverUv = vUv * mixDstAspectAspectRatio + (1.0 - mixDstAspectAspectRatio) * .5; #endif \ No newline at end of file diff --git a/packages/use-shader-fx/src/libs/shaders/ShaderChunk/mixSrc_fragment_begin.glsl b/packages/use-shader-fx/src/libs/shaders/ShaderChunk/mixSrc_fragment_begin.glsl index d1b9355b..7b9bd1de 100644 --- a/packages/use-shader-fx/src/libs/shaders/ShaderChunk/mixSrc_fragment_begin.glsl +++ b/packages/use-shader-fx/src/libs/shaders/ShaderChunk/mixSrc_fragment_begin.glsl @@ -1,6 +1,6 @@ #ifdef USF_USE_MIXSRC - vec4 mixSrcMap = texture2D(mixSrc, vMixSrcCoverUv); - usf_Uv = mix(usf_Uv, mixSrcMap.rg, mixSrcUv); + vec4 mixSrcColor = texture2D(mixSrc, vMixSrcCoverUv); + usf_Uv = mix(usf_Uv, mixSrcColor.rg, mixSrcUvFactor); #endif \ No newline at end of file diff --git a/packages/use-shader-fx/src/libs/shaders/ShaderChunk/mixSrc_fragment_end.glsl b/packages/use-shader-fx/src/libs/shaders/ShaderChunk/mixSrc_fragment_end.glsl index 8d97c8f8..587ffa03 100644 --- a/packages/use-shader-fx/src/libs/shaders/ShaderChunk/mixSrc_fragment_end.glsl +++ b/packages/use-shader-fx/src/libs/shaders/ShaderChunk/mixSrc_fragment_end.glsl @@ -1,7 +1,7 @@ #ifdef USF_USE_MIXSRC - usf_FragColor = mix(usf_FragColor, mixSrcMap, mixSrcColor); + usf_FragColor = mix(usf_FragColor, mixSrcColor, mixSrcColorFactor); - usf_FragColor = mix(usf_FragColor, mixSrcMap, mixSrcMap.a * mixSrcAlpha); + usf_FragColor = mix(usf_FragColor, mixSrcColor, mixSrcColor.a * mixSrcAlphaFactor); #endif \ No newline at end of file diff --git a/packages/use-shader-fx/src/libs/shaders/ShaderChunk/mixSrc_pars_fragment.glsl b/packages/use-shader-fx/src/libs/shaders/ShaderChunk/mixSrc_pars_fragment.glsl index 35fa8c27..618c161a 100644 --- a/packages/use-shader-fx/src/libs/shaders/ShaderChunk/mixSrc_pars_fragment.glsl +++ b/packages/use-shader-fx/src/libs/shaders/ShaderChunk/mixSrc_pars_fragment.glsl @@ -1,7 +1,7 @@ #ifdef USF_USE_MIXSRC varying vec2 vMixSrcCoverUv; uniform sampler2D mixSrc; - uniform float mixSrcUv; - uniform float mixSrcAlpha; - uniform float mixSrcColor; + uniform float mixSrcUvFactor; + uniform float mixSrcAlphaFactor; + uniform float mixSrcColorFactor; #endif \ No newline at end of file diff --git a/packages/use-shader-fx/src/libs/shaders/ShaderChunk/mixSrc_vertex.glsl b/packages/use-shader-fx/src/libs/shaders/ShaderChunk/mixSrc_vertex.glsl index dd1a5873..40edcc13 100644 --- a/packages/use-shader-fx/src/libs/shaders/ShaderChunk/mixSrc_vertex.glsl +++ b/packages/use-shader-fx/src/libs/shaders/ShaderChunk/mixSrc_vertex.glsl @@ -1,8 +1,8 @@ #ifdef USF_USE_MIXSRC float mixSrcAspect = mixSrcResolution.x / mixSrcResolution.y; vec2 mixSrcAspectAspectRatio = vec2( - min(screenAspect / mixSrcAspect, 1.0), - min(mixSrcAspect / screenAspect, 1.0) + min(aspectRatio / mixSrcAspect, 1.0), + min(mixSrcAspect / aspectRatio, 1.0) ); vMixSrcCoverUv = vUv * mixSrcAspectAspectRatio + (1.0 - mixSrcAspectAspectRatio) * .5; #endif \ No newline at end of file diff --git a/packages/use-shader-fx/src/libs/shaders/ShaderLib/basicFx_pars_fragment.glsl b/packages/use-shader-fx/src/libs/shaders/ShaderLib/basicFx_pars_fragment.glsl index e1590e0e..dfacb117 100644 --- a/packages/use-shader-fx/src/libs/shaders/ShaderLib/basicFx_pars_fragment.glsl +++ b/packages/use-shader-fx/src/libs/shaders/ShaderLib/basicFx_pars_fragment.glsl @@ -1,5 +1,3 @@ -precision highp float; - #usf #usf #usf \ No newline at end of file diff --git a/packages/use-shader-fx/src/libs/shaders/ShaderLib/basicFx_pars_vertex.glsl b/packages/use-shader-fx/src/libs/shaders/ShaderLib/basicFx_pars_vertex.glsl index 13b530ee..875e8f9c 100644 --- a/packages/use-shader-fx/src/libs/shaders/ShaderLib/basicFx_pars_vertex.glsl +++ b/packages/use-shader-fx/src/libs/shaders/ShaderLib/basicFx_pars_vertex.glsl @@ -1,5 +1,3 @@ -precision highp float; - #usf #usf #usf \ No newline at end of file diff --git a/packages/use-shader-fx/src/utils/useScene.ts b/packages/use-shader-fx/src/utils/useScene.ts index 0a050fe2..fe741ed6 100644 --- a/packages/use-shader-fx/src/utils/useScene.ts +++ b/packages/use-shader-fx/src/utils/useScene.ts @@ -1,8 +1,11 @@ import { useMemo } from "react"; import * as THREE from "three"; import { useObject3D } from "./useObject3D"; +import { Size } from "../fxs/types"; +import { useResolution } from "./useResolution"; +import { FxMaterial } from "../fxs/materials/FxMaterial"; -type MaterialConstructor = new ( +type MaterialConstructor = new ( uniformValues?: any, materialParameters?: THREE.ShaderMaterialParameters ) => M; @@ -11,13 +14,17 @@ type GeometryConstructor = new ( height: number ) => THREE.BufferGeometry; -export const useScene = ({ +export const useScene = ({ + size, + dpr, material, uniformValues, materialParameters, geometry = THREE.PlaneGeometry, geometrySize, }: { + size: Size; + dpr: number | false; material: MaterialConstructor; uniformValues?: any; materialParameters?: THREE.ShaderMaterialParameters; @@ -39,6 +46,9 @@ export const useScene = ({ [material, uniformValues, materialParameters] ); + const resolution = useResolution(size, dpr); + _material.updateResolution(resolution); + useObject3D(scene, _geometry, _material, THREE.Mesh); return { diff --git a/todo b/todo index 71e76fc9..1fe9021c 100644 --- a/todo +++ b/todo @@ -1,16 +1,10 @@ -- coverTextureつくる -- noiseをbaseFxにいれる -- fluidを整える +- useBlankの設計まとめる -- srcBlending, dstBlendingをつくる - - blend srcでこのhookでblendingする - - このhookでblend dstをblendingする - - たぶん、basic_begin_fragmentとbasic_end_fragmentを作ればいいかな - - fxBlendingをmixSrc/mixDstに変更する +- pixelateつくる +- 要件定義つくって、ろくくんに引き継ぐ +- grain をbasic fxに +- 流体まとめる +- grain、暗くならないような工夫 -- updateBasicFxでneedsUpdateしなくても更新できるはず。 - - 実態はthis.versionを++してるだけだった! - -- ShaderのmixDstMap、mixSrcMapの命名が気持ちわるい \ No newline at end of file From 55677881d82bfc47a5afbe0e7daf0b373a3e4a02 Mon Sep 17 00:00:00 2001 From: takuma-hmng8 Date: Tue, 24 Sep 2024 18:40:57 +0900 Subject: [PATCH 05/60] update --- app/v2/Playground.tsx | 55 +++++-- .../src/fxs/materials/BasicFxLib.ts | 139 ++++++++++++++++++ .../src/fxs/materials/FxBasicFxMaterial.ts | 126 ++++------------ .../src/fxs/materials/FxMaterial.ts | 25 +++- packages/use-shader-fx/src/fxs/types/index.ts | 1 - .../useCoverTexture/CoverTextureMaterial.ts | 17 ++- .../src/fxs/useCoverTexture/index.ts | 2 +- .../useFluid/materials/AdvectionMaterial.ts | 19 ++- .../useFluid/materials/DivergenceMaterial.ts | 19 ++- .../fxs/useFluid/materials/PoissonMaterial.ts | 19 ++- .../useFluid/materials/PressureMaterial.ts | 19 ++- .../fxs/useFluid/materials/SplatMaterial.ts | 19 ++- .../src/fxs/useNoise/NoiseMaterial.ts | 17 +-- packages/use-shader-fx/src/utils/useScene.ts | 19 +-- todo | 2 - 15 files changed, 311 insertions(+), 187 deletions(-) create mode 100644 packages/use-shader-fx/src/fxs/materials/BasicFxLib.ts diff --git a/app/v2/Playground.tsx b/app/v2/Playground.tsx index 0a03d683..20f505ea 100644 --- a/app/v2/Playground.tsx +++ b/app/v2/Playground.tsx @@ -9,7 +9,12 @@ import { useCoverTexture, } from "@/packages/use-shader-fx/src"; import { FxMaterial } from "./FxMaterial"; -import { Float, OrbitControls, useVideoTexture } from "@react-three/drei"; +import { + Environment, + Float, + OrbitControls, + useVideoTexture, +} from "@react-three/drei"; /*=============================================== # webglooの設計 @@ -60,7 +65,7 @@ export const Playground = () => { const fluid = useFluid({ size, - dpr: 0.15, + dpr: 0.1, }); const cover = useCoverTexture({ @@ -68,17 +73,17 @@ export const Playground = () => { dpr: 2, src: funkun_mov, textureResolution: new THREE.Vector2(1280, 720), - mixSrc: fluid.texture, - // mixSrcResolution: new THREE.Vector2(512, 512), + // mixSrc: fluid.texture, + mixSrcResolution: new THREE.Vector2(512, 512), mixSrcUvFactor: 0.05, - // mixSrcAlphaFactor: 0.1, - // mixSrcColorFactor: 0.0, + mixSrcAlphaFactor: 0.1, + mixSrcColorFactor: 0.0, }); useFrame((state) => { - cover.render(state); + // cover.render(state); fluid.render(state); - noise.render(state); + // noise.render(state); // material.color = new THREE.Color( // Math.sin(state.clock.getElapsedTime()), // 1, @@ -90,10 +95,36 @@ export const Playground = () => { return ( <> - - - - + + + {/* + */} + + + + + {/* */} + + + + + + + {/* */} + + ); }; diff --git a/packages/use-shader-fx/src/fxs/materials/BasicFxLib.ts b/packages/use-shader-fx/src/fxs/materials/BasicFxLib.ts new file mode 100644 index 00000000..81ff8fa3 --- /dev/null +++ b/packages/use-shader-fx/src/fxs/materials/BasicFxLib.ts @@ -0,0 +1,139 @@ +import * as THREE from "three"; +import { DefaultUniforms } from "./FxMaterial"; + +/*=============================================== +basic fxを追加するときはこことShaderChunk,Libを編集する +===============================================*/ + +type BasicFxUniformsUnique = { + // mixSrc + mixSrc: { value: THREE.Texture | null }; + mixSrcResolution: { value: THREE.Vector2 }; + mixSrcUvFactor: { value: number }; + mixSrcAlphaFactor: { value: number }; + mixSrcColorFactor: { value: number }; + // mixDst + mixDst: { value: THREE.Texture | null }; + mixDstResolution: { value: THREE.Vector2 }; + mixDstUvFactor: { value: number }; + mixDstAlphaFactor: { value: number }; + mixDstColorFactor: { value: number }; +}; + +export type BasicFxUniforms = BasicFxUniformsUnique & DefaultUniforms; + +export type BasicFxValues = { + // mixSrc + mixSrc?: THREE.Texture | null; + mixSrcResolution?: THREE.Vector2; + mixSrcUvFactor?: number; + mixSrcAlphaFactor?: number; + mixSrcColorFactor?: number; + //mixDst + mixDst?: THREE.Texture | null; + mixDstResolution?: THREE.Vector2; + mixDstUvFactor?: number; + mixDstAlphaFactor?: number; + mixDstColorFactor?: number; +}; + +const DEFAULT_BASICFX_VALUES: BasicFxUniformsUnique = { + // mixSrc + mixSrc: { value: null }, + mixSrcResolution: { value: new THREE.Vector2() }, + mixSrcUvFactor: { value: 0 }, + mixSrcAlphaFactor: { value: 0 }, + mixSrcColorFactor: { value: 0 }, + // mixDst + mixDst: { value: null }, + mixDstResolution: { value: new THREE.Vector2() }, + mixDstUvFactor: { value: 0 }, + mixDstAlphaFactor: { value: 0 }, + mixDstColorFactor: { value: 0 }, +}; + +export type BasicFxFlag = { + mixSrc: boolean; + mixDst: boolean; +}; + +function setupDefaultFlag(uniformValues?: BasicFxValues): BasicFxFlag { + return { + mixSrc: uniformValues?.mixSrc ? true : false, + mixDst: uniformValues?.mixDst ? true : false, + }; +} + +function handleUpdateBasicFx( + uniforms: BasicFxUniforms, + basicFxFlag: BasicFxFlag +): { + validCount: number; + updatedFlag: BasicFxFlag; +} { + const isMixSrc = uniforms.mixSrc.value ? true : false; + const isMixDst = uniforms.mixDst.value ? true : false; + + const { mixSrc, mixDst } = basicFxFlag; + + const updatedFlag = basicFxFlag; + + let validCount = 0; + + if (mixSrc !== isMixSrc) { + updatedFlag.mixSrc = isMixSrc; + validCount++; + } + + if (mixDst !== isMixDst) { + updatedFlag.mixDst = isMixDst; + validCount++; + } + + return { + validCount, + updatedFlag, + }; +} + +function filterEmptyLine(string: string) { + return string !== ""; +} + +const BASICFX_SHADER_PREFIX = { + mixSrc: "#define USF_USE_MIXSRC", + mixDst: "#define USF_USE_MIXDST", +}; + +function handleUpdateBasicFxPrefix(basicFxFlag: BasicFxFlag): { + prefixVertex: string; + prefixFragment: string; +} { + const { mixSrc, mixDst } = basicFxFlag; + const prefixVertex = [ + mixSrc ? BASICFX_SHADER_PREFIX.mixSrc : "", + mixDst ? BASICFX_SHADER_PREFIX.mixDst : "", + "\n", + ] + .filter(filterEmptyLine) + .join("\n"); + const prefixFragment = [ + mixSrc ? BASICFX_SHADER_PREFIX.mixSrc : "", + mixDst ? BASICFX_SHADER_PREFIX.mixDst : "", + "\n", + ] + .filter(filterEmptyLine) + .join("\n"); + + return { + prefixVertex, + prefixFragment, + }; +} + +export const BasicFxLib = { + DEFAULT_BASICFX_VALUES, + setupDefaultFlag, + handleUpdateBasicFx, + handleUpdateBasicFxPrefix, +}; diff --git a/packages/use-shader-fx/src/fxs/materials/FxBasicFxMaterial.ts b/packages/use-shader-fx/src/fxs/materials/FxBasicFxMaterial.ts index a94269eb..53a8dbb3 100644 --- a/packages/use-shader-fx/src/fxs/materials/FxBasicFxMaterial.ts +++ b/packages/use-shader-fx/src/fxs/materials/FxBasicFxMaterial.ts @@ -1,49 +1,13 @@ -import * as THREE from "three"; -import { DefaultUniforms, FxMaterial } from "./FxMaterial"; -import { mergeUniforms } from "three/src/renderers/shaders/UniformsUtils.js"; - -export type BasicFxUniforms = { - // mixSrc - mixSrc: { value: THREE.Texture | null }; - mixSrcResolution: { value: THREE.Vector2 }; - mixSrcUvFactor: { value: number }; - mixSrcAlphaFactor: { value: number }; - mixSrcColorFactor: { value: number }; - // mixDst - mixDst: { value: THREE.Texture | null }; - mixDstResolution: { value: THREE.Vector2 }; - mixDstUvFactor: { value: number }; - mixDstAlphaFactor: { value: number }; - mixDstColorFactor: { value: number }; -} & DefaultUniforms; - -export type BasicFxValues = { - // mixSrc - mixSrc?: THREE.Texture | null; - mixSrcResolution?: THREE.Vector2; - mixSrcUvFactor?: number; - mixSrcAlphaFactor?: number; - mixSrcColorFactor?: number; - //mixDst - mixDst?: THREE.Texture | null; - mixDstResolution?: THREE.Vector2; - mixDstUvFactor?: number; - mixDstAlphaFactor?: number; - mixDstColorFactor?: number; -}; - -type FxBasicMaterialProps = { - uniformValues?: BasicFxValues; - parameters?: {}; - vertexShader?: string; - fragmentShader?: string; -}; +import { FxMaterial, FxMaterialProps } from "./FxMaterial"; +import { + BasicFxUniforms, + BasicFxValues, + BasicFxFlag, + BasicFxLib, +} from "./BasicFxLib"; export class FxBasicFxMaterial extends FxMaterial { - basicFx: { - mixSrc: boolean; - mixDst: boolean; - }; + basicFxFlag: BasicFxFlag; uniforms!: BasicFxUniforms; @@ -55,37 +19,23 @@ export class FxBasicFxMaterial extends FxMaterial { constructor({ uniformValues, - parameters = {}, + materialParameters = {}, + uniforms, vertexShader, fragmentShader, - }: FxBasicMaterialProps = {}) { + }: FxMaterialProps = {}) { super(); - this.basicFx = { - mixSrc: uniformValues?.mixSrc ? true : false, - mixDst: uniformValues?.mixDst ? true : false, - }; + this.basicFxFlag = BasicFxLib.setupDefaultFlag(uniformValues); - this.uniforms = mergeUniforms([ - this.uniforms, - { - // mixSrc - mixSrc: { value: null }, - mixSrcResolution: { value: new THREE.Vector2() }, - mixSrcUvFactor: { value: 0 }, - mixSrcAlphaFactor: { value: 0 }, - mixSrcColorFactor: { value: 0 }, - // mixDst - mixDst: { value: null }, - mixDstResolution: { value: new THREE.Vector2() }, - mixDstUvFactor: { value: 0 }, - mixDstAlphaFactor: { value: 0 }, - mixDstColorFactor: { value: 0 }, - } as BasicFxUniforms, - ]) as BasicFxUniforms; + this.uniforms = { + ...this.uniforms, + ...BasicFxLib.DEFAULT_BASICFX_VALUES, + ...uniforms, + } as BasicFxUniforms; this.setUniformValues(uniformValues); - this.setValues(parameters); + this.setValues(materialParameters); this.vertexShaderCache = this.vertexShader; this.fragmentShaderCache = this.fragmentShader; @@ -99,20 +49,13 @@ export class FxBasicFxMaterial extends FxMaterial { updateBasicFx() { const _cache = this.programCache; - const isMixSrc = this.uniforms.mixSrc.value ? true : false; - const isMixDst = this.uniforms.mixDst.value ? true : false; - - const { mixSrc, mixDst } = this.basicFx; - - if (mixSrc !== isMixSrc) { - this.basicFx.mixSrc = isMixSrc; - this.programCache++; - } + const { validCount, updatedFlag } = BasicFxLib.handleUpdateBasicFx( + this.uniforms, + this.basicFxFlag + ); - if (mixDst !== isMixDst) { - this.basicFx.mixDst = isMixDst; - this.programCache++; - } + this.programCache += validCount; + this.basicFxFlag = updatedFlag; if (_cache !== this.programCache) { this.updateBasicFxPrefix(); @@ -122,21 +65,8 @@ export class FxBasicFxMaterial extends FxMaterial { } updateBasicFxPrefix() { - const { mixSrc, mixDst } = this.basicFx; - const prefixVertex = [ - mixSrc ? "#define USF_USE_MIXSRC" : "", - mixDst ? "#define USF_USE_MIXDST" : "", - "\n", - ] - .filter(filterEmptyLine) - .join("\n"); - const prefixFragment = [ - mixSrc ? "#define USF_USE_MIXSRC" : "", - mixDst ? "#define USF_USE_MIXDST" : "", - "\n", - ] - .filter(filterEmptyLine) - .join("\n"); + const { prefixVertex, prefixFragment } = + BasicFxLib.handleUpdateBasicFxPrefix(this.basicFxFlag); this.vertexPrefixCache = prefixVertex; this.fragmentPrefixCache = prefixFragment; } @@ -157,7 +87,3 @@ export class FxBasicFxMaterial extends FxMaterial { this.updateBasicFxShader(); } } - -function filterEmptyLine(string: string) { - return string !== ""; -} diff --git a/packages/use-shader-fx/src/fxs/materials/FxMaterial.ts b/packages/use-shader-fx/src/fxs/materials/FxMaterial.ts index eea9d017..0069bd85 100644 --- a/packages/use-shader-fx/src/fxs/materials/FxMaterial.ts +++ b/packages/use-shader-fx/src/fxs/materials/FxMaterial.ts @@ -8,8 +8,22 @@ export type DefaultUniforms = { maxAspect: { value: THREE.Vector2 }; }; +export type FxMaterialProps = { + uniformValues?: T; + materialParameters?: {}; + uniforms?: { [uniform: string]: THREE.IUniform }; + vertexShader?: string; + fragmentShader?: string; +}; + export class FxMaterial extends THREE.ShaderMaterial { - constructor(parameters = {}) { + constructor({ + uniformValues, + materialParameters = {}, + uniforms, + vertexShader, + fragmentShader, + }: FxMaterialProps = {}) { super(); this.uniforms = { @@ -17,9 +31,14 @@ export class FxMaterial extends THREE.ShaderMaterial { texelSize: { value: new THREE.Vector2() }, aspectRatio: { value: 0 }, maxAspect: { value: new THREE.Vector2() }, + ...uniforms, } as DefaultUniforms; - this.setValues(parameters); + this.vertexShader = vertexShader || this.vertexShader; + this.fragmentShader = fragmentShader || this.fragmentShader; + + this.setUniformValues(uniformValues); + this.setValues(materialParameters); } updateResolution(resolution: THREE.Vector2) { @@ -36,7 +55,7 @@ export class FxMaterial extends THREE.ShaderMaterial { this.fragmentShader = resolveIncludes(fragmentShader); } - setUniformValues(values: any) { + setUniformValues(values?: { [key: string]: any }) { if (values === undefined) return; for (const key in values) { diff --git a/packages/use-shader-fx/src/fxs/types/index.ts b/packages/use-shader-fx/src/fxs/types/index.ts index 09f2f33b..4f2cd119 100644 --- a/packages/use-shader-fx/src/fxs/types/index.ts +++ b/packages/use-shader-fx/src/fxs/types/index.ts @@ -1,5 +1,4 @@ import * as THREE from "three"; -import { BasicFx } from "../materials/FxBasicFxMaterial"; export type Size = { width: number; height: number }; diff --git a/packages/use-shader-fx/src/fxs/useCoverTexture/CoverTextureMaterial.ts b/packages/use-shader-fx/src/fxs/useCoverTexture/CoverTextureMaterial.ts index e7368722..e44f1475 100644 --- a/packages/use-shader-fx/src/fxs/useCoverTexture/CoverTextureMaterial.ts +++ b/packages/use-shader-fx/src/fxs/useCoverTexture/CoverTextureMaterial.ts @@ -5,7 +5,7 @@ import { FxBasicFxMaterial, } from "../materials/FxBasicFxMaterial"; import { CoverTextureValues } from "."; -import { mergeUniforms } from "three/src/renderers/shaders/UniformsUtils.js"; +import { FxMaterialProps } from "../materials/FxMaterial"; type CoverTextureUniforms = { src: { value: THREE.Texture | null }; @@ -19,21 +19,24 @@ export class CoverTextureMaterial extends FxBasicFxMaterial { uniforms!: CoverTextureUniforms; - constructor(uniformValues?: CoverTextureValues, parameters = {}) { + constructor({ + uniformValues, + materialParameters = {}, + }: FxMaterialProps) { super(); this.type = CoverTextureMaterial.type; - this.uniforms = mergeUniforms([ - this.uniforms, - { + this.uniforms = { + ...this.uniforms, + ...{ src: { value: null }, textureResolution: { value: new THREE.Vector2() }, }, - ]) as CoverTextureUniforms; + }; this.setUniformValues(uniformValues); - this.setValues(parameters); + this.setValues(materialParameters); this.setupBasicFxShaders(vertex, fragment); } diff --git a/packages/use-shader-fx/src/fxs/useCoverTexture/index.ts b/packages/use-shader-fx/src/fxs/useCoverTexture/index.ts index b7e98b63..aaeb77de 100644 --- a/packages/use-shader-fx/src/fxs/useCoverTexture/index.ts +++ b/packages/use-shader-fx/src/fxs/useCoverTexture/index.ts @@ -7,7 +7,7 @@ import { getDpr } from "../../utils/getDpr"; import { RootState } from "../types"; import { CoverTextureMaterial } from "./CoverTextureMaterial"; import { useScene } from "../../utils/useScene"; -import { BasicFxValues } from "../materials/FxBasicFxMaterial"; +import { BasicFxValues } from "../materials/BasicFxLib"; export type CoverTextureValues = { src?: THREE.Texture; diff --git a/packages/use-shader-fx/src/fxs/useFluid/materials/AdvectionMaterial.ts b/packages/use-shader-fx/src/fxs/useFluid/materials/AdvectionMaterial.ts index 3c95a903..f1c8b9bc 100644 --- a/packages/use-shader-fx/src/fxs/useFluid/materials/AdvectionMaterial.ts +++ b/packages/use-shader-fx/src/fxs/useFluid/materials/AdvectionMaterial.ts @@ -1,10 +1,13 @@ import * as THREE from "three"; import vertex from "./shaders/vertex"; import fragment from "./shaders/advection.frag"; -import { FxMaterial, DefaultUniforms } from "../../materials/FxMaterial"; +import { + FxMaterial, + DefaultUniforms, + FxMaterialProps, +} from "../../materials/FxMaterial"; import { DEFAULT_TEXTURE } from "../../../libs/constants"; import { DeltaTime } from ".."; -import { mergeUniforms } from "three/src/renderers/shaders/UniformsUtils.js"; type AdvectionUniforms = { velocity: { value: THREE.Texture }; @@ -18,22 +21,22 @@ export class AdvectionMaterial extends FxMaterial { uniforms!: AdvectionUniforms; - constructor(uniformValues = {}, parameters = {}) { + constructor({ uniformValues, materialParameters = {} }: FxMaterialProps) { super(); this.type = AdvectionMaterial.type; - this.uniforms = mergeUniforms([ - this.uniforms, - { + this.uniforms = { + ...this.uniforms, + ...{ velocity: { value: DEFAULT_TEXTURE }, dt: { value: DeltaTime }, }, - ]) as AdvectionUniforms; + }; this.resolveDefaultShaders(vertex.advection, fragment); this.setUniformValues(uniformValues); - this.setValues(parameters); + this.setValues(materialParameters); } } diff --git a/packages/use-shader-fx/src/fxs/useFluid/materials/DivergenceMaterial.ts b/packages/use-shader-fx/src/fxs/useFluid/materials/DivergenceMaterial.ts index 016c5b4b..5f6bfb31 100644 --- a/packages/use-shader-fx/src/fxs/useFluid/materials/DivergenceMaterial.ts +++ b/packages/use-shader-fx/src/fxs/useFluid/materials/DivergenceMaterial.ts @@ -1,10 +1,13 @@ import * as THREE from "three"; import vertex from "./shaders/vertex"; import fragment from "./shaders/divergence.frag"; -import { FxMaterial, DefaultUniforms } from "../../materials/FxMaterial"; +import { + FxMaterial, + DefaultUniforms, + FxMaterialProps, +} from "../../materials/FxMaterial"; import { DEFAULT_TEXTURE } from "../../../libs/constants"; import { DeltaTime } from ".."; -import { mergeUniforms } from "three/src/renderers/shaders/UniformsUtils.js"; type DivergenceUniforms = { isBounce: { value: boolean }; @@ -19,23 +22,23 @@ export class DivergenceMaterial extends FxMaterial { uniforms!: DivergenceUniforms; - constructor(uniformValues = {}, parameters = {}) { + constructor({ uniformValues, materialParameters = {} }: FxMaterialProps) { super(); this.type = DivergenceMaterial.type; - this.uniforms = mergeUniforms([ - this.uniforms, - { + this.uniforms = { + ...this.uniforms, + ...{ isBounce: { value: true }, velocity: { value: DEFAULT_TEXTURE }, dt: { value: DeltaTime }, }, - ]) as DivergenceUniforms; + }; this.resolveDefaultShaders(vertex.main, fragment); this.setUniformValues(uniformValues); - this.setValues(parameters); + this.setValues(materialParameters); } } diff --git a/packages/use-shader-fx/src/fxs/useFluid/materials/PoissonMaterial.ts b/packages/use-shader-fx/src/fxs/useFluid/materials/PoissonMaterial.ts index 9cd5736a..51c29a18 100644 --- a/packages/use-shader-fx/src/fxs/useFluid/materials/PoissonMaterial.ts +++ b/packages/use-shader-fx/src/fxs/useFluid/materials/PoissonMaterial.ts @@ -1,9 +1,12 @@ import * as THREE from "three"; import vertex from "./shaders/vertex"; import fragment from "./shaders/poisson.frag"; -import { DefaultUniforms, FxMaterial } from "../../materials/FxMaterial"; +import { + DefaultUniforms, + FxMaterial, + FxMaterialProps, +} from "../../materials/FxMaterial"; import { DEFAULT_TEXTURE } from "../../../libs/constants"; -import { mergeUniforms } from "three/src/renderers/shaders/UniformsUtils.js"; type PoissonUniforms = { isBounce: { value: boolean }; @@ -20,25 +23,25 @@ export class PoissonMaterial extends FxMaterial { iteration: number; - constructor(uniformValues = {}, parameters = {}) { + constructor({ uniformValues, materialParameters = {} }: FxMaterialProps) { super(); this.type = PoissonMaterial.type; - this.uniforms = mergeUniforms([ - this.uniforms, - { + this.uniforms = { + ...this.uniforms, + ...{ isBounce: { value: true }, pressure: { value: DEFAULT_TEXTURE }, divergence: { value: DEFAULT_TEXTURE }, }, - ]) as PoissonUniforms; + }; this.iteration = 32; this.resolveDefaultShaders(vertex.poisson, fragment); this.setUniformValues(uniformValues); - this.setValues(parameters); + this.setValues(materialParameters); } } diff --git a/packages/use-shader-fx/src/fxs/useFluid/materials/PressureMaterial.ts b/packages/use-shader-fx/src/fxs/useFluid/materials/PressureMaterial.ts index ff12abc0..880f3243 100644 --- a/packages/use-shader-fx/src/fxs/useFluid/materials/PressureMaterial.ts +++ b/packages/use-shader-fx/src/fxs/useFluid/materials/PressureMaterial.ts @@ -1,10 +1,13 @@ import * as THREE from "three"; import vertex from "./shaders/vertex"; import fragment from "./shaders/pressure.frag"; -import { FxMaterial, DefaultUniforms } from "../../materials/FxMaterial"; +import { + FxMaterial, + DefaultUniforms, + FxMaterialProps, +} from "../../materials/FxMaterial"; import { DEFAULT_TEXTURE } from "../../../libs/constants"; import { DeltaTime } from ".."; -import { mergeUniforms } from "three/src/renderers/shaders/UniformsUtils.js"; type PressureUniforms = { isBounce: { value: boolean }; @@ -20,24 +23,24 @@ export class PressureMaterial extends FxMaterial { uniforms!: PressureUniforms; - constructor(uniformValues = {}, parameters = {}) { + constructor({ uniformValues, materialParameters = {} }: FxMaterialProps) { super(); this.type = PressureMaterial.type; - this.uniforms = mergeUniforms([ - this.uniforms, - { + this.uniforms = { + ...this.uniforms, + ...{ isBounce: { value: true }, pressure: { value: DEFAULT_TEXTURE }, velocity: { value: DEFAULT_TEXTURE }, dt: { value: DeltaTime }, }, - ]) as PressureUniforms; + }; this.resolveDefaultShaders(vertex.main, fragment); this.setUniformValues(uniformValues); - this.setValues(parameters); + this.setValues(materialParameters); } } diff --git a/packages/use-shader-fx/src/fxs/useFluid/materials/SplatMaterial.ts b/packages/use-shader-fx/src/fxs/useFluid/materials/SplatMaterial.ts index b5387fb9..c54d262d 100644 --- a/packages/use-shader-fx/src/fxs/useFluid/materials/SplatMaterial.ts +++ b/packages/use-shader-fx/src/fxs/useFluid/materials/SplatMaterial.ts @@ -1,8 +1,11 @@ import * as THREE from "three"; import vertex from "./shaders/vertex"; import fragment from "./shaders/splat.frag"; -import { DefaultUniforms, FxMaterial } from "../../materials/FxMaterial"; -import { mergeUniforms } from "three/src/renderers/shaders/UniformsUtils.js"; +import { + DefaultUniforms, + FxMaterial, + FxMaterialProps, +} from "../../materials/FxMaterial"; type SplatUniforms = { force: { value: THREE.Vector2 }; @@ -19,27 +22,27 @@ export class SplatMaterial extends FxMaterial { uniforms!: SplatUniforms; - constructor(uniformValues = {}, parameters = {}) { + constructor({ uniformValues, materialParameters = {} }: FxMaterialProps) { super(); this.type = SplatMaterial.type; this.force = 30; - this.uniforms = mergeUniforms([ - this.uniforms, - { + this.uniforms = { + ...this.uniforms, + ...{ force: { value: new THREE.Vector2(0, 0) }, center: { value: new THREE.Vector2(0, 0) }, scale: { value: new THREE.Vector2(20, 20) }, }, - ]) as SplatUniforms; + }; this.resolveDefaultShaders(vertex.splat, fragment); this.blending = THREE.AdditiveBlending; this.setUniformValues(uniformValues); - this.setValues(parameters); + this.setValues(materialParameters); } } diff --git a/packages/use-shader-fx/src/fxs/useNoise/NoiseMaterial.ts b/packages/use-shader-fx/src/fxs/useNoise/NoiseMaterial.ts index 01f7a787..4ded8e72 100644 --- a/packages/use-shader-fx/src/fxs/useNoise/NoiseMaterial.ts +++ b/packages/use-shader-fx/src/fxs/useNoise/NoiseMaterial.ts @@ -4,8 +4,7 @@ import { BasicFxUniforms, FxBasicFxMaterial, } from "../materials/FxBasicFxMaterial"; -import { NoiseValues } from "."; -import { mergeUniforms } from "three/src/renderers/shaders/UniformsUtils.js"; +import { FxMaterialProps } from "../materials/FxMaterial"; type NoiseUniforms = { tick: { value: number }; @@ -23,16 +22,16 @@ export class NoiseMaterial extends FxBasicFxMaterial { return "NoiseMaterial"; } - uniforms: NoiseUniforms; + uniforms!: NoiseUniforms; - constructor(uniformValues?: NoiseValues, parameters = {}) { + constructor({ uniformValues, materialParameters = {} }: FxMaterialProps) { super(); this.type = NoiseMaterial.type; - this.uniforms = mergeUniforms([ - this.uniforms, - { + this.uniforms = { + ...this.uniforms, + ...{ tick: { value: 0.0 }, scale: { value: 0.03 }, timeStrength: { value: 0.3 }, @@ -42,10 +41,10 @@ export class NoiseMaterial extends FxBasicFxMaterial { warpDirection: { value: new THREE.Vector2(2.0, 2.0) }, warpStrength: { value: 8 }, }, - ]) as NoiseUniforms; + }; this.setUniformValues(uniformValues); - this.setValues(parameters); + this.setValues(materialParameters); this.setupBasicFxShaders(noiseVertex, noiseFragment); } diff --git a/packages/use-shader-fx/src/utils/useScene.ts b/packages/use-shader-fx/src/utils/useScene.ts index fe741ed6..33f4c2a2 100644 --- a/packages/use-shader-fx/src/utils/useScene.ts +++ b/packages/use-shader-fx/src/utils/useScene.ts @@ -3,12 +3,10 @@ import * as THREE from "three"; import { useObject3D } from "./useObject3D"; import { Size } from "../fxs/types"; import { useResolution } from "./useResolution"; -import { FxMaterial } from "../fxs/materials/FxMaterial"; +import { FxMaterial, FxMaterialProps } from "../fxs/materials/FxMaterial"; + +type MaterialConstructor = new (props: FxMaterialProps) => M; -type MaterialConstructor = new ( - uniformValues?: any, - materialParameters?: THREE.ShaderMaterialParameters -) => M; type GeometryConstructor = new ( width: number, height: number @@ -18,22 +16,19 @@ export const useScene = ({ size, dpr, material, - uniformValues, - materialParameters, geometry = THREE.PlaneGeometry, geometrySize, + ...materialProps }: { size: Size; dpr: number | false; material: MaterialConstructor; - uniformValues?: any; - materialParameters?: THREE.ShaderMaterialParameters; geometry?: GeometryConstructor; geometrySize?: { width: number; height: number; }; -}) => { +} & FxMaterialProps) => { const scene = useMemo(() => new THREE.Scene(), []); const _geometry = useMemo( @@ -42,8 +37,8 @@ export const useScene = ({ ); const _material = useMemo( - () => new material(uniformValues, materialParameters), - [material, uniformValues, materialParameters] + () => new material(materialProps), + [material, materialProps] ); const resolution = useResolution(size, dpr); diff --git a/todo b/todo index 1fe9021c..870637e2 100644 --- a/todo +++ b/todo @@ -6,5 +6,3 @@ - 流体まとめる - grain、暗くならないような工夫 - - From 452d5f07e67b8387e64a80b60ca050cafff61bf4 Mon Sep 17 00:00:00 2001 From: takuma-hmng8 Date: Tue, 24 Sep 2024 18:42:24 +0900 Subject: [PATCH 06/60] update --- todo | 2 ++ 1 file changed, 2 insertions(+) diff --git a/todo b/todo index 870637e2..09fa2132 100644 --- a/todo +++ b/todo @@ -1,4 +1,6 @@ - useBlankの設計まとめる +- usf wip + - blank つくって水面のやつで - pixelateつくる - 要件定義つくって、ろくくんに引き継ぐ From 5f4f8677e5662e51aabdc335235a1ce7739911b0 Mon Sep 17 00:00:00 2001 From: takuma-hmng8 Date: Mon, 30 Sep 2024 19:13:22 +0900 Subject: [PATCH 07/60] update --- app/v2/Playground.tsx | 78 ++++++++++++------- .../src/fxs/materials/FxBasicFxMaterial.ts | 14 +++- .../src/fxs/materials/FxMaterial.ts | 27 +++++-- .../useCoverTexture/CoverTextureMaterial.ts | 6 +- .../fxs/useCoverTexture/coverTexture.glsl.ts | 8 +- .../src/fxs/useCoverTexture/index.ts | 14 ++-- .../use-shader-fx/src/fxs/useFluid/index.ts | 4 +- .../useFluid/materials/AdvectionMaterial.ts | 2 +- .../useFluid/materials/DivergenceMaterial.ts | 2 +- .../fxs/useFluid/materials/PoissonMaterial.ts | 2 +- .../useFluid/materials/PressureMaterial.ts | 2 +- .../fxs/useFluid/materials/SplatMaterial.ts | 4 +- .../useFluid/materials/shaders/advection.frag | 2 - .../materials/shaders/divergence.frag | 2 - .../useFluid/materials/shaders/poisson.frag | 2 - .../useFluid/materials/shaders/pressure.frag | 2 - .../fxs/useFluid/materials/shaders/splat.frag | 2 - .../fxs/useFluid/materials/shaders/vertex.ts | 13 +--- .../src/fxs/useFluid/scenes/useAdvection.ts | 7 +- .../src/fxs/useFluid/scenes/useDivergence.ts | 11 +-- .../src/fxs/useFluid/scenes/usePoisson.ts | 11 +-- .../src/fxs/useFluid/scenes/usePressure.ts | 9 +-- .../src/fxs/useFluid/scenes/useSplat.ts | 10 +-- .../use-shader-fx/src/fxs/useNoise/index.ts | 12 +-- .../src/fxs/useNoise/noise.glsl.ts | 3 +- .../src/fxs/useRawBlank/RawBlankMaterial.ts | 11 +++ .../src/fxs/useRawBlank/index.ts | 78 +++++++++++++++++++ packages/use-shader-fx/src/index.js | 1 + .../shaders/{ShdaerLib.ts => ShaderLib.ts} | 11 ++- .../ShaderLib/basicFx_pars_fragment.glsl | 1 - .../ShaderLib/basicFx_pars_vertex.glsl | 1 - .../shaders/ShaderLib/basicFx_vertex.glsl | 1 - .../ShaderLib/default_pars_fragment.glsl | 1 + .../ShaderLib/default_pars_vertex.glsl | 1 + .../shaders/ShaderLib/default_vertex.glsl | 1 + .../src/libs/shaders/mergeShaderLib.ts | 42 ++++++++++ .../src/libs/shaders/resolveShaders.ts | 1 - packages/use-shader-fx/src/utils/getDpr.ts | 13 ---- packages/use-shader-fx/src/utils/useCamera.ts | 10 +-- packages/use-shader-fx/src/utils/useDpr.ts | 18 +++++ .../src/utils/{useScene.ts => useFxScene.ts} | 6 +- todo | 9 ++- 42 files changed, 303 insertions(+), 152 deletions(-) create mode 100644 packages/use-shader-fx/src/fxs/useRawBlank/RawBlankMaterial.ts create mode 100644 packages/use-shader-fx/src/fxs/useRawBlank/index.ts rename packages/use-shader-fx/src/libs/shaders/{ShdaerLib.ts => ShaderLib.ts} (64%) create mode 100644 packages/use-shader-fx/src/libs/shaders/ShaderLib/default_pars_fragment.glsl create mode 100644 packages/use-shader-fx/src/libs/shaders/ShaderLib/default_pars_vertex.glsl create mode 100644 packages/use-shader-fx/src/libs/shaders/ShaderLib/default_vertex.glsl create mode 100644 packages/use-shader-fx/src/libs/shaders/mergeShaderLib.ts delete mode 100644 packages/use-shader-fx/src/utils/getDpr.ts create mode 100644 packages/use-shader-fx/src/utils/useDpr.ts rename packages/use-shader-fx/src/utils/{useScene.ts => useFxScene.ts} (89%) diff --git a/app/v2/Playground.tsx b/app/v2/Playground.tsx index 20f505ea..b72f87e4 100644 --- a/app/v2/Playground.tsx +++ b/app/v2/Playground.tsx @@ -7,6 +7,7 @@ import { useNoise, useFluid, useCoverTexture, + useRawBlank, } from "@/packages/use-shader-fx/src"; import { FxMaterial } from "./FxMaterial"; import { @@ -35,7 +36,7 @@ const useFxResolver = (test: boolean) => { // const hooks = [useNoise, useNoise]; export const Playground = () => { - const { size } = useThree(); + const { size, viewport } = useThree(); const funkun_mov = useVideoTexture("/FT_Ch02-comp.mp4", { width: 1280, @@ -47,40 +48,64 @@ export const Playground = () => { "smoke.png", ]); - const noise = useNoise({ - size, - dpr: 0.2, - scale: 0.02, - // mixSrc: gear, - // mixSrcResolution: new THREE.Vector2(512, 512), - // mixSrcUvFactor: 0.2, - // mixSrcAlphaFactor: 0.1, - // mixSrcColorFactor: 0.4, - // mixDst: gear, - // mixDstResolution: new THREE.Vector2(512, 512), - // mixDstUvFactor: 0.3, - // mixDstAlphaFactor: 1, - // mixDstColorFactor: 0, - }); + // const rawBlank = useRawBlank({ + // size, + // dpr: 1, + // uniforms: { + // testTex: { value: funkun_mov }, + // }, + // fragmentShader: ` + // uniform sampler2D testTex; + // void main() { + // gl_FragColor = texture2D(testTex, vUv); + // } + // `, + // vertexShader: ` + // void main() { + // gl_Position = vec4(position, 1.0); + // } + // `, + // }); + + // const noise = useNoise({ + // size, + // dpr: 0.2, + // scale: 0.02, + // // mixSrc: gear, + // // mixSrcResolution: new THREE.Vector2(512, 512), + // // mixSrcUvFactor: 0.2, + // // mixSrcAlphaFactor: 0.1, + // // mixSrcColorFactor: 0.4, + // // mixDst: gear, + // // mixDstResolution: new THREE.Vector2(512, 512), + // // mixDstUvFactor: 0.3, + // // mixDstAlphaFactor: 1, + // // mixDstColorFactor: 0, + // }); const fluid = useFluid({ size, - dpr: 0.1, + dpr: 0.25, }); const cover = useCoverTexture({ size, - dpr: 2, + dpr: 0.25, src: funkun_mov, textureResolution: new THREE.Vector2(1280, 720), - // mixSrc: fluid.texture, + mixSrc: smoke, + mixDstResolution: new THREE.Vector2(512, 512), + mixDstUvFactor: 0.9, + mixDstAlphaFactor: 0.1, + mixDstColorFactor: 0.4, mixSrcResolution: new THREE.Vector2(512, 512), - mixSrcUvFactor: 0.05, + mixSrcUvFactor: 0.8, mixSrcAlphaFactor: 0.1, mixSrcColorFactor: 0.0, }); useFrame((state) => { + // cover.render(state); // cover.render(state); fluid.render(state); // noise.render(state); @@ -95,12 +120,14 @@ export const Playground = () => { return ( <> + {/* + + + */} - {/* - */} - - + {/* */} + {/* */} { metalness={0.1} color={0xffffff} /> - {/* */} @@ -122,7 +148,7 @@ export const Playground = () => { /> - {/* */} + diff --git a/packages/use-shader-fx/src/fxs/materials/FxBasicFxMaterial.ts b/packages/use-shader-fx/src/fxs/materials/FxBasicFxMaterial.ts index 53a8dbb3..48b4a843 100644 --- a/packages/use-shader-fx/src/fxs/materials/FxBasicFxMaterial.ts +++ b/packages/use-shader-fx/src/fxs/materials/FxBasicFxMaterial.ts @@ -5,6 +5,7 @@ import { BasicFxFlag, BasicFxLib, } from "./BasicFxLib"; +import { mergeShaderLib } from "../../libs/shaders/mergeShaderLib"; export class FxBasicFxMaterial extends FxMaterial { basicFxFlag: BasicFxFlag; @@ -60,7 +61,7 @@ export class FxBasicFxMaterial extends FxMaterial { if (_cache !== this.programCache) { this.updateBasicFxPrefix(); this.updateBasicFxShader(); - this.needsUpdate = true; // same as this.version++ + this.version++; // same as this.needsUpdate = true; } } @@ -78,10 +79,15 @@ export class FxBasicFxMaterial extends FxMaterial { setupBasicFxShaders(vertexShader?: string, fragmentShader?: string) { this.updateBasicFxPrefix(); - this.resolveDefaultShaders( - vertexShader || this.vertexShaderCache, - fragmentShader || this.fragmentShaderCache + + const [vertex, fragment] = mergeShaderLib( + vertexShader, + fragmentShader, + "basicFx" ); + + this.setupDefaultShaders(vertex, fragment); + this.vertexShaderCache = this.vertexShader; this.fragmentShaderCache = this.fragmentShader; this.updateBasicFxShader(); diff --git a/packages/use-shader-fx/src/fxs/materials/FxMaterial.ts b/packages/use-shader-fx/src/fxs/materials/FxMaterial.ts index 0069bd85..f4bf0d17 100644 --- a/packages/use-shader-fx/src/fxs/materials/FxMaterial.ts +++ b/packages/use-shader-fx/src/fxs/materials/FxMaterial.ts @@ -1,5 +1,6 @@ import * as THREE from "three"; import { resolveIncludes } from "../../libs/shaders/resolveShaders"; +import { mergeShaderLib } from "../../libs/shaders/mergeShaderLib"; export type DefaultUniforms = { resolution: { value: THREE.Vector2 }; @@ -8,14 +9,17 @@ export type DefaultUniforms = { maxAspect: { value: THREE.Vector2 }; }; -export type FxMaterialProps = { - uniformValues?: T; - materialParameters?: {}; +export type ShaderWithUniforms = { uniforms?: { [uniform: string]: THREE.IUniform }; vertexShader?: string; fragmentShader?: string; }; +export type FxMaterialProps = { + uniformValues?: T; + materialParameters?: {}; +} & ShaderWithUniforms; + export class FxMaterial extends THREE.ShaderMaterial { constructor({ uniformValues, @@ -34,13 +38,13 @@ export class FxMaterial extends THREE.ShaderMaterial { ...uniforms, } as DefaultUniforms; - this.vertexShader = vertexShader || this.vertexShader; - this.fragmentShader = fragmentShader || this.fragmentShader; + this.setupDefaultShaders(vertexShader, fragmentShader); this.setUniformValues(uniformValues); this.setValues(materialParameters); } + /** This is updated in useFxScene */ updateResolution(resolution: THREE.Vector2) { const { width, height } = resolution; const maxAspect = Math.max(width, height); @@ -50,9 +54,16 @@ export class FxMaterial extends THREE.ShaderMaterial { this.uniforms.maxAspect.value.set(maxAspect / width, maxAspect / height); } - resolveDefaultShaders(vertexShader: string, fragmentShader: string) { - this.vertexShader = resolveIncludes(vertexShader); - this.fragmentShader = resolveIncludes(fragmentShader); + setupDefaultShaders(vertexShader?: string, fragmentShader?: string) { + const [vertex, fragment] = mergeShaderLib( + vertexShader, + fragmentShader, + "default" + ); + this.vertexShader = vertex ? resolveIncludes(vertex) : this.vertexShader; + this.fragmentShader = fragment + ? resolveIncludes(fragment) + : this.fragmentShader; } setUniformValues(values?: { [key: string]: any }) { diff --git a/packages/use-shader-fx/src/fxs/useCoverTexture/CoverTextureMaterial.ts b/packages/use-shader-fx/src/fxs/useCoverTexture/CoverTextureMaterial.ts index e44f1475..d48b0a95 100644 --- a/packages/use-shader-fx/src/fxs/useCoverTexture/CoverTextureMaterial.ts +++ b/packages/use-shader-fx/src/fxs/useCoverTexture/CoverTextureMaterial.ts @@ -1,11 +1,9 @@ import * as THREE from "three"; import { fragment, vertex } from "./coverTexture.glsl"; -import { - BasicFxUniforms, - FxBasicFxMaterial, -} from "../materials/FxBasicFxMaterial"; +import { FxBasicFxMaterial } from "../materials/FxBasicFxMaterial"; import { CoverTextureValues } from "."; import { FxMaterialProps } from "../materials/FxMaterial"; +import { BasicFxUniforms } from "../materials/BasicFxLib"; type CoverTextureUniforms = { src: { value: THREE.Texture | null }; diff --git a/packages/use-shader-fx/src/fxs/useCoverTexture/coverTexture.glsl.ts b/packages/use-shader-fx/src/fxs/useCoverTexture/coverTexture.glsl.ts index a0e3e3a2..12df916b 100644 --- a/packages/use-shader-fx/src/fxs/useCoverTexture/coverTexture.glsl.ts +++ b/packages/use-shader-fx/src/fxs/useCoverTexture/coverTexture.glsl.ts @@ -1,14 +1,10 @@ -import { ShaderLib } from "../../libs/shaders/ShdaerLib"; +import { ShaderLib } from "../../libs/shaders/ShaderLib"; export const vertex = ` - ${ShaderLib.basicFx_pars_vertex} - uniform vec2 textureResolution; varying vec2 vCoverTextureUv; void main() { - ${ShaderLib.basicFx_vertex} - float textureAspect = textureResolution.x / textureResolution.y; vec2 aspectRatio = vec2( min(aspectRatio / textureAspect, 1.0), @@ -21,8 +17,6 @@ export const vertex = ` `; export const fragment = ` - ${ShaderLib.basicFx_pars_fragment} - uniform sampler2D src; varying vec2 vCoverTextureUv; diff --git a/packages/use-shader-fx/src/fxs/useCoverTexture/index.ts b/packages/use-shader-fx/src/fxs/useCoverTexture/index.ts index aaeb77de..11e74ebd 100644 --- a/packages/use-shader-fx/src/fxs/useCoverTexture/index.ts +++ b/packages/use-shader-fx/src/fxs/useCoverTexture/index.ts @@ -1,12 +1,11 @@ import * as THREE from "three"; -import { useCallback, useMemo } from "react"; -import { useCamera } from "../../utils/useCamera"; +import { useCallback } from "react"; import { useSingleFBO } from "../../utils/useSingleFBO"; import { HooksProps, HooksReturn } from "../types"; -import { getDpr } from "../../utils/getDpr"; +import { useDpr } from "../../utils/useDpr"; import { RootState } from "../types"; import { CoverTextureMaterial } from "./CoverTextureMaterial"; -import { useScene } from "../../utils/useScene"; +import { useFxScene } from "../../utils/useFxScene"; import { BasicFxValues } from "../materials/BasicFxLib"; export type CoverTextureValues = { @@ -16,8 +15,6 @@ export type CoverTextureValues = { /** * @link https://github.com/FunTechInc/use-shader-fx?tab=readme-ov-file#usage - * - * It is a basic value noise with `fbm` and `domain warping` */ export const useCoverTexture = ({ size, @@ -30,9 +27,9 @@ export const useCoverTexture = ({ CoverTextureValues, CoverTextureMaterial > => { - const _dpr = getDpr(dpr); + const _dpr = useDpr(dpr); - const { scene, material } = useScene({ + const { scene, material, camera } = useFxScene({ size, dpr: _dpr.shader, material: CoverTextureMaterial, @@ -40,7 +37,6 @@ export const useCoverTexture = ({ materialParameters, }); - const camera = useCamera(size); const [renderTarget, updateRenderTarget] = useSingleFBO({ scene, camera, diff --git a/packages/use-shader-fx/src/fxs/useFluid/index.ts b/packages/use-shader-fx/src/fxs/useFluid/index.ts index 8d7f9700..fb5e0d5b 100644 --- a/packages/use-shader-fx/src/fxs/useFluid/index.ts +++ b/packages/use-shader-fx/src/fxs/useFluid/index.ts @@ -2,7 +2,7 @@ import * as THREE from "three"; import { useCallback, useMemo } from "react"; import { UseFboProps, useSingleFBO } from "../../utils/useSingleFBO"; import { HooksProps, HooksReturn } from "../types"; -import { getDpr } from "../../utils/getDpr"; +import { useDpr } from "../../utils/useDpr"; import { RootState } from "../types"; import { useDoubleFBO } from "../../utils/useDoubleFBO"; import { useAdvection } from "./scenes/useAdvection"; @@ -34,7 +34,7 @@ export const useFluid = ({ renderTargetOptions, ...values }: HooksProps & FluidValues): HooksReturn => { - const _dpr = getDpr(dpr); + const _dpr = useDpr(dpr); // fbos const fboProps = useMemo( diff --git a/packages/use-shader-fx/src/fxs/useFluid/materials/AdvectionMaterial.ts b/packages/use-shader-fx/src/fxs/useFluid/materials/AdvectionMaterial.ts index f1c8b9bc..da927456 100644 --- a/packages/use-shader-fx/src/fxs/useFluid/materials/AdvectionMaterial.ts +++ b/packages/use-shader-fx/src/fxs/useFluid/materials/AdvectionMaterial.ts @@ -34,7 +34,7 @@ export class AdvectionMaterial extends FxMaterial { }, }; - this.resolveDefaultShaders(vertex.advection, fragment); + this.setupDefaultShaders(vertex.advection, fragment); this.setUniformValues(uniformValues); this.setValues(materialParameters); diff --git a/packages/use-shader-fx/src/fxs/useFluid/materials/DivergenceMaterial.ts b/packages/use-shader-fx/src/fxs/useFluid/materials/DivergenceMaterial.ts index 5f6bfb31..ba0b5e77 100644 --- a/packages/use-shader-fx/src/fxs/useFluid/materials/DivergenceMaterial.ts +++ b/packages/use-shader-fx/src/fxs/useFluid/materials/DivergenceMaterial.ts @@ -36,7 +36,7 @@ export class DivergenceMaterial extends FxMaterial { }, }; - this.resolveDefaultShaders(vertex.main, fragment); + this.setupDefaultShaders(vertex.main, fragment); this.setUniformValues(uniformValues); this.setValues(materialParameters); diff --git a/packages/use-shader-fx/src/fxs/useFluid/materials/PoissonMaterial.ts b/packages/use-shader-fx/src/fxs/useFluid/materials/PoissonMaterial.ts index 51c29a18..633c7be8 100644 --- a/packages/use-shader-fx/src/fxs/useFluid/materials/PoissonMaterial.ts +++ b/packages/use-shader-fx/src/fxs/useFluid/materials/PoissonMaterial.ts @@ -39,7 +39,7 @@ export class PoissonMaterial extends FxMaterial { this.iteration = 32; - this.resolveDefaultShaders(vertex.poisson, fragment); + this.setupDefaultShaders(vertex.poisson, fragment); this.setUniformValues(uniformValues); this.setValues(materialParameters); diff --git a/packages/use-shader-fx/src/fxs/useFluid/materials/PressureMaterial.ts b/packages/use-shader-fx/src/fxs/useFluid/materials/PressureMaterial.ts index 880f3243..847ccb5a 100644 --- a/packages/use-shader-fx/src/fxs/useFluid/materials/PressureMaterial.ts +++ b/packages/use-shader-fx/src/fxs/useFluid/materials/PressureMaterial.ts @@ -38,7 +38,7 @@ export class PressureMaterial extends FxMaterial { }, }; - this.resolveDefaultShaders(vertex.main, fragment); + this.setupDefaultShaders(vertex.main, fragment); this.setUniformValues(uniformValues); this.setValues(materialParameters); diff --git a/packages/use-shader-fx/src/fxs/useFluid/materials/SplatMaterial.ts b/packages/use-shader-fx/src/fxs/useFluid/materials/SplatMaterial.ts index c54d262d..b31f135d 100644 --- a/packages/use-shader-fx/src/fxs/useFluid/materials/SplatMaterial.ts +++ b/packages/use-shader-fx/src/fxs/useFluid/materials/SplatMaterial.ts @@ -27,7 +27,7 @@ export class SplatMaterial extends FxMaterial { this.type = SplatMaterial.type; - this.force = 30; + this.force = 15; this.uniforms = { ...this.uniforms, @@ -38,7 +38,7 @@ export class SplatMaterial extends FxMaterial { }, }; - this.resolveDefaultShaders(vertex.splat, fragment); + this.setupDefaultShaders(vertex.splat, fragment); this.blending = THREE.AdditiveBlending; diff --git a/packages/use-shader-fx/src/fxs/useFluid/materials/shaders/advection.frag b/packages/use-shader-fx/src/fxs/useFluid/materials/shaders/advection.frag index 0349cef5..03cdfe0f 100644 --- a/packages/use-shader-fx/src/fxs/useFluid/materials/shaders/advection.frag +++ b/packages/use-shader-fx/src/fxs/useFluid/materials/shaders/advection.frag @@ -1,5 +1,3 @@ -#usf - uniform float dt; uniform sampler2D velocity; diff --git a/packages/use-shader-fx/src/fxs/useFluid/materials/shaders/divergence.frag b/packages/use-shader-fx/src/fxs/useFluid/materials/shaders/divergence.frag index 155d4d6e..9450edd7 100644 --- a/packages/use-shader-fx/src/fxs/useFluid/materials/shaders/divergence.frag +++ b/packages/use-shader-fx/src/fxs/useFluid/materials/shaders/divergence.frag @@ -1,5 +1,3 @@ -#usf - uniform float dt; uniform sampler2D velocity; diff --git a/packages/use-shader-fx/src/fxs/useFluid/materials/shaders/poisson.frag b/packages/use-shader-fx/src/fxs/useFluid/materials/shaders/poisson.frag index 147776ed..67590e0a 100644 --- a/packages/use-shader-fx/src/fxs/useFluid/materials/shaders/poisson.frag +++ b/packages/use-shader-fx/src/fxs/useFluid/materials/shaders/poisson.frag @@ -1,5 +1,3 @@ -#usf - uniform sampler2D pressure; uniform sampler2D divergence; diff --git a/packages/use-shader-fx/src/fxs/useFluid/materials/shaders/pressure.frag b/packages/use-shader-fx/src/fxs/useFluid/materials/shaders/pressure.frag index bfcb441a..2a656c63 100644 --- a/packages/use-shader-fx/src/fxs/useFluid/materials/shaders/pressure.frag +++ b/packages/use-shader-fx/src/fxs/useFluid/materials/shaders/pressure.frag @@ -1,5 +1,3 @@ -#usf - uniform float dt; uniform sampler2D pressure; uniform sampler2D velocity; diff --git a/packages/use-shader-fx/src/fxs/useFluid/materials/shaders/splat.frag b/packages/use-shader-fx/src/fxs/useFluid/materials/shaders/splat.frag index c1ac4c1f..a3900824 100644 --- a/packages/use-shader-fx/src/fxs/useFluid/materials/shaders/splat.frag +++ b/packages/use-shader-fx/src/fxs/useFluid/materials/shaders/splat.frag @@ -1,5 +1,3 @@ -#usf - uniform vec2 force; uniform vec2 center; diff --git a/packages/use-shader-fx/src/fxs/useFluid/materials/shaders/vertex.ts b/packages/use-shader-fx/src/fxs/useFluid/materials/shaders/vertex.ts index 7f7f5ca1..dec2d5ee 100644 --- a/packages/use-shader-fx/src/fxs/useFluid/materials/shaders/vertex.ts +++ b/packages/use-shader-fx/src/fxs/useFluid/materials/shaders/vertex.ts @@ -1,7 +1,3 @@ -const base = ` - #usf -`; - const boxVarying = ` uniform bool isBounce; varying vec2 vL; @@ -19,7 +15,7 @@ const getPosition = (isBounce: boolean = true) => { : "1.-texelSize*2." }; pos.xy = pos.xy * scale; - vUv = vec2(.5)+(pos.xy)*.5; + vUv = vec2(.5)+(pos.xy)*.5; `; }; @@ -34,7 +30,6 @@ const getBoxCompute = (diff: string) => { const vertex = { main: ` - ${base} ${boxVarying} void main(){ @@ -46,7 +41,6 @@ const vertex = { } `, poisson: ` - ${base} ${boxVarying} void main(){ @@ -58,19 +52,16 @@ const vertex = { } `, advection: ` - ${base} void main(){ ${getPosition(false)} gl_Position = vec4(pos, 1.0); } `, splat: ` - ${base} uniform vec2 center; uniform vec2 scale; - void main(){ + void main(){ vec2 pos = position.xy * scale * 2.0 * texelSize + center; - vUv = uv; gl_Position = vec4(pos, 0.0, 1.0); } `, diff --git a/packages/use-shader-fx/src/fxs/useFluid/scenes/useAdvection.ts b/packages/use-shader-fx/src/fxs/useFluid/scenes/useAdvection.ts index 248ce00d..09cb0bbc 100644 --- a/packages/use-shader-fx/src/fxs/useFluid/scenes/useAdvection.ts +++ b/packages/use-shader-fx/src/fxs/useFluid/scenes/useAdvection.ts @@ -1,10 +1,9 @@ import * as THREE from "three"; import { useCallback } from "react"; -import { useCamera } from "../../../utils/useCamera"; import { RootState, Size } from "../../types"; import { AdvectionMaterial } from "../materials/AdvectionMaterial"; import { SingleFBOUpdateFunction } from "../../../utils/useSingleFBO"; -import { useScene } from "../../../utils/useScene"; +import { useFxScene } from "../../../utils/useFxScene"; export const useAdvection = ( { @@ -18,15 +17,13 @@ export const useAdvection = ( }, updateRenderTarget: SingleFBOUpdateFunction ) => { - const { scene, material } = useScene({ + const { scene, material, camera } = useFxScene({ size, dpr, material: AdvectionMaterial, uniformValues: values, }); - const camera = useCamera(size); - const render = useCallback( (rootState: RootState) => { const { gl } = rootState; diff --git a/packages/use-shader-fx/src/fxs/useFluid/scenes/useDivergence.ts b/packages/use-shader-fx/src/fxs/useFluid/scenes/useDivergence.ts index 5ce3fe00..dca95c45 100644 --- a/packages/use-shader-fx/src/fxs/useFluid/scenes/useDivergence.ts +++ b/packages/use-shader-fx/src/fxs/useFluid/scenes/useDivergence.ts @@ -1,10 +1,9 @@ import * as THREE from "three"; -import { useCallback, useMemo } from "react"; -import { useCamera } from "../../../utils/useCamera"; -import { Dpr, RootState, Size } from "../../types"; +import { useCallback } from "react"; +import { RootState, Size } from "../../types"; import { SingleFBOUpdateFunction } from "../../../utils/useSingleFBO"; import { DivergenceMaterial } from "../materials/DivergenceMaterial"; -import { useScene } from "../../../utils/useScene"; +import { useFxScene } from "../../../utils/useFxScene"; export const useDivergence = ( { @@ -18,15 +17,13 @@ export const useDivergence = ( }, updateRenderTarget: SingleFBOUpdateFunction ) => { - const { scene, material } = useScene({ + const { scene, material, camera } = useFxScene({ size, dpr, material: DivergenceMaterial, uniformValues: values, }); - const camera = useCamera(size); - const render = useCallback( (rootState: RootState) => { const { gl } = rootState; diff --git a/packages/use-shader-fx/src/fxs/useFluid/scenes/usePoisson.ts b/packages/use-shader-fx/src/fxs/useFluid/scenes/usePoisson.ts index 89e35578..1d413bf1 100644 --- a/packages/use-shader-fx/src/fxs/useFluid/scenes/usePoisson.ts +++ b/packages/use-shader-fx/src/fxs/useFluid/scenes/usePoisson.ts @@ -1,10 +1,9 @@ import * as THREE from "three"; -import { useCallback, useMemo } from "react"; -import { useCamera } from "../../../utils/useCamera"; -import { Dpr, RootState, Size } from "../../types"; +import { useCallback } from "react"; +import { RootState, Size } from "../../types"; import { SingleFBOUpdateFunction } from "../../../utils/useSingleFBO"; import { PoissonMaterial } from "../materials/PoissonMaterial"; -import { useScene } from "../../../utils/useScene"; +import { useFxScene } from "../../../utils/useFxScene"; export const usePoisson = ( { @@ -18,15 +17,13 @@ export const usePoisson = ( }, updateRenderTarget: SingleFBOUpdateFunction ) => { - const { scene, material } = useScene({ + const { scene, material, camera } = useFxScene({ size, dpr, material: PoissonMaterial, uniformValues: values, }); - const camera = useCamera(size); - const render = useCallback( (rootState: RootState) => { const { gl } = rootState; diff --git a/packages/use-shader-fx/src/fxs/useFluid/scenes/usePressure.ts b/packages/use-shader-fx/src/fxs/useFluid/scenes/usePressure.ts index 21f26a89..74667a23 100644 --- a/packages/use-shader-fx/src/fxs/useFluid/scenes/usePressure.ts +++ b/packages/use-shader-fx/src/fxs/useFluid/scenes/usePressure.ts @@ -1,10 +1,9 @@ import * as THREE from "three"; -import { useCallback, useMemo } from "react"; -import { useCamera } from "../../../utils/useCamera"; +import { useCallback } from "react"; import { RootState, Size } from "../../types"; import { SingleFBOUpdateFunction } from "../../../utils/useSingleFBO"; import { PressureMaterial } from "../materials/PressureMaterial"; -import { useScene } from "../../../utils/useScene"; +import { useFxScene } from "../../../utils/useFxScene"; export const usePressure = ( { @@ -19,15 +18,13 @@ export const usePressure = ( }, updateRenderTarget: SingleFBOUpdateFunction ) => { - const { scene, material } = useScene({ + const { scene, material, camera } = useFxScene({ size, dpr, material: PressureMaterial, uniformValues: values, }); - const camera = useCamera(size); - const render = useCallback( (rootState: RootState) => { const { gl } = rootState; diff --git a/packages/use-shader-fx/src/fxs/useFluid/scenes/useSplat.ts b/packages/use-shader-fx/src/fxs/useFluid/scenes/useSplat.ts index 67904f98..87bad285 100644 --- a/packages/use-shader-fx/src/fxs/useFluid/scenes/useSplat.ts +++ b/packages/use-shader-fx/src/fxs/useFluid/scenes/useSplat.ts @@ -1,11 +1,9 @@ -import * as THREE from "three"; -import { useCallback, useMemo } from "react"; -import { useCamera } from "../../../utils/useCamera"; +import { useCallback } from "react"; import { RootState, Size } from "../../types"; import { SingleFBOUpdateFunction } from "../../../utils/useSingleFBO"; import { SplatMaterial } from "../materials/SplatMaterial"; import { usePointer } from "../../../misc/usePointer"; -import { useScene } from "../../../utils/useScene"; +import { useFxScene } from "../../../utils/useFxScene"; export const useSplat = ( { @@ -17,7 +15,7 @@ export const useSplat = ( }, updateRenderTarget: SingleFBOUpdateFunction ) => { - const { scene, material } = useScene({ + const { scene, material, camera } = useFxScene({ size, dpr, material: SplatMaterial, @@ -27,8 +25,6 @@ export const useSplat = ( }, }); - const camera = useCamera(size); - const updatePointer = usePointer(); const render = useCallback( diff --git a/packages/use-shader-fx/src/fxs/useNoise/index.ts b/packages/use-shader-fx/src/fxs/useNoise/index.ts index 7efc77c7..dc04e15d 100644 --- a/packages/use-shader-fx/src/fxs/useNoise/index.ts +++ b/packages/use-shader-fx/src/fxs/useNoise/index.ts @@ -3,11 +3,11 @@ import { useCallback } from "react"; import { useCamera } from "../../utils/useCamera"; import { useSingleFBO } from "../../utils/useSingleFBO"; import { HooksProps, HooksReturn } from "../types"; -import { getDpr } from "../../utils/getDpr"; +import { getDpr } from "../../utils/useDpr"; import { RootState } from "../types"; import { NoiseMaterial } from "./NoiseMaterial"; -import { useScene } from "../../utils/useScene"; -import { BasicFxValues } from "../materials/FxBasicFxMaterial"; +import { useScene } from "../../utils/useFxScene"; +import { BasicFxValues } from "../materials/BasicFxLib"; export type NoiseValues = { /** noise scale , default : `0.004` */ @@ -24,8 +24,8 @@ export type NoiseValues = { warpDirection?: THREE.Vector2; /** strength of domain warping , default : `8.0` */ warpStrength?: number; - /** you can get into the rhythm ♪ , default : `false` */ - beat?: number | false; + /** useBeatを渡せば、リズムを変えられる。 */ + tick?: number; } & BasicFxValues; /** @@ -73,7 +73,7 @@ export const useNoise = ({ const { gl, clock } = rootState; newValues && setValues(newValues); material.uniforms.tick.value = - newValues?.beat || clock.getElapsedTime(); + newValues?.tick || clock.getElapsedTime(); material.updateBasicFx(); diff --git a/packages/use-shader-fx/src/fxs/useNoise/noise.glsl.ts b/packages/use-shader-fx/src/fxs/useNoise/noise.glsl.ts index f7f93fdf..95506cfc 100644 --- a/packages/use-shader-fx/src/fxs/useNoise/noise.glsl.ts +++ b/packages/use-shader-fx/src/fxs/useNoise/noise.glsl.ts @@ -1,4 +1,4 @@ -import { ShaderLib } from "../../libs/shaders/ShdaerLib"; +import { ShaderLib } from "../../libs/shaders/ShaderLib"; export const noiseVertex = ` ${ShaderLib.basicFx_pars_vertex} @@ -9,7 +9,6 @@ export const noiseVertex = ` `; export const noiseFragment = ` - precision highp float; precision highp int; ${ShaderLib.basicFx_pars_fragment} diff --git a/packages/use-shader-fx/src/fxs/useRawBlank/RawBlankMaterial.ts b/packages/use-shader-fx/src/fxs/useRawBlank/RawBlankMaterial.ts new file mode 100644 index 00000000..d813626e --- /dev/null +++ b/packages/use-shader-fx/src/fxs/useRawBlank/RawBlankMaterial.ts @@ -0,0 +1,11 @@ +import { FxMaterial, FxMaterialProps } from "../materials/FxMaterial"; + +export class RawBlankMaterial extends FxMaterial { + static get type() { + return "RawBlankMaterial"; + } + constructor(props: FxMaterialProps) { + super(props); + this.type = RawBlankMaterial.type; + } +} diff --git a/packages/use-shader-fx/src/fxs/useRawBlank/index.ts b/packages/use-shader-fx/src/fxs/useRawBlank/index.ts new file mode 100644 index 00000000..e983365c --- /dev/null +++ b/packages/use-shader-fx/src/fxs/useRawBlank/index.ts @@ -0,0 +1,78 @@ +import * as THREE from "three"; +import { useCallback } from "react"; +import { useSingleFBO } from "../../utils/useSingleFBO"; +import { HooksProps, HooksReturn } from "../types"; +import { useDpr } from "../../utils/useDpr"; +import { RootState } from "../types"; +import { RawBlankMaterial } from "./RawBlankMaterial"; +import { useFxScene } from "../../utils/useFxScene"; +import { ShaderWithUniforms } from "../materials/FxMaterial"; + +export type RawBlankValues = {}; + +type RawBlankConfig = ShaderWithUniforms; + +/** + * @link https://github.com/FunTechInc/use-shader-fx?tab=readme-ov-file#usage + */ +export const useRawBlank = ({ + size, + dpr, + sizeUpdate, + renderTargetOptions, + materialParameters, + uniforms, + vertexShader, + fragmentShader, + ...uniformValues +}: HooksProps & RawBlankValues & RawBlankConfig): HooksReturn< + RawBlankValues, + RawBlankMaterial +> => { + const _dpr = useDpr(dpr); + + const { scene, material, camera } = useFxScene({ + size, + dpr: _dpr.shader, + material: RawBlankMaterial, + uniformValues, + materialParameters, + uniforms, + vertexShader, + fragmentShader, + }); + + const [renderTarget, updateRenderTarget] = useSingleFBO({ + scene, + camera, + size, + dpr: _dpr.fbo, + sizeUpdate, + ...renderTargetOptions, + }); + + const setValues = useCallback( + (newValues: RawBlankValues) => { + material.setUniformValues(newValues); + }, + [material] + ); + + const render = useCallback( + (rootState: RootState, newValues?: RawBlankValues) => { + const { gl } = rootState; + newValues && setValues(newValues); + return updateRenderTarget({ gl }); + }, + [setValues, updateRenderTarget] + ); + + return { + render, + setValues, + texture: renderTarget.texture, + material, + scene, + camera, + }; +}; diff --git a/packages/use-shader-fx/src/index.js b/packages/use-shader-fx/src/index.js index 095546d4..da3740ac 100644 --- a/packages/use-shader-fx/src/index.js +++ b/packages/use-shader-fx/src/index.js @@ -4,3 +4,4 @@ FXs export * from "./fxs/useNoise"; export * from "./fxs/useFluid"; export * from "./fxs/useCoverTexture"; +export * from "./fxs/useRawBlank"; diff --git a/packages/use-shader-fx/src/libs/shaders/ShdaerLib.ts b/packages/use-shader-fx/src/libs/shaders/ShaderLib.ts similarity index 64% rename from packages/use-shader-fx/src/libs/shaders/ShdaerLib.ts rename to packages/use-shader-fx/src/libs/shaders/ShaderLib.ts index 60be5962..44d39c10 100644 --- a/packages/use-shader-fx/src/libs/shaders/ShdaerLib.ts +++ b/packages/use-shader-fx/src/libs/shaders/ShaderLib.ts @@ -3,13 +3,19 @@ import basicFx_fragment_begin from "./ShaderLib/basicFx_fragment_begin.glsl"; import basicFx_fragment_end from "./ShaderLib/basicFx_fragment_end.glsl"; import basicFx_pars_fragment from "./ShaderLib/basicFx_pars_fragment.glsl"; import basicFx_pars_vertex from "./ShaderLib/basicFx_pars_vertex.glsl"; +import default_pars_fragment from "./ShaderLib/default_pars_fragment.glsl"; +import default_pars_vertex from "./ShaderLib/default_pars_vertex.glsl"; +import default_vertex from "./ShaderLib/default_vertex.glsl"; export type ShaderLibTypes = | "basicFx_vertex" | "basicFx_fragment_begin" | "basicFx_fragment_end" | "basicFx_pars_fragment" - | "basicFx_pars_vertex"; + | "basicFx_pars_vertex" + | "default_pars_fragment" + | "default_pars_vertex" + | "default_vertex"; export const ShaderLib: { [K in ShaderLibTypes]: string } = Object.freeze({ basicFx_vertex, @@ -17,4 +23,7 @@ export const ShaderLib: { [K in ShaderLibTypes]: string } = Object.freeze({ basicFx_fragment_end, basicFx_pars_fragment, basicFx_pars_vertex, + default_pars_fragment, + default_pars_vertex, + default_vertex, }); diff --git a/packages/use-shader-fx/src/libs/shaders/ShaderLib/basicFx_pars_fragment.glsl b/packages/use-shader-fx/src/libs/shaders/ShaderLib/basicFx_pars_fragment.glsl index dfacb117..d559b6ba 100644 --- a/packages/use-shader-fx/src/libs/shaders/ShaderLib/basicFx_pars_fragment.glsl +++ b/packages/use-shader-fx/src/libs/shaders/ShaderLib/basicFx_pars_fragment.glsl @@ -1,3 +1,2 @@ -#usf #usf #usf \ No newline at end of file diff --git a/packages/use-shader-fx/src/libs/shaders/ShaderLib/basicFx_pars_vertex.glsl b/packages/use-shader-fx/src/libs/shaders/ShaderLib/basicFx_pars_vertex.glsl index 875e8f9c..9d1bb8d8 100644 --- a/packages/use-shader-fx/src/libs/shaders/ShaderLib/basicFx_pars_vertex.glsl +++ b/packages/use-shader-fx/src/libs/shaders/ShaderLib/basicFx_pars_vertex.glsl @@ -1,3 +1,2 @@ -#usf #usf #usf \ No newline at end of file diff --git a/packages/use-shader-fx/src/libs/shaders/ShaderLib/basicFx_vertex.glsl b/packages/use-shader-fx/src/libs/shaders/ShaderLib/basicFx_vertex.glsl index 2df65a30..30529c1e 100644 --- a/packages/use-shader-fx/src/libs/shaders/ShaderLib/basicFx_vertex.glsl +++ b/packages/use-shader-fx/src/libs/shaders/ShaderLib/basicFx_vertex.glsl @@ -1,3 +1,2 @@ -vUv = uv; #usf #usf \ No newline at end of file diff --git a/packages/use-shader-fx/src/libs/shaders/ShaderLib/default_pars_fragment.glsl b/packages/use-shader-fx/src/libs/shaders/ShaderLib/default_pars_fragment.glsl new file mode 100644 index 00000000..8971a903 --- /dev/null +++ b/packages/use-shader-fx/src/libs/shaders/ShaderLib/default_pars_fragment.glsl @@ -0,0 +1 @@ +#usf \ No newline at end of file diff --git a/packages/use-shader-fx/src/libs/shaders/ShaderLib/default_pars_vertex.glsl b/packages/use-shader-fx/src/libs/shaders/ShaderLib/default_pars_vertex.glsl new file mode 100644 index 00000000..a8f35a66 --- /dev/null +++ b/packages/use-shader-fx/src/libs/shaders/ShaderLib/default_pars_vertex.glsl @@ -0,0 +1 @@ +#usf \ No newline at end of file diff --git a/packages/use-shader-fx/src/libs/shaders/ShaderLib/default_vertex.glsl b/packages/use-shader-fx/src/libs/shaders/ShaderLib/default_vertex.glsl new file mode 100644 index 00000000..06d19f37 --- /dev/null +++ b/packages/use-shader-fx/src/libs/shaders/ShaderLib/default_vertex.glsl @@ -0,0 +1 @@ +vUv = uv; \ No newline at end of file diff --git a/packages/use-shader-fx/src/libs/shaders/mergeShaderLib.ts b/packages/use-shader-fx/src/libs/shaders/mergeShaderLib.ts new file mode 100644 index 00000000..43ad89a0 --- /dev/null +++ b/packages/use-shader-fx/src/libs/shaders/mergeShaderLib.ts @@ -0,0 +1,42 @@ +import { ShaderLib } from "./ShaderLib"; + +/** + * 共通でパースするShaderの共有部分を解決する + * basicFx_fragment_begin, basicFx_fragment_endは含まない。これらは各FXでカスタマイズする必要があるため。 + */ +function mergeShaderLib( + vertexShader: string | undefined, + fragmentShader: string | undefined, + type: "default" | "basicFx" +): [string | undefined, string | undefined] { + let vertex, + fragment = undefined; + + const isDefault = type === "default"; + + const vertexPars = isDefault + ? ShaderLib.default_pars_vertex + : ShaderLib.basicFx_pars_vertex; + const vertexMain = isDefault + ? ShaderLib.default_vertex + : ShaderLib.basicFx_vertex; + const fragmentPars = isDefault + ? ShaderLib.default_pars_fragment + : ShaderLib.basicFx_pars_fragment; + + if (vertexShader) { + vertex = vertexPars + `\n` + vertexShader; + vertex = vertex.replace( + /void\s+main\s*\(\)\s*\{/, + `void main() {\n${vertexMain}` + ); + } + + if (fragmentShader) { + fragment = fragmentPars + `\n` + fragmentShader; + } + + return [vertex, fragment]; +} + +export { mergeShaderLib }; diff --git a/packages/use-shader-fx/src/libs/shaders/resolveShaders.ts b/packages/use-shader-fx/src/libs/shaders/resolveShaders.ts index 3b7ef675..27452a4d 100644 --- a/packages/use-shader-fx/src/libs/shaders/resolveShaders.ts +++ b/packages/use-shader-fx/src/libs/shaders/resolveShaders.ts @@ -9,5 +9,4 @@ function includeReplacer(match: string, include: ShaderChunkTypes): string { function resolveIncludes(string: string): string { return string.replace(includePattern, includeReplacer); } - export { resolveIncludes }; diff --git a/packages/use-shader-fx/src/utils/getDpr.ts b/packages/use-shader-fx/src/utils/getDpr.ts deleted file mode 100644 index 88caeef8..00000000 --- a/packages/use-shader-fx/src/utils/getDpr.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { Dpr } from "../fxs/types"; - -export const getDpr = ( - dpr: Dpr -): { shader: number | false; fbo: number | false } => { - if (typeof dpr === "number") { - return { shader: dpr, fbo: dpr }; - } - return { - shader: dpr.shader ?? false, - fbo: dpr.fbo ?? false, - }; -}; diff --git a/packages/use-shader-fx/src/utils/useCamera.ts b/packages/use-shader-fx/src/utils/useCamera.ts index 8da37f48..cf615867 100644 --- a/packages/use-shader-fx/src/utils/useCamera.ts +++ b/packages/use-shader-fx/src/utils/useCamera.ts @@ -15,11 +15,11 @@ export const useCamera = ( cameraType: "OrthographicCamera" | "PerspectiveCamera" = "OrthographicCamera" ) => { const resolution = useResolution(size); - const { width, height, near, far } = getCameraProps( - resolution.x, - resolution.y - ); const camera = useMemo(() => { + const { width, height, near, far } = getCameraProps( + resolution.x, + resolution.y + ); return cameraType === "OrthographicCamera" ? new THREE.OrthographicCamera( -width, @@ -30,6 +30,6 @@ export const useCamera = ( far ) : new THREE.PerspectiveCamera(50, width / height); - }, [width, height, near, far, cameraType]); + }, [resolution, cameraType]); return camera; }; diff --git a/packages/use-shader-fx/src/utils/useDpr.ts b/packages/use-shader-fx/src/utils/useDpr.ts new file mode 100644 index 00000000..17337bc0 --- /dev/null +++ b/packages/use-shader-fx/src/utils/useDpr.ts @@ -0,0 +1,18 @@ +import { useMemo } from "react"; +import { Dpr } from "../fxs/types"; + +export const useDpr = ( + dpr: Dpr +): { shader: number | false; fbo: number | false } => { + const _dpr = useMemo(() => { + if (typeof dpr === "number") { + return { shader: dpr, fbo: dpr }; + } + return { + shader: dpr.shader ?? false, + fbo: dpr.fbo ?? false, + }; + }, [dpr]); + + return _dpr; +}; diff --git a/packages/use-shader-fx/src/utils/useScene.ts b/packages/use-shader-fx/src/utils/useFxScene.ts similarity index 89% rename from packages/use-shader-fx/src/utils/useScene.ts rename to packages/use-shader-fx/src/utils/useFxScene.ts index 33f4c2a2..b0c80124 100644 --- a/packages/use-shader-fx/src/utils/useScene.ts +++ b/packages/use-shader-fx/src/utils/useFxScene.ts @@ -4,6 +4,7 @@ import { useObject3D } from "./useObject3D"; import { Size } from "../fxs/types"; import { useResolution } from "./useResolution"; import { FxMaterial, FxMaterialProps } from "../fxs/materials/FxMaterial"; +import { useCamera } from "./useCamera"; type MaterialConstructor = new (props: FxMaterialProps) => M; @@ -12,7 +13,7 @@ type GeometryConstructor = new ( height: number ) => THREE.BufferGeometry; -export const useScene = ({ +export const useFxScene = ({ size, dpr, material, @@ -46,8 +47,11 @@ export const useScene = ({ useObject3D(scene, _geometry, _material, THREE.Mesh); + const camera = useCamera(size); + return { scene, material: _material, + camera, }; }; diff --git a/todo b/todo index 09fa2132..3f4793ad 100644 --- a/todo +++ b/todo @@ -1,10 +1,17 @@ - useBlankの設計まとめる - usf wip - blank つくって水面のやつで +- 設計まとめ、ろくくんに引き継ぐ - pixelateつくる -- 要件定義つくって、ろくくんに引き継ぐ - grain をbasic fxに - 流体まとめる - grain、暗くならないような工夫 + + +- useNoiseのtickの処理を確認 + - valuesの値はuniformと一致させるべき + - 一致しないものはconfigsで設定する + - useBlankで例つくる +- \ No newline at end of file From 0cbe89d7853b648d23a1b3b3676eb7dc09c8056e Mon Sep 17 00:00:00 2001 From: takuma-hmng8 Date: Tue, 1 Oct 2024 20:02:14 +0900 Subject: [PATCH 08/60] update --- app/v2/FxMaterial.tsx | 64 ++++-- app/v2/Playground.tsx | 182 ++++++------------ app/v2_FxRenderer/FxMaterial.tsx | 80 ++++++++ app/v2_FxRenderer/Playground.tsx | 89 +++++++++ app/v2_FxRenderer/page.tsx | 18 ++ .../{fxs => hooks}/materials/BasicFxLib.ts | 0 .../materials/FxBasicFxMaterial.ts | 0 .../{fxs => hooks}/materials/FxMaterial.ts | 0 .../src/{fxs => hooks}/types/index.ts | 0 .../src/hooks/useBlur/BlurMaterial.ts | 41 ++++ .../src/hooks/useBlur/blur.glsl.ts | 33 ++++ .../use-shader-fx/src/hooks/useBlur/index.ts | 93 +++++++++ .../useCoverTexture/CoverTextureMaterial.ts | 0 .../useCoverTexture/coverTexture.glsl.ts | 2 +- .../{fxs => hooks}/useCoverTexture/index.ts | 0 .../src/{fxs => hooks}/useFluid/index.ts | 18 +- .../useFluid/materials/AdvectionMaterial.ts | 0 .../useFluid/materials/DivergenceMaterial.ts | 0 .../useFluid/materials/PoissonMaterial.ts | 0 .../useFluid/materials/PressureMaterial.ts | 0 .../useFluid/materials/SplatMaterial.ts | 4 +- .../useFluid/materials/shaders/advection.frag | 0 .../materials/shaders/divergence.frag | 0 .../useFluid/materials/shaders/poisson.frag | 0 .../useFluid/materials/shaders/pressure.frag | 0 .../useFluid/materials/shaders/splat.frag | 0 .../useFluid/materials/shaders/vertex.ts | 0 .../useFluid/scenes/useAdvection.ts | 0 .../useFluid/scenes/useDivergence.ts | 0 .../useFluid/scenes/usePoisson.ts | 0 .../useFluid/scenes/usePressure.ts | 0 .../useFluid/scenes/useSplat.ts | 0 .../{fxs => hooks}/useNoise/NoiseMaterial.ts | 6 +- .../src/{fxs => hooks}/useNoise/index.ts | 8 +- .../src/{fxs => hooks}/useNoise/noise.glsl.ts | 6 +- .../useRawBlank/RawBlankMaterial.ts | 0 .../src/{fxs => hooks}/useRawBlank/index.ts | 0 packages/use-shader-fx/src/index.js | 9 +- .../src/libs/shaders/ShaderChunk.ts | 6 + .../shaders/ShaderChunk/default_vertex.glsl | 1 + .../shaders/ShaderChunk/plane_vertex.glsl | 1 + .../src/libs/shaders/ShaderLib.ts | 5 +- .../shaders/ShaderLib/default_vertex.glsl | 2 +- .../libs/shaders/ShaderLib/plane_vertex.glsl | 1 + todo | 17 -- 45 files changed, 506 insertions(+), 180 deletions(-) create mode 100644 app/v2_FxRenderer/FxMaterial.tsx create mode 100644 app/v2_FxRenderer/Playground.tsx create mode 100644 app/v2_FxRenderer/page.tsx rename packages/use-shader-fx/src/{fxs => hooks}/materials/BasicFxLib.ts (100%) rename packages/use-shader-fx/src/{fxs => hooks}/materials/FxBasicFxMaterial.ts (100%) rename packages/use-shader-fx/src/{fxs => hooks}/materials/FxMaterial.ts (100%) rename packages/use-shader-fx/src/{fxs => hooks}/types/index.ts (100%) create mode 100644 packages/use-shader-fx/src/hooks/useBlur/BlurMaterial.ts create mode 100644 packages/use-shader-fx/src/hooks/useBlur/blur.glsl.ts create mode 100644 packages/use-shader-fx/src/hooks/useBlur/index.ts rename packages/use-shader-fx/src/{fxs => hooks}/useCoverTexture/CoverTextureMaterial.ts (100%) rename packages/use-shader-fx/src/{fxs => hooks}/useCoverTexture/coverTexture.glsl.ts (95%) rename packages/use-shader-fx/src/{fxs => hooks}/useCoverTexture/index.ts (100%) rename packages/use-shader-fx/src/{fxs => hooks}/useFluid/index.ts (90%) rename packages/use-shader-fx/src/{fxs => hooks}/useFluid/materials/AdvectionMaterial.ts (100%) rename packages/use-shader-fx/src/{fxs => hooks}/useFluid/materials/DivergenceMaterial.ts (100%) rename packages/use-shader-fx/src/{fxs => hooks}/useFluid/materials/PoissonMaterial.ts (100%) rename packages/use-shader-fx/src/{fxs => hooks}/useFluid/materials/PressureMaterial.ts (100%) rename packages/use-shader-fx/src/{fxs => hooks}/useFluid/materials/SplatMaterial.ts (92%) rename packages/use-shader-fx/src/{fxs => hooks}/useFluid/materials/shaders/advection.frag (100%) rename packages/use-shader-fx/src/{fxs => hooks}/useFluid/materials/shaders/divergence.frag (100%) rename packages/use-shader-fx/src/{fxs => hooks}/useFluid/materials/shaders/poisson.frag (100%) rename packages/use-shader-fx/src/{fxs => hooks}/useFluid/materials/shaders/pressure.frag (100%) rename packages/use-shader-fx/src/{fxs => hooks}/useFluid/materials/shaders/splat.frag (100%) rename packages/use-shader-fx/src/{fxs => hooks}/useFluid/materials/shaders/vertex.ts (100%) rename packages/use-shader-fx/src/{fxs => hooks}/useFluid/scenes/useAdvection.ts (100%) rename packages/use-shader-fx/src/{fxs => hooks}/useFluid/scenes/useDivergence.ts (100%) rename packages/use-shader-fx/src/{fxs => hooks}/useFluid/scenes/usePoisson.ts (100%) rename packages/use-shader-fx/src/{fxs => hooks}/useFluid/scenes/usePressure.ts (100%) rename packages/use-shader-fx/src/{fxs => hooks}/useFluid/scenes/useSplat.ts (100%) rename packages/use-shader-fx/src/{fxs => hooks}/useNoise/NoiseMaterial.ts (91%) rename packages/use-shader-fx/src/{fxs => hooks}/useNoise/index.ts (93%) rename packages/use-shader-fx/src/{fxs => hooks}/useNoise/noise.glsl.ts (94%) rename packages/use-shader-fx/src/{fxs => hooks}/useRawBlank/RawBlankMaterial.ts (100%) rename packages/use-shader-fx/src/{fxs => hooks}/useRawBlank/index.ts (100%) create mode 100644 packages/use-shader-fx/src/libs/shaders/ShaderChunk/default_vertex.glsl create mode 100644 packages/use-shader-fx/src/libs/shaders/ShaderChunk/plane_vertex.glsl create mode 100644 packages/use-shader-fx/src/libs/shaders/ShaderLib/plane_vertex.glsl diff --git a/app/v2/FxMaterial.tsx b/app/v2/FxMaterial.tsx index 1da7f98f..dfc77629 100644 --- a/app/v2/FxMaterial.tsx +++ b/app/v2/FxMaterial.tsx @@ -10,12 +10,22 @@ declare global { } export type FxMaterialProps = { - u_fx: THREE.Texture; + u_blur: THREE.Texture; + u_gooey: THREE.Texture; + u_model: THREE.Texture; + u_noise?: THREE.Texture; + u_color0?: THREE.Color; + u_color1?: THREE.Color; }; export const FxMaterial = shaderMaterial( { - u_fx: new THREE.Texture(), + u_blur: new THREE.Texture(), + u_gooey: new THREE.Texture(), + u_model: new THREE.Texture(), + u_noise: new THREE.Texture(), + u_color0: new THREE.Color(0x1974d2), + u_color1: new THREE.Color(0xff1e90), }, ` @@ -28,22 +38,52 @@ export const FxMaterial = shaderMaterial( ` precision highp float; varying vec2 vUv; - uniform sampler2D u_fx; + uniform sampler2D u_blur; + uniform sampler2D u_gooey; + uniform sampler2D u_model; + uniform sampler2D u_noise; + uniform vec3 u_color0; + uniform vec3 u_color1; + + float vignetteStrength = 0.9; // 強度(0.0〜1.0) + float vignetteRadius = 0.64; // 効果が始まる半径(0.0〜1.0) + + float rand(vec2 n) { + return fract(sin(dot(n ,vec2(12.9898,78.233))) * 43758.5453); + } void main() { vec2 uv = vUv; + float grain = rand(uv); // -1.0〜1.0 + + // ビネット + vec2 position = uv - 0.5; + float distance = length(position); + float vignette = smoothstep(vignetteRadius, vignetteRadius - 0.5, distance); + vignette = mix(1.0, vignette, vignetteStrength); - vec4 color = texture2D(u_fx, uv); - gl_FragColor = color; - - // vec2 vel = texture2D(u_fx, uv).xy; - // float len = length(vel); - // vel = vel * 0.5 + 0.5; + // ノイズ + vec4 noise = texture2D(u_noise, uv); + vec3 noisedColor = mix(u_color0, u_color1, length(noise.rg * uv) + .1); + noisedColor -= grain * .1; + + // ブラー + vec4 blurColor = texture2D(u_blur,uv); + blurColor.rgb+=grain * .3; + blurColor.rgb+=noisedColor * 2.; + + // ブラーとノイズを混ぜる + vec3 mixedBlurColor = mix(noisedColor, blurColor.rgb, blurColor.a); - // vec3 color = vec3(vel.x, vel.y, 1.); - // color = mix(vec3(1.), color, len); + // モデル + vec4 modelColor = texture2D(u_model,uv); + float gooeyAlpha = texture2D(u_gooey,uv).a; + vec3 mixedModelColor = mix(mixedBlurColor, vec3(0.), clamp(gooeyAlpha * 80.0 - 20.0,0.,1.)); + + vec3 finalColor = mixedModelColor * vignette; + + gl_FragColor = vec4(finalColor, 1.0); - // gl_FragColor = vec4(color, 1.0); } ` ); diff --git a/app/v2/Playground.tsx b/app/v2/Playground.tsx index b72f87e4..e6a06347 100644 --- a/app/v2/Playground.tsx +++ b/app/v2/Playground.tsx @@ -2,13 +2,8 @@ import * as THREE from "three"; import { useCallback, useEffect, useMemo, useRef, useState } from "react"; -import { useFrame, useThree, extend, useLoader } from "@react-three/fiber"; -import { - useNoise, - useFluid, - useCoverTexture, - useRawBlank, -} from "@/packages/use-shader-fx/src"; +import { useFrame, useThree, extend, createPortal } from "@react-three/fiber"; +import { useNoise, useBlur } from "@/packages/use-shader-fx/src"; import { FxMaterial } from "./FxMaterial"; import { Environment, @@ -16,141 +11,86 @@ import { OrbitControls, useVideoTexture, } from "@react-three/drei"; - -/*=============================================== -# webglooの設計 -- useFxResolverでhookを切り替える -===============================================*/ +import { useSingleFBO } from "@/packages/use-shader-fx/legacy"; extend({ FxMaterial }); -// ここに渡すstateでレンダリングを切り替える -const useFxResolver = (test: boolean) => { - if (test) { - return useNoise; - } else { - return useFluid; - } -}; - -// const hooks = [useNoise, useNoise]; - export const Playground = () => { - const { size, viewport } = useThree(); + const { size, viewport, camera } = useThree(); - const funkun_mov = useVideoTexture("/FT_Ch02-comp.mp4", { - width: 1280, - height: 720, + const offscreenScene = useMemo(() => new THREE.Scene(), []); + const [renderTarget, updateRenderTarget] = useSingleFBO({ + scene: offscreenScene, + camera, + size, + dpr: viewport.dpr, + depthBuffer: true, }); - const [gear, smoke] = useLoader(THREE.TextureLoader, [ - "/stickers/webp/sticker17.webp", - "smoke.png", - ]); - - // const rawBlank = useRawBlank({ - // size, - // dpr: 1, - // uniforms: { - // testTex: { value: funkun_mov }, - // }, - // fragmentShader: ` - // uniform sampler2D testTex; - // void main() { - // gl_FragColor = texture2D(testTex, vUv); - // } - // `, - // vertexShader: ` - // void main() { - // gl_Position = vec4(position, 1.0); - // } - // `, - // }); - - // const noise = useNoise({ - // size, - // dpr: 0.2, - // scale: 0.02, - // // mixSrc: gear, - // // mixSrcResolution: new THREE.Vector2(512, 512), - // // mixSrcUvFactor: 0.2, - // // mixSrcAlphaFactor: 0.1, - // // mixSrcColorFactor: 0.4, - // // mixDst: gear, - // // mixDstResolution: new THREE.Vector2(512, 512), - // // mixDstUvFactor: 0.3, - // // mixDstAlphaFactor: 1, - // // mixDstColorFactor: 0, - // }); + const blur = useBlur({ + size, + dpr: 0.6, + blurSize: 8, + blurIteration: 20, + src: renderTarget.texture, + }); - const fluid = useFluid({ + const gooey = useBlur({ size, - dpr: 0.25, + dpr: 2, + blurSize: 4, + blurIteration: 30, + src: renderTarget.texture, }); - const cover = useCoverTexture({ + const noise = useNoise({ size, - dpr: 0.25, - src: funkun_mov, - textureResolution: new THREE.Vector2(1280, 720), - mixSrc: smoke, - mixDstResolution: new THREE.Vector2(512, 512), - mixDstUvFactor: 0.9, - mixDstAlphaFactor: 0.1, - mixDstColorFactor: 0.4, - mixSrcResolution: new THREE.Vector2(512, 512), - mixSrcUvFactor: 0.8, - mixSrcAlphaFactor: 0.1, - mixSrcColorFactor: 0.0, + dpr: 0.05, + scale: 0.03, }); + const mesh0 = useRef(null); + const mesh1 = useRef(null); + useFrame((state) => { - // cover.render(state); - // cover.render(state); - fluid.render(state); - // noise.render(state); - // material.color = new THREE.Color( - // Math.sin(state.clock.getElapsedTime()), - // 1, - // 1 - // ); - // mesh.current!.rotation.x += 0.01; - // mesh.current!.rotation.y += 0.01; + blur.render(state); + gooey.render(state); + noise.render(state); + updateRenderTarget(state.gl); + mesh0.current!.position.x -= + Math.sin(state.clock.getElapsedTime()) * 0.02; }); return ( <> - {/* + - - */} - - - {/* */} - {/* */} - - - - - - - - + + + {createPortal( + + + + + + + + + + + + + - - + , + offscreenScene + )} ); }; diff --git a/app/v2_FxRenderer/FxMaterial.tsx b/app/v2_FxRenderer/FxMaterial.tsx new file mode 100644 index 00000000..948c0e9a --- /dev/null +++ b/app/v2_FxRenderer/FxMaterial.tsx @@ -0,0 +1,80 @@ +import * as THREE from "three"; +import { shaderMaterial } from "@react-three/drei"; + +declare global { + namespace JSX { + interface IntrinsicElements { + fxMaterial: any; + } + } +} + +export type FxMaterialProps = { + u_fx: THREE.Texture; + u_noise?: THREE.Texture; + u_color0?: THREE.Color; + u_color1?: THREE.Color; +}; + +export const FxMaterial = shaderMaterial( + { + u_fx: new THREE.Texture(), + u_noise: new THREE.Texture(), + u_color0: new THREE.Color(0x1974d2), + u_color1: new THREE.Color(0xff1e90), + }, + + ` + varying vec2 vUv; + void main() { + vUv = uv; + gl_Position = vec4(position, 1.0); + } + `, + ` + precision highp float; + varying vec2 vUv; + uniform sampler2D u_fx; + uniform sampler2D u_noise; + uniform vec3 u_color0; + uniform vec3 u_color1; + + float vignetteStrength = 0.88; // 強度(0.0〜1.0) + float vignetteRadius = 0.8; // 効果が始まる半径(0.0〜1.0) + + float rand(vec2 n) { + return fract(sin(dot(n ,vec2(12.9898,78.233))) * 43758.5453); + } + + void main() { + vec2 uv = vUv; + + float grain = rand(uv); // -1.0〜1.0 + + // ビネット + vec2 position = uv - 0.5; + float distance = length(position); + float vignette = smoothstep(vignetteRadius, vignetteRadius - 0.5, distance); + vignette = mix(1.0, vignette, vignetteStrength); + + // ノイズ + vec4 noise = texture2D(u_noise, uv); + vec3 noisedColor = mix(u_color0, u_color1, length(noise.rg * uv) + .1); + noisedColor += grain * .1; + + // モデル + vec4 modelColor = texture2D(u_fx,uv); + modelColor.rgb+=grain * .3; + + modelColor.rgb+=noisedColor; + + // モデルとノイズを混ぜる + vec3 mixedModelColor = mix(noisedColor, modelColor.rgb, modelColor.a); + + vec3 finalColor = mixedModelColor * vignette; + + gl_FragColor = vec4(finalColor, 1.0); + + } + ` +); diff --git a/app/v2_FxRenderer/Playground.tsx b/app/v2_FxRenderer/Playground.tsx new file mode 100644 index 00000000..f6b95052 --- /dev/null +++ b/app/v2_FxRenderer/Playground.tsx @@ -0,0 +1,89 @@ +"use client"; + +import * as THREE from "three"; +import { useCallback, useEffect, useMemo, useRef, useState } from "react"; +import { + useFrame, + useThree, + extend, + useLoader, + createPortal, +} from "@react-three/fiber"; +import { + useNoise, + useFluid, + useCoverTexture, + useRawBlank, + useBlur, +} from "@/packages/use-shader-fx/src"; +import { FxMaterial } from "./FxMaterial"; +import { + Environment, + Float, + OrbitControls, + useVideoTexture, +} from "@react-three/drei"; +import { useSingleFBO } from "@/packages/use-shader-fx/legacy"; + +/*=============================================== +TODO * これをFxRendererで、描画できるようにする +glslのカスマイズなしで、レンダリングするのを目標とする +===============================================*/ + +extend({ FxMaterial }); + +export const Playground = () => { + const { size, viewport, camera } = useThree(); + + const offscreenScene = useMemo(() => new THREE.Scene(), []); + const [renderTarget, updateRenderTarget] = useSingleFBO({ + scene: offscreenScene, + camera, + size, + dpr: viewport.dpr, + depthBuffer: true, + }); + + const blur = useBlur({ + size, + dpr: 1, + src: renderTarget.texture, + }); + + const noise = useNoise({ + size, + dpr: 0.05, + scale: 0.03, + }); + + useFrame((state) => { + blur.render(state); + noise.render(state); + updateRenderTarget(state.gl); + }); + + return ( + <> + + + + + {createPortal( + + + + + + + + + , + offscreenScene + )} + + ); +}; diff --git a/app/v2_FxRenderer/page.tsx b/app/v2_FxRenderer/page.tsx new file mode 100644 index 00000000..a84dd222 --- /dev/null +++ b/app/v2_FxRenderer/page.tsx @@ -0,0 +1,18 @@ +import { ShaderFx } from "../ShaderFx"; +import { Playground } from "./Playground"; + +export default function Page() { + return ( +
    + + + +
    + ); +} diff --git a/packages/use-shader-fx/src/fxs/materials/BasicFxLib.ts b/packages/use-shader-fx/src/hooks/materials/BasicFxLib.ts similarity index 100% rename from packages/use-shader-fx/src/fxs/materials/BasicFxLib.ts rename to packages/use-shader-fx/src/hooks/materials/BasicFxLib.ts diff --git a/packages/use-shader-fx/src/fxs/materials/FxBasicFxMaterial.ts b/packages/use-shader-fx/src/hooks/materials/FxBasicFxMaterial.ts similarity index 100% rename from packages/use-shader-fx/src/fxs/materials/FxBasicFxMaterial.ts rename to packages/use-shader-fx/src/hooks/materials/FxBasicFxMaterial.ts diff --git a/packages/use-shader-fx/src/fxs/materials/FxMaterial.ts b/packages/use-shader-fx/src/hooks/materials/FxMaterial.ts similarity index 100% rename from packages/use-shader-fx/src/fxs/materials/FxMaterial.ts rename to packages/use-shader-fx/src/hooks/materials/FxMaterial.ts diff --git a/packages/use-shader-fx/src/fxs/types/index.ts b/packages/use-shader-fx/src/hooks/types/index.ts similarity index 100% rename from packages/use-shader-fx/src/fxs/types/index.ts rename to packages/use-shader-fx/src/hooks/types/index.ts diff --git a/packages/use-shader-fx/src/hooks/useBlur/BlurMaterial.ts b/packages/use-shader-fx/src/hooks/useBlur/BlurMaterial.ts new file mode 100644 index 00000000..a3643c98 --- /dev/null +++ b/packages/use-shader-fx/src/hooks/useBlur/BlurMaterial.ts @@ -0,0 +1,41 @@ +import * as THREE from "three"; +import { fragment, vertex } from "./blur.glsl"; +import { FxBasicFxMaterial } from "../materials/FxBasicFxMaterial"; +import { BlurValues } from "."; +import { FxMaterialProps } from "../materials/FxMaterial"; +import { BasicFxUniforms } from "../materials/BasicFxLib"; + +type BlurUniforms = { + src: { value: THREE.Texture | null }; + blurSize: { value: number }; +} & BasicFxUniforms; + +export class BlurMaterial extends FxBasicFxMaterial { + static get type() { + return "BlurMaterial"; + } + + uniforms!: BlurUniforms; + + constructor({ + uniformValues, + materialParameters = {}, + }: FxMaterialProps) { + super(); + + this.type = BlurMaterial.type; + + this.uniforms = { + ...this.uniforms, + ...{ + src: { value: null }, + blurSize: { value: 5 }, + }, + }; + + this.setUniformValues(uniformValues); + this.setValues(materialParameters); + + this.setupBasicFxShaders(vertex, fragment); + } +} diff --git a/packages/use-shader-fx/src/hooks/useBlur/blur.glsl.ts b/packages/use-shader-fx/src/hooks/useBlur/blur.glsl.ts new file mode 100644 index 00000000..a9310c29 --- /dev/null +++ b/packages/use-shader-fx/src/hooks/useBlur/blur.glsl.ts @@ -0,0 +1,33 @@ +import { ShaderLib } from "../../libs/shaders/ShaderLib"; + +export const vertex = ` + void main() { + ${ShaderLib.plane_vertex} + } +`; + +export const fragment = ` + uniform sampler2D src; + uniform float blurSize; + + void main() { + + vec2 perDivSize = blurSize / resolution; + + vec4 outColor = vec4( + texture2D(src, vUv + perDivSize * vec2(-1.0, -1.0)) + + texture2D(src, vUv + perDivSize * vec2(0.0, -1.0)) + + texture2D(src, vUv + perDivSize * vec2(1.0, -1.0)) + + texture2D(src, vUv + perDivSize * vec2(-1.0, 0.0)) + + texture2D(src, vUv + perDivSize * vec2(0.0, 0.0)) + + texture2D(src, vUv + perDivSize * vec2(1.0, 0.0)) + + texture2D(src, vUv + perDivSize * vec2(-1.0, 1.0)) + + texture2D(src, vUv + perDivSize * vec2(0.0, 1.0)) + + texture2D(src, vUv + perDivSize * vec2(1.0, 1.0)) + ) / 9.0; + + gl_FragColor = outColor; + + + } +`; diff --git a/packages/use-shader-fx/src/hooks/useBlur/index.ts b/packages/use-shader-fx/src/hooks/useBlur/index.ts new file mode 100644 index 00000000..e693f18f --- /dev/null +++ b/packages/use-shader-fx/src/hooks/useBlur/index.ts @@ -0,0 +1,93 @@ +import * as THREE from "three"; +import { useCallback } from "react"; +import { HooksProps, HooksReturn } from "../types"; +import { useDpr } from "../../utils/useDpr"; +import { RootState } from "../types"; +import { BlurMaterial } from "./BlurMaterial"; +import { useFxScene } from "../../utils/useFxScene"; +import { BasicFxValues } from "../materials/BasicFxLib"; +import { useDoubleFBO } from "../../utils/useDoubleFBO"; + +export type BlurValues = { + src?: THREE.Texture | null; + blurSize?: number; +} & BasicFxValues; + +type BlurConfig = { + blurIteration?: number; +}; + +/** + * @link https://github.com/FunTechInc/use-shader-fx?tab=readme-ov-file#usage + */ +export const useBlur = ({ + size, + dpr, + sizeUpdate, + renderTargetOptions, + materialParameters, + blurIteration = 5, + ...uniformValues +}: HooksProps & BlurValues & BlurConfig): HooksReturn< + BlurValues, + BlurMaterial +> => { + const _dpr = useDpr(dpr); + + const { scene, material, camera } = useFxScene({ + size, + dpr: _dpr.shader, + material: BlurMaterial, + uniformValues, + materialParameters, + }); + + const [renderTarget, updateRenderTarget] = useDoubleFBO({ + scene, + camera, + size, + dpr: _dpr.fbo, + sizeUpdate, + ...renderTargetOptions, + }); + + const setValues = useCallback( + (newValues: BlurValues) => { + material.setUniformValues(newValues); + }, + [material] + ); + + const render = useCallback( + (rootState: RootState, newValues?: BlurValues) => { + const { gl } = rootState; + newValues && setValues(newValues); + + const srcCache = material.uniforms.src?.value; + + material.updateBasicFx(); + + updateRenderTarget({ gl }); + + for (let i = 0; i < blurIteration; i++) { + updateRenderTarget({ gl }, ({ read }) => { + material.uniforms.src.value = read; + }); + } + + material.uniforms.src.value = srcCache; + + return renderTarget.read.texture; + }, + [setValues, updateRenderTarget, material, renderTarget, blurIteration] + ); + + return { + render, + setValues, + texture: renderTarget.read.texture, + material, + scene, + camera, + }; +}; diff --git a/packages/use-shader-fx/src/fxs/useCoverTexture/CoverTextureMaterial.ts b/packages/use-shader-fx/src/hooks/useCoverTexture/CoverTextureMaterial.ts similarity index 100% rename from packages/use-shader-fx/src/fxs/useCoverTexture/CoverTextureMaterial.ts rename to packages/use-shader-fx/src/hooks/useCoverTexture/CoverTextureMaterial.ts diff --git a/packages/use-shader-fx/src/fxs/useCoverTexture/coverTexture.glsl.ts b/packages/use-shader-fx/src/hooks/useCoverTexture/coverTexture.glsl.ts similarity index 95% rename from packages/use-shader-fx/src/fxs/useCoverTexture/coverTexture.glsl.ts rename to packages/use-shader-fx/src/hooks/useCoverTexture/coverTexture.glsl.ts index 12df916b..a1b37201 100644 --- a/packages/use-shader-fx/src/fxs/useCoverTexture/coverTexture.glsl.ts +++ b/packages/use-shader-fx/src/hooks/useCoverTexture/coverTexture.glsl.ts @@ -12,7 +12,7 @@ export const vertex = ` ); vCoverTextureUv = vUv * aspectRatio + (1.0 - aspectRatio) * .5; - gl_Position = vec4(position, 1.0); + ${ShaderLib.plane_vertex} } `; diff --git a/packages/use-shader-fx/src/fxs/useCoverTexture/index.ts b/packages/use-shader-fx/src/hooks/useCoverTexture/index.ts similarity index 100% rename from packages/use-shader-fx/src/fxs/useCoverTexture/index.ts rename to packages/use-shader-fx/src/hooks/useCoverTexture/index.ts diff --git a/packages/use-shader-fx/src/fxs/useFluid/index.ts b/packages/use-shader-fx/src/hooks/useFluid/index.ts similarity index 90% rename from packages/use-shader-fx/src/fxs/useFluid/index.ts rename to packages/use-shader-fx/src/hooks/useFluid/index.ts index fb5e0d5b..f4d1fd0f 100644 --- a/packages/use-shader-fx/src/fxs/useFluid/index.ts +++ b/packages/use-shader-fx/src/hooks/useFluid/index.ts @@ -13,14 +13,16 @@ import { usePressure } from "./scenes/usePressure"; export const DeltaTime = 0.015; -export type FluidValues = {}; - -/*=============================================== -- 出力でcolormapとvelocitymapを選択できるみたいな仕組みにする -- params - - velocity dissipation - - color dissipation (color map) -===============================================*/ +export type FluidValues = { + /*=============================================== + TODO * + - 出力でcolormapとvelocitymapを選択できるみたいな仕組みにする + - colormapはfxBasicFxmaterialで、基礎FXも + - params + - velocity dissipation + - color dissipation (color map) + ===============================================*/ +}; /** * @link https://github.com/FunTechInc/use-shader-fx?tab=readme-ov-file#usage diff --git a/packages/use-shader-fx/src/fxs/useFluid/materials/AdvectionMaterial.ts b/packages/use-shader-fx/src/hooks/useFluid/materials/AdvectionMaterial.ts similarity index 100% rename from packages/use-shader-fx/src/fxs/useFluid/materials/AdvectionMaterial.ts rename to packages/use-shader-fx/src/hooks/useFluid/materials/AdvectionMaterial.ts diff --git a/packages/use-shader-fx/src/fxs/useFluid/materials/DivergenceMaterial.ts b/packages/use-shader-fx/src/hooks/useFluid/materials/DivergenceMaterial.ts similarity index 100% rename from packages/use-shader-fx/src/fxs/useFluid/materials/DivergenceMaterial.ts rename to packages/use-shader-fx/src/hooks/useFluid/materials/DivergenceMaterial.ts diff --git a/packages/use-shader-fx/src/fxs/useFluid/materials/PoissonMaterial.ts b/packages/use-shader-fx/src/hooks/useFluid/materials/PoissonMaterial.ts similarity index 100% rename from packages/use-shader-fx/src/fxs/useFluid/materials/PoissonMaterial.ts rename to packages/use-shader-fx/src/hooks/useFluid/materials/PoissonMaterial.ts diff --git a/packages/use-shader-fx/src/fxs/useFluid/materials/PressureMaterial.ts b/packages/use-shader-fx/src/hooks/useFluid/materials/PressureMaterial.ts similarity index 100% rename from packages/use-shader-fx/src/fxs/useFluid/materials/PressureMaterial.ts rename to packages/use-shader-fx/src/hooks/useFluid/materials/PressureMaterial.ts diff --git a/packages/use-shader-fx/src/fxs/useFluid/materials/SplatMaterial.ts b/packages/use-shader-fx/src/hooks/useFluid/materials/SplatMaterial.ts similarity index 92% rename from packages/use-shader-fx/src/fxs/useFluid/materials/SplatMaterial.ts rename to packages/use-shader-fx/src/hooks/useFluid/materials/SplatMaterial.ts index b31f135d..00967370 100644 --- a/packages/use-shader-fx/src/fxs/useFluid/materials/SplatMaterial.ts +++ b/packages/use-shader-fx/src/hooks/useFluid/materials/SplatMaterial.ts @@ -27,14 +27,14 @@ export class SplatMaterial extends FxMaterial { this.type = SplatMaterial.type; - this.force = 15; + this.force = 30; this.uniforms = { ...this.uniforms, ...{ force: { value: new THREE.Vector2(0, 0) }, center: { value: new THREE.Vector2(0, 0) }, - scale: { value: new THREE.Vector2(20, 20) }, + scale: { value: new THREE.Vector2(30, 30) }, }, }; diff --git a/packages/use-shader-fx/src/fxs/useFluid/materials/shaders/advection.frag b/packages/use-shader-fx/src/hooks/useFluid/materials/shaders/advection.frag similarity index 100% rename from packages/use-shader-fx/src/fxs/useFluid/materials/shaders/advection.frag rename to packages/use-shader-fx/src/hooks/useFluid/materials/shaders/advection.frag diff --git a/packages/use-shader-fx/src/fxs/useFluid/materials/shaders/divergence.frag b/packages/use-shader-fx/src/hooks/useFluid/materials/shaders/divergence.frag similarity index 100% rename from packages/use-shader-fx/src/fxs/useFluid/materials/shaders/divergence.frag rename to packages/use-shader-fx/src/hooks/useFluid/materials/shaders/divergence.frag diff --git a/packages/use-shader-fx/src/fxs/useFluid/materials/shaders/poisson.frag b/packages/use-shader-fx/src/hooks/useFluid/materials/shaders/poisson.frag similarity index 100% rename from packages/use-shader-fx/src/fxs/useFluid/materials/shaders/poisson.frag rename to packages/use-shader-fx/src/hooks/useFluid/materials/shaders/poisson.frag diff --git a/packages/use-shader-fx/src/fxs/useFluid/materials/shaders/pressure.frag b/packages/use-shader-fx/src/hooks/useFluid/materials/shaders/pressure.frag similarity index 100% rename from packages/use-shader-fx/src/fxs/useFluid/materials/shaders/pressure.frag rename to packages/use-shader-fx/src/hooks/useFluid/materials/shaders/pressure.frag diff --git a/packages/use-shader-fx/src/fxs/useFluid/materials/shaders/splat.frag b/packages/use-shader-fx/src/hooks/useFluid/materials/shaders/splat.frag similarity index 100% rename from packages/use-shader-fx/src/fxs/useFluid/materials/shaders/splat.frag rename to packages/use-shader-fx/src/hooks/useFluid/materials/shaders/splat.frag diff --git a/packages/use-shader-fx/src/fxs/useFluid/materials/shaders/vertex.ts b/packages/use-shader-fx/src/hooks/useFluid/materials/shaders/vertex.ts similarity index 100% rename from packages/use-shader-fx/src/fxs/useFluid/materials/shaders/vertex.ts rename to packages/use-shader-fx/src/hooks/useFluid/materials/shaders/vertex.ts diff --git a/packages/use-shader-fx/src/fxs/useFluid/scenes/useAdvection.ts b/packages/use-shader-fx/src/hooks/useFluid/scenes/useAdvection.ts similarity index 100% rename from packages/use-shader-fx/src/fxs/useFluid/scenes/useAdvection.ts rename to packages/use-shader-fx/src/hooks/useFluid/scenes/useAdvection.ts diff --git a/packages/use-shader-fx/src/fxs/useFluid/scenes/useDivergence.ts b/packages/use-shader-fx/src/hooks/useFluid/scenes/useDivergence.ts similarity index 100% rename from packages/use-shader-fx/src/fxs/useFluid/scenes/useDivergence.ts rename to packages/use-shader-fx/src/hooks/useFluid/scenes/useDivergence.ts diff --git a/packages/use-shader-fx/src/fxs/useFluid/scenes/usePoisson.ts b/packages/use-shader-fx/src/hooks/useFluid/scenes/usePoisson.ts similarity index 100% rename from packages/use-shader-fx/src/fxs/useFluid/scenes/usePoisson.ts rename to packages/use-shader-fx/src/hooks/useFluid/scenes/usePoisson.ts diff --git a/packages/use-shader-fx/src/fxs/useFluid/scenes/usePressure.ts b/packages/use-shader-fx/src/hooks/useFluid/scenes/usePressure.ts similarity index 100% rename from packages/use-shader-fx/src/fxs/useFluid/scenes/usePressure.ts rename to packages/use-shader-fx/src/hooks/useFluid/scenes/usePressure.ts diff --git a/packages/use-shader-fx/src/fxs/useFluid/scenes/useSplat.ts b/packages/use-shader-fx/src/hooks/useFluid/scenes/useSplat.ts similarity index 100% rename from packages/use-shader-fx/src/fxs/useFluid/scenes/useSplat.ts rename to packages/use-shader-fx/src/hooks/useFluid/scenes/useSplat.ts diff --git a/packages/use-shader-fx/src/fxs/useNoise/NoiseMaterial.ts b/packages/use-shader-fx/src/hooks/useNoise/NoiseMaterial.ts similarity index 91% rename from packages/use-shader-fx/src/fxs/useNoise/NoiseMaterial.ts rename to packages/use-shader-fx/src/hooks/useNoise/NoiseMaterial.ts index 4ded8e72..2796ec1e 100644 --- a/packages/use-shader-fx/src/fxs/useNoise/NoiseMaterial.ts +++ b/packages/use-shader-fx/src/hooks/useNoise/NoiseMaterial.ts @@ -1,10 +1,8 @@ import * as THREE from "three"; import { noiseFragment, noiseVertex } from "./noise.glsl"; -import { - BasicFxUniforms, - FxBasicFxMaterial, -} from "../materials/FxBasicFxMaterial"; +import { FxBasicFxMaterial } from "../materials/FxBasicFxMaterial"; import { FxMaterialProps } from "../materials/FxMaterial"; +import { BasicFxUniforms } from "../materials/BasicFxLib"; type NoiseUniforms = { tick: { value: number }; diff --git a/packages/use-shader-fx/src/fxs/useNoise/index.ts b/packages/use-shader-fx/src/hooks/useNoise/index.ts similarity index 93% rename from packages/use-shader-fx/src/fxs/useNoise/index.ts rename to packages/use-shader-fx/src/hooks/useNoise/index.ts index dc04e15d..fb3055ac 100644 --- a/packages/use-shader-fx/src/fxs/useNoise/index.ts +++ b/packages/use-shader-fx/src/hooks/useNoise/index.ts @@ -3,10 +3,10 @@ import { useCallback } from "react"; import { useCamera } from "../../utils/useCamera"; import { useSingleFBO } from "../../utils/useSingleFBO"; import { HooksProps, HooksReturn } from "../types"; -import { getDpr } from "../../utils/useDpr"; +import { useDpr } from "../../utils/useDpr"; import { RootState } from "../types"; import { NoiseMaterial } from "./NoiseMaterial"; -import { useScene } from "../../utils/useFxScene"; +import { useFxScene } from "../../utils/useFxScene"; import { BasicFxValues } from "../materials/BasicFxLib"; export type NoiseValues = { @@ -41,9 +41,9 @@ export const useNoise = ({ materialParameters, ...uniformValues }: HooksProps & NoiseValues): HooksReturn => { - const _dpr = getDpr(dpr); + const _dpr = useDpr(dpr); - const { scene, material } = useScene({ + const { scene, material } = useFxScene({ size, dpr: _dpr.shader, material: NoiseMaterial, diff --git a/packages/use-shader-fx/src/fxs/useNoise/noise.glsl.ts b/packages/use-shader-fx/src/hooks/useNoise/noise.glsl.ts similarity index 94% rename from packages/use-shader-fx/src/fxs/useNoise/noise.glsl.ts rename to packages/use-shader-fx/src/hooks/useNoise/noise.glsl.ts index 95506cfc..15d06691 100644 --- a/packages/use-shader-fx/src/fxs/useNoise/noise.glsl.ts +++ b/packages/use-shader-fx/src/hooks/useNoise/noise.glsl.ts @@ -1,18 +1,14 @@ import { ShaderLib } from "../../libs/shaders/ShaderLib"; export const noiseVertex = ` - ${ShaderLib.basicFx_pars_vertex} void main() { - ${ShaderLib.basicFx_vertex} - gl_Position = vec4(position, 1.0); + ${ShaderLib.plane_vertex} } `; export const noiseFragment = ` precision highp int; - ${ShaderLib.basicFx_pars_fragment} - uniform float tick; uniform float timeStrength; uniform int noiseOctaves; diff --git a/packages/use-shader-fx/src/fxs/useRawBlank/RawBlankMaterial.ts b/packages/use-shader-fx/src/hooks/useRawBlank/RawBlankMaterial.ts similarity index 100% rename from packages/use-shader-fx/src/fxs/useRawBlank/RawBlankMaterial.ts rename to packages/use-shader-fx/src/hooks/useRawBlank/RawBlankMaterial.ts diff --git a/packages/use-shader-fx/src/fxs/useRawBlank/index.ts b/packages/use-shader-fx/src/hooks/useRawBlank/index.ts similarity index 100% rename from packages/use-shader-fx/src/fxs/useRawBlank/index.ts rename to packages/use-shader-fx/src/hooks/useRawBlank/index.ts diff --git a/packages/use-shader-fx/src/index.js b/packages/use-shader-fx/src/index.js index da3740ac..c928b1ba 100644 --- a/packages/use-shader-fx/src/index.js +++ b/packages/use-shader-fx/src/index.js @@ -1,7 +1,8 @@ /*=============================================== FXs ===============================================*/ -export * from "./fxs/useNoise"; -export * from "./fxs/useFluid"; -export * from "./fxs/useCoverTexture"; -export * from "./fxs/useRawBlank"; +export * from "./hooks/useNoise"; +export * from "./hooks/useFluid"; +export * from "./hooks/useCoverTexture"; +export * from "./hooks/useRawBlank"; +export * from "./hooks/useBlur"; diff --git a/packages/use-shader-fx/src/libs/shaders/ShaderChunk.ts b/packages/use-shader-fx/src/libs/shaders/ShaderChunk.ts index 84f21fdd..f7336f01 100644 --- a/packages/use-shader-fx/src/libs/shaders/ShaderChunk.ts +++ b/packages/use-shader-fx/src/libs/shaders/ShaderChunk.ts @@ -1,5 +1,7 @@ import default_pars_fragment from "./ShaderChunk/default_pars_fragment.glsl"; import default_pars_vertex from "./ShaderChunk/default_pars_vertex.glsl"; +import default_vertex from "./ShaderChunk/default_vertex.glsl"; +import plane_vertex from "./ShaderChunk/plane_vertex.glsl"; import mixSrc_fragment_begin from "./ShaderChunk/mixSrc_fragment_begin.glsl"; import mixSrc_fragment_end from "./ShaderChunk/mixSrc_fragment_end.glsl"; import mixSrc_pars_fragment from "./ShaderChunk/mixSrc_pars_fragment.glsl"; @@ -13,6 +15,8 @@ import mixDst_vertex from "./ShaderChunk/mixDst_vertex.glsl"; export type ShaderChunkTypes = | "default_pars_fragment" | "default_pars_vertex" + | "default_vertex" + | "plane_vertex" | "mixSrc_fragment_begin" | "mixSrc_fragment_end" | "mixSrc_pars_fragment" @@ -26,6 +30,8 @@ export type ShaderChunkTypes = export const ShaderChunk: { [K in ShaderChunkTypes]: string } = Object.freeze({ default_pars_fragment, default_pars_vertex, + default_vertex, + plane_vertex, mixSrc_fragment_begin, mixSrc_fragment_end, mixSrc_pars_fragment, diff --git a/packages/use-shader-fx/src/libs/shaders/ShaderChunk/default_vertex.glsl b/packages/use-shader-fx/src/libs/shaders/ShaderChunk/default_vertex.glsl new file mode 100644 index 00000000..06d19f37 --- /dev/null +++ b/packages/use-shader-fx/src/libs/shaders/ShaderChunk/default_vertex.glsl @@ -0,0 +1 @@ +vUv = uv; \ No newline at end of file diff --git a/packages/use-shader-fx/src/libs/shaders/ShaderChunk/plane_vertex.glsl b/packages/use-shader-fx/src/libs/shaders/ShaderChunk/plane_vertex.glsl new file mode 100644 index 00000000..bd687d85 --- /dev/null +++ b/packages/use-shader-fx/src/libs/shaders/ShaderChunk/plane_vertex.glsl @@ -0,0 +1 @@ +gl_Position = vec4(position, 1.0); \ No newline at end of file diff --git a/packages/use-shader-fx/src/libs/shaders/ShaderLib.ts b/packages/use-shader-fx/src/libs/shaders/ShaderLib.ts index 44d39c10..ee574367 100644 --- a/packages/use-shader-fx/src/libs/shaders/ShaderLib.ts +++ b/packages/use-shader-fx/src/libs/shaders/ShaderLib.ts @@ -6,6 +6,7 @@ import basicFx_pars_vertex from "./ShaderLib/basicFx_pars_vertex.glsl"; import default_pars_fragment from "./ShaderLib/default_pars_fragment.glsl"; import default_pars_vertex from "./ShaderLib/default_pars_vertex.glsl"; import default_vertex from "./ShaderLib/default_vertex.glsl"; +import plane_vertex from "./ShaderLib/plane_vertex.glsl"; export type ShaderLibTypes = | "basicFx_vertex" @@ -15,7 +16,8 @@ export type ShaderLibTypes = | "basicFx_pars_vertex" | "default_pars_fragment" | "default_pars_vertex" - | "default_vertex"; + | "default_vertex" + | "plane_vertex"; export const ShaderLib: { [K in ShaderLibTypes]: string } = Object.freeze({ basicFx_vertex, @@ -26,4 +28,5 @@ export const ShaderLib: { [K in ShaderLibTypes]: string } = Object.freeze({ default_pars_fragment, default_pars_vertex, default_vertex, + plane_vertex, }); diff --git a/packages/use-shader-fx/src/libs/shaders/ShaderLib/default_vertex.glsl b/packages/use-shader-fx/src/libs/shaders/ShaderLib/default_vertex.glsl index 06d19f37..69d54c90 100644 --- a/packages/use-shader-fx/src/libs/shaders/ShaderLib/default_vertex.glsl +++ b/packages/use-shader-fx/src/libs/shaders/ShaderLib/default_vertex.glsl @@ -1 +1 @@ -vUv = uv; \ No newline at end of file +#usf \ No newline at end of file diff --git a/packages/use-shader-fx/src/libs/shaders/ShaderLib/plane_vertex.glsl b/packages/use-shader-fx/src/libs/shaders/ShaderLib/plane_vertex.glsl new file mode 100644 index 00000000..a2b40495 --- /dev/null +++ b/packages/use-shader-fx/src/libs/shaders/ShaderLib/plane_vertex.glsl @@ -0,0 +1 @@ +#usf \ No newline at end of file diff --git a/todo b/todo index 3f4793ad..e69de29b 100644 --- a/todo +++ b/todo @@ -1,17 +0,0 @@ -- useBlankの設計まとめる -- usf wip - - blank つくって水面のやつで -- 設計まとめ、ろくくんに引き継ぐ - -- pixelateつくる -- grain をbasic fxに -- 流体まとめる - -- grain、暗くならないような工夫 - - -- useNoiseのtickの処理を確認 - - valuesの値はuniformと一致させるべき - - 一致しないものはconfigsで設定する - - useBlankで例つくる -- \ No newline at end of file From 8d8b6330d98db9f1516fcd7eb71e8f8f0a770613 Mon Sep 17 00:00:00 2001 From: takuma-hmng8 Date: Wed, 2 Oct 2024 21:32:14 +0900 Subject: [PATCH 09/60] update --- app/cream/FxMaterial.tsx | 41 ---- app/cream/Playground.tsx | 40 ---- app/cream/page.tsx | 18 -- app/domSyncer/DomSyncer.tsx | 166 -------------- app/domSyncer/page.tsx | 103 --------- app/expo2025/FxMaterial.tsx | 38 ---- app/expo2025/Playground.tsx | 179 --------------- app/expo2025/page.tsx | 18 -- app/gradation/FxMaterial.tsx | 34 --- app/gradation/Playground.tsx | 100 --------- app/gradation/main.frag | 23 -- app/gradation/page.tsx | 18 -- app/obscurus/FxMaterial.tsx | 38 ---- app/obscurus/Playground.tsx | 210 ------------------ app/obscurus/page.tsx | 18 -- app/playground/FxMaterial.tsx | 38 ---- app/playground/Playground.tsx | 80 ------- app/playground/page.tsx | 18 -- app/shoasakawa-0/FxMaterial.tsx | 38 ---- app/shoasakawa-0/Playground.tsx | 182 --------------- app/shoasakawa-0/page.tsx | 33 --- app/useBlank/FxMaterial.tsx | 38 ---- app/useBlank/Playground.tsx | 67 ------ app/useBlank/page.tsx | 18 -- app/useMorphParticles/FxMaterial.tsx | 30 --- app/useMorphParticles/Playground.tsx | 192 ---------------- app/useMorphParticles/main.frag | 7 - app/useMorphParticles/page.tsx | 18 -- app/useWobble3D/FxMaterial.tsx | 38 ---- app/useWobble3D/Playground.tsx | 173 --------------- app/useWobble3D/page.tsx | 18 -- app/v2/Playground.tsx | 21 +- app/v2_FxRenderer/Playground.tsx | 52 +++-- .../src/hooks/useBlur/BlurMaterial.ts | 6 +- .../src/hooks/useBlur/blur.glsl.ts | 1 - .../use-shader-fx/src/hooks/useBlur/index.ts | 2 +- .../useCoverTexture/CoverTextureMaterial.ts | 6 +- .../src/hooks/useCoverTexture/index.ts | 2 +- .../useFluid/materials/AdvectionMaterial.ts | 2 +- .../useFluid/materials/DivergenceMaterial.ts | 2 +- .../useFluid/materials/PoissonMaterial.ts | 2 +- .../useFluid/materials/PressureMaterial.ts | 2 +- .../hooks/useFluid/materials/SplatMaterial.ts | 2 +- .../src/hooks/useNoise/NoiseMaterial.ts | 6 +- .../use-shader-fx/src/hooks/useNoise/index.ts | 2 +- .../src/hooks/useRawBlank/RawBlankMaterial.ts | 2 +- .../src/hooks/useRawBlank/index.ts | 2 +- packages/use-shader-fx/src/index.js | 12 + .../src/{hooks => }/materials/BasicFxLib.ts | 0 .../materials/FxBasicFxMaterial.ts | 2 +- .../src/materials/FxBasicFxMaterialImpl.ts | 92 ++++++++ .../src/{hooks => }/materials/FxMaterial.ts | 21 +- .../src/materials/FxMaterialImpl.ts | 72 ++++++ packages/use-shader-fx/src/utils/useCamera.ts | 31 ++- .../use-shader-fx/src/utils/useDoubleFBO.ts | 7 +- packages/use-shader-fx/src/utils/useDpr.ts | 2 +- .../use-shader-fx/src/utils/useFxScene.ts | 20 +- .../use-shader-fx/src/utils/useObject3D.ts | 4 +- .../use-shader-fx/src/utils/useResolution.ts | 2 +- .../use-shader-fx/src/utils/useSingleFBO.ts | 48 ++-- todo | 2 + utils/useGUI.ts | 5 +- 62 files changed, 320 insertions(+), 2144 deletions(-) delete mode 100644 app/cream/FxMaterial.tsx delete mode 100644 app/cream/Playground.tsx delete mode 100644 app/cream/page.tsx delete mode 100644 app/domSyncer/DomSyncer.tsx delete mode 100644 app/domSyncer/page.tsx delete mode 100644 app/expo2025/FxMaterial.tsx delete mode 100644 app/expo2025/Playground.tsx delete mode 100644 app/expo2025/page.tsx delete mode 100644 app/gradation/FxMaterial.tsx delete mode 100644 app/gradation/Playground.tsx delete mode 100644 app/gradation/main.frag delete mode 100644 app/gradation/page.tsx delete mode 100644 app/obscurus/FxMaterial.tsx delete mode 100644 app/obscurus/Playground.tsx delete mode 100644 app/obscurus/page.tsx delete mode 100644 app/playground/FxMaterial.tsx delete mode 100644 app/playground/Playground.tsx delete mode 100644 app/playground/page.tsx delete mode 100644 app/shoasakawa-0/FxMaterial.tsx delete mode 100644 app/shoasakawa-0/Playground.tsx delete mode 100644 app/shoasakawa-0/page.tsx delete mode 100644 app/useBlank/FxMaterial.tsx delete mode 100644 app/useBlank/Playground.tsx delete mode 100644 app/useBlank/page.tsx delete mode 100644 app/useMorphParticles/FxMaterial.tsx delete mode 100644 app/useMorphParticles/Playground.tsx delete mode 100644 app/useMorphParticles/main.frag delete mode 100644 app/useMorphParticles/page.tsx delete mode 100644 app/useWobble3D/FxMaterial.tsx delete mode 100644 app/useWobble3D/Playground.tsx delete mode 100644 app/useWobble3D/page.tsx rename packages/use-shader-fx/src/{hooks => }/materials/BasicFxLib.ts (100%) rename packages/use-shader-fx/src/{hooks => }/materials/FxBasicFxMaterial.ts (97%) create mode 100644 packages/use-shader-fx/src/materials/FxBasicFxMaterialImpl.ts rename packages/use-shader-fx/src/{hooks => }/materials/FxMaterial.ts (80%) create mode 100644 packages/use-shader-fx/src/materials/FxMaterialImpl.ts diff --git a/app/cream/FxMaterial.tsx b/app/cream/FxMaterial.tsx deleted file mode 100644 index 8f28d08b..00000000 --- a/app/cream/FxMaterial.tsx +++ /dev/null @@ -1,41 +0,0 @@ -import * as THREE from "three"; -import { shaderMaterial } from "@react-three/drei"; - -declare global { - namespace JSX { - interface IntrinsicElements { - fxMaterial: any; - } - } -} - -export type FxMaterialProps = { - u_fx: THREE.Texture; -}; - -export const FxMaterial = shaderMaterial( - { - u_fx: new THREE.Texture(), - }, - - ` - varying vec2 vUv; - void main() { - vUv = uv; - gl_Position = vec4(position, 1.0); - } - `, - ` - precision highp float; - varying vec2 vUv; - uniform sampler2D u_fx; - - void main() { - vec2 uv = vUv; - vec4 color = texture2D(u_fx, uv); - gl_FragColor = color; - // gl_FragColor.rgb = color.rgb; - // gl_FragColor.a = color.r + color.g + color.b; - } - ` -); diff --git a/app/cream/Playground.tsx b/app/cream/Playground.tsx deleted file mode 100644 index cc5c4aab..00000000 --- a/app/cream/Playground.tsx +++ /dev/null @@ -1,40 +0,0 @@ -"use client"; - -import * as THREE from "three"; -import { useEffect, useMemo, useRef, useState } from "react"; -import { useFrame, useThree, extend, useLoader } from "@react-three/fiber"; -import { useFluid } from "@/packages/use-shader-fx/src"; -import { FxMaterial } from "./FxMaterial"; - -extend({ FxMaterial }); - -export const Playground = () => { - const { size } = useThree(); - const [updateFluid, setFluid, { output: fluid }] = useFluid({ - size, - dpr: { - shader: 0.2, - fbo: 0.8, - }, - }); - - setFluid({ - densityDissipation: 0.99, - velocityDissipation: 0.99, - splatRadius: 0.001, - pressureIterations: 1, - }); - - useFrame((state) => { - updateFluid(state); - }); - - return ( - <> - - - - - - ); -}; diff --git a/app/cream/page.tsx b/app/cream/page.tsx deleted file mode 100644 index 4afc0060..00000000 --- a/app/cream/page.tsx +++ /dev/null @@ -1,18 +0,0 @@ -import { ShaderFx } from "../ShaderFx"; -import { Playground } from "./Playground"; - -export default function Page() { - return ( -
    - - - -
    - ); -} diff --git a/app/domSyncer/DomSyncer.tsx b/app/domSyncer/DomSyncer.tsx deleted file mode 100644 index 23516103..00000000 --- a/app/domSyncer/DomSyncer.tsx +++ /dev/null @@ -1,166 +0,0 @@ -import * as THREE from "three"; -import { useEffect, useLayoutEffect, useRef } from "react"; -import { useFrame, extend, useThree, useLoader } from "@react-three/fiber"; -import { FxMaterial, FxMaterialProps } from "@/utils/fxMaterial"; -import { - useDomSyncer, - useWave, - useFxTexture, - useCopyTexture, -} from "@/packages/use-shader-fx/src"; -import { WaveParams } from "@/packages/use-shader-fx/src/fxs/effects/useWave"; -import gsap from "gsap"; - -extend({ FxMaterial }); - -const CONFIG: { - textureResolution: THREE.Vector2; - waveArr: WaveParams[]; - waveConfig: WaveParams; -} = { - textureResolution: new THREE.Vector2(1440, 1029), - waveArr: [], - waveConfig: { - epicenter: new THREE.Vector2(0.0, 0.0), - progress: 0.0, - strength: 0.2, - }, -}; - -export const DomSyncer = ({ state }: { state: number }) => { - useEffect(() => { - document.documentElement.style.overflow = "auto"; - }); - - const mainShaderRef = useRef(); - const textureRef = useRef(new THREE.Texture()); - - const [momo] = useLoader(THREE.TextureLoader, ["momo.jpg"]); - - const { size, dpr } = useThree((state) => { - return { size: state.size, dpr: state.viewport.dpr }; - }); - - const [updateFxTexture, , fxTextureObj] = useFxTexture({ size, dpr }); - const [updateWave] = useWave({ size, dpr }); - - const [updateDomSyncer, setDomSyncer, domSyncerObj] = useDomSyncer( - { size, dpr }, - [state] - ); - - const { setFrameloop } = useThree(); - domSyncerObj.useDomView({ - onView: () => { - console.log("play"); - setFrameloop("always"); - }, - onHidden: () => { - console.log("stop"); - setFrameloop("never"); - }, - }); - - const domArr = useRef<(HTMLElement | Element)[]>([]); - const contentArr = useRef([]); - - useLayoutEffect(() => { - CONFIG.waveArr = []; - - if (state === 0) { - domArr.current = [...document.querySelectorAll(".item")!]; - contentArr.current = Array.from( - document.querySelectorAll(".content") - ); - } else { - domArr.current = [...document.querySelectorAll(".item2")!]; - contentArr.current = Array.from( - document.querySelectorAll(".content2") - ); - } - CONFIG.waveArr = [...Array(domArr.current.length)].map(() => ({ - ...CONFIG.waveConfig, - })); - - setDomSyncer({ - dom: domArr.current, - updateKey: performance.now(), - boderRadius: [...Array(domArr.current.length)].map((_, i) => i * 50.0), - rotation: [...Array(domArr.current.length)].map( - (_, i) => new THREE.Euler(0.0, 0.0, i * 0.1) - ), - onIntersect: [...Array(domArr.current.length)].map( - (_, i) => (entry) => { - if ( - entry.isIntersecting && - !domSyncerObj.isIntersecting(i, false) - ) { - gsap.fromTo( - CONFIG.waveArr[i], - { - progress: 0.0, - }, - { - progress: 1.0, - duration: 10.0, - } - ); - } - } - ), - }); - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [state]); - - const [, copyTexture] = useCopyTexture( - { scene: fxTextureObj.scene, camera: fxTextureObj.camera, size, dpr }, - domArr.current.length - ); - - useFrame((state) => { - const syncedTexture = updateDomSyncer(state, { - texture: [...Array(domArr.current.length)].map((_, i) => { - if (domSyncerObj.isIntersecting(i, false)) { - updateFxTexture(state, { - padding: 0.0, - map: updateWave(state, { - epicenter: CONFIG.waveArr[i].epicenter, - progress: CONFIG.waveArr[i].progress, - strength: CONFIG.waveArr[i].strength, - }), - mapIntensity: 0.4, - edgeIntensity: 0.0, - texture0: momo, - }); - - return copyTexture(state.gl, i); - } - return textureRef.current; - }), - }); - - contentArr.current.forEach((content, i) => { - if ( - domSyncerObj.DOMRects[i] && - domSyncerObj.isIntersecting(i, false) - ) { - content.style.opacity = "1.0"; - content.style.top = `${domSyncerObj.DOMRects[i].top}px`; - content.style.left = `${domSyncerObj.DOMRects[i].left}px`; - } - }); - - const main = mainShaderRef.current; - if (main) { - main.u_fx = syncedTexture; - main.u_alpha = 0.0; - } - }); - - return ( - - - - - ); -}; diff --git a/app/domSyncer/page.tsx b/app/domSyncer/page.tsx deleted file mode 100644 index 53e48e79..00000000 --- a/app/domSyncer/page.tsx +++ /dev/null @@ -1,103 +0,0 @@ -"use client"; - -import { useState } from "react"; -import { ShaderFx } from "../ShaderFx"; -import { DomSyncer } from "./DomSyncer"; - -export default function Page() { - const [domSwitch, setDomSwitch] = useState(0); - return ( - <> -
    - - - -
    - -
    - {domSwitch === 0 ? ( - <> - {[...Array(4)].map((_, i) => ( -
    -
    -
    -

    title

    -

    text

    -
    -
    - ))} - - ) : ( - <> - {[...Array(2)].map((_, i) => ( -
    -
    -
    -

    title

    -

    text

    -
    -
    - ))} - - )} -
    -
    - - ); -} diff --git a/app/expo2025/FxMaterial.tsx b/app/expo2025/FxMaterial.tsx deleted file mode 100644 index d1a9c743..00000000 --- a/app/expo2025/FxMaterial.tsx +++ /dev/null @@ -1,38 +0,0 @@ -import * as THREE from "three"; -import { shaderMaterial } from "@react-three/drei"; - -declare global { - namespace JSX { - interface IntrinsicElements { - fxMaterial: any; - } - } -} - -export type FxMaterialProps = { - u_fx: THREE.Texture; -}; - -export const FxMaterial = shaderMaterial( - { - u_fx: new THREE.Texture(), - }, - - ` - varying vec2 vUv; - void main() { - vUv = uv; - gl_Position = vec4(position, 1.0); - } - `, - ` - precision highp float; - varying vec2 vUv; - uniform sampler2D u_fx; - - void main() { - gl_FragColor = texture2D(u_fx,vUv); - // gl_FragColor = vec4(1.,1.,0.,1.); - } - ` -); diff --git a/app/expo2025/Playground.tsx b/app/expo2025/Playground.tsx deleted file mode 100644 index b035a57b..00000000 --- a/app/expo2025/Playground.tsx +++ /dev/null @@ -1,179 +0,0 @@ -"use client"; - -import * as THREE from "three"; -import { useMemo, useRef } from "react"; -import { useFrame, useThree, extend, MeshProps } from "@react-three/fiber"; -import { - useCreateWobble3D, - Wobble3DParams, - WOBBLE3D_PARAMS, -} from "@/packages/use-shader-fx/src"; -import { FxMaterial } from "./FxMaterial"; -import GUI from "lil-gui"; -import { useGUI } from "@/utils/useGUI"; -import { Environment, Lightformer } from "@react-three/drei"; - -extend({ FxMaterial }); - -const CONFIG: Wobble3DParams = { - ...structuredClone(WOBBLE3D_PARAMS), - wobbleStrength: 0.16, - wobbleTimeFrequency: 0.2, - warpStrength: 0.0, - colorMix: 0, -}; - -const setGUI = (gui: GUI) => { - gui.addColor(CONFIG, "color0"); - gui.addColor(CONFIG, "color1"); - gui.addColor(CONFIG, "color2"); - gui.addColor(CONFIG, "color3"); - gui.add(CONFIG, "wobbleStrength", 0, 2, 0.01); - gui.add(CONFIG, "colorMix", 0, 1, 0.01); - return gui; -}; -const setConfig = () => { - return { - ...CONFIG, - } as Wobble3DParams; -}; - -const MyakuMyaku = (props: MeshProps) => { - const [updateWobble, wobble] = useCreateWobble3D({ - baseMaterial: THREE.MeshStandardMaterial, - materialParameters: useMemo( - () => ({ - color: new THREE.Color(0xd53220), - metalness: 0.16, - roughness: 0.16, - }), - [] - ), - onBeforeInit: (params) => { - Object.assign(params.uniforms, { - uEyeColor: { value: new THREE.Color(0x2469b3) }, - uEyeMoving: { value: new THREE.Vector2(0, 0) }, - }); - params.fragmentShader = params.fragmentShader.replace( - "uniform float uRefractionSamples;", - ` - uniform float uRefractionSamples; - uniform vec2 uEyeMoving; - uniform vec3 uEyeColor; - ` - ); - params.fragmentShader = params.fragmentShader.replace( - "#include ", - ` - float whiteDist = distance(uEyeMoving * 0.4,vPosition); - float blackDist = distance(uEyeMoving * 0.8,vPosition); - if (whiteDist < .8) { - diffuseColor = vec4(vec3(1.), 1.0); - } - if (blackDist < .34) { - diffuseColor = vec4(uEyeColor, 1.0); - } - #include - ` - ); - }, - }); - const pointerVector = useRef(new THREE.Vector2(0, 0)); - const randomness = useMemo(() => Math.random() + 1, []); - useFrame((rootState) => { - updateWobble( - rootState, - { - ...setConfig(), - wobbleStrength: CONFIG.wobbleStrength! * randomness, - wobbleTimeFrequency: CONFIG.wobbleTimeFrequency! * randomness, - }, - { - uEyeMoving: pointerVector.current.lerp(rootState.pointer, 0.24), - } - ); - }); - return ( - - - - ); -}; - -export const Playground = () => { - const updateGUI = useGUI(setGUI); - - const { camera } = useThree(); - - const cameraVec = useRef(new THREE.Vector3(0, 0, 0)); - useFrame((props) => { - camera.position.lerp( - cameraVec.current.set(props.pointer.y * 3, props.pointer.x * 3, 12), - 0.1 - ); - camera.lookAt(0, 0, 0); - - updateGUI(); - }); - - return ( - - - - - - - - - - - - - - - - - - - - - ); -}; diff --git a/app/expo2025/page.tsx b/app/expo2025/page.tsx deleted file mode 100644 index a84dd222..00000000 --- a/app/expo2025/page.tsx +++ /dev/null @@ -1,18 +0,0 @@ -import { ShaderFx } from "../ShaderFx"; -import { Playground } from "./Playground"; - -export default function Page() { - return ( -
    - - - -
    - ); -} diff --git a/app/gradation/FxMaterial.tsx b/app/gradation/FxMaterial.tsx deleted file mode 100644 index 98a03717..00000000 --- a/app/gradation/FxMaterial.tsx +++ /dev/null @@ -1,34 +0,0 @@ -import * as THREE from "three"; -import { shaderMaterial } from "@react-three/drei"; -import fragment from "./main.frag"; - -declare global { - namespace JSX { - interface IntrinsicElements { - fxMaterial: any; - } - } -} - -export type FxMaterialProps = { - u_noise: THREE.Texture; - u_colorStrata: THREE.Texture; - u_noiseIntensity: number; -}; - -export const FxMaterial = shaderMaterial( - { - u_noise: new THREE.Texture(), - u_colorStrata: new THREE.Texture(), - u_noiseIntensity: 1, - }, - - ` - varying vec2 vUv; - void main() { - vUv = uv; - gl_Position = vec4(position, 1.0); - } - `, - fragment -); diff --git a/app/gradation/Playground.tsx b/app/gradation/Playground.tsx deleted file mode 100644 index 35fa8afe..00000000 --- a/app/gradation/Playground.tsx +++ /dev/null @@ -1,100 +0,0 @@ -"use client"; - -import * as THREE from "three"; -import { useMemo, useRef } from "react"; -import { useFrame, useThree, extend } from "@react-three/fiber"; -import { - useColorStrata, - useMarble, - useHSV, - ColorStrataParams, - HSVParams, - MarbleParams, -} from "@/packages/use-shader-fx/src"; -import { FxMaterial, FxMaterialProps } from "./FxMaterial"; -import GUI from "lil-gui"; -import { useGUI } from "@/utils/useGUI"; -import { CONFIG as HomeConfig } from "../_home/Playground"; -import { useDownloadCanvas } from "@/utils/useDownloadCanvas"; - -extend({ FxMaterial }); - -const CONFIG = { - ...HomeConfig, - save: () => {}, -}; -const setGUI = (gui: GUI) => { - gui.add(CONFIG, "random").name("Randomize"); - gui.add(CONFIG, "save").name("Save"); -}; - -const setConfig = (key: "marble" | "colorStrata" | "hsv") => { - return { - ...CONFIG[key], - }; -}; - -export const Playground = () => { - const ref = useRef(); - - const saveImage = useDownloadCanvas(); - - useMemo(() => { - CONFIG.save = saveImage; - CONFIG.random(); - }, [saveImage]); - useGUI(setGUI); - - const { size, viewport } = useThree(); - - const [updateColorStrata, setColorStrata, { output: colorStrata }] = - useColorStrata({ size, dpr: viewport.dpr }); - const [updateMarble, setMarble, { output: marble }] = useMarble({ - size, - dpr: viewport.dpr, - }); - const [updateHSV, setHSV, { output: hsv }] = useHSV({ - size, - dpr: viewport.dpr, - }); - - setMarble({ - ...setConfig("marble"), - timeStrength: 0, - }); - - setColorStrata({ - ...setConfig("colorStrata"), - timeStrength: new THREE.Vector2(0, 0), - }); - - setHSV({ - ...setConfig("hsv"), - texture: colorStrata, - }); - - useFrame((state) => { - updateColorStrata(state, { - ...(setConfig("colorStrata") as ColorStrataParams), - }); - updateHSV(state, { - ...(setConfig("hsv") as HSVParams), - }); - updateMarble(state, { - ...(setConfig("marble") as MarbleParams), - }); - ref.current!.u_noiseIntensity = CONFIG.noiseIntensity; - }); - - return ( - - - - - ); -}; diff --git a/app/gradation/main.frag b/app/gradation/main.frag deleted file mode 100644 index c696b891..00000000 --- a/app/gradation/main.frag +++ /dev/null @@ -1,23 +0,0 @@ -precision highp float; -varying vec2 vUv; -uniform sampler2D u_noise; -uniform float u_noiseIntensity; -uniform sampler2D u_colorStrata; - -float rand(vec2 n) { - return fract(sin(dot(n ,vec2(12.9898,78.233))) * 43758.5453); -} - -void main() { - - vec2 uv = vUv; - float grain = rand(uv) * 0.1; - vec4 noise = texture2D(u_noise, uv); - - uv += grain; - uv += noise.rg * u_noiseIntensity; - vec4 colorStrata = texture2D(u_colorStrata,uv); - - gl_FragColor = colorStrata; - gl_FragColor.a = 1.0; -} \ No newline at end of file diff --git a/app/gradation/page.tsx b/app/gradation/page.tsx deleted file mode 100644 index 0d7658ef..00000000 --- a/app/gradation/page.tsx +++ /dev/null @@ -1,18 +0,0 @@ -import { ShaderFx } from "../ShaderFx"; -import { Playground } from "./Playground"; - -export default function Page() { - return ( -
    - - - -
    - ); -} diff --git a/app/obscurus/FxMaterial.tsx b/app/obscurus/FxMaterial.tsx deleted file mode 100644 index d1a9c743..00000000 --- a/app/obscurus/FxMaterial.tsx +++ /dev/null @@ -1,38 +0,0 @@ -import * as THREE from "three"; -import { shaderMaterial } from "@react-three/drei"; - -declare global { - namespace JSX { - interface IntrinsicElements { - fxMaterial: any; - } - } -} - -export type FxMaterialProps = { - u_fx: THREE.Texture; -}; - -export const FxMaterial = shaderMaterial( - { - u_fx: new THREE.Texture(), - }, - - ` - varying vec2 vUv; - void main() { - vUv = uv; - gl_Position = vec4(position, 1.0); - } - `, - ` - precision highp float; - varying vec2 vUv; - uniform sampler2D u_fx; - - void main() { - gl_FragColor = texture2D(u_fx,vUv); - // gl_FragColor = vec4(1.,1.,0.,1.); - } - ` -); diff --git a/app/obscurus/Playground.tsx b/app/obscurus/Playground.tsx deleted file mode 100644 index ed47aed6..00000000 --- a/app/obscurus/Playground.tsx +++ /dev/null @@ -1,210 +0,0 @@ -"use client"; - -import * as THREE from "three"; -import { useMemo } from "react"; -import { useFrame, useThree, extend, useLoader } from "@react-three/fiber"; -import { - useCreateWobble3D, - Wobble3DParams, - WOBBLE3D_PARAMS, - useCreateMorphParticles, - MorphParticlesParams, - MORPHPARTICLES_PARAMS, -} from "@/packages/use-shader-fx/src"; -import { FxMaterial } from "./FxMaterial"; -import GUI from "lil-gui"; -import { useGUI } from "@/utils/useGUI"; -import { OrbitControls, Environment } from "@react-three/drei"; - -extend({ FxMaterial }); - -const WOBBLE_CONFIG: Wobble3DParams = { - ...structuredClone(WOBBLE3D_PARAMS), - color0: new THREE.Color(0x000000), - color1: new THREE.Color(0x000000), - color2: new THREE.Color(0x000000), - color3: new THREE.Color(0x000000), - wobbleStrength: 0.35, - wobbleTimeFrequency: 0.2, - warpStrength: 0.2, - colorMix: 0.3, - chromaticAberration: 0.05, - anisotropicBlur: 0.2, - distortion: 0.3, - distortionScale: 0.5, - temporalDistortion: 0.3, -}; - -const MATERIAL_CONFIG: THREE.MeshPhysicalMaterialParameters = { - iridescence: 0.1, - metalness: 0.0, - roughness: 0.0, - transmission: 2, - thickness: 1.2, - transparent: true, -}; - -const PARTICLE_CONFIG: MorphParticlesParams = { - ...structuredClone(MORPHPARTICLES_PARAMS), - blurAlpha: 0.01, - blurRadius: 0.6, - pointSize: 0.4, - sizeRandomIntensity: 1, - sizeRandomMax: 2.5, - sizeRandomMin: 0.8, - sizeRandomTimeFrequency: 1, - color0: new THREE.Color(0x000000), - color1: new THREE.Color(0x000000), - color2: new THREE.Color(0x000000), - color3: new THREE.Color(0x000000), - wobbleStrength: 0.6, - warpStrength: 3, - wobblePositionFrequency: 0.4, - wobbleTimeFrequency: 0.4, - warpTimeFrequency: 0.2, -}; - -const setGUI = (gui: GUI) => { - const wobble = gui.addFolder("Wobble3D"); - wobble.addColor(WOBBLE_CONFIG, "color0"); - wobble.addColor(WOBBLE_CONFIG, "color1"); - wobble.addColor(WOBBLE_CONFIG, "color2"); - wobble.addColor(WOBBLE_CONFIG, "color3"); - wobble.add(WOBBLE_CONFIG, "wobbleStrength", 0, 10, 0.01); - wobble.add(WOBBLE_CONFIG, "wobblePositionFrequency", 0, 10, 0.01); - wobble.add(WOBBLE_CONFIG, "wobbleTimeFrequency", 0, 10, 0.01); - wobble.add(WOBBLE_CONFIG, "warpStrength", 0, 10, 0.01); - wobble.add(WOBBLE_CONFIG, "warpPositionFrequency", 0, 10, 0.01); - wobble.add(WOBBLE_CONFIG, "warpTimeFrequency", 0, 10, 0.01); - // wobble.add(WOBBLE_CONFIG, "wobbleShine", 0, 5, 0.01); - // wobble.add(WOBBLE_CONFIG, "samples", 0, 10, 1); - wobble.add(WOBBLE_CONFIG, "colorMix", 0, 1, 0.01); - wobble.add(WOBBLE_CONFIG, "chromaticAberration", 0, 10, 0.01); - wobble.add(WOBBLE_CONFIG, "anisotropicBlur", 0, 10, 0.01); - wobble.add(WOBBLE_CONFIG, "distortion", 0, 10, 0.01); - wobble.add(WOBBLE_CONFIG, "distortionScale", 0, 10, 0.01); - wobble.add(WOBBLE_CONFIG, "temporalDistortion", 0, 10, 0.01); - - const mpm = gui.addFolder("MeshPhysicalMaterial"); - mpm.add(MATERIAL_CONFIG, "iridescence", 0, 1, 0.01); - mpm.add(MATERIAL_CONFIG, "metalness", 0, 1, 0.01); - mpm.add(MATERIAL_CONFIG, "roughness", 0, 1, 0.01); - mpm.add(MATERIAL_CONFIG, "transmission", 0, 10, 0.01); - mpm.add(MATERIAL_CONFIG, "thickness", 0, 10, 0.01); - - const particle = gui.addFolder("MorphParticles"); - particle.add(PARTICLE_CONFIG, "blurAlpha", 0, 1, 0.01); - particle.add(PARTICLE_CONFIG, "blurRadius", 0, 2, 0.01); - particle.add(PARTICLE_CONFIG, "pointSize", 0.01, 2, 0.01); - particle.addColor(PARTICLE_CONFIG, "color0"); - particle.addColor(PARTICLE_CONFIG, "color1"); - particle.addColor(PARTICLE_CONFIG, "color2"); - particle.addColor(PARTICLE_CONFIG, "color3"); - particle.add(PARTICLE_CONFIG, "wobbleStrength", 0, 10, 0.01); - particle.add(PARTICLE_CONFIG, "wobblePositionFrequency", 0, 10, 0.01); - particle.add(PARTICLE_CONFIG, "wobbleTimeFrequency", 0, 10, 0.01); - particle.add(PARTICLE_CONFIG, "warpStrength", 0, 10, 0.01); - particle.add(PARTICLE_CONFIG, "warpPositionFrequency", 0, 10, 0.01); - particle.add(PARTICLE_CONFIG, "warpTimeFrequency", 0, 10, 0.01); - particle.add(PARTICLE_CONFIG, "displacementIntensity", 0, 10, 0.01); - particle.add(PARTICLE_CONFIG, "displacementColorIntensity", 0, 40, 0.01); - particle.add(PARTICLE_CONFIG, "sizeRandomIntensity", 0, 10, 0.01); - particle.add(PARTICLE_CONFIG, "sizeRandomTimeFrequency", 0, 3, 0.01); - particle.add(PARTICLE_CONFIG, "sizeRandomMin", 0, 1, 0.01); - particle.add(PARTICLE_CONFIG, "sizeRandomMax", 1, 2, 0.01); - particle.add(PARTICLE_CONFIG, "divergence", -2, 2, 0.1); - return gui; -}; -const setParticleConfig = () => { - return { - ...PARTICLE_CONFIG, - } as MorphParticlesParams; -}; -const setWobbleConfig = () => { - return { - ...WOBBLE_CONFIG, - } as Wobble3DParams; -}; - -export const Playground = () => { - useGUI(setGUI); - const { size, viewport, camera } = useThree(); - const [noise] = useLoader(THREE.TextureLoader, ["/noise.jpg"]); - const [updateWobble, wobble] = useCreateWobble3D({ - geometry: useMemo(() => new THREE.IcosahedronGeometry(2.4, 10), []), - materialParameters: MATERIAL_CONFIG, - isCustomTransmission: true, - }); - const [updateParticle, particles] = useCreateMorphParticles({ - size, - dpr: viewport.dpr, - geometry: useMemo(() => new THREE.IcosahedronGeometry(0.8, 10), []), - }); - useMemo(() => { - particles.points.material.blending = THREE.NormalBlending; - camera.position.z = 8; - }, [particles.points.material, camera]); - useFrame((state) => { - updateWobble(state, { - ...setWobbleConfig(), - }); - const mat = wobble.mesh.material as THREE.MeshPhysicalMaterial; - mat.iridescence = MATERIAL_CONFIG.iridescence!; - mat.metalness = MATERIAL_CONFIG.metalness!; - mat.roughness = MATERIAL_CONFIG.roughness!; - mat.transmission = MATERIAL_CONFIG.transmission!; - mat.thickness = MATERIAL_CONFIG.thickness!; - updateParticle(state, { - ...setParticleConfig(), - alphaMap: noise, - }); - }); - - return ( - - - - - - - ); -}; - -/*=============================================== -simple version -===============================================*/ -// export const Playground = () => { -// const { size, viewport, camera } = useThree(); -// const [noise] = useLoader(THREE.TextureLoader, ["/noise.jpg"]); - -// const [updateWobble, wobble] = useCreateWobble3D({ -// baseMaterial: THREE.MeshPhysicalMaterial, -// geometry: useMemo(() => new THREE.IcosahedronGeometry(2.4, 10), []), -// materialParameters: MATERIAL_CONFIG, -// }); -// const [updateParticle, particles] = useCreateMorphParticles({ -// size, -// dpr: viewport.dpr, -// geometry: useMemo(() => new THREE.IcosahedronGeometry(0.8, 10), []), -// }); - -// useEffect(() => { -// particles.points.material.blending = THREE.NormalBlending; -// camera.position.z = 8; -// updateWobble(null, WOBBLE_CONFIG); -// updateParticle(null, { ...PARTICLE_CONFIG, alphaMap: noise }); -// }, [particles.points.material, camera, updateWobble, updateParticle, noise]); -// useFrame((props) => { -// updateWobble(props); -// updateParticle(props); -// }); - -// return ( -// -// -// -// -// -// -// ); -// }; diff --git a/app/obscurus/page.tsx b/app/obscurus/page.tsx deleted file mode 100644 index 4afc0060..00000000 --- a/app/obscurus/page.tsx +++ /dev/null @@ -1,18 +0,0 @@ -import { ShaderFx } from "../ShaderFx"; -import { Playground } from "./Playground"; - -export default function Page() { - return ( -
    - - - -
    - ); -} diff --git a/app/playground/FxMaterial.tsx b/app/playground/FxMaterial.tsx deleted file mode 100644 index b87eac16..00000000 --- a/app/playground/FxMaterial.tsx +++ /dev/null @@ -1,38 +0,0 @@ -import * as THREE from "three"; -import { shaderMaterial } from "@react-three/drei"; - -declare global { - namespace JSX { - interface IntrinsicElements { - fxMaterial: any; - } - } -} - -export type FxMaterialProps = { - u_fx: THREE.Texture; -}; - -export const FxMaterial = shaderMaterial( - { - u_fx: new THREE.Texture(), - }, - - ` - varying vec2 vUv; - void main() { - vUv = uv; - gl_Position = vec4(position, 1.0); - } - `, - ` - precision highp float; - varying vec2 vUv; - uniform sampler2D u_fx; - void main() { - vec2 uv = vUv; - vec4 color = texture2D(u_fx, uv); - gl_FragColor = color; - } - ` -); diff --git a/app/playground/Playground.tsx b/app/playground/Playground.tsx deleted file mode 100644 index 99a4c5b6..00000000 --- a/app/playground/Playground.tsx +++ /dev/null @@ -1,80 +0,0 @@ -"use client"; - -import * as THREE from "three"; -import { useCallback, useEffect, useMemo, useRef, useState } from "react"; -import { - useFrame, - useThree, - extend, - useLoader, - createPortal, -} from "@react-three/fiber"; -import { useRawBlank } from "@/packages/use-shader-fx/src"; -import { FxMaterial } from "./FxMaterial"; -import { OrbitControls, useVideoTexture } from "@react-three/drei"; - -extend({ FxMaterial }); - -export const Playground = () => { - const { size, viewport, camera } = useThree(); - - const [funkun] = useLoader(THREE.TextureLoader, ["/funkun.jpg"]); - - const [update, set, { output }] = useRawBlank({ - size, - dpr: 2, - onBeforeInit: (param) => { - Object.assign(param.uniforms, { - uTexture: { value: funkun }, - uTime: { value: 0 }, - }); - param.fragmentShader = param.fragmentShader.replace( - "#usf ", - ` - uniform sampler2D uTexture; - uniform float uTime; - ` - ); - param.fragmentShader = param.fragmentShader.replace( - "#usf
    ", - ` - vec2 uv = vUv; - vec2 perDivSize = vec2(20.) / uResolution; - vec4 outColor = vec4( - texture2D(uTexture, uv + perDivSize * vec2(-1.0, -1.0)) + - texture2D(uTexture, uv + perDivSize * vec2(0.0, -1.0)) + - texture2D(uTexture, uv + perDivSize * vec2(1.0, -1.0)) + - texture2D(uTexture, uv + perDivSize * vec2(-1.0, 0.0)) + - texture2D(uTexture, uv + perDivSize * vec2(0.0, 0.0)) + - texture2D(uTexture, uv + perDivSize * vec2(1.0, 0.0)) + - texture2D(uTexture, uv + perDivSize * vec2(-1.0, 1.0)) + - texture2D(uTexture, uv + perDivSize * vec2(0.0, 1.0)) + - texture2D(uTexture, uv + perDivSize * vec2(1.0, 1.0)) - ) / 9.0; - usf_FragColor = outColor; - usf_FragColor.r += sin(uTime); - ` - ); - }, - }); - - useFrame((state) => { - update( - state, - { hofsehfgose: 2 }, - { - uTime: state.clock.getElapsedTime(), - } - ); - }); - - return ( - <> - - - - - - ); -}; -// diff --git a/app/playground/page.tsx b/app/playground/page.tsx deleted file mode 100644 index a84dd222..00000000 --- a/app/playground/page.tsx +++ /dev/null @@ -1,18 +0,0 @@ -import { ShaderFx } from "../ShaderFx"; -import { Playground } from "./Playground"; - -export default function Page() { - return ( -
    - - - -
    - ); -} diff --git a/app/shoasakawa-0/FxMaterial.tsx b/app/shoasakawa-0/FxMaterial.tsx deleted file mode 100644 index b87eac16..00000000 --- a/app/shoasakawa-0/FxMaterial.tsx +++ /dev/null @@ -1,38 +0,0 @@ -import * as THREE from "three"; -import { shaderMaterial } from "@react-three/drei"; - -declare global { - namespace JSX { - interface IntrinsicElements { - fxMaterial: any; - } - } -} - -export type FxMaterialProps = { - u_fx: THREE.Texture; -}; - -export const FxMaterial = shaderMaterial( - { - u_fx: new THREE.Texture(), - }, - - ` - varying vec2 vUv; - void main() { - vUv = uv; - gl_Position = vec4(position, 1.0); - } - `, - ` - precision highp float; - varying vec2 vUv; - uniform sampler2D u_fx; - void main() { - vec2 uv = vUv; - vec4 color = texture2D(u_fx, uv); - gl_FragColor = color; - } - ` -); diff --git a/app/shoasakawa-0/Playground.tsx b/app/shoasakawa-0/Playground.tsx deleted file mode 100644 index 88565d6d..00000000 --- a/app/shoasakawa-0/Playground.tsx +++ /dev/null @@ -1,182 +0,0 @@ -"use client"; - -import * as THREE from "three"; -import { useCallback, useRef, useState } from "react"; -import { useFrame, useThree, extend, useLoader } from "@react-three/fiber"; -import { useBeat, useBlank } from "@/packages/use-shader-fx/src"; -import { FxMaterial } from "./FxMaterial"; -import { Environment, OrbitControls } from "@react-three/drei"; -import GUI from "lil-gui"; -import { useGUI } from "@/utils/useGUI"; -import { OnBeforeInitParameters } from "@/packages/use-shader-fx/src/fxs/types"; - -extend({ FxMaterial }); - -const CONFIG = { - scale: 0.1, - box: () => {}, -}; - -const setGUI = (gui: GUI) => { - gui.add(CONFIG, "scale", 0.0001, 0.2, 0.0001); - gui.add(CONFIG, "box").name("3D⚡️"); - return gui; -}; - -export const Playground = () => { - const updateGUI = useGUI(setGUI); - const { size, viewport } = useThree(); - const [gear] = useLoader(THREE.TextureLoader, [ - "/shoasakawa/gear/gear.webp", - ]); - const [updateBlank, setBlank, { output: blank }] = useBlank({ - size, - dpr: viewport.dpr, - onBeforeInit: useCallback((params: OnBeforeInitParameters) => { - Object.assign(params.uniforms, { - lerpPointer: { value: new THREE.Vector2(0) }, - tileSize: { value: CONFIG.scale }, - bigRadius: { value: 0.34 }, - smallRadius: { value: 0.12 }, - outerColor0: { value: new THREE.Color("#FF0038") }, - outerColor1: { value: new THREE.Color("#AD00FF") }, - outerColor2: { value: new THREE.Color(0, 0, 0) }, - innerColor0: { value: new THREE.Color("#FFD500") }, - innerColor1: { value: new THREE.Color("#FF0038") }, - innerColor2: { value: new THREE.Color("#008CFF") }, - isBox: { value: false }, - }); - params.fragmentShader = params.fragmentShader.replace( - "#usf ", - ` - uniform float tileSize; - uniform float bigRadius; - uniform float smallRadius; - uniform vec3 outerColor0; - uniform vec3 outerColor1; - uniform vec3 outerColor2; - uniform vec3 innerColor0; - uniform vec3 innerColor1; - uniform vec3 innerColor2; - uniform vec2 lerpPointer; - uniform bool isBox; - - float hash(vec2 p) { return fract(1e4 * sin(17.0 * p.x + p.y * 0.1) * (0.1 + abs(sin(p.y * 13.0 + p.x)))); } - - vec4 getCircleColor (float d , float r, vec3 c0,vec3 c1, vec3 c2){ - float dist = d / r; - float nDist = dist*2.-1.; - return vec4(mix(mix(c0, c1, nDist),mix(c1, c2, nDist), dist),1.); - } - ` - ); - params.fragmentShader = params.fragmentShader.replace( - "#usf
    ", - ` - vec2 uv = vUv; - float aspect = uResolution.x / uResolution.y; - uv.x *= isBox ? 1. : aspect; - - float tile = tileSize; - vec2 gridUV = fract(uv / tile); - vec2 gridIndex = floor(uv / tile); - float gridHash = hash(gridIndex); - - float bigDist = distance(gridUV, vec2(.5)); - - if(bigDist>.49){ - discard; - } - - if(bigDist < bigRadius){ - usf_FragColor = getCircleColor(bigDist, bigRadius, outerColor0, outerColor1, outerColor2); - vec2 pointer = lerpPointer*(gridHash+.1); - vec2 offsets[4] = vec2[4]( - vec2(0., -smallRadius*2.2)+pointer*0.2, - vec2(smallRadius*1.6, 0.)+pointer*0.15, - vec2(0., smallRadius*2.2)+pointer*0.1, - vec2(smallRadius*-1.6, 0.)+pointer*0.05 - ); - for (int i = 0; i < 4; i++) { - vec2 smallCenter = vec2(.5)+offsets[i]*.4; - float smallDist = distance(gridUV, smallCenter); - if (smallDist < smallRadius + sin(uTime*(gridHash+.5)+float(i))*.05) { - usf_FragColor = getCircleColor(smallDist, smallRadius, innerColor0, innerColor1, innerColor2); - break; - } - } - }else{ - float angle = uTime*(gridHash+.1)*.2; - float cosAngle = cos(angle); - float sinAngle = sin(angle); - mat2 rotationMatrix = mat2( - cosAngle, -sinAngle, - sinAngle, cosAngle - ); - vec2 texCoord = gridUV-vec2(.5); - texCoord = rotationMatrix * texCoord; - texCoord += vec2(.5); - usf_FragColor = texture2D(uTexture,texCoord); - } - ` - ); - }, []), - }); - - setBlank({ - texture: gear, - }); - - const beater = useBeat(120, "easeInOutQuad"); - const pointerVec = new THREE.Vector2(); - - const [isBox, setIsBox] = useState(false); - - CONFIG.box = () => setIsBox((prev) => !prev); - - const meshRef = useRef(null); - useFrame((state) => { - const { beat } = beater(state.clock); - updateBlank( - state, - { - beat: beat, - }, - { - tileSize: CONFIG.scale, - lerpPointer: pointerVec.lerp(state.pointer, 0.1), - isBox, - } - ); - if (meshRef.current!) { - meshRef.current!.rotation.x += 0.01; - meshRef.current!.rotation.y += 0.01; - meshRef.current!.rotation.z += 0.01; - } - updateGUI(); - }); - - return ( - <> - {isBox ? ( - - - - - - - - - ) : ( - - - - - )} - - ); -}; diff --git a/app/shoasakawa-0/page.tsx b/app/shoasakawa-0/page.tsx deleted file mode 100644 index 25a23700..00000000 --- a/app/shoasakawa-0/page.tsx +++ /dev/null @@ -1,33 +0,0 @@ -import { ShaderFx } from "../ShaderFx"; -import { Playground } from "./Playground"; - -export default function Page() { - return ( - - ); -} diff --git a/app/useBlank/FxMaterial.tsx b/app/useBlank/FxMaterial.tsx deleted file mode 100644 index b87eac16..00000000 --- a/app/useBlank/FxMaterial.tsx +++ /dev/null @@ -1,38 +0,0 @@ -import * as THREE from "three"; -import { shaderMaterial } from "@react-three/drei"; - -declare global { - namespace JSX { - interface IntrinsicElements { - fxMaterial: any; - } - } -} - -export type FxMaterialProps = { - u_fx: THREE.Texture; -}; - -export const FxMaterial = shaderMaterial( - { - u_fx: new THREE.Texture(), - }, - - ` - varying vec2 vUv; - void main() { - vUv = uv; - gl_Position = vec4(position, 1.0); - } - `, - ` - precision highp float; - varying vec2 vUv; - uniform sampler2D u_fx; - void main() { - vec2 uv = vUv; - vec4 color = texture2D(u_fx, uv); - gl_FragColor = color; - } - ` -); diff --git a/app/useBlank/Playground.tsx b/app/useBlank/Playground.tsx deleted file mode 100644 index 9a19c213..00000000 --- a/app/useBlank/Playground.tsx +++ /dev/null @@ -1,67 +0,0 @@ -"use client"; - -import * as THREE from "three"; -import { useCallback, useMemo } from "react"; -import { useFrame, useThree, extend } from "@react-three/fiber"; -import { useBlank, useCoverTexture } from "@/packages/use-shader-fx/src"; -import { FxMaterial } from "./FxMaterial"; -import { useVideoTexture } from "@react-three/drei"; -import { OnBeforeInitParameters } from "@/packages/use-shader-fx/src/fxs/types"; - -extend({ FxMaterial }); - -export const Playground = () => { - const { size, viewport, gl } = useThree(); - const funkun_mov = useVideoTexture("/FT_Ch02-comp.mp4", { - width: 1280, - height: 720, - }); - const [updateCover, setCover, { output: cover }] = useCoverTexture({ - size, - dpr: 1, - }); - setCover({ - texture: funkun_mov, - }); - const [updateBlank, setBlank, { output: blank }] = useBlank({ - size, - dpr: viewport.dpr, - onBeforeInit: useCallback((params: OnBeforeInitParameters) => { - Object.assign(params.uniforms, { - hoge: { value: 0 }, - }); - params.fragmentShader = params.fragmentShader.replace( - "#usf ", - "uniform float hoge;" - ); - params.fragmentShader = params.fragmentShader.replace( - "#usf
    ", - `float t=uTime,c;vec2 z,u,n=vec2(cos(t),sin(t));z=vUv*2.-1.;for(int i=0;i<12;i++){if(dot(z,z)>8.)discard;z=vec2(z.x*z.x-z.y*z.y,z.x*z.y)+n;}c=cos(length(z)+log(length(z)));u=vUv;u+=z*hoge;usf_FragColor=vec4(mix(vec3(c),texture2D(uTexture,u).rgb,1.-hoge),1.);` - ); - console.log(params); - }, []), - }); - setBlank({ - texture: cover, - }); - - useFrame((state) => { - updateBlank( - state, - {}, - { - hoge: Math.sin(state.clock.getElapsedTime()), - } - ); - updateCover(state); - }); - - return ( - <> - - - - - - ); -}; diff --git a/app/useBlank/page.tsx b/app/useBlank/page.tsx deleted file mode 100644 index a84dd222..00000000 --- a/app/useBlank/page.tsx +++ /dev/null @@ -1,18 +0,0 @@ -import { ShaderFx } from "../ShaderFx"; -import { Playground } from "./Playground"; - -export default function Page() { - return ( -
    - - - -
    - ); -} diff --git a/app/useMorphParticles/FxMaterial.tsx b/app/useMorphParticles/FxMaterial.tsx deleted file mode 100644 index 2f49a508..00000000 --- a/app/useMorphParticles/FxMaterial.tsx +++ /dev/null @@ -1,30 +0,0 @@ -import * as THREE from "three"; -import { shaderMaterial } from "@react-three/drei"; -import fragment from "./main.frag"; - -declare global { - namespace JSX { - interface IntrinsicElements { - fxMaterial: any; - } - } -} - -export type FxMaterialProps = { - u_fx: THREE.Texture; -}; - -export const FxMaterial = shaderMaterial( - { - u_fx: new THREE.Texture(), - }, - - ` - varying vec2 vUv; - void main() { - vUv = uv; - gl_Position = vec4(position, 1.0); - } - `, - fragment -); diff --git a/app/useMorphParticles/Playground.tsx b/app/useMorphParticles/Playground.tsx deleted file mode 100644 index bbff09ef..00000000 --- a/app/useMorphParticles/Playground.tsx +++ /dev/null @@ -1,192 +0,0 @@ -"use client"; - -import * as THREE from "three"; -import { use, useCallback, useEffect, useMemo, useRef } from "react"; -import { - useFrame, - useThree, - extend, - useLoader, - Size, -} from "@react-three/fiber"; -import { - useMorphParticles, - useCreateMorphParticles, - MORPHPARTICLES_PARAMS, - MorphParticlesParams, - useBeat, - useFluid, - usePointer, -} from "@/packages/use-shader-fx/src"; -import { FxMaterial, FxMaterialProps } from "./FxMaterial"; -import GUI from "lil-gui"; -import { useGUI } from "@/utils/useGUI"; -import { OrbitControls } from "@react-three/drei"; - -extend({ FxMaterial }); - -const CONFIG: MorphParticlesParams = structuredClone(MORPHPARTICLES_PARAMS); -const setGUI = (gui: GUI) => { - gui.add(CONFIG, "blurAlpha", 0, 1, 0.01); - gui.add(CONFIG, "blurRadius", 0, 2, 0.01); - gui.add(CONFIG, "pointSize", 0.01, 2, 0.01); - // gui.addColor(CONFIG, "color0"); - // gui.addColor(CONFIG, "color1"); - // gui.addColor(CONFIG, "color2"); - // gui.addColor(CONFIG, "color3"); - gui.add(CONFIG, "wobbleStrength", 0, 10, 0.01); - gui.add(CONFIG, "wobblePositionFrequency", 0, 10, 0.01); - gui.add(CONFIG, "wobbleTimeFrequency", 0, 10, 0.01); - gui.add(CONFIG, "warpStrength", 0, 10, 0.01); - gui.add(CONFIG, "warpPositionFrequency", 0, 10, 0.01); - gui.add(CONFIG, "warpTimeFrequency", 0, 10, 0.01); - gui.add(CONFIG, "displacementIntensity", 0, 10, 0.01); - gui.add(CONFIG, "displacementColorIntensity", 0, 40, 0.01); - gui.add(CONFIG, "sizeRandomIntensity", 0, 10, 0.01); - gui.add(CONFIG, "sizeRandomTimeFrequency", 0, 3, 0.01); - gui.add(CONFIG, "sizeRandomMin", 0, 1, 0.01); - gui.add(CONFIG, "sizeRandomMax", 1, 2, 0.01); - gui.add(CONFIG, "divergence", -2, 2, 0.1); -}; -const setConfig = () => { - return { - ...CONFIG, - } as MorphParticlesParams; -}; -const morphList = [ - new THREE.PlaneGeometry(5, 5, 100, 100).attributes.position - .array as Float32Array, - new THREE.TorusGeometry(2.5, 1, 50, 30).attributes.position - .array as Float32Array, -]; -const uvList = [ - new THREE.PlaneGeometry(5, 5, 100, 100).attributes.uv.array as Float32Array, - new THREE.TorusGeometry(2.5, 1, 50, 30).attributes.uv.array as Float32Array, -]; - -export const Playground = () => { - const updateGUI = useGUI(setGUI); - const [funkun, funkunAlpha] = useLoader(THREE.TextureLoader, [ - "/funkun.jpg", - "/funkun-alpha.jpg", - ]); - const { size, viewport, scene } = useThree(); - - const [updateFluid, setFluid, { output: fluid }] = useFluid({ - size, - dpr: 0.1, - }); - - const colorVec = new THREE.Vector3(0, 0, 0); - setFluid({ - fluidColor: (velocity: THREE.Vector2) => { - const rCol = Math.max(0.0, Math.abs(velocity.x) * 200); - const gCol = Math.max(0.0, Math.abs(velocity.y) * 100); - const bCol = Math.max(0.0, (rCol + gCol) / 2); - return colorVec.set(rCol, gCol, bCol); - }, - }); - - const [updatePoints, points] = useCreateMorphParticles({ - scene: false, - size, - dpr: viewport.dpr, - geometry: useMemo(() => new THREE.IcosahedronGeometry(2.5, 50), []), - positions: morphList, - uvs: uvList, - // geometry: new THREE.PlaneGeometry(5, 5, 100, 100), - // onBeforeCompile: useCallback((shader: THREE.Shader) => { - // // shader.vertexShader = shader.vertexShader.replace( - // // "gl_Position = projectedPosition += wobble;", - // // "gl_Position = projectedPosition += wobble + 2.;" - // // ); - // console.log(shader); - // }, []), - }); - - const beat = useBeat(140, "easeOutCubic"); - const updatePointer = usePointer(); - const refPointer = useRef(new THREE.Vector2(0, 0)); - const handlePointerMove = (e: any) => { - if (!e?.pointer) { - return; - } - refPointer.current = e.pointer; - }; - - useFrame((state) => { - const b = beat(state.clock); - updateFluid(state, { - pointerValues: updatePointer(refPointer.current), - }); - updatePoints(state, { - ...setConfig(), - displacement: fluid, - picture: funkun, - alphaPicture: funkunAlpha, - // map: funkun, - // alphaMap: funkunAlpha, - beat: b.beat, - morphProgress: Math.max(Math.sin(state.clock.getElapsedTime() / 2), 0), - // morphProgress: 0.5, - }); - updateGUI(); - }); - - return ( - - - - - - ); -}; - -/*=============================================== -you can also use useMorphParticles (FBO) -===============================================*/ -// export const Playground = () => { -// const { size, viewport, scene, camera } = useThree(); - -// const [updatePoints, setPoints, { output }] = useMorphParticles({ -// camera, -// size, -// dpr: viewport.dpr, -// geometry: new THREE.IcosahedronGeometry(2.5, 50), -// positions: morphList, -// uvs: uvList, -// // geometry: new THREE.PlaneGeometry(5, 5, 100, 100), -// }); - -// const beat = useBeat(140, "easeOutCubic"); -// const updatePointer = usePointer(); -// const refPointer = useRef(new THREE.Vector2(0, 0)); -// const handlePointerMove = (e: any) => { -// if (!e?.pointer) { -// return; -// } -// refPointer.current = e.pointer; -// }; - -// useFrame((state) => { -// const b = beat(state.clock); -// updatePoints(state, { -// ...setConfig(), -// // map: funkun, -// // alphaMap: funkunAlpha, -// beat: b.beat, -// morphProgress: Math.max(Math.sin(state.clock.getElapsedTime() / 2), 0), -// // morphProgress: 0.5, -// }); -// }); - -// return ( -// -// -// -// -// ); -// }; diff --git a/app/useMorphParticles/main.frag b/app/useMorphParticles/main.frag deleted file mode 100644 index bdaf5c1b..00000000 --- a/app/useMorphParticles/main.frag +++ /dev/null @@ -1,7 +0,0 @@ -precision highp float; -varying vec2 vUv; -uniform sampler2D u_fx; - -void main() { - gl_FragColor = texture2D(u_fx,vUv); -} \ No newline at end of file diff --git a/app/useMorphParticles/page.tsx b/app/useMorphParticles/page.tsx deleted file mode 100644 index 4afc0060..00000000 --- a/app/useMorphParticles/page.tsx +++ /dev/null @@ -1,18 +0,0 @@ -import { ShaderFx } from "../ShaderFx"; -import { Playground } from "./Playground"; - -export default function Page() { - return ( -
    - - - -
    - ); -} diff --git a/app/useWobble3D/FxMaterial.tsx b/app/useWobble3D/FxMaterial.tsx deleted file mode 100644 index d1a9c743..00000000 --- a/app/useWobble3D/FxMaterial.tsx +++ /dev/null @@ -1,38 +0,0 @@ -import * as THREE from "three"; -import { shaderMaterial } from "@react-three/drei"; - -declare global { - namespace JSX { - interface IntrinsicElements { - fxMaterial: any; - } - } -} - -export type FxMaterialProps = { - u_fx: THREE.Texture; -}; - -export const FxMaterial = shaderMaterial( - { - u_fx: new THREE.Texture(), - }, - - ` - varying vec2 vUv; - void main() { - vUv = uv; - gl_Position = vec4(position, 1.0); - } - `, - ` - precision highp float; - varying vec2 vUv; - uniform sampler2D u_fx; - - void main() { - gl_FragColor = texture2D(u_fx,vUv); - // gl_FragColor = vec4(1.,1.,0.,1.); - } - ` -); diff --git a/app/useWobble3D/Playground.tsx b/app/useWobble3D/Playground.tsx deleted file mode 100644 index 1a1a63a8..00000000 --- a/app/useWobble3D/Playground.tsx +++ /dev/null @@ -1,173 +0,0 @@ -"use client"; - -import * as THREE from "three"; -import { useEffect } from "react"; -import { useFrame, useThree, extend, useLoader } from "@react-three/fiber"; -import { - useBeat, - useCreateWobble3D, - Wobble3DParams, - WOBBLE3D_PARAMS, - useWobble3D, -} from "@/packages/use-shader-fx/src"; -import { FxMaterial } from "./FxMaterial"; -import GUI from "lil-gui"; -import { useGUI } from "@/utils/useGUI"; -import { OrbitControls, Environment } from "@react-three/drei"; - -extend({ FxMaterial }); - -const CONFIG: Wobble3DParams = { - ...structuredClone(WOBBLE3D_PARAMS), - color0: new THREE.Color(0x1adb91), - color1: new THREE.Color(0xdbff57), - color2: new THREE.Color(0xdf6bff), - color3: new THREE.Color(0x9eaeff), - wobbleStrength: 0.8, - wobbleTimeFrequency: 0.4, - warpStrength: 0.2, - colorMix: 0.6, - chromaticAberration: 0.8, - anisotropicBlur: 0.2, - distortion: 2, - distortionScale: 0.8, - temporalDistortion: 0.3, - refractionSamples: 6, -}; - -const MATERIAL_CONFIG: THREE.MeshPhysicalMaterialParameters = { - iridescence: 0, - metalness: 0.0, - roughness: 0.0, - transmission: 0.99, - thickness: 0.2, - transparent: true, -}; - -const setGUI = (gui: GUI) => { - gui.addColor(CONFIG, "color0"); - gui.addColor(CONFIG, "color1"); - gui.addColor(CONFIG, "color2"); - gui.addColor(CONFIG, "color3"); - gui.add(CONFIG, "wobbleStrength", 0, 10, 0.01); - gui.add(CONFIG, "wobblePositionFrequency", 0, 10, 0.01); - gui.add(CONFIG, "wobbleTimeFrequency", 0, 10, 0.01); - gui.add(CONFIG, "warpStrength", 0, 10, 0.01); - gui.add(CONFIG, "warpPositionFrequency", 0, 10, 0.01); - gui.add(CONFIG, "warpTimeFrequency", 0, 10, 0.01); - gui.add(CONFIG, "refractionSamples", 0, 10, 1); - gui.add(CONFIG, "colorMix", 0, 1, 0.01); - gui.add(CONFIG, "chromaticAberration", 0, 10, 0.01); - gui.add(CONFIG, "anisotropicBlur", 0, 10, 0.01); - gui.add(CONFIG, "distortion", 0, 10, 0.01); - gui.add(CONFIG, "distortionScale", 0, 10, 0.01); - gui.add(CONFIG, "temporalDistortion", 0, 10, 0.01); - const mpm = gui.addFolder("MeshPhysicalMaterial"); - mpm.add(MATERIAL_CONFIG, "iridescence", 0, 1, 0.01); - mpm.add(MATERIAL_CONFIG, "metalness", 0, 1, 0.01); - mpm.add(MATERIAL_CONFIG, "roughness", 0, 1, 0.01); - mpm.add(MATERIAL_CONFIG, "transmission", 0, 10, 0.01); - mpm.add(MATERIAL_CONFIG, "thickness", 0, 10, 0.01); - return gui; -}; -const setConfig = () => { - return { - ...CONFIG, - } as Wobble3DParams; -}; - -export const Playground = () => { - const updateGUI = useGUI(setGUI); - const [funkun] = useLoader(THREE.TextureLoader, ["/funkun.jpg"]); - - /*=============================================== - example of FBO - ===============================================*/ - // const { size, viewport, camera } = useThree(); - // const [update, _, { output, scene }] = useWobble3D({ - // size, - // dpr: viewport.dpr, - // camera, - // }); - // useEffect(() => { - // const light = new THREE.AmbientLight(0xffffff, 2); - // scene.add(light); - // }, [scene]); - // useFrame((props) => update(props)); - - /*=============================================== - example of primitive - ===============================================*/ - const [updateWobble, wobble] = useCreateWobble3D({ - baseMaterial: THREE.MeshPhysicalMaterial, - materialParameters: MATERIAL_CONFIG, - isCustomTransmission: true, - depth: true, - // onBeforeInit: (params) => { - // console.log(params); - // }, - }); - if (wobble.depthMaterial) { - wobble.mesh.customDepthMaterial = wobble.depthMaterial; - } - wobble.mesh.receiveShadow = true; - wobble.mesh.castShadow = true; - - const beat = useBeat(140, "easeInOutBack"); - - useFrame((state) => { - updateWobble(state, { - ...setConfig(), - beat: beat(state.clock).beat, - }); - const mat = wobble.mesh.material as THREE.MeshPhysicalMaterial; - mat.iridescence = MATERIAL_CONFIG.iridescence!; - mat.metalness = MATERIAL_CONFIG.metalness!; - mat.roughness = MATERIAL_CONFIG.roughness!; - mat.transmission = MATERIAL_CONFIG.transmission!; - mat.thickness = MATERIAL_CONFIG.thickness!; - updateGUI(); - }); - - return ( - - - - - - - - - - {/* - - */} - - ); -}; - -/*=============================================== -simpler example -===============================================*/ -// export const Playground = () => { -// const [updateWobble, wobble] = useCreateWobble3D({ -// baseMaterial: THREE.MeshPhysicalMaterial, -// materialParameters: { -// roughness: 0.0, -// transmission: 1, -// thickness: 1, -// }, -// }); -// useFrame((state) => updateWobble(state)); -// return ( -// -// -// -// -// ); -// }; diff --git a/app/useWobble3D/page.tsx b/app/useWobble3D/page.tsx deleted file mode 100644 index 420e310a..00000000 --- a/app/useWobble3D/page.tsx +++ /dev/null @@ -1,18 +0,0 @@ -import { ShaderFx } from "../ShaderFx"; -import { Playground } from "./Playground"; - -export default function Page() { - return ( -
    - - - -
    - ); -} diff --git a/app/v2/Playground.tsx b/app/v2/Playground.tsx index e6a06347..368f6edb 100644 --- a/app/v2/Playground.tsx +++ b/app/v2/Playground.tsx @@ -1,24 +1,19 @@ "use client"; import * as THREE from "three"; -import { useCallback, useEffect, useMemo, useRef, useState } from "react"; +import { useRef, useState } from "react"; import { useFrame, useThree, extend, createPortal } from "@react-three/fiber"; -import { useNoise, useBlur } from "@/packages/use-shader-fx/src"; +import { useNoise, useBlur, useSingleFBO } from "@/packages/use-shader-fx/src"; import { FxMaterial } from "./FxMaterial"; -import { - Environment, - Float, - OrbitControls, - useVideoTexture, -} from "@react-three/drei"; -import { useSingleFBO } from "@/packages/use-shader-fx/legacy"; +import { Float, OrbitControls } from "@react-three/drei"; extend({ FxMaterial }); export const Playground = () => { const { size, viewport, camera } = useThree(); - const offscreenScene = useMemo(() => new THREE.Scene(), []); + const [offscreenScene] = useState(() => new THREE.Scene()); + const [renderTarget, updateRenderTarget] = useSingleFBO({ scene: offscreenScene, camera, @@ -29,8 +24,8 @@ export const Playground = () => { const blur = useBlur({ size, - dpr: 0.6, - blurSize: 8, + dpr: 0.4, + blurSize: 4, blurIteration: 20, src: renderTarget.texture, }); @@ -56,7 +51,7 @@ export const Playground = () => { blur.render(state); gooey.render(state); noise.render(state); - updateRenderTarget(state.gl); + updateRenderTarget({ gl: state.gl }); mesh0.current!.position.x -= Math.sin(state.clock.getElapsedTime()) * 0.02; }); diff --git a/app/v2_FxRenderer/Playground.tsx b/app/v2_FxRenderer/Playground.tsx index f6b95052..10d311ff 100644 --- a/app/v2_FxRenderer/Playground.tsx +++ b/app/v2_FxRenderer/Playground.tsx @@ -1,7 +1,7 @@ "use client"; import * as THREE from "three"; -import { useCallback, useEffect, useMemo, useRef, useState } from "react"; +import { useRef, useState } from "react"; import { useFrame, useThree, @@ -15,27 +15,37 @@ import { useCoverTexture, useRawBlank, useBlur, + useSingleFBO, + createFxMaterial, + createFxBasixFxMaterial, } from "@/packages/use-shader-fx/src"; -import { FxMaterial } from "./FxMaterial"; +// import { FxMaterial } from "./FxMaterial"; import { Environment, Float, OrbitControls, useVideoTexture, } from "@react-three/drei"; -import { useSingleFBO } from "@/packages/use-shader-fx/legacy"; -/*=============================================== -TODO * これをFxRendererで、描画できるようにする -glslのカスマイズなしで、レンダリングするのを目標とする -===============================================*/ +const FxMaterial = createFxMaterial(); +const FxBasicFxMaterial = createFxBasixFxMaterial(); -extend({ FxMaterial }); +extend({ FxMaterial, FxBasicFxMaterial }); + +declare global { + namespace JSX { + interface IntrinsicElements { + fxMaterial: any; + fxBasicFxMaterial: any; + } + } +} export const Playground = () => { const { size, viewport, camera } = useThree(); - const offscreenScene = useMemo(() => new THREE.Scene(), []); + const [offscreenScene] = useState(() => new THREE.Scene()); + const [renderTarget, updateRenderTarget] = useSingleFBO({ scene: offscreenScene, camera, @@ -57,19 +67,31 @@ export const Playground = () => { }); useFrame((state) => { - blur.render(state); + updateRenderTarget({ gl: state.gl }); noise.render(state); - updateRenderTarget(state.gl); + blur.render(state); + }); + + const ref = useRef(); + useFrame(() => { + // ref.current.updateBasicFx(); }); + // console.log(ref.current.updateResolution); return ( <> - {createPortal( diff --git a/packages/use-shader-fx/src/hooks/useBlur/BlurMaterial.ts b/packages/use-shader-fx/src/hooks/useBlur/BlurMaterial.ts index a3643c98..35536636 100644 --- a/packages/use-shader-fx/src/hooks/useBlur/BlurMaterial.ts +++ b/packages/use-shader-fx/src/hooks/useBlur/BlurMaterial.ts @@ -1,9 +1,9 @@ import * as THREE from "three"; import { fragment, vertex } from "./blur.glsl"; -import { FxBasicFxMaterial } from "../materials/FxBasicFxMaterial"; +import { FxBasicFxMaterial } from "../../materials/FxBasicFxMaterial"; import { BlurValues } from "."; -import { FxMaterialProps } from "../materials/FxMaterial"; -import { BasicFxUniforms } from "../materials/BasicFxLib"; +import { FxMaterialProps } from "../../materials/FxMaterial"; +import { BasicFxUniforms } from "../../materials/BasicFxLib"; type BlurUniforms = { src: { value: THREE.Texture | null }; diff --git a/packages/use-shader-fx/src/hooks/useBlur/blur.glsl.ts b/packages/use-shader-fx/src/hooks/useBlur/blur.glsl.ts index a9310c29..32a485ca 100644 --- a/packages/use-shader-fx/src/hooks/useBlur/blur.glsl.ts +++ b/packages/use-shader-fx/src/hooks/useBlur/blur.glsl.ts @@ -28,6 +28,5 @@ export const fragment = ` gl_FragColor = outColor; - } `; diff --git a/packages/use-shader-fx/src/hooks/useBlur/index.ts b/packages/use-shader-fx/src/hooks/useBlur/index.ts index e693f18f..222f0fa4 100644 --- a/packages/use-shader-fx/src/hooks/useBlur/index.ts +++ b/packages/use-shader-fx/src/hooks/useBlur/index.ts @@ -5,7 +5,7 @@ import { useDpr } from "../../utils/useDpr"; import { RootState } from "../types"; import { BlurMaterial } from "./BlurMaterial"; import { useFxScene } from "../../utils/useFxScene"; -import { BasicFxValues } from "../materials/BasicFxLib"; +import { BasicFxValues } from "../../materials/BasicFxLib"; import { useDoubleFBO } from "../../utils/useDoubleFBO"; export type BlurValues = { diff --git a/packages/use-shader-fx/src/hooks/useCoverTexture/CoverTextureMaterial.ts b/packages/use-shader-fx/src/hooks/useCoverTexture/CoverTextureMaterial.ts index d48b0a95..39657618 100644 --- a/packages/use-shader-fx/src/hooks/useCoverTexture/CoverTextureMaterial.ts +++ b/packages/use-shader-fx/src/hooks/useCoverTexture/CoverTextureMaterial.ts @@ -1,9 +1,9 @@ import * as THREE from "three"; import { fragment, vertex } from "./coverTexture.glsl"; -import { FxBasicFxMaterial } from "../materials/FxBasicFxMaterial"; +import { FxBasicFxMaterial } from "../../materials/FxBasicFxMaterial"; import { CoverTextureValues } from "."; -import { FxMaterialProps } from "../materials/FxMaterial"; -import { BasicFxUniforms } from "../materials/BasicFxLib"; +import { FxMaterialProps } from "../../materials/FxMaterial"; +import { BasicFxUniforms } from "../../materials/BasicFxLib"; type CoverTextureUniforms = { src: { value: THREE.Texture | null }; diff --git a/packages/use-shader-fx/src/hooks/useCoverTexture/index.ts b/packages/use-shader-fx/src/hooks/useCoverTexture/index.ts index 11e74ebd..cee3a5ed 100644 --- a/packages/use-shader-fx/src/hooks/useCoverTexture/index.ts +++ b/packages/use-shader-fx/src/hooks/useCoverTexture/index.ts @@ -6,7 +6,7 @@ import { useDpr } from "../../utils/useDpr"; import { RootState } from "../types"; import { CoverTextureMaterial } from "./CoverTextureMaterial"; import { useFxScene } from "../../utils/useFxScene"; -import { BasicFxValues } from "../materials/BasicFxLib"; +import { BasicFxValues } from "../../materials/BasicFxLib"; export type CoverTextureValues = { src?: THREE.Texture; diff --git a/packages/use-shader-fx/src/hooks/useFluid/materials/AdvectionMaterial.ts b/packages/use-shader-fx/src/hooks/useFluid/materials/AdvectionMaterial.ts index da927456..3080ed67 100644 --- a/packages/use-shader-fx/src/hooks/useFluid/materials/AdvectionMaterial.ts +++ b/packages/use-shader-fx/src/hooks/useFluid/materials/AdvectionMaterial.ts @@ -5,7 +5,7 @@ import { FxMaterial, DefaultUniforms, FxMaterialProps, -} from "../../materials/FxMaterial"; +} from "../../../materials/FxMaterial"; import { DEFAULT_TEXTURE } from "../../../libs/constants"; import { DeltaTime } from ".."; diff --git a/packages/use-shader-fx/src/hooks/useFluid/materials/DivergenceMaterial.ts b/packages/use-shader-fx/src/hooks/useFluid/materials/DivergenceMaterial.ts index ba0b5e77..fdef8994 100644 --- a/packages/use-shader-fx/src/hooks/useFluid/materials/DivergenceMaterial.ts +++ b/packages/use-shader-fx/src/hooks/useFluid/materials/DivergenceMaterial.ts @@ -5,7 +5,7 @@ import { FxMaterial, DefaultUniforms, FxMaterialProps, -} from "../../materials/FxMaterial"; +} from "../../../materials/FxMaterial"; import { DEFAULT_TEXTURE } from "../../../libs/constants"; import { DeltaTime } from ".."; diff --git a/packages/use-shader-fx/src/hooks/useFluid/materials/PoissonMaterial.ts b/packages/use-shader-fx/src/hooks/useFluid/materials/PoissonMaterial.ts index 633c7be8..fde836de 100644 --- a/packages/use-shader-fx/src/hooks/useFluid/materials/PoissonMaterial.ts +++ b/packages/use-shader-fx/src/hooks/useFluid/materials/PoissonMaterial.ts @@ -5,7 +5,7 @@ import { DefaultUniforms, FxMaterial, FxMaterialProps, -} from "../../materials/FxMaterial"; +} from "../../../materials/FxMaterial"; import { DEFAULT_TEXTURE } from "../../../libs/constants"; type PoissonUniforms = { diff --git a/packages/use-shader-fx/src/hooks/useFluid/materials/PressureMaterial.ts b/packages/use-shader-fx/src/hooks/useFluid/materials/PressureMaterial.ts index 847ccb5a..aa468ea8 100644 --- a/packages/use-shader-fx/src/hooks/useFluid/materials/PressureMaterial.ts +++ b/packages/use-shader-fx/src/hooks/useFluid/materials/PressureMaterial.ts @@ -5,7 +5,7 @@ import { FxMaterial, DefaultUniforms, FxMaterialProps, -} from "../../materials/FxMaterial"; +} from "../../../materials/FxMaterial"; import { DEFAULT_TEXTURE } from "../../../libs/constants"; import { DeltaTime } from ".."; diff --git a/packages/use-shader-fx/src/hooks/useFluid/materials/SplatMaterial.ts b/packages/use-shader-fx/src/hooks/useFluid/materials/SplatMaterial.ts index 00967370..5ed9491a 100644 --- a/packages/use-shader-fx/src/hooks/useFluid/materials/SplatMaterial.ts +++ b/packages/use-shader-fx/src/hooks/useFluid/materials/SplatMaterial.ts @@ -5,7 +5,7 @@ import { DefaultUniforms, FxMaterial, FxMaterialProps, -} from "../../materials/FxMaterial"; +} from "../../../materials/FxMaterial"; type SplatUniforms = { force: { value: THREE.Vector2 }; diff --git a/packages/use-shader-fx/src/hooks/useNoise/NoiseMaterial.ts b/packages/use-shader-fx/src/hooks/useNoise/NoiseMaterial.ts index 2796ec1e..f8d05942 100644 --- a/packages/use-shader-fx/src/hooks/useNoise/NoiseMaterial.ts +++ b/packages/use-shader-fx/src/hooks/useNoise/NoiseMaterial.ts @@ -1,8 +1,8 @@ import * as THREE from "three"; import { noiseFragment, noiseVertex } from "./noise.glsl"; -import { FxBasicFxMaterial } from "../materials/FxBasicFxMaterial"; -import { FxMaterialProps } from "../materials/FxMaterial"; -import { BasicFxUniforms } from "../materials/BasicFxLib"; +import { FxBasicFxMaterial } from "../../materials/FxBasicFxMaterial"; +import { FxMaterialProps } from "../../materials/FxMaterial"; +import { BasicFxUniforms } from "../../materials/BasicFxLib"; type NoiseUniforms = { tick: { value: number }; diff --git a/packages/use-shader-fx/src/hooks/useNoise/index.ts b/packages/use-shader-fx/src/hooks/useNoise/index.ts index fb3055ac..6837db8b 100644 --- a/packages/use-shader-fx/src/hooks/useNoise/index.ts +++ b/packages/use-shader-fx/src/hooks/useNoise/index.ts @@ -7,7 +7,7 @@ import { useDpr } from "../../utils/useDpr"; import { RootState } from "../types"; import { NoiseMaterial } from "./NoiseMaterial"; import { useFxScene } from "../../utils/useFxScene"; -import { BasicFxValues } from "../materials/BasicFxLib"; +import { BasicFxValues } from "../../materials/BasicFxLib"; export type NoiseValues = { /** noise scale , default : `0.004` */ diff --git a/packages/use-shader-fx/src/hooks/useRawBlank/RawBlankMaterial.ts b/packages/use-shader-fx/src/hooks/useRawBlank/RawBlankMaterial.ts index d813626e..9441f457 100644 --- a/packages/use-shader-fx/src/hooks/useRawBlank/RawBlankMaterial.ts +++ b/packages/use-shader-fx/src/hooks/useRawBlank/RawBlankMaterial.ts @@ -1,4 +1,4 @@ -import { FxMaterial, FxMaterialProps } from "../materials/FxMaterial"; +import { FxMaterial, FxMaterialProps } from "../../materials/FxMaterial"; export class RawBlankMaterial extends FxMaterial { static get type() { diff --git a/packages/use-shader-fx/src/hooks/useRawBlank/index.ts b/packages/use-shader-fx/src/hooks/useRawBlank/index.ts index e983365c..b93727fc 100644 --- a/packages/use-shader-fx/src/hooks/useRawBlank/index.ts +++ b/packages/use-shader-fx/src/hooks/useRawBlank/index.ts @@ -6,7 +6,7 @@ import { useDpr } from "../../utils/useDpr"; import { RootState } from "../types"; import { RawBlankMaterial } from "./RawBlankMaterial"; import { useFxScene } from "../../utils/useFxScene"; -import { ShaderWithUniforms } from "../materials/FxMaterial"; +import { ShaderWithUniforms } from "../../materials/FxMaterial"; export type RawBlankValues = {}; diff --git a/packages/use-shader-fx/src/index.js b/packages/use-shader-fx/src/index.js index c928b1ba..9aac21e8 100644 --- a/packages/use-shader-fx/src/index.js +++ b/packages/use-shader-fx/src/index.js @@ -6,3 +6,15 @@ export * from "./hooks/useFluid"; export * from "./hooks/useCoverTexture"; export * from "./hooks/useRawBlank"; export * from "./hooks/useBlur"; + +/*=============================================== +materials +===============================================*/ +export * from "./materials/FxMaterialImpl"; +export * from "./materials/FxBasicFxMaterialImpl"; + +/*=============================================== +utils +===============================================*/ +export * from "./utils/useDoubleFBO"; +export * from "./utils/useSingleFBO"; diff --git a/packages/use-shader-fx/src/hooks/materials/BasicFxLib.ts b/packages/use-shader-fx/src/materials/BasicFxLib.ts similarity index 100% rename from packages/use-shader-fx/src/hooks/materials/BasicFxLib.ts rename to packages/use-shader-fx/src/materials/BasicFxLib.ts diff --git a/packages/use-shader-fx/src/hooks/materials/FxBasicFxMaterial.ts b/packages/use-shader-fx/src/materials/FxBasicFxMaterial.ts similarity index 97% rename from packages/use-shader-fx/src/hooks/materials/FxBasicFxMaterial.ts rename to packages/use-shader-fx/src/materials/FxBasicFxMaterial.ts index 48b4a843..2939385e 100644 --- a/packages/use-shader-fx/src/hooks/materials/FxBasicFxMaterial.ts +++ b/packages/use-shader-fx/src/materials/FxBasicFxMaterial.ts @@ -5,7 +5,7 @@ import { BasicFxFlag, BasicFxLib, } from "./BasicFxLib"; -import { mergeShaderLib } from "../../libs/shaders/mergeShaderLib"; +import { mergeShaderLib } from "../libs/shaders/mergeShaderLib"; export class FxBasicFxMaterial extends FxMaterial { basicFxFlag: BasicFxFlag; diff --git a/packages/use-shader-fx/src/materials/FxBasicFxMaterialImpl.ts b/packages/use-shader-fx/src/materials/FxBasicFxMaterialImpl.ts new file mode 100644 index 00000000..2ff0e531 --- /dev/null +++ b/packages/use-shader-fx/src/materials/FxBasicFxMaterialImpl.ts @@ -0,0 +1,92 @@ +import * as THREE from "three"; +import { + DefaultUniforms, + FxMaterial, + FxMaterialProps, + ShaderWithUniforms, +} from "./FxMaterial"; +import { ShaderLib } from "../libs/shaders/ShaderLib"; +import { DEFAULT_TEXTURE } from "../libs/constants"; +import { FxBasicFxMaterial } from "./FxBasicFxMaterial"; +import { BasicFxUniforms, BasicFxValues } from "./BasicFxLib"; + +type FxBasicFxMaterialImplUniforms = { + src: { value: THREE.Texture }; +} & BasicFxUniforms; + +type FxBasixFxMaterialImplValues = { + src?: THREE.Texture; +} & BasicFxValues; + +const vertex = ` + void main() { + ${ShaderLib.plane_vertex} + } +`; + +const fragment = ` + uniform sampler2D src; + void main() { + + vec2 usf_Uv = vUv; + + ${ShaderLib.basicFx_fragment_begin} + + vec4 usf_FragColor = texture2D(src, usf_Uv); + + ${ShaderLib.basicFx_fragment_end} + + gl_FragColor = usf_FragColor; + + } +`; + +/*=============================================== +TODO * +- FxMaterialImplもTHREE.UniformsUtils.mergeを使うように変更 + - そもそもなぜ、mergeを使うとバグが解消されるのか調査 +- 全体的に、THREE.UniformsUtils.mergeの必要性を検討 + +===============================================*/ +export const createFxBasixFxMaterial = ({ + uniforms, + vertexShader = vertex, + fragmentShader = fragment, +}: ShaderWithUniforms = {}) => { + class FxBasicFxMaterialImpl extends FxBasicFxMaterial { + static get type() { + return "FxBasicFxMaterialImpl"; + } + + uniforms!: FxBasicFxMaterialImplUniforms; + + constructor(props: FxMaterialProps) { + super(); + + this.type = FxBasicFxMaterialImpl.type; + + this.uniforms = { + ...THREE.UniformsUtils.merge([ + this.uniforms, + { + src: { value: null }, + }, + ]), + ...uniforms, + ...props?.uniforms, + }; + + this.setupBasicFxShaders( + props?.vertexShader || vertexShader, + props?.fragmentShader || fragmentShader + ); + + this.setUniformValues(props?.uniformValues); + this.setValues(props?.materialParameters || {}); + + this.defineUniformAccessors(() => this.updateBasicFx()); + } + } + + return FxBasicFxMaterialImpl; +}; diff --git a/packages/use-shader-fx/src/hooks/materials/FxMaterial.ts b/packages/use-shader-fx/src/materials/FxMaterial.ts similarity index 80% rename from packages/use-shader-fx/src/hooks/materials/FxMaterial.ts rename to packages/use-shader-fx/src/materials/FxMaterial.ts index f4bf0d17..30232295 100644 --- a/packages/use-shader-fx/src/hooks/materials/FxMaterial.ts +++ b/packages/use-shader-fx/src/materials/FxMaterial.ts @@ -1,6 +1,6 @@ import * as THREE from "three"; -import { resolveIncludes } from "../../libs/shaders/resolveShaders"; -import { mergeShaderLib } from "../../libs/shaders/mergeShaderLib"; +import { resolveIncludes } from "../libs/shaders/resolveShaders"; +import { mergeShaderLib } from "../libs/shaders/mergeShaderLib"; export type DefaultUniforms = { resolution: { value: THREE.Vector2 }; @@ -9,8 +9,9 @@ export type DefaultUniforms = { maxAspect: { value: THREE.Vector2 }; }; +export type Uniforms = { [uniform: string]: THREE.IUniform }; export type ShaderWithUniforms = { - uniforms?: { [uniform: string]: THREE.IUniform }; + uniforms?: Uniforms; vertexShader?: string; fragmentShader?: string; }; @@ -91,4 +92,18 @@ export class FxMaterial extends THREE.ShaderMaterial { curretUniform.value = newValue; } } + + // Create getter/setters + defineUniformAccessors(onSet?: () => void) { + const entries = Object.entries(this.uniforms); + entries.forEach(([name]) => + Object.defineProperty(this, name, { + get: () => this.uniforms[name].value, + set: (v) => { + this.uniforms[name].value = v; + onSet?.(); + }, + }) + ); + } } diff --git a/packages/use-shader-fx/src/materials/FxMaterialImpl.ts b/packages/use-shader-fx/src/materials/FxMaterialImpl.ts new file mode 100644 index 00000000..be24d873 --- /dev/null +++ b/packages/use-shader-fx/src/materials/FxMaterialImpl.ts @@ -0,0 +1,72 @@ +import * as THREE from "three"; +import { + DefaultUniforms, + FxMaterial, + FxMaterialProps, + ShaderWithUniforms, + Uniforms, +} from "./FxMaterial"; +import { ShaderLib } from "../libs/shaders/ShaderLib"; +import { DEFAULT_TEXTURE } from "../libs/constants"; + +type FxMaterialImplUniforms = { + src: { value: THREE.Texture }; +} & DefaultUniforms; + +type FxMaterialImplValues = { + src?: THREE.Texture; +}; + +const vertex = ` + void main() { + ${ShaderLib.plane_vertex} + } +`; + +const fragment = ` + uniform sampler2D src; + void main() { + gl_FragColor = texture2D(src, vUv); + } +`; + +export const createFxMaterial = ({ + uniforms, + vertexShader = vertex, + fragmentShader = fragment, +}: ShaderWithUniforms = {}) => { + class FxMaterialImpl extends FxMaterial { + static get type() { + return "FxMaterialImpl"; + } + + uniforms!: FxMaterialImplUniforms & Uniforms; + + constructor(props: FxMaterialProps) { + super(); + + this.type = FxMaterialImpl.type; + + this.uniforms = { + ...this.uniforms, + ...{ + src: { value: DEFAULT_TEXTURE }, + }, + ...uniforms, + ...props?.uniforms, + }; + + this.setupDefaultShaders( + props?.vertexShader || vertexShader, + props?.fragmentShader || fragmentShader + ); + + this.setUniformValues(props?.uniformValues); + this.setValues(props?.materialParameters || {}); + + this.defineUniformAccessors(); + } + } + + return FxMaterialImpl; +}; diff --git a/packages/use-shader-fx/src/utils/useCamera.ts b/packages/use-shader-fx/src/utils/useCamera.ts index cf615867..187fb416 100644 --- a/packages/use-shader-fx/src/utils/useCamera.ts +++ b/packages/use-shader-fx/src/utils/useCamera.ts @@ -1,7 +1,7 @@ import * as THREE from "three"; import { useResolution } from "./useResolution"; -import { useMemo } from "react"; -import { Size } from "../fxs/types"; +import { useState } from "react"; +import { Size } from "../hooks/types"; const getCameraProps = (width: number, height: number) => { const frustumSize = height; @@ -15,11 +15,12 @@ export const useCamera = ( cameraType: "OrthographicCamera" | "PerspectiveCamera" = "OrthographicCamera" ) => { const resolution = useResolution(size); - const camera = useMemo(() => { - const { width, height, near, far } = getCameraProps( - resolution.x, - resolution.y - ); + const { width, height, near, far } = getCameraProps( + resolution.x, + resolution.y + ); + + const [camera] = useState(() => { return cameraType === "OrthographicCamera" ? new THREE.OrthographicCamera( -width, @@ -30,6 +31,20 @@ export const useCamera = ( far ) : new THREE.PerspectiveCamera(50, width / height); - }, [resolution, cameraType]); + }); + + if (camera instanceof THREE.OrthographicCamera) { + camera.left = -width; + camera.right = width; + camera.top = height; + camera.bottom = -height; + camera.near = near; + camera.far = far; + camera.updateProjectionMatrix(); + } else if (camera instanceof THREE.PerspectiveCamera) { + camera.aspect = width / height; + camera.updateProjectionMatrix(); + } + return camera; }; diff --git a/packages/use-shader-fx/src/utils/useDoubleFBO.ts b/packages/use-shader-fx/src/utils/useDoubleFBO.ts index 0249a388..4481aadb 100644 --- a/packages/use-shader-fx/src/utils/useDoubleFBO.ts +++ b/packages/use-shader-fx/src/utils/useDoubleFBO.ts @@ -1,5 +1,5 @@ import * as THREE from "three"; -import { useCallback, useEffect, useMemo } from "react"; +import { useCallback, useEffect, useState } from "react"; import { FBO_DEFAULT_OPTION, UseFboProps, @@ -51,7 +51,7 @@ export const useDoubleFBO = (props: UseFboProps): UseDoubleFBOReturn => { const resolution = useResolution(size, dpr); - const renderTarget = useMemo(() => { + const [renderTarget] = useState(() => { const read = new THREE.WebGLRenderTarget(resolution.x, resolution.y, { ...FBO_DEFAULT_OPTION, ...renderTargetOptions, @@ -83,8 +83,7 @@ export const useDoubleFBO = (props: UseFboProps): UseDoubleFBOReturn => { this.write = temp; }, }; - // eslint-disable-next-line react-hooks/exhaustive-deps - }, []); + }); if (sizeUpdate) { renderTarget.read?.setSize(resolution.x, resolution.y); diff --git a/packages/use-shader-fx/src/utils/useDpr.ts b/packages/use-shader-fx/src/utils/useDpr.ts index 17337bc0..f2e3493f 100644 --- a/packages/use-shader-fx/src/utils/useDpr.ts +++ b/packages/use-shader-fx/src/utils/useDpr.ts @@ -1,5 +1,5 @@ import { useMemo } from "react"; -import { Dpr } from "../fxs/types"; +import { Dpr } from "../hooks/types"; export const useDpr = ( dpr: Dpr diff --git a/packages/use-shader-fx/src/utils/useFxScene.ts b/packages/use-shader-fx/src/utils/useFxScene.ts index b0c80124..c013b217 100644 --- a/packages/use-shader-fx/src/utils/useFxScene.ts +++ b/packages/use-shader-fx/src/utils/useFxScene.ts @@ -1,9 +1,9 @@ -import { useMemo } from "react"; import * as THREE from "three"; +import { useState } from "react"; import { useObject3D } from "./useObject3D"; -import { Size } from "../fxs/types"; +import { Size } from "../hooks/types"; import { useResolution } from "./useResolution"; -import { FxMaterial, FxMaterialProps } from "../fxs/materials/FxMaterial"; +import { FxMaterial, FxMaterialProps } from "../materials/FxMaterial"; import { useCamera } from "./useCamera"; type MaterialConstructor = new (props: FxMaterialProps) => M; @@ -30,17 +30,11 @@ export const useFxScene = ({ height: number; }; } & FxMaterialProps) => { - const scene = useMemo(() => new THREE.Scene(), []); - - const _geometry = useMemo( - () => new geometry(geometrySize?.width || 2, geometrySize?.height || 2), - [geometry, geometrySize] - ); - - const _material = useMemo( - () => new material(materialProps), - [material, materialProps] + const [scene] = useState(() => new THREE.Scene()); + const [_geometry] = useState( + () => new geometry(geometrySize?.width || 2, geometrySize?.height || 2) ); + const [_material] = useState(() => new material(materialProps)); const resolution = useResolution(size, dpr); _material.updateResolution(resolution); diff --git a/packages/use-shader-fx/src/utils/useObject3D.ts b/packages/use-shader-fx/src/utils/useObject3D.ts index 29fd8895..0a5abccc 100644 --- a/packages/use-shader-fx/src/utils/useObject3D.ts +++ b/packages/use-shader-fx/src/utils/useObject3D.ts @@ -1,5 +1,5 @@ import * as THREE from "three"; -import { useEffect, useMemo } from "react"; +import { useEffect, useMemo, useState } from "react"; type Object3DConstructor = new ( geometry: THREE.BufferGeometry, @@ -19,7 +19,7 @@ export const useObject3D = ( const obj = new Proto(geometry, material); scene && scene.add(obj); return obj; - }, [geometry, material, Proto, scene]); + }, [scene, geometry, material, Proto]); useEffect(() => { return () => { diff --git a/packages/use-shader-fx/src/utils/useResolution.ts b/packages/use-shader-fx/src/utils/useResolution.ts index 1ae2c633..712e51e4 100644 --- a/packages/use-shader-fx/src/utils/useResolution.ts +++ b/packages/use-shader-fx/src/utils/useResolution.ts @@ -1,6 +1,6 @@ import * as THREE from "three"; import { useMemo } from "react"; -import { Size } from "../fxs/types"; +import { Size } from "../hooks/types"; /** * @params dpr if dpr is set, it returns the resolution which is size multiplied by dpr. diff --git a/packages/use-shader-fx/src/utils/useSingleFBO.ts b/packages/use-shader-fx/src/utils/useSingleFBO.ts index 00cb7b8a..fda48909 100644 --- a/packages/use-shader-fx/src/utils/useSingleFBO.ts +++ b/packages/use-shader-fx/src/utils/useSingleFBO.ts @@ -1,7 +1,7 @@ import * as THREE from "three"; -import { useCallback, useEffect, useMemo, useRef } from "react"; +import { useCallback, useEffect, useState } from "react"; import { useResolution } from "./useResolution"; -import { Size } from "../fxs/types"; +import { Size } from "../hooks/types"; export const FBO_DEFAULT_OPTION: THREE.RenderTargetOptions = { depthBuffer: false, @@ -75,47 +75,37 @@ export const useSingleFBO = (props: UseFboProps): UseSingleFBOReturn => { ...renderTargetOptions } = props; - const renderTarget = useRef(); - const resolution = useResolution(size, dpr); - renderTarget.current = useMemo( - () => { - const target = new THREE.WebGLRenderTarget( + const [renderTarget] = useState(() => { + const target = new THREE.WebGLRenderTarget(resolution.x, resolution.y, { + ...FBO_DEFAULT_OPTION, + ...renderTargetOptions, + }); + if (depth) { + target.depthTexture = new THREE.DepthTexture( resolution.x, resolution.y, - { - ...FBO_DEFAULT_OPTION, - ...renderTargetOptions, - } + THREE.FloatType ); - if (depth) { - target.depthTexture = new THREE.DepthTexture( - resolution.x, - resolution.y, - THREE.FloatType - ); - } - return target; - }, - // eslint-disable-next-line react-hooks/exhaustive-deps - [] - ); + } + return target; + }); if (sizeUpdate) { - renderTarget.current?.setSize(resolution.x, resolution.y); + renderTarget.setSize(resolution.x, resolution.y); } useEffect(() => { - const temp = renderTarget.current; + const temp = renderTarget; return () => { temp?.dispose(); }; - }, []); + }, [renderTarget]); const updateRenderTarget: SingleFBOUpdateFunction = useCallback( (renderProps, onBeforeRender) => { - const fbo = renderTarget.current!; + const fbo = renderTarget!; renderFBO({ ...renderProps, scene: renderProps.scene || scene, @@ -125,8 +115,8 @@ export const useSingleFBO = (props: UseFboProps): UseSingleFBOReturn => { }); return fbo.texture; }, - [scene, camera] + [scene, camera, renderTarget] ); - return [renderTarget.current, updateRenderTarget]; + return [renderTarget, updateRenderTarget]; }; diff --git a/todo b/todo index e69de29b..341c7894 100644 --- a/todo +++ b/todo @@ -0,0 +1,2 @@ + +- ぜんぶdefineUniformAccessorsしたら、materialとして使えるのでは? \ No newline at end of file diff --git a/utils/useGUI.ts b/utils/useGUI.ts index b79d9b7c..4fe0f5f2 100644 --- a/utils/useGUI.ts +++ b/utils/useGUI.ts @@ -1,8 +1,9 @@ -import { useCallback, useEffect, useMemo } from "react"; +import { useCallback, useEffect, useState } from "react"; import GUI from "lil-gui"; export const useGUI = (setGUI: (gui: GUI) => void) => { - const gui = useMemo(() => new GUI({ closeFolders: true, width: 240 }), []); + const [gui] = useState(() => new GUI({ closeFolders: true, width: 240 })); + useEffect(() => { setGUI(gui); return () => { From d792a6e0ef4a168cfb3d1668219236b242f0a8f4 Mon Sep 17 00:00:00 2001 From: takuma-hmng8 Date: Thu, 3 Oct 2024 12:21:11 +0900 Subject: [PATCH 10/60] update --- app/v2_FxRenderer/FxMaterial.tsx | 80 ----------------- app/v2_FxRenderer/Playground.tsx | 88 ++++++++++--------- app/v2_FxRenderer/page.tsx | 14 +++ .../src/hooks/useBlur/BlurMaterial.ts | 8 +- .../useCoverTexture/CoverTextureMaterial.ts | 8 +- .../useFluid/materials/AdvectionMaterial.ts | 8 +- .../useFluid/materials/DivergenceMaterial.ts | 8 +- .../useFluid/materials/PoissonMaterial.ts | 8 +- .../useFluid/materials/PressureMaterial.ts | 8 +- .../hooks/useFluid/materials/SplatMaterial.ts | 8 +- .../src/hooks/useNoise/NoiseMaterial.ts | 8 +- .../src/materials/FxBasicFxMaterial.ts | 11 +-- .../src/materials/FxBasicFxMaterialImpl.ts | 48 ++++------ .../use-shader-fx/src/materials/FxMaterial.ts | 16 ++-- .../src/materials/FxMaterialImpl.ts | 25 +++--- todo | 2 - 16 files changed, 140 insertions(+), 208 deletions(-) delete mode 100644 app/v2_FxRenderer/FxMaterial.tsx diff --git a/app/v2_FxRenderer/FxMaterial.tsx b/app/v2_FxRenderer/FxMaterial.tsx deleted file mode 100644 index 948c0e9a..00000000 --- a/app/v2_FxRenderer/FxMaterial.tsx +++ /dev/null @@ -1,80 +0,0 @@ -import * as THREE from "three"; -import { shaderMaterial } from "@react-three/drei"; - -declare global { - namespace JSX { - interface IntrinsicElements { - fxMaterial: any; - } - } -} - -export type FxMaterialProps = { - u_fx: THREE.Texture; - u_noise?: THREE.Texture; - u_color0?: THREE.Color; - u_color1?: THREE.Color; -}; - -export const FxMaterial = shaderMaterial( - { - u_fx: new THREE.Texture(), - u_noise: new THREE.Texture(), - u_color0: new THREE.Color(0x1974d2), - u_color1: new THREE.Color(0xff1e90), - }, - - ` - varying vec2 vUv; - void main() { - vUv = uv; - gl_Position = vec4(position, 1.0); - } - `, - ` - precision highp float; - varying vec2 vUv; - uniform sampler2D u_fx; - uniform sampler2D u_noise; - uniform vec3 u_color0; - uniform vec3 u_color1; - - float vignetteStrength = 0.88; // 強度(0.0〜1.0) - float vignetteRadius = 0.8; // 効果が始まる半径(0.0〜1.0) - - float rand(vec2 n) { - return fract(sin(dot(n ,vec2(12.9898,78.233))) * 43758.5453); - } - - void main() { - vec2 uv = vUv; - - float grain = rand(uv); // -1.0〜1.0 - - // ビネット - vec2 position = uv - 0.5; - float distance = length(position); - float vignette = smoothstep(vignetteRadius, vignetteRadius - 0.5, distance); - vignette = mix(1.0, vignette, vignetteStrength); - - // ノイズ - vec4 noise = texture2D(u_noise, uv); - vec3 noisedColor = mix(u_color0, u_color1, length(noise.rg * uv) + .1); - noisedColor += grain * .1; - - // モデル - vec4 modelColor = texture2D(u_fx,uv); - modelColor.rgb+=grain * .3; - - modelColor.rgb+=noisedColor; - - // モデルとノイズを混ぜる - vec3 mixedModelColor = mix(noisedColor, modelColor.rgb, modelColor.a); - - vec3 finalColor = mixedModelColor * vignette; - - gl_FragColor = vec4(finalColor, 1.0); - - } - ` -); diff --git a/app/v2_FxRenderer/Playground.tsx b/app/v2_FxRenderer/Playground.tsx index 10d311ff..29404c99 100644 --- a/app/v2_FxRenderer/Playground.tsx +++ b/app/v2_FxRenderer/Playground.tsx @@ -2,44 +2,37 @@ import * as THREE from "three"; import { useRef, useState } from "react"; -import { - useFrame, - useThree, - extend, - useLoader, - createPortal, -} from "@react-three/fiber"; +import { useFrame, useThree, extend, createPortal } from "@react-three/fiber"; import { useNoise, - useFluid, - useCoverTexture, - useRawBlank, useBlur, useSingleFBO, - createFxMaterial, - createFxBasixFxMaterial, + createFxMaterialImpl, + createFxBasicFxMaterialImpl, + FxMaterialImplValues, + FxBasicFxMaterialImplValues, + useFluid, } from "@/packages/use-shader-fx/src"; -// import { FxMaterial } from "./FxMaterial"; -import { - Environment, - Float, - OrbitControls, - useVideoTexture, -} from "@react-three/drei"; +import { Float, OrbitControls } from "@react-three/drei"; -const FxMaterial = createFxMaterial(); -const FxBasicFxMaterial = createFxBasixFxMaterial(); +const FxMaterialImpl = createFxMaterialImpl({ + fragmentShader: ` + uniform sampler2D src; + void main() { + vec2 vel = texture2D(src, vUv).xy; + float len = length(vel); + vel = vel * 0.5 + 0.5; + + vec3 color = vec3(vel.x, vel.y, 1.0); + color = mix(vec3(1.0), color, len); -extend({ FxMaterial, FxBasicFxMaterial }); + gl_FragColor = vec4(color, 1.0); + } +`, +}); +const FxBasicFxMaterialImpl = createFxBasicFxMaterialImpl(); -declare global { - namespace JSX { - interface IntrinsicElements { - fxMaterial: any; - fxBasicFxMaterial: any; - } - } -} +extend({ FxMaterialImpl, FxBasicFxMaterialImpl }); export const Playground = () => { const { size, viewport, camera } = useThree(); @@ -66,32 +59,32 @@ export const Playground = () => { scale: 0.03, }); + const fluid = useFluid({ + size, + dpr: 0.25, + }); + useFrame((state) => { updateRenderTarget({ gl: state.gl }); noise.render(state); blur.render(state); + fluid.render(state); }); const ref = useRef(); - useFrame(() => { - // ref.current.updateBasicFx(); - }); + useFrame(() => {}); // console.log(ref.current.updateResolution); return ( <> - {createPortal( @@ -109,3 +102,14 @@ export const Playground = () => { ); }; + +declare global { + namespace JSX { + interface IntrinsicElements { + fxMaterialImpl: FxMaterialImplValues & + JSX.IntrinsicElements["shaderMaterial"]; + fxBasicFxMaterialImpl: FxBasicFxMaterialImplValues & + JSX.IntrinsicElements["shaderMaterial"]; + } + } +} diff --git a/app/v2_FxRenderer/page.tsx b/app/v2_FxRenderer/page.tsx index a84dd222..cc9a6d74 100644 --- a/app/v2_FxRenderer/page.tsx +++ b/app/v2_FxRenderer/page.tsx @@ -1,5 +1,6 @@ import { ShaderFx } from "../ShaderFx"; import { Playground } from "./Playground"; +import Image from "next/image"; export default function Page() { return ( @@ -10,6 +11,19 @@ export default function Page() { height: "100svh", pointerEvents: "none", }}> +
    + +
    diff --git a/packages/use-shader-fx/src/hooks/useBlur/BlurMaterial.ts b/packages/use-shader-fx/src/hooks/useBlur/BlurMaterial.ts index 35536636..923ffe01 100644 --- a/packages/use-shader-fx/src/hooks/useBlur/BlurMaterial.ts +++ b/packages/use-shader-fx/src/hooks/useBlur/BlurMaterial.ts @@ -25,13 +25,13 @@ export class BlurMaterial extends FxBasicFxMaterial { this.type = BlurMaterial.type; - this.uniforms = { - ...this.uniforms, - ...{ + this.uniforms = THREE.UniformsUtils.merge([ + this.uniforms, + { src: { value: null }, blurSize: { value: 5 }, }, - }; + ]) as BlurUniforms; this.setUniformValues(uniformValues); this.setValues(materialParameters); diff --git a/packages/use-shader-fx/src/hooks/useCoverTexture/CoverTextureMaterial.ts b/packages/use-shader-fx/src/hooks/useCoverTexture/CoverTextureMaterial.ts index 39657618..38a318fe 100644 --- a/packages/use-shader-fx/src/hooks/useCoverTexture/CoverTextureMaterial.ts +++ b/packages/use-shader-fx/src/hooks/useCoverTexture/CoverTextureMaterial.ts @@ -25,13 +25,13 @@ export class CoverTextureMaterial extends FxBasicFxMaterial { this.type = CoverTextureMaterial.type; - this.uniforms = { - ...this.uniforms, - ...{ + this.uniforms = THREE.UniformsUtils.merge([ + this.uniforms, + { src: { value: null }, textureResolution: { value: new THREE.Vector2() }, }, - }; + ]) as CoverTextureUniforms; this.setUniformValues(uniformValues); this.setValues(materialParameters); diff --git a/packages/use-shader-fx/src/hooks/useFluid/materials/AdvectionMaterial.ts b/packages/use-shader-fx/src/hooks/useFluid/materials/AdvectionMaterial.ts index 3080ed67..c6ab8410 100644 --- a/packages/use-shader-fx/src/hooks/useFluid/materials/AdvectionMaterial.ts +++ b/packages/use-shader-fx/src/hooks/useFluid/materials/AdvectionMaterial.ts @@ -26,13 +26,13 @@ export class AdvectionMaterial extends FxMaterial { this.type = AdvectionMaterial.type; - this.uniforms = { - ...this.uniforms, - ...{ + this.uniforms = THREE.UniformsUtils.merge([ + this.uniforms, + { velocity: { value: DEFAULT_TEXTURE }, dt: { value: DeltaTime }, }, - }; + ]) as AdvectionUniforms; this.setupDefaultShaders(vertex.advection, fragment); diff --git a/packages/use-shader-fx/src/hooks/useFluid/materials/DivergenceMaterial.ts b/packages/use-shader-fx/src/hooks/useFluid/materials/DivergenceMaterial.ts index fdef8994..aaeab2ea 100644 --- a/packages/use-shader-fx/src/hooks/useFluid/materials/DivergenceMaterial.ts +++ b/packages/use-shader-fx/src/hooks/useFluid/materials/DivergenceMaterial.ts @@ -27,14 +27,14 @@ export class DivergenceMaterial extends FxMaterial { this.type = DivergenceMaterial.type; - this.uniforms = { - ...this.uniforms, - ...{ + this.uniforms = THREE.UniformsUtils.merge([ + this.uniforms, + { isBounce: { value: true }, velocity: { value: DEFAULT_TEXTURE }, dt: { value: DeltaTime }, }, - }; + ]) as DivergenceUniforms; this.setupDefaultShaders(vertex.main, fragment); diff --git a/packages/use-shader-fx/src/hooks/useFluid/materials/PoissonMaterial.ts b/packages/use-shader-fx/src/hooks/useFluid/materials/PoissonMaterial.ts index fde836de..03579371 100644 --- a/packages/use-shader-fx/src/hooks/useFluid/materials/PoissonMaterial.ts +++ b/packages/use-shader-fx/src/hooks/useFluid/materials/PoissonMaterial.ts @@ -28,14 +28,14 @@ export class PoissonMaterial extends FxMaterial { this.type = PoissonMaterial.type; - this.uniforms = { - ...this.uniforms, - ...{ + this.uniforms = THREE.UniformsUtils.merge([ + this.uniforms, + { isBounce: { value: true }, pressure: { value: DEFAULT_TEXTURE }, divergence: { value: DEFAULT_TEXTURE }, }, - }; + ]) as PoissonUniforms; this.iteration = 32; diff --git a/packages/use-shader-fx/src/hooks/useFluid/materials/PressureMaterial.ts b/packages/use-shader-fx/src/hooks/useFluid/materials/PressureMaterial.ts index aa468ea8..69b652e2 100644 --- a/packages/use-shader-fx/src/hooks/useFluid/materials/PressureMaterial.ts +++ b/packages/use-shader-fx/src/hooks/useFluid/materials/PressureMaterial.ts @@ -28,15 +28,15 @@ export class PressureMaterial extends FxMaterial { this.type = PressureMaterial.type; - this.uniforms = { - ...this.uniforms, - ...{ + this.uniforms = THREE.UniformsUtils.merge([ + this.uniforms, + { isBounce: { value: true }, pressure: { value: DEFAULT_TEXTURE }, velocity: { value: DEFAULT_TEXTURE }, dt: { value: DeltaTime }, }, - }; + ]) as PressureUniforms; this.setupDefaultShaders(vertex.main, fragment); diff --git a/packages/use-shader-fx/src/hooks/useFluid/materials/SplatMaterial.ts b/packages/use-shader-fx/src/hooks/useFluid/materials/SplatMaterial.ts index 5ed9491a..f70465b1 100644 --- a/packages/use-shader-fx/src/hooks/useFluid/materials/SplatMaterial.ts +++ b/packages/use-shader-fx/src/hooks/useFluid/materials/SplatMaterial.ts @@ -29,14 +29,14 @@ export class SplatMaterial extends FxMaterial { this.force = 30; - this.uniforms = { - ...this.uniforms, - ...{ + this.uniforms = THREE.UniformsUtils.merge([ + this.uniforms, + { force: { value: new THREE.Vector2(0, 0) }, center: { value: new THREE.Vector2(0, 0) }, scale: { value: new THREE.Vector2(30, 30) }, }, - }; + ]) as SplatUniforms; this.setupDefaultShaders(vertex.splat, fragment); diff --git a/packages/use-shader-fx/src/hooks/useNoise/NoiseMaterial.ts b/packages/use-shader-fx/src/hooks/useNoise/NoiseMaterial.ts index f8d05942..bce5bfae 100644 --- a/packages/use-shader-fx/src/hooks/useNoise/NoiseMaterial.ts +++ b/packages/use-shader-fx/src/hooks/useNoise/NoiseMaterial.ts @@ -27,9 +27,9 @@ export class NoiseMaterial extends FxBasicFxMaterial { this.type = NoiseMaterial.type; - this.uniforms = { - ...this.uniforms, - ...{ + this.uniforms = THREE.UniformsUtils.merge([ + this.uniforms, + { tick: { value: 0.0 }, scale: { value: 0.03 }, timeStrength: { value: 0.3 }, @@ -39,7 +39,7 @@ export class NoiseMaterial extends FxBasicFxMaterial { warpDirection: { value: new THREE.Vector2(2.0, 2.0) }, warpStrength: { value: 8 }, }, - }; + ]) as NoiseUniforms; this.setUniformValues(uniformValues); this.setValues(materialParameters); diff --git a/packages/use-shader-fx/src/materials/FxBasicFxMaterial.ts b/packages/use-shader-fx/src/materials/FxBasicFxMaterial.ts index 2939385e..dade84ef 100644 --- a/packages/use-shader-fx/src/materials/FxBasicFxMaterial.ts +++ b/packages/use-shader-fx/src/materials/FxBasicFxMaterial.ts @@ -1,3 +1,4 @@ +import * as THREE from "three"; import { FxMaterial, FxMaterialProps } from "./FxMaterial"; import { BasicFxUniforms, @@ -29,11 +30,11 @@ export class FxBasicFxMaterial extends FxMaterial { this.basicFxFlag = BasicFxLib.setupDefaultFlag(uniformValues); - this.uniforms = { - ...this.uniforms, - ...BasicFxLib.DEFAULT_BASICFX_VALUES, - ...uniforms, - } as BasicFxUniforms; + this.uniforms = THREE.UniformsUtils.merge([ + this.uniforms, + BasicFxLib.DEFAULT_BASICFX_VALUES, + uniforms || {}, + ]) as BasicFxUniforms; this.setUniformValues(uniformValues); this.setValues(materialParameters); diff --git a/packages/use-shader-fx/src/materials/FxBasicFxMaterialImpl.ts b/packages/use-shader-fx/src/materials/FxBasicFxMaterialImpl.ts index 2ff0e531..ab6a7f91 100644 --- a/packages/use-shader-fx/src/materials/FxBasicFxMaterialImpl.ts +++ b/packages/use-shader-fx/src/materials/FxBasicFxMaterialImpl.ts @@ -1,12 +1,6 @@ import * as THREE from "three"; -import { - DefaultUniforms, - FxMaterial, - FxMaterialProps, - ShaderWithUniforms, -} from "./FxMaterial"; +import { FxMaterialProps, ShaderWithUniforms } from "./FxMaterial"; import { ShaderLib } from "../libs/shaders/ShaderLib"; -import { DEFAULT_TEXTURE } from "../libs/constants"; import { FxBasicFxMaterial } from "./FxBasicFxMaterial"; import { BasicFxUniforms, BasicFxValues } from "./BasicFxLib"; @@ -14,7 +8,7 @@ type FxBasicFxMaterialImplUniforms = { src: { value: THREE.Texture }; } & BasicFxUniforms; -type FxBasixFxMaterialImplValues = { +export type FxBasicFxMaterialImplValues = { src?: THREE.Texture; } & BasicFxValues; @@ -41,40 +35,33 @@ const fragment = ` } `; -/*=============================================== -TODO * -- FxMaterialImplもTHREE.UniformsUtils.mergeを使うように変更 - - そもそもなぜ、mergeを使うとバグが解消されるのか調査 -- 全体的に、THREE.UniformsUtils.mergeの必要性を検討 - -===============================================*/ -export const createFxBasixFxMaterial = ({ +export const createFxBasicFxMaterialImpl = ({ uniforms, vertexShader = vertex, fragmentShader = fragment, }: ShaderWithUniforms = {}) => { class FxBasicFxMaterialImpl extends FxBasicFxMaterial { + public key: string = THREE.MathUtils.generateUUID(); + static get type() { return "FxBasicFxMaterialImpl"; } uniforms!: FxBasicFxMaterialImplUniforms; - constructor(props: FxMaterialProps) { + constructor(props: FxMaterialProps) { super(); this.type = FxBasicFxMaterialImpl.type; - this.uniforms = { - ...THREE.UniformsUtils.merge([ - this.uniforms, - { - src: { value: null }, - }, - ]), - ...uniforms, - ...props?.uniforms, - }; + this.uniforms = THREE.UniformsUtils.merge([ + this.uniforms, + { + src: { value: null }, + }, + uniforms || {}, + props?.uniforms || {}, + ]) as FxBasicFxMaterialImplUniforms; this.setupBasicFxShaders( props?.vertexShader || vertexShader, @@ -84,9 +71,12 @@ export const createFxBasixFxMaterial = ({ this.setUniformValues(props?.uniformValues); this.setValues(props?.materialParameters || {}); - this.defineUniformAccessors(() => this.updateBasicFx()); + // to update basicFx flag + this.defineUniformAccessors(this.updateBasicFx.bind(this)); } } - return FxBasicFxMaterialImpl; + return FxBasicFxMaterialImpl as typeof FxBasicFxMaterialImpl & { + key: string; + }; }; diff --git a/packages/use-shader-fx/src/materials/FxMaterial.ts b/packages/use-shader-fx/src/materials/FxMaterial.ts index 30232295..7c1c21ff 100644 --- a/packages/use-shader-fx/src/materials/FxMaterial.ts +++ b/packages/use-shader-fx/src/materials/FxMaterial.ts @@ -31,13 +31,15 @@ export class FxMaterial extends THREE.ShaderMaterial { }: FxMaterialProps = {}) { super(); - this.uniforms = { - resolution: { value: new THREE.Vector2() }, - texelSize: { value: new THREE.Vector2() }, - aspectRatio: { value: 0 }, - maxAspect: { value: new THREE.Vector2() }, - ...uniforms, - } as DefaultUniforms; + this.uniforms = THREE.UniformsUtils.merge([ + { + resolution: { value: new THREE.Vector2() }, + texelSize: { value: new THREE.Vector2() }, + aspectRatio: { value: 0 }, + maxAspect: { value: new THREE.Vector2() }, + }, + uniforms || {}, + ]) as DefaultUniforms; this.setupDefaultShaders(vertexShader, fragmentShader); diff --git a/packages/use-shader-fx/src/materials/FxMaterialImpl.ts b/packages/use-shader-fx/src/materials/FxMaterialImpl.ts index be24d873..57a825b0 100644 --- a/packages/use-shader-fx/src/materials/FxMaterialImpl.ts +++ b/packages/use-shader-fx/src/materials/FxMaterialImpl.ts @@ -4,7 +4,6 @@ import { FxMaterial, FxMaterialProps, ShaderWithUniforms, - Uniforms, } from "./FxMaterial"; import { ShaderLib } from "../libs/shaders/ShaderLib"; import { DEFAULT_TEXTURE } from "../libs/constants"; @@ -13,7 +12,7 @@ type FxMaterialImplUniforms = { src: { value: THREE.Texture }; } & DefaultUniforms; -type FxMaterialImplValues = { +export type FxMaterialImplValues = { src?: THREE.Texture; }; @@ -30,31 +29,33 @@ const fragment = ` } `; -export const createFxMaterial = ({ +export const createFxMaterialImpl = ({ uniforms, vertexShader = vertex, fragmentShader = fragment, }: ShaderWithUniforms = {}) => { class FxMaterialImpl extends FxMaterial { + public key: string = THREE.MathUtils.generateUUID(); + static get type() { return "FxMaterialImpl"; } - uniforms!: FxMaterialImplUniforms & Uniforms; + uniforms!: FxMaterialImplUniforms; constructor(props: FxMaterialProps) { super(); this.type = FxMaterialImpl.type; - this.uniforms = { - ...this.uniforms, - ...{ + this.uniforms = THREE.UniformsUtils.merge([ + this.uniforms, + { src: { value: DEFAULT_TEXTURE }, }, - ...uniforms, - ...props?.uniforms, - }; + uniforms || {}, + props?.uniforms || {}, + ]) as FxMaterialImplUniforms; this.setupDefaultShaders( props?.vertexShader || vertexShader, @@ -68,5 +69,7 @@ export const createFxMaterial = ({ } } - return FxMaterialImpl; + return FxMaterialImpl as typeof FxMaterialImpl & { + key: string; + }; }; diff --git a/todo b/todo index 341c7894..e69de29b 100644 --- a/todo +++ b/todo @@ -1,2 +0,0 @@ - -- ぜんぶdefineUniformAccessorsしたら、materialとして使えるのでは? \ No newline at end of file From 3d0f899de4d8381313b419868c4137b5a9c15d2a Mon Sep 17 00:00:00 2001 From: takuma-hmng8 Date: Fri, 4 Oct 2024 11:33:09 +0900 Subject: [PATCH 11/60] add:useWindowPointer --- README.md | 10 ++--- .../use-shader-fx/src/hooks/types/index.ts | 8 +++- .../src/hooks/useFluid/scenes/useSplat.ts | 8 ++-- .../{usePointer.ts => usePointerTracker.ts} | 8 ++-- .../src/misc/useWindowPointer.ts | 39 +++++++++++++++++++ 5 files changed, 59 insertions(+), 14 deletions(-) rename packages/use-shader-fx/src/misc/{usePointer.ts => usePointerTracker.ts} (92%) create mode 100644 packages/use-shader-fx/src/misc/useWindowPointer.ts diff --git a/README.md b/README.md index 2ca77a06..f3389976 100644 --- a/README.md +++ b/README.md @@ -73,7 +73,7 @@ npm install @funtech-inc/use-shader-fx - +
    miscuseBeat, useFPSLimiter, usePointer, useDomSynceruseBeat, useFPSLimiter, usePointerTracker, useDomSyncer
    @@ -409,23 +409,23 @@ type DomSyncerParams = { `updateKey` : Because DOM rendering and React updates occur asynchronously, there may be a lag between updating dependent arrays and setting DOM arrays. That's what the Key is for. If the dependent array is updated but the Key is not, the loop will skip and return an empty texture. By updating the timing key when DOM acquisition is complete, you can perfectly synchronize DOM and Mesh updates. -## usePointer +## usePointerTracker When given the `pointer` vector2 from r3f's `RootState`, it generates an update function that returns {currentPointer, prevPointer, diffPointer, isVelocityUpdate, velocity}. You can also add `lerp` (0~1, lerp intensity (0 to less than 1) , default: 0) ```js -const updatePointer = usePointer(lerp); +const pointerTracker = usePointerTracker(lerp); const { currentPointer, prevPointer, diffPointer, isVelocityUpdate, velocity } = - updatePointer(pointer); + pointerTracker(pointer); ``` You can override the pointer process by passing `pointerValues` to `updateFx` in the `useFrame`. ```ts useFrame((rootState) => { - const pointerValues = updatePointer(rootState.pointer); + const pointerValues = pointerTracker(rootState.pointer); updateBrush(rootState, { pointerValues: pointerValues, }); diff --git a/packages/use-shader-fx/src/hooks/types/index.ts b/packages/use-shader-fx/src/hooks/types/index.ts index 4f2cd119..0319b515 100644 --- a/packages/use-shader-fx/src/hooks/types/index.ts +++ b/packages/use-shader-fx/src/hooks/types/index.ts @@ -1,6 +1,12 @@ import * as THREE from "three"; -export type Size = { width: number; height: number }; +export type Size = { + width: number; + height: number; + top: number; + left: number; + updateStyle?: boolean; +}; export type Dpr = | number diff --git a/packages/use-shader-fx/src/hooks/useFluid/scenes/useSplat.ts b/packages/use-shader-fx/src/hooks/useFluid/scenes/useSplat.ts index 87bad285..6f79e62f 100644 --- a/packages/use-shader-fx/src/hooks/useFluid/scenes/useSplat.ts +++ b/packages/use-shader-fx/src/hooks/useFluid/scenes/useSplat.ts @@ -2,7 +2,7 @@ import { useCallback } from "react"; import { RootState, Size } from "../../types"; import { SingleFBOUpdateFunction } from "../../../utils/useSingleFBO"; import { SplatMaterial } from "../materials/SplatMaterial"; -import { usePointer } from "../../../misc/usePointer"; +import { usePointerTracker } from "../../../misc/usePointerTracker"; import { useFxScene } from "../../../utils/useFxScene"; export const useSplat = ( @@ -25,12 +25,12 @@ export const useSplat = ( }, }); - const updatePointer = usePointer(); + const pointerTracker = usePointerTracker(); const render = useCallback( (rootState: RootState) => { const { gl, pointer } = rootState; - const { currentPointer, diffPointer } = updatePointer(pointer); + const { currentPointer, diffPointer } = pointerTracker(pointer); material.uniforms.center.value.copy(currentPointer); material.uniforms.force.value.copy( @@ -39,7 +39,7 @@ export const useSplat = ( updateRenderTarget({ gl, scene, camera, clear: false }); }, - [updateRenderTarget, material, updatePointer, scene, camera] + [updateRenderTarget, material, pointerTracker, scene, camera] ); return { render, material }; diff --git a/packages/use-shader-fx/src/misc/usePointer.ts b/packages/use-shader-fx/src/misc/usePointerTracker.ts similarity index 92% rename from packages/use-shader-fx/src/misc/usePointer.ts rename to packages/use-shader-fx/src/misc/usePointerTracker.ts index dc8482ed..9077b688 100644 --- a/packages/use-shader-fx/src/misc/usePointer.ts +++ b/packages/use-shader-fx/src/misc/usePointerTracker.ts @@ -9,14 +9,14 @@ export type PointerValues = { isVelocityUpdate: boolean; }; -type UpdatePointer = (currentPointer: THREE.Vector2) => PointerValues; +type PointerTracker = (currentPointer: THREE.Vector2) => PointerValues; /** * @description When given the pointer vector2 from r3f's RootState, it generates an update function that returns {`currentPointer`, `prevPointer`, `diffPointer`, `isVelocityUpdate`, `velocity`}. * @description When calling custom in a `useFrame` loop, you can avoid duplication of execution by passing `pointerValues` to the update function of a Pointer-activated fxHook, such as `useBrush`. * @param lerp 0~1, lerp intensity (0 to less than 1) , default : `0` */ -export const usePointer = (lerp: number = 0): UpdatePointer => { +export const usePointerTracker = (lerp: number = 0): PointerTracker => { const prevPointer = useRef(new THREE.Vector2(0, 0)); const diffPointer = useRef(new THREE.Vector2(0, 0)); const lerpPointer = useRef(new THREE.Vector2(0, 0)); @@ -24,7 +24,7 @@ export const usePointer = (lerp: number = 0): UpdatePointer => { const velocity = useRef(new THREE.Vector2(0, 0)); const isMoved = useRef(false); - const updatePointer = useCallback( + const pointerTracker = useCallback( (currentPointer: THREE.Vector2) => { const now = performance.now(); @@ -76,5 +76,5 @@ export const usePointer = (lerp: number = 0): UpdatePointer => { [lerp] ); - return updatePointer; + return pointerTracker; }; diff --git a/packages/use-shader-fx/src/misc/useWindowPointer.ts b/packages/use-shader-fx/src/misc/useWindowPointer.ts new file mode 100644 index 00000000..d1d20c12 --- /dev/null +++ b/packages/use-shader-fx/src/misc/useWindowPointer.ts @@ -0,0 +1,39 @@ +import { useEffect, useRef } from "react"; +import * as THREE from "three"; +import { Size } from "../hooks/types"; + +const PASSIVE = { passive: true }; + +/** + * @param size Size + * @returns THREE.Vector2 + */ +export const useWindowPointer = (size: Size) => { + const windowPointer = useRef(new THREE.Vector2(0)); + + useEffect(() => { + const compute = (x: number, y: number) => { + windowPointer.current.set( + ((x - size.left) / size.width) * 2 - 1, + -((y - size.top) / size.height) * 2 + 1 + ); + }; + const handleTouchMove = (event: TouchEvent) => { + const touch = event.touches[0]; + compute(touch.clientX, touch.clientY); + }; + const handlePointerMove = (event: PointerEvent) => { + compute(event.clientX, event.clientY); + }; + + window.addEventListener("touchmove", handleTouchMove, PASSIVE); + window.addEventListener("pointermove", handlePointerMove, PASSIVE); + + return () => { + window.removeEventListener("touchmove", handleTouchMove); + window.removeEventListener("pointermove", handlePointerMove); + }; + }, [size]); + + return windowPointer.current; +}; From 9cf6898b23ff8408d1d39c0471f4e6c836c1827b Mon Sep 17 00:00:00 2001 From: takuma-hmng8 Date: Tue, 8 Oct 2024 15:13:31 +0900 Subject: [PATCH 12/60] update:compose --- app/{v2_FxRenderer => v2_impl}/Playground.tsx | 24 +++--- app/{v2_FxRenderer => v2_impl}/page.tsx | 0 app/v2_pipe/Playground.tsx | 80 +++++++++++++++++++ app/v2_pipe/page.tsx | 19 +++++ .../use-shader-fx/src/hooks/types/index.ts | 3 +- 5 files changed, 113 insertions(+), 13 deletions(-) rename app/{v2_FxRenderer => v2_impl}/Playground.tsx (90%) rename app/{v2_FxRenderer => v2_impl}/page.tsx (100%) create mode 100644 app/v2_pipe/Playground.tsx create mode 100644 app/v2_pipe/page.tsx diff --git a/app/v2_FxRenderer/Playground.tsx b/app/v2_impl/Playground.tsx similarity index 90% rename from app/v2_FxRenderer/Playground.tsx rename to app/v2_impl/Playground.tsx index 29404c99..1a459622 100644 --- a/app/v2_FxRenderer/Playground.tsx +++ b/app/v2_impl/Playground.tsx @@ -47,17 +47,17 @@ export const Playground = () => { depthBuffer: true, }); - const blur = useBlur({ - size, - dpr: 1, - src: renderTarget.texture, - }); + // const blur = useBlur({ + // size, + // dpr: 1, + // src: renderTarget.texture, + // }); - const noise = useNoise({ - size, - dpr: 0.05, - scale: 0.03, - }); + // const noise = useNoise({ + // size, + // dpr: 0.05, + // scale: 0.03, + // }); const fluid = useFluid({ size, @@ -66,8 +66,8 @@ export const Playground = () => { useFrame((state) => { updateRenderTarget({ gl: state.gl }); - noise.render(state); - blur.render(state); + // noise.render(state); + // blur.render(state); fluid.render(state); }); diff --git a/app/v2_FxRenderer/page.tsx b/app/v2_impl/page.tsx similarity index 100% rename from app/v2_FxRenderer/page.tsx rename to app/v2_impl/page.tsx diff --git a/app/v2_pipe/Playground.tsx b/app/v2_pipe/Playground.tsx new file mode 100644 index 00000000..4c799f16 --- /dev/null +++ b/app/v2_pipe/Playground.tsx @@ -0,0 +1,80 @@ +"use client"; + +import * as THREE from "three"; +import { useCallback, useMemo, useRef, useState } from "react"; +import { useFrame, useThree, extend, createPortal } from "@react-three/fiber"; +import { + useNoise, + useBlur, + useSingleFBO, + createFxMaterialImpl, + createFxBasicFxMaterialImpl, + FxMaterialImplValues, + FxBasicFxMaterialImplValues, + useFluid, +} from "@/packages/use-shader-fx/src"; +import { + HooksProps, + HooksReturn, + RootState, +} from "@/packages/use-shader-fx/src/hooks/types"; +import { BasicFxValues } from "@/packages/use-shader-fx/src/materials/BasicFxLib"; + +const FxMaterialImpl = createFxMaterialImpl(); +const FxBasicFxMaterialImpl = createFxBasicFxMaterialImpl(); + +extend({ FxMaterialImpl, FxBasicFxMaterialImpl }); + +/*=============================================== +fxのパイプラインをつくる +const {render,texture} = compose({type,size,dpr,config},{type,size,dpr,config}); +- Generates a pipeline of fx +- Automatically receives one previous texture as mixSrc +===============================================*/ + +type FxConfig = { + fx: typeof useFluid | typeof useNoise; +} & HooksProps & + BasicFxValues; + +const compose = (...configs: FxConfig[]) => { + const fxArr: HooksReturn[] = []; + configs.forEach(({ fx, ...rest }, i) => + fxArr.push( + fx({ + ...rest, + mixSrc: fxArr[i - 1]?.texture, + }) + ) + ); + const render = (state: RootState) => fxArr.forEach((fx) => fx.render(state)); + return { render, texture: fxArr.at(-1)?.texture }; +}; + +export const Playground = () => { + const { size } = useThree(); + + const { render, texture } = compose( + { fx: useFluid, size, dpr: 0.4 }, + { fx: useNoise, size, dpr: 0.2, mixSrcColorFactor: 0.3 } + ); + useFrame((state) => render(state)); + + return ( + + + + + ); +}; + +declare global { + namespace JSX { + interface IntrinsicElements { + fxMaterialImpl: FxMaterialImplValues & + JSX.IntrinsicElements["shaderMaterial"]; + fxBasicFxMaterialImpl: FxBasicFxMaterialImplValues & + JSX.IntrinsicElements["shaderMaterial"]; + } + } +} diff --git a/app/v2_pipe/page.tsx b/app/v2_pipe/page.tsx new file mode 100644 index 00000000..be301da0 --- /dev/null +++ b/app/v2_pipe/page.tsx @@ -0,0 +1,19 @@ +import { ShaderFx } from "../ShaderFx"; +import { Playground } from "./Playground"; +import Image from "next/image"; + +export default function Page() { + return ( +
    + + + +
    + ); +} diff --git a/packages/use-shader-fx/src/hooks/types/index.ts b/packages/use-shader-fx/src/hooks/types/index.ts index 0319b515..689f4161 100644 --- a/packages/use-shader-fx/src/hooks/types/index.ts +++ b/packages/use-shader-fx/src/hooks/types/index.ts @@ -1,4 +1,5 @@ import * as THREE from "three"; +import { FxBasicFxMaterial } from "../../materials/FxBasicFxMaterial"; export type Size = { width: number; @@ -54,7 +55,7 @@ export interface HooksProps { * @template V The type for the FX parameters. * @template O The type for the material. */ -export type HooksReturn = { +export type HooksReturn = { /** * Functions to update parameters and render. * @param rootState RootState From 1c82584b7c7c2c3ca8a56cfdf263f30d82f13092 Mon Sep 17 00:00:00 2001 From: takuma-hmng8 Date: Tue, 8 Oct 2024 15:31:28 +0900 Subject: [PATCH 13/60] update:compose --- app/v2_impl/Playground.tsx | 16 ++++++++-------- app/v2_impl/page.tsx | 2 +- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/app/v2_impl/Playground.tsx b/app/v2_impl/Playground.tsx index 1a459622..7b20ec67 100644 --- a/app/v2_impl/Playground.tsx +++ b/app/v2_impl/Playground.tsx @@ -53,11 +53,11 @@ export const Playground = () => { // src: renderTarget.texture, // }); - // const noise = useNoise({ - // size, - // dpr: 0.05, - // scale: 0.03, - // }); + const noise = useNoise({ + size, + dpr: 0.23, + scale: 0.03, + }); const fluid = useFluid({ size, @@ -66,9 +66,9 @@ export const Playground = () => { useFrame((state) => { updateRenderTarget({ gl: state.gl }); - // noise.render(state); + noise.render(state); // blur.render(state); - fluid.render(state); + // fluid.render(state); }); const ref = useRef(); @@ -82,7 +82,7 @@ export const Playground = () => { diff --git a/app/v2_impl/page.tsx b/app/v2_impl/page.tsx index cc9a6d74..22ab960c 100644 --- a/app/v2_impl/page.tsx +++ b/app/v2_impl/page.tsx @@ -24,7 +24,7 @@ export default function Page() { }}> - + From bf937c450272005ffeb602fc4284c1c00f9ab2cf Mon Sep 17 00:00:00 2001 From: takuma-hmng8 Date: Thu, 10 Oct 2024 13:13:57 +0900 Subject: [PATCH 14/60] update:useComposer --- app/v2_impl/Playground.tsx | 15 +-- app/v2_impl/page.tsx | 2 +- app/v2_pipe/Playground.tsx | 98 +++++++++++-------- app/v2_pipe/page.tsx | 1 - .../use-shader-fx/src/hooks/types/index.ts | 2 +- .../src/hooks/useBlur/BlurMaterial.ts | 6 +- .../use-shader-fx/src/hooks/useBlur/index.ts | 2 +- .../useCoverTexture/CoverTextureMaterial.ts | 6 +- .../src/hooks/useCoverTexture/index.ts | 2 +- .../useFluid/materials/AdvectionMaterial.ts | 2 +- .../useFluid/materials/DivergenceMaterial.ts | 2 +- .../useFluid/materials/PoissonMaterial.ts | 2 +- .../useFluid/materials/PressureMaterial.ts | 2 +- .../hooks/useFluid/materials/SplatMaterial.ts | 2 +- .../src/hooks/useNoise/NoiseMaterial.ts | 6 +- .../use-shader-fx/src/hooks/useNoise/index.ts | 2 +- .../src/hooks/useRawBlank/RawBlankMaterial.ts | 2 +- packages/use-shader-fx/src/index.js | 9 +- .../src/materials/{ => core}/BasicFxLib.ts | 0 .../materials/{ => core}/FxBasicFxMaterial.ts | 2 +- .../src/materials/{ => core}/FxMaterial.ts | 4 +- .../{ => impl}/FxBasicFxMaterialImpl.ts | 8 +- .../materials/{ => impl}/FxMaterialImpl.ts | 6 +- .../use-shader-fx/src/misc/useComposer.ts | 52 ++++++++++ .../use-shader-fx/src/utils/useFxScene.ts | 4 +- todo | 18 ++++ 26 files changed, 178 insertions(+), 79 deletions(-) rename packages/use-shader-fx/src/materials/{ => core}/BasicFxLib.ts (100%) rename packages/use-shader-fx/src/materials/{ => core}/FxBasicFxMaterial.ts (97%) rename packages/use-shader-fx/src/materials/{ => core}/FxMaterial.ts (95%) rename packages/use-shader-fx/src/materials/{ => impl}/FxBasicFxMaterialImpl.ts (87%) rename packages/use-shader-fx/src/materials/{ => impl}/FxMaterialImpl.ts (91%) create mode 100644 packages/use-shader-fx/src/misc/useComposer.ts diff --git a/app/v2_impl/Playground.tsx b/app/v2_impl/Playground.tsx index 7b20ec67..ba09c527 100644 --- a/app/v2_impl/Playground.tsx +++ b/app/v2_impl/Playground.tsx @@ -55,14 +55,17 @@ export const Playground = () => { const noise = useNoise({ size, - dpr: 0.23, - scale: 0.03, + dpr: 0.3, + scale: 0.3, + noiseOctaves: 2, }); - const fluid = useFluid({ - size, - dpr: 0.25, - }); + console.log(noise); + + // const fluid = useFluid({ + // size, + // dpr: 0.25, + // }); useFrame((state) => { updateRenderTarget({ gl: state.gl }); diff --git a/app/v2_impl/page.tsx b/app/v2_impl/page.tsx index 22ab960c..cc9a6d74 100644 --- a/app/v2_impl/page.tsx +++ b/app/v2_impl/page.tsx @@ -24,7 +24,7 @@ export default function Page() { }}> - + diff --git a/app/v2_pipe/Playground.tsx b/app/v2_pipe/Playground.tsx index 4c799f16..00f040e8 100644 --- a/app/v2_pipe/Playground.tsx +++ b/app/v2_pipe/Playground.tsx @@ -1,24 +1,17 @@ "use client"; -import * as THREE from "three"; -import { useCallback, useMemo, useRef, useState } from "react"; import { useFrame, useThree, extend, createPortal } from "@react-three/fiber"; import { useNoise, - useBlur, - useSingleFBO, createFxMaterialImpl, createFxBasicFxMaterialImpl, FxMaterialImplValues, FxBasicFxMaterialImplValues, useFluid, + useComposer, + FxConfig, } from "@/packages/use-shader-fx/src"; -import { - HooksProps, - HooksReturn, - RootState, -} from "@/packages/use-shader-fx/src/hooks/types"; -import { BasicFxValues } from "@/packages/use-shader-fx/src/materials/BasicFxLib"; +import { useEffect, useMemo, useState } from "react"; const FxMaterialImpl = createFxMaterialImpl(); const FxBasicFxMaterialImpl = createFxBasicFxMaterialImpl(); @@ -26,48 +19,75 @@ const FxBasicFxMaterialImpl = createFxBasicFxMaterialImpl(); extend({ FxMaterialImpl, FxBasicFxMaterialImpl }); /*=============================================== -fxのパイプラインをつくる -const {render,texture} = compose({type,size,dpr,config},{type,size,dpr,config}); -- Generates a pipeline of fx -- Automatically receives one previous texture as mixSrc +reactive way +- fxの変更をtriggerにkeyを変更することで、reactiveにfxを変更することが可能 ===============================================*/ - -type FxConfig = { - fx: typeof useFluid | typeof useNoise; -} & HooksProps & - BasicFxValues; - -const compose = (...configs: FxConfig[]) => { - const fxArr: HooksReturn[] = []; - configs.forEach(({ fx, ...rest }, i) => - fxArr.push( - fx({ - ...rest, - mixSrc: fxArr[i - 1]?.texture, - }) - ) - ); - const render = (state: RootState) => fxArr.forEach((fx) => fx.render(state)); - return { render, texture: fxArr.at(-1)?.texture }; +const Composer = ({ compose }: { compose: FxConfig[] }) => { + const { texture, render } = useComposer(...compose); + useFrame((state) => render(state)); + return ; }; - export const Playground = () => { const { size } = useThree(); - const { render, texture } = compose( - { fx: useFluid, size, dpr: 0.4 }, - { fx: useNoise, size, dpr: 0.2, mixSrcColorFactor: 0.3 } - ); - useFrame((state) => render(state)); + const compose: FxConfig[] = [ + { fx: useFluid, size, dpr: 0.3 }, + { + fx: useNoise, + size, + dpr: 0.1, + mixSrcColorFactor: 0.2, + }, + ]; + + // keyを変更することで、fxの変更をreactiveにすることが可能 + // UIではGUIの変更を検知して、keyを変更することで、reactiveに変更を反映するなどを想定 + const [composeCache, setComposeCache] = useState(compose.length); + const [version, setVersion] = useState(0); + if (compose.length !== composeCache) { + setComposeCache(compose.length); + setVersion(version + 1); + } return ( - + ); }; +/*=============================================== +non-reactive way +- resolutionはreactive + - ただし他のhooksと同様、resolution以外はnon-reactive +===============================================*/ +// export const Playground = () => { +// const { size } = useThree(); + +// const { texture, render } = useComposer( +// { +// fx: useFluid, +// size, +// dpr: 0.2, +// }, +// { +// fx: useNoise, +// size, +// dpr: 0.1, +// mixSrcColorFactor: 0.2, +// } +// ); +// useFrame((state) => render(state)); + +// return ( +// +// +// +// +// ); +// }; + declare global { namespace JSX { interface IntrinsicElements { diff --git a/app/v2_pipe/page.tsx b/app/v2_pipe/page.tsx index be301da0..a84dd222 100644 --- a/app/v2_pipe/page.tsx +++ b/app/v2_pipe/page.tsx @@ -1,6 +1,5 @@ import { ShaderFx } from "../ShaderFx"; import { Playground } from "./Playground"; -import Image from "next/image"; export default function Page() { return ( diff --git a/packages/use-shader-fx/src/hooks/types/index.ts b/packages/use-shader-fx/src/hooks/types/index.ts index 689f4161..1955c143 100644 --- a/packages/use-shader-fx/src/hooks/types/index.ts +++ b/packages/use-shader-fx/src/hooks/types/index.ts @@ -1,5 +1,5 @@ import * as THREE from "three"; -import { FxBasicFxMaterial } from "../../materials/FxBasicFxMaterial"; +import { FxBasicFxMaterial } from "../../materials/core/FxBasicFxMaterial"; export type Size = { width: number; diff --git a/packages/use-shader-fx/src/hooks/useBlur/BlurMaterial.ts b/packages/use-shader-fx/src/hooks/useBlur/BlurMaterial.ts index 923ffe01..97acb65c 100644 --- a/packages/use-shader-fx/src/hooks/useBlur/BlurMaterial.ts +++ b/packages/use-shader-fx/src/hooks/useBlur/BlurMaterial.ts @@ -1,9 +1,9 @@ import * as THREE from "three"; import { fragment, vertex } from "./blur.glsl"; -import { FxBasicFxMaterial } from "../../materials/FxBasicFxMaterial"; +import { FxBasicFxMaterial } from "../../materials/core/FxBasicFxMaterial"; import { BlurValues } from "."; -import { FxMaterialProps } from "../../materials/FxMaterial"; -import { BasicFxUniforms } from "../../materials/BasicFxLib"; +import { FxMaterialProps } from "../../materials/core/FxMaterial"; +import { BasicFxUniforms } from "../../materials/core/BasicFxLib"; type BlurUniforms = { src: { value: THREE.Texture | null }; diff --git a/packages/use-shader-fx/src/hooks/useBlur/index.ts b/packages/use-shader-fx/src/hooks/useBlur/index.ts index 222f0fa4..ecb06a61 100644 --- a/packages/use-shader-fx/src/hooks/useBlur/index.ts +++ b/packages/use-shader-fx/src/hooks/useBlur/index.ts @@ -5,7 +5,7 @@ import { useDpr } from "../../utils/useDpr"; import { RootState } from "../types"; import { BlurMaterial } from "./BlurMaterial"; import { useFxScene } from "../../utils/useFxScene"; -import { BasicFxValues } from "../../materials/BasicFxLib"; +import { BasicFxValues } from "../../materials/core/BasicFxLib"; import { useDoubleFBO } from "../../utils/useDoubleFBO"; export type BlurValues = { diff --git a/packages/use-shader-fx/src/hooks/useCoverTexture/CoverTextureMaterial.ts b/packages/use-shader-fx/src/hooks/useCoverTexture/CoverTextureMaterial.ts index 38a318fe..c3561991 100644 --- a/packages/use-shader-fx/src/hooks/useCoverTexture/CoverTextureMaterial.ts +++ b/packages/use-shader-fx/src/hooks/useCoverTexture/CoverTextureMaterial.ts @@ -1,9 +1,9 @@ import * as THREE from "three"; import { fragment, vertex } from "./coverTexture.glsl"; -import { FxBasicFxMaterial } from "../../materials/FxBasicFxMaterial"; +import { FxBasicFxMaterial } from "../../materials/core/FxBasicFxMaterial"; import { CoverTextureValues } from "."; -import { FxMaterialProps } from "../../materials/FxMaterial"; -import { BasicFxUniforms } from "../../materials/BasicFxLib"; +import { FxMaterialProps } from "../../materials/core/FxMaterial"; +import { BasicFxUniforms } from "../../materials/core/BasicFxLib"; type CoverTextureUniforms = { src: { value: THREE.Texture | null }; diff --git a/packages/use-shader-fx/src/hooks/useCoverTexture/index.ts b/packages/use-shader-fx/src/hooks/useCoverTexture/index.ts index cee3a5ed..bcfe9444 100644 --- a/packages/use-shader-fx/src/hooks/useCoverTexture/index.ts +++ b/packages/use-shader-fx/src/hooks/useCoverTexture/index.ts @@ -6,7 +6,7 @@ import { useDpr } from "../../utils/useDpr"; import { RootState } from "../types"; import { CoverTextureMaterial } from "./CoverTextureMaterial"; import { useFxScene } from "../../utils/useFxScene"; -import { BasicFxValues } from "../../materials/BasicFxLib"; +import { BasicFxValues } from "../../materials/core/BasicFxLib"; export type CoverTextureValues = { src?: THREE.Texture; diff --git a/packages/use-shader-fx/src/hooks/useFluid/materials/AdvectionMaterial.ts b/packages/use-shader-fx/src/hooks/useFluid/materials/AdvectionMaterial.ts index c6ab8410..f58ead9a 100644 --- a/packages/use-shader-fx/src/hooks/useFluid/materials/AdvectionMaterial.ts +++ b/packages/use-shader-fx/src/hooks/useFluid/materials/AdvectionMaterial.ts @@ -5,7 +5,7 @@ import { FxMaterial, DefaultUniforms, FxMaterialProps, -} from "../../../materials/FxMaterial"; +} from "../../../materials/core/FxMaterial"; import { DEFAULT_TEXTURE } from "../../../libs/constants"; import { DeltaTime } from ".."; diff --git a/packages/use-shader-fx/src/hooks/useFluid/materials/DivergenceMaterial.ts b/packages/use-shader-fx/src/hooks/useFluid/materials/DivergenceMaterial.ts index aaeab2ea..b519a0ed 100644 --- a/packages/use-shader-fx/src/hooks/useFluid/materials/DivergenceMaterial.ts +++ b/packages/use-shader-fx/src/hooks/useFluid/materials/DivergenceMaterial.ts @@ -5,7 +5,7 @@ import { FxMaterial, DefaultUniforms, FxMaterialProps, -} from "../../../materials/FxMaterial"; +} from "../../../materials/core/FxMaterial"; import { DEFAULT_TEXTURE } from "../../../libs/constants"; import { DeltaTime } from ".."; diff --git a/packages/use-shader-fx/src/hooks/useFluid/materials/PoissonMaterial.ts b/packages/use-shader-fx/src/hooks/useFluid/materials/PoissonMaterial.ts index 03579371..b9c24bb8 100644 --- a/packages/use-shader-fx/src/hooks/useFluid/materials/PoissonMaterial.ts +++ b/packages/use-shader-fx/src/hooks/useFluid/materials/PoissonMaterial.ts @@ -5,7 +5,7 @@ import { DefaultUniforms, FxMaterial, FxMaterialProps, -} from "../../../materials/FxMaterial"; +} from "../../../materials/core/FxMaterial"; import { DEFAULT_TEXTURE } from "../../../libs/constants"; type PoissonUniforms = { diff --git a/packages/use-shader-fx/src/hooks/useFluid/materials/PressureMaterial.ts b/packages/use-shader-fx/src/hooks/useFluid/materials/PressureMaterial.ts index 69b652e2..c9ff3f4c 100644 --- a/packages/use-shader-fx/src/hooks/useFluid/materials/PressureMaterial.ts +++ b/packages/use-shader-fx/src/hooks/useFluid/materials/PressureMaterial.ts @@ -5,7 +5,7 @@ import { FxMaterial, DefaultUniforms, FxMaterialProps, -} from "../../../materials/FxMaterial"; +} from "../../../materials/core/FxMaterial"; import { DEFAULT_TEXTURE } from "../../../libs/constants"; import { DeltaTime } from ".."; diff --git a/packages/use-shader-fx/src/hooks/useFluid/materials/SplatMaterial.ts b/packages/use-shader-fx/src/hooks/useFluid/materials/SplatMaterial.ts index f70465b1..a1bec3ac 100644 --- a/packages/use-shader-fx/src/hooks/useFluid/materials/SplatMaterial.ts +++ b/packages/use-shader-fx/src/hooks/useFluid/materials/SplatMaterial.ts @@ -5,7 +5,7 @@ import { DefaultUniforms, FxMaterial, FxMaterialProps, -} from "../../../materials/FxMaterial"; +} from "../../../materials/core/FxMaterial"; type SplatUniforms = { force: { value: THREE.Vector2 }; diff --git a/packages/use-shader-fx/src/hooks/useNoise/NoiseMaterial.ts b/packages/use-shader-fx/src/hooks/useNoise/NoiseMaterial.ts index bce5bfae..9ea7d4ff 100644 --- a/packages/use-shader-fx/src/hooks/useNoise/NoiseMaterial.ts +++ b/packages/use-shader-fx/src/hooks/useNoise/NoiseMaterial.ts @@ -1,8 +1,8 @@ import * as THREE from "three"; import { noiseFragment, noiseVertex } from "./noise.glsl"; -import { FxBasicFxMaterial } from "../../materials/FxBasicFxMaterial"; -import { FxMaterialProps } from "../../materials/FxMaterial"; -import { BasicFxUniforms } from "../../materials/BasicFxLib"; +import { FxBasicFxMaterial } from "../../materials/core/FxBasicFxMaterial"; +import { FxMaterialProps } from "../../materials/core/FxMaterial"; +import { BasicFxUniforms } from "../../materials/core/BasicFxLib"; type NoiseUniforms = { tick: { value: number }; diff --git a/packages/use-shader-fx/src/hooks/useNoise/index.ts b/packages/use-shader-fx/src/hooks/useNoise/index.ts index 6837db8b..d0b50ef1 100644 --- a/packages/use-shader-fx/src/hooks/useNoise/index.ts +++ b/packages/use-shader-fx/src/hooks/useNoise/index.ts @@ -7,7 +7,7 @@ import { useDpr } from "../../utils/useDpr"; import { RootState } from "../types"; import { NoiseMaterial } from "./NoiseMaterial"; import { useFxScene } from "../../utils/useFxScene"; -import { BasicFxValues } from "../../materials/BasicFxLib"; +import { BasicFxValues } from "../../materials/core/BasicFxLib"; export type NoiseValues = { /** noise scale , default : `0.004` */ diff --git a/packages/use-shader-fx/src/hooks/useRawBlank/RawBlankMaterial.ts b/packages/use-shader-fx/src/hooks/useRawBlank/RawBlankMaterial.ts index 9441f457..834baac7 100644 --- a/packages/use-shader-fx/src/hooks/useRawBlank/RawBlankMaterial.ts +++ b/packages/use-shader-fx/src/hooks/useRawBlank/RawBlankMaterial.ts @@ -1,4 +1,4 @@ -import { FxMaterial, FxMaterialProps } from "../../materials/FxMaterial"; +import { FxMaterial, FxMaterialProps } from "../../materials/core/FxMaterial"; export class RawBlankMaterial extends FxMaterial { static get type() { diff --git a/packages/use-shader-fx/src/index.js b/packages/use-shader-fx/src/index.js index 9aac21e8..4676f6b3 100644 --- a/packages/use-shader-fx/src/index.js +++ b/packages/use-shader-fx/src/index.js @@ -10,11 +10,16 @@ export * from "./hooks/useBlur"; /*=============================================== materials ===============================================*/ -export * from "./materials/FxMaterialImpl"; -export * from "./materials/FxBasicFxMaterialImpl"; +export * from "./materials/impl/FxMaterialImpl"; +export * from "./materials/impl/FxBasicFxMaterialImpl"; /*=============================================== utils ===============================================*/ export * from "./utils/useDoubleFBO"; export * from "./utils/useSingleFBO"; + +/*=============================================== +misc +===============================================*/ +export * from "./misc/useComposer"; diff --git a/packages/use-shader-fx/src/materials/BasicFxLib.ts b/packages/use-shader-fx/src/materials/core/BasicFxLib.ts similarity index 100% rename from packages/use-shader-fx/src/materials/BasicFxLib.ts rename to packages/use-shader-fx/src/materials/core/BasicFxLib.ts diff --git a/packages/use-shader-fx/src/materials/FxBasicFxMaterial.ts b/packages/use-shader-fx/src/materials/core/FxBasicFxMaterial.ts similarity index 97% rename from packages/use-shader-fx/src/materials/FxBasicFxMaterial.ts rename to packages/use-shader-fx/src/materials/core/FxBasicFxMaterial.ts index dade84ef..5a3bad8b 100644 --- a/packages/use-shader-fx/src/materials/FxBasicFxMaterial.ts +++ b/packages/use-shader-fx/src/materials/core/FxBasicFxMaterial.ts @@ -6,7 +6,7 @@ import { BasicFxFlag, BasicFxLib, } from "./BasicFxLib"; -import { mergeShaderLib } from "../libs/shaders/mergeShaderLib"; +import { mergeShaderLib } from "../../libs/shaders/mergeShaderLib"; export class FxBasicFxMaterial extends FxMaterial { basicFxFlag: BasicFxFlag; diff --git a/packages/use-shader-fx/src/materials/FxMaterial.ts b/packages/use-shader-fx/src/materials/core/FxMaterial.ts similarity index 95% rename from packages/use-shader-fx/src/materials/FxMaterial.ts rename to packages/use-shader-fx/src/materials/core/FxMaterial.ts index 7c1c21ff..20bf1f86 100644 --- a/packages/use-shader-fx/src/materials/FxMaterial.ts +++ b/packages/use-shader-fx/src/materials/core/FxMaterial.ts @@ -1,6 +1,6 @@ import * as THREE from "three"; -import { resolveIncludes } from "../libs/shaders/resolveShaders"; -import { mergeShaderLib } from "../libs/shaders/mergeShaderLib"; +import { resolveIncludes } from "../../libs/shaders/resolveShaders"; +import { mergeShaderLib } from "../../libs/shaders/mergeShaderLib"; export type DefaultUniforms = { resolution: { value: THREE.Vector2 }; diff --git a/packages/use-shader-fx/src/materials/FxBasicFxMaterialImpl.ts b/packages/use-shader-fx/src/materials/impl/FxBasicFxMaterialImpl.ts similarity index 87% rename from packages/use-shader-fx/src/materials/FxBasicFxMaterialImpl.ts rename to packages/use-shader-fx/src/materials/impl/FxBasicFxMaterialImpl.ts index ab6a7f91..7ffbb4af 100644 --- a/packages/use-shader-fx/src/materials/FxBasicFxMaterialImpl.ts +++ b/packages/use-shader-fx/src/materials/impl/FxBasicFxMaterialImpl.ts @@ -1,8 +1,8 @@ import * as THREE from "three"; -import { FxMaterialProps, ShaderWithUniforms } from "./FxMaterial"; -import { ShaderLib } from "../libs/shaders/ShaderLib"; -import { FxBasicFxMaterial } from "./FxBasicFxMaterial"; -import { BasicFxUniforms, BasicFxValues } from "./BasicFxLib"; +import { FxMaterialProps, ShaderWithUniforms } from "../core/FxMaterial"; +import { ShaderLib } from "../../libs/shaders/ShaderLib"; +import { FxBasicFxMaterial } from "../core/FxBasicFxMaterial"; +import { BasicFxUniforms, BasicFxValues } from "../core/BasicFxLib"; type FxBasicFxMaterialImplUniforms = { src: { value: THREE.Texture }; diff --git a/packages/use-shader-fx/src/materials/FxMaterialImpl.ts b/packages/use-shader-fx/src/materials/impl/FxMaterialImpl.ts similarity index 91% rename from packages/use-shader-fx/src/materials/FxMaterialImpl.ts rename to packages/use-shader-fx/src/materials/impl/FxMaterialImpl.ts index 57a825b0..05465156 100644 --- a/packages/use-shader-fx/src/materials/FxMaterialImpl.ts +++ b/packages/use-shader-fx/src/materials/impl/FxMaterialImpl.ts @@ -4,9 +4,9 @@ import { FxMaterial, FxMaterialProps, ShaderWithUniforms, -} from "./FxMaterial"; -import { ShaderLib } from "../libs/shaders/ShaderLib"; -import { DEFAULT_TEXTURE } from "../libs/constants"; +} from "../core/FxMaterial"; +import { ShaderLib } from "../../libs/shaders/ShaderLib"; +import { DEFAULT_TEXTURE } from "../../libs/constants"; type FxMaterialImplUniforms = { src: { value: THREE.Texture }; diff --git a/packages/use-shader-fx/src/misc/useComposer.ts b/packages/use-shader-fx/src/misc/useComposer.ts new file mode 100644 index 00000000..606b889d --- /dev/null +++ b/packages/use-shader-fx/src/misc/useComposer.ts @@ -0,0 +1,52 @@ +import { useState } from "react"; +import { HooksProps, HooksReturn, RootState } from "../hooks/types"; +import { useFluid } from "../hooks/useFluid"; +import { useNoise } from "../hooks/useNoise"; +import { BasicFxValues } from "../materials/core/BasicFxLib"; + +export type FxConfig = { + // TODO * ここの型定義うまいことしたい /hooksにindex.tsを作ってそこでexportしてimportするとかかな + fx: typeof useFluid | typeof useNoise; +} & HooksProps & + BasicFxValues; + +/*=============================================== +- Generates a pipeline of fx +- hooks are non-reactive +- Automatically receives one previous texture as mixSrc +===============================================*/ +export const useComposer = (...args: FxConfig[]) => { + // non reactive + const [hooks] = useState(() => args.map(({ fx }) => fx)); + + // resolutionを更新するため、argsはreactiveにする + let _args = [...args]; + const argsDiff = hooks.length - _args.length; + + if (argsDiff !== 0) { + console.warn( + `use-shader-fx: fx and args length mismatch. fx is non-reactive; update by changing the key to reset state.` + ); + // argsの長さを調整する + if (argsDiff < 0) { + _args = _args.slice(0, hooks.length); + } else { + _args = _args.concat(Array(argsDiff).fill(_args.at(-1))); + } + } + + // hooksからの返り値を格納する + const fxArr: HooksReturn[] = []; + + hooks.forEach((hook, i) => { + const prev = fxArr[i - 1]?.texture; + const { fx: _, ...rest } = _args[i]; + fxArr.push(hook({ ...rest, ...(prev && { mixSrc: prev }) })); + }); + + const render = (state: RootState) => fxArr.forEach((fx) => fx.render(state)); + const setValues = (...values: {}[]) => + fxArr.forEach((fx, i) => fx.setValues(values[i])); + + return { render, setValues, texture: fxArr.at(-1)?.texture }; +}; diff --git a/packages/use-shader-fx/src/utils/useFxScene.ts b/packages/use-shader-fx/src/utils/useFxScene.ts index c013b217..e9586eaa 100644 --- a/packages/use-shader-fx/src/utils/useFxScene.ts +++ b/packages/use-shader-fx/src/utils/useFxScene.ts @@ -3,7 +3,7 @@ import { useState } from "react"; import { useObject3D } from "./useObject3D"; import { Size } from "../hooks/types"; import { useResolution } from "./useResolution"; -import { FxMaterial, FxMaterialProps } from "../materials/FxMaterial"; +import { FxMaterial, FxMaterialProps } from "../materials/core/FxMaterial"; import { useCamera } from "./useCamera"; type MaterialConstructor = new (props: FxMaterialProps) => M; @@ -30,12 +30,14 @@ export const useFxScene = ({ height: number; }; } & FxMaterialProps) => { + // non-reactive const [scene] = useState(() => new THREE.Scene()); const [_geometry] = useState( () => new geometry(geometrySize?.width || 2, geometrySize?.height || 2) ); const [_material] = useState(() => new material(materialProps)); + // materialのresolutionはreactiveに更新する const resolution = useResolution(size, dpr); _material.updateResolution(resolution); diff --git a/todo b/todo index e69de29b..ea454e38 100644 --- a/todo +++ b/todo @@ -0,0 +1,18 @@ +- useFxScene + - TODO* uniformValuesとmaterialParametersをreactiveにする + - Q * ここ、変更時のみにしないと一瞬ズレるかな? + - ここ(初期化時のuniformValues)nonReactiveでいいか(useComposeもnon reactiveだし。) +- useComposer + - non reactiveにすることにした! + - reactiveに処理したい場合は、keyを渡せばいい + - このケース、webglooでしか使わないよね + +- つまり、HooksPropsはsizeとdpr以外はnon reactiveになる。 + - ※ fboのsizeはsizeUpdateをtrueにしないと、nonReactive. + - ※ shaderのsizeは常にreactive + +TODO +- hooksReturnにfbo/renderTarget追加する +- hooksPropsのreactiveとnon-reactiveについてコメント追加 +- rename sizeUpdate to autoFBO/rendertarget SetSizeとか? +- useDPR、メモ化する必要ないかも \ No newline at end of file From 1bd0af0f36d6d12aefbd9e4c0f36f4bcf43d2980 Mon Sep 17 00:00:00 2001 From: takuma-hmng8 Date: Thu, 10 Oct 2024 20:29:32 +0900 Subject: [PATCH 15/60] update --- README.md | 2 +- app/v2_impl/Playground.tsx | 21 +++++---- .../use-shader-fx/src/hooks/types/index.ts | 7 ++- .../use-shader-fx/src/hooks/useBlur/index.ts | 9 ++-- .../src/hooks/useCoverTexture/index.ts | 9 ++-- .../use-shader-fx/src/hooks/useFluid/index.ts | 44 +++++++++---------- .../use-shader-fx/src/hooks/useNoise/index.ts | 9 ++-- .../src/hooks/useRawBlank/index.ts | 10 ++--- .../use-shader-fx/src/misc/useComposer.ts | 6 +-- packages/use-shader-fx/src/utils/getDpr.ts | 13 ++++++ .../use-shader-fx/src/utils/useDoubleFBO.ts | 4 +- packages/use-shader-fx/src/utils/useDpr.ts | 18 -------- .../use-shader-fx/src/utils/useObject3D.ts | 9 ++-- .../use-shader-fx/src/utils/useSingleFBO.ts | 8 ++-- todo | 18 -------- 15 files changed, 84 insertions(+), 103 deletions(-) create mode 100644 packages/use-shader-fx/src/utils/getDpr.ts delete mode 100644 packages/use-shader-fx/src/utils/useDpr.ts diff --git a/README.md b/README.md index f3389976..fb898ed6 100644 --- a/README.md +++ b/README.md @@ -84,7 +84,7 @@ From each `fxHooks`, you can receive [`updateFx`, `setParams`, `fxObject`] in ar 1. `updateFx` - Functions to update parameters and render. 2. `updateParams` - Function to update parameters only. 3. `fxObject` - An object that holds various FX components, such as scene, camera, mesh, renderTarget, and `output`(final rendered texture). -4. `HooksProps` - `size`,`dpr`,`isSizeUpdate`,`onBeforeInit` and `renderTargetOptions` ※ `isSizeUpdate` : Whether to `setSize` the FBO when updating size or dpr(default : `false`). +4. `HooksProps` - `size`,`dpr`,`fboAutoSetSize`,`onBeforeInit` and `renderTargetOptions` ※ `fboAutoSetSize` : Whether to `setSize` the FBO when updating size or dpr(default : `false`). ```js const [updateFx, updateParams, fxObject] = useSomeFx(HooksProps); diff --git a/app/v2_impl/Playground.tsx b/app/v2_impl/Playground.tsx index ba09c527..088647b8 100644 --- a/app/v2_impl/Playground.tsx +++ b/app/v2_impl/Playground.tsx @@ -55,23 +55,22 @@ export const Playground = () => { const noise = useNoise({ size, - dpr: 0.3, - scale: 0.3, + dpr: 0.1, + fboAutoSetSize: true, + scale: 0.2, noiseOctaves: 2, }); - console.log(noise); - - // const fluid = useFluid({ - // size, - // dpr: 0.25, - // }); + const fluid = useFluid({ + size, + dpr: 0.25, + }); useFrame((state) => { updateRenderTarget({ gl: state.gl }); - noise.render(state); + // noise.render(state); // blur.render(state); - // fluid.render(state); + fluid.render(state); }); const ref = useRef(); @@ -85,7 +84,7 @@ export const Playground = () => { diff --git a/packages/use-shader-fx/src/hooks/types/index.ts b/packages/use-shader-fx/src/hooks/types/index.ts index 1955c143..7d88faf9 100644 --- a/packages/use-shader-fx/src/hooks/types/index.ts +++ b/packages/use-shader-fx/src/hooks/types/index.ts @@ -1,5 +1,6 @@ import * as THREE from "three"; import { FxBasicFxMaterial } from "../../materials/core/FxBasicFxMaterial"; +import { DoubleRenderTarget } from "../../utils/useDoubleFBO"; export type Size = { width: number; @@ -29,13 +30,16 @@ export type RootState = { size: Size; }; +/** + * sceneやmaterialなどはミュータブルなオブジェクトであり、non-reactiveであるべき + */ export interface HooksProps { /** Width,Height in pixels, or `size` from r3f */ size: Size; /** Pixel-ratio, use `window.devicePixelRatio` or viewport.dpr from r3f */ dpr: Dpr; /** Whether to `setSize` the FBO when updating size or dpr. default : `false` */ - sizeUpdate?: boolean; + fboAutoSetSize?: boolean; /** * @type `THREE.RenderTargetOptions` * @param depthBuffer Unlike the default in three.js, the default is `false`. @@ -71,4 +75,5 @@ export type HooksReturn = { material: M; scene: THREE.Scene; camera: THREE.Camera; + renderTarget: THREE.WebGLRenderTarget | DoubleRenderTarget; }; diff --git a/packages/use-shader-fx/src/hooks/useBlur/index.ts b/packages/use-shader-fx/src/hooks/useBlur/index.ts index ecb06a61..af77870d 100644 --- a/packages/use-shader-fx/src/hooks/useBlur/index.ts +++ b/packages/use-shader-fx/src/hooks/useBlur/index.ts @@ -1,7 +1,7 @@ import * as THREE from "three"; import { useCallback } from "react"; import { HooksProps, HooksReturn } from "../types"; -import { useDpr } from "../../utils/useDpr"; +import { getDpr } from "../../utils/getDpr"; import { RootState } from "../types"; import { BlurMaterial } from "./BlurMaterial"; import { useFxScene } from "../../utils/useFxScene"; @@ -23,7 +23,7 @@ type BlurConfig = { export const useBlur = ({ size, dpr, - sizeUpdate, + fboAutoSetSize, renderTargetOptions, materialParameters, blurIteration = 5, @@ -32,7 +32,7 @@ export const useBlur = ({ BlurValues, BlurMaterial > => { - const _dpr = useDpr(dpr); + const _dpr = getDpr(dpr); const { scene, material, camera } = useFxScene({ size, @@ -47,7 +47,7 @@ export const useBlur = ({ camera, size, dpr: _dpr.fbo, - sizeUpdate, + fboAutoSetSize, ...renderTargetOptions, }); @@ -89,5 +89,6 @@ export const useBlur = ({ material, scene, camera, + renderTarget, }; }; diff --git a/packages/use-shader-fx/src/hooks/useCoverTexture/index.ts b/packages/use-shader-fx/src/hooks/useCoverTexture/index.ts index bcfe9444..90c6b9f6 100644 --- a/packages/use-shader-fx/src/hooks/useCoverTexture/index.ts +++ b/packages/use-shader-fx/src/hooks/useCoverTexture/index.ts @@ -2,7 +2,7 @@ import * as THREE from "three"; import { useCallback } from "react"; import { useSingleFBO } from "../../utils/useSingleFBO"; import { HooksProps, HooksReturn } from "../types"; -import { useDpr } from "../../utils/useDpr"; +import { getDpr } from "../../utils/getDpr"; import { RootState } from "../types"; import { CoverTextureMaterial } from "./CoverTextureMaterial"; import { useFxScene } from "../../utils/useFxScene"; @@ -19,7 +19,7 @@ export type CoverTextureValues = { export const useCoverTexture = ({ size, dpr, - sizeUpdate, + fboAutoSetSize, renderTargetOptions, materialParameters, ...uniformValues @@ -27,7 +27,7 @@ export const useCoverTexture = ({ CoverTextureValues, CoverTextureMaterial > => { - const _dpr = useDpr(dpr); + const _dpr = getDpr(dpr); const { scene, material, camera } = useFxScene({ size, @@ -42,7 +42,7 @@ export const useCoverTexture = ({ camera, size, dpr: _dpr.fbo, - sizeUpdate, + fboAutoSetSize, ...renderTargetOptions, }); @@ -72,5 +72,6 @@ export const useCoverTexture = ({ material, scene, camera, + renderTarget, }; }; diff --git a/packages/use-shader-fx/src/hooks/useFluid/index.ts b/packages/use-shader-fx/src/hooks/useFluid/index.ts index f4d1fd0f..9b17a43c 100644 --- a/packages/use-shader-fx/src/hooks/useFluid/index.ts +++ b/packages/use-shader-fx/src/hooks/useFluid/index.ts @@ -1,8 +1,8 @@ import * as THREE from "three"; -import { useCallback, useMemo } from "react"; +import { useCallback, useMemo, useState } from "react"; import { UseFboProps, useSingleFBO } from "../../utils/useSingleFBO"; import { HooksProps, HooksReturn } from "../types"; -import { useDpr } from "../../utils/useDpr"; +import { getDpr } from "../../utils/getDpr"; import { RootState } from "../types"; import { useDoubleFBO } from "../../utils/useDoubleFBO"; import { useAdvection } from "./scenes/useAdvection"; @@ -32,30 +32,27 @@ export type FluidValues = { export const useFluid = ({ size, dpr, - sizeUpdate, + fboAutoSetSize, renderTargetOptions, ...values }: HooksProps & FluidValues): HooksReturn => { - const _dpr = useDpr(dpr); + const _dpr = getDpr(dpr); // fbos - const fboProps = useMemo( - () => ({ - dpr: _dpr.fbo, - size, - sizeUpdate, - type: THREE.HalfFloatType, - ...renderTargetOptions, - }), - [size, _dpr.fbo, renderTargetOptions, sizeUpdate] - ); + const fboProps = { + dpr: _dpr.fbo, + size, + fboAutoSetSize, + type: THREE.HalfFloatType, + ...renderTargetOptions, + }; const [velocity_0, updateVelocity_0] = useSingleFBO(fboProps); const [velocity_1, updateVelocity_1] = useSingleFBO(fboProps); const [divergenceFBO, updateDivergenceFBO] = useSingleFBO(fboProps); const [pressureFBO, updatePressureFBO] = useDoubleFBO(fboProps); // scenes - const SceneSize = useMemo(() => ({ size, dpr: _dpr.shader }), [size, _dpr]); + const SceneSize = { size, dpr: _dpr.shader }; const advection = useAdvection( { ...SceneSize, @@ -87,11 +84,6 @@ export const useFluid = ({ updateVelocity_0 ); - const fluidShaders = useMemo( - () => [advection, splat, divergence, poisson, pressure], - [advection, splat, divergence, poisson, pressure] - ); - const setValues = useCallback((newValues: FluidValues) => { // splat.material.force = newValues.force; // bounce の設定 @@ -104,13 +96,21 @@ export const useFluid = ({ (rootState: RootState, newValues?: FluidValues) => { newValues && setValues(newValues); - fluidShaders.forEach((shader) => { + [advection, splat, divergence, poisson, pressure].forEach((shader) => { shader.render(rootState); }); return velocity_0.texture; }, - [setValues, fluidShaders, velocity_0.texture] + [ + setValues, + velocity_0.texture, + advection, + splat, + divergence, + poisson, + pressure, + ] ); return { diff --git a/packages/use-shader-fx/src/hooks/useNoise/index.ts b/packages/use-shader-fx/src/hooks/useNoise/index.ts index d0b50ef1..bdd1c745 100644 --- a/packages/use-shader-fx/src/hooks/useNoise/index.ts +++ b/packages/use-shader-fx/src/hooks/useNoise/index.ts @@ -3,7 +3,7 @@ import { useCallback } from "react"; import { useCamera } from "../../utils/useCamera"; import { useSingleFBO } from "../../utils/useSingleFBO"; import { HooksProps, HooksReturn } from "../types"; -import { useDpr } from "../../utils/useDpr"; +import { getDpr } from "../../utils/getDpr"; import { RootState } from "../types"; import { NoiseMaterial } from "./NoiseMaterial"; import { useFxScene } from "../../utils/useFxScene"; @@ -36,12 +36,12 @@ export type NoiseValues = { export const useNoise = ({ size, dpr, - sizeUpdate, + fboAutoSetSize, renderTargetOptions, materialParameters, ...uniformValues }: HooksProps & NoiseValues): HooksReturn => { - const _dpr = useDpr(dpr); + const _dpr = getDpr(dpr); const { scene, material } = useFxScene({ size, @@ -57,7 +57,7 @@ export const useNoise = ({ camera, size, dpr: _dpr.fbo, - sizeUpdate, + fboAutoSetSize, ...renderTargetOptions, }); @@ -89,5 +89,6 @@ export const useNoise = ({ material, scene, camera, + renderTarget, }; }; diff --git a/packages/use-shader-fx/src/hooks/useRawBlank/index.ts b/packages/use-shader-fx/src/hooks/useRawBlank/index.ts index b93727fc..03c365c5 100644 --- a/packages/use-shader-fx/src/hooks/useRawBlank/index.ts +++ b/packages/use-shader-fx/src/hooks/useRawBlank/index.ts @@ -2,11 +2,11 @@ import * as THREE from "three"; import { useCallback } from "react"; import { useSingleFBO } from "../../utils/useSingleFBO"; import { HooksProps, HooksReturn } from "../types"; -import { useDpr } from "../../utils/useDpr"; +import { getDpr } from "../../utils/getDpr"; import { RootState } from "../types"; import { RawBlankMaterial } from "./RawBlankMaterial"; import { useFxScene } from "../../utils/useFxScene"; -import { ShaderWithUniforms } from "../../materials/FxMaterial"; +import { ShaderWithUniforms } from "../../materials/core/FxMaterial"; export type RawBlankValues = {}; @@ -18,7 +18,7 @@ type RawBlankConfig = ShaderWithUniforms; export const useRawBlank = ({ size, dpr, - sizeUpdate, + fboAutoSetSize, renderTargetOptions, materialParameters, uniforms, @@ -29,7 +29,7 @@ export const useRawBlank = ({ RawBlankValues, RawBlankMaterial > => { - const _dpr = useDpr(dpr); + const _dpr = getDpr(dpr); const { scene, material, camera } = useFxScene({ size, @@ -47,7 +47,7 @@ export const useRawBlank = ({ camera, size, dpr: _dpr.fbo, - sizeUpdate, + fboAutoSetSize, ...renderTargetOptions, }); diff --git a/packages/use-shader-fx/src/misc/useComposer.ts b/packages/use-shader-fx/src/misc/useComposer.ts index 606b889d..a7bb7c23 100644 --- a/packages/use-shader-fx/src/misc/useComposer.ts +++ b/packages/use-shader-fx/src/misc/useComposer.ts @@ -10,6 +10,8 @@ export type FxConfig = { } & HooksProps & BasicFxValues; +const WARN_TEXT = `use-shader-fx: fx and args length mismatch. fx is non-reactive; update by changing the key to reset state.`; + /*=============================================== - Generates a pipeline of fx - hooks are non-reactive @@ -24,9 +26,7 @@ export const useComposer = (...args: FxConfig[]) => { const argsDiff = hooks.length - _args.length; if (argsDiff !== 0) { - console.warn( - `use-shader-fx: fx and args length mismatch. fx is non-reactive; update by changing the key to reset state.` - ); + console.warn(WARN_TEXT); // argsの長さを調整する if (argsDiff < 0) { _args = _args.slice(0, hooks.length); diff --git a/packages/use-shader-fx/src/utils/getDpr.ts b/packages/use-shader-fx/src/utils/getDpr.ts new file mode 100644 index 00000000..20f28eff --- /dev/null +++ b/packages/use-shader-fx/src/utils/getDpr.ts @@ -0,0 +1,13 @@ +import { Dpr } from "../hooks/types"; + +export const getDpr = ( + dpr: Dpr +): { shader: number | false; fbo: number | false } => { + if (typeof dpr === "number") { + return { shader: dpr, fbo: dpr }; + } + return { + shader: dpr.shader ?? false, + fbo: dpr.fbo ?? false, + }; +}; diff --git a/packages/use-shader-fx/src/utils/useDoubleFBO.ts b/packages/use-shader-fx/src/utils/useDoubleFBO.ts index 4481aadb..a5df25c1 100644 --- a/packages/use-shader-fx/src/utils/useDoubleFBO.ts +++ b/packages/use-shader-fx/src/utils/useDoubleFBO.ts @@ -44,7 +44,7 @@ export const useDoubleFBO = (props: UseFboProps): UseDoubleFBOReturn => { camera, size, dpr = false, - sizeUpdate = false, + fboAutoSetSize = false, depth = false, ...renderTargetOptions } = props; @@ -85,7 +85,7 @@ export const useDoubleFBO = (props: UseFboProps): UseDoubleFBOReturn => { }; }); - if (sizeUpdate) { + if (fboAutoSetSize) { renderTarget.read?.setSize(resolution.x, resolution.y); renderTarget.write?.setSize(resolution.x, resolution.y); } diff --git a/packages/use-shader-fx/src/utils/useDpr.ts b/packages/use-shader-fx/src/utils/useDpr.ts deleted file mode 100644 index f2e3493f..00000000 --- a/packages/use-shader-fx/src/utils/useDpr.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { useMemo } from "react"; -import { Dpr } from "../hooks/types"; - -export const useDpr = ( - dpr: Dpr -): { shader: number | false; fbo: number | false } => { - const _dpr = useMemo(() => { - if (typeof dpr === "number") { - return { shader: dpr, fbo: dpr }; - } - return { - shader: dpr.shader ?? false, - fbo: dpr.fbo ?? false, - }; - }, [dpr]); - - return _dpr; -}; diff --git a/packages/use-shader-fx/src/utils/useObject3D.ts b/packages/use-shader-fx/src/utils/useObject3D.ts index 0a5abccc..46fbdd40 100644 --- a/packages/use-shader-fx/src/utils/useObject3D.ts +++ b/packages/use-shader-fx/src/utils/useObject3D.ts @@ -1,5 +1,5 @@ import * as THREE from "three"; -import { useEffect, useMemo, useState } from "react"; +import { useEffect, useState } from "react"; type Object3DConstructor = new ( geometry: THREE.BufferGeometry, @@ -15,13 +15,10 @@ export const useObject3D = ( material: M, Proto: Object3DConstructor ) => { - const object3D = useMemo(() => { - const obj = new Proto(geometry, material); - scene && scene.add(obj); - return obj; - }, [scene, geometry, material, Proto]); + const [object3D] = useState(() => new Proto(geometry, material)); useEffect(() => { + scene && scene.add(object3D); return () => { scene && scene.remove(object3D); geometry.dispose(); diff --git a/packages/use-shader-fx/src/utils/useSingleFBO.ts b/packages/use-shader-fx/src/utils/useSingleFBO.ts index fda48909..ccd7a5d9 100644 --- a/packages/use-shader-fx/src/utils/useSingleFBO.ts +++ b/packages/use-shader-fx/src/utils/useSingleFBO.ts @@ -14,7 +14,7 @@ export type UseFboProps = { /** If dpr is set, dpr will be multiplied, default : `false` */ dpr?: number | false; /** Whether to resize when resizing occurs. If isDpr is true, set FBO to setSize even if dpr is changed, default : `false` */ - sizeUpdate?: boolean; + fboAutoSetSize?: boolean; /** If set, the scene depth will be rendered into buffer.depthTexture. default : `false` */ depth?: boolean; } & THREE.RenderTargetOptions; @@ -60,7 +60,7 @@ type UseSingleFBOReturn = [THREE.WebGLRenderTarget, SingleFBOUpdateFunction]; /** * @param dpr If dpr is set, dpr will be multiplied, default:false - * @param sizeUpdate Whether to resize when resizing occurs. If isDpr is true, set FBO to setSize even if dpr is changed, default:false + * @param fboAutoSetSize Whether to resize when resizing occurs. If isDpr is true, set FBO to setSize even if dpr is changed, default:false * @param depthBuffer Unlike the default in three.js, the default is `false`. * @returns [THREE.WebGLRenderTarget , updateFBO] -Receives the RenderTarget as the first argument and the update function as the second argument. */ @@ -70,7 +70,7 @@ export const useSingleFBO = (props: UseFboProps): UseSingleFBOReturn => { camera, size, dpr = false, - sizeUpdate = false, + fboAutoSetSize = false, depth = false, ...renderTargetOptions } = props; @@ -92,7 +92,7 @@ export const useSingleFBO = (props: UseFboProps): UseSingleFBOReturn => { return target; }); - if (sizeUpdate) { + if (fboAutoSetSize) { renderTarget.setSize(resolution.x, resolution.y); } diff --git a/todo b/todo index ea454e38..e69de29b 100644 --- a/todo +++ b/todo @@ -1,18 +0,0 @@ -- useFxScene - - TODO* uniformValuesとmaterialParametersをreactiveにする - - Q * ここ、変更時のみにしないと一瞬ズレるかな? - - ここ(初期化時のuniformValues)nonReactiveでいいか(useComposeもnon reactiveだし。) -- useComposer - - non reactiveにすることにした! - - reactiveに処理したい場合は、keyを渡せばいい - - このケース、webglooでしか使わないよね - -- つまり、HooksPropsはsizeとdpr以外はnon reactiveになる。 - - ※ fboのsizeはsizeUpdateをtrueにしないと、nonReactive. - - ※ shaderのsizeは常にreactive - -TODO -- hooksReturnにfbo/renderTarget追加する -- hooksPropsのreactiveとnon-reactiveについてコメント追加 -- rename sizeUpdate to autoFBO/rendertarget SetSizeとか? -- useDPR、メモ化する必要ないかも \ No newline at end of file From 90f09cf88f54b51bdf8737d31385acbff0bd228d Mon Sep 17 00:00:00 2001 From: takuma-hmng8 Date: Fri, 11 Oct 2024 13:21:42 +0900 Subject: [PATCH 16/60] update:defineUniformAccessors --- app/v2_fxMaterials/Playground.tsx | 39 +++++++++++++++++++ app/v2_fxMaterials/page.tsx | 32 +++++++++++++++ app/v2_impl/Playground.tsx | 18 ++++----- .../useCoverTexture/CoverTextureMaterial.ts | 2 +- .../src/hooks/useNoise/NoiseMaterial.ts | 9 ++++- .../src/hooks/useRawBlank/RawBlankMaterial.ts | 2 + packages/use-shader-fx/src/index.js | 2 + .../src/materials/core/FxBasicFxMaterial.ts | 2 + .../src/materials/core/FxMaterial.ts | 18 +++++++-- .../materials/impl/FxBasicFxMaterialImpl.ts | 4 +- .../src/materials/impl/FxMaterialImpl.ts | 2 +- todo | 5 +++ 12 files changed, 115 insertions(+), 20 deletions(-) create mode 100644 app/v2_fxMaterials/Playground.tsx create mode 100644 app/v2_fxMaterials/page.tsx diff --git a/app/v2_fxMaterials/Playground.tsx b/app/v2_fxMaterials/Playground.tsx new file mode 100644 index 00000000..c472f752 --- /dev/null +++ b/app/v2_fxMaterials/Playground.tsx @@ -0,0 +1,39 @@ +"use client"; + +import * as THREE from "three"; +import { useRef, useState } from "react"; +import { useFrame, useThree, extend, createPortal } from "@react-three/fiber"; +import { + NoiseMaterial, + NoiseValues, + FxMaterialImplValues, + FxBasicFxMaterialImplValues, +} from "@/packages/use-shader-fx/src"; + +extend({ NoiseMaterial }); +export const Playground = () => { + const ref = useRef(); + useFrame(({ clock }) => { + ref.current.tick = clock.getElapsedTime(); + }); + return ( + <> + + + + + + ); +}; + +declare global { + namespace JSX { + interface IntrinsicElements { + noiseMaterial: NoiseValues & JSX.IntrinsicElements["shaderMaterial"]; + fxMaterialImpl: FxMaterialImplValues & + JSX.IntrinsicElements["shaderMaterial"]; + fxBasicFxMaterialImpl: FxBasicFxMaterialImplValues & + JSX.IntrinsicElements["shaderMaterial"]; + } + } +} diff --git a/app/v2_fxMaterials/page.tsx b/app/v2_fxMaterials/page.tsx new file mode 100644 index 00000000..cc9a6d74 --- /dev/null +++ b/app/v2_fxMaterials/page.tsx @@ -0,0 +1,32 @@ +import { ShaderFx } from "../ShaderFx"; +import { Playground } from "./Playground"; +import Image from "next/image"; + +export default function Page() { + return ( +
    +
    + +
    + + + +
    + ); +} diff --git a/app/v2_impl/Playground.tsx b/app/v2_impl/Playground.tsx index 088647b8..4d5bbc88 100644 --- a/app/v2_impl/Playground.tsx +++ b/app/v2_impl/Playground.tsx @@ -53,13 +53,13 @@ export const Playground = () => { // src: renderTarget.texture, // }); - const noise = useNoise({ - size, - dpr: 0.1, - fboAutoSetSize: true, - scale: 0.2, - noiseOctaves: 2, - }); + // const noise = useNoise({ + // size, + // dpr: 0.1, + // fboAutoSetSize: true, + // scale: 0.2, + // noiseOctaves: 2, + // }); const fluid = useFluid({ size, @@ -74,8 +74,6 @@ export const Playground = () => { }); const ref = useRef(); - useFrame(() => {}); - // console.log(ref.current.updateResolution); return ( <> @@ -85,8 +83,6 @@ export const Playground = () => { key={FxMaterialImpl.key} ref={ref} src={fluid.texture} - // mixSrc={noise.texture} - // mixSrcUvFactor={0.6} /> {createPortal( diff --git a/packages/use-shader-fx/src/hooks/useCoverTexture/CoverTextureMaterial.ts b/packages/use-shader-fx/src/hooks/useCoverTexture/CoverTextureMaterial.ts index c3561991..7aa7dc17 100644 --- a/packages/use-shader-fx/src/hooks/useCoverTexture/CoverTextureMaterial.ts +++ b/packages/use-shader-fx/src/hooks/useCoverTexture/CoverTextureMaterial.ts @@ -20,7 +20,7 @@ export class CoverTextureMaterial extends FxBasicFxMaterial { constructor({ uniformValues, materialParameters = {}, - }: FxMaterialProps) { + }: FxMaterialProps = {}) { super(); this.type = CoverTextureMaterial.type; diff --git a/packages/use-shader-fx/src/hooks/useNoise/NoiseMaterial.ts b/packages/use-shader-fx/src/hooks/useNoise/NoiseMaterial.ts index 9ea7d4ff..59399839 100644 --- a/packages/use-shader-fx/src/hooks/useNoise/NoiseMaterial.ts +++ b/packages/use-shader-fx/src/hooks/useNoise/NoiseMaterial.ts @@ -16,13 +16,18 @@ type NoiseUniforms = { } & BasicFxUniforms; export class NoiseMaterial extends FxBasicFxMaterial { + public static readonly key: string = THREE.MathUtils.generateUUID(); + static get type() { return "NoiseMaterial"; } uniforms!: NoiseUniforms; - constructor({ uniformValues, materialParameters = {} }: FxMaterialProps) { + constructor({ + uniformValues, + materialParameters = {}, + }: FxMaterialProps = {}) { super(); this.type = NoiseMaterial.type; @@ -45,5 +50,7 @@ export class NoiseMaterial extends FxBasicFxMaterial { this.setValues(materialParameters); this.setupBasicFxShaders(noiseVertex, noiseFragment); + + this.defineUniformAccessors(); } } diff --git a/packages/use-shader-fx/src/hooks/useRawBlank/RawBlankMaterial.ts b/packages/use-shader-fx/src/hooks/useRawBlank/RawBlankMaterial.ts index 834baac7..90f6aa9e 100644 --- a/packages/use-shader-fx/src/hooks/useRawBlank/RawBlankMaterial.ts +++ b/packages/use-shader-fx/src/hooks/useRawBlank/RawBlankMaterial.ts @@ -7,5 +7,7 @@ export class RawBlankMaterial extends FxMaterial { constructor(props: FxMaterialProps) { super(props); this.type = RawBlankMaterial.type; + + this.defineUniformAccessors(); } } diff --git a/packages/use-shader-fx/src/index.js b/packages/use-shader-fx/src/index.js index 4676f6b3..4922438a 100644 --- a/packages/use-shader-fx/src/index.js +++ b/packages/use-shader-fx/src/index.js @@ -2,6 +2,8 @@ FXs ===============================================*/ export * from "./hooks/useNoise"; +export * from "./hooks/useNoise/NoiseMaterial"; + export * from "./hooks/useFluid"; export * from "./hooks/useCoverTexture"; export * from "./hooks/useRawBlank"; diff --git a/packages/use-shader-fx/src/materials/core/FxBasicFxMaterial.ts b/packages/use-shader-fx/src/materials/core/FxBasicFxMaterial.ts index 5a3bad8b..32d1c4c8 100644 --- a/packages/use-shader-fx/src/materials/core/FxBasicFxMaterial.ts +++ b/packages/use-shader-fx/src/materials/core/FxBasicFxMaterial.ts @@ -9,6 +9,8 @@ import { import { mergeShaderLib } from "../../libs/shaders/mergeShaderLib"; export class FxBasicFxMaterial extends FxMaterial { + public static readonly key: string = THREE.MathUtils.generateUUID(); + basicFxFlag: BasicFxFlag; uniforms!: BasicFxUniforms; diff --git a/packages/use-shader-fx/src/materials/core/FxMaterial.ts b/packages/use-shader-fx/src/materials/core/FxMaterial.ts index 20bf1f86..ceebbd6e 100644 --- a/packages/use-shader-fx/src/materials/core/FxMaterial.ts +++ b/packages/use-shader-fx/src/materials/core/FxMaterial.ts @@ -22,6 +22,8 @@ export type FxMaterialProps = { } & ShaderWithUniforms; export class FxMaterial extends THREE.ShaderMaterial { + public static readonly key: string = THREE.MathUtils.generateUUID(); + constructor({ uniformValues, materialParameters = {}, @@ -95,17 +97,25 @@ export class FxMaterial extends THREE.ShaderMaterial { } } - // Create getter/setters + /** + * Create getter/setters, This method should be called in the implementing class + */ defineUniformAccessors(onSet?: () => void) { const entries = Object.entries(this.uniforms); - entries.forEach(([name]) => + + entries.forEach(([name]) => { + if (this.hasOwnProperty(name)) { + console.warn(`use-shader-fx: ${name} is already defined.`); + return; + } + Object.defineProperty(this, name, { get: () => this.uniforms[name].value, set: (v) => { this.uniforms[name].value = v; onSet?.(); }, - }) - ); + }); + }); } } diff --git a/packages/use-shader-fx/src/materials/impl/FxBasicFxMaterialImpl.ts b/packages/use-shader-fx/src/materials/impl/FxBasicFxMaterialImpl.ts index 7ffbb4af..bb16b811 100644 --- a/packages/use-shader-fx/src/materials/impl/FxBasicFxMaterialImpl.ts +++ b/packages/use-shader-fx/src/materials/impl/FxBasicFxMaterialImpl.ts @@ -41,7 +41,7 @@ export const createFxBasicFxMaterialImpl = ({ fragmentShader = fragment, }: ShaderWithUniforms = {}) => { class FxBasicFxMaterialImpl extends FxBasicFxMaterial { - public key: string = THREE.MathUtils.generateUUID(); + public static readonly key: string = THREE.MathUtils.generateUUID(); static get type() { return "FxBasicFxMaterialImpl"; @@ -71,7 +71,7 @@ export const createFxBasicFxMaterialImpl = ({ this.setUniformValues(props?.uniformValues); this.setValues(props?.materialParameters || {}); - // to update basicFx flag + // set callback `onSet` to update basicFx flag this.defineUniformAccessors(this.updateBasicFx.bind(this)); } } diff --git a/packages/use-shader-fx/src/materials/impl/FxMaterialImpl.ts b/packages/use-shader-fx/src/materials/impl/FxMaterialImpl.ts index 05465156..41ad2860 100644 --- a/packages/use-shader-fx/src/materials/impl/FxMaterialImpl.ts +++ b/packages/use-shader-fx/src/materials/impl/FxMaterialImpl.ts @@ -35,7 +35,7 @@ export const createFxMaterialImpl = ({ fragmentShader = fragment, }: ShaderWithUniforms = {}) => { class FxMaterialImpl extends FxMaterial { - public key: string = THREE.MathUtils.generateUUID(); + public static readonly key: string = THREE.MathUtils.generateUUID(); static get type() { return "FxMaterialImpl"; diff --git a/todo b/todo index e69de29b..b58fa0e2 100644 --- a/todo +++ b/todo @@ -0,0 +1,5 @@ +- fxのmaterialを/material/impl/xxxに移動する + - clothとかwobble3Dとか、materialのみのnodeも今後できそうなので。 +- すべてのfxのmaterialをexportする +- /hooksにindex.tsつくってexportまとめたほうが良さそうね。 + - useComposerのFxConfigもここで定義する \ No newline at end of file From 04d7002cd2c90768066a1e80209ca6744f722bbc Mon Sep 17 00:00:00 2001 From: takuma-hmng8 Date: Sat, 12 Oct 2024 17:43:17 +0900 Subject: [PATCH 17/60] update --- app/v2_fxMaterials/Playground.tsx | 3 +- app/v2_impl/Playground.tsx | 28 ++++++---- app/v2_impl/page.tsx | 13 +++-- packages/use-shader-fx/src/hooks/index.ts | 14 +++++ .../use-shader-fx/src/hooks/useBlur/index.ts | 9 +--- .../src/hooks/useCoverTexture/index.ts | 9 +--- .../use-shader-fx/src/hooks/useFluid/index.ts | 8 +-- .../src/hooks/useFluid/scenes/useAdvection.ts | 2 +- .../hooks/useFluid/scenes/useDivergence.ts | 2 +- .../src/hooks/useFluid/scenes/usePoisson.ts | 2 +- .../src/hooks/useFluid/scenes/usePressure.ts | 2 +- .../src/hooks/useFluid/scenes/useSplat.ts | 4 +- .../use-shader-fx/src/hooks/useNoise/index.ts | 32 +---------- .../src/hooks/useRawBlank/index.ts | 6 +-- packages/use-shader-fx/src/index.js | 25 ++------- .../src/materials/core/BasicFxLib.ts | 35 ++++++------ .../src/materials/core/FxBasicFxMaterial.ts | 46 +++++++++++----- .../src/materials/core/FxMaterial.ts | 12 +++-- .../materials/impl/FxBasicFxMaterialImpl.ts | 53 +++++++++---------- .../src/materials/impl/FxMaterialImpl.ts | 46 +++++++--------- .../impl/blur}/BlurMaterial.ts | 37 +++++++------ .../impl/blur}/blur.glsl.ts | 2 +- .../impl/cover}/CoverTextureMaterial.ts | 38 +++++++------ .../impl/cover}/coverTexture.glsl.ts | 2 +- .../impl/fluid}/AdvectionMaterial.ts | 28 ++++------ .../impl/fluid}/DivergenceMaterial.ts | 27 ++++------ .../impl/fluid}/PoissonMaterial.ts | 27 ++++------ .../impl/fluid}/PressureMaterial.ts | 27 ++++------ .../impl/fluid}/SplatMaterial.ts | 31 +++++------ .../src/materials/impl/fluid/index.js | 7 +++ .../impl/fluid}/shaders/advection.frag | 0 .../impl/fluid}/shaders/divergence.frag | 0 .../impl/fluid}/shaders/poisson.frag | 0 .../impl/fluid}/shaders/pressure.frag | 0 .../impl/fluid}/shaders/splat.frag | 0 .../impl/fluid}/shaders/vertex.ts | 0 .../impl/noise}/NoiseMaterial.ts | 47 +++++++++------- .../impl/noise}/noise.glsl.ts | 2 +- .../impl/rawBlank}/RawBlankMaterial.ts | 6 +-- packages/use-shader-fx/src/materials/index.js | 8 +++ packages/use-shader-fx/src/misc/index.js | 4 ++ .../use-shader-fx/src/misc/useComposer.ts | 6 +-- todo | 5 -- 43 files changed, 311 insertions(+), 344 deletions(-) create mode 100644 packages/use-shader-fx/src/hooks/index.ts rename packages/use-shader-fx/src/{hooks/useBlur => materials/impl/blur}/BlurMaterial.ts (51%) rename packages/use-shader-fx/src/{hooks/useBlur => materials/impl/blur}/blur.glsl.ts (92%) rename packages/use-shader-fx/src/{hooks/useCoverTexture => materials/impl/cover}/CoverTextureMaterial.ts (54%) rename packages/use-shader-fx/src/{hooks/useCoverTexture => materials/impl/cover}/coverTexture.glsl.ts (92%) rename packages/use-shader-fx/src/{hooks/useFluid/materials => materials/impl/fluid}/AdvectionMaterial.ts (66%) rename packages/use-shader-fx/src/{hooks/useFluid/materials => materials/impl/fluid}/DivergenceMaterial.ts (69%) rename packages/use-shader-fx/src/{hooks/useFluid/materials => materials/impl/fluid}/PoissonMaterial.ts (72%) rename packages/use-shader-fx/src/{hooks/useFluid/materials => materials/impl/fluid}/PressureMaterial.ts (71%) rename packages/use-shader-fx/src/{hooks/useFluid/materials => materials/impl/fluid}/SplatMaterial.ts (69%) create mode 100644 packages/use-shader-fx/src/materials/impl/fluid/index.js rename packages/use-shader-fx/src/{hooks/useFluid/materials => materials/impl/fluid}/shaders/advection.frag (100%) rename packages/use-shader-fx/src/{hooks/useFluid/materials => materials/impl/fluid}/shaders/divergence.frag (100%) rename packages/use-shader-fx/src/{hooks/useFluid/materials => materials/impl/fluid}/shaders/poisson.frag (100%) rename packages/use-shader-fx/src/{hooks/useFluid/materials => materials/impl/fluid}/shaders/pressure.frag (100%) rename packages/use-shader-fx/src/{hooks/useFluid/materials => materials/impl/fluid}/shaders/splat.frag (100%) rename packages/use-shader-fx/src/{hooks/useFluid/materials => materials/impl/fluid}/shaders/vertex.ts (100%) rename packages/use-shader-fx/src/{hooks/useNoise => materials/impl/noise}/NoiseMaterial.ts (52%) rename packages/use-shader-fx/src/{hooks/useNoise => materials/impl/noise}/noise.glsl.ts (97%) rename packages/use-shader-fx/src/{hooks/useRawBlank => materials/impl/rawBlank}/RawBlankMaterial.ts (65%) create mode 100644 packages/use-shader-fx/src/materials/index.js create mode 100644 packages/use-shader-fx/src/misc/index.js diff --git a/app/v2_fxMaterials/Playground.tsx b/app/v2_fxMaterials/Playground.tsx index c472f752..935d599f 100644 --- a/app/v2_fxMaterials/Playground.tsx +++ b/app/v2_fxMaterials/Playground.tsx @@ -11,6 +11,7 @@ import { } from "@/packages/use-shader-fx/src"; extend({ NoiseMaterial }); + export const Playground = () => { const ref = useRef(); useFrame(({ clock }) => { @@ -20,7 +21,7 @@ export const Playground = () => { <> - + ); diff --git a/app/v2_impl/Playground.tsx b/app/v2_impl/Playground.tsx index 4d5bbc88..6546fc4b 100644 --- a/app/v2_impl/Playground.tsx +++ b/app/v2_impl/Playground.tsx @@ -5,6 +5,7 @@ import { useRef, useState } from "react"; import { useFrame, useThree, extend, createPortal } from "@react-three/fiber"; import { useNoise, + NoiseValues, useBlur, useSingleFBO, createFxMaterialImpl, @@ -53,22 +54,29 @@ export const Playground = () => { // src: renderTarget.texture, // }); - // const noise = useNoise({ - // size, - // dpr: 0.1, - // fboAutoSetSize: true, - // scale: 0.2, - // noiseOctaves: 2, - // }); - const fluid = useFluid({ size, dpr: 0.25, }); + const noise = useNoise({ + size, + dpr: 0.3, + fboAutoSetSize: true, + scale: 0.4, + noiseOctaves: 2, + // mixSrc: fluid.texture, + mixSrcColorFactor: 0.5, + mixSrcUvFactor: 0.6, + }); + + noise.setValues({ + mixSrc: fluid.texture, + }); + useFrame((state) => { updateRenderTarget({ gl: state.gl }); - // noise.render(state); + noise.render(state); // blur.render(state); fluid.render(state); }); @@ -82,7 +90,7 @@ export const Playground = () => { {createPortal( diff --git a/app/v2_impl/page.tsx b/app/v2_impl/page.tsx index cc9a6d74..51d1d029 100644 --- a/app/v2_impl/page.tsx +++ b/app/v2_impl/page.tsx @@ -13,8 +13,8 @@ export default function Page() { }}>
    - +
    diff --git a/packages/use-shader-fx/src/hooks/index.ts b/packages/use-shader-fx/src/hooks/index.ts new file mode 100644 index 00000000..ea078dc3 --- /dev/null +++ b/packages/use-shader-fx/src/hooks/index.ts @@ -0,0 +1,14 @@ +import { useBlur } from "./useBlur"; +import { useCoverTexture } from "./useCoverTexture"; +import { useFluid } from "./useFluid"; +import { useNoise } from "./useNoise"; +import { useRawBlank } from "./useRawBlank"; + +export type FxTypes = + | typeof useBlur + | typeof useCoverTexture + | typeof useFluid + | typeof useNoise + | typeof useRawBlank; + +export { useBlur, useCoverTexture, useFluid, useNoise, useRawBlank }; diff --git a/packages/use-shader-fx/src/hooks/useBlur/index.ts b/packages/use-shader-fx/src/hooks/useBlur/index.ts index af77870d..75869d5a 100644 --- a/packages/use-shader-fx/src/hooks/useBlur/index.ts +++ b/packages/use-shader-fx/src/hooks/useBlur/index.ts @@ -1,18 +1,11 @@ -import * as THREE from "three"; import { useCallback } from "react"; import { HooksProps, HooksReturn } from "../types"; import { getDpr } from "../../utils/getDpr"; import { RootState } from "../types"; -import { BlurMaterial } from "./BlurMaterial"; +import { BlurMaterial, BlurValues } from "../../materials"; import { useFxScene } from "../../utils/useFxScene"; -import { BasicFxValues } from "../../materials/core/BasicFxLib"; import { useDoubleFBO } from "../../utils/useDoubleFBO"; -export type BlurValues = { - src?: THREE.Texture | null; - blurSize?: number; -} & BasicFxValues; - type BlurConfig = { blurIteration?: number; }; diff --git a/packages/use-shader-fx/src/hooks/useCoverTexture/index.ts b/packages/use-shader-fx/src/hooks/useCoverTexture/index.ts index 90c6b9f6..9de3e990 100644 --- a/packages/use-shader-fx/src/hooks/useCoverTexture/index.ts +++ b/packages/use-shader-fx/src/hooks/useCoverTexture/index.ts @@ -1,17 +1,10 @@ -import * as THREE from "three"; import { useCallback } from "react"; import { useSingleFBO } from "../../utils/useSingleFBO"; import { HooksProps, HooksReturn } from "../types"; import { getDpr } from "../../utils/getDpr"; import { RootState } from "../types"; -import { CoverTextureMaterial } from "./CoverTextureMaterial"; +import { CoverTextureMaterial, CoverTextureValues } from "../../materials"; import { useFxScene } from "../../utils/useFxScene"; -import { BasicFxValues } from "../../materials/core/BasicFxLib"; - -export type CoverTextureValues = { - src?: THREE.Texture; - textureResolution?: THREE.Vector2; -} & BasicFxValues; /** * @link https://github.com/FunTechInc/use-shader-fx?tab=readme-ov-file#usage diff --git a/packages/use-shader-fx/src/hooks/useFluid/index.ts b/packages/use-shader-fx/src/hooks/useFluid/index.ts index 9b17a43c..22b12cac 100644 --- a/packages/use-shader-fx/src/hooks/useFluid/index.ts +++ b/packages/use-shader-fx/src/hooks/useFluid/index.ts @@ -1,6 +1,6 @@ import * as THREE from "three"; -import { useCallback, useMemo, useState } from "react"; -import { UseFboProps, useSingleFBO } from "../../utils/useSingleFBO"; +import { useCallback } from "react"; +import { useSingleFBO } from "../../utils/useSingleFBO"; import { HooksProps, HooksReturn } from "../types"; import { getDpr } from "../../utils/getDpr"; import { RootState } from "../types"; @@ -11,8 +11,6 @@ import { useDivergence } from "./scenes/useDivergence"; import { usePoisson } from "./scenes/usePoisson"; import { usePressure } from "./scenes/usePressure"; -export const DeltaTime = 0.015; - export type FluidValues = { /*=============================================== TODO * @@ -26,8 +24,6 @@ export type FluidValues = { /** * @link https://github.com/FunTechInc/use-shader-fx?tab=readme-ov-file#usage - * - * It is a basic value noise with `fbm` and `domain warping` */ export const useFluid = ({ size, diff --git a/packages/use-shader-fx/src/hooks/useFluid/scenes/useAdvection.ts b/packages/use-shader-fx/src/hooks/useFluid/scenes/useAdvection.ts index 09cb0bbc..514036ed 100644 --- a/packages/use-shader-fx/src/hooks/useFluid/scenes/useAdvection.ts +++ b/packages/use-shader-fx/src/hooks/useFluid/scenes/useAdvection.ts @@ -1,7 +1,7 @@ import * as THREE from "three"; import { useCallback } from "react"; import { RootState, Size } from "../../types"; -import { AdvectionMaterial } from "../materials/AdvectionMaterial"; +import { AdvectionMaterial } from "../../../materials"; import { SingleFBOUpdateFunction } from "../../../utils/useSingleFBO"; import { useFxScene } from "../../../utils/useFxScene"; diff --git a/packages/use-shader-fx/src/hooks/useFluid/scenes/useDivergence.ts b/packages/use-shader-fx/src/hooks/useFluid/scenes/useDivergence.ts index dca95c45..2ccf61ec 100644 --- a/packages/use-shader-fx/src/hooks/useFluid/scenes/useDivergence.ts +++ b/packages/use-shader-fx/src/hooks/useFluid/scenes/useDivergence.ts @@ -2,7 +2,7 @@ import * as THREE from "three"; import { useCallback } from "react"; import { RootState, Size } from "../../types"; import { SingleFBOUpdateFunction } from "../../../utils/useSingleFBO"; -import { DivergenceMaterial } from "../materials/DivergenceMaterial"; +import { DivergenceMaterial } from "../../../materials"; import { useFxScene } from "../../../utils/useFxScene"; export const useDivergence = ( diff --git a/packages/use-shader-fx/src/hooks/useFluid/scenes/usePoisson.ts b/packages/use-shader-fx/src/hooks/useFluid/scenes/usePoisson.ts index 1d413bf1..dbb84359 100644 --- a/packages/use-shader-fx/src/hooks/useFluid/scenes/usePoisson.ts +++ b/packages/use-shader-fx/src/hooks/useFluid/scenes/usePoisson.ts @@ -2,7 +2,7 @@ import * as THREE from "three"; import { useCallback } from "react"; import { RootState, Size } from "../../types"; import { SingleFBOUpdateFunction } from "../../../utils/useSingleFBO"; -import { PoissonMaterial } from "../materials/PoissonMaterial"; +import { PoissonMaterial } from "../../../materials"; import { useFxScene } from "../../../utils/useFxScene"; export const usePoisson = ( diff --git a/packages/use-shader-fx/src/hooks/useFluid/scenes/usePressure.ts b/packages/use-shader-fx/src/hooks/useFluid/scenes/usePressure.ts index 74667a23..673463f5 100644 --- a/packages/use-shader-fx/src/hooks/useFluid/scenes/usePressure.ts +++ b/packages/use-shader-fx/src/hooks/useFluid/scenes/usePressure.ts @@ -2,7 +2,7 @@ import * as THREE from "three"; import { useCallback } from "react"; import { RootState, Size } from "../../types"; import { SingleFBOUpdateFunction } from "../../../utils/useSingleFBO"; -import { PressureMaterial } from "../materials/PressureMaterial"; +import { PressureMaterial } from "../../../materials"; import { useFxScene } from "../../../utils/useFxScene"; export const usePressure = ( diff --git a/packages/use-shader-fx/src/hooks/useFluid/scenes/useSplat.ts b/packages/use-shader-fx/src/hooks/useFluid/scenes/useSplat.ts index 6f79e62f..aae70673 100644 --- a/packages/use-shader-fx/src/hooks/useFluid/scenes/useSplat.ts +++ b/packages/use-shader-fx/src/hooks/useFluid/scenes/useSplat.ts @@ -1,7 +1,7 @@ import { useCallback } from "react"; import { RootState, Size } from "../../types"; import { SingleFBOUpdateFunction } from "../../../utils/useSingleFBO"; -import { SplatMaterial } from "../materials/SplatMaterial"; +import { SplatMaterial } from "../../../materials"; import { usePointerTracker } from "../../../misc/usePointerTracker"; import { useFxScene } from "../../../utils/useFxScene"; @@ -34,7 +34,7 @@ export const useSplat = ( material.uniforms.center.value.copy(currentPointer); material.uniforms.force.value.copy( - diffPointer.multiplyScalar(material.force) + diffPointer.multiplyScalar(material.forceBias) ); updateRenderTarget({ gl, scene, camera, clear: false }); diff --git a/packages/use-shader-fx/src/hooks/useNoise/index.ts b/packages/use-shader-fx/src/hooks/useNoise/index.ts index bdd1c745..3b501df7 100644 --- a/packages/use-shader-fx/src/hooks/useNoise/index.ts +++ b/packages/use-shader-fx/src/hooks/useNoise/index.ts @@ -1,37 +1,13 @@ -import * as THREE from "three"; import { useCallback } from "react"; -import { useCamera } from "../../utils/useCamera"; import { useSingleFBO } from "../../utils/useSingleFBO"; import { HooksProps, HooksReturn } from "../types"; import { getDpr } from "../../utils/getDpr"; import { RootState } from "../types"; -import { NoiseMaterial } from "./NoiseMaterial"; +import { NoiseMaterial, NoiseValues } from "../../materials"; import { useFxScene } from "../../utils/useFxScene"; -import { BasicFxValues } from "../../materials/core/BasicFxLib"; - -export type NoiseValues = { - /** noise scale , default : `0.004` */ - scale?: number; - /** time factor default : `0.3` */ - timeStrength?: number; - /** noiseOctaves, affects performance default : `2` */ - noiseOctaves?: number; - /** fbmOctaves, affects performance default : `2` */ - fbmOctaves?: number; - /** domain warping octaves , affects performance default : `2` */ - warpOctaves?: number; - /** direction of domain warping , default : `(2.0,2,0)` */ - warpDirection?: THREE.Vector2; - /** strength of domain warping , default : `8.0` */ - warpStrength?: number; - /** useBeatを渡せば、リズムを変えられる。 */ - tick?: number; -} & BasicFxValues; /** * @link https://github.com/FunTechInc/use-shader-fx?tab=readme-ov-file#usage - * - * It is a basic value noise with `fbm` and `domain warping` */ export const useNoise = ({ size, @@ -43,7 +19,7 @@ export const useNoise = ({ }: HooksProps & NoiseValues): HooksReturn => { const _dpr = getDpr(dpr); - const { scene, material } = useFxScene({ + const { scene, material, camera } = useFxScene({ size, dpr: _dpr.shader, material: NoiseMaterial, @@ -51,7 +27,6 @@ export const useNoise = ({ materialParameters, }); - const camera = useCamera(size); const [renderTarget, updateRenderTarget] = useSingleFBO({ scene, camera, @@ -74,9 +49,6 @@ export const useNoise = ({ newValues && setValues(newValues); material.uniforms.tick.value = newValues?.tick || clock.getElapsedTime(); - - material.updateBasicFx(); - return updateRenderTarget({ gl }); }, [setValues, updateRenderTarget, material] diff --git a/packages/use-shader-fx/src/hooks/useRawBlank/index.ts b/packages/use-shader-fx/src/hooks/useRawBlank/index.ts index 03c365c5..ca3a04e1 100644 --- a/packages/use-shader-fx/src/hooks/useRawBlank/index.ts +++ b/packages/use-shader-fx/src/hooks/useRawBlank/index.ts @@ -1,15 +1,12 @@ -import * as THREE from "three"; import { useCallback } from "react"; import { useSingleFBO } from "../../utils/useSingleFBO"; import { HooksProps, HooksReturn } from "../types"; import { getDpr } from "../../utils/getDpr"; import { RootState } from "../types"; -import { RawBlankMaterial } from "./RawBlankMaterial"; +import { RawBlankMaterial, RawBlankValues } from "../../materials"; import { useFxScene } from "../../utils/useFxScene"; import { ShaderWithUniforms } from "../../materials/core/FxMaterial"; -export type RawBlankValues = {}; - type RawBlankConfig = ShaderWithUniforms; /** @@ -74,5 +71,6 @@ export const useRawBlank = ({ material, scene, camera, + renderTarget, }; }; diff --git a/packages/use-shader-fx/src/index.js b/packages/use-shader-fx/src/index.js index 4922438a..c81e1932 100644 --- a/packages/use-shader-fx/src/index.js +++ b/packages/use-shader-fx/src/index.js @@ -1,27 +1,8 @@ -/*=============================================== -FXs -===============================================*/ -export * from "./hooks/useNoise"; -export * from "./hooks/useNoise/NoiseMaterial"; +export * from "./hooks"; -export * from "./hooks/useFluid"; -export * from "./hooks/useCoverTexture"; -export * from "./hooks/useRawBlank"; -export * from "./hooks/useBlur"; +export * from "./materials"; -/*=============================================== -materials -===============================================*/ -export * from "./materials/impl/FxMaterialImpl"; -export * from "./materials/impl/FxBasicFxMaterialImpl"; - -/*=============================================== -utils -===============================================*/ export * from "./utils/useDoubleFBO"; export * from "./utils/useSingleFBO"; -/*=============================================== -misc -===============================================*/ -export * from "./misc/useComposer"; +export * from "./misc"; diff --git a/packages/use-shader-fx/src/materials/core/BasicFxLib.ts b/packages/use-shader-fx/src/materials/core/BasicFxLib.ts index 81ff8fa3..6d6ee7f4 100644 --- a/packages/use-shader-fx/src/materials/core/BasicFxLib.ts +++ b/packages/use-shader-fx/src/materials/core/BasicFxLib.ts @@ -4,7 +4,6 @@ import { DefaultUniforms } from "./FxMaterial"; /*=============================================== basic fxを追加するときはこことShaderChunk,Libを編集する ===============================================*/ - type BasicFxUniformsUnique = { // mixSrc mixSrc: { value: THREE.Texture | null }; @@ -19,24 +18,6 @@ type BasicFxUniformsUnique = { mixDstAlphaFactor: { value: number }; mixDstColorFactor: { value: number }; }; - -export type BasicFxUniforms = BasicFxUniformsUnique & DefaultUniforms; - -export type BasicFxValues = { - // mixSrc - mixSrc?: THREE.Texture | null; - mixSrcResolution?: THREE.Vector2; - mixSrcUvFactor?: number; - mixSrcAlphaFactor?: number; - mixSrcColorFactor?: number; - //mixDst - mixDst?: THREE.Texture | null; - mixDstResolution?: THREE.Vector2; - mixDstUvFactor?: number; - mixDstAlphaFactor?: number; - mixDstColorFactor?: number; -}; - const DEFAULT_BASICFX_VALUES: BasicFxUniformsUnique = { // mixSrc mixSrc: { value: null }, @@ -52,11 +33,26 @@ const DEFAULT_BASICFX_VALUES: BasicFxUniformsUnique = { mixDstColorFactor: { value: 0 }, }; +export type BasicFxUniforms = BasicFxUniformsUnique & DefaultUniforms; + +export type ExtractUniformValue = { + [K in keyof T]?: T[K] extends { value: infer U } ? U : never; +}; +export type BasicFxValues = ExtractUniformValue; + export type BasicFxFlag = { mixSrc: boolean; mixDst: boolean; }; +/** valuesのkeyにbasicFxが含まれているかどうかの判定 */ +function containsBasicFxValues(values?: { [key: string]: any }): boolean { + if (!values) return false; + return Object.keys(values).some((key) => + Object.keys(DEFAULT_BASICFX_VALUES).includes(key as keyof BasicFxValues) + ); +} + function setupDefaultFlag(uniformValues?: BasicFxValues): BasicFxFlag { return { mixSrc: uniformValues?.mixSrc ? true : false, @@ -136,4 +132,5 @@ export const BasicFxLib = { setupDefaultFlag, handleUpdateBasicFx, handleUpdateBasicFxPrefix, + containsBasicFxValues, }; diff --git a/packages/use-shader-fx/src/materials/core/FxBasicFxMaterial.ts b/packages/use-shader-fx/src/materials/core/FxBasicFxMaterial.ts index 32d1c4c8..257a284e 100644 --- a/packages/use-shader-fx/src/materials/core/FxBasicFxMaterial.ts +++ b/packages/use-shader-fx/src/materials/core/FxBasicFxMaterial.ts @@ -28,18 +28,14 @@ export class FxBasicFxMaterial extends FxMaterial { vertexShader, fragmentShader, }: FxMaterialProps = {}) { - super(); - - this.basicFxFlag = BasicFxLib.setupDefaultFlag(uniformValues); - - this.uniforms = THREE.UniformsUtils.merge([ - this.uniforms, - BasicFxLib.DEFAULT_BASICFX_VALUES, - uniforms || {}, - ]) as BasicFxUniforms; - - this.setUniformValues(uniformValues); - this.setValues(materialParameters); + super({ + uniformValues, + materialParameters, + uniforms: THREE.UniformsUtils.merge([ + BasicFxLib.DEFAULT_BASICFX_VALUES, + uniforms || {}, + ]), + }); this.vertexShaderCache = this.vertexShader; this.fragmentShaderCache = this.fragmentShader; @@ -47,10 +43,15 @@ export class FxBasicFxMaterial extends FxMaterial { this.fragmentPrefixCache = ""; this.programCache = 0; + this.basicFxFlag = BasicFxLib.setupDefaultFlag(uniformValues); + this.setupBasicFxShaders(vertexShader, fragmentShader); } updateBasicFx() { + // shaderのsetup前は実行しない + if (!this.basicFxFlag) return; + const _cache = this.programCache; const { validCount, updatedFlag } = BasicFxLib.handleUpdateBasicFx( @@ -81,6 +82,8 @@ export class FxBasicFxMaterial extends FxMaterial { } setupBasicFxShaders(vertexShader?: string, fragmentShader?: string) { + if (!vertexShader && !fragmentShader) return; + this.updateBasicFxPrefix(); const [vertex, fragment] = mergeShaderLib( @@ -89,10 +92,27 @@ export class FxBasicFxMaterial extends FxMaterial { "basicFx" ); - this.setupDefaultShaders(vertex, fragment); + super.setupDefaultShaders(vertex, fragment); this.vertexShaderCache = this.vertexShader; this.fragmentShaderCache = this.fragmentShader; + this.updateBasicFxShader(); } + + // override super class method + setUniformValues(values?: { [key: string]: any }) { + super.setUniformValues(values); + if (BasicFxLib.containsBasicFxValues(values)) { + this.updateBasicFx(); + } + } + + // override super class method + defineUniformAccessors(onSet?: () => void) { + super.defineUniformAccessors(() => { + this.updateBasicFx(); + onSet?.(); + }); + } } diff --git a/packages/use-shader-fx/src/materials/core/FxMaterial.ts b/packages/use-shader-fx/src/materials/core/FxMaterial.ts index ceebbd6e..5bd27839 100644 --- a/packages/use-shader-fx/src/materials/core/FxMaterial.ts +++ b/packages/use-shader-fx/src/materials/core/FxMaterial.ts @@ -10,6 +10,7 @@ export type DefaultUniforms = { }; export type Uniforms = { [uniform: string]: THREE.IUniform }; + export type ShaderWithUniforms = { uniforms?: Uniforms; vertexShader?: string; @@ -47,6 +48,8 @@ export class FxMaterial extends THREE.ShaderMaterial { this.setUniformValues(uniformValues); this.setValues(materialParameters); + + this.defineUniformAccessors(); } /** This is updated in useFxScene */ @@ -60,6 +63,8 @@ export class FxMaterial extends THREE.ShaderMaterial { } setupDefaultShaders(vertexShader?: string, fragmentShader?: string) { + if (!vertexShader && !fragmentShader) return; + const [vertex, fragment] = mergeShaderLib( vertexShader, fragmentShader, @@ -97,15 +102,12 @@ export class FxMaterial extends THREE.ShaderMaterial { } } - /** - * Create getter/setters, This method should be called in the implementing class - */ + /** define getter/setters */ defineUniformAccessors(onSet?: () => void) { const entries = Object.entries(this.uniforms); - entries.forEach(([name]) => { if (this.hasOwnProperty(name)) { - console.warn(`use-shader-fx: ${name} is already defined.`); + // skip if already defined return; } diff --git a/packages/use-shader-fx/src/materials/impl/FxBasicFxMaterialImpl.ts b/packages/use-shader-fx/src/materials/impl/FxBasicFxMaterialImpl.ts index bb16b811..2cf77409 100644 --- a/packages/use-shader-fx/src/materials/impl/FxBasicFxMaterialImpl.ts +++ b/packages/use-shader-fx/src/materials/impl/FxBasicFxMaterialImpl.ts @@ -2,23 +2,26 @@ import * as THREE from "three"; import { FxMaterialProps, ShaderWithUniforms } from "../core/FxMaterial"; import { ShaderLib } from "../../libs/shaders/ShaderLib"; import { FxBasicFxMaterial } from "../core/FxBasicFxMaterial"; -import { BasicFxUniforms, BasicFxValues } from "../core/BasicFxLib"; +import { + BasicFxUniforms, + BasicFxValues, + ExtractUniformValue, +} from "../core/BasicFxLib"; type FxBasicFxMaterialImplUniforms = { src: { value: THREE.Texture }; } & BasicFxUniforms; -export type FxBasicFxMaterialImplValues = { - src?: THREE.Texture; -} & BasicFxValues; +export type FxBasicFxMaterialImplValues = + ExtractUniformValue & BasicFxValues; -const vertex = ` +const DEFAULT_VERTEX = ` void main() { ${ShaderLib.plane_vertex} } `; -const fragment = ` +const DEFAULT_FRAGMENT = ` uniform sampler2D src; void main() { @@ -37,8 +40,8 @@ const fragment = ` export const createFxBasicFxMaterialImpl = ({ uniforms, - vertexShader = vertex, - fragmentShader = fragment, + vertexShader = DEFAULT_VERTEX, + fragmentShader = DEFAULT_FRAGMENT, }: ShaderWithUniforms = {}) => { class FxBasicFxMaterialImpl extends FxBasicFxMaterial { public static readonly key: string = THREE.MathUtils.generateUUID(); @@ -50,29 +53,21 @@ export const createFxBasicFxMaterialImpl = ({ uniforms!: FxBasicFxMaterialImplUniforms; constructor(props: FxMaterialProps) { - super(); + super({ + vertexShader: props?.vertexShader || vertexShader, + fragmentShader: props?.fragmentShader || fragmentShader, + uniformValues: props?.uniformValues, + materialParameters: props?.materialParameters, + uniforms: THREE.UniformsUtils.merge([ + { + src: { value: null }, + }, + uniforms || {}, + props?.uniforms || {}, + ]), + }); this.type = FxBasicFxMaterialImpl.type; - - this.uniforms = THREE.UniformsUtils.merge([ - this.uniforms, - { - src: { value: null }, - }, - uniforms || {}, - props?.uniforms || {}, - ]) as FxBasicFxMaterialImplUniforms; - - this.setupBasicFxShaders( - props?.vertexShader || vertexShader, - props?.fragmentShader || fragmentShader - ); - - this.setUniformValues(props?.uniformValues); - this.setValues(props?.materialParameters || {}); - - // set callback `onSet` to update basicFx flag - this.defineUniformAccessors(this.updateBasicFx.bind(this)); } } diff --git a/packages/use-shader-fx/src/materials/impl/FxMaterialImpl.ts b/packages/use-shader-fx/src/materials/impl/FxMaterialImpl.ts index 41ad2860..1c520814 100644 --- a/packages/use-shader-fx/src/materials/impl/FxMaterialImpl.ts +++ b/packages/use-shader-fx/src/materials/impl/FxMaterialImpl.ts @@ -7,22 +7,21 @@ import { } from "../core/FxMaterial"; import { ShaderLib } from "../../libs/shaders/ShaderLib"; import { DEFAULT_TEXTURE } from "../../libs/constants"; +import { ExtractUniformValue } from "../core/BasicFxLib"; type FxMaterialImplUniforms = { src: { value: THREE.Texture }; } & DefaultUniforms; -export type FxMaterialImplValues = { - src?: THREE.Texture; -}; +export type FxMaterialImplValues = ExtractUniformValue; -const vertex = ` +const DEFAULT_VERTEX = ` void main() { ${ShaderLib.plane_vertex} } `; -const fragment = ` +const DEFAULT_FRAGMENT = ` uniform sampler2D src; void main() { gl_FragColor = texture2D(src, vUv); @@ -31,8 +30,8 @@ const fragment = ` export const createFxMaterialImpl = ({ uniforms, - vertexShader = vertex, - fragmentShader = fragment, + vertexShader = DEFAULT_VERTEX, + fragmentShader = DEFAULT_FRAGMENT, }: ShaderWithUniforms = {}) => { class FxMaterialImpl extends FxMaterial { public static readonly key: string = THREE.MathUtils.generateUUID(); @@ -44,28 +43,21 @@ export const createFxMaterialImpl = ({ uniforms!: FxMaterialImplUniforms; constructor(props: FxMaterialProps) { - super(); + super({ + vertexShader: props?.vertexShader || vertexShader, + fragmentShader: props?.fragmentShader || fragmentShader, + uniformValues: props?.uniformValues, + materialParameters: props?.materialParameters, + uniforms: THREE.UniformsUtils.merge([ + { + src: { value: DEFAULT_TEXTURE }, + }, + uniforms || {}, + props?.uniforms || {}, + ]), + }); this.type = FxMaterialImpl.type; - - this.uniforms = THREE.UniformsUtils.merge([ - this.uniforms, - { - src: { value: DEFAULT_TEXTURE }, - }, - uniforms || {}, - props?.uniforms || {}, - ]) as FxMaterialImplUniforms; - - this.setupDefaultShaders( - props?.vertexShader || vertexShader, - props?.fragmentShader || fragmentShader - ); - - this.setUniformValues(props?.uniformValues); - this.setValues(props?.materialParameters || {}); - - this.defineUniformAccessors(); } } diff --git a/packages/use-shader-fx/src/hooks/useBlur/BlurMaterial.ts b/packages/use-shader-fx/src/materials/impl/blur/BlurMaterial.ts similarity index 51% rename from packages/use-shader-fx/src/hooks/useBlur/BlurMaterial.ts rename to packages/use-shader-fx/src/materials/impl/blur/BlurMaterial.ts index 97acb65c..b91cee50 100644 --- a/packages/use-shader-fx/src/hooks/useBlur/BlurMaterial.ts +++ b/packages/use-shader-fx/src/materials/impl/blur/BlurMaterial.ts @@ -1,15 +1,22 @@ import * as THREE from "three"; import { fragment, vertex } from "./blur.glsl"; -import { FxBasicFxMaterial } from "../../materials/core/FxBasicFxMaterial"; -import { BlurValues } from "."; -import { FxMaterialProps } from "../../materials/core/FxMaterial"; -import { BasicFxUniforms } from "../../materials/core/BasicFxLib"; +import { FxBasicFxMaterial } from "../../core/FxBasicFxMaterial"; +import { FxMaterialProps } from "../../core/FxMaterial"; +import { + BasicFxUniforms, + BasicFxValues, + ExtractUniformValue, +} from "../../core/BasicFxLib"; type BlurUniforms = { + /** */ src: { value: THREE.Texture | null }; + /** */ blurSize: { value: number }; } & BasicFxUniforms; +export type BlurValues = ExtractUniformValue & BasicFxValues; + export class BlurMaterial extends FxBasicFxMaterial { static get type() { return "BlurMaterial"; @@ -21,21 +28,17 @@ export class BlurMaterial extends FxBasicFxMaterial { uniformValues, materialParameters = {}, }: FxMaterialProps) { - super(); - - this.type = BlurMaterial.type; - - this.uniforms = THREE.UniformsUtils.merge([ - this.uniforms, - { + super({ + vertexShader: vertex, + fragmentShader: fragment, + uniformValues, + materialParameters, + uniforms: { src: { value: null }, blurSize: { value: 5 }, - }, - ]) as BlurUniforms; - - this.setUniformValues(uniformValues); - this.setValues(materialParameters); + } as BlurUniforms, + }); - this.setupBasicFxShaders(vertex, fragment); + this.type = BlurMaterial.type; } } diff --git a/packages/use-shader-fx/src/hooks/useBlur/blur.glsl.ts b/packages/use-shader-fx/src/materials/impl/blur/blur.glsl.ts similarity index 92% rename from packages/use-shader-fx/src/hooks/useBlur/blur.glsl.ts rename to packages/use-shader-fx/src/materials/impl/blur/blur.glsl.ts index 32a485ca..408966f2 100644 --- a/packages/use-shader-fx/src/hooks/useBlur/blur.glsl.ts +++ b/packages/use-shader-fx/src/materials/impl/blur/blur.glsl.ts @@ -1,4 +1,4 @@ -import { ShaderLib } from "../../libs/shaders/ShaderLib"; +import { ShaderLib } from "../../../libs/shaders/ShaderLib"; export const vertex = ` void main() { diff --git a/packages/use-shader-fx/src/hooks/useCoverTexture/CoverTextureMaterial.ts b/packages/use-shader-fx/src/materials/impl/cover/CoverTextureMaterial.ts similarity index 54% rename from packages/use-shader-fx/src/hooks/useCoverTexture/CoverTextureMaterial.ts rename to packages/use-shader-fx/src/materials/impl/cover/CoverTextureMaterial.ts index 7aa7dc17..fdcaae7b 100644 --- a/packages/use-shader-fx/src/hooks/useCoverTexture/CoverTextureMaterial.ts +++ b/packages/use-shader-fx/src/materials/impl/cover/CoverTextureMaterial.ts @@ -1,15 +1,23 @@ import * as THREE from "three"; import { fragment, vertex } from "./coverTexture.glsl"; -import { FxBasicFxMaterial } from "../../materials/core/FxBasicFxMaterial"; -import { CoverTextureValues } from "."; -import { FxMaterialProps } from "../../materials/core/FxMaterial"; -import { BasicFxUniforms } from "../../materials/core/BasicFxLib"; +import { FxBasicFxMaterial } from "../../core/FxBasicFxMaterial"; +import { FxMaterialProps } from "../../core/FxMaterial"; +import { + BasicFxUniforms, + BasicFxValues, + ExtractUniformValue, +} from "../../core/BasicFxLib"; type CoverTextureUniforms = { + /** */ src: { value: THREE.Texture | null }; + /** */ textureResolution: { value: THREE.Vector2 }; } & BasicFxUniforms; +export type CoverTextureValues = ExtractUniformValue & + BasicFxValues; + export class CoverTextureMaterial extends FxBasicFxMaterial { static get type() { return "NoiseMaterial"; @@ -21,21 +29,17 @@ export class CoverTextureMaterial extends FxBasicFxMaterial { uniformValues, materialParameters = {}, }: FxMaterialProps = {}) { - super(); - - this.type = CoverTextureMaterial.type; - - this.uniforms = THREE.UniformsUtils.merge([ - this.uniforms, - { + super({ + vertexShader: vertex, + fragmentShader: fragment, + uniformValues, + materialParameters, + uniforms: { src: { value: null }, textureResolution: { value: new THREE.Vector2() }, - }, - ]) as CoverTextureUniforms; - - this.setUniformValues(uniformValues); - this.setValues(materialParameters); + } as CoverTextureUniforms, + }); - this.setupBasicFxShaders(vertex, fragment); + this.type = CoverTextureMaterial.type; } } diff --git a/packages/use-shader-fx/src/hooks/useCoverTexture/coverTexture.glsl.ts b/packages/use-shader-fx/src/materials/impl/cover/coverTexture.glsl.ts similarity index 92% rename from packages/use-shader-fx/src/hooks/useCoverTexture/coverTexture.glsl.ts rename to packages/use-shader-fx/src/materials/impl/cover/coverTexture.glsl.ts index a1b37201..429704f5 100644 --- a/packages/use-shader-fx/src/hooks/useCoverTexture/coverTexture.glsl.ts +++ b/packages/use-shader-fx/src/materials/impl/cover/coverTexture.glsl.ts @@ -1,4 +1,4 @@ -import { ShaderLib } from "../../libs/shaders/ShaderLib"; +import { ShaderLib } from "../../../libs/shaders/ShaderLib"; export const vertex = ` uniform vec2 textureResolution; diff --git a/packages/use-shader-fx/src/hooks/useFluid/materials/AdvectionMaterial.ts b/packages/use-shader-fx/src/materials/impl/fluid/AdvectionMaterial.ts similarity index 66% rename from packages/use-shader-fx/src/hooks/useFluid/materials/AdvectionMaterial.ts rename to packages/use-shader-fx/src/materials/impl/fluid/AdvectionMaterial.ts index f58ead9a..d68bf0e0 100644 --- a/packages/use-shader-fx/src/hooks/useFluid/materials/AdvectionMaterial.ts +++ b/packages/use-shader-fx/src/materials/impl/fluid/AdvectionMaterial.ts @@ -3,16 +3,15 @@ import vertex from "./shaders/vertex"; import fragment from "./shaders/advection.frag"; import { FxMaterial, - DefaultUniforms, FxMaterialProps, } from "../../../materials/core/FxMaterial"; import { DEFAULT_TEXTURE } from "../../../libs/constants"; -import { DeltaTime } from ".."; +import { DeltaTime } from "."; type AdvectionUniforms = { velocity: { value: THREE.Texture }; dt: { value: number }; -} & DefaultUniforms; +}; export class AdvectionMaterial extends FxMaterial { static get type() { @@ -22,21 +21,16 @@ export class AdvectionMaterial extends FxMaterial { uniforms!: AdvectionUniforms; constructor({ uniformValues, materialParameters = {} }: FxMaterialProps) { - super(); - - this.type = AdvectionMaterial.type; - - this.uniforms = THREE.UniformsUtils.merge([ - this.uniforms, - { + super({ + vertexShader: vertex.advection, + fragmentShader: fragment, + uniformValues, + materialParameters, + uniforms: { velocity: { value: DEFAULT_TEXTURE }, dt: { value: DeltaTime }, - }, - ]) as AdvectionUniforms; - - this.setupDefaultShaders(vertex.advection, fragment); - - this.setUniformValues(uniformValues); - this.setValues(materialParameters); + } as AdvectionUniforms, + }); + this.type = AdvectionMaterial.type; } } diff --git a/packages/use-shader-fx/src/hooks/useFluid/materials/DivergenceMaterial.ts b/packages/use-shader-fx/src/materials/impl/fluid/DivergenceMaterial.ts similarity index 69% rename from packages/use-shader-fx/src/hooks/useFluid/materials/DivergenceMaterial.ts rename to packages/use-shader-fx/src/materials/impl/fluid/DivergenceMaterial.ts index b519a0ed..fec614e1 100644 --- a/packages/use-shader-fx/src/hooks/useFluid/materials/DivergenceMaterial.ts +++ b/packages/use-shader-fx/src/materials/impl/fluid/DivergenceMaterial.ts @@ -3,17 +3,16 @@ import vertex from "./shaders/vertex"; import fragment from "./shaders/divergence.frag"; import { FxMaterial, - DefaultUniforms, FxMaterialProps, } from "../../../materials/core/FxMaterial"; import { DEFAULT_TEXTURE } from "../../../libs/constants"; -import { DeltaTime } from ".."; +import { DeltaTime } from "."; type DivergenceUniforms = { isBounce: { value: boolean }; velocity: { value: THREE.Texture }; dt: { value: number }; -} & DefaultUniforms; +}; export class DivergenceMaterial extends FxMaterial { static get type() { @@ -23,22 +22,18 @@ export class DivergenceMaterial extends FxMaterial { uniforms!: DivergenceUniforms; constructor({ uniformValues, materialParameters = {} }: FxMaterialProps) { - super(); - - this.type = DivergenceMaterial.type; - - this.uniforms = THREE.UniformsUtils.merge([ - this.uniforms, - { + super({ + vertexShader: vertex.main, + fragmentShader: fragment, + uniformValues, + materialParameters, + uniforms: { isBounce: { value: true }, velocity: { value: DEFAULT_TEXTURE }, dt: { value: DeltaTime }, - }, - ]) as DivergenceUniforms; + } as DivergenceUniforms, + }); - this.setupDefaultShaders(vertex.main, fragment); - - this.setUniformValues(uniformValues); - this.setValues(materialParameters); + this.type = DivergenceMaterial.type; } } diff --git a/packages/use-shader-fx/src/hooks/useFluid/materials/PoissonMaterial.ts b/packages/use-shader-fx/src/materials/impl/fluid/PoissonMaterial.ts similarity index 72% rename from packages/use-shader-fx/src/hooks/useFluid/materials/PoissonMaterial.ts rename to packages/use-shader-fx/src/materials/impl/fluid/PoissonMaterial.ts index b9c24bb8..fbe2ef41 100644 --- a/packages/use-shader-fx/src/hooks/useFluid/materials/PoissonMaterial.ts +++ b/packages/use-shader-fx/src/materials/impl/fluid/PoissonMaterial.ts @@ -2,7 +2,6 @@ import * as THREE from "three"; import vertex from "./shaders/vertex"; import fragment from "./shaders/poisson.frag"; import { - DefaultUniforms, FxMaterial, FxMaterialProps, } from "../../../materials/core/FxMaterial"; @@ -12,7 +11,7 @@ type PoissonUniforms = { isBounce: { value: boolean }; pressure: { value: THREE.Texture }; divergence: { value: THREE.Texture }; -} & DefaultUniforms; +}; export class PoissonMaterial extends FxMaterial { static get type() { @@ -24,24 +23,18 @@ export class PoissonMaterial extends FxMaterial { iteration: number; constructor({ uniformValues, materialParameters = {} }: FxMaterialProps) { - super(); - - this.type = PoissonMaterial.type; - - this.uniforms = THREE.UniformsUtils.merge([ - this.uniforms, - { + super({ + vertexShader: vertex.poisson, + fragmentShader: fragment, + uniformValues, + materialParameters, + uniforms: { isBounce: { value: true }, pressure: { value: DEFAULT_TEXTURE }, divergence: { value: DEFAULT_TEXTURE }, - }, - ]) as PoissonUniforms; - + } as PoissonUniforms, + }); + this.type = PoissonMaterial.type; this.iteration = 32; - - this.setupDefaultShaders(vertex.poisson, fragment); - - this.setUniformValues(uniformValues); - this.setValues(materialParameters); } } diff --git a/packages/use-shader-fx/src/hooks/useFluid/materials/PressureMaterial.ts b/packages/use-shader-fx/src/materials/impl/fluid/PressureMaterial.ts similarity index 71% rename from packages/use-shader-fx/src/hooks/useFluid/materials/PressureMaterial.ts rename to packages/use-shader-fx/src/materials/impl/fluid/PressureMaterial.ts index c9ff3f4c..0f77b484 100644 --- a/packages/use-shader-fx/src/hooks/useFluid/materials/PressureMaterial.ts +++ b/packages/use-shader-fx/src/materials/impl/fluid/PressureMaterial.ts @@ -3,18 +3,17 @@ import vertex from "./shaders/vertex"; import fragment from "./shaders/pressure.frag"; import { FxMaterial, - DefaultUniforms, FxMaterialProps, } from "../../../materials/core/FxMaterial"; import { DEFAULT_TEXTURE } from "../../../libs/constants"; -import { DeltaTime } from ".."; +import { DeltaTime } from "."; type PressureUniforms = { isBounce: { value: boolean }; pressure: { value: THREE.Texture }; velocity: { value: THREE.Texture }; dt: { value: number }; -} & DefaultUniforms; +}; export class PressureMaterial extends FxMaterial { static get type() { @@ -24,23 +23,19 @@ export class PressureMaterial extends FxMaterial { uniforms!: PressureUniforms; constructor({ uniformValues, materialParameters = {} }: FxMaterialProps) { - super(); - - this.type = PressureMaterial.type; - - this.uniforms = THREE.UniformsUtils.merge([ - this.uniforms, - { + super({ + vertexShader: vertex.main, + fragmentShader: fragment, + uniformValues, + materialParameters, + uniforms: { isBounce: { value: true }, pressure: { value: DEFAULT_TEXTURE }, velocity: { value: DEFAULT_TEXTURE }, dt: { value: DeltaTime }, - }, - ]) as PressureUniforms; + } as PressureUniforms, + }); - this.setupDefaultShaders(vertex.main, fragment); - - this.setUniformValues(uniformValues); - this.setValues(materialParameters); + this.type = PressureMaterial.type; } } diff --git a/packages/use-shader-fx/src/hooks/useFluid/materials/SplatMaterial.ts b/packages/use-shader-fx/src/materials/impl/fluid/SplatMaterial.ts similarity index 69% rename from packages/use-shader-fx/src/hooks/useFluid/materials/SplatMaterial.ts rename to packages/use-shader-fx/src/materials/impl/fluid/SplatMaterial.ts index a1bec3ac..1fbf8996 100644 --- a/packages/use-shader-fx/src/hooks/useFluid/materials/SplatMaterial.ts +++ b/packages/use-shader-fx/src/materials/impl/fluid/SplatMaterial.ts @@ -2,7 +2,6 @@ import * as THREE from "three"; import vertex from "./shaders/vertex"; import fragment from "./shaders/splat.frag"; import { - DefaultUniforms, FxMaterial, FxMaterialProps, } from "../../../materials/core/FxMaterial"; @@ -11,38 +10,34 @@ type SplatUniforms = { force: { value: THREE.Vector2 }; center: { value: THREE.Vector2 }; scale: { value: THREE.Vector2 }; -} & DefaultUniforms; +}; export class SplatMaterial extends FxMaterial { static get type() { return "SplatMaterial"; } - force: number; + forceBias: number; uniforms!: SplatUniforms; constructor({ uniformValues, materialParameters = {} }: FxMaterialProps) { - super(); - - this.type = SplatMaterial.type; - - this.force = 30; - - this.uniforms = THREE.UniformsUtils.merge([ - this.uniforms, - { + super({ + vertexShader: vertex.splat, + fragmentShader: fragment, + uniformValues, + materialParameters, + uniforms: { force: { value: new THREE.Vector2(0, 0) }, center: { value: new THREE.Vector2(0, 0) }, scale: { value: new THREE.Vector2(30, 30) }, - }, - ]) as SplatUniforms; + } as SplatUniforms, + }); - this.setupDefaultShaders(vertex.splat, fragment); + this.type = SplatMaterial.type; - this.blending = THREE.AdditiveBlending; + this.forceBias = 30; - this.setUniformValues(uniformValues); - this.setValues(materialParameters); + this.blending = THREE.AdditiveBlending; } } diff --git a/packages/use-shader-fx/src/materials/impl/fluid/index.js b/packages/use-shader-fx/src/materials/impl/fluid/index.js new file mode 100644 index 00000000..814b29b9 --- /dev/null +++ b/packages/use-shader-fx/src/materials/impl/fluid/index.js @@ -0,0 +1,7 @@ +export * from "./AdvectionMaterial"; +export * from "./DivergenceMaterial"; +export * from "./PressureMaterial"; +export * from "./PoissonMaterial"; +export * from "./SplatMaterial"; + +export const DeltaTime = 0.015; diff --git a/packages/use-shader-fx/src/hooks/useFluid/materials/shaders/advection.frag b/packages/use-shader-fx/src/materials/impl/fluid/shaders/advection.frag similarity index 100% rename from packages/use-shader-fx/src/hooks/useFluid/materials/shaders/advection.frag rename to packages/use-shader-fx/src/materials/impl/fluid/shaders/advection.frag diff --git a/packages/use-shader-fx/src/hooks/useFluid/materials/shaders/divergence.frag b/packages/use-shader-fx/src/materials/impl/fluid/shaders/divergence.frag similarity index 100% rename from packages/use-shader-fx/src/hooks/useFluid/materials/shaders/divergence.frag rename to packages/use-shader-fx/src/materials/impl/fluid/shaders/divergence.frag diff --git a/packages/use-shader-fx/src/hooks/useFluid/materials/shaders/poisson.frag b/packages/use-shader-fx/src/materials/impl/fluid/shaders/poisson.frag similarity index 100% rename from packages/use-shader-fx/src/hooks/useFluid/materials/shaders/poisson.frag rename to packages/use-shader-fx/src/materials/impl/fluid/shaders/poisson.frag diff --git a/packages/use-shader-fx/src/hooks/useFluid/materials/shaders/pressure.frag b/packages/use-shader-fx/src/materials/impl/fluid/shaders/pressure.frag similarity index 100% rename from packages/use-shader-fx/src/hooks/useFluid/materials/shaders/pressure.frag rename to packages/use-shader-fx/src/materials/impl/fluid/shaders/pressure.frag diff --git a/packages/use-shader-fx/src/hooks/useFluid/materials/shaders/splat.frag b/packages/use-shader-fx/src/materials/impl/fluid/shaders/splat.frag similarity index 100% rename from packages/use-shader-fx/src/hooks/useFluid/materials/shaders/splat.frag rename to packages/use-shader-fx/src/materials/impl/fluid/shaders/splat.frag diff --git a/packages/use-shader-fx/src/hooks/useFluid/materials/shaders/vertex.ts b/packages/use-shader-fx/src/materials/impl/fluid/shaders/vertex.ts similarity index 100% rename from packages/use-shader-fx/src/hooks/useFluid/materials/shaders/vertex.ts rename to packages/use-shader-fx/src/materials/impl/fluid/shaders/vertex.ts diff --git a/packages/use-shader-fx/src/hooks/useNoise/NoiseMaterial.ts b/packages/use-shader-fx/src/materials/impl/noise/NoiseMaterial.ts similarity index 52% rename from packages/use-shader-fx/src/hooks/useNoise/NoiseMaterial.ts rename to packages/use-shader-fx/src/materials/impl/noise/NoiseMaterial.ts index 59399839..1a6e00e4 100644 --- a/packages/use-shader-fx/src/hooks/useNoise/NoiseMaterial.ts +++ b/packages/use-shader-fx/src/materials/impl/noise/NoiseMaterial.ts @@ -1,20 +1,34 @@ import * as THREE from "three"; import { noiseFragment, noiseVertex } from "./noise.glsl"; -import { FxBasicFxMaterial } from "../../materials/core/FxBasicFxMaterial"; -import { FxMaterialProps } from "../../materials/core/FxMaterial"; -import { BasicFxUniforms } from "../../materials/core/BasicFxLib"; +import { FxBasicFxMaterial } from "../../core/FxBasicFxMaterial"; +import { FxMaterialProps } from "../../core/FxMaterial"; +import { + BasicFxUniforms, + BasicFxValues, + ExtractUniformValue, +} from "../../core/BasicFxLib"; type NoiseUniforms = { + /** useBeatを渡せば、リズムを変えられる。 */ tick: { value: number }; + /** noise scale , default : `0.004` */ scale: { value: number }; + /** time factor default : `0.3` */ timeStrength: { value: number }; + /** noiseOctaves, affects performance default : `2` */ noiseOctaves: { value: number }; + /** fbmOctaves, affects performance default : `2` */ fbmOctaves: { value: number }; + /** domain warping octaves , affects performance default : `2` */ warpOctaves: { value: number }; + /** direction of domain warping , default : `(2.0,2,0)` */ warpDirection: { value: THREE.Vector2 }; + /** strength of domain warping , default : `8.0` */ warpStrength: { value: number }; } & BasicFxUniforms; +export type NoiseValues = ExtractUniformValue & BasicFxValues; + export class NoiseMaterial extends FxBasicFxMaterial { public static readonly key: string = THREE.MathUtils.generateUUID(); @@ -27,14 +41,13 @@ export class NoiseMaterial extends FxBasicFxMaterial { constructor({ uniformValues, materialParameters = {}, - }: FxMaterialProps = {}) { - super(); - - this.type = NoiseMaterial.type; - - this.uniforms = THREE.UniformsUtils.merge([ - this.uniforms, - { + }: FxMaterialProps = {}) { + super({ + uniformValues, + materialParameters, + vertexShader: noiseVertex, + fragmentShader: noiseFragment, + uniforms: { tick: { value: 0.0 }, scale: { value: 0.03 }, timeStrength: { value: 0.3 }, @@ -43,14 +56,8 @@ export class NoiseMaterial extends FxBasicFxMaterial { warpOctaves: { value: 2 }, warpDirection: { value: new THREE.Vector2(2.0, 2.0) }, warpStrength: { value: 8 }, - }, - ]) as NoiseUniforms; - - this.setUniformValues(uniformValues); - this.setValues(materialParameters); - - this.setupBasicFxShaders(noiseVertex, noiseFragment); - - this.defineUniformAccessors(); + } as NoiseUniforms, + }); + this.type = NoiseMaterial.type; } } diff --git a/packages/use-shader-fx/src/hooks/useNoise/noise.glsl.ts b/packages/use-shader-fx/src/materials/impl/noise/noise.glsl.ts similarity index 97% rename from packages/use-shader-fx/src/hooks/useNoise/noise.glsl.ts rename to packages/use-shader-fx/src/materials/impl/noise/noise.glsl.ts index 15d06691..82ad6c16 100644 --- a/packages/use-shader-fx/src/hooks/useNoise/noise.glsl.ts +++ b/packages/use-shader-fx/src/materials/impl/noise/noise.glsl.ts @@ -1,4 +1,4 @@ -import { ShaderLib } from "../../libs/shaders/ShaderLib"; +import { ShaderLib } from "../../../libs/shaders/ShaderLib"; export const noiseVertex = ` void main() { diff --git a/packages/use-shader-fx/src/hooks/useRawBlank/RawBlankMaterial.ts b/packages/use-shader-fx/src/materials/impl/rawBlank/RawBlankMaterial.ts similarity index 65% rename from packages/use-shader-fx/src/hooks/useRawBlank/RawBlankMaterial.ts rename to packages/use-shader-fx/src/materials/impl/rawBlank/RawBlankMaterial.ts index 90f6aa9e..6662104c 100644 --- a/packages/use-shader-fx/src/hooks/useRawBlank/RawBlankMaterial.ts +++ b/packages/use-shader-fx/src/materials/impl/rawBlank/RawBlankMaterial.ts @@ -1,4 +1,6 @@ -import { FxMaterial, FxMaterialProps } from "../../materials/core/FxMaterial"; +import { FxMaterial, FxMaterialProps } from "../../core/FxMaterial"; + +export type RawBlankValues = {}; export class RawBlankMaterial extends FxMaterial { static get type() { @@ -7,7 +9,5 @@ export class RawBlankMaterial extends FxMaterial { constructor(props: FxMaterialProps) { super(props); this.type = RawBlankMaterial.type; - - this.defineUniformAccessors(); } } diff --git a/packages/use-shader-fx/src/materials/index.js b/packages/use-shader-fx/src/materials/index.js new file mode 100644 index 00000000..a058b63e --- /dev/null +++ b/packages/use-shader-fx/src/materials/index.js @@ -0,0 +1,8 @@ +export * from "./impl/FxMaterialImpl"; +export * from "./impl/FxBasicFxMaterialImpl"; + +export * from "./impl/noise/NoiseMaterial"; +export * from "./impl/rawBlank/RawBlankMaterial"; +export * from "./impl/fluid"; +export * from "./impl/blur/BlurMaterial"; +export * from "./impl/cover/CoverTextureMaterial"; diff --git a/packages/use-shader-fx/src/misc/index.js b/packages/use-shader-fx/src/misc/index.js new file mode 100644 index 00000000..16924fb4 --- /dev/null +++ b/packages/use-shader-fx/src/misc/index.js @@ -0,0 +1,4 @@ +export * from "./useBeat"; +export * from "./useComposer"; +export * from "./usePointerTracker"; +export * from "./useWindowPointer"; diff --git a/packages/use-shader-fx/src/misc/useComposer.ts b/packages/use-shader-fx/src/misc/useComposer.ts index a7bb7c23..5ac1c0a9 100644 --- a/packages/use-shader-fx/src/misc/useComposer.ts +++ b/packages/use-shader-fx/src/misc/useComposer.ts @@ -1,12 +1,10 @@ import { useState } from "react"; import { HooksProps, HooksReturn, RootState } from "../hooks/types"; -import { useFluid } from "../hooks/useFluid"; -import { useNoise } from "../hooks/useNoise"; import { BasicFxValues } from "../materials/core/BasicFxLib"; +import { FxTypes } from "../hooks"; export type FxConfig = { - // TODO * ここの型定義うまいことしたい /hooksにindex.tsを作ってそこでexportしてimportするとかかな - fx: typeof useFluid | typeof useNoise; + fx: FxTypes; } & HooksProps & BasicFxValues; diff --git a/todo b/todo index b58fa0e2..e69de29b 100644 --- a/todo +++ b/todo @@ -1,5 +0,0 @@ -- fxのmaterialを/material/impl/xxxに移動する - - clothとかwobble3Dとか、materialのみのnodeも今後できそうなので。 -- すべてのfxのmaterialをexportする -- /hooksにindex.tsつくってexportまとめたほうが良さそうね。 - - useComposerのFxConfigもここで定義する \ No newline at end of file From 8cdca3c58260273e451ccc9e20e5c8f406fb779f Mon Sep 17 00:00:00 2001 From: takuma-hmng8 Date: Tue, 15 Oct 2024 17:04:10 +0900 Subject: [PATCH 18/60] update --- .../use-shader-fx/src/materials/core/FxBasicFxMaterial.ts | 6 +++--- todo | 5 +++++ 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/packages/use-shader-fx/src/materials/core/FxBasicFxMaterial.ts b/packages/use-shader-fx/src/materials/core/FxBasicFxMaterial.ts index 257a284e..c554b087 100644 --- a/packages/use-shader-fx/src/materials/core/FxBasicFxMaterial.ts +++ b/packages/use-shader-fx/src/materials/core/FxBasicFxMaterial.ts @@ -100,15 +100,15 @@ export class FxBasicFxMaterial extends FxMaterial { this.updateBasicFxShader(); } - // override super class method + /*=============================================== + override super class method + ===============================================*/ setUniformValues(values?: { [key: string]: any }) { super.setUniformValues(values); if (BasicFxLib.containsBasicFxValues(values)) { this.updateBasicFx(); } } - - // override super class method defineUniformAccessors(onSet?: () => void) { super.defineUniformAccessors(() => { this.updateBasicFx(); diff --git a/todo b/todo index e69de29b..4623631a 100644 --- a/todo +++ b/todo @@ -0,0 +1,5 @@ +- useComposer,直接hookを渡すんじゃなくて、stringにしようかな + + +- touch designerを解剖して、機能を因数分解してみる + - webglooの設計つくる \ No newline at end of file From f009f8096373d46f62a7339616f8b73ba4b131bb Mon Sep 17 00:00:00 2001 From: takuma-hmng8 Date: Wed, 16 Oct 2024 14:49:06 +0900 Subject: [PATCH 19/60] update --- app/v2_impl/Playground.tsx | 35 +++++--- app/v2_impl/page.tsx | 4 +- app/v2_pipe/Playground.tsx | 35 +++++--- packages/use-shader-fx/src/misc/index.js | 2 +- .../use-shader-fx/src/misc/useComposer.ts | 50 ----------- .../use-shader-fx/src/misc/usePipeline.ts | 85 +++++++++++++++++++ todo | 11 ++- 7 files changed, 145 insertions(+), 77 deletions(-) delete mode 100644 packages/use-shader-fx/src/misc/useComposer.ts create mode 100644 packages/use-shader-fx/src/misc/usePipeline.ts diff --git a/app/v2_impl/Playground.tsx b/app/v2_impl/Playground.tsx index 6546fc4b..318e4544 100644 --- a/app/v2_impl/Playground.tsx +++ b/app/v2_impl/Playground.tsx @@ -13,6 +13,7 @@ import { FxMaterialImplValues, FxBasicFxMaterialImplValues, useFluid, + useCoverTexture, } from "@/packages/use-shader-fx/src"; import { Float, OrbitControls } from "@react-three/drei"; @@ -54,31 +55,39 @@ export const Playground = () => { // src: renderTarget.texture, // }); - const fluid = useFluid({ - size, - dpr: 0.25, - }); + // const fluid = useFluid({ + // size, + // dpr: 0.25, + // }); const noise = useNoise({ size, - dpr: 0.3, - fboAutoSetSize: true, - scale: 0.4, + dpr: 1, + scale: 100, noiseOctaves: 2, // mixSrc: fluid.texture, - mixSrcColorFactor: 0.5, - mixSrcUvFactor: 0.6, + // mixSrcColorFactor: 0.5, + // mixSrcUvFactor: 0.6, }); - noise.setValues({ - mixSrc: fluid.texture, + const cover = useCoverTexture({ + size, + dpr: 1, + src: renderTarget.texture, + mixSrc: noise.texture, + mixSrcUvFactor: 0.2, }); + // noise.setValues({ + // mixSrc: cover.texture, + // mixSrcColorFactor: 1, + // }); + useFrame((state) => { updateRenderTarget({ gl: state.gl }); noise.render(state); // blur.render(state); - fluid.render(state); + cover.render(state); }); const ref = useRef(); @@ -90,7 +99,7 @@ export const Playground = () => { {createPortal( diff --git a/app/v2_impl/page.tsx b/app/v2_impl/page.tsx index 51d1d029..6256d104 100644 --- a/app/v2_impl/page.tsx +++ b/app/v2_impl/page.tsx @@ -11,7 +11,7 @@ export default function Page() { height: "100svh", pointerEvents: "none", }}> -
    -
    + */} diff --git a/app/v2_pipe/Playground.tsx b/app/v2_pipe/Playground.tsx index 00f040e8..1ce78fc3 100644 --- a/app/v2_pipe/Playground.tsx +++ b/app/v2_pipe/Playground.tsx @@ -8,8 +8,9 @@ import { FxMaterialImplValues, FxBasicFxMaterialImplValues, useFluid, - useComposer, + usePipeline, FxConfig, + PipelineConfig, } from "@/packages/use-shader-fx/src"; import { useEffect, useMemo, useState } from "react"; @@ -22,37 +23,49 @@ extend({ FxMaterialImpl, FxBasicFxMaterialImpl }); reactive way - fxの変更をtriggerにkeyを変更することで、reactiveにfxを変更することが可能 ===============================================*/ -const Composer = ({ compose }: { compose: FxConfig[] }) => { - const { texture, render } = useComposer(...compose); +const Pipeline = ({ + fxConfig, + pipelineConfig, +}: { + fxConfig: FxConfig[]; + pipelineConfig: PipelineConfig[]; +}) => { + const { texture, render, setPipeline } = usePipeline(...fxConfig); + setPipeline(...pipelineConfig); useFrame((state) => render(state)); return ; }; export const Playground = () => { const { size } = useThree(); - const compose: FxConfig[] = [ + const fxConfig: FxConfig[] = [ { fx: useFluid, size, dpr: 0.3 }, { fx: useNoise, size, - dpr: 0.1, + dpr: 0.2, mixSrcColorFactor: 0.2, }, ]; + const pipelineConfig: PipelineConfig[] = [{}, { mixSrc: 0 }]; // keyを変更することで、fxの変更をreactiveにすることが可能 // UIではGUIの変更を検知して、keyを変更することで、reactiveに変更を反映するなどを想定 - const [composeCache, setComposeCache] = useState(compose.length); + const [pipelineCache, setPipelineCache] = useState(fxConfig.length); const [version, setVersion] = useState(0); - if (compose.length !== composeCache) { - setComposeCache(compose.length); + if (fxConfig.length !== pipelineCache) { + setPipelineCache(fxConfig.length); setVersion(version + 1); } return ( - + ); }; @@ -65,7 +78,7 @@ non-reactive way // export const Playground = () => { // const { size } = useThree(); -// const { texture, render } = useComposer( +// const { texture, render, setPipeline } = usePipeline( // { // fx: useFluid, // size, @@ -78,6 +91,8 @@ non-reactive way // mixSrcColorFactor: 0.2, // } // ); +// setPipeline({}, { mixSrc: 0 }); + // useFrame((state) => render(state)); // return ( diff --git a/packages/use-shader-fx/src/misc/index.js b/packages/use-shader-fx/src/misc/index.js index 16924fb4..6a9694b0 100644 --- a/packages/use-shader-fx/src/misc/index.js +++ b/packages/use-shader-fx/src/misc/index.js @@ -1,4 +1,4 @@ export * from "./useBeat"; -export * from "./useComposer"; export * from "./usePointerTracker"; export * from "./useWindowPointer"; +export * from "./usePipeline"; diff --git a/packages/use-shader-fx/src/misc/useComposer.ts b/packages/use-shader-fx/src/misc/useComposer.ts deleted file mode 100644 index 5ac1c0a9..00000000 --- a/packages/use-shader-fx/src/misc/useComposer.ts +++ /dev/null @@ -1,50 +0,0 @@ -import { useState } from "react"; -import { HooksProps, HooksReturn, RootState } from "../hooks/types"; -import { BasicFxValues } from "../materials/core/BasicFxLib"; -import { FxTypes } from "../hooks"; - -export type FxConfig = { - fx: FxTypes; -} & HooksProps & - BasicFxValues; - -const WARN_TEXT = `use-shader-fx: fx and args length mismatch. fx is non-reactive; update by changing the key to reset state.`; - -/*=============================================== -- Generates a pipeline of fx -- hooks are non-reactive -- Automatically receives one previous texture as mixSrc -===============================================*/ -export const useComposer = (...args: FxConfig[]) => { - // non reactive - const [hooks] = useState(() => args.map(({ fx }) => fx)); - - // resolutionを更新するため、argsはreactiveにする - let _args = [...args]; - const argsDiff = hooks.length - _args.length; - - if (argsDiff !== 0) { - console.warn(WARN_TEXT); - // argsの長さを調整する - if (argsDiff < 0) { - _args = _args.slice(0, hooks.length); - } else { - _args = _args.concat(Array(argsDiff).fill(_args.at(-1))); - } - } - - // hooksからの返り値を格納する - const fxArr: HooksReturn[] = []; - - hooks.forEach((hook, i) => { - const prev = fxArr[i - 1]?.texture; - const { fx: _, ...rest } = _args[i]; - fxArr.push(hook({ ...rest, ...(prev && { mixSrc: prev }) })); - }); - - const render = (state: RootState) => fxArr.forEach((fx) => fx.render(state)); - const setValues = (...values: {}[]) => - fxArr.forEach((fx, i) => fx.setValues(values[i])); - - return { render, setValues, texture: fxArr.at(-1)?.texture }; -}; diff --git a/packages/use-shader-fx/src/misc/usePipeline.ts b/packages/use-shader-fx/src/misc/usePipeline.ts new file mode 100644 index 00000000..d5100bf7 --- /dev/null +++ b/packages/use-shader-fx/src/misc/usePipeline.ts @@ -0,0 +1,85 @@ +import * as THREE from "three"; +import { useState } from "react"; +import { HooksProps, HooksReturn, RootState } from "../hooks/types"; +import { BasicFxValues } from "../materials/core/BasicFxLib"; +import { FxTypes } from "../hooks"; + +export type FxConfig = { + fx: FxTypes; +} & HooksProps & + BasicFxValues; + +export type PipelineConfig = { + src?: number; + mixSrc?: number; + mixDst?: number; +}; + +export type PipelineValues = { + src?: THREE.Texture; + mixSrc?: THREE.Texture; + mixDst?: THREE.Texture; +}; + +const WARN_TEXT = { + args: `use-shader-fx: fx and args length mismatch. fx is non-reactive; update by changing the key to reset state.`, + pipeline: `use-shader-fx: fx and pipeline length mismatch. fx is non-reactive; update by changing the key to reset state.`, +}; + +/*=============================================== +- Generates a pipeline of fx +- hooks are non-reactive +===============================================*/ +export const usePipeline = (...args: FxConfig[]) => { + // non reactive + const [hooks] = useState(() => args.map(({ fx }) => fx)); + + // resolutionを更新するため、argsはreactiveにする + let _args = args.map(({ fx, ...rest }) => rest); + + const argsDiff = hooks.length - _args.length; + + if (argsDiff !== 0) { + console.warn(WARN_TEXT.args); + // argsの長さを調整する + if (argsDiff < 0) { + _args = _args.slice(0, hooks.length); + } else { + _args = _args.concat(Array(argsDiff).fill(_args.at(-1))); + } + } + + // hooksからの返り値を格納する + const pipeline: HooksReturn[] = []; + hooks.forEach((hook, i) => pipeline.push(hook(_args[i]))); + + const render = (state: RootState) => + pipeline.forEach((fx) => fx.render(state)); + const setValues = (...values: {}[]) => + pipeline.forEach((fx, i) => fx.setValues(values[i])); + + // setPipiline + const textures = pipeline.map((fx) => fx.texture); + + const setPipeline = (...args: PipelineConfig[]) => { + if (args.length !== pipeline.length) { + console.warn(WARN_TEXT.pipeline); + return; + } + args.forEach(({ src, mixSrc, mixDst }, i) => { + const value: PipelineValues = {}; + if (src !== undefined) value.src = textures[src]; + if (mixSrc !== undefined) value.mixSrc = textures[mixSrc]; + if (mixDst !== undefined) value.mixDst = textures[mixDst]; + pipeline[i].setValues(value); + }); + }; + + return { + render, + setValues, + texture: pipeline.at(-1)?.texture, + textures, + setPipeline, + }; +}; diff --git a/todo b/todo index 4623631a..e7b19ed1 100644 --- a/todo +++ b/todo @@ -2,4 +2,13 @@ - touch designerを解剖して、機能を因数分解してみる - - webglooの設計つくる \ No newline at end of file + - webglooの設計つくる + +- rename + - fxbasicfx→basicfx + +- createMaterial + - createMaterialImplにして、引数に関数で引数にチャンクとれるみたいな。第二引数でマテリアルの種類選べるみたいな。 + - createfxbasicfxmateralimpl + →createBasicFxMaterial + →createSamplingFxMaterial \ No newline at end of file From 928238fcf0606f6d760a39771a135592adcd1432 Mon Sep 17 00:00:00 2001 From: takuma-hmng8 Date: Wed, 16 Oct 2024 17:27:16 +0900 Subject: [PATCH 20/60] update --- app/v2_pipe/Playground.tsx | 128 +++++++++--------- packages/use-shader-fx/src/hooks/index.ts | 28 +++- .../use-shader-fx/src/hooks/useBlur/index.ts | 7 +- .../src/hooks/useCoverTexture/index.ts | 4 +- .../use-shader-fx/src/hooks/useFluid/index.ts | 4 +- .../use-shader-fx/src/hooks/useNoise/index.ts | 4 +- .../src/hooks/useRawBlank/index.ts | 7 +- .../use-shader-fx/src/misc/usePipeline.ts | 37 +++-- todo | 12 +- 9 files changed, 125 insertions(+), 106 deletions(-) diff --git a/app/v2_pipe/Playground.tsx b/app/v2_pipe/Playground.tsx index 1ce78fc3..e7628826 100644 --- a/app/v2_pipe/Playground.tsx +++ b/app/v2_pipe/Playground.tsx @@ -11,6 +11,9 @@ import { usePipeline, FxConfig, PipelineConfig, + useBlur, + NoiseProps, + useCoverTexture, } from "@/packages/use-shader-fx/src"; import { useEffect, useMemo, useState } from "react"; @@ -23,86 +26,89 @@ extend({ FxMaterialImpl, FxBasicFxMaterialImpl }); reactive way - fxの変更をtriggerにkeyを変更することで、reactiveにfxを変更することが可能 ===============================================*/ -const Pipeline = ({ - fxConfig, - pipelineConfig, -}: { - fxConfig: FxConfig[]; - pipelineConfig: PipelineConfig[]; -}) => { - const { texture, render, setPipeline } = usePipeline(...fxConfig); - setPipeline(...pipelineConfig); - useFrame((state) => render(state)); - return ; -}; -export const Playground = () => { - const { size } = useThree(); - - const fxConfig: FxConfig[] = [ - { fx: useFluid, size, dpr: 0.3 }, - { - fx: useNoise, - size, - dpr: 0.2, - mixSrcColorFactor: 0.2, - }, - ]; - const pipelineConfig: PipelineConfig[] = [{}, { mixSrc: 0 }]; - - // keyを変更することで、fxの変更をreactiveにすることが可能 - // UIではGUIの変更を検知して、keyを変更することで、reactiveに変更を反映するなどを想定 - const [pipelineCache, setPipelineCache] = useState(fxConfig.length); - const [version, setVersion] = useState(0); - if (fxConfig.length !== pipelineCache) { - setPipelineCache(fxConfig.length); - setVersion(version + 1); - } - return ( - - - - - ); -}; +// const Pipeline = ({ +// fxConfig, +// pipelineConfig, +// }: { +// fxConfig: FxConfig[]; +// pipelineConfig: PipelineConfig[]; +// }) => { +// const { texture, render, setPipeline } = usePipeline(...fxConfig); +// setPipeline(...pipelineConfig); +// useFrame((state) => render(state)); +// return ; +// }; -/*=============================================== -non-reactive way -- resolutionはreactive - - ただし他のhooksと同様、resolution以外はnon-reactive -===============================================*/ // export const Playground = () => { // const { size } = useThree(); -// const { texture, render, setPipeline } = usePipeline( -// { -// fx: useFluid, -// size, -// dpr: 0.2, -// }, +// const fxConfig = [ +// { fx: useFluid, size, dpr: 0.2 }, // { // fx: useNoise, // size, // dpr: 0.1, // mixSrcColorFactor: 0.2, -// } -// ); -// setPipeline({}, { mixSrc: 0 }); +// }, +// ]; -// useFrame((state) => render(state)); +// const pipelineConfig: PipelineConfig[] = [{}, { mixSrc: 0 }]; + +// // keyを変更することで、fxの変更をreactiveにすることが可能 +// // UIではGUIの変更を検知して、keyを変更することで、reactiveに変更を反映するなどを想定 +// const [pipelineCache, setPipelineCache] = useState(fxConfig.length); +// const [version, setVersion] = useState(0); +// if (fxConfig.length !== pipelineCache) { +// setPipelineCache(fxConfig.length); +// setVersion(version + 1); +// } // return ( // // -// +// // // ); // }; +/*=============================================== +non-reactive way +- resolutionはreactive + - ただし他のhooksと同様、resolution以外はnon-reactive +===============================================*/ +export const Playground = () => { + const { size } = useThree(); + + const { texture, render, setPipeline } = usePipeline( + { + fx: useFluid, + size, + dpr: 0.2, + }, + { + fx: useNoise, + size, + dpr: 0.1, + mixSrcColorFactor: 0.2, + } + ); + setPipeline({}, { mixSrc: 0 }); + + useFrame((state) => render(state)); + + return ( + + + + + ); +}; + declare global { namespace JSX { interface IntrinsicElements { diff --git a/packages/use-shader-fx/src/hooks/index.ts b/packages/use-shader-fx/src/hooks/index.ts index ea078dc3..b733a765 100644 --- a/packages/use-shader-fx/src/hooks/index.ts +++ b/packages/use-shader-fx/src/hooks/index.ts @@ -1,8 +1,8 @@ -import { useBlur } from "./useBlur"; -import { useCoverTexture } from "./useCoverTexture"; -import { useFluid } from "./useFluid"; -import { useNoise } from "./useNoise"; -import { useRawBlank } from "./useRawBlank"; +import { useBlur, BlurProps } from "./useBlur"; +import { useCoverTexture, CoverTextureProps } from "./useCoverTexture"; +import { useFluid, FluidProps } from "./useFluid"; +import { useNoise, NoiseProps } from "./useNoise"; +import { useRawBlank, RawBlankProps } from "./useRawBlank"; export type FxTypes = | typeof useBlur @@ -11,4 +11,20 @@ export type FxTypes = | typeof useNoise | typeof useRawBlank; -export { useBlur, useCoverTexture, useFluid, useNoise, useRawBlank }; +export type FxProps = T extends typeof useBlur + ? BlurProps + : T extends typeof useCoverTexture + ? CoverTextureProps + : T extends typeof useNoise + ? NoiseProps + : T extends typeof useFluid + ? FluidProps + : T extends typeof useRawBlank + ? RawBlankProps + : never; + +export * from "./useBlur"; +export * from "./useCoverTexture"; +export * from "./useFluid"; +export * from "./useNoise"; +export * from "./useRawBlank"; diff --git a/packages/use-shader-fx/src/hooks/useBlur/index.ts b/packages/use-shader-fx/src/hooks/useBlur/index.ts index 75869d5a..9667de3b 100644 --- a/packages/use-shader-fx/src/hooks/useBlur/index.ts +++ b/packages/use-shader-fx/src/hooks/useBlur/index.ts @@ -10,6 +10,8 @@ type BlurConfig = { blurIteration?: number; }; +export type BlurProps = HooksProps & BlurValues & BlurConfig; + /** * @link https://github.com/FunTechInc/use-shader-fx?tab=readme-ov-file#usage */ @@ -21,10 +23,7 @@ export const useBlur = ({ materialParameters, blurIteration = 5, ...uniformValues -}: HooksProps & BlurValues & BlurConfig): HooksReturn< - BlurValues, - BlurMaterial -> => { +}: BlurProps): HooksReturn => { const _dpr = getDpr(dpr); const { scene, material, camera } = useFxScene({ diff --git a/packages/use-shader-fx/src/hooks/useCoverTexture/index.ts b/packages/use-shader-fx/src/hooks/useCoverTexture/index.ts index 9de3e990..f0628647 100644 --- a/packages/use-shader-fx/src/hooks/useCoverTexture/index.ts +++ b/packages/use-shader-fx/src/hooks/useCoverTexture/index.ts @@ -6,6 +6,8 @@ import { RootState } from "../types"; import { CoverTextureMaterial, CoverTextureValues } from "../../materials"; import { useFxScene } from "../../utils/useFxScene"; +export type CoverTextureProps = HooksProps & CoverTextureValues; + /** * @link https://github.com/FunTechInc/use-shader-fx?tab=readme-ov-file#usage */ @@ -16,7 +18,7 @@ export const useCoverTexture = ({ renderTargetOptions, materialParameters, ...uniformValues -}: HooksProps & CoverTextureValues): HooksReturn< +}: CoverTextureProps): HooksReturn< CoverTextureValues, CoverTextureMaterial > => { diff --git a/packages/use-shader-fx/src/hooks/useFluid/index.ts b/packages/use-shader-fx/src/hooks/useFluid/index.ts index 22b12cac..f4dd72ed 100644 --- a/packages/use-shader-fx/src/hooks/useFluid/index.ts +++ b/packages/use-shader-fx/src/hooks/useFluid/index.ts @@ -22,6 +22,8 @@ export type FluidValues = { ===============================================*/ }; +export type FluidProps = HooksProps & FluidValues; + /** * @link https://github.com/FunTechInc/use-shader-fx?tab=readme-ov-file#usage */ @@ -31,7 +33,7 @@ export const useFluid = ({ fboAutoSetSize, renderTargetOptions, ...values -}: HooksProps & FluidValues): HooksReturn => { +}: FluidProps): HooksReturn => { const _dpr = getDpr(dpr); // fbos diff --git a/packages/use-shader-fx/src/hooks/useNoise/index.ts b/packages/use-shader-fx/src/hooks/useNoise/index.ts index 3b501df7..0adffc31 100644 --- a/packages/use-shader-fx/src/hooks/useNoise/index.ts +++ b/packages/use-shader-fx/src/hooks/useNoise/index.ts @@ -6,6 +6,8 @@ import { RootState } from "../types"; import { NoiseMaterial, NoiseValues } from "../../materials"; import { useFxScene } from "../../utils/useFxScene"; +export type NoiseProps = HooksProps & NoiseValues; + /** * @link https://github.com/FunTechInc/use-shader-fx?tab=readme-ov-file#usage */ @@ -16,7 +18,7 @@ export const useNoise = ({ renderTargetOptions, materialParameters, ...uniformValues -}: HooksProps & NoiseValues): HooksReturn => { +}: NoiseProps): HooksReturn => { const _dpr = getDpr(dpr); const { scene, material, camera } = useFxScene({ diff --git a/packages/use-shader-fx/src/hooks/useRawBlank/index.ts b/packages/use-shader-fx/src/hooks/useRawBlank/index.ts index ca3a04e1..5906e740 100644 --- a/packages/use-shader-fx/src/hooks/useRawBlank/index.ts +++ b/packages/use-shader-fx/src/hooks/useRawBlank/index.ts @@ -9,6 +9,8 @@ import { ShaderWithUniforms } from "../../materials/core/FxMaterial"; type RawBlankConfig = ShaderWithUniforms; +export type RawBlankProps = HooksProps & RawBlankValues & RawBlankConfig; + /** * @link https://github.com/FunTechInc/use-shader-fx?tab=readme-ov-file#usage */ @@ -22,10 +24,7 @@ export const useRawBlank = ({ vertexShader, fragmentShader, ...uniformValues -}: HooksProps & RawBlankValues & RawBlankConfig): HooksReturn< - RawBlankValues, - RawBlankMaterial -> => { +}: RawBlankProps): HooksReturn => { const _dpr = getDpr(dpr); const { scene, material, camera } = useFxScene({ diff --git a/packages/use-shader-fx/src/misc/usePipeline.ts b/packages/use-shader-fx/src/misc/usePipeline.ts index d5100bf7..e1b2a64f 100644 --- a/packages/use-shader-fx/src/misc/usePipeline.ts +++ b/packages/use-shader-fx/src/misc/usePipeline.ts @@ -1,13 +1,11 @@ import * as THREE from "three"; import { useState } from "react"; -import { HooksProps, HooksReturn, RootState } from "../hooks/types"; -import { BasicFxValues } from "../materials/core/BasicFxLib"; -import { FxTypes } from "../hooks"; +import { HooksReturn, RootState } from "../hooks/types"; +import { FxTypes, FxProps } from "../hooks"; -export type FxConfig = { - fx: FxTypes; -} & HooksProps & - BasicFxValues; +export type FxConfig = { + fx: T; +} & FxProps; export type PipelineConfig = { src?: number; @@ -26,22 +24,20 @@ const WARN_TEXT = { pipeline: `use-shader-fx: fx and pipeline length mismatch. fx is non-reactive; update by changing the key to reset state.`, }; -/*=============================================== -- Generates a pipeline of fx -- hooks are non-reactive -===============================================*/ -export const usePipeline = (...args: FxConfig[]) => { - // non reactive +export const usePipeline = ( + ...args: { [K in keyof T]: FxConfig } +) => { + // hooks are non-reactive const [hooks] = useState(() => args.map(({ fx }) => fx)); - // resolutionを更新するため、argsはreactiveにする + // to update the resolution, make the args reactive. let _args = args.map(({ fx, ...rest }) => rest); const argsDiff = hooks.length - _args.length; if (argsDiff !== 0) { console.warn(WARN_TEXT.args); - // argsの長さを調整する + // adjust length of args if (argsDiff < 0) { _args = _args.slice(0, hooks.length); } else { @@ -49,7 +45,6 @@ export const usePipeline = (...args: FxConfig[]) => { } } - // hooksからの返り値を格納する const pipeline: HooksReturn[] = []; hooks.forEach((hook, i) => pipeline.push(hook(_args[i]))); @@ -58,7 +53,6 @@ export const usePipeline = (...args: FxConfig[]) => { const setValues = (...values: {}[]) => pipeline.forEach((fx, i) => fx.setValues(values[i])); - // setPipiline const textures = pipeline.map((fx) => fx.texture); const setPipeline = (...args: PipelineConfig[]) => { @@ -68,9 +62,9 @@ export const usePipeline = (...args: FxConfig[]) => { } args.forEach(({ src, mixSrc, mixDst }, i) => { const value: PipelineValues = {}; - if (src !== undefined) value.src = textures[src]; - if (mixSrc !== undefined) value.mixSrc = textures[mixSrc]; - if (mixDst !== undefined) value.mixDst = textures[mixDst]; + if (src != null) value.src = textures[src]; + if (mixSrc != null) value.mixSrc = textures[mixSrc]; + if (mixDst != null) value.mixDst = textures[mixDst]; pipeline[i].setValues(value); }); }; @@ -78,8 +72,9 @@ export const usePipeline = (...args: FxConfig[]) => { return { render, setValues, + setPipeline, texture: pipeline.at(-1)?.texture, textures, - setPipeline, + pipeline, }; }; diff --git a/todo b/todo index e7b19ed1..833f770a 100644 --- a/todo +++ b/todo @@ -1,14 +1,12 @@ -- useComposer,直接hookを渡すんじゃなくて、stringにしようかな - - - touch designerを解剖して、機能を因数分解してみる - webglooの設計つくる - rename - fxbasicfx→basicfx -- createMaterial +- createMaterialImpl - createMaterialImplにして、引数に関数で引数にチャンクとれるみたいな。第二引数でマテリアルの種類選べるみたいな。 - - createfxbasicfxmateralimpl - →createBasicFxMaterial - →createSamplingFxMaterial \ No newline at end of file + - 実装クラスを生成する関数 + +- SamplingFxMaterialの実装 + - rgbShiftなど \ No newline at end of file From 38da72f21505b3d85ea8a30ff2f64c02b9213217 Mon Sep 17 00:00:00 2001 From: takuma-hmng8 Date: Wed, 16 Oct 2024 18:42:10 +0900 Subject: [PATCH 21/60] update --- app/v2_pipe/Playground.tsx | 14 ++++---- .../use-shader-fx/src/misc/usePipeline.ts | 32 +++++++++++-------- 2 files changed, 25 insertions(+), 21 deletions(-) diff --git a/app/v2_pipe/Playground.tsx b/app/v2_pipe/Playground.tsx index e7628826..babee93a 100644 --- a/app/v2_pipe/Playground.tsx +++ b/app/v2_pipe/Playground.tsx @@ -9,13 +9,9 @@ import { FxBasicFxMaterialImplValues, useFluid, usePipeline, - FxConfig, - PipelineConfig, - useBlur, - NoiseProps, - useCoverTexture, } from "@/packages/use-shader-fx/src"; import { useEffect, useMemo, useState } from "react"; +import { useTexture } from "@react-three/drei"; const FxMaterialImpl = createFxMaterialImpl(); const FxBasicFxMaterialImpl = createFxBasicFxMaterialImpl(); @@ -84,6 +80,8 @@ non-reactive way export const Playground = () => { const { size } = useThree(); + const [app] = useTexture(["/app-head.jpg"]); + const { texture, render, setPipeline } = usePipeline( { fx: useFluid, @@ -94,10 +92,12 @@ export const Playground = () => { fx: useNoise, size, dpr: 0.1, - mixSrcColorFactor: 0.2, + mixDstUvFactor: 0.2, + mixDstColorFactor: 0.2, } ); - setPipeline({}, { mixSrc: 0 }); + + setPipeline({}, { mixDst: 0 }); useFrame((state) => render(state)); diff --git a/packages/use-shader-fx/src/misc/usePipeline.ts b/packages/use-shader-fx/src/misc/usePipeline.ts index e1b2a64f..2ec920db 100644 --- a/packages/use-shader-fx/src/misc/usePipeline.ts +++ b/packages/use-shader-fx/src/misc/usePipeline.ts @@ -8,15 +8,12 @@ export type FxConfig = { } & FxProps; export type PipelineConfig = { - src?: number; - mixSrc?: number; - mixDst?: number; + src?: number | THREE.Texture; + mixSrc?: number | THREE.Texture; + mixDst?: number | THREE.Texture; }; - export type PipelineValues = { - src?: THREE.Texture; - mixSrc?: THREE.Texture; - mixDst?: THREE.Texture; + [K in keyof PipelineConfig]: THREE.Texture | undefined; }; const WARN_TEXT = { @@ -60,13 +57,9 @@ export const usePipeline = ( console.warn(WARN_TEXT.pipeline); return; } - args.forEach(({ src, mixSrc, mixDst }, i) => { - const value: PipelineValues = {}; - if (src != null) value.src = textures[src]; - if (mixSrc != null) value.mixSrc = textures[mixSrc]; - if (mixDst != null) value.mixDst = textures[mixDst]; - pipeline[i].setValues(value); - }); + args.forEach((arg, i) => + pipeline[i].setValues(getPipelineValues(arg, textures)) + ); }; return { @@ -78,3 +71,14 @@ export const usePipeline = ( pipeline, }; }; + +function getPipelineValues(config: PipelineConfig, textures: THREE.Texture[]) { + const value: PipelineValues = {}; + for (const key in config) { + const _val = config[key as keyof PipelineConfig]; + if (_val != null) + value[key as keyof PipelineConfig] = + typeof _val === "number" ? textures[_val] : _val; + } + return value; +} From 85fabf2b56ac491e3a321290150e12c043bb1987 Mon Sep 17 00:00:00 2001 From: takuma-hmng8 Date: Thu, 17 Oct 2024 10:24:28 +0900 Subject: [PATCH 22/60] update --- app/v2_fxMaterials/Playground.tsx | 4 ++-- app/v2_impl/Playground.tsx | 10 ++++----- app/v2_pipe/Playground.tsx | 10 ++++----- .../use-shader-fx/src/hooks/types/index.ts | 4 ++-- .../use-shader-fx/src/hooks/useFluid/index.ts | 2 +- ...xBasicFxMaterial.ts => BasicFxMaterial.ts} | 2 +- .../src/materials/core/SamplingFxMaterial.ts | 6 +++++ ...MaterialImpl.ts => BasicFxMaterialImpl.ts} | 22 +++++++++---------- .../src/materials/impl/blur/BlurMaterial.ts | 4 ++-- .../impl/cover/CoverTextureMaterial.ts | 4 ++-- .../src/materials/impl/noise/NoiseMaterial.ts | 4 ++-- packages/use-shader-fx/src/materials/index.js | 2 +- todo | 13 +++++------ 13 files changed, 46 insertions(+), 41 deletions(-) rename packages/use-shader-fx/src/materials/core/{FxBasicFxMaterial.ts => BasicFxMaterial.ts} (98%) create mode 100644 packages/use-shader-fx/src/materials/core/SamplingFxMaterial.ts rename packages/use-shader-fx/src/materials/impl/{FxBasicFxMaterialImpl.ts => BasicFxMaterialImpl.ts} (70%) diff --git a/app/v2_fxMaterials/Playground.tsx b/app/v2_fxMaterials/Playground.tsx index 935d599f..bf8a7fcc 100644 --- a/app/v2_fxMaterials/Playground.tsx +++ b/app/v2_fxMaterials/Playground.tsx @@ -7,7 +7,7 @@ import { NoiseMaterial, NoiseValues, FxMaterialImplValues, - FxBasicFxMaterialImplValues, + BasicFxMaterialImplValues, } from "@/packages/use-shader-fx/src"; extend({ NoiseMaterial }); @@ -33,7 +33,7 @@ declare global { noiseMaterial: NoiseValues & JSX.IntrinsicElements["shaderMaterial"]; fxMaterialImpl: FxMaterialImplValues & JSX.IntrinsicElements["shaderMaterial"]; - fxBasicFxMaterialImpl: FxBasicFxMaterialImplValues & + BasicFxMaterialImpl: BasicFxMaterialImplValues & JSX.IntrinsicElements["shaderMaterial"]; } } diff --git a/app/v2_impl/Playground.tsx b/app/v2_impl/Playground.tsx index 318e4544..aa0f1969 100644 --- a/app/v2_impl/Playground.tsx +++ b/app/v2_impl/Playground.tsx @@ -9,9 +9,9 @@ import { useBlur, useSingleFBO, createFxMaterialImpl, - createFxBasicFxMaterialImpl, + createBasicFxMaterialImpl, FxMaterialImplValues, - FxBasicFxMaterialImplValues, + BasicFxMaterialImplValues, useFluid, useCoverTexture, } from "@/packages/use-shader-fx/src"; @@ -32,9 +32,9 @@ const FxMaterialImpl = createFxMaterialImpl({ } `, }); -const FxBasicFxMaterialImpl = createFxBasicFxMaterialImpl(); +const BasicFxMaterialImpl = createBasicFxMaterialImpl(); -extend({ FxMaterialImpl, FxBasicFxMaterialImpl }); +extend({ FxMaterialImpl, BasicFxMaterialImpl }); export const Playground = () => { const { size, viewport, camera } = useThree(); @@ -123,7 +123,7 @@ declare global { interface IntrinsicElements { fxMaterialImpl: FxMaterialImplValues & JSX.IntrinsicElements["shaderMaterial"]; - fxBasicFxMaterialImpl: FxBasicFxMaterialImplValues & + BasicFxMaterialImpl: BasicFxMaterialImplValues & JSX.IntrinsicElements["shaderMaterial"]; } } diff --git a/app/v2_pipe/Playground.tsx b/app/v2_pipe/Playground.tsx index babee93a..00982ef9 100644 --- a/app/v2_pipe/Playground.tsx +++ b/app/v2_pipe/Playground.tsx @@ -4,9 +4,9 @@ import { useFrame, useThree, extend, createPortal } from "@react-three/fiber"; import { useNoise, createFxMaterialImpl, - createFxBasicFxMaterialImpl, + createBasicFxMaterialImpl, FxMaterialImplValues, - FxBasicFxMaterialImplValues, + BasicFxMaterialImplValues, useFluid, usePipeline, } from "@/packages/use-shader-fx/src"; @@ -14,9 +14,9 @@ import { useEffect, useMemo, useState } from "react"; import { useTexture } from "@react-three/drei"; const FxMaterialImpl = createFxMaterialImpl(); -const FxBasicFxMaterialImpl = createFxBasicFxMaterialImpl(); +const BasicFxMaterialImpl = createBasicFxMaterialImpl(); -extend({ FxMaterialImpl, FxBasicFxMaterialImpl }); +extend({ FxMaterialImpl, BasicFxMaterialImpl }); /*=============================================== reactive way @@ -114,7 +114,7 @@ declare global { interface IntrinsicElements { fxMaterialImpl: FxMaterialImplValues & JSX.IntrinsicElements["shaderMaterial"]; - fxBasicFxMaterialImpl: FxBasicFxMaterialImplValues & + BasicFxMaterialImpl: BasicFxMaterialImplValues & JSX.IntrinsicElements["shaderMaterial"]; } } diff --git a/packages/use-shader-fx/src/hooks/types/index.ts b/packages/use-shader-fx/src/hooks/types/index.ts index 7d88faf9..005a665f 100644 --- a/packages/use-shader-fx/src/hooks/types/index.ts +++ b/packages/use-shader-fx/src/hooks/types/index.ts @@ -1,5 +1,5 @@ import * as THREE from "three"; -import { FxBasicFxMaterial } from "../../materials/core/FxBasicFxMaterial"; +import { BasicFxMaterial } from "../../materials/core/BasicFxMaterial"; import { DoubleRenderTarget } from "../../utils/useDoubleFBO"; export type Size = { @@ -59,7 +59,7 @@ export interface HooksProps { * @template V The type for the FX parameters. * @template O The type for the material. */ -export type HooksReturn = { +export type HooksReturn = { /** * Functions to update parameters and render. * @param rootState RootState diff --git a/packages/use-shader-fx/src/hooks/useFluid/index.ts b/packages/use-shader-fx/src/hooks/useFluid/index.ts index f4dd72ed..6f3182e2 100644 --- a/packages/use-shader-fx/src/hooks/useFluid/index.ts +++ b/packages/use-shader-fx/src/hooks/useFluid/index.ts @@ -15,7 +15,7 @@ export type FluidValues = { /*=============================================== TODO * - 出力でcolormapとvelocitymapを選択できるみたいな仕組みにする - - colormapはfxBasicFxmaterialで、基礎FXも + - colormapはBasicFxmaterial - params - velocity dissipation - color dissipation (color map) diff --git a/packages/use-shader-fx/src/materials/core/FxBasicFxMaterial.ts b/packages/use-shader-fx/src/materials/core/BasicFxMaterial.ts similarity index 98% rename from packages/use-shader-fx/src/materials/core/FxBasicFxMaterial.ts rename to packages/use-shader-fx/src/materials/core/BasicFxMaterial.ts index c554b087..76d05e25 100644 --- a/packages/use-shader-fx/src/materials/core/FxBasicFxMaterial.ts +++ b/packages/use-shader-fx/src/materials/core/BasicFxMaterial.ts @@ -8,7 +8,7 @@ import { } from "./BasicFxLib"; import { mergeShaderLib } from "../../libs/shaders/mergeShaderLib"; -export class FxBasicFxMaterial extends FxMaterial { +export class BasicFxMaterial extends FxMaterial { public static readonly key: string = THREE.MathUtils.generateUUID(); basicFxFlag: BasicFxFlag; diff --git a/packages/use-shader-fx/src/materials/core/SamplingFxMaterial.ts b/packages/use-shader-fx/src/materials/core/SamplingFxMaterial.ts new file mode 100644 index 00000000..8ac90f94 --- /dev/null +++ b/packages/use-shader-fx/src/materials/core/SamplingFxMaterial.ts @@ -0,0 +1,6 @@ +/*=============================================== +- rgbshift +- glitch +- pixelate +など、テクスチャサンプリング系のエフェクトを提供するマテリアル +===============================================*/ diff --git a/packages/use-shader-fx/src/materials/impl/FxBasicFxMaterialImpl.ts b/packages/use-shader-fx/src/materials/impl/BasicFxMaterialImpl.ts similarity index 70% rename from packages/use-shader-fx/src/materials/impl/FxBasicFxMaterialImpl.ts rename to packages/use-shader-fx/src/materials/impl/BasicFxMaterialImpl.ts index 2cf77409..9384120b 100644 --- a/packages/use-shader-fx/src/materials/impl/FxBasicFxMaterialImpl.ts +++ b/packages/use-shader-fx/src/materials/impl/BasicFxMaterialImpl.ts @@ -1,19 +1,19 @@ import * as THREE from "three"; import { FxMaterialProps, ShaderWithUniforms } from "../core/FxMaterial"; import { ShaderLib } from "../../libs/shaders/ShaderLib"; -import { FxBasicFxMaterial } from "../core/FxBasicFxMaterial"; +import { BasicFxMaterial } from "../core/BasicFxMaterial"; import { BasicFxUniforms, BasicFxValues, ExtractUniformValue, } from "../core/BasicFxLib"; -type FxBasicFxMaterialImplUniforms = { +type BasicFxMaterialImplUniforms = { src: { value: THREE.Texture }; } & BasicFxUniforms; -export type FxBasicFxMaterialImplValues = - ExtractUniformValue & BasicFxValues; +export type BasicFxMaterialImplValues = + ExtractUniformValue & BasicFxValues; const DEFAULT_VERTEX = ` void main() { @@ -38,21 +38,21 @@ const DEFAULT_FRAGMENT = ` } `; -export const createFxBasicFxMaterialImpl = ({ +export const createBasicFxMaterialImpl = ({ uniforms, vertexShader = DEFAULT_VERTEX, fragmentShader = DEFAULT_FRAGMENT, }: ShaderWithUniforms = {}) => { - class FxBasicFxMaterialImpl extends FxBasicFxMaterial { + class BasicFxMaterialImpl extends BasicFxMaterial { public static readonly key: string = THREE.MathUtils.generateUUID(); static get type() { - return "FxBasicFxMaterialImpl"; + return "BasicFxMaterialImpl"; } - uniforms!: FxBasicFxMaterialImplUniforms; + uniforms!: BasicFxMaterialImplUniforms; - constructor(props: FxMaterialProps) { + constructor(props: FxMaterialProps) { super({ vertexShader: props?.vertexShader || vertexShader, fragmentShader: props?.fragmentShader || fragmentShader, @@ -67,11 +67,11 @@ export const createFxBasicFxMaterialImpl = ({ ]), }); - this.type = FxBasicFxMaterialImpl.type; + this.type = BasicFxMaterialImpl.type; } } - return FxBasicFxMaterialImpl as typeof FxBasicFxMaterialImpl & { + return BasicFxMaterialImpl as typeof BasicFxMaterialImpl & { key: string; }; }; diff --git a/packages/use-shader-fx/src/materials/impl/blur/BlurMaterial.ts b/packages/use-shader-fx/src/materials/impl/blur/BlurMaterial.ts index b91cee50..67b48739 100644 --- a/packages/use-shader-fx/src/materials/impl/blur/BlurMaterial.ts +++ b/packages/use-shader-fx/src/materials/impl/blur/BlurMaterial.ts @@ -1,6 +1,6 @@ import * as THREE from "three"; import { fragment, vertex } from "./blur.glsl"; -import { FxBasicFxMaterial } from "../../core/FxBasicFxMaterial"; +import { BasicFxMaterial } from "../../core/BasicFxMaterial"; import { FxMaterialProps } from "../../core/FxMaterial"; import { BasicFxUniforms, @@ -17,7 +17,7 @@ type BlurUniforms = { export type BlurValues = ExtractUniformValue & BasicFxValues; -export class BlurMaterial extends FxBasicFxMaterial { +export class BlurMaterial extends BasicFxMaterial { static get type() { return "BlurMaterial"; } diff --git a/packages/use-shader-fx/src/materials/impl/cover/CoverTextureMaterial.ts b/packages/use-shader-fx/src/materials/impl/cover/CoverTextureMaterial.ts index fdcaae7b..c5ef5b47 100644 --- a/packages/use-shader-fx/src/materials/impl/cover/CoverTextureMaterial.ts +++ b/packages/use-shader-fx/src/materials/impl/cover/CoverTextureMaterial.ts @@ -1,6 +1,6 @@ import * as THREE from "three"; import { fragment, vertex } from "./coverTexture.glsl"; -import { FxBasicFxMaterial } from "../../core/FxBasicFxMaterial"; +import { BasicFxMaterial } from "../../core/BasicFxMaterial"; import { FxMaterialProps } from "../../core/FxMaterial"; import { BasicFxUniforms, @@ -18,7 +18,7 @@ type CoverTextureUniforms = { export type CoverTextureValues = ExtractUniformValue & BasicFxValues; -export class CoverTextureMaterial extends FxBasicFxMaterial { +export class CoverTextureMaterial extends BasicFxMaterial { static get type() { return "NoiseMaterial"; } diff --git a/packages/use-shader-fx/src/materials/impl/noise/NoiseMaterial.ts b/packages/use-shader-fx/src/materials/impl/noise/NoiseMaterial.ts index 1a6e00e4..fff61e14 100644 --- a/packages/use-shader-fx/src/materials/impl/noise/NoiseMaterial.ts +++ b/packages/use-shader-fx/src/materials/impl/noise/NoiseMaterial.ts @@ -1,6 +1,6 @@ import * as THREE from "three"; import { noiseFragment, noiseVertex } from "./noise.glsl"; -import { FxBasicFxMaterial } from "../../core/FxBasicFxMaterial"; +import { BasicFxMaterial } from "../../core/BasicFxMaterial"; import { FxMaterialProps } from "../../core/FxMaterial"; import { BasicFxUniforms, @@ -29,7 +29,7 @@ type NoiseUniforms = { export type NoiseValues = ExtractUniformValue & BasicFxValues; -export class NoiseMaterial extends FxBasicFxMaterial { +export class NoiseMaterial extends BasicFxMaterial { public static readonly key: string = THREE.MathUtils.generateUUID(); static get type() { diff --git a/packages/use-shader-fx/src/materials/index.js b/packages/use-shader-fx/src/materials/index.js index a058b63e..a6f9ae19 100644 --- a/packages/use-shader-fx/src/materials/index.js +++ b/packages/use-shader-fx/src/materials/index.js @@ -1,5 +1,5 @@ export * from "./impl/FxMaterialImpl"; -export * from "./impl/FxBasicFxMaterialImpl"; +export * from "./impl/BasicFxMaterialImpl"; export * from "./impl/noise/NoiseMaterial"; export * from "./impl/rawBlank/RawBlankMaterial"; diff --git a/todo b/todo index 833f770a..a0cbfcb7 100644 --- a/todo +++ b/todo @@ -1,12 +1,11 @@ -- touch designerを解剖して、機能を因数分解してみる - - webglooの設計つくる - -- rename - - fxbasicfx→basicfx - - createMaterialImpl - createMaterialImplにして、引数に関数で引数にチャンクとれるみたいな。第二引数でマテリアルの種類選べるみたいな。 - 実装クラスを生成する関数 - SamplingFxMaterialの実装 - - rgbShiftなど \ No newline at end of file + - rgbShiftなど + - basicFxLibを拡張する + +- blending mode + - mixSrc,mixDstのblendingMode + - basicFxにcolor追加 From 487228cff68c848b79a3f6fad6c676357166c61e Mon Sep 17 00:00:00 2001 From: takuma-hmng8 Date: Thu, 17 Oct 2024 23:33:21 +0900 Subject: [PATCH 23/60] update --- app/v2_pipe/Playground.tsx | 5 +- .../use-shader-fx/legacy/utils/useParams.ts | 1 + .../src/materials/core/FxMaterial.ts | 8 +- .../use-shader-fx/src/misc/usePipeline.ts | 82 +++++++++++++------ 4 files changed, 63 insertions(+), 33 deletions(-) diff --git a/app/v2_pipe/Playground.tsx b/app/v2_pipe/Playground.tsx index 00982ef9..dea9bde8 100644 --- a/app/v2_pipe/Playground.tsx +++ b/app/v2_pipe/Playground.tsx @@ -91,8 +91,9 @@ export const Playground = () => { { fx: useNoise, size, - dpr: 0.1, - mixDstUvFactor: 0.2, + dpr: 0.8, + fboAutoSetSize: true, + mixDstUvFactor: 0.3, mixDstColorFactor: 0.2, } ); diff --git a/packages/use-shader-fx/legacy/utils/useParams.ts b/packages/use-shader-fx/legacy/utils/useParams.ts index a8e2f2ff..afe52ae6 100644 --- a/packages/use-shader-fx/legacy/utils/useParams.ts +++ b/packages/use-shader-fx/legacy/utils/useParams.ts @@ -18,6 +18,7 @@ export const useParams = (params: T): UseParamsReturn => { return; } for (const key in newParams) { + // hasOwnPropertyで保証するべき const paramKey = key as keyof T; if ( paramKey in paramsRef.current && diff --git a/packages/use-shader-fx/src/materials/core/FxMaterial.ts b/packages/use-shader-fx/src/materials/core/FxMaterial.ts index 5bd27839..a9780f0e 100644 --- a/packages/use-shader-fx/src/materials/core/FxMaterial.ts +++ b/packages/use-shader-fx/src/materials/core/FxMaterial.ts @@ -79,10 +79,8 @@ export class FxMaterial extends THREE.ShaderMaterial { setUniformValues(values?: { [key: string]: any }) { if (values === undefined) return; - for (const key in values) { - const newValue = values[key]; - - if (newValue === undefined) { + for (const [key, value] of Object.entries(values)) { + if (value === undefined) { console.warn( `use-shader-fx: parameter '${key}' has value of undefined.` ); @@ -98,7 +96,7 @@ export class FxMaterial extends THREE.ShaderMaterial { return; } - curretUniform.value = newValue; + curretUniform.value = value; } } diff --git a/packages/use-shader-fx/src/misc/usePipeline.ts b/packages/use-shader-fx/src/misc/usePipeline.ts index 2ec920db..d28abab6 100644 --- a/packages/use-shader-fx/src/misc/usePipeline.ts +++ b/packages/use-shader-fx/src/misc/usePipeline.ts @@ -1,5 +1,5 @@ import * as THREE from "three"; -import { useState } from "react"; +import { useCallback, useMemo, useState } from "react"; import { HooksReturn, RootState } from "../hooks/types"; import { FxTypes, FxProps } from "../hooks"; @@ -8,17 +8,19 @@ export type FxConfig = { } & FxProps; export type PipelineConfig = { - src?: number | THREE.Texture; - mixSrc?: number | THREE.Texture; - mixDst?: number | THREE.Texture; + src?: number | THREE.Texture | null; + mixSrc?: number | THREE.Texture | null; + mixDst?: number | THREE.Texture | null; }; export type PipelineValues = { - [K in keyof PipelineConfig]: THREE.Texture | undefined; + [K in keyof PipelineConfig]: THREE.Texture | null | undefined; }; const WARN_TEXT = { args: `use-shader-fx: fx and args length mismatch. fx is non-reactive; update by changing the key to reset state.`, pipeline: `use-shader-fx: fx and pipeline length mismatch. fx is non-reactive; update by changing the key to reset state.`, + pipelineValue: (val: number, pipelineIndex: number, key: string) => + `use-shader-fx: texture(index:${val}) is missing, at "${key}" of pipeline(index:${pipelineIndex}).`, }; export const usePipeline = ( @@ -42,25 +44,32 @@ export const usePipeline = ( } } - const pipeline: HooksReturn[] = []; - hooks.forEach((hook, i) => pipeline.push(hook(_args[i]))); + const pipeline = hooks.map((hook, i) => hook(_args[i])); - const render = (state: RootState) => - pipeline.forEach((fx) => fx.render(state)); - const setValues = (...values: {}[]) => - pipeline.forEach((fx, i) => fx.setValues(values[i])); + const render = useCallback( + (state: RootState) => pipeline.forEach((fx) => fx.render(state)), + [pipeline] + ); + + const setValues = useCallback( + (...values: {}[]) => pipeline.forEach((fx, i) => fx.setValues(values[i])), + [pipeline] + ); const textures = pipeline.map((fx) => fx.texture); - const setPipeline = (...args: PipelineConfig[]) => { - if (args.length !== pipeline.length) { - console.warn(WARN_TEXT.pipeline); - return; - } - args.forEach((arg, i) => - pipeline[i].setValues(getPipelineValues(arg, textures)) - ); - }; + const setPipeline = useCallback( + (...args: PipelineConfig[]) => { + if (args.length !== pipeline.length) { + console.warn(WARN_TEXT.pipeline); + return; + } + args.forEach((arg, i) => + pipeline[i].setValues(getPipelineValues(arg, textures, i)) + ); + }, + [pipeline, textures] + ); return { render, @@ -72,13 +81,34 @@ export const usePipeline = ( }; }; -function getPipelineValues(config: PipelineConfig, textures: THREE.Texture[]) { +function getPipelineValues( + config: PipelineConfig, + textures: THREE.Texture[], + pipelineIndex: number +) { const value: PipelineValues = {}; - for (const key in config) { - const _val = config[key as keyof PipelineConfig]; - if (_val != null) - value[key as keyof PipelineConfig] = - typeof _val === "number" ? textures[_val] : _val; + + for (const [key, val] of Object.entries(config)) { + const _key = key as keyof PipelineConfig; + + if (val == null) { + value[_key] = null; + break; + } + + if (typeof val === "number") { + const _tex = textures[val]; + if (!_tex) { + console.warn(WARN_TEXT.pipelineValue(val, pipelineIndex, key)); + value[_key] = null; + break; + } + value[_key] = _tex; + break; + } + + value[_key] = val; } + return value; } From b8142203ff29538417906e3d2901f568e7127630 Mon Sep 17 00:00:00 2001 From: takuma-hmng8 Date: Fri, 18 Oct 2024 10:37:49 +0900 Subject: [PATCH 24/60] update --- .../use-shader-fx/src/materials/core/BasicFxLib.ts | 5 +++-- .../materials/impl/cover/CoverTextureMaterial.ts | 3 ++- packages/use-shader-fx/src/misc/usePipeline.ts | 14 ++++++++------ 3 files changed, 13 insertions(+), 9 deletions(-) diff --git a/packages/use-shader-fx/src/materials/core/BasicFxLib.ts b/packages/use-shader-fx/src/materials/core/BasicFxLib.ts index 6d6ee7f4..5d825b31 100644 --- a/packages/use-shader-fx/src/materials/core/BasicFxLib.ts +++ b/packages/use-shader-fx/src/materials/core/BasicFxLib.ts @@ -1,18 +1,19 @@ import * as THREE from "three"; import { DefaultUniforms } from "./FxMaterial"; +import { TexturePipelineSrc } from "../../misc"; /*=============================================== basic fxを追加するときはこことShaderChunk,Libを編集する ===============================================*/ type BasicFxUniformsUnique = { // mixSrc - mixSrc: { value: THREE.Texture | null }; + mixSrc: { value: TexturePipelineSrc }; mixSrcResolution: { value: THREE.Vector2 }; mixSrcUvFactor: { value: number }; mixSrcAlphaFactor: { value: number }; mixSrcColorFactor: { value: number }; // mixDst - mixDst: { value: THREE.Texture | null }; + mixDst: { value: TexturePipelineSrc }; mixDstResolution: { value: THREE.Vector2 }; mixDstUvFactor: { value: number }; mixDstAlphaFactor: { value: number }; diff --git a/packages/use-shader-fx/src/materials/impl/cover/CoverTextureMaterial.ts b/packages/use-shader-fx/src/materials/impl/cover/CoverTextureMaterial.ts index c5ef5b47..48d3b265 100644 --- a/packages/use-shader-fx/src/materials/impl/cover/CoverTextureMaterial.ts +++ b/packages/use-shader-fx/src/materials/impl/cover/CoverTextureMaterial.ts @@ -7,10 +7,11 @@ import { BasicFxValues, ExtractUniformValue, } from "../../core/BasicFxLib"; +import { TexturePipelineSrc } from "../../../misc"; type CoverTextureUniforms = { /** */ - src: { value: THREE.Texture | null }; + src: { value: TexturePipelineSrc }; /** */ textureResolution: { value: THREE.Vector2 }; } & BasicFxUniforms; diff --git a/packages/use-shader-fx/src/misc/usePipeline.ts b/packages/use-shader-fx/src/misc/usePipeline.ts index d28abab6..e11aa595 100644 --- a/packages/use-shader-fx/src/misc/usePipeline.ts +++ b/packages/use-shader-fx/src/misc/usePipeline.ts @@ -1,19 +1,21 @@ import * as THREE from "three"; -import { useCallback, useMemo, useState } from "react"; -import { HooksReturn, RootState } from "../hooks/types"; +import { useCallback, useState } from "react"; +import { RootState } from "../hooks/types"; import { FxTypes, FxProps } from "../hooks"; export type FxConfig = { fx: T; } & FxProps; +export type TexturePipelineSrc = THREE.Texture | null; + export type PipelineConfig = { - src?: number | THREE.Texture | null; - mixSrc?: number | THREE.Texture | null; - mixDst?: number | THREE.Texture | null; + src?: number | TexturePipelineSrc; + mixSrc?: number | TexturePipelineSrc; + mixDst?: number | TexturePipelineSrc; }; export type PipelineValues = { - [K in keyof PipelineConfig]: THREE.Texture | null | undefined; + [K in keyof PipelineConfig]?: TexturePipelineSrc; }; const WARN_TEXT = { From daf3d9ca22f5c648e3f16c594722648d096409ae Mon Sep 17 00:00:00 2001 From: takuma-hmng8 Date: Fri, 18 Oct 2024 20:29:12 +0900 Subject: [PATCH 25/60] update --- app/v2_impl/Playground.tsx | 11 +- app/v2_impl_fluid_contrast/Playground.tsx | 105 ++++++++++++++++++ app/v2_impl_fluid_contrast/page.tsx | 39 +++++++ .../use-shader-fx/src/hooks/useFluid/index.ts | 7 +- .../src/materials/impl/fluid/SplatMaterial.ts | 4 +- .../src/materials/impl/fluid/index.js | 2 +- .../impl/fluid/shaders/advection.frag | 4 +- todo | 9 ++ 8 files changed, 171 insertions(+), 10 deletions(-) create mode 100644 app/v2_impl_fluid_contrast/Playground.tsx create mode 100644 app/v2_impl_fluid_contrast/page.tsx diff --git a/app/v2_impl/Playground.tsx b/app/v2_impl/Playground.tsx index aa0f1969..43593e0a 100644 --- a/app/v2_impl/Playground.tsx +++ b/app/v2_impl/Playground.tsx @@ -55,10 +55,10 @@ export const Playground = () => { // src: renderTarget.texture, // }); - // const fluid = useFluid({ - // size, - // dpr: 0.25, - // }); + const fluid = useFluid({ + size, + dpr: 0.25, + }); const noise = useNoise({ size, @@ -88,6 +88,7 @@ export const Playground = () => { noise.render(state); // blur.render(state); cover.render(state); + fluid.render(state); }); const ref = useRef(); @@ -99,7 +100,7 @@ export const Playground = () => { {createPortal( diff --git a/app/v2_impl_fluid_contrast/Playground.tsx b/app/v2_impl_fluid_contrast/Playground.tsx new file mode 100644 index 00000000..fdb2917e --- /dev/null +++ b/app/v2_impl_fluid_contrast/Playground.tsx @@ -0,0 +1,105 @@ +"use client"; + +import * as THREE from "three"; +import { useRef, useState } from "react"; +import { useFrame, useThree, extend, createPortal } from "@react-three/fiber"; +import { + useNoise, + NoiseValues, + useBlur, + useSingleFBO, + createFxMaterialImpl, + createBasicFxMaterialImpl, + FxMaterialImplValues, + BasicFxMaterialImplValues, + useFluid, + useCoverTexture, +} from "@/packages/use-shader-fx/src"; +import { Float, OrbitControls } from "@react-three/drei"; + +const FxMaterialImpl = createFxMaterialImpl({ + fragmentShader: ` + uniform sampler2D src; + + vec3 hsv2rgb(vec3 c) +{ + vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0); + vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www); + return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y); +} + +vec3 rgb2hsv(vec3 c) +{ + vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0); + vec4 p = mix(vec4(c.bg, K.wz), vec4(c.gb, K.xy), step(c.b, c.g)); + vec4 q = mix(vec4(p.xyw, c.r), vec4(c.r, p.yzx), step(p.x, c.r)); + + float d = q.x - min(q.w, q.y); + float e = 1.0e-10; + return vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x); +} + + void main() { + + vec4 fluid = texture2D(src, vUv); + vec2 vel = fluid.rg; + + // THINK つまりfluidのcolorMapは最後lenを返せばいいのか? それをを色調補正すれば以下ができるじゃない + float len = length(vel); // 0~1 + + vec3 fluidColor = vec3(len); + fluidColor.r = clamp(fluidColor.r + .2, 0., 1.); + fluidColor.b = clamp(fluidColor.b + .1, 0., 1.); + + // THINK ここまでがデフォルトのfluidのcolor + + // THINK ここからがbasicFxの色調補正 + + vec3 hsv = rgb2hsv(fluidColor); + + hsv.y *= 100.; // 彩度 + hsv.z *= 2.; // 明度 + + vec3 final = hsv2rgb(hsv); + + vec3 gamma = pow(final, vec3(1./.01)); + gamma = ((gamma-.5)*10.)+.5; + + gl_FragColor = vec4(vec3(gamma), len); + } +`, +}); +const BasicFxMaterialImpl = createBasicFxMaterialImpl(); + +extend({ FxMaterialImpl, BasicFxMaterialImpl }); + +export const Playground = () => { + const { size, viewport, camera } = useThree(); + + const fluid = useFluid({ + size, + dpr: 0.8, + }); + + useFrame((state) => { + fluid.render(state); + }); + + return ( + + + + + ); +}; + +declare global { + namespace JSX { + interface IntrinsicElements { + fxMaterialImpl: FxMaterialImplValues & + JSX.IntrinsicElements["shaderMaterial"]; + BasicFxMaterialImpl: BasicFxMaterialImplValues & + JSX.IntrinsicElements["shaderMaterial"]; + } + } +} diff --git a/app/v2_impl_fluid_contrast/page.tsx b/app/v2_impl_fluid_contrast/page.tsx new file mode 100644 index 00000000..6256d104 --- /dev/null +++ b/app/v2_impl_fluid_contrast/page.tsx @@ -0,0 +1,39 @@ +import { ShaderFx } from "../ShaderFx"; +import { Playground } from "./Playground"; +import Image from "next/image"; + +export default function Page() { + return ( +
    + {/*
    + +
    */} + + + +
    + ); +} diff --git a/packages/use-shader-fx/src/hooks/useFluid/index.ts b/packages/use-shader-fx/src/hooks/useFluid/index.ts index 6f3182e2..f7add789 100644 --- a/packages/use-shader-fx/src/hooks/useFluid/index.ts +++ b/packages/use-shader-fx/src/hooks/useFluid/index.ts @@ -18,7 +18,7 @@ export type FluidValues = { - colormapはBasicFxmaterial - params - velocity dissipation - - color dissipation (color map) + - color dissipation (color map / pressure disippation的なこと?)  ===============================================*/ }; @@ -90,6 +90,11 @@ export const useFluid = ({ pressure.material.uniforms.isBounce.value = false; }, []); + // bounce の設定 一旦OFFに + divergence.material.uniforms.isBounce.value = false; + poisson.material.uniforms.isBounce.value = false; + pressure.material.uniforms.isBounce.value = false; + const render = useCallback( (rootState: RootState, newValues?: FluidValues) => { newValues && setValues(newValues); diff --git a/packages/use-shader-fx/src/materials/impl/fluid/SplatMaterial.ts b/packages/use-shader-fx/src/materials/impl/fluid/SplatMaterial.ts index 1fbf8996..f20f5986 100644 --- a/packages/use-shader-fx/src/materials/impl/fluid/SplatMaterial.ts +++ b/packages/use-shader-fx/src/materials/impl/fluid/SplatMaterial.ts @@ -30,13 +30,13 @@ export class SplatMaterial extends FxMaterial { uniforms: { force: { value: new THREE.Vector2(0, 0) }, center: { value: new THREE.Vector2(0, 0) }, - scale: { value: new THREE.Vector2(30, 30) }, + scale: { value: new THREE.Vector2(120, 120) }, } as SplatUniforms, }); this.type = SplatMaterial.type; - this.forceBias = 30; + this.forceBias = 20; this.blending = THREE.AdditiveBlending; } diff --git a/packages/use-shader-fx/src/materials/impl/fluid/index.js b/packages/use-shader-fx/src/materials/impl/fluid/index.js index 814b29b9..4781316c 100644 --- a/packages/use-shader-fx/src/materials/impl/fluid/index.js +++ b/packages/use-shader-fx/src/materials/impl/fluid/index.js @@ -4,4 +4,4 @@ export * from "./PressureMaterial"; export * from "./PoissonMaterial"; export * from "./SplatMaterial"; -export const DeltaTime = 0.015; +export const DeltaTime = 0.01; diff --git a/packages/use-shader-fx/src/materials/impl/fluid/shaders/advection.frag b/packages/use-shader-fx/src/materials/impl/fluid/shaders/advection.frag index 03cdfe0f..31143059 100644 --- a/packages/use-shader-fx/src/materials/impl/fluid/shaders/advection.frag +++ b/packages/use-shader-fx/src/materials/impl/fluid/shaders/advection.frag @@ -1,9 +1,11 @@ uniform float dt; uniform sampler2D velocity; +float dissipation = 0.95; // TODO disipationを追加する + void main(){ vec2 vel = texture2D(velocity, vUv).xy; vec2 uv2 = vUv - vel * dt * maxAspect; vec2 newVel = texture2D(velocity, uv2).xy; - gl_FragColor = vec4(newVel, 0.0, 0.0); + gl_FragColor = vec4(dissipation * newVel, 0.0, 0.0); } \ No newline at end of file diff --git a/todo b/todo index a0cbfcb7..a06258c3 100644 --- a/todo +++ b/todo @@ -9,3 +9,12 @@ - blending mode - mixSrc,mixDstのblendingMode - basicFxにcolor追加 + + + +- 粘性の追加 +- advectionのdisipationを追加する +- deltaTimeも操作できるように +- コントラストを強めてみて + - これの、aboutページみたいにできるはずなんだけどな + - https://www.hatom.com/ \ No newline at end of file From 1962f05cf68eb0e8857b9df5a40f04373077886d Mon Sep 17 00:00:00 2001 From: takuma-hmng8 Date: Mon, 21 Oct 2024 19:52:04 +0900 Subject: [PATCH 26/60] update --- app/v2_impl_fluid_contrast/Playground.tsx | 45 ++++++++++++------- .../src/materials/impl/fluid/SplatMaterial.ts | 2 +- .../src/materials/impl/fluid/index.js | 2 +- .../impl/fluid/shaders/advection.frag | 2 +- todo | 19 ++++---- 5 files changed, 44 insertions(+), 26 deletions(-) diff --git a/app/v2_impl_fluid_contrast/Playground.tsx b/app/v2_impl_fluid_contrast/Playground.tsx index fdb2917e..a5db9bc3 100644 --- a/app/v2_impl_fluid_contrast/Playground.tsx +++ b/app/v2_impl_fluid_contrast/Playground.tsx @@ -44,28 +44,43 @@ vec3 rgb2hsv(vec3 c) vec4 fluid = texture2D(src, vUv); vec2 vel = fluid.rg; - // THINK つまりfluidのcolorMapは最後lenを返せばいいのか? それをを色調補正すれば以下ができるじゃない float len = length(vel); // 0~1 - vec3 fluidColor = vec3(len); - fluidColor.r = clamp(fluidColor.r + .2, 0., 1.); - fluidColor.b = clamp(fluidColor.b + .1, 0., 1.); - + vec4 fluidColor = vec4(len); + + // color overlay + fluidColor.r *= clamp(fluidColor.r * .2, 0., 1.); + fluidColor.g *= clamp(fluidColor.g * .1, 0., 1.); + fluidColor.b *= clamp(fluidColor.b * .8, 0., 1.); // THINK ここまでがデフォルトのfluidのcolor - + // THINK ここからがbasicFxの色調補正 + // THINK ガンマ補正とコントラストはvec4でやればいいのかも + + // ガンマ補正 + float gammaFactor = .4; + vec4 gamma = pow(fluidColor, vec4(1./gammaFactor)); + // コントラスト + float contrastFactor = 1.; + vec4 contrast = clamp(((gamma-.5)*contrastFactor)+.5, 0., 1.); + + vec4 outputColor = contrast; - vec3 hsv = rgb2hsv(fluidColor); + // color overlay + outputColor.r *= clamp(outputColor.r * 1.2, 0., 1.); + outputColor.g *= clamp(outputColor.g * .4, 0., 1.); + outputColor.b *= clamp(outputColor.b * .9, 0., 1.); - hsv.y *= 100.; // 彩度 + // 彩度と明度 + vec3 hsv = rgb2hsv(outputColor.rgb); + hsv.y *= 2.4; // 彩度 hsv.z *= 2.; // 明度 + outputColor.rgb = hsv2rgb(hsv); - vec3 final = hsv2rgb(hsv); - - vec3 gamma = pow(final, vec3(1./.01)); - gamma = ((gamma-.5)*10.)+.5; - - gl_FragColor = vec4(vec3(gamma), len); + // alpha TODO * transparentを選択できるようにする? + float alpha = outputColor.a; + // float alpha = 1.; + gl_FragColor = vec4(outputColor.rgb, alpha); } `, }); @@ -78,7 +93,7 @@ export const Playground = () => { const fluid = useFluid({ size, - dpr: 0.8, + dpr: 0.6, }); useFrame((state) => { diff --git a/packages/use-shader-fx/src/materials/impl/fluid/SplatMaterial.ts b/packages/use-shader-fx/src/materials/impl/fluid/SplatMaterial.ts index f20f5986..73384f30 100644 --- a/packages/use-shader-fx/src/materials/impl/fluid/SplatMaterial.ts +++ b/packages/use-shader-fx/src/materials/impl/fluid/SplatMaterial.ts @@ -36,7 +36,7 @@ export class SplatMaterial extends FxMaterial { this.type = SplatMaterial.type; - this.forceBias = 20; + this.forceBias = 30; this.blending = THREE.AdditiveBlending; } diff --git a/packages/use-shader-fx/src/materials/impl/fluid/index.js b/packages/use-shader-fx/src/materials/impl/fluid/index.js index 4781316c..15d84156 100644 --- a/packages/use-shader-fx/src/materials/impl/fluid/index.js +++ b/packages/use-shader-fx/src/materials/impl/fluid/index.js @@ -4,4 +4,4 @@ export * from "./PressureMaterial"; export * from "./PoissonMaterial"; export * from "./SplatMaterial"; -export const DeltaTime = 0.01; +export const DeltaTime = 0.008; diff --git a/packages/use-shader-fx/src/materials/impl/fluid/shaders/advection.frag b/packages/use-shader-fx/src/materials/impl/fluid/shaders/advection.frag index 31143059..7eb67db5 100644 --- a/packages/use-shader-fx/src/materials/impl/fluid/shaders/advection.frag +++ b/packages/use-shader-fx/src/materials/impl/fluid/shaders/advection.frag @@ -1,7 +1,7 @@ uniform float dt; uniform sampler2D velocity; -float dissipation = 0.95; // TODO disipationを追加する +float dissipation = .99; // TODO disipationを追加する void main(){ vec2 vel = texture2D(velocity, vUv).xy; diff --git a/todo b/todo index a06258c3..0ec84b05 100644 --- a/todo +++ b/todo @@ -6,15 +6,18 @@ - rgbShiftなど - basicFxLibを拡張する -- blending mode +- basic fx - mixSrc,mixDstのblendingMode - - basicFxにcolor追加 + - basicFxに色調補正 + - fluid contrastを参考に + - micSrc => 色調補正系 => micDstの順 + +- fluid + - 粘性の追加 + - advectionのdisipationを追加する + - deltaTimeも操作できるように + - transparencyを選択できるように + - transparencyにして、0~1でmixする方式で -- 粘性の追加 -- advectionのdisipationを追加する -- deltaTimeも操作できるように -- コントラストを強めてみて - - これの、aboutページみたいにできるはずなんだけどな - - https://www.hatom.com/ \ No newline at end of file From a1bf5c45b087f96619ad4d1905c623fe513240b6 Mon Sep 17 00:00:00 2001 From: takuma-hmng8 Date: Mon, 21 Oct 2024 22:05:35 +0900 Subject: [PATCH 27/60] update --- app/v2_impl_fluid_contrast/Playground.tsx | 40 +++++++++++++++++------ todo | 30 +++++++++++++---- 2 files changed, 53 insertions(+), 17 deletions(-) diff --git a/app/v2_impl_fluid_contrast/Playground.tsx b/app/v2_impl_fluid_contrast/Playground.tsx index a5db9bc3..559642f5 100644 --- a/app/v2_impl_fluid_contrast/Playground.tsx +++ b/app/v2_impl_fluid_contrast/Playground.tsx @@ -49,31 +49,51 @@ vec3 rgb2hsv(vec3 c) vec4 fluidColor = vec4(len); // color overlay - fluidColor.r *= clamp(fluidColor.r * .2, 0., 1.); - fluidColor.g *= clamp(fluidColor.g * .1, 0., 1.); - fluidColor.b *= clamp(fluidColor.b * .8, 0., 1.); + fluidColor.r *= clamp(fluidColor.r * 1.1, 0., 1.); + fluidColor.g *= clamp(fluidColor.g * 0.2, 0., 1.); + fluidColor.b *= clamp(fluidColor.b * .6, 0., 1.); // THINK ここまでがデフォルトのfluidのcolor // THINK ここからがbasicFxの色調補正 // THINK ガンマ補正とコントラストはvec4でやればいいのかも + // レベル補正 + + // float gammaFactor = .0; + // vec4 gamma = pow(fluidColor, vec4(1./gammaFactor)); + + float u_shadows = 1.2; // シャドウ値 (0.0 〜 1.0) + float u_midtones = 1.1; // ミッドトーン値 (0.0 〜 1.0) + float u_highlights = 1.4; // ハイライト値 (0.0 〜 1.0) + float u_outputMin = 0.0; // 出力の最小値 (0.0 〜 1.0) + float u_outputMax = 1.0; // 出力の最大値 (0.0 〜 1.0) + + // 入力レベル補正 + vec4 correctedColor = (fluidColor - vec4(u_shadows)) / (vec4(u_highlights) - vec4(u_shadows)); + // ガンマ補正 - float gammaFactor = .4; - vec4 gamma = pow(fluidColor, vec4(1./gammaFactor)); + correctedColor = pow(correctedColor, vec4(1.0 / u_midtones)); + + // 出力レベル補正 + correctedColor = correctedColor * (vec4(u_outputMax) - vec4(u_outputMin)) + vec4(u_outputMin); + + vec4 gamma = correctedColor; + + // コントラスト - float contrastFactor = 1.; + float contrastFactor = 20.; vec4 contrast = clamp(((gamma-.5)*contrastFactor)+.5, 0., 1.); vec4 outputColor = contrast; // color overlay - outputColor.r *= clamp(outputColor.r * 1.2, 0., 1.); - outputColor.g *= clamp(outputColor.g * .4, 0., 1.); - outputColor.b *= clamp(outputColor.b * .9, 0., 1.); + outputColor.r *= clamp(outputColor.r * 2., 0., 1.); + outputColor.g *= clamp(outputColor.g * 1., 0., 1.); + outputColor.b *= clamp(outputColor.b * 1., 0., 1.); // 彩度と明度 vec3 hsv = rgb2hsv(outputColor.rgb); - hsv.y *= 2.4; // 彩度 + hsv.y *= 1.; // 彩度 hsv.z *= 2.; // 明度 outputColor.rgb = hsv2rgb(hsv); diff --git a/todo b/todo index 0ec84b05..7702ee89 100644 --- a/todo +++ b/todo @@ -6,18 +6,34 @@ - rgbShiftなど - basicFxLibを拡張する +- fluid + - advectionのdisipationを追加する + - deltaTimeも操作できるように + - transparencyを選択できるように + - transparencyにして、0~1でmixする方式で + - 粘性の追加 + - basic fx + - valueをオブジェクトにする仕組み + - 変数が多くなって変数名が冗長になるため - mixSrc,mixDstのblendingMode - basicFxに色調補正 - fluid contrastを参考に - micSrc => 色調補正系 => micDstの順 -- fluid - - 粘性の追加 - - advectionのdisipationを追加する - - deltaTimeも操作できるように - - transparencyを選択できるように - - transparencyにして、0~1でmixする方式で - +### mix +- mixSrc +- mixDst +### color adjustments +- duotone +- saturation +- brightness +- contrast +- levels +- colorBalance +- threshold +- posterization +### misc +- vignette \ No newline at end of file From edeea4caaafee9a5c6e4b2e927298b73dce74bf1 Mon Sep 17 00:00:00 2001 From: takuma-hmng8 Date: Wed, 23 Oct 2024 13:15:34 +0900 Subject: [PATCH 28/60] update --- app/v2_impl/Playground.tsx | 6 +- .../Playground.tsx | 84 +++++++++++++------ .../page.tsx | 0 app/v2_pipe/Playground.tsx | 10 ++- packages/use-shader-fx/src/libs/constants.ts | 21 +++++ .../shaders/ShaderChunk/mixDst_fragment.glsl | 9 -- .../ShaderChunk/mixDst_pars_fragment.glsl | 7 -- .../ShaderChunk/mixSrc_fragment_begin.glsl | 6 -- .../ShaderChunk/mixSrc_pars_fragment.glsl | 7 -- .../src/materials/core/BasicFxLib.ts | 56 +++++++------ .../src/materials/core/BasicFxMaterial.ts | 2 +- .../src/materials/core/FxMaterial.ts | 47 +++++------ .../src/materials/impl/BasicFxMaterialImpl.ts | 14 ++-- .../src/materials/impl/FxMaterialImpl.ts | 10 ++- .../src/materials/impl/blur/BlurMaterial.ts | 12 ++- .../src/materials/impl/blur/blur.glsl.ts | 2 +- .../impl/cover/CoverTextureMaterial.ts | 9 +- .../materials/impl/cover/coverTexture.glsl.ts | 2 +- .../src/materials/impl/noise/NoiseMaterial.ts | 9 +- .../src/materials/impl/noise/noise.glsl.ts | 2 +- .../use-shader-fx/src/misc/usePipeline.ts | 43 ++++++---- .../src/{libs => }/shaders/ShaderChunk.ts | 0 .../ShaderChunk/default_pars_fragment.glsl | 0 .../ShaderChunk/default_pars_vertex.glsl | 0 .../shaders/ShaderChunk/default_vertex.glsl | 0 .../shaders/ShaderChunk/mixDst_fragment.glsl | 9 ++ .../ShaderChunk/mixDst_pars_fragment.glsl | 7 ++ .../ShaderChunk/mixDst_pars_vertex.glsl | 2 +- .../shaders/ShaderChunk/mixDst_vertex.glsl | 2 +- .../ShaderChunk/mixSrc_fragment_begin.glsl | 6 ++ .../ShaderChunk/mixSrc_fragment_end.glsl | 4 +- .../ShaderChunk/mixSrc_pars_fragment.glsl | 7 ++ .../ShaderChunk/mixSrc_pars_vertex.glsl | 2 +- .../shaders/ShaderChunk/mixSrc_vertex.glsl | 2 +- .../shaders/ShaderChunk/plane_vertex.glsl | 0 .../src/{libs => }/shaders/ShaderLib.ts | 0 .../ShaderLib/basicFx_fragment_begin.glsl | 0 .../ShaderLib/basicFx_fragment_end.glsl | 0 .../ShaderLib/basicFx_pars_fragment.glsl | 0 .../ShaderLib/basicFx_pars_vertex.glsl | 0 .../shaders/ShaderLib/basicFx_vertex.glsl | 0 .../ShaderLib/default_pars_fragment.glsl | 0 .../ShaderLib/default_pars_vertex.glsl | 0 .../shaders/ShaderLib/default_vertex.glsl | 0 .../shaders/ShaderLib/plane_vertex.glsl | 0 .../src/{libs => }/shaders/mergeShaderLib.ts | 0 .../src/{libs => }/shaders/resolveShaders.ts | 0 .../src/shaders/uniformsUtils.ts | 66 +++++++++++++++ packages/use-shader-fx/src/utils/warn.ts | 7 ++ todo | 22 +---- 50 files changed, 303 insertions(+), 191 deletions(-) rename app/{v2_impl_fluid_contrast => v2_impl_colorAdjustments}/Playground.tsx (55%) rename app/{v2_impl_fluid_contrast => v2_impl_colorAdjustments}/page.tsx (100%) delete mode 100644 packages/use-shader-fx/src/libs/shaders/ShaderChunk/mixDst_fragment.glsl delete mode 100644 packages/use-shader-fx/src/libs/shaders/ShaderChunk/mixDst_pars_fragment.glsl delete mode 100644 packages/use-shader-fx/src/libs/shaders/ShaderChunk/mixSrc_fragment_begin.glsl delete mode 100644 packages/use-shader-fx/src/libs/shaders/ShaderChunk/mixSrc_pars_fragment.glsl rename packages/use-shader-fx/src/{libs => }/shaders/ShaderChunk.ts (100%) rename packages/use-shader-fx/src/{libs => }/shaders/ShaderChunk/default_pars_fragment.glsl (100%) rename packages/use-shader-fx/src/{libs => }/shaders/ShaderChunk/default_pars_vertex.glsl (100%) rename packages/use-shader-fx/src/{libs => }/shaders/ShaderChunk/default_vertex.glsl (100%) create mode 100644 packages/use-shader-fx/src/shaders/ShaderChunk/mixDst_fragment.glsl create mode 100644 packages/use-shader-fx/src/shaders/ShaderChunk/mixDst_pars_fragment.glsl rename packages/use-shader-fx/src/{libs => }/shaders/ShaderChunk/mixDst_pars_vertex.glsl (63%) rename packages/use-shader-fx/src/{libs => }/shaders/ShaderChunk/mixDst_vertex.glsl (78%) create mode 100644 packages/use-shader-fx/src/shaders/ShaderChunk/mixSrc_fragment_begin.glsl rename packages/use-shader-fx/src/{libs => }/shaders/ShaderChunk/mixSrc_fragment_end.glsl (51%) create mode 100644 packages/use-shader-fx/src/shaders/ShaderChunk/mixSrc_pars_fragment.glsl rename packages/use-shader-fx/src/{libs => }/shaders/ShaderChunk/mixSrc_pars_vertex.glsl (63%) rename packages/use-shader-fx/src/{libs => }/shaders/ShaderChunk/mixSrc_vertex.glsl (78%) rename packages/use-shader-fx/src/{libs => }/shaders/ShaderChunk/plane_vertex.glsl (100%) rename packages/use-shader-fx/src/{libs => }/shaders/ShaderLib.ts (100%) rename packages/use-shader-fx/src/{libs => }/shaders/ShaderLib/basicFx_fragment_begin.glsl (100%) rename packages/use-shader-fx/src/{libs => }/shaders/ShaderLib/basicFx_fragment_end.glsl (100%) rename packages/use-shader-fx/src/{libs => }/shaders/ShaderLib/basicFx_pars_fragment.glsl (100%) rename packages/use-shader-fx/src/{libs => }/shaders/ShaderLib/basicFx_pars_vertex.glsl (100%) rename packages/use-shader-fx/src/{libs => }/shaders/ShaderLib/basicFx_vertex.glsl (100%) rename packages/use-shader-fx/src/{libs => }/shaders/ShaderLib/default_pars_fragment.glsl (100%) rename packages/use-shader-fx/src/{libs => }/shaders/ShaderLib/default_pars_vertex.glsl (100%) rename packages/use-shader-fx/src/{libs => }/shaders/ShaderLib/default_vertex.glsl (100%) rename packages/use-shader-fx/src/{libs => }/shaders/ShaderLib/plane_vertex.glsl (100%) rename packages/use-shader-fx/src/{libs => }/shaders/mergeShaderLib.ts (100%) rename packages/use-shader-fx/src/{libs => }/shaders/resolveShaders.ts (100%) create mode 100644 packages/use-shader-fx/src/shaders/uniformsUtils.ts create mode 100644 packages/use-shader-fx/src/utils/warn.ts diff --git a/app/v2_impl/Playground.tsx b/app/v2_impl/Playground.tsx index 43593e0a..a4fae91a 100644 --- a/app/v2_impl/Playground.tsx +++ b/app/v2_impl/Playground.tsx @@ -74,8 +74,10 @@ export const Playground = () => { size, dpr: 1, src: renderTarget.texture, - mixSrc: noise.texture, - mixSrcUvFactor: 0.2, + mixSrc: { + src: noise.texture, + uvFactor: 0.2, + }, }); // noise.setValues({ diff --git a/app/v2_impl_fluid_contrast/Playground.tsx b/app/v2_impl_colorAdjustments/Playground.tsx similarity index 55% rename from app/v2_impl_fluid_contrast/Playground.tsx rename to app/v2_impl_colorAdjustments/Playground.tsx index 559642f5..063fc8c5 100644 --- a/app/v2_impl_fluid_contrast/Playground.tsx +++ b/app/v2_impl_colorAdjustments/Playground.tsx @@ -15,7 +15,7 @@ import { useFluid, useCoverTexture, } from "@/packages/use-shader-fx/src"; -import { Float, OrbitControls } from "@react-three/drei"; +import { Float, OrbitControls, useTexture } from "@react-three/drei"; const FxMaterialImpl = createFxMaterialImpl({ fragmentShader: ` @@ -43,12 +43,10 @@ vec3 rgb2hsv(vec3 c) vec4 fluid = texture2D(src, vUv); vec2 vel = fluid.rg; - float len = length(vel); // 0~1 - vec4 fluidColor = vec4(len); - - // color overlay + + // color balance fluidColor.r *= clamp(fluidColor.r * 1.1, 0., 1.); fluidColor.g *= clamp(fluidColor.g * 0.2, 0., 1.); fluidColor.b *= clamp(fluidColor.b * .6, 0., 1.); @@ -56,47 +54,77 @@ vec3 rgb2hsv(vec3 c) // THINK ここからがbasicFxの色調補正 // THINK ガンマ補正とコントラストはvec4でやればいいのかも + + vec4 outputColor = fluidColor; + /*=============================================== // レベル補正 - - // float gammaFactor = .0; - // vec4 gamma = pow(fluidColor, vec4(1./gammaFactor)); - - float u_shadows = 1.2; // シャドウ値 (0.0 〜 1.0) - float u_midtones = 1.1; // ミッドトーン値 (0.0 〜 1.0) - float u_highlights = 1.4; // ハイライト値 (0.0 〜 1.0) - float u_outputMin = 0.0; // 出力の最小値 (0.0 〜 1.0) - float u_outputMax = 1.0; // 出力の最大値 (0.0 〜 1.0) + ===============================================*/ + float u_shadows = 1.2; // シャドウ値 + float u_midtones = 1.1; // ミッドトーン値 + float u_highlights = 1.4; // ハイライト値 + float u_outputMin = 0.0; // 出力の最小値 + float u_outputMax = 1.0; // 出力の最大値 // 入力レベル補正 - vec4 correctedColor = (fluidColor - vec4(u_shadows)) / (vec4(u_highlights) - vec4(u_shadows)); + outputColor = (outputColor - vec4(u_shadows)) / (vec4(u_highlights) - vec4(u_shadows)); // ガンマ補正 - correctedColor = pow(correctedColor, vec4(1.0 / u_midtones)); + outputColor = pow(outputColor, vec4(1.0 / u_midtones)); // 出力レベル補正 - correctedColor = correctedColor * (vec4(u_outputMax) - vec4(u_outputMin)) + vec4(u_outputMin); - - vec4 gamma = correctedColor; - - + outputColor = outputColor * (vec4(u_outputMax) - vec4(u_outputMin)) + vec4(u_outputMin); + /*=============================================== + // コントラスト + ===============================================*/ // コントラスト float contrastFactor = 20.; - vec4 contrast = clamp(((gamma-.5)*contrastFactor)+.5, 0., 1.); - - vec4 outputColor = contrast; + outputColor = clamp(((outputColor-.5)*contrastFactor)+.5, 0., 1.); - // color overlay - outputColor.r *= clamp(outputColor.r * 2., 0., 1.); + /*=============================================== + // color balance + ===============================================*/ + outputColor.r *= clamp(outputColor.r * 1., 0., 1.); outputColor.g *= clamp(outputColor.g * 1., 0., 1.); outputColor.b *= clamp(outputColor.b * 1., 0., 1.); - // 彩度と明度 + /*=============================================== + // saturation・brightness + ===============================================*/ vec3 hsv = rgb2hsv(outputColor.rgb); hsv.y *= 1.; // 彩度 hsv.z *= 2.; // 明度 outputColor.rgb = hsv2rgb(hsv); + /*=============================================== + // ポスタライゼーション + ===============================================*/ + float posterizationLevels = 6.; + outputColor.rgb = floor(outputColor.rgb * posterizationLevels) / posterizationLevels; + + /*=============================================== + // black&White + ===============================================*/ + float redWeight = 0.; + float greenWeight = 0.; + float blueWeight = 0.; + float grayscale = dot(outputColor.rgb, vec3(0.299 + redWeight, 0.587 + greenWeight, 0.114 + blueWeight)); + + outputColor.rgb = vec3(grayscale); + + /*=============================================== + // duo tone + ===============================================*/ + vec3 color0 = vec3(0.45, .5, 0.534); + vec3 color1 = vec3(.3, 0.876, 0.579); + // outputColor.rgb = mix(color0, color1, grayscale); + + /*=============================================== + // threshold + ===============================================*/ + float threshold = 0.4; + // outputColor.rgb = grayscale > threshold ? vec3(1.) : vec3(0.); + // alpha TODO * transparentを選択できるようにする? float alpha = outputColor.a; // float alpha = 1.; @@ -111,6 +139,8 @@ extend({ FxMaterialImpl, BasicFxMaterialImpl }); export const Playground = () => { const { size, viewport, camera } = useThree(); + const [funkun] = useTexture(["/funkun.jpg"]); + const fluid = useFluid({ size, dpr: 0.6, diff --git a/app/v2_impl_fluid_contrast/page.tsx b/app/v2_impl_colorAdjustments/page.tsx similarity index 100% rename from app/v2_impl_fluid_contrast/page.tsx rename to app/v2_impl_colorAdjustments/page.tsx diff --git a/app/v2_pipe/Playground.tsx b/app/v2_pipe/Playground.tsx index dea9bde8..1ec0a7b7 100644 --- a/app/v2_pipe/Playground.tsx +++ b/app/v2_pipe/Playground.tsx @@ -86,19 +86,21 @@ export const Playground = () => { { fx: useFluid, size, - dpr: 0.2, + dpr: 0.5, }, { fx: useNoise, size, dpr: 0.8, fboAutoSetSize: true, - mixDstUvFactor: 0.3, - mixDstColorFactor: 0.2, + mixSrc: { + uvFactor: 0.7, + colorFactor: 0.2, + }, } ); - setPipeline({}, { mixDst: 0 }); + setPipeline({}, { mixSrc: 0 }); useFrame((state) => render(state)); diff --git a/packages/use-shader-fx/src/libs/constants.ts b/packages/use-shader-fx/src/libs/constants.ts index ab338087..78e950be 100644 --- a/packages/use-shader-fx/src/libs/constants.ts +++ b/packages/use-shader-fx/src/libs/constants.ts @@ -14,3 +14,24 @@ export const DEFAULT_TEXTURE = new THREE.DataTexture( 1, THREE.RGBAFormat ); + +export const APP_NAME = "use-shader-fx"; + +export const THREE_TYPES = new Set([ + THREE.Color, + THREE.Matrix3, + THREE.Matrix4, + THREE.Vector2, + THREE.Vector3, + THREE.Vector4, + THREE.Texture, + THREE.Quaternion, + THREE.WebGLRenderTarget, + THREE.Euler, + THREE.BufferGeometry, + THREE.Material, + THREE.Camera, + THREE.Light, + THREE.Object3D, + THREE.Bone, +]); diff --git a/packages/use-shader-fx/src/libs/shaders/ShaderChunk/mixDst_fragment.glsl b/packages/use-shader-fx/src/libs/shaders/ShaderChunk/mixDst_fragment.glsl deleted file mode 100644 index 28b78a3f..00000000 --- a/packages/use-shader-fx/src/libs/shaders/ShaderChunk/mixDst_fragment.glsl +++ /dev/null @@ -1,9 +0,0 @@ -#ifdef USF_USE_MIXDST - - vec4 mixDstColor = texture2D(mixDst, mix(vMixDstCoverUv,usf_FragColor.rg,mixDstUvFactor)); - - usf_FragColor = mix(usf_FragColor, mixDstColor, mixDstColorFactor); - - usf_FragColor = mix(usf_FragColor, mixDstColor, mixDstColor.a * mixDstAlphaFactor); - -#endif \ No newline at end of file diff --git a/packages/use-shader-fx/src/libs/shaders/ShaderChunk/mixDst_pars_fragment.glsl b/packages/use-shader-fx/src/libs/shaders/ShaderChunk/mixDst_pars_fragment.glsl deleted file mode 100644 index c8e1277c..00000000 --- a/packages/use-shader-fx/src/libs/shaders/ShaderChunk/mixDst_pars_fragment.glsl +++ /dev/null @@ -1,7 +0,0 @@ -#ifdef USF_USE_MIXDST - varying vec2 vMixDstCoverUv; - uniform sampler2D mixDst; - uniform float mixDstUvFactor; - uniform float mixDstAlphaFactor; - uniform float mixDstColorFactor; -#endif \ No newline at end of file diff --git a/packages/use-shader-fx/src/libs/shaders/ShaderChunk/mixSrc_fragment_begin.glsl b/packages/use-shader-fx/src/libs/shaders/ShaderChunk/mixSrc_fragment_begin.glsl deleted file mode 100644 index 7b9bd1de..00000000 --- a/packages/use-shader-fx/src/libs/shaders/ShaderChunk/mixSrc_fragment_begin.glsl +++ /dev/null @@ -1,6 +0,0 @@ -#ifdef USF_USE_MIXSRC - - vec4 mixSrcColor = texture2D(mixSrc, vMixSrcCoverUv); - usf_Uv = mix(usf_Uv, mixSrcColor.rg, mixSrcUvFactor); - -#endif \ No newline at end of file diff --git a/packages/use-shader-fx/src/libs/shaders/ShaderChunk/mixSrc_pars_fragment.glsl b/packages/use-shader-fx/src/libs/shaders/ShaderChunk/mixSrc_pars_fragment.glsl deleted file mode 100644 index 618c161a..00000000 --- a/packages/use-shader-fx/src/libs/shaders/ShaderChunk/mixSrc_pars_fragment.glsl +++ /dev/null @@ -1,7 +0,0 @@ -#ifdef USF_USE_MIXSRC - varying vec2 vMixSrcCoverUv; - uniform sampler2D mixSrc; - uniform float mixSrcUvFactor; - uniform float mixSrcAlphaFactor; - uniform float mixSrcColorFactor; -#endif \ No newline at end of file diff --git a/packages/use-shader-fx/src/materials/core/BasicFxLib.ts b/packages/use-shader-fx/src/materials/core/BasicFxLib.ts index 5d825b31..12ee7c5e 100644 --- a/packages/use-shader-fx/src/materials/core/BasicFxLib.ts +++ b/packages/use-shader-fx/src/materials/core/BasicFxLib.ts @@ -1,45 +1,46 @@ import * as THREE from "three"; import { DefaultUniforms } from "./FxMaterial"; import { TexturePipelineSrc } from "../../misc"; +import { + NestUniformValues, + flattenUniformValues, +} from "../../shaders/uniformsUtils"; /*=============================================== basic fxを追加するときはこことShaderChunk,Libを編集する ===============================================*/ type BasicFxUniformsUnique = { // mixSrc - mixSrc: { value: TexturePipelineSrc }; - mixSrcResolution: { value: THREE.Vector2 }; - mixSrcUvFactor: { value: number }; - mixSrcAlphaFactor: { value: number }; - mixSrcColorFactor: { value: number }; + mixSrc_src: { value: TexturePipelineSrc }; + mixSrc_resolution: { value: THREE.Vector2 }; + mixSrc_uvFactor: { value: number }; + mixSrc_alphaFactor: { value: number }; + mixSrc_colorFactor: { value: number }; // mixDst - mixDst: { value: TexturePipelineSrc }; - mixDstResolution: { value: THREE.Vector2 }; - mixDstUvFactor: { value: number }; - mixDstAlphaFactor: { value: number }; - mixDstColorFactor: { value: number }; + mixDst_src: { value: TexturePipelineSrc }; + mixDst_resolution: { value: THREE.Vector2 }; + mixDst_uvFactor: { value: number }; + mixDst_alphaFactor: { value: number }; + mixDst_colorFactor: { value: number }; }; const DEFAULT_BASICFX_VALUES: BasicFxUniformsUnique = { // mixSrc - mixSrc: { value: null }, - mixSrcResolution: { value: new THREE.Vector2() }, - mixSrcUvFactor: { value: 0 }, - mixSrcAlphaFactor: { value: 0 }, - mixSrcColorFactor: { value: 0 }, + mixSrc_src: { value: null }, + mixSrc_resolution: { value: new THREE.Vector2() }, + mixSrc_uvFactor: { value: 0 }, + mixSrc_alphaFactor: { value: 0 }, + mixSrc_colorFactor: { value: 0 }, // mixDst - mixDst: { value: null }, - mixDstResolution: { value: new THREE.Vector2() }, - mixDstUvFactor: { value: 0 }, - mixDstAlphaFactor: { value: 0 }, - mixDstColorFactor: { value: 0 }, + mixDst_src: { value: null }, + mixDst_resolution: { value: new THREE.Vector2() }, + mixDst_uvFactor: { value: 0 }, + mixDst_alphaFactor: { value: 0 }, + mixDst_colorFactor: { value: 0 }, }; export type BasicFxUniforms = BasicFxUniformsUnique & DefaultUniforms; -export type ExtractUniformValue = { - [K in keyof T]?: T[K] extends { value: infer U } ? U : never; -}; -export type BasicFxValues = ExtractUniformValue; +export type BasicFxValues = NestUniformValues; export type BasicFxFlag = { mixSrc: boolean; @@ -49,7 +50,8 @@ export type BasicFxFlag = { /** valuesのkeyにbasicFxが含まれているかどうかの判定 */ function containsBasicFxValues(values?: { [key: string]: any }): boolean { if (!values) return false; - return Object.keys(values).some((key) => + const _values = flattenUniformValues(values); + return Object.keys(_values).some((key) => Object.keys(DEFAULT_BASICFX_VALUES).includes(key as keyof BasicFxValues) ); } @@ -68,8 +70,8 @@ function handleUpdateBasicFx( validCount: number; updatedFlag: BasicFxFlag; } { - const isMixSrc = uniforms.mixSrc.value ? true : false; - const isMixDst = uniforms.mixDst.value ? true : false; + const isMixSrc = uniforms.mixSrc_src.value ? true : false; + const isMixDst = uniforms.mixDst_src.value ? true : false; const { mixSrc, mixDst } = basicFxFlag; diff --git a/packages/use-shader-fx/src/materials/core/BasicFxMaterial.ts b/packages/use-shader-fx/src/materials/core/BasicFxMaterial.ts index 76d05e25..c1c4f1da 100644 --- a/packages/use-shader-fx/src/materials/core/BasicFxMaterial.ts +++ b/packages/use-shader-fx/src/materials/core/BasicFxMaterial.ts @@ -6,7 +6,7 @@ import { BasicFxFlag, BasicFxLib, } from "./BasicFxLib"; -import { mergeShaderLib } from "../../libs/shaders/mergeShaderLib"; +import { mergeShaderLib } from "../../shaders/mergeShaderLib"; export class BasicFxMaterial extends FxMaterial { public static readonly key: string = THREE.MathUtils.generateUUID(); diff --git a/packages/use-shader-fx/src/materials/core/FxMaterial.ts b/packages/use-shader-fx/src/materials/core/FxMaterial.ts index a9780f0e..d567b272 100644 --- a/packages/use-shader-fx/src/materials/core/FxMaterial.ts +++ b/packages/use-shader-fx/src/materials/core/FxMaterial.ts @@ -1,6 +1,11 @@ import * as THREE from "three"; -import { resolveIncludes } from "../../libs/shaders/resolveShaders"; -import { mergeShaderLib } from "../../libs/shaders/mergeShaderLib"; +import { resolveIncludes } from "../../shaders/resolveShaders"; +import { mergeShaderLib } from "../../shaders/mergeShaderLib"; +import { + flattenUniformValues, + ShaderWithUniforms, +} from "../../shaders/uniformsUtils"; +import { warn } from "../../utils/warn"; export type DefaultUniforms = { resolution: { value: THREE.Vector2 }; @@ -9,14 +14,6 @@ export type DefaultUniforms = { maxAspect: { value: THREE.Vector2 }; }; -export type Uniforms = { [uniform: string]: THREE.IUniform }; - -export type ShaderWithUniforms = { - uniforms?: Uniforms; - vertexShader?: string; - fragmentShader?: string; -}; - export type FxMaterialProps = { uniformValues?: T; materialParameters?: {}; @@ -78,22 +75,19 @@ export class FxMaterial extends THREE.ShaderMaterial { setUniformValues(values?: { [key: string]: any }) { if (values === undefined) return; + const _values = flattenUniformValues(values); - for (const [key, value] of Object.entries(values)) { + for (const [key, value] of Object.entries(_values)) { if (value === undefined) { - console.warn( - `use-shader-fx: parameter '${key}' has value of undefined.` - ); + warn(`parameter '${key}' has value of undefined.`); continue; } const curretUniform = this.uniforms[key]; if (curretUniform === undefined) { - console.warn( - `use-shader-fx: '${key}' is not a uniform property of ${this.type}.` - ); - return; + warn(`'${key}' is not a uniform property of ${this.type}.`); + continue; } curretUniform.value = value; @@ -102,20 +96,17 @@ export class FxMaterial extends THREE.ShaderMaterial { /** define getter/setters */ defineUniformAccessors(onSet?: () => void) { - const entries = Object.entries(this.uniforms); - entries.forEach(([name]) => { - if (this.hasOwnProperty(name)) { - // skip if already defined - return; + for (const key of Object.keys(this.uniforms)) { + if (this.hasOwnProperty(key)) { + continue; } - - Object.defineProperty(this, name, { - get: () => this.uniforms[name].value, + Object.defineProperty(this, key, { + get: () => this.uniforms[key].value, set: (v) => { - this.uniforms[name].value = v; + this.uniforms[key].value = v; onSet?.(); }, }); - }); + } } } diff --git a/packages/use-shader-fx/src/materials/impl/BasicFxMaterialImpl.ts b/packages/use-shader-fx/src/materials/impl/BasicFxMaterialImpl.ts index 9384120b..44216c38 100644 --- a/packages/use-shader-fx/src/materials/impl/BasicFxMaterialImpl.ts +++ b/packages/use-shader-fx/src/materials/impl/BasicFxMaterialImpl.ts @@ -1,19 +1,19 @@ import * as THREE from "three"; -import { FxMaterialProps, ShaderWithUniforms } from "../core/FxMaterial"; -import { ShaderLib } from "../../libs/shaders/ShaderLib"; +import { FxMaterialProps } from "../core/FxMaterial"; +import { ShaderLib } from "../../shaders/ShaderLib"; import { BasicFxMaterial } from "../core/BasicFxMaterial"; +import { BasicFxUniforms, BasicFxValues } from "../core/BasicFxLib"; import { - BasicFxUniforms, - BasicFxValues, - ExtractUniformValue, -} from "../core/BasicFxLib"; + NestUniformValues, + ShaderWithUniforms, +} from "../../shaders/uniformsUtils"; type BasicFxMaterialImplUniforms = { src: { value: THREE.Texture }; } & BasicFxUniforms; export type BasicFxMaterialImplValues = - ExtractUniformValue & BasicFxValues; + NestUniformValues & BasicFxValues; const DEFAULT_VERTEX = ` void main() { diff --git a/packages/use-shader-fx/src/materials/impl/FxMaterialImpl.ts b/packages/use-shader-fx/src/materials/impl/FxMaterialImpl.ts index 1c520814..a77fb76d 100644 --- a/packages/use-shader-fx/src/materials/impl/FxMaterialImpl.ts +++ b/packages/use-shader-fx/src/materials/impl/FxMaterialImpl.ts @@ -3,17 +3,19 @@ import { DefaultUniforms, FxMaterial, FxMaterialProps, - ShaderWithUniforms, } from "../core/FxMaterial"; -import { ShaderLib } from "../../libs/shaders/ShaderLib"; +import { ShaderLib } from "../../shaders/ShaderLib"; import { DEFAULT_TEXTURE } from "../../libs/constants"; -import { ExtractUniformValue } from "../core/BasicFxLib"; +import { + ShaderWithUniforms, + NestUniformValues, +} from "../../shaders/uniformsUtils"; type FxMaterialImplUniforms = { src: { value: THREE.Texture }; } & DefaultUniforms; -export type FxMaterialImplValues = ExtractUniformValue; +export type FxMaterialImplValues = NestUniformValues; const DEFAULT_VERTEX = ` void main() { diff --git a/packages/use-shader-fx/src/materials/impl/blur/BlurMaterial.ts b/packages/use-shader-fx/src/materials/impl/blur/BlurMaterial.ts index 67b48739..579e2d58 100644 --- a/packages/use-shader-fx/src/materials/impl/blur/BlurMaterial.ts +++ b/packages/use-shader-fx/src/materials/impl/blur/BlurMaterial.ts @@ -2,20 +2,18 @@ import * as THREE from "three"; import { fragment, vertex } from "./blur.glsl"; import { BasicFxMaterial } from "../../core/BasicFxMaterial"; import { FxMaterialProps } from "../../core/FxMaterial"; -import { - BasicFxUniforms, - BasicFxValues, - ExtractUniformValue, -} from "../../core/BasicFxLib"; +import { BasicFxUniforms, BasicFxValues } from "../../core/BasicFxLib"; +import { NestUniformValues } from "../../../shaders/uniformsUtils"; +import { TexturePipelineSrc } from "../../../misc"; type BlurUniforms = { /** */ - src: { value: THREE.Texture | null }; + src: { value: TexturePipelineSrc }; /** */ blurSize: { value: number }; } & BasicFxUniforms; -export type BlurValues = ExtractUniformValue & BasicFxValues; +export type BlurValues = NestUniformValues & BasicFxValues; export class BlurMaterial extends BasicFxMaterial { static get type() { diff --git a/packages/use-shader-fx/src/materials/impl/blur/blur.glsl.ts b/packages/use-shader-fx/src/materials/impl/blur/blur.glsl.ts index 408966f2..e856eb56 100644 --- a/packages/use-shader-fx/src/materials/impl/blur/blur.glsl.ts +++ b/packages/use-shader-fx/src/materials/impl/blur/blur.glsl.ts @@ -1,4 +1,4 @@ -import { ShaderLib } from "../../../libs/shaders/ShaderLib"; +import { ShaderLib } from "../../../shaders/ShaderLib"; export const vertex = ` void main() { diff --git a/packages/use-shader-fx/src/materials/impl/cover/CoverTextureMaterial.ts b/packages/use-shader-fx/src/materials/impl/cover/CoverTextureMaterial.ts index 48d3b265..75f588c2 100644 --- a/packages/use-shader-fx/src/materials/impl/cover/CoverTextureMaterial.ts +++ b/packages/use-shader-fx/src/materials/impl/cover/CoverTextureMaterial.ts @@ -2,12 +2,9 @@ import * as THREE from "three"; import { fragment, vertex } from "./coverTexture.glsl"; import { BasicFxMaterial } from "../../core/BasicFxMaterial"; import { FxMaterialProps } from "../../core/FxMaterial"; -import { - BasicFxUniforms, - BasicFxValues, - ExtractUniformValue, -} from "../../core/BasicFxLib"; +import { BasicFxUniforms, BasicFxValues } from "../../core/BasicFxLib"; import { TexturePipelineSrc } from "../../../misc"; +import { NestUniformValues } from "../../../shaders/uniformsUtils"; type CoverTextureUniforms = { /** */ @@ -16,7 +13,7 @@ type CoverTextureUniforms = { textureResolution: { value: THREE.Vector2 }; } & BasicFxUniforms; -export type CoverTextureValues = ExtractUniformValue & +export type CoverTextureValues = NestUniformValues & BasicFxValues; export class CoverTextureMaterial extends BasicFxMaterial { diff --git a/packages/use-shader-fx/src/materials/impl/cover/coverTexture.glsl.ts b/packages/use-shader-fx/src/materials/impl/cover/coverTexture.glsl.ts index 429704f5..16201be5 100644 --- a/packages/use-shader-fx/src/materials/impl/cover/coverTexture.glsl.ts +++ b/packages/use-shader-fx/src/materials/impl/cover/coverTexture.glsl.ts @@ -1,4 +1,4 @@ -import { ShaderLib } from "../../../libs/shaders/ShaderLib"; +import { ShaderLib } from "../../../shaders/ShaderLib"; export const vertex = ` uniform vec2 textureResolution; diff --git a/packages/use-shader-fx/src/materials/impl/noise/NoiseMaterial.ts b/packages/use-shader-fx/src/materials/impl/noise/NoiseMaterial.ts index fff61e14..ca007093 100644 --- a/packages/use-shader-fx/src/materials/impl/noise/NoiseMaterial.ts +++ b/packages/use-shader-fx/src/materials/impl/noise/NoiseMaterial.ts @@ -2,11 +2,8 @@ import * as THREE from "three"; import { noiseFragment, noiseVertex } from "./noise.glsl"; import { BasicFxMaterial } from "../../core/BasicFxMaterial"; import { FxMaterialProps } from "../../core/FxMaterial"; -import { - BasicFxUniforms, - BasicFxValues, - ExtractUniformValue, -} from "../../core/BasicFxLib"; +import { BasicFxUniforms, BasicFxValues } from "../../core/BasicFxLib"; +import { NestUniformValues } from "../../../shaders/uniformsUtils"; type NoiseUniforms = { /** useBeatを渡せば、リズムを変えられる。 */ @@ -27,7 +24,7 @@ type NoiseUniforms = { warpStrength: { value: number }; } & BasicFxUniforms; -export type NoiseValues = ExtractUniformValue & BasicFxValues; +export type NoiseValues = NestUniformValues & BasicFxValues; export class NoiseMaterial extends BasicFxMaterial { public static readonly key: string = THREE.MathUtils.generateUUID(); diff --git a/packages/use-shader-fx/src/materials/impl/noise/noise.glsl.ts b/packages/use-shader-fx/src/materials/impl/noise/noise.glsl.ts index 82ad6c16..0d475218 100644 --- a/packages/use-shader-fx/src/materials/impl/noise/noise.glsl.ts +++ b/packages/use-shader-fx/src/materials/impl/noise/noise.glsl.ts @@ -1,4 +1,4 @@ -import { ShaderLib } from "../../../libs/shaders/ShaderLib"; +import { ShaderLib } from "../../../shaders/ShaderLib"; export const noiseVertex = ` void main() { diff --git a/packages/use-shader-fx/src/misc/usePipeline.ts b/packages/use-shader-fx/src/misc/usePipeline.ts index e11aa595..e7d908ef 100644 --- a/packages/use-shader-fx/src/misc/usePipeline.ts +++ b/packages/use-shader-fx/src/misc/usePipeline.ts @@ -2,6 +2,7 @@ import * as THREE from "three"; import { useCallback, useState } from "react"; import { RootState } from "../hooks/types"; import { FxTypes, FxProps } from "../hooks"; +import { warn } from "../utils/warn"; export type FxConfig = { fx: T; @@ -15,14 +16,20 @@ export type PipelineConfig = { mixDst?: number | TexturePipelineSrc; }; export type PipelineValues = { - [K in keyof PipelineConfig]?: TexturePipelineSrc; + src?: TexturePipelineSrc; + mixSrc?: { + src?: TexturePipelineSrc; + }; + mixDst?: { + src?: TexturePipelineSrc; + }; }; const WARN_TEXT = { - args: `use-shader-fx: fx and args length mismatch. fx is non-reactive; update by changing the key to reset state.`, - pipeline: `use-shader-fx: fx and pipeline length mismatch. fx is non-reactive; update by changing the key to reset state.`, + args: `fx and args length mismatch. fx is non-reactive; update by changing the key to reset state.`, + pipeline: `fx and pipeline length mismatch. fx is non-reactive; update by changing the key to reset state.`, pipelineValue: (val: number, pipelineIndex: number, key: string) => - `use-shader-fx: texture(index:${val}) is missing, at "${key}" of pipeline(index:${pipelineIndex}).`, + `texture(index:${val}) is missing, at "${key}" of pipeline(index:${pipelineIndex}).`, }; export const usePipeline = ( @@ -37,7 +44,7 @@ export const usePipeline = ( const argsDiff = hooks.length - _args.length; if (argsDiff !== 0) { - console.warn(WARN_TEXT.args); + warn(WARN_TEXT.args); // adjust length of args if (argsDiff < 0) { _args = _args.slice(0, hooks.length); @@ -63,7 +70,7 @@ export const usePipeline = ( const setPipeline = useCallback( (...args: PipelineConfig[]) => { if (args.length !== pipeline.length) { - console.warn(WARN_TEXT.pipeline); + warn(WARN_TEXT.pipeline); return; } args.forEach((arg, i) => @@ -90,26 +97,34 @@ function getPipelineValues( ) { const value: PipelineValues = {}; + const setValue = (key: keyof PipelineConfig, val: TexturePipelineSrc) => { + if (key === "src") { + value[key] = val; + return; + } + value[key] = { src: val }; + }; + for (const [key, val] of Object.entries(config)) { const _key = key as keyof PipelineConfig; if (val == null) { - value[_key] = null; - break; + setValue(_key, null); + continue; } if (typeof val === "number") { const _tex = textures[val]; if (!_tex) { - console.warn(WARN_TEXT.pipelineValue(val, pipelineIndex, key)); - value[_key] = null; - break; + warn(WARN_TEXT.pipelineValue(val, pipelineIndex, key)); + setValue(_key, null); + continue; } - value[_key] = _tex; - break; + setValue(_key, _tex); + continue; } - value[_key] = val; + setValue(_key, val); } return value; diff --git a/packages/use-shader-fx/src/libs/shaders/ShaderChunk.ts b/packages/use-shader-fx/src/shaders/ShaderChunk.ts similarity index 100% rename from packages/use-shader-fx/src/libs/shaders/ShaderChunk.ts rename to packages/use-shader-fx/src/shaders/ShaderChunk.ts diff --git a/packages/use-shader-fx/src/libs/shaders/ShaderChunk/default_pars_fragment.glsl b/packages/use-shader-fx/src/shaders/ShaderChunk/default_pars_fragment.glsl similarity index 100% rename from packages/use-shader-fx/src/libs/shaders/ShaderChunk/default_pars_fragment.glsl rename to packages/use-shader-fx/src/shaders/ShaderChunk/default_pars_fragment.glsl diff --git a/packages/use-shader-fx/src/libs/shaders/ShaderChunk/default_pars_vertex.glsl b/packages/use-shader-fx/src/shaders/ShaderChunk/default_pars_vertex.glsl similarity index 100% rename from packages/use-shader-fx/src/libs/shaders/ShaderChunk/default_pars_vertex.glsl rename to packages/use-shader-fx/src/shaders/ShaderChunk/default_pars_vertex.glsl diff --git a/packages/use-shader-fx/src/libs/shaders/ShaderChunk/default_vertex.glsl b/packages/use-shader-fx/src/shaders/ShaderChunk/default_vertex.glsl similarity index 100% rename from packages/use-shader-fx/src/libs/shaders/ShaderChunk/default_vertex.glsl rename to packages/use-shader-fx/src/shaders/ShaderChunk/default_vertex.glsl diff --git a/packages/use-shader-fx/src/shaders/ShaderChunk/mixDst_fragment.glsl b/packages/use-shader-fx/src/shaders/ShaderChunk/mixDst_fragment.glsl new file mode 100644 index 00000000..6ae3873d --- /dev/null +++ b/packages/use-shader-fx/src/shaders/ShaderChunk/mixDst_fragment.glsl @@ -0,0 +1,9 @@ +#ifdef USF_USE_MIXDST + + vec4 mixDstColor = texture2D(mixDst_src, mix(vMixDstCoverUv,usf_FragColor.rg,mixDst_uvFactor)); + + usf_FragColor = mix(usf_FragColor, mixDstColor, mixDst_colorFactor); + + usf_FragColor = mix(usf_FragColor, mixDstColor, mixDstColor.a * mixDst_alphaFactor); + +#endif \ No newline at end of file diff --git a/packages/use-shader-fx/src/shaders/ShaderChunk/mixDst_pars_fragment.glsl b/packages/use-shader-fx/src/shaders/ShaderChunk/mixDst_pars_fragment.glsl new file mode 100644 index 00000000..893a7287 --- /dev/null +++ b/packages/use-shader-fx/src/shaders/ShaderChunk/mixDst_pars_fragment.glsl @@ -0,0 +1,7 @@ +#ifdef USF_USE_MIXDST + varying vec2 vMixDstCoverUv; + uniform sampler2D mixDst_src; + uniform float mixDst_uvFactor; + uniform float mixDst_alphaFactor; + uniform float mixDst_colorFactor; +#endif \ No newline at end of file diff --git a/packages/use-shader-fx/src/libs/shaders/ShaderChunk/mixDst_pars_vertex.glsl b/packages/use-shader-fx/src/shaders/ShaderChunk/mixDst_pars_vertex.glsl similarity index 63% rename from packages/use-shader-fx/src/libs/shaders/ShaderChunk/mixDst_pars_vertex.glsl rename to packages/use-shader-fx/src/shaders/ShaderChunk/mixDst_pars_vertex.glsl index 668d3c09..842fb720 100644 --- a/packages/use-shader-fx/src/libs/shaders/ShaderChunk/mixDst_pars_vertex.glsl +++ b/packages/use-shader-fx/src/shaders/ShaderChunk/mixDst_pars_vertex.glsl @@ -1,4 +1,4 @@ #ifdef USF_USE_MIXDST varying vec2 vMixDstCoverUv; - uniform vec2 mixDstResolution; + uniform vec2 mixDst_resolution; #endif \ No newline at end of file diff --git a/packages/use-shader-fx/src/libs/shaders/ShaderChunk/mixDst_vertex.glsl b/packages/use-shader-fx/src/shaders/ShaderChunk/mixDst_vertex.glsl similarity index 78% rename from packages/use-shader-fx/src/libs/shaders/ShaderChunk/mixDst_vertex.glsl rename to packages/use-shader-fx/src/shaders/ShaderChunk/mixDst_vertex.glsl index e70c3b50..5ca228a2 100644 --- a/packages/use-shader-fx/src/libs/shaders/ShaderChunk/mixDst_vertex.glsl +++ b/packages/use-shader-fx/src/shaders/ShaderChunk/mixDst_vertex.glsl @@ -1,5 +1,5 @@ #ifdef USF_USE_MIXDST - float mixDstAspect = mixDstResolution.x / mixDstResolution.y; + float mixDstAspect = mixDst_resolution.x / mixDst_resolution.y; vec2 mixDstAspectAspectRatio = vec2( min(aspectRatio / mixDstAspect, 1.0), min(mixDstAspect / aspectRatio, 1.0) diff --git a/packages/use-shader-fx/src/shaders/ShaderChunk/mixSrc_fragment_begin.glsl b/packages/use-shader-fx/src/shaders/ShaderChunk/mixSrc_fragment_begin.glsl new file mode 100644 index 00000000..de081873 --- /dev/null +++ b/packages/use-shader-fx/src/shaders/ShaderChunk/mixSrc_fragment_begin.glsl @@ -0,0 +1,6 @@ +#ifdef USF_USE_MIXSRC + + vec4 mixSrcColor = texture2D(mixSrc_src, vMixSrcCoverUv); + usf_Uv = mix(usf_Uv, mixSrcColor.rg, mixSrc_uvFactor); + +#endif \ No newline at end of file diff --git a/packages/use-shader-fx/src/libs/shaders/ShaderChunk/mixSrc_fragment_end.glsl b/packages/use-shader-fx/src/shaders/ShaderChunk/mixSrc_fragment_end.glsl similarity index 51% rename from packages/use-shader-fx/src/libs/shaders/ShaderChunk/mixSrc_fragment_end.glsl rename to packages/use-shader-fx/src/shaders/ShaderChunk/mixSrc_fragment_end.glsl index 587ffa03..750f41cf 100644 --- a/packages/use-shader-fx/src/libs/shaders/ShaderChunk/mixSrc_fragment_end.glsl +++ b/packages/use-shader-fx/src/shaders/ShaderChunk/mixSrc_fragment_end.glsl @@ -1,7 +1,7 @@ #ifdef USF_USE_MIXSRC - usf_FragColor = mix(usf_FragColor, mixSrcColor, mixSrcColorFactor); + usf_FragColor = mix(usf_FragColor, mixSrcColor, mixSrc_colorFactor); - usf_FragColor = mix(usf_FragColor, mixSrcColor, mixSrcColor.a * mixSrcAlphaFactor); + usf_FragColor = mix(usf_FragColor, mixSrcColor, mixSrcColor.a * mixSrc_alphaFactor); #endif \ No newline at end of file diff --git a/packages/use-shader-fx/src/shaders/ShaderChunk/mixSrc_pars_fragment.glsl b/packages/use-shader-fx/src/shaders/ShaderChunk/mixSrc_pars_fragment.glsl new file mode 100644 index 00000000..53c06c46 --- /dev/null +++ b/packages/use-shader-fx/src/shaders/ShaderChunk/mixSrc_pars_fragment.glsl @@ -0,0 +1,7 @@ +#ifdef USF_USE_MIXSRC + varying vec2 vMixSrcCoverUv; + uniform sampler2D mixSrc_src; + uniform float mixSrc_uvFactor; + uniform float mixSrc_alphaFactor; + uniform float mixSrc_colorFactor; +#endif \ No newline at end of file diff --git a/packages/use-shader-fx/src/libs/shaders/ShaderChunk/mixSrc_pars_vertex.glsl b/packages/use-shader-fx/src/shaders/ShaderChunk/mixSrc_pars_vertex.glsl similarity index 63% rename from packages/use-shader-fx/src/libs/shaders/ShaderChunk/mixSrc_pars_vertex.glsl rename to packages/use-shader-fx/src/shaders/ShaderChunk/mixSrc_pars_vertex.glsl index a98019a6..98ba0b64 100644 --- a/packages/use-shader-fx/src/libs/shaders/ShaderChunk/mixSrc_pars_vertex.glsl +++ b/packages/use-shader-fx/src/shaders/ShaderChunk/mixSrc_pars_vertex.glsl @@ -1,4 +1,4 @@ #ifdef USF_USE_MIXSRC varying vec2 vMixSrcCoverUv; - uniform vec2 mixSrcResolution; + uniform vec2 mixSrc_resolution; #endif \ No newline at end of file diff --git a/packages/use-shader-fx/src/libs/shaders/ShaderChunk/mixSrc_vertex.glsl b/packages/use-shader-fx/src/shaders/ShaderChunk/mixSrc_vertex.glsl similarity index 78% rename from packages/use-shader-fx/src/libs/shaders/ShaderChunk/mixSrc_vertex.glsl rename to packages/use-shader-fx/src/shaders/ShaderChunk/mixSrc_vertex.glsl index 40edcc13..d3c2db9b 100644 --- a/packages/use-shader-fx/src/libs/shaders/ShaderChunk/mixSrc_vertex.glsl +++ b/packages/use-shader-fx/src/shaders/ShaderChunk/mixSrc_vertex.glsl @@ -1,5 +1,5 @@ #ifdef USF_USE_MIXSRC - float mixSrcAspect = mixSrcResolution.x / mixSrcResolution.y; + float mixSrcAspect = mixSrc_resolution.x / mixSrc_resolution.y; vec2 mixSrcAspectAspectRatio = vec2( min(aspectRatio / mixSrcAspect, 1.0), min(mixSrcAspect / aspectRatio, 1.0) diff --git a/packages/use-shader-fx/src/libs/shaders/ShaderChunk/plane_vertex.glsl b/packages/use-shader-fx/src/shaders/ShaderChunk/plane_vertex.glsl similarity index 100% rename from packages/use-shader-fx/src/libs/shaders/ShaderChunk/plane_vertex.glsl rename to packages/use-shader-fx/src/shaders/ShaderChunk/plane_vertex.glsl diff --git a/packages/use-shader-fx/src/libs/shaders/ShaderLib.ts b/packages/use-shader-fx/src/shaders/ShaderLib.ts similarity index 100% rename from packages/use-shader-fx/src/libs/shaders/ShaderLib.ts rename to packages/use-shader-fx/src/shaders/ShaderLib.ts diff --git a/packages/use-shader-fx/src/libs/shaders/ShaderLib/basicFx_fragment_begin.glsl b/packages/use-shader-fx/src/shaders/ShaderLib/basicFx_fragment_begin.glsl similarity index 100% rename from packages/use-shader-fx/src/libs/shaders/ShaderLib/basicFx_fragment_begin.glsl rename to packages/use-shader-fx/src/shaders/ShaderLib/basicFx_fragment_begin.glsl diff --git a/packages/use-shader-fx/src/libs/shaders/ShaderLib/basicFx_fragment_end.glsl b/packages/use-shader-fx/src/shaders/ShaderLib/basicFx_fragment_end.glsl similarity index 100% rename from packages/use-shader-fx/src/libs/shaders/ShaderLib/basicFx_fragment_end.glsl rename to packages/use-shader-fx/src/shaders/ShaderLib/basicFx_fragment_end.glsl diff --git a/packages/use-shader-fx/src/libs/shaders/ShaderLib/basicFx_pars_fragment.glsl b/packages/use-shader-fx/src/shaders/ShaderLib/basicFx_pars_fragment.glsl similarity index 100% rename from packages/use-shader-fx/src/libs/shaders/ShaderLib/basicFx_pars_fragment.glsl rename to packages/use-shader-fx/src/shaders/ShaderLib/basicFx_pars_fragment.glsl diff --git a/packages/use-shader-fx/src/libs/shaders/ShaderLib/basicFx_pars_vertex.glsl b/packages/use-shader-fx/src/shaders/ShaderLib/basicFx_pars_vertex.glsl similarity index 100% rename from packages/use-shader-fx/src/libs/shaders/ShaderLib/basicFx_pars_vertex.glsl rename to packages/use-shader-fx/src/shaders/ShaderLib/basicFx_pars_vertex.glsl diff --git a/packages/use-shader-fx/src/libs/shaders/ShaderLib/basicFx_vertex.glsl b/packages/use-shader-fx/src/shaders/ShaderLib/basicFx_vertex.glsl similarity index 100% rename from packages/use-shader-fx/src/libs/shaders/ShaderLib/basicFx_vertex.glsl rename to packages/use-shader-fx/src/shaders/ShaderLib/basicFx_vertex.glsl diff --git a/packages/use-shader-fx/src/libs/shaders/ShaderLib/default_pars_fragment.glsl b/packages/use-shader-fx/src/shaders/ShaderLib/default_pars_fragment.glsl similarity index 100% rename from packages/use-shader-fx/src/libs/shaders/ShaderLib/default_pars_fragment.glsl rename to packages/use-shader-fx/src/shaders/ShaderLib/default_pars_fragment.glsl diff --git a/packages/use-shader-fx/src/libs/shaders/ShaderLib/default_pars_vertex.glsl b/packages/use-shader-fx/src/shaders/ShaderLib/default_pars_vertex.glsl similarity index 100% rename from packages/use-shader-fx/src/libs/shaders/ShaderLib/default_pars_vertex.glsl rename to packages/use-shader-fx/src/shaders/ShaderLib/default_pars_vertex.glsl diff --git a/packages/use-shader-fx/src/libs/shaders/ShaderLib/default_vertex.glsl b/packages/use-shader-fx/src/shaders/ShaderLib/default_vertex.glsl similarity index 100% rename from packages/use-shader-fx/src/libs/shaders/ShaderLib/default_vertex.glsl rename to packages/use-shader-fx/src/shaders/ShaderLib/default_vertex.glsl diff --git a/packages/use-shader-fx/src/libs/shaders/ShaderLib/plane_vertex.glsl b/packages/use-shader-fx/src/shaders/ShaderLib/plane_vertex.glsl similarity index 100% rename from packages/use-shader-fx/src/libs/shaders/ShaderLib/plane_vertex.glsl rename to packages/use-shader-fx/src/shaders/ShaderLib/plane_vertex.glsl diff --git a/packages/use-shader-fx/src/libs/shaders/mergeShaderLib.ts b/packages/use-shader-fx/src/shaders/mergeShaderLib.ts similarity index 100% rename from packages/use-shader-fx/src/libs/shaders/mergeShaderLib.ts rename to packages/use-shader-fx/src/shaders/mergeShaderLib.ts diff --git a/packages/use-shader-fx/src/libs/shaders/resolveShaders.ts b/packages/use-shader-fx/src/shaders/resolveShaders.ts similarity index 100% rename from packages/use-shader-fx/src/libs/shaders/resolveShaders.ts rename to packages/use-shader-fx/src/shaders/resolveShaders.ts diff --git a/packages/use-shader-fx/src/shaders/uniformsUtils.ts b/packages/use-shader-fx/src/shaders/uniformsUtils.ts new file mode 100644 index 00000000..dd942307 --- /dev/null +++ b/packages/use-shader-fx/src/shaders/uniformsUtils.ts @@ -0,0 +1,66 @@ +import * as THREE from "three"; +import { warn } from "../utils/warn"; +import { THREE_TYPES } from "../libs/constants"; + +export type Uniforms = { [uniform: string]: THREE.IUniform }; + +export type ShaderWithUniforms = { + uniforms?: Uniforms; + vertexShader?: string; + fragmentShader?: string; +}; + +type Nest = K extends `${infer First}_${infer Rest}` + ? { [P in First]?: Nest } + : { [P in K]?: V }; + +type UnionToIntersection = (U extends any ? (k: U) => void : never) extends ( + k: infer I +) => void + ? I + : never; + +/** + * test_test => { test: { test: number } } + */ +export type NestUniformValues = UnionToIntersection< + { [K in keyof U]: Nest, U[K]["value"]> }[keyof U] +>; + +function isTHREE(property: any) { + return property && THREE_TYPES.has(property.constructor); +} + +/** + * {test:{test:1}} => {test_test:1} + */ +export function flattenUniformValues( + obj: Record +): Record { + const flatObject: Record = {}; + + const helper = (currentObj: any, parentKey = ""): void => { + for (const key in currentObj) { + if (Object.prototype.hasOwnProperty.call(currentObj, key)) { + const value = currentObj[key]; + const newKey = parentKey ? `${parentKey}_${key}` : key; + if ( + value && + typeof value === "object" && + !Array.isArray(value) && + !isTHREE(value) + ) { + helper(value, newKey); + } else { + if (flatObject.hasOwnProperty(newKey)) { + warn(`${newKey} already exists and will be overwritten.`); + } + flatObject[newKey] = value; + } + } + } + }; + + helper(obj); + return flatObject; +} diff --git a/packages/use-shader-fx/src/utils/warn.ts b/packages/use-shader-fx/src/utils/warn.ts new file mode 100644 index 00000000..518fb1cc --- /dev/null +++ b/packages/use-shader-fx/src/utils/warn.ts @@ -0,0 +1,7 @@ +import { APP_NAME, ISDEV } from "../libs/constants"; + +export const warn = (text: string) => { + if (ISDEV) { + console.warn(`${APP_NAME}: ${text}`); + } +}; diff --git a/todo b/todo index 7702ee89..d8dcc16d 100644 --- a/todo +++ b/todo @@ -14,26 +14,8 @@ - 粘性の追加 - basic fx - - valueをオブジェクトにする仕組み - - 変数が多くなって変数名が冗長になるため - - mixSrc,mixDstのblendingMode - - basicFxに色調補正 + - basicFxに色調補正系 - fluid contrastを参考に + - mixSrc,mixDstのblendingMode - micSrc => 色調補正系 => micDstの順 -### mix -- mixSrc -- mixDst - -### color adjustments -- duotone -- saturation -- brightness -- contrast -- levels -- colorBalance -- threshold -- posterization - -### misc -- vignette \ No newline at end of file From 498d969ad212dfe6f9e8710b8960c6a6566f2578 Mon Sep 17 00:00:00 2001 From: takuma-hmng8 Date: Wed, 23 Oct 2024 16:58:47 +0900 Subject: [PATCH 29/60] update --- app/v2_fxMaterials/Playground.tsx | 27 +++++++-------- .../src/materials/core/FxMaterial.ts | 1 + .../src/shaders/uniformsUtils.ts | 33 +++++++++---------- todo | 1 - 4 files changed, 28 insertions(+), 34 deletions(-) diff --git a/app/v2_fxMaterials/Playground.tsx b/app/v2_fxMaterials/Playground.tsx index bf8a7fcc..529a0a9e 100644 --- a/app/v2_fxMaterials/Playground.tsx +++ b/app/v2_fxMaterials/Playground.tsx @@ -1,14 +1,9 @@ "use client"; -import * as THREE from "three"; -import { useRef, useState } from "react"; -import { useFrame, useThree, extend, createPortal } from "@react-three/fiber"; -import { - NoiseMaterial, - NoiseValues, - FxMaterialImplValues, - BasicFxMaterialImplValues, -} from "@/packages/use-shader-fx/src"; +import { useRef } from "react"; +import { useFrame, extend } from "@react-three/fiber"; +import { NoiseMaterial } from "@/packages/use-shader-fx/src"; +import { useTexture } from "@react-three/drei"; extend({ NoiseMaterial }); @@ -17,11 +12,17 @@ export const Playground = () => { useFrame(({ clock }) => { ref.current.tick = clock.getElapsedTime(); }); + const [funkun] = useTexture(["/funkun.jpg"]); return ( <> - + ); @@ -30,11 +31,7 @@ export const Playground = () => { declare global { namespace JSX { interface IntrinsicElements { - noiseMaterial: NoiseValues & JSX.IntrinsicElements["shaderMaterial"]; - fxMaterialImpl: FxMaterialImplValues & - JSX.IntrinsicElements["shaderMaterial"]; - BasicFxMaterialImpl: BasicFxMaterialImplValues & - JSX.IntrinsicElements["shaderMaterial"]; + noiseMaterial: any & JSX.IntrinsicElements["shaderMaterial"]; } } } diff --git a/packages/use-shader-fx/src/materials/core/FxMaterial.ts b/packages/use-shader-fx/src/materials/core/FxMaterial.ts index d567b272..138fea25 100644 --- a/packages/use-shader-fx/src/materials/core/FxMaterial.ts +++ b/packages/use-shader-fx/src/materials/core/FxMaterial.ts @@ -98,6 +98,7 @@ export class FxMaterial extends THREE.ShaderMaterial { defineUniformAccessors(onSet?: () => void) { for (const key of Object.keys(this.uniforms)) { if (this.hasOwnProperty(key)) { + warn(`'${key}' is already defined in ${this.type}.`); continue; } Object.defineProperty(this, key, { diff --git a/packages/use-shader-fx/src/shaders/uniformsUtils.ts b/packages/use-shader-fx/src/shaders/uniformsUtils.ts index dd942307..95e02eba 100644 --- a/packages/use-shader-fx/src/shaders/uniformsUtils.ts +++ b/packages/use-shader-fx/src/shaders/uniformsUtils.ts @@ -39,28 +39,25 @@ export function flattenUniformValues( ): Record { const flatObject: Record = {}; - const helper = (currentObj: any, parentKey = ""): void => { - for (const key in currentObj) { - if (Object.prototype.hasOwnProperty.call(currentObj, key)) { - const value = currentObj[key]; - const newKey = parentKey ? `${parentKey}_${key}` : key; - if ( - value && - typeof value === "object" && - !Array.isArray(value) && - !isTHREE(value) - ) { - helper(value, newKey); - } else { - if (flatObject.hasOwnProperty(newKey)) { - warn(`${newKey} already exists and will be overwritten.`); - } - flatObject[newKey] = value; + const flatten = (currentObj: any, parentKey = ""): void => { + for (const [key, val] of Object.entries(currentObj)) { + const newKey = parentKey ? `${parentKey}_${key}` : key; + if ( + val && + typeof val === "object" && + !Array.isArray(val) && + !isTHREE(val) + ) { + flatten(val, newKey); + } else { + if (flatObject.hasOwnProperty(newKey)) { + warn(`${newKey} already exists and will be overwritten.`); } + flatObject[newKey] = val; } } }; - helper(obj); + flatten(obj); return flatObject; } diff --git a/todo b/todo index d8dcc16d..e02e4a07 100644 --- a/todo +++ b/todo @@ -18,4 +18,3 @@ - fluid contrastを参考に - mixSrc,mixDstのblendingMode - micSrc => 色調補正系 => micDstの順 - From a70a01f6e7d32f689ffa69a2d4fc225eecf42a47 Mon Sep 17 00:00:00 2001 From: takuma-hmng8 Date: Wed, 23 Oct 2024 21:51:57 +0900 Subject: [PATCH 30/60] update --- app/v2_fxMaterials/Playground.tsx | 8 +++++-- .../use-shader-fx/src/hooks/useNoise/index.ts | 11 +++++++-- .../src/materials/impl/noise/NoiseMaterial.ts | 7 +++++- .../src/shaders/uniformsUtils.ts | 23 ++++++++++++------- todo | 3 +++ 5 files changed, 39 insertions(+), 13 deletions(-) diff --git a/app/v2_fxMaterials/Playground.tsx b/app/v2_fxMaterials/Playground.tsx index 529a0a9e..6fcc76ad 100644 --- a/app/v2_fxMaterials/Playground.tsx +++ b/app/v2_fxMaterials/Playground.tsx @@ -2,7 +2,10 @@ import { useRef } from "react"; import { useFrame, extend } from "@react-three/fiber"; -import { NoiseMaterial } from "@/packages/use-shader-fx/src"; +import { + NoiseMaterial, + NoiseMaterialProps, +} from "@/packages/use-shader-fx/src"; import { useTexture } from "@react-three/drei"; extend({ NoiseMaterial }); @@ -31,7 +34,8 @@ export const Playground = () => { declare global { namespace JSX { interface IntrinsicElements { - noiseMaterial: any & JSX.IntrinsicElements["shaderMaterial"]; + noiseMaterial: NoiseMaterialProps & + JSX.IntrinsicElements["shaderMaterial"]; } } } diff --git a/packages/use-shader-fx/src/hooks/useNoise/index.ts b/packages/use-shader-fx/src/hooks/useNoise/index.ts index 0adffc31..7817c8a1 100644 --- a/packages/use-shader-fx/src/hooks/useNoise/index.ts +++ b/packages/use-shader-fx/src/hooks/useNoise/index.ts @@ -3,7 +3,11 @@ import { useSingleFBO } from "../../utils/useSingleFBO"; import { HooksProps, HooksReturn } from "../types"; import { getDpr } from "../../utils/getDpr"; import { RootState } from "../types"; -import { NoiseMaterial, NoiseValues } from "../../materials"; +import { + NoiseMaterial, + NoiseMaterialProps, + NoiseValues, +} from "../../materials"; import { useFxScene } from "../../utils/useFxScene"; export type NoiseProps = HooksProps & NoiseValues; @@ -18,7 +22,10 @@ export const useNoise = ({ renderTargetOptions, materialParameters, ...uniformValues -}: NoiseProps): HooksReturn => { +}: NoiseProps): HooksReturn< + NoiseValues, + NoiseMaterial & NoiseMaterialProps +> => { const _dpr = getDpr(dpr); const { scene, material, camera } = useFxScene({ diff --git a/packages/use-shader-fx/src/materials/impl/noise/NoiseMaterial.ts b/packages/use-shader-fx/src/materials/impl/noise/NoiseMaterial.ts index ca007093..a3f2804e 100644 --- a/packages/use-shader-fx/src/materials/impl/noise/NoiseMaterial.ts +++ b/packages/use-shader-fx/src/materials/impl/noise/NoiseMaterial.ts @@ -3,7 +3,10 @@ import { noiseFragment, noiseVertex } from "./noise.glsl"; import { BasicFxMaterial } from "../../core/BasicFxMaterial"; import { FxMaterialProps } from "../../core/FxMaterial"; import { BasicFxUniforms, BasicFxValues } from "../../core/BasicFxLib"; -import { NestUniformValues } from "../../../shaders/uniformsUtils"; +import { + ExtractUniformValues, + NestUniformValues, +} from "../../../shaders/uniformsUtils"; type NoiseUniforms = { /** useBeatを渡せば、リズムを変えられる。 */ @@ -26,6 +29,8 @@ type NoiseUniforms = { export type NoiseValues = NestUniformValues & BasicFxValues; +export type NoiseMaterialProps = ExtractUniformValues; + export class NoiseMaterial extends BasicFxMaterial { public static readonly key: string = THREE.MathUtils.generateUUID(); diff --git a/packages/use-shader-fx/src/shaders/uniformsUtils.ts b/packages/use-shader-fx/src/shaders/uniformsUtils.ts index 95e02eba..8ff7d09b 100644 --- a/packages/use-shader-fx/src/shaders/uniformsUtils.ts +++ b/packages/use-shader-fx/src/shaders/uniformsUtils.ts @@ -10,6 +10,18 @@ export type ShaderWithUniforms = { fragmentShader?: string; }; +/** + * test:{value:number} => test:number + * materialのprops型を定義する + * materialにはuniformsのsetter/getterが定義されている.その型推論のため. + */ +export type ExtractUniformValues = { + [K in keyof T]?: T[K] extends { value: infer U } ? U : never; +}; + +/** + * test_test => { test: { test: number } } + */ type Nest = K extends `${infer First}_${infer Rest}` ? { [P in First]?: Nest } : { [P in K]?: V }; @@ -19,21 +31,16 @@ type UnionToIntersection = (U extends any ? (k: U) => void : never) extends ( ) => void ? I : never; - -/** - * test_test => { test: { test: number } } - */ export type NestUniformValues = UnionToIntersection< { [K in keyof U]: Nest, U[K]["value"]> }[keyof U] >; -function isTHREE(property: any) { - return property && THREE_TYPES.has(property.constructor); -} - /** * {test:{test:1}} => {test_test:1} */ +function isTHREE(property: any) { + return property && THREE_TYPES.has(property.constructor); +} export function flattenUniformValues( obj: Record ): Record { diff --git a/todo b/todo index e02e4a07..46434ada 100644 --- a/todo +++ b/todo @@ -18,3 +18,6 @@ - fluid contrastを参考に - mixSrc,mixDstのblendingMode - micSrc => 色調補正系 => micDstの順 + + +- NoiseMaterialPropsみたいにMaterialのprops型をつくって、HooksReturnのMaterialに&しちゃおう \ No newline at end of file From 865e9a8ea8862525d3f26844e6d7523dff85c8a4 Mon Sep 17 00:00:00 2001 From: takuma-hmng8 Date: Wed, 23 Oct 2024 22:06:41 +0900 Subject: [PATCH 31/60] update --- packages/use-shader-fx/src/shaders/uniformsUtils.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/use-shader-fx/src/shaders/uniformsUtils.ts b/packages/use-shader-fx/src/shaders/uniformsUtils.ts index 8ff7d09b..115329cc 100644 --- a/packages/use-shader-fx/src/shaders/uniformsUtils.ts +++ b/packages/use-shader-fx/src/shaders/uniformsUtils.ts @@ -20,7 +20,7 @@ export type ExtractUniformValues = { }; /** - * test_test => { test: { test: number } } + * test_test:{value:number} => { test: { test: number } } */ type Nest = K extends `${infer First}_${infer Rest}` ? { [P in First]?: Nest } From 4421c4acc079d6b75648eee18c816e350f9865ba Mon Sep 17 00:00:00 2001 From: takuma-hmng8 Date: Thu, 7 Nov 2024 12:55:59 +0900 Subject: [PATCH 32/60] update --- app/v2_impl_colorAdjustments/Playground.tsx | 2 +- packages/use-shader-fx/src/hooks/useFluid/index.ts | 1 + .../src/materials/core/SamplingFxMaterial.ts | 6 ------ .../materials/impl/samplingFx/SamplingFxMaterial.ts | 12 ++++++++++++ todo | 4 ++-- 5 files changed, 16 insertions(+), 9 deletions(-) delete mode 100644 packages/use-shader-fx/src/materials/core/SamplingFxMaterial.ts create mode 100644 packages/use-shader-fx/src/materials/impl/samplingFx/SamplingFxMaterial.ts diff --git a/app/v2_impl_colorAdjustments/Playground.tsx b/app/v2_impl_colorAdjustments/Playground.tsx index 063fc8c5..8103cdfe 100644 --- a/app/v2_impl_colorAdjustments/Playground.tsx +++ b/app/v2_impl_colorAdjustments/Playground.tsx @@ -75,7 +75,7 @@ vec3 rgb2hsv(vec3 c) // 出力レベル補正 outputColor = outputColor * (vec4(u_outputMax) - vec4(u_outputMin)) + vec4(u_outputMin); /*=============================================== - // コントラスト + // コントラスト TODO これもvec4でuniformを渡す! alphaだけコントラストかけたり! ===============================================*/ // コントラスト float contrastFactor = 20.; diff --git a/packages/use-shader-fx/src/hooks/useFluid/index.ts b/packages/use-shader-fx/src/hooks/useFluid/index.ts index f7add789..f0a866d7 100644 --- a/packages/use-shader-fx/src/hooks/useFluid/index.ts +++ b/packages/use-shader-fx/src/hooks/useFluid/index.ts @@ -19,6 +19,7 @@ export type FluidValues = { - params - velocity dissipation - color dissipation (color map / pressure disippation的なこと?)  + ===============================================*/ }; diff --git a/packages/use-shader-fx/src/materials/core/SamplingFxMaterial.ts b/packages/use-shader-fx/src/materials/core/SamplingFxMaterial.ts deleted file mode 100644 index 8ac90f94..00000000 --- a/packages/use-shader-fx/src/materials/core/SamplingFxMaterial.ts +++ /dev/null @@ -1,6 +0,0 @@ -/*=============================================== -- rgbshift -- glitch -- pixelate -など、テクスチャサンプリング系のエフェクトを提供するマテリアル -===============================================*/ diff --git a/packages/use-shader-fx/src/materials/impl/samplingFx/SamplingFxMaterial.ts b/packages/use-shader-fx/src/materials/impl/samplingFx/SamplingFxMaterial.ts new file mode 100644 index 00000000..6a51205a --- /dev/null +++ b/packages/use-shader-fx/src/materials/impl/samplingFx/SamplingFxMaterial.ts @@ -0,0 +1,12 @@ +/*=============================================== +- rgbshift +- glitch +- pixelate +など、テクスチャサンプリング系のエフェクトを提供するマテリアル + + +- samplingFxも、macro化する必要がある + - 例えば、rgbshiftだけ使いたい場合とかは、macro化する必要がある。 + - つまり、BasicFx materialを継承するんだけど、basicFXlibとかを拡張する必要がある! + - つまり、ShaderLibとかもいじる必要がある! +===============================================*/ diff --git a/todo b/todo index 46434ada..3c01ed4c 100644 --- a/todo +++ b/todo @@ -11,7 +11,7 @@ - deltaTimeも操作できるように - transparencyを選択できるように - transparencyにして、0~1でmixする方式で - - 粘性の追加 + - 粘性の追加! - basic fx - basicFxに色調補正系 @@ -20,4 +20,4 @@ - micSrc => 色調補正系 => micDstの順 -- NoiseMaterialPropsみたいにMaterialのprops型をつくって、HooksReturnのMaterialに&しちゃおう \ No newline at end of file +- NoiseMaterialPropsみたいにMaterialのprops型をつくって、HooksReturnのMaterialに&しちゃおう From b28057c94f2ee30d46b31d512f39d9e27ee38e87 Mon Sep 17 00:00:00 2001 From: takuma-hmng8 Date: Mon, 11 Nov 2024 19:45:57 +0900 Subject: [PATCH 33/60] update --- app/v2_impl_colorAdjustments/Playground.tsx | 2 +- app/v2_pipe/Playground.tsx | 1 - packages/use-shader-fx/src/materials/core/BasicFxLib.ts | 6 ++++++ .../use-shader-fx/src/materials/core/BasicFxMaterial.ts | 2 ++ packages/use-shader-fx/src/materials/core/FxMaterial.ts | 5 ++--- packages/use-shader-fx/src/utils/useResolution.ts | 1 + todo | 5 ----- 7 files changed, 12 insertions(+), 10 deletions(-) diff --git a/app/v2_impl_colorAdjustments/Playground.tsx b/app/v2_impl_colorAdjustments/Playground.tsx index 8103cdfe..384ebe9c 100644 --- a/app/v2_impl_colorAdjustments/Playground.tsx +++ b/app/v2_impl_colorAdjustments/Playground.tsx @@ -63,7 +63,7 @@ vec3 rgb2hsv(vec3 c) float u_shadows = 1.2; // シャドウ値 float u_midtones = 1.1; // ミッドトーン値 float u_highlights = 1.4; // ハイライト値 - float u_outputMin = 0.0; // 出力の最小値 + float u_outputMin = 0.0; // 出力の最小値 float u_outputMax = 1.0; // 出力の最大値 // 入力レベル補正 diff --git a/app/v2_pipe/Playground.tsx b/app/v2_pipe/Playground.tsx index 1ec0a7b7..e299f7c8 100644 --- a/app/v2_pipe/Playground.tsx +++ b/app/v2_pipe/Playground.tsx @@ -10,7 +10,6 @@ import { useFluid, usePipeline, } from "@/packages/use-shader-fx/src"; -import { useEffect, useMemo, useState } from "react"; import { useTexture } from "@react-three/drei"; const FxMaterialImpl = createFxMaterialImpl(); diff --git a/packages/use-shader-fx/src/materials/core/BasicFxLib.ts b/packages/use-shader-fx/src/materials/core/BasicFxLib.ts index 12ee7c5e..a5baf6a0 100644 --- a/packages/use-shader-fx/src/materials/core/BasicFxLib.ts +++ b/packages/use-shader-fx/src/materials/core/BasicFxLib.ts @@ -48,8 +48,10 @@ export type BasicFxFlag = { }; /** valuesのkeyにbasicFxが含まれているかどうかの判定 */ +// TODO : rename to isContainsBasicFxValues function containsBasicFxValues(values?: { [key: string]: any }): boolean { if (!values) return false; + // THINK : ここでflattenUniformValuesを呼び出すべき? const _values = flattenUniformValues(values); return Object.keys(_values).some((key) => Object.keys(DEFAULT_BASICFX_VALUES).includes(key as keyof BasicFxValues) @@ -58,6 +60,8 @@ function containsBasicFxValues(values?: { [key: string]: any }): boolean { function setupDefaultFlag(uniformValues?: BasicFxValues): BasicFxFlag { return { + // THINK : `handleUpdateBasicFx`での判定は、uniformの値で行っている.例えばsaturation・brightnessとかはどう判定する? + // THINK : `isMixSrc` みたいなuniform値をつくる? uniformValues?.mixSrcを判定するイメージ mixSrc: uniformValues?.mixSrc ? true : false, mixDst: uniformValues?.mixDst ? true : false, }; @@ -70,6 +74,8 @@ function handleUpdateBasicFx( validCount: number; updatedFlag: BasicFxFlag; } { + // THINK : `handleUpdateBasicFx`での判定は、uniformの値で行っている.例えばsaturation・brightnessとかはどう判定する? + // THINK : `isMixSrc` みたいなuniform値をつくる? uniformValues?.mixSrcを判定するイメージ const isMixSrc = uniforms.mixSrc_src.value ? true : false; const isMixDst = uniforms.mixDst_src.value ? true : false; diff --git a/packages/use-shader-fx/src/materials/core/BasicFxMaterial.ts b/packages/use-shader-fx/src/materials/core/BasicFxMaterial.ts index c1c4f1da..45376d71 100644 --- a/packages/use-shader-fx/src/materials/core/BasicFxMaterial.ts +++ b/packages/use-shader-fx/src/materials/core/BasicFxMaterial.ts @@ -104,7 +104,9 @@ export class BasicFxMaterial extends FxMaterial { override super class method ===============================================*/ setUniformValues(values?: { [key: string]: any }) { + // THINK : `flattenUniformValues`するのはこのレイヤーの方がいいかも super.setUniformValues(values); + // THINK : flattenUniformValuesしたあとで、containsBasicFxValuesに渡せばいい。containsBasicFxValuesでflattenUniformValuesを実行してるので、二度手間になっている if (BasicFxLib.containsBasicFxValues(values)) { this.updateBasicFx(); } diff --git a/packages/use-shader-fx/src/materials/core/FxMaterial.ts b/packages/use-shader-fx/src/materials/core/FxMaterial.ts index 138fea25..d82362fb 100644 --- a/packages/use-shader-fx/src/materials/core/FxMaterial.ts +++ b/packages/use-shader-fx/src/materials/core/FxMaterial.ts @@ -16,7 +16,7 @@ export type DefaultUniforms = { export type FxMaterialProps = { uniformValues?: T; - materialParameters?: {}; + materialParameters?: THREE.ShaderMaterialParameters; } & ShaderWithUniforms; export class FxMaterial extends THREE.ShaderMaterial { @@ -29,7 +29,7 @@ export class FxMaterial extends THREE.ShaderMaterial { vertexShader, fragmentShader, }: FxMaterialProps = {}) { - super(); + super(materialParameters); this.uniforms = THREE.UniformsUtils.merge([ { @@ -44,7 +44,6 @@ export class FxMaterial extends THREE.ShaderMaterial { this.setupDefaultShaders(vertexShader, fragmentShader); this.setUniformValues(uniformValues); - this.setValues(materialParameters); this.defineUniformAccessors(); } diff --git a/packages/use-shader-fx/src/utils/useResolution.ts b/packages/use-shader-fx/src/utils/useResolution.ts index 712e51e4..a11e8b27 100644 --- a/packages/use-shader-fx/src/utils/useResolution.ts +++ b/packages/use-shader-fx/src/utils/useResolution.ts @@ -5,6 +5,7 @@ import { Size } from "../hooks/types"; /** * @params dpr if dpr is set, it returns the resolution which is size multiplied by dpr. */ +// TODO : materialを引数に取る場合はmaterialのupdateResolutionを呼び出す:M extends FxMaterial export const useResolution = (size: Size, dpr: number | false = false) => { const _width = dpr ? size.width * dpr : size.width; const _height = dpr ? size.height * dpr : size.height; diff --git a/todo b/todo index 3c01ed4c..a2d866c3 100644 --- a/todo +++ b/todo @@ -2,10 +2,6 @@ - createMaterialImplにして、引数に関数で引数にチャンクとれるみたいな。第二引数でマテリアルの種類選べるみたいな。 - 実装クラスを生成する関数 -- SamplingFxMaterialの実装 - - rgbShiftなど - - basicFxLibを拡張する - - fluid - advectionのdisipationを追加する - deltaTimeも操作できるように @@ -16,7 +12,6 @@ - basic fx - basicFxに色調補正系 - fluid contrastを参考に - - mixSrc,mixDstのblendingMode - micSrc => 色調補正系 => micDstの順 From 086db67d484ca788916424eb5c965757d3513dc0 Mon Sep 17 00:00:00 2001 From: roku-ft Date: Tue, 12 Nov 2024 13:40:22 +0900 Subject: [PATCH 34/60] rename useBlur to useBoxBlur --- app/v2/Playground.tsx | 6 +-- app/v2_impl/Playground.tsx | 4 +- app/v2_impl_colorAdjustments/Playground.tsx | 1 - .../{useBlur => blur/useBoxBlur}/index.ts | 26 ++++++------ packages/use-shader-fx/src/hooks/index.ts | 13 +++--- .../materials/impl/boxBlur/BoxBlurMaterial.ts | 41 +++++++++++++++++++ .../materials/impl/boxBlur/boxBlur.glsl.ts | 32 +++++++++++++++ packages/use-shader-fx/src/materials/index.js | 1 + 8 files changed, 99 insertions(+), 25 deletions(-) rename packages/use-shader-fx/src/hooks/{useBlur => blur/useBoxBlur}/index.ts (70%) create mode 100644 packages/use-shader-fx/src/materials/impl/boxBlur/BoxBlurMaterial.ts create mode 100644 packages/use-shader-fx/src/materials/impl/boxBlur/boxBlur.glsl.ts diff --git a/app/v2/Playground.tsx b/app/v2/Playground.tsx index 368f6edb..d817f2be 100644 --- a/app/v2/Playground.tsx +++ b/app/v2/Playground.tsx @@ -3,7 +3,7 @@ import * as THREE from "three"; import { useRef, useState } from "react"; import { useFrame, useThree, extend, createPortal } from "@react-three/fiber"; -import { useNoise, useBlur, useSingleFBO } from "@/packages/use-shader-fx/src"; +import { useNoise, useBoxBlur, useSingleFBO } from "@/packages/use-shader-fx/src"; import { FxMaterial } from "./FxMaterial"; import { Float, OrbitControls } from "@react-three/drei"; @@ -22,7 +22,7 @@ export const Playground = () => { depthBuffer: true, }); - const blur = useBlur({ + const blur = useBoxBlur({ size, dpr: 0.4, blurSize: 4, @@ -30,7 +30,7 @@ export const Playground = () => { src: renderTarget.texture, }); - const gooey = useBlur({ + const gooey = useBoxBlur({ size, dpr: 2, blurSize: 4, diff --git a/app/v2_impl/Playground.tsx b/app/v2_impl/Playground.tsx index a4fae91a..264c7763 100644 --- a/app/v2_impl/Playground.tsx +++ b/app/v2_impl/Playground.tsx @@ -6,7 +6,7 @@ import { useFrame, useThree, extend, createPortal } from "@react-three/fiber"; import { useNoise, NoiseValues, - useBlur, + useBoxBlur, useSingleFBO, createFxMaterialImpl, createBasicFxMaterialImpl, @@ -49,7 +49,7 @@ export const Playground = () => { depthBuffer: true, }); - // const blur = useBlur({ + // const blur = useBoxBlur({ // size, // dpr: 1, // src: renderTarget.texture, diff --git a/app/v2_impl_colorAdjustments/Playground.tsx b/app/v2_impl_colorAdjustments/Playground.tsx index 384ebe9c..9fbf3c98 100644 --- a/app/v2_impl_colorAdjustments/Playground.tsx +++ b/app/v2_impl_colorAdjustments/Playground.tsx @@ -6,7 +6,6 @@ import { useFrame, useThree, extend, createPortal } from "@react-three/fiber"; import { useNoise, NoiseValues, - useBlur, useSingleFBO, createFxMaterialImpl, createBasicFxMaterialImpl, diff --git a/packages/use-shader-fx/src/hooks/useBlur/index.ts b/packages/use-shader-fx/src/hooks/blur/useBoxBlur/index.ts similarity index 70% rename from packages/use-shader-fx/src/hooks/useBlur/index.ts rename to packages/use-shader-fx/src/hooks/blur/useBoxBlur/index.ts index 9667de3b..fa06cb83 100644 --- a/packages/use-shader-fx/src/hooks/useBlur/index.ts +++ b/packages/use-shader-fx/src/hooks/blur/useBoxBlur/index.ts @@ -1,21 +1,21 @@ import { useCallback } from "react"; -import { HooksProps, HooksReturn } from "../types"; -import { getDpr } from "../../utils/getDpr"; -import { RootState } from "../types"; -import { BlurMaterial, BlurValues } from "../../materials"; -import { useFxScene } from "../../utils/useFxScene"; -import { useDoubleFBO } from "../../utils/useDoubleFBO"; +import { HooksProps, HooksReturn } from "../../types"; +import { getDpr } from "../../../utils/getDpr"; +import { RootState } from "../../types"; +import { BoxBlurMaterial, BoxBlurValues } from "../../../materials"; +import { useFxScene } from "../../../utils/useFxScene"; +import { useDoubleFBO } from "../../../utils/useDoubleFBO"; -type BlurConfig = { +type BoxBlurConfig = { blurIteration?: number; }; -export type BlurProps = HooksProps & BlurValues & BlurConfig; +export type BoxBlurProps = HooksProps & BoxBlurValues & BoxBlurConfig; /** * @link https://github.com/FunTechInc/use-shader-fx?tab=readme-ov-file#usage */ -export const useBlur = ({ +export const useBoxBlur = ({ size, dpr, fboAutoSetSize, @@ -23,13 +23,13 @@ export const useBlur = ({ materialParameters, blurIteration = 5, ...uniformValues -}: BlurProps): HooksReturn => { +}: BoxBlurProps): HooksReturn => { const _dpr = getDpr(dpr); const { scene, material, camera } = useFxScene({ size, dpr: _dpr.shader, - material: BlurMaterial, + material: BoxBlurMaterial, uniformValues, materialParameters, }); @@ -44,14 +44,14 @@ export const useBlur = ({ }); const setValues = useCallback( - (newValues: BlurValues) => { + (newValues: BoxBlurValues) => { material.setUniformValues(newValues); }, [material] ); const render = useCallback( - (rootState: RootState, newValues?: BlurValues) => { + (rootState: RootState, newValues?: BoxBlurValues) => { const { gl } = rootState; newValues && setValues(newValues); diff --git a/packages/use-shader-fx/src/hooks/index.ts b/packages/use-shader-fx/src/hooks/index.ts index b733a765..acfa6fba 100644 --- a/packages/use-shader-fx/src/hooks/index.ts +++ b/packages/use-shader-fx/src/hooks/index.ts @@ -1,18 +1,19 @@ -import { useBlur, BlurProps } from "./useBlur"; +import { useBoxBlur, BoxBlurProps } from "./blur/useBoxBlur"; import { useCoverTexture, CoverTextureProps } from "./useCoverTexture"; import { useFluid, FluidProps } from "./useFluid"; import { useNoise, NoiseProps } from "./useNoise"; import { useRawBlank, RawBlankProps } from "./useRawBlank"; -export type FxTypes = - | typeof useBlur +export type FxTypes = + | typeof useBoxBlur | typeof useCoverTexture | typeof useFluid | typeof useNoise | typeof useRawBlank; -export type FxProps = T extends typeof useBlur - ? BlurProps +export type FxProps = + T extends typeof useBoxBlur + ? BoxBlurProps : T extends typeof useCoverTexture ? CoverTextureProps : T extends typeof useNoise @@ -23,7 +24,7 @@ export type FxProps = T extends typeof useBlur ? RawBlankProps : never; -export * from "./useBlur"; +export * from "./blur/useBoxBlur"; export * from "./useCoverTexture"; export * from "./useFluid"; export * from "./useNoise"; diff --git a/packages/use-shader-fx/src/materials/impl/boxBlur/BoxBlurMaterial.ts b/packages/use-shader-fx/src/materials/impl/boxBlur/BoxBlurMaterial.ts new file mode 100644 index 00000000..82e64a9b --- /dev/null +++ b/packages/use-shader-fx/src/materials/impl/boxBlur/BoxBlurMaterial.ts @@ -0,0 +1,41 @@ +import { fragment, vertex } from "./boxBlur.glsl"; +import { BasicFxMaterial } from "../../core/BasicFxMaterial"; +import { FxMaterialProps } from "../../core/FxMaterial"; +import { BasicFxUniforms, BasicFxValues } from "../../core/BasicFxLib"; +import { NestUniformValues } from "../../../shaders/uniformsUtils"; +import { TexturePipelineSrc } from "../../../misc"; + +type BoxBlurUniforms = { + /** */ + src: { value: TexturePipelineSrc }; + /** */ + blurSize: { value: number }; +} & BasicFxUniforms; + +export type BoxBlurValues = NestUniformValues & BasicFxValues; + +export class BoxBlurMaterial extends BasicFxMaterial { + static get type() { + return "BoxBlurMaterial"; + } + + uniforms!: BoxBlurUniforms; + + constructor({ + uniformValues, + materialParameters = {}, + }: FxMaterialProps) { + super({ + vertexShader: vertex, + fragmentShader: fragment, + uniformValues, + materialParameters, + uniforms: { + src: { value: null }, + blurSize: { value: 5 }, + } as BoxBlurUniforms, + }); + + this.type = BoxBlurMaterial.type; + } +} diff --git a/packages/use-shader-fx/src/materials/impl/boxBlur/boxBlur.glsl.ts b/packages/use-shader-fx/src/materials/impl/boxBlur/boxBlur.glsl.ts new file mode 100644 index 00000000..e856eb56 --- /dev/null +++ b/packages/use-shader-fx/src/materials/impl/boxBlur/boxBlur.glsl.ts @@ -0,0 +1,32 @@ +import { ShaderLib } from "../../../shaders/ShaderLib"; + +export const vertex = ` + void main() { + ${ShaderLib.plane_vertex} + } +`; + +export const fragment = ` + uniform sampler2D src; + uniform float blurSize; + + void main() { + + vec2 perDivSize = blurSize / resolution; + + vec4 outColor = vec4( + texture2D(src, vUv + perDivSize * vec2(-1.0, -1.0)) + + texture2D(src, vUv + perDivSize * vec2(0.0, -1.0)) + + texture2D(src, vUv + perDivSize * vec2(1.0, -1.0)) + + texture2D(src, vUv + perDivSize * vec2(-1.0, 0.0)) + + texture2D(src, vUv + perDivSize * vec2(0.0, 0.0)) + + texture2D(src, vUv + perDivSize * vec2(1.0, 0.0)) + + texture2D(src, vUv + perDivSize * vec2(-1.0, 1.0)) + + texture2D(src, vUv + perDivSize * vec2(0.0, 1.0)) + + texture2D(src, vUv + perDivSize * vec2(1.0, 1.0)) + ) / 9.0; + + gl_FragColor = outColor; + + } +`; diff --git a/packages/use-shader-fx/src/materials/index.js b/packages/use-shader-fx/src/materials/index.js index a6f9ae19..5786eeae 100644 --- a/packages/use-shader-fx/src/materials/index.js +++ b/packages/use-shader-fx/src/materials/index.js @@ -5,4 +5,5 @@ export * from "./impl/noise/NoiseMaterial"; export * from "./impl/rawBlank/RawBlankMaterial"; export * from "./impl/fluid"; export * from "./impl/blur/BlurMaterial"; +export * from "./impl/boxBlur/BoxBlurMaterial"; export * from "./impl/cover/CoverTextureMaterial"; From cd46f8bba8d7223ddb0834c53a6e03d3531821fd Mon Sep 17 00:00:00 2001 From: roku-ft Date: Tue, 12 Nov 2024 13:48:44 +0900 Subject: [PATCH 35/60] remove blurMaterial --- .../src/materials/impl/blur/BlurMaterial.ts | 42 ------------------- .../src/materials/impl/blur/blur.glsl.ts | 32 -------------- packages/use-shader-fx/src/materials/index.js | 1 - 3 files changed, 75 deletions(-) delete mode 100644 packages/use-shader-fx/src/materials/impl/blur/BlurMaterial.ts delete mode 100644 packages/use-shader-fx/src/materials/impl/blur/blur.glsl.ts diff --git a/packages/use-shader-fx/src/materials/impl/blur/BlurMaterial.ts b/packages/use-shader-fx/src/materials/impl/blur/BlurMaterial.ts deleted file mode 100644 index 579e2d58..00000000 --- a/packages/use-shader-fx/src/materials/impl/blur/BlurMaterial.ts +++ /dev/null @@ -1,42 +0,0 @@ -import * as THREE from "three"; -import { fragment, vertex } from "./blur.glsl"; -import { BasicFxMaterial } from "../../core/BasicFxMaterial"; -import { FxMaterialProps } from "../../core/FxMaterial"; -import { BasicFxUniforms, BasicFxValues } from "../../core/BasicFxLib"; -import { NestUniformValues } from "../../../shaders/uniformsUtils"; -import { TexturePipelineSrc } from "../../../misc"; - -type BlurUniforms = { - /** */ - src: { value: TexturePipelineSrc }; - /** */ - blurSize: { value: number }; -} & BasicFxUniforms; - -export type BlurValues = NestUniformValues & BasicFxValues; - -export class BlurMaterial extends BasicFxMaterial { - static get type() { - return "BlurMaterial"; - } - - uniforms!: BlurUniforms; - - constructor({ - uniformValues, - materialParameters = {}, - }: FxMaterialProps) { - super({ - vertexShader: vertex, - fragmentShader: fragment, - uniformValues, - materialParameters, - uniforms: { - src: { value: null }, - blurSize: { value: 5 }, - } as BlurUniforms, - }); - - this.type = BlurMaterial.type; - } -} diff --git a/packages/use-shader-fx/src/materials/impl/blur/blur.glsl.ts b/packages/use-shader-fx/src/materials/impl/blur/blur.glsl.ts deleted file mode 100644 index e856eb56..00000000 --- a/packages/use-shader-fx/src/materials/impl/blur/blur.glsl.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { ShaderLib } from "../../../shaders/ShaderLib"; - -export const vertex = ` - void main() { - ${ShaderLib.plane_vertex} - } -`; - -export const fragment = ` - uniform sampler2D src; - uniform float blurSize; - - void main() { - - vec2 perDivSize = blurSize / resolution; - - vec4 outColor = vec4( - texture2D(src, vUv + perDivSize * vec2(-1.0, -1.0)) + - texture2D(src, vUv + perDivSize * vec2(0.0, -1.0)) + - texture2D(src, vUv + perDivSize * vec2(1.0, -1.0)) + - texture2D(src, vUv + perDivSize * vec2(-1.0, 0.0)) + - texture2D(src, vUv + perDivSize * vec2(0.0, 0.0)) + - texture2D(src, vUv + perDivSize * vec2(1.0, 0.0)) + - texture2D(src, vUv + perDivSize * vec2(-1.0, 1.0)) + - texture2D(src, vUv + perDivSize * vec2(0.0, 1.0)) + - texture2D(src, vUv + perDivSize * vec2(1.0, 1.0)) - ) / 9.0; - - gl_FragColor = outColor; - - } -`; diff --git a/packages/use-shader-fx/src/materials/index.js b/packages/use-shader-fx/src/materials/index.js index 5786eeae..210b881b 100644 --- a/packages/use-shader-fx/src/materials/index.js +++ b/packages/use-shader-fx/src/materials/index.js @@ -4,6 +4,5 @@ export * from "./impl/BasicFxMaterialImpl"; export * from "./impl/noise/NoiseMaterial"; export * from "./impl/rawBlank/RawBlankMaterial"; export * from "./impl/fluid"; -export * from "./impl/blur/BlurMaterial"; export * from "./impl/boxBlur/BoxBlurMaterial"; export * from "./impl/cover/CoverTextureMaterial"; From 467981cf3a52a2cd723c2ede30b39437af6f9f04 Mon Sep 17 00:00:00 2001 From: roku-ft Date: Tue, 12 Nov 2024 14:05:36 +0900 Subject: [PATCH 36/60] add directory to add other blur material --- .../impl/{ => blur}/boxBlur/BoxBlurMaterial.ts | 10 +++++----- .../materials/impl/{ => blur}/boxBlur/boxBlur.glsl.ts | 2 +- packages/use-shader-fx/src/materials/index.js | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) rename packages/use-shader-fx/src/materials/impl/{ => blur}/boxBlur/BoxBlurMaterial.ts (72%) rename packages/use-shader-fx/src/materials/impl/{ => blur}/boxBlur/boxBlur.glsl.ts (93%) diff --git a/packages/use-shader-fx/src/materials/impl/boxBlur/BoxBlurMaterial.ts b/packages/use-shader-fx/src/materials/impl/blur/boxBlur/BoxBlurMaterial.ts similarity index 72% rename from packages/use-shader-fx/src/materials/impl/boxBlur/BoxBlurMaterial.ts rename to packages/use-shader-fx/src/materials/impl/blur/boxBlur/BoxBlurMaterial.ts index 82e64a9b..805ad493 100644 --- a/packages/use-shader-fx/src/materials/impl/boxBlur/BoxBlurMaterial.ts +++ b/packages/use-shader-fx/src/materials/impl/blur/boxBlur/BoxBlurMaterial.ts @@ -1,9 +1,9 @@ import { fragment, vertex } from "./boxBlur.glsl"; -import { BasicFxMaterial } from "../../core/BasicFxMaterial"; -import { FxMaterialProps } from "../../core/FxMaterial"; -import { BasicFxUniforms, BasicFxValues } from "../../core/BasicFxLib"; -import { NestUniformValues } from "../../../shaders/uniformsUtils"; -import { TexturePipelineSrc } from "../../../misc"; +import { BasicFxMaterial } from "../../../core/BasicFxMaterial"; +import { FxMaterialProps } from "../../../core/FxMaterial"; +import { BasicFxUniforms, BasicFxValues } from "../../../core/BasicFxLib"; +import { NestUniformValues } from "../../../../shaders/uniformsUtils"; +import { TexturePipelineSrc } from "../../../../misc"; type BoxBlurUniforms = { /** */ diff --git a/packages/use-shader-fx/src/materials/impl/boxBlur/boxBlur.glsl.ts b/packages/use-shader-fx/src/materials/impl/blur/boxBlur/boxBlur.glsl.ts similarity index 93% rename from packages/use-shader-fx/src/materials/impl/boxBlur/boxBlur.glsl.ts rename to packages/use-shader-fx/src/materials/impl/blur/boxBlur/boxBlur.glsl.ts index e856eb56..a8e17865 100644 --- a/packages/use-shader-fx/src/materials/impl/boxBlur/boxBlur.glsl.ts +++ b/packages/use-shader-fx/src/materials/impl/blur/boxBlur/boxBlur.glsl.ts @@ -1,4 +1,4 @@ -import { ShaderLib } from "../../../shaders/ShaderLib"; +import { ShaderLib } from "../../../../shaders/ShaderLib"; export const vertex = ` void main() { diff --git a/packages/use-shader-fx/src/materials/index.js b/packages/use-shader-fx/src/materials/index.js index 210b881b..3ee6574d 100644 --- a/packages/use-shader-fx/src/materials/index.js +++ b/packages/use-shader-fx/src/materials/index.js @@ -4,5 +4,5 @@ export * from "./impl/BasicFxMaterialImpl"; export * from "./impl/noise/NoiseMaterial"; export * from "./impl/rawBlank/RawBlankMaterial"; export * from "./impl/fluid"; -export * from "./impl/boxBlur/BoxBlurMaterial"; +export * from "./impl/blur/boxBlur/BoxBlurMaterial"; export * from "./impl/cover/CoverTextureMaterial"; From cbc83d4579fecc55b0733c212b6a9ac381079a03 Mon Sep 17 00:00:00 2001 From: roku-ft Date: Tue, 12 Nov 2024 20:31:56 +0900 Subject: [PATCH 37/60] #138 add GaussianBlur --- .../src/hooks/blur/useGaussianBlur/index.ts | 99 +++++++++++++++++ .../blur/gaussianBlur/GaussianBlurMaterial.ts | 101 ++++++++++++++++++ .../impl/blur/gaussianBlur/boxBlur.glsl.ts | 55 ++++++++++ packages/use-shader-fx/src/materials/index.js | 1 + 4 files changed, 256 insertions(+) create mode 100644 packages/use-shader-fx/src/hooks/blur/useGaussianBlur/index.ts create mode 100644 packages/use-shader-fx/src/materials/impl/blur/gaussianBlur/GaussianBlurMaterial.ts create mode 100644 packages/use-shader-fx/src/materials/impl/blur/gaussianBlur/boxBlur.glsl.ts diff --git a/packages/use-shader-fx/src/hooks/blur/useGaussianBlur/index.ts b/packages/use-shader-fx/src/hooks/blur/useGaussianBlur/index.ts new file mode 100644 index 00000000..d13651b4 --- /dev/null +++ b/packages/use-shader-fx/src/hooks/blur/useGaussianBlur/index.ts @@ -0,0 +1,99 @@ +import { useCallback, useEffect, useMemo } from "react"; +import { HooksProps, HooksReturn } from "../../types"; +import { getDpr } from "../../../utils/getDpr"; +import { RootState } from "../../types"; +import { GaussianBlurMaterial, GaussianBlurValues } from "../../../materials"; +import { useFxScene } from "../../../utils/useFxScene"; +import { useDoubleFBO } from "../../../utils/useDoubleFBO"; +import * as THREE from "three"; + +type GaussianBlurConfig = { + radius?: number; +}; + +export type GaussianBlurProps = HooksProps & GaussianBlurValues & GaussianBlurConfig; + +export const useGaussianBlur = ({ + size, + dpr, + fboAutoSetSize, + renderTargetOptions, + materialParameters, + radius = 1, + src, + ...uniformValues +}: GaussianBlurProps +): HooksReturn => { + const _dpr = getDpr(dpr); + + const { scene, material, camera } = useFxScene({ + size, + dpr: _dpr.shader, + material: GaussianBlurMaterial, + uniformValues, + materialParameters: { + defines: { + "KERNEL_SIZE": radius, + }, + ...materialParameters, + }, + }); + + useEffect(() => { + material.setBlurRadius(radius); + },[material, radius]); + + useEffect(() => { + material.setStep({size}); + }, [material, size]); + + const [renderTarget, updateRenderTarget] = useDoubleFBO({ + scene, + camera, + size, + dpr: _dpr.fbo, + fboAutoSetSize, + ...renderTargetOptions, + }); + + const setValues = useCallback( + (newValues: GaussianBlurValues) => { + material.setUniformValues(newValues); + }, + [material] + ); + + const render = useCallback( + (rootState: RootState, newValues?: GaussianBlurValues) => { + const { gl } = rootState; + newValues && setValues(newValues); + + // draw vertical blur + updateRenderTarget({ gl }, () => { + material.uniforms.src.value = src || new THREE.Texture(); + material.uniforms.u_stepSize.value.set(0, 1); + material.updateBasicFx(); + }); + + // draw horizontal blur + updateRenderTarget({ gl }, ({ read }) => { + material.uniforms.src.value = read; + material.uniforms.u_stepSize.value.set(1, 0); + material.updateBasicFx(); + }) + + return renderTarget.read.texture; + }, + [setValues, updateRenderTarget, material, renderTarget, src] + ); + + return { + render, + setValues, + texture: renderTarget.read.texture, + material, + scene, + camera, + renderTarget, + }; +}; diff --git a/packages/use-shader-fx/src/materials/impl/blur/gaussianBlur/GaussianBlurMaterial.ts b/packages/use-shader-fx/src/materials/impl/blur/gaussianBlur/GaussianBlurMaterial.ts new file mode 100644 index 00000000..28389082 --- /dev/null +++ b/packages/use-shader-fx/src/materials/impl/blur/gaussianBlur/GaussianBlurMaterial.ts @@ -0,0 +1,101 @@ +import * as THREE from "three"; +import { fragment, vertex } from "./boxBlur.glsl"; +import { BasicFxMaterial } from "../../../core/BasicFxMaterial"; +import { FxMaterialProps } from "../../../core/FxMaterial"; +import { BasicFxUniforms, BasicFxValues } from "../../../core/BasicFxLib"; +import { NestUniformValues } from "../../../../shaders/uniformsUtils"; +import { TexturePipelineSrc } from "../../../../misc"; +import { Size } from "../../../../hooks/types"; + +type GaussianBlurUniforms = { + /** */ + src: { value: TexturePipelineSrc }; + /** */ + sigma: { + value: THREE.Vector2 + }, + u_weights: { + value: number[] + }, + u_step: { + value: THREE.Vector2 + }, + u_stepSize: { + value: THREE.Vector2 + }, +} & BasicFxUniforms; + +export type GaussianBlurValues = NestUniformValues & BasicFxValues; + +export class GaussianBlurMaterial extends BasicFxMaterial { + static get type() { + return "GaussianBlurMaterial"; + } + + uniforms!: GaussianBlurUniforms; + + constructor({ + uniformValues, + materialParameters = {}, + }: FxMaterialProps) { + super({ + vertexShader: vertex, + fragmentShader: fragment, + uniformValues, + materialParameters: { + defines: { + "KERNEL_SIZE": 1, + }, + ...materialParameters, + }, + uniforms: { + src: { + value: null + }, + sigma: { + value: new THREE.Vector2(1,1) + }, + u_weights: { + value: [0] + }, + u_step: { + value: new THREE.Vector2(0,0) + }, + u_stepSize: { + value: new THREE.Vector2(0) + }, + } as GaussianBlurUniforms, + }); + + this.type = GaussianBlurMaterial.type; + } + + setBlurRadius(kernelSize: number) { + const weights = [] + let t = 0.0; + + for(let i = kernelSize - 1; i >= 0; i--){ + let r = 1.0 + 2.0 * i; + let w = Math.exp(-0.5 * (r * r) / (kernelSize * kernelSize)); + weights.push(w); + if(i > 0){w *= 2.0;} + t += w; + } + + for(let i = 0; i < weights.length; i++){ + weights[i] /= t; + } + + // materiaに反映して更新を通知 + this.defines.KERNEL_SIZE = weights.length; + this.uniforms.u_weights.value = weights; + this.needsUpdate = true; + } + + setStep({size}:{size?: Size}) { + this.uniforms.u_step.value.set( + 1 / (size?.width || this.uniforms.resolution.value.x || window.innerWidth), + 1 / (size?.height || this.uniforms.resolution.value.y || window.innerHeight) + ); + } +} diff --git a/packages/use-shader-fx/src/materials/impl/blur/gaussianBlur/boxBlur.glsl.ts b/packages/use-shader-fx/src/materials/impl/blur/gaussianBlur/boxBlur.glsl.ts new file mode 100644 index 00000000..d2eb8b2f --- /dev/null +++ b/packages/use-shader-fx/src/materials/impl/blur/gaussianBlur/boxBlur.glsl.ts @@ -0,0 +1,55 @@ +import { ShaderLib } from "../../../../shaders/ShaderLib"; + +export const vertex = ` + void main() { + ${ShaderLib.plane_vertex} + } +`; + +export const fragment = ` + uniform sampler2D src; + uniform vec2 u_step; + uniform vec2 u_stepSize; + uniform vec2 sigma; + uniform float u_weights[KERNEL_SIZE]; + + void main() { + + float count = float(KERNEL_SIZE) - 1.0; + + vec4 color = vec4(0.0); + vec4 sum = vec4(0.0); + float w; + float sumW = 0.0; + float actualWeight; + vec2 stepSize = u_stepSize * sigma; + + for(int i = 0; i < KERNEL_SIZE - 1; i++){ + + w = u_weights[i]; + color = texture2D( src, vUv - count * u_step * stepSize ); + actualWeight = w * color.a; + sum.rgb += color.rgb * actualWeight; + sum.a += color.a * w; + sumW += actualWeight; + + color = texture2D( src, vUv + count * u_step * stepSize ); + actualWeight = w * color.a; + sum.rgb += color.rgb * actualWeight; + sum.a += color.a * w; + sumW += actualWeight; + + count--; + } + + w = u_weights[KERNEL_SIZE - 1]; + + color = texture2D( src, vUv ); + actualWeight = w * color.a; + sum.rgb += color.rgb * actualWeight; + sum.a += color.a * w; + sumW += actualWeight; + + gl_FragColor = vec4(sum.rgb / sumW, sum.a); + } +`; diff --git a/packages/use-shader-fx/src/materials/index.js b/packages/use-shader-fx/src/materials/index.js index 3ee6574d..8c272be1 100644 --- a/packages/use-shader-fx/src/materials/index.js +++ b/packages/use-shader-fx/src/materials/index.js @@ -5,4 +5,5 @@ export * from "./impl/noise/NoiseMaterial"; export * from "./impl/rawBlank/RawBlankMaterial"; export * from "./impl/fluid"; export * from "./impl/blur/boxBlur/BoxBlurMaterial"; +export * from "./impl/blur/gaussianBlur/GaussianBlurMaterial"; export * from "./impl/cover/CoverTextureMaterial"; From 3e121ebb049c8401404a4a73930697fac5ddcce7 Mon Sep 17 00:00:00 2001 From: takuma-hmng8 Date: Fri, 15 Nov 2024 19:44:46 +0900 Subject: [PATCH 38/60] update --- app/v2/Playground.tsx | 8 +- app/v2_pipe/Playground.tsx | 5 + app/v2_test/Playground.tsx | 79 +++++++++++++++ app/v2_test/page.tsx | 39 ++++++++ .../src/hooks/blur/useBoxBlur/index.ts | 26 +++-- .../src/hooks/blur/useGaussianBlur/index.ts | 66 +++++++------ .../blur/gaussianBlur/GaussianBlurMaterial.ts | 95 +++++++++++-------- .../use-shader-fx/src/utils/useFxScene.ts | 5 +- .../src/utils/useMutableConfig.ts | 26 +++++ .../use-shader-fx/src/utils/useResolution.ts | 10 +- 10 files changed, 271 insertions(+), 88 deletions(-) create mode 100644 app/v2_test/Playground.tsx create mode 100644 app/v2_test/page.tsx create mode 100644 packages/use-shader-fx/src/utils/useMutableConfig.ts diff --git a/app/v2/Playground.tsx b/app/v2/Playground.tsx index d817f2be..eb3b59da 100644 --- a/app/v2/Playground.tsx +++ b/app/v2/Playground.tsx @@ -1,9 +1,13 @@ "use client"; import * as THREE from "three"; -import { useRef, useState } from "react"; +import { useEffect, useRef, useState } from "react"; import { useFrame, useThree, extend, createPortal } from "@react-three/fiber"; -import { useNoise, useBoxBlur, useSingleFBO } from "@/packages/use-shader-fx/src"; +import { + useNoise, + useBoxBlur, + useSingleFBO, +} from "@/packages/use-shader-fx/src"; import { FxMaterial } from "./FxMaterial"; import { Float, OrbitControls } from "@react-three/drei"; diff --git a/app/v2_pipe/Playground.tsx b/app/v2_pipe/Playground.tsx index e299f7c8..69fa1808 100644 --- a/app/v2_pipe/Playground.tsx +++ b/app/v2_pipe/Playground.tsx @@ -11,6 +11,7 @@ import { usePipeline, } from "@/packages/use-shader-fx/src"; import { useTexture } from "@react-three/drei"; +import * as THREE from "three"; const FxMaterialImpl = createFxMaterialImpl(); const BasicFxMaterialImpl = createBasicFxMaterialImpl(); @@ -103,6 +104,10 @@ export const Playground = () => { useFrame((state) => render(state)); + const color1 = new THREE.Color(0x000000); + const color2 = new THREE.Color(0x000000); + console.log(color1 === color2); + return ( diff --git a/app/v2_test/Playground.tsx b/app/v2_test/Playground.tsx new file mode 100644 index 00000000..f7903950 --- /dev/null +++ b/app/v2_test/Playground.tsx @@ -0,0 +1,79 @@ +"use client"; + +import * as THREE from "three"; +import { useEffect, useRef, useState } from "react"; +import { useFrame, useThree, extend, createPortal } from "@react-three/fiber"; +import { + useNoise, + NoiseValues, + useBoxBlur, + useSingleFBO, + createFxMaterialImpl, + createBasicFxMaterialImpl, + FxMaterialImplValues, + BasicFxMaterialImplValues, + useFluid, + useCoverTexture, +} from "@/packages/use-shader-fx/src"; +import { Float, OrbitControls, useTexture } from "@react-three/drei"; +import { useGaussianBlur } from "@/packages/use-shader-fx/src/hooks/blur/useGaussianBlur"; + +const FxMaterialImpl = createFxMaterialImpl({ + fragmentShader: ` + uniform sampler2D src; + void main() { + vec2 vel = texture2D(src, vUv).xy; + float len = length(vel); + vel = vel * 0.5 + 0.5; + + vec3 color = vec3(vel.x, vel.y, 1.0); + color = mix(vec3(1.0), color, len); + + gl_FragColor = vec4(color, 1.0); + } +`, +}); +const BasicFxMaterialImpl = createBasicFxMaterialImpl(); + +extend({ FxMaterialImpl, BasicFxMaterialImpl }); + +export const Playground = () => { + const { size, viewport, camera } = useThree(); + + const [app] = useTexture(["/app-head.jpg"]); + + const blur = useBoxBlur({ + size, + dpr: 1, + // radius: 19, + // blurIteration: 1, + src: app, + }); + + blur.setValues({ + // radius: 9, + blurIteration: 20, + }); + + useFrame((state) => { + blur.render(state); + }); + + return ( + + + + + ); +}; + +declare global { + namespace JSX { + interface IntrinsicElements { + fxMaterialImpl: FxMaterialImplValues & + JSX.IntrinsicElements["shaderMaterial"]; + BasicFxMaterialImpl: BasicFxMaterialImplValues & + JSX.IntrinsicElements["shaderMaterial"]; + } + } +} diff --git a/app/v2_test/page.tsx b/app/v2_test/page.tsx new file mode 100644 index 00000000..6256d104 --- /dev/null +++ b/app/v2_test/page.tsx @@ -0,0 +1,39 @@ +import { ShaderFx } from "../ShaderFx"; +import { Playground } from "./Playground"; +import Image from "next/image"; + +export default function Page() { + return ( +
    + {/*
    + +
    */} + + + +
    + ); +} diff --git a/packages/use-shader-fx/src/hooks/blur/useBoxBlur/index.ts b/packages/use-shader-fx/src/hooks/blur/useBoxBlur/index.ts index fa06cb83..89c7de3b 100644 --- a/packages/use-shader-fx/src/hooks/blur/useBoxBlur/index.ts +++ b/packages/use-shader-fx/src/hooks/blur/useBoxBlur/index.ts @@ -1,16 +1,18 @@ -import { useCallback } from "react"; +import { useCallback, useEffect, useState } from "react"; import { HooksProps, HooksReturn } from "../../types"; import { getDpr } from "../../../utils/getDpr"; import { RootState } from "../../types"; import { BoxBlurMaterial, BoxBlurValues } from "../../../materials"; import { useFxScene } from "../../../utils/useFxScene"; import { useDoubleFBO } from "../../../utils/useDoubleFBO"; +import { useMutableConfig } from "../../../utils/useMutableConfig"; type BoxBlurConfig = { blurIteration?: number; }; -export type BoxBlurProps = HooksProps & BoxBlurValues & BoxBlurConfig; +type BoxBlurValuesAndConfig = BoxBlurValues & BoxBlurConfig; +export type BoxBlurProps = HooksProps & BoxBlurValuesAndConfig; /** * @link https://github.com/FunTechInc/use-shader-fx?tab=readme-ov-file#usage @@ -23,7 +25,7 @@ export const useBoxBlur = ({ materialParameters, blurIteration = 5, ...uniformValues -}: BoxBlurProps): HooksReturn => { +}: BoxBlurProps): HooksReturn => { const _dpr = getDpr(dpr); const { scene, material, camera } = useFxScene({ @@ -43,15 +45,21 @@ export const useBoxBlur = ({ ...renderTargetOptions, }); + const [config, setConfig] = useMutableConfig({ + blurIteration, + }); + const setValues = useCallback( - (newValues: BoxBlurValues) => { - material.setUniformValues(newValues); + (newValues: BoxBlurValuesAndConfig) => { + const { blurIteration, ...rest } = newValues; + setConfig({ blurIteration }); + material.setUniformValues(rest); }, - [material] + [material, setConfig] ); const render = useCallback( - (rootState: RootState, newValues?: BoxBlurValues) => { + (rootState: RootState, newValues?: BoxBlurValuesAndConfig) => { const { gl } = rootState; newValues && setValues(newValues); @@ -61,7 +69,7 @@ export const useBoxBlur = ({ updateRenderTarget({ gl }); - for (let i = 0; i < blurIteration; i++) { + for (let i = 0; i < config.current.blurIteration!; i++) { updateRenderTarget({ gl }, ({ read }) => { material.uniforms.src.value = read; }); @@ -71,7 +79,7 @@ export const useBoxBlur = ({ return renderTarget.read.texture; }, - [setValues, updateRenderTarget, material, renderTarget, blurIteration] + [setValues, updateRenderTarget, material, renderTarget, config] ); return { diff --git a/packages/use-shader-fx/src/hooks/blur/useGaussianBlur/index.ts b/packages/use-shader-fx/src/hooks/blur/useGaussianBlur/index.ts index d13651b4..9b7da1c4 100644 --- a/packages/use-shader-fx/src/hooks/blur/useGaussianBlur/index.ts +++ b/packages/use-shader-fx/src/hooks/blur/useGaussianBlur/index.ts @@ -1,4 +1,4 @@ -import { useCallback, useEffect, useMemo } from "react"; +import { useCallback, useEffect } from "react"; import { HooksProps, HooksReturn } from "../../types"; import { getDpr } from "../../../utils/getDpr"; import { RootState } from "../../types"; @@ -6,12 +6,15 @@ import { GaussianBlurMaterial, GaussianBlurValues } from "../../../materials"; import { useFxScene } from "../../../utils/useFxScene"; import { useDoubleFBO } from "../../../utils/useDoubleFBO"; import * as THREE from "three"; +import { useMutableConfig } from "../../../utils/useMutableConfig"; -type GaussianBlurConfig = { - radius?: number; +type GaussianBlurConfig = { + radius?: number; }; -export type GaussianBlurProps = HooksProps & GaussianBlurValues & GaussianBlurConfig; +type GaussianBlurValuesAndConfig = GaussianBlurValues & GaussianBlurConfig; + +export type GaussianBlurProps = HooksProps & GaussianBlurValuesAndConfig; export const useGaussianBlur = ({ size, @@ -19,12 +22,14 @@ export const useGaussianBlur = ({ fboAutoSetSize, renderTargetOptions, materialParameters, - radius = 1, - src, + radius = 1, + src, // TODO * ここでsrcを定義すると、uniformValuesにsrcがふくまれなくなっちゃう ...uniformValues -}: GaussianBlurProps -): HooksReturn => { - const _dpr = getDpr(dpr); +}: GaussianBlurProps): HooksReturn< + GaussianBlurValuesAndConfig, + GaussianBlurMaterial +> => { + const _dpr = getDpr(dpr); const { scene, material, camera } = useFxScene({ size, @@ -32,20 +37,15 @@ export const useGaussianBlur = ({ material: GaussianBlurMaterial, uniformValues, materialParameters: { + ...materialParameters, defines: { - "KERNEL_SIZE": radius, + KERNEL_SIZE: radius, }, - ...materialParameters, }, }); - useEffect(() => { - material.setBlurRadius(radius); - },[material, radius]); - - useEffect(() => { - material.setStep({size}); - }, [material, size]); + //THINKS * レンダー中に処理しちゃっていいかも. そもそも不要かも. materialのコメントを確認. + material.setStep(size); const [renderTarget, updateRenderTarget] = useDoubleFBO({ scene, @@ -55,20 +55,32 @@ export const useGaussianBlur = ({ fboAutoSetSize, ...renderTargetOptions, }); - + + const [config, setConfig] = useMutableConfig({ + radius, + }); + const setValues = useCallback( - (newValues: GaussianBlurValues) => { - material.setUniformValues(newValues); + (newValues: GaussianBlurValuesAndConfig) => { + const { radius, ...rest } = newValues; + if (radius) { + setConfig((prev) => { + // 変更がある場合だけsetBlurRadiusを実行する + if (radius !== prev.radius) material.setBlurRadius(radius); + return { radius }; + }); + } + material.setUniformValues(rest); }, - [material] + [material, setConfig] ); const render = useCallback( - (rootState: RootState, newValues?: GaussianBlurValues) => { + (rootState: RootState, newValues?: GaussianBlurValuesAndConfig) => { const { gl } = rootState; - newValues && setValues(newValues); - - // draw vertical blur + newValues && setValues(newValues); + + // draw vertical blur updateRenderTarget({ gl }, () => { material.uniforms.src.value = src || new THREE.Texture(); material.uniforms.u_stepSize.value.set(0, 1); @@ -80,7 +92,7 @@ export const useGaussianBlur = ({ material.uniforms.src.value = read; material.uniforms.u_stepSize.value.set(1, 0); material.updateBasicFx(); - }) + }); return renderTarget.read.texture; }, diff --git a/packages/use-shader-fx/src/materials/impl/blur/gaussianBlur/GaussianBlurMaterial.ts b/packages/use-shader-fx/src/materials/impl/blur/gaussianBlur/GaussianBlurMaterial.ts index 28389082..981a0a7d 100644 --- a/packages/use-shader-fx/src/materials/impl/blur/gaussianBlur/GaussianBlurMaterial.ts +++ b/packages/use-shader-fx/src/materials/impl/blur/gaussianBlur/GaussianBlurMaterial.ts @@ -10,26 +10,27 @@ import { Size } from "../../../../hooks/types"; type GaussianBlurUniforms = { /** */ src: { value: TexturePipelineSrc }; - /** */ + /** */ sigma: { - value: THREE.Vector2 - }, + value: THREE.Vector2; + }; u_weights: { - value: number[] - }, + value: number[]; + }; u_step: { - value: THREE.Vector2 - }, + value: THREE.Vector2; + }; u_stepSize: { - value: THREE.Vector2 - }, + value: THREE.Vector2; + }; } & BasicFxUniforms; -export type GaussianBlurValues = NestUniformValues & BasicFxValues; +export type GaussianBlurValues = NestUniformValues & + BasicFxValues; export class GaussianBlurMaterial extends BasicFxMaterial { static get type() { - return "GaussianBlurMaterial"; + return "GaussianBlurMaterial"; } uniforms!: GaussianBlurUniforms; @@ -42,60 +43,70 @@ export class GaussianBlurMaterial extends BasicFxMaterial { vertexShader: vertex, fragmentShader: fragment, uniformValues, - materialParameters: { - defines: { - "KERNEL_SIZE": 1, - }, - ...materialParameters, - }, + materialParameters, uniforms: { src: { - value: null + value: null, }, sigma: { - value: new THREE.Vector2(1,1) + value: new THREE.Vector2(1, 1), }, u_weights: { - value: [0] + value: [0], }, u_step: { - value: new THREE.Vector2(0,0) + value: new THREE.Vector2(0, 0), }, u_stepSize: { - value: new THREE.Vector2(0) - }, + value: new THREE.Vector2(0), + }, } as GaussianBlurUniforms, }); + // 初期化時に更新 + this.setBlurRadius(materialParameters.defines.KERNEL_SIZE); + this.type = GaussianBlurMaterial.type; } setBlurRadius(kernelSize: number) { - const weights = [] - let t = 0.0; + const weights = []; + let t = 0.0; + + console.log("setBlurRadius", kernelSize); - for(let i = kernelSize - 1; i >= 0; i--){ - let r = 1.0 + 2.0 * i; - let w = Math.exp(-0.5 * (r * r) / (kernelSize * kernelSize)); - weights.push(w); - if(i > 0){w *= 2.0;} - t += w; - } + for (let i = kernelSize - 1; i >= 0; i--) { + let r = 1.0 + 2.0 * i; + let w = Math.exp((-0.5 * (r * r)) / (kernelSize * kernelSize)); + weights.push(w); + if (i > 0) { + w *= 2.0; + } + t += w; + } - for(let i = 0; i < weights.length; i++){ - weights[i] /= t; - } + for (let i = 0; i < weights.length; i++) { + weights[i] /= t; + } // materiaに反映して更新を通知 - this.defines.KERNEL_SIZE = weights.length; - this.uniforms.u_weights.value = weights; + this.defines.KERNEL_SIZE = weights.length; // TODO * ここkerbelSizeをそのまま渡す方が直感的かな? + this.uniforms.u_weights.value = weights; this.needsUpdate = true; } - setStep({size}:{size?: Size}) { - this.uniforms.u_step.value.set( - 1 / (size?.width || this.uniforms.resolution.value.x || window.innerWidth), - 1 / (size?.height || this.uniforms.resolution.value.y || window.innerHeight) - ); + // TODO * これは必要? resolutionをshaderで使っちゃえばいいのでは? + // TODO * ちなみに、FxMaterialには、texelSizeというuniformがあるので、それをそのまま使えば処理も不要になるかも updateResolutionのupdateResolutionメソッドを確認。これらのDefaultUniformsは、全てのshaderで自動でprefixとして挿入される。 + setStep(size: Size) { + this.uniforms.u_step.value.set( + 1 / + (size?.width || + this.uniforms.resolution.value.x || + window.innerWidth), + 1 / + (size?.height || + this.uniforms.resolution.value.y || + window.innerHeight) + ); } } diff --git a/packages/use-shader-fx/src/utils/useFxScene.ts b/packages/use-shader-fx/src/utils/useFxScene.ts index e9586eaa..d8534fbb 100644 --- a/packages/use-shader-fx/src/utils/useFxScene.ts +++ b/packages/use-shader-fx/src/utils/useFxScene.ts @@ -1,5 +1,5 @@ import * as THREE from "three"; -import { useState } from "react"; +import { useEffect, useState } from "react"; import { useObject3D } from "./useObject3D"; import { Size } from "../hooks/types"; import { useResolution } from "./useResolution"; @@ -30,7 +30,8 @@ export const useFxScene = ({ height: number; }; } & FxMaterialProps) => { - // non-reactive + // Mutable THREE objects should retain their values in useState + // https://github.com/FunTechInc/use-shader-fx/issues/145 const [scene] = useState(() => new THREE.Scene()); const [_geometry] = useState( () => new geometry(geometrySize?.width || 2, geometrySize?.height || 2) diff --git a/packages/use-shader-fx/src/utils/useMutableConfig.ts b/packages/use-shader-fx/src/utils/useMutableConfig.ts new file mode 100644 index 00000000..95e1def4 --- /dev/null +++ b/packages/use-shader-fx/src/utils/useMutableConfig.ts @@ -0,0 +1,26 @@ +import { useCallback, useRef } from "react"; + +type SetConfigAction = C | ((prevConfig: C) => C); + +export const useMutableConfig = >(config: C) => { + const _config = useRef(config); + + const updateConfig = useCallback((nextConfig: Partial) => { + for (const [key, value] of Object.entries(nextConfig)) { + if (value !== undefined && key in _config.current) { + _config.current[key as keyof C] = value as C[keyof C]; + } + } + }, []); + + const setConfig = useCallback( + (value: SetConfigAction) => { + typeof value === "function" + ? updateConfig(value(_config.current)) + : updateConfig(value); + }, + [updateConfig] + ); + + return [_config, setConfig] as const; +}; diff --git a/packages/use-shader-fx/src/utils/useResolution.ts b/packages/use-shader-fx/src/utils/useResolution.ts index a11e8b27..e4d1a1bc 100644 --- a/packages/use-shader-fx/src/utils/useResolution.ts +++ b/packages/use-shader-fx/src/utils/useResolution.ts @@ -1,18 +1,16 @@ import * as THREE from "three"; -import { useMemo } from "react"; +import { useState } from "react"; import { Size } from "../hooks/types"; /** * @params dpr if dpr is set, it returns the resolution which is size multiplied by dpr. */ -// TODO : materialを引数に取る場合はmaterialのupdateResolutionを呼び出す:M extends FxMaterial export const useResolution = (size: Size, dpr: number | false = false) => { const _width = dpr ? size.width * dpr : size.width; const _height = dpr ? size.height * dpr : size.height; - const resolution = useMemo( - () => new THREE.Vector2(_width, _height), - [_width, _height] - ); + const [resolution] = useState(() => new THREE.Vector2(_width, _height)); + resolution.set(_width, _height); + return resolution; }; From f66df16c275b508d61d411e8cbad9171f893fc8c Mon Sep 17 00:00:00 2001 From: takuma-hmng8 Date: Fri, 15 Nov 2024 19:49:05 +0900 Subject: [PATCH 39/60] update --- app/v2_pipe/Playground.tsx | 4 ---- packages/use-shader-fx/src/hooks/blur/useBoxBlur/index.ts | 2 +- .../use-shader-fx/src/hooks/blur/useGaussianBlur/index.ts | 2 +- 3 files changed, 2 insertions(+), 6 deletions(-) diff --git a/app/v2_pipe/Playground.tsx b/app/v2_pipe/Playground.tsx index 69fa1808..323715b3 100644 --- a/app/v2_pipe/Playground.tsx +++ b/app/v2_pipe/Playground.tsx @@ -104,10 +104,6 @@ export const Playground = () => { useFrame((state) => render(state)); - const color1 = new THREE.Color(0x000000); - const color2 = new THREE.Color(0x000000); - console.log(color1 === color2); - return ( diff --git a/packages/use-shader-fx/src/hooks/blur/useBoxBlur/index.ts b/packages/use-shader-fx/src/hooks/blur/useBoxBlur/index.ts index 89c7de3b..27af1c16 100644 --- a/packages/use-shader-fx/src/hooks/blur/useBoxBlur/index.ts +++ b/packages/use-shader-fx/src/hooks/blur/useBoxBlur/index.ts @@ -1,4 +1,4 @@ -import { useCallback, useEffect, useState } from "react"; +import { useCallback } from "react"; import { HooksProps, HooksReturn } from "../../types"; import { getDpr } from "../../../utils/getDpr"; import { RootState } from "../../types"; diff --git a/packages/use-shader-fx/src/hooks/blur/useGaussianBlur/index.ts b/packages/use-shader-fx/src/hooks/blur/useGaussianBlur/index.ts index 9b7da1c4..3a7c26f8 100644 --- a/packages/use-shader-fx/src/hooks/blur/useGaussianBlur/index.ts +++ b/packages/use-shader-fx/src/hooks/blur/useGaussianBlur/index.ts @@ -1,4 +1,4 @@ -import { useCallback, useEffect } from "react"; +import { useCallback } from "react"; import { HooksProps, HooksReturn } from "../../types"; import { getDpr } from "../../../utils/getDpr"; import { RootState } from "../../types"; From 94be996f11c1708cfa21d64e2b56c4821832f8f7 Mon Sep 17 00:00:00 2001 From: takuma-hmng8 Date: Fri, 15 Nov 2024 21:24:21 +0900 Subject: [PATCH 40/60] update --- app/v2_test/Playground.tsx | 14 +++------- .../src/hooks/blur/useBoxBlur/index.ts | 24 +++++++++++------ .../src/hooks/blur/useGaussianBlur/index.ts | 10 +++---- .../use-shader-fx/src/hooks/types/index.ts | 2 +- .../src/hooks/useCoverTexture/index.ts | 7 ++--- .../use-shader-fx/src/hooks/useFluid/index.ts | 7 ++--- .../src/hooks/useFluid/scenes/useAdvection.ts | 3 +-- .../hooks/useFluid/scenes/useDivergence.ts | 3 +-- .../src/hooks/useFluid/scenes/usePoisson.ts | 3 +-- .../src/hooks/useFluid/scenes/usePressure.ts | 3 +-- .../src/hooks/useFluid/scenes/useSplat.ts | 3 +-- .../use-shader-fx/src/hooks/useNoise/index.ts | 7 ++--- .../src/hooks/useRawBlank/index.ts | 9 +++---- packages/use-shader-fx/src/index.js | 3 +-- .../src/materials/core/FxMaterial.ts | 2 +- .../use-shader-fx/src/misc/usePipeline.ts | 2 +- .../src/shaders/uniformsUtils.ts | 2 +- packages/use-shader-fx/src/utils/index.ts | 9 +++++++ .../src/utils/useMutableConfig.ts | 26 ------------------- .../use-shader-fx/src/utils/useRefState.ts | 13 ++++++++++ 20 files changed, 64 insertions(+), 88 deletions(-) create mode 100644 packages/use-shader-fx/src/utils/index.ts delete mode 100644 packages/use-shader-fx/src/utils/useMutableConfig.ts create mode 100644 packages/use-shader-fx/src/utils/useRefState.ts diff --git a/app/v2_test/Playground.tsx b/app/v2_test/Playground.tsx index f7903950..013ad72e 100644 --- a/app/v2_test/Playground.tsx +++ b/app/v2_test/Playground.tsx @@ -4,16 +4,10 @@ import * as THREE from "three"; import { useEffect, useRef, useState } from "react"; import { useFrame, useThree, extend, createPortal } from "@react-three/fiber"; import { - useNoise, - NoiseValues, - useBoxBlur, - useSingleFBO, createFxMaterialImpl, createBasicFxMaterialImpl, FxMaterialImplValues, BasicFxMaterialImplValues, - useFluid, - useCoverTexture, } from "@/packages/use-shader-fx/src"; import { Float, OrbitControls, useTexture } from "@react-three/drei"; import { useGaussianBlur } from "@/packages/use-shader-fx/src/hooks/blur/useGaussianBlur"; @@ -42,17 +36,17 @@ export const Playground = () => { const [app] = useTexture(["/app-head.jpg"]); - const blur = useBoxBlur({ + const blur = useGaussianBlur({ size, dpr: 1, - // radius: 19, + radius: 21, // blurIteration: 1, src: app, }); blur.setValues({ - // radius: 9, - blurIteration: 20, + radius: 41, + // blurIteration: 20, }); useFrame((state) => { diff --git a/packages/use-shader-fx/src/hooks/blur/useBoxBlur/index.ts b/packages/use-shader-fx/src/hooks/blur/useBoxBlur/index.ts index 27af1c16..94f01690 100644 --- a/packages/use-shader-fx/src/hooks/blur/useBoxBlur/index.ts +++ b/packages/use-shader-fx/src/hooks/blur/useBoxBlur/index.ts @@ -1,11 +1,8 @@ import { useCallback } from "react"; import { HooksProps, HooksReturn } from "../../types"; -import { getDpr } from "../../../utils/getDpr"; +import { getDpr, useFxScene, useDoubleFBO, useRefState } from "../../../utils"; import { RootState } from "../../types"; import { BoxBlurMaterial, BoxBlurValues } from "../../../materials"; -import { useFxScene } from "../../../utils/useFxScene"; -import { useDoubleFBO } from "../../../utils/useDoubleFBO"; -import { useMutableConfig } from "../../../utils/useMutableConfig"; type BoxBlurConfig = { blurIteration?: number; @@ -45,14 +42,14 @@ export const useBoxBlur = ({ ...renderTargetOptions, }); - const [config, setConfig] = useMutableConfig({ + const [config, setConfig] = useRefState({ blurIteration, }); const setValues = useCallback( (newValues: BoxBlurValuesAndConfig) => { const { blurIteration, ...rest } = newValues; - setConfig({ blurIteration }); + if (blurIteration) setConfig({ blurIteration }); material.setUniformValues(rest); }, [material, setConfig] @@ -69,7 +66,11 @@ export const useBoxBlur = ({ updateRenderTarget({ gl }); - for (let i = 0; i < config.current.blurIteration!; i++) { + for ( + let i = 0; + i < (config.current.blurIteration || blurIteration); + i++ + ) { updateRenderTarget({ gl }, ({ read }) => { material.uniforms.src.value = read; }); @@ -79,7 +80,14 @@ export const useBoxBlur = ({ return renderTarget.read.texture; }, - [setValues, updateRenderTarget, material, renderTarget, config] + [ + setValues, + updateRenderTarget, + material, + renderTarget, + config, + blurIteration, + ] ); return { diff --git a/packages/use-shader-fx/src/hooks/blur/useGaussianBlur/index.ts b/packages/use-shader-fx/src/hooks/blur/useGaussianBlur/index.ts index 3a7c26f8..5a3a5870 100644 --- a/packages/use-shader-fx/src/hooks/blur/useGaussianBlur/index.ts +++ b/packages/use-shader-fx/src/hooks/blur/useGaussianBlur/index.ts @@ -1,12 +1,9 @@ +import * as THREE from "three"; import { useCallback } from "react"; import { HooksProps, HooksReturn } from "../../types"; -import { getDpr } from "../../../utils/getDpr"; +import { getDpr, useFxScene, useDoubleFBO, useRefState } from "../../../utils"; import { RootState } from "../../types"; import { GaussianBlurMaterial, GaussianBlurValues } from "../../../materials"; -import { useFxScene } from "../../../utils/useFxScene"; -import { useDoubleFBO } from "../../../utils/useDoubleFBO"; -import * as THREE from "three"; -import { useMutableConfig } from "../../../utils/useMutableConfig"; type GaussianBlurConfig = { radius?: number; @@ -56,7 +53,7 @@ export const useGaussianBlur = ({ ...renderTargetOptions, }); - const [config, setConfig] = useMutableConfig({ + const [config, setConfig] = useRefState({ radius, }); @@ -65,7 +62,6 @@ export const useGaussianBlur = ({ const { radius, ...rest } = newValues; if (radius) { setConfig((prev) => { - // 変更がある場合だけsetBlurRadiusを実行する if (radius !== prev.radius) material.setBlurRadius(radius); return { radius }; }); diff --git a/packages/use-shader-fx/src/hooks/types/index.ts b/packages/use-shader-fx/src/hooks/types/index.ts index 005a665f..5065ede5 100644 --- a/packages/use-shader-fx/src/hooks/types/index.ts +++ b/packages/use-shader-fx/src/hooks/types/index.ts @@ -1,6 +1,6 @@ import * as THREE from "three"; import { BasicFxMaterial } from "../../materials/core/BasicFxMaterial"; -import { DoubleRenderTarget } from "../../utils/useDoubleFBO"; +import { DoubleRenderTarget } from "../../utils"; export type Size = { width: number; diff --git a/packages/use-shader-fx/src/hooks/useCoverTexture/index.ts b/packages/use-shader-fx/src/hooks/useCoverTexture/index.ts index f0628647..baa00838 100644 --- a/packages/use-shader-fx/src/hooks/useCoverTexture/index.ts +++ b/packages/use-shader-fx/src/hooks/useCoverTexture/index.ts @@ -1,10 +1,7 @@ import { useCallback } from "react"; -import { useSingleFBO } from "../../utils/useSingleFBO"; -import { HooksProps, HooksReturn } from "../types"; -import { getDpr } from "../../utils/getDpr"; -import { RootState } from "../types"; +import { useSingleFBO, getDpr, useFxScene } from "../../utils"; +import { HooksProps, HooksReturn, RootState } from "../types"; import { CoverTextureMaterial, CoverTextureValues } from "../../materials"; -import { useFxScene } from "../../utils/useFxScene"; export type CoverTextureProps = HooksProps & CoverTextureValues; diff --git a/packages/use-shader-fx/src/hooks/useFluid/index.ts b/packages/use-shader-fx/src/hooks/useFluid/index.ts index f0a866d7..da26317b 100644 --- a/packages/use-shader-fx/src/hooks/useFluid/index.ts +++ b/packages/use-shader-fx/src/hooks/useFluid/index.ts @@ -1,10 +1,7 @@ import * as THREE from "three"; import { useCallback } from "react"; -import { useSingleFBO } from "../../utils/useSingleFBO"; -import { HooksProps, HooksReturn } from "../types"; -import { getDpr } from "../../utils/getDpr"; -import { RootState } from "../types"; -import { useDoubleFBO } from "../../utils/useDoubleFBO"; +import { useSingleFBO, useDoubleFBO, getDpr } from "../../utils"; +import { HooksProps, HooksReturn, RootState } from "../types"; import { useAdvection } from "./scenes/useAdvection"; import { useSplat } from "./scenes/useSplat"; import { useDivergence } from "./scenes/useDivergence"; diff --git a/packages/use-shader-fx/src/hooks/useFluid/scenes/useAdvection.ts b/packages/use-shader-fx/src/hooks/useFluid/scenes/useAdvection.ts index 514036ed..d531c834 100644 --- a/packages/use-shader-fx/src/hooks/useFluid/scenes/useAdvection.ts +++ b/packages/use-shader-fx/src/hooks/useFluid/scenes/useAdvection.ts @@ -2,8 +2,7 @@ import * as THREE from "three"; import { useCallback } from "react"; import { RootState, Size } from "../../types"; import { AdvectionMaterial } from "../../../materials"; -import { SingleFBOUpdateFunction } from "../../../utils/useSingleFBO"; -import { useFxScene } from "../../../utils/useFxScene"; +import { SingleFBOUpdateFunction, useFxScene } from "../../../utils"; export const useAdvection = ( { diff --git a/packages/use-shader-fx/src/hooks/useFluid/scenes/useDivergence.ts b/packages/use-shader-fx/src/hooks/useFluid/scenes/useDivergence.ts index 2ccf61ec..7e41a826 100644 --- a/packages/use-shader-fx/src/hooks/useFluid/scenes/useDivergence.ts +++ b/packages/use-shader-fx/src/hooks/useFluid/scenes/useDivergence.ts @@ -1,9 +1,8 @@ import * as THREE from "three"; import { useCallback } from "react"; import { RootState, Size } from "../../types"; -import { SingleFBOUpdateFunction } from "../../../utils/useSingleFBO"; import { DivergenceMaterial } from "../../../materials"; -import { useFxScene } from "../../../utils/useFxScene"; +import { useFxScene, SingleFBOUpdateFunction } from "../../../utils"; export const useDivergence = ( { diff --git a/packages/use-shader-fx/src/hooks/useFluid/scenes/usePoisson.ts b/packages/use-shader-fx/src/hooks/useFluid/scenes/usePoisson.ts index dbb84359..8d4c1410 100644 --- a/packages/use-shader-fx/src/hooks/useFluid/scenes/usePoisson.ts +++ b/packages/use-shader-fx/src/hooks/useFluid/scenes/usePoisson.ts @@ -1,9 +1,8 @@ import * as THREE from "three"; import { useCallback } from "react"; import { RootState, Size } from "../../types"; -import { SingleFBOUpdateFunction } from "../../../utils/useSingleFBO"; +import { SingleFBOUpdateFunction, useFxScene } from "../../../utils"; import { PoissonMaterial } from "../../../materials"; -import { useFxScene } from "../../../utils/useFxScene"; export const usePoisson = ( { diff --git a/packages/use-shader-fx/src/hooks/useFluid/scenes/usePressure.ts b/packages/use-shader-fx/src/hooks/useFluid/scenes/usePressure.ts index 673463f5..85248cc8 100644 --- a/packages/use-shader-fx/src/hooks/useFluid/scenes/usePressure.ts +++ b/packages/use-shader-fx/src/hooks/useFluid/scenes/usePressure.ts @@ -1,9 +1,8 @@ import * as THREE from "three"; import { useCallback } from "react"; import { RootState, Size } from "../../types"; -import { SingleFBOUpdateFunction } from "../../../utils/useSingleFBO"; +import { SingleFBOUpdateFunction, useFxScene } from "../../../utils"; import { PressureMaterial } from "../../../materials"; -import { useFxScene } from "../../../utils/useFxScene"; export const usePressure = ( { diff --git a/packages/use-shader-fx/src/hooks/useFluid/scenes/useSplat.ts b/packages/use-shader-fx/src/hooks/useFluid/scenes/useSplat.ts index aae70673..5edde699 100644 --- a/packages/use-shader-fx/src/hooks/useFluid/scenes/useSplat.ts +++ b/packages/use-shader-fx/src/hooks/useFluid/scenes/useSplat.ts @@ -1,9 +1,8 @@ import { useCallback } from "react"; import { RootState, Size } from "../../types"; -import { SingleFBOUpdateFunction } from "../../../utils/useSingleFBO"; +import { SingleFBOUpdateFunction, useFxScene } from "../../../utils"; import { SplatMaterial } from "../../../materials"; import { usePointerTracker } from "../../../misc/usePointerTracker"; -import { useFxScene } from "../../../utils/useFxScene"; export const useSplat = ( { diff --git a/packages/use-shader-fx/src/hooks/useNoise/index.ts b/packages/use-shader-fx/src/hooks/useNoise/index.ts index 7817c8a1..b195655e 100644 --- a/packages/use-shader-fx/src/hooks/useNoise/index.ts +++ b/packages/use-shader-fx/src/hooks/useNoise/index.ts @@ -1,14 +1,11 @@ import { useCallback } from "react"; -import { useSingleFBO } from "../../utils/useSingleFBO"; -import { HooksProps, HooksReturn } from "../types"; -import { getDpr } from "../../utils/getDpr"; -import { RootState } from "../types"; +import { useSingleFBO, getDpr, useFxScene } from "../../utils"; +import { HooksProps, HooksReturn, RootState } from "../types"; import { NoiseMaterial, NoiseMaterialProps, NoiseValues, } from "../../materials"; -import { useFxScene } from "../../utils/useFxScene"; export type NoiseProps = HooksProps & NoiseValues; diff --git a/packages/use-shader-fx/src/hooks/useRawBlank/index.ts b/packages/use-shader-fx/src/hooks/useRawBlank/index.ts index 5906e740..3a12e470 100644 --- a/packages/use-shader-fx/src/hooks/useRawBlank/index.ts +++ b/packages/use-shader-fx/src/hooks/useRawBlank/index.ts @@ -1,11 +1,8 @@ import { useCallback } from "react"; -import { useSingleFBO } from "../../utils/useSingleFBO"; -import { HooksProps, HooksReturn } from "../types"; -import { getDpr } from "../../utils/getDpr"; -import { RootState } from "../types"; +import { useSingleFBO, useFxScene, getDpr } from "../../utils"; +import { HooksProps, HooksReturn, RootState } from "../types"; import { RawBlankMaterial, RawBlankValues } from "../../materials"; -import { useFxScene } from "../../utils/useFxScene"; -import { ShaderWithUniforms } from "../../materials/core/FxMaterial"; +import { ShaderWithUniforms } from "../../shaders/uniformsUtils"; type RawBlankConfig = ShaderWithUniforms; diff --git a/packages/use-shader-fx/src/index.js b/packages/use-shader-fx/src/index.js index c81e1932..471b506a 100644 --- a/packages/use-shader-fx/src/index.js +++ b/packages/use-shader-fx/src/index.js @@ -2,7 +2,6 @@ export * from "./hooks"; export * from "./materials"; -export * from "./utils/useDoubleFBO"; -export * from "./utils/useSingleFBO"; +export { useDoubleFBO, useSingleFBO } from "./utils"; export * from "./misc"; diff --git a/packages/use-shader-fx/src/materials/core/FxMaterial.ts b/packages/use-shader-fx/src/materials/core/FxMaterial.ts index d82362fb..7537881b 100644 --- a/packages/use-shader-fx/src/materials/core/FxMaterial.ts +++ b/packages/use-shader-fx/src/materials/core/FxMaterial.ts @@ -5,7 +5,7 @@ import { flattenUniformValues, ShaderWithUniforms, } from "../../shaders/uniformsUtils"; -import { warn } from "../../utils/warn"; +import { warn } from "../../utils"; export type DefaultUniforms = { resolution: { value: THREE.Vector2 }; diff --git a/packages/use-shader-fx/src/misc/usePipeline.ts b/packages/use-shader-fx/src/misc/usePipeline.ts index e7d908ef..c8a421e5 100644 --- a/packages/use-shader-fx/src/misc/usePipeline.ts +++ b/packages/use-shader-fx/src/misc/usePipeline.ts @@ -2,7 +2,7 @@ import * as THREE from "three"; import { useCallback, useState } from "react"; import { RootState } from "../hooks/types"; import { FxTypes, FxProps } from "../hooks"; -import { warn } from "../utils/warn"; +import { warn } from "../utils"; export type FxConfig = { fx: T; diff --git a/packages/use-shader-fx/src/shaders/uniformsUtils.ts b/packages/use-shader-fx/src/shaders/uniformsUtils.ts index 115329cc..6f5e3e65 100644 --- a/packages/use-shader-fx/src/shaders/uniformsUtils.ts +++ b/packages/use-shader-fx/src/shaders/uniformsUtils.ts @@ -1,5 +1,5 @@ import * as THREE from "three"; -import { warn } from "../utils/warn"; +import { warn } from "../utils"; import { THREE_TYPES } from "../libs/constants"; export type Uniforms = { [uniform: string]: THREE.IUniform }; diff --git a/packages/use-shader-fx/src/utils/index.ts b/packages/use-shader-fx/src/utils/index.ts new file mode 100644 index 00000000..ba56e0ff --- /dev/null +++ b/packages/use-shader-fx/src/utils/index.ts @@ -0,0 +1,9 @@ +export * from "./getDpr"; +export * from "./useCamera"; +export * from "./useDoubleFBO"; +export * from "./useFxScene"; +export * from "./useRefState"; +export * from "./useObject3D"; +export * from "./useResolution"; +export * from "./useSingleFBO"; +export * from "./warn"; diff --git a/packages/use-shader-fx/src/utils/useMutableConfig.ts b/packages/use-shader-fx/src/utils/useMutableConfig.ts deleted file mode 100644 index 95e1def4..00000000 --- a/packages/use-shader-fx/src/utils/useMutableConfig.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { useCallback, useRef } from "react"; - -type SetConfigAction = C | ((prevConfig: C) => C); - -export const useMutableConfig = >(config: C) => { - const _config = useRef(config); - - const updateConfig = useCallback((nextConfig: Partial) => { - for (const [key, value] of Object.entries(nextConfig)) { - if (value !== undefined && key in _config.current) { - _config.current[key as keyof C] = value as C[keyof C]; - } - } - }, []); - - const setConfig = useCallback( - (value: SetConfigAction) => { - typeof value === "function" - ? updateConfig(value(_config.current)) - : updateConfig(value); - }, - [updateConfig] - ); - - return [_config, setConfig] as const; -}; diff --git a/packages/use-shader-fx/src/utils/useRefState.ts b/packages/use-shader-fx/src/utils/useRefState.ts new file mode 100644 index 00000000..4b07a0e1 --- /dev/null +++ b/packages/use-shader-fx/src/utils/useRefState.ts @@ -0,0 +1,13 @@ +import { useCallback, useRef } from "react"; + +export const useRefState = (state: S) => { + const ref = useRef(state); + const setRef = useCallback((value: S | ((prevState: S) => S)) => { + ref.current = + typeof value === "function" + ? (value as (prevState: S) => S)(ref.current) + : value; + }, []); + + return [ref, setRef] as const; +}; From 8d74f5c878fd6dad2a0ac610fe8fbaf97dce2207 Mon Sep 17 00:00:00 2001 From: takuma-hmng8 Date: Fri, 15 Nov 2024 21:26:40 +0900 Subject: [PATCH 41/60] update --- .../use-shader-fx/src/hooks/blur/useBoxBlur/index.ts | 9 +++++++-- .../src/hooks/blur/useGaussianBlur/index.ts | 9 +++++++-- packages/use-shader-fx/src/utils/index.ts | 2 +- .../src/utils/{useRefState.ts => useMutableRefState.ts} | 2 +- 4 files changed, 16 insertions(+), 6 deletions(-) rename packages/use-shader-fx/src/utils/{useRefState.ts => useMutableRefState.ts} (86%) diff --git a/packages/use-shader-fx/src/hooks/blur/useBoxBlur/index.ts b/packages/use-shader-fx/src/hooks/blur/useBoxBlur/index.ts index 94f01690..5ccd3f83 100644 --- a/packages/use-shader-fx/src/hooks/blur/useBoxBlur/index.ts +++ b/packages/use-shader-fx/src/hooks/blur/useBoxBlur/index.ts @@ -1,6 +1,11 @@ import { useCallback } from "react"; import { HooksProps, HooksReturn } from "../../types"; -import { getDpr, useFxScene, useDoubleFBO, useRefState } from "../../../utils"; +import { + getDpr, + useFxScene, + useDoubleFBO, + useMutableRefState, +} from "../../../utils"; import { RootState } from "../../types"; import { BoxBlurMaterial, BoxBlurValues } from "../../../materials"; @@ -42,7 +47,7 @@ export const useBoxBlur = ({ ...renderTargetOptions, }); - const [config, setConfig] = useRefState({ + const [config, setConfig] = useMutableRefState({ blurIteration, }); diff --git a/packages/use-shader-fx/src/hooks/blur/useGaussianBlur/index.ts b/packages/use-shader-fx/src/hooks/blur/useGaussianBlur/index.ts index 5a3a5870..2f35cc51 100644 --- a/packages/use-shader-fx/src/hooks/blur/useGaussianBlur/index.ts +++ b/packages/use-shader-fx/src/hooks/blur/useGaussianBlur/index.ts @@ -1,7 +1,12 @@ import * as THREE from "three"; import { useCallback } from "react"; import { HooksProps, HooksReturn } from "../../types"; -import { getDpr, useFxScene, useDoubleFBO, useRefState } from "../../../utils"; +import { + getDpr, + useFxScene, + useDoubleFBO, + useMutableRefState, +} from "../../../utils"; import { RootState } from "../../types"; import { GaussianBlurMaterial, GaussianBlurValues } from "../../../materials"; @@ -53,7 +58,7 @@ export const useGaussianBlur = ({ ...renderTargetOptions, }); - const [config, setConfig] = useRefState({ + const [config, setConfig] = useMutableRefState({ radius, }); diff --git a/packages/use-shader-fx/src/utils/index.ts b/packages/use-shader-fx/src/utils/index.ts index ba56e0ff..3217d4b5 100644 --- a/packages/use-shader-fx/src/utils/index.ts +++ b/packages/use-shader-fx/src/utils/index.ts @@ -2,7 +2,7 @@ export * from "./getDpr"; export * from "./useCamera"; export * from "./useDoubleFBO"; export * from "./useFxScene"; -export * from "./useRefState"; +export * from "./useMutableRefState"; export * from "./useObject3D"; export * from "./useResolution"; export * from "./useSingleFBO"; diff --git a/packages/use-shader-fx/src/utils/useRefState.ts b/packages/use-shader-fx/src/utils/useMutableRefState.ts similarity index 86% rename from packages/use-shader-fx/src/utils/useRefState.ts rename to packages/use-shader-fx/src/utils/useMutableRefState.ts index 4b07a0e1..6a946a88 100644 --- a/packages/use-shader-fx/src/utils/useRefState.ts +++ b/packages/use-shader-fx/src/utils/useMutableRefState.ts @@ -1,6 +1,6 @@ import { useCallback, useRef } from "react"; -export const useRefState = (state: S) => { +export const useMutableRefState = (state: S) => { const ref = useRef(state); const setRef = useCallback((value: S | ((prevState: S) => S)) => { ref.current = From c395215c34770e5bdd955c10f03f5a17e3c99385 Mon Sep 17 00:00:00 2001 From: takuma-hmng8 Date: Fri, 15 Nov 2024 21:30:41 +0900 Subject: [PATCH 42/60] update --- packages/use-shader-fx/src/hooks/blur/useBoxBlur/index.ts | 4 ++-- .../use-shader-fx/src/hooks/blur/useGaussianBlur/index.ts | 4 ++-- packages/use-shader-fx/src/utils/index.ts | 2 +- .../src/utils/{useMutableRefState.ts => useMutableState.ts} | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) rename packages/use-shader-fx/src/utils/{useMutableRefState.ts => useMutableState.ts} (86%) diff --git a/packages/use-shader-fx/src/hooks/blur/useBoxBlur/index.ts b/packages/use-shader-fx/src/hooks/blur/useBoxBlur/index.ts index 5ccd3f83..d141e3ed 100644 --- a/packages/use-shader-fx/src/hooks/blur/useBoxBlur/index.ts +++ b/packages/use-shader-fx/src/hooks/blur/useBoxBlur/index.ts @@ -4,7 +4,7 @@ import { getDpr, useFxScene, useDoubleFBO, - useMutableRefState, + useMutableState, } from "../../../utils"; import { RootState } from "../../types"; import { BoxBlurMaterial, BoxBlurValues } from "../../../materials"; @@ -47,7 +47,7 @@ export const useBoxBlur = ({ ...renderTargetOptions, }); - const [config, setConfig] = useMutableRefState({ + const [config, setConfig] = useMutableState({ blurIteration, }); diff --git a/packages/use-shader-fx/src/hooks/blur/useGaussianBlur/index.ts b/packages/use-shader-fx/src/hooks/blur/useGaussianBlur/index.ts index 2f35cc51..cc86fafc 100644 --- a/packages/use-shader-fx/src/hooks/blur/useGaussianBlur/index.ts +++ b/packages/use-shader-fx/src/hooks/blur/useGaussianBlur/index.ts @@ -5,7 +5,7 @@ import { getDpr, useFxScene, useDoubleFBO, - useMutableRefState, + useMutableState, } from "../../../utils"; import { RootState } from "../../types"; import { GaussianBlurMaterial, GaussianBlurValues } from "../../../materials"; @@ -58,7 +58,7 @@ export const useGaussianBlur = ({ ...renderTargetOptions, }); - const [config, setConfig] = useMutableRefState({ + const [config, setConfig] = useMutableState({ radius, }); diff --git a/packages/use-shader-fx/src/utils/index.ts b/packages/use-shader-fx/src/utils/index.ts index 3217d4b5..6218cb41 100644 --- a/packages/use-shader-fx/src/utils/index.ts +++ b/packages/use-shader-fx/src/utils/index.ts @@ -2,7 +2,7 @@ export * from "./getDpr"; export * from "./useCamera"; export * from "./useDoubleFBO"; export * from "./useFxScene"; -export * from "./useMutableRefState"; +export * from "./useMutableState"; export * from "./useObject3D"; export * from "./useResolution"; export * from "./useSingleFBO"; diff --git a/packages/use-shader-fx/src/utils/useMutableRefState.ts b/packages/use-shader-fx/src/utils/useMutableState.ts similarity index 86% rename from packages/use-shader-fx/src/utils/useMutableRefState.ts rename to packages/use-shader-fx/src/utils/useMutableState.ts index 6a946a88..352604eb 100644 --- a/packages/use-shader-fx/src/utils/useMutableRefState.ts +++ b/packages/use-shader-fx/src/utils/useMutableState.ts @@ -1,6 +1,6 @@ import { useCallback, useRef } from "react"; -export const useMutableRefState = (state: S) => { +export const useMutableState = (state: S) => { const ref = useRef(state); const setRef = useCallback((value: S | ((prevState: S) => S)) => { ref.current = From d9af622fa8678f049a60a684a247b1fc8879054e Mon Sep 17 00:00:00 2001 From: roku-ft Date: Fri, 15 Nov 2024 21:31:30 +0900 Subject: [PATCH 43/60] #146 add base of rgbShift --- packages/use-shader-fx/src/hooks/index.ts | 7 +- .../src/hooks/useRGBShift/index.tsx | 81 +++++++++++++++++++ .../impl/rgbShift/RGBShiftMaterial.ts | 42 ++++++++++ .../materials/impl/rgbShift/rgbShift.glsl.ts | 27 +++++++ packages/use-shader-fx/src/materials/index.js | 1 + 5 files changed, 157 insertions(+), 1 deletion(-) create mode 100644 packages/use-shader-fx/src/hooks/useRGBShift/index.tsx create mode 100644 packages/use-shader-fx/src/materials/impl/rgbShift/RGBShiftMaterial.ts create mode 100644 packages/use-shader-fx/src/materials/impl/rgbShift/rgbShift.glsl.ts diff --git a/packages/use-shader-fx/src/hooks/index.ts b/packages/use-shader-fx/src/hooks/index.ts index acfa6fba..16f544d8 100644 --- a/packages/use-shader-fx/src/hooks/index.ts +++ b/packages/use-shader-fx/src/hooks/index.ts @@ -3,13 +3,15 @@ import { useCoverTexture, CoverTextureProps } from "./useCoverTexture"; import { useFluid, FluidProps } from "./useFluid"; import { useNoise, NoiseProps } from "./useNoise"; import { useRawBlank, RawBlankProps } from "./useRawBlank"; +import { useRGBShift, RGBShiftProps } from "./useRGBShift"; export type FxTypes = | typeof useBoxBlur | typeof useCoverTexture | typeof useFluid | typeof useNoise - | typeof useRawBlank; + | typeof useRawBlank + | typeof useRGBShift; export type FxProps = T extends typeof useBoxBlur @@ -21,6 +23,8 @@ export type FxProps = : T extends typeof useFluid ? FluidProps : T extends typeof useRawBlank + ? RGBShiftProps + : T extends typeof useRGBShift ? RawBlankProps : never; @@ -29,3 +33,4 @@ export * from "./useCoverTexture"; export * from "./useFluid"; export * from "./useNoise"; export * from "./useRawBlank"; +export * from "./useRGBShift"; diff --git a/packages/use-shader-fx/src/hooks/useRGBShift/index.tsx b/packages/use-shader-fx/src/hooks/useRGBShift/index.tsx new file mode 100644 index 00000000..143c3256 --- /dev/null +++ b/packages/use-shader-fx/src/hooks/useRGBShift/index.tsx @@ -0,0 +1,81 @@ +import { useCallback } from "react"; +import { HooksProps, HooksReturn } from "../types"; +import { getDpr } from "../../utils/getDpr"; +import { RootState } from "../types"; +import { RGBShiftMaterial, RGBShiftValues } from "../../materials"; +import { useFxScene } from "../../utils/useFxScene"; +import { useMutableConfig } from "../../utils/useMutableConfig"; +import { useSingleFBO } from "../../utils/useSingleFBO"; + +type RGBShiftConfig = { +// blurIteration?: number; +}; + +type RGBShiftValuesAndConfig = RGBShiftValues & RGBShiftConfig; +export type RGBShiftProps = HooksProps & RGBShiftValuesAndConfig; + +/** + * @link https://github.com/FunTechInc/use-shader-fx?tab=readme-ov-file#usage + */ +export const useRGBShift = ({ + size, + dpr, + fboAutoSetSize, + renderTargetOptions, + materialParameters, +// blurIteration = 5, + ...uniformValues +}: RGBShiftProps): HooksReturn => { + const _dpr = getDpr(dpr); + + const { scene, material, camera } = useFxScene({ + size, + dpr: _dpr.shader, + material: RGBShiftMaterial, + uniformValues, + materialParameters, + }); + + const [renderTarget, updateRenderTarget] = useSingleFBO({ + scene, + camera, + size, + dpr: _dpr.fbo, + fboAutoSetSize, + ...renderTargetOptions, + }); + + const [config, setConfig] = useMutableConfig({ + // blurIteration, + }); + + const setValues = useCallback( + (newValues: RGBShiftValuesAndConfig) => { + const { ...rest } = newValues; + // setConfig({ blurIteration }); + material.setUniformValues(rest); + }, + [material, setConfig] + ); + + const render = useCallback( + (rootState: RootState, newValues?: RGBShiftValuesAndConfig) => { + const { gl } = rootState; + newValues && setValues(newValues); + material.updateBasicFx(); + updateRenderTarget({ gl }); + return renderTarget.texture; + }, + [setValues, updateRenderTarget, material, renderTarget, config] + ); + + return { + render, + setValues, + texture: renderTarget.texture, + material, + scene, + camera, + renderTarget, + }; +}; diff --git a/packages/use-shader-fx/src/materials/impl/rgbShift/RGBShiftMaterial.ts b/packages/use-shader-fx/src/materials/impl/rgbShift/RGBShiftMaterial.ts new file mode 100644 index 00000000..398d2dc8 --- /dev/null +++ b/packages/use-shader-fx/src/materials/impl/rgbShift/RGBShiftMaterial.ts @@ -0,0 +1,42 @@ +import { fragment, vertex } from "./rgbShift.glsl"; +import { BasicFxMaterial } from "../../core/BasicFxMaterial"; +import { FxMaterialProps } from "../../core/FxMaterial"; +import { BasicFxUniforms, BasicFxValues } from "../../core/BasicFxLib"; +import { NestUniformValues } from "../../../shaders/uniformsUtils"; +import { TexturePipelineSrc } from "../../../misc"; +import * as THREE from 'three'; + +type RGBShiftUniforms = { + /** */ + src: { value: TexturePipelineSrc }; + /** */ + shiftPower: { value: THREE.Vector2 }; +} & BasicFxUniforms; + +export type RGBShiftValues = NestUniformValues & BasicFxValues; + +export class RGBShiftMaterial extends BasicFxMaterial { + static get type() { + return "RGBShiftMaterial"; + } + + uniforms!: RGBShiftUniforms; + + constructor({ + uniformValues, + materialParameters = {}, + }: FxMaterialProps) { + super({ + vertexShader: vertex, + fragmentShader: fragment, + uniformValues, + materialParameters, + uniforms: { + src: { value: null }, + shiftPower: { value: new THREE.Vector2(1, 1) }, + } as RGBShiftUniforms, + }); + + this.type = RGBShiftMaterial.type; + } +} diff --git a/packages/use-shader-fx/src/materials/impl/rgbShift/rgbShift.glsl.ts b/packages/use-shader-fx/src/materials/impl/rgbShift/rgbShift.glsl.ts new file mode 100644 index 00000000..6a866635 --- /dev/null +++ b/packages/use-shader-fx/src/materials/impl/rgbShift/rgbShift.glsl.ts @@ -0,0 +1,27 @@ +import { ShaderLib } from "../../../shaders/ShaderLib"; + +export const vertex = ` + void main() { + ${ShaderLib.plane_vertex} + } +`; + +export const fragment = ` + + uniform sampler2D src; + uniform vec2 shiftPower; + + // TODO: add texture for each channel + + void main() { + + vec2 shift = shiftPower * 0.01; + vec4 r = texture2D(src, vUv + shift); + vec4 g = texture2D(src, vUv); + vec4 b = texture2D(src, vUv - shift); + vec4 outColor = vec4(r.r, g.g, b.b, 1.0); + + gl_FragColor = outColor; + + } +`; diff --git a/packages/use-shader-fx/src/materials/index.js b/packages/use-shader-fx/src/materials/index.js index 8c272be1..f400b625 100644 --- a/packages/use-shader-fx/src/materials/index.js +++ b/packages/use-shader-fx/src/materials/index.js @@ -7,3 +7,4 @@ export * from "./impl/fluid"; export * from "./impl/blur/boxBlur/BoxBlurMaterial"; export * from "./impl/blur/gaussianBlur/GaussianBlurMaterial"; export * from "./impl/cover/CoverTextureMaterial"; +export * from "./impl/rgbShift/RGBShiftMaterial"; From abcb9b55e7bc950d221ded78e66a94d6d52cad39 Mon Sep 17 00:00:00 2001 From: roku-ft Date: Fri, 15 Nov 2024 21:33:01 +0900 Subject: [PATCH 44/60] #146 fix name of useMutableState --- packages/use-shader-fx/src/hooks/useRGBShift/index.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/use-shader-fx/src/hooks/useRGBShift/index.tsx b/packages/use-shader-fx/src/hooks/useRGBShift/index.tsx index 143c3256..e8d9b4d0 100644 --- a/packages/use-shader-fx/src/hooks/useRGBShift/index.tsx +++ b/packages/use-shader-fx/src/hooks/useRGBShift/index.tsx @@ -4,7 +4,7 @@ import { getDpr } from "../../utils/getDpr"; import { RootState } from "../types"; import { RGBShiftMaterial, RGBShiftValues } from "../../materials"; import { useFxScene } from "../../utils/useFxScene"; -import { useMutableConfig } from "../../utils/useMutableConfig"; +import { useMutableState } from "../../utils/useMutableState"; import { useSingleFBO } from "../../utils/useSingleFBO"; type RGBShiftConfig = { @@ -45,7 +45,7 @@ export const useRGBShift = ({ ...renderTargetOptions, }); - const [config, setConfig] = useMutableConfig({ + const [config, setConfig] = useMutableState({ // blurIteration, }); From 0d628b72fb3effd8a55c84d48718c0ea0aa66c0c Mon Sep 17 00:00:00 2001 From: roku-ft Date: Mon, 18 Nov 2024 19:44:40 +0900 Subject: [PATCH 45/60] fix gaussianBlur --- .../src/hooks/blur/useGaussianBlur/index.ts | 9 +++---- .../blur/gaussianBlur/GaussianBlurMaterial.ts | 27 ++----------------- .../impl/blur/gaussianBlur/boxBlur.glsl.ts | 11 ++++---- 3 files changed, 10 insertions(+), 37 deletions(-) diff --git a/packages/use-shader-fx/src/hooks/blur/useGaussianBlur/index.ts b/packages/use-shader-fx/src/hooks/blur/useGaussianBlur/index.ts index cc86fafc..91bdbcd7 100644 --- a/packages/use-shader-fx/src/hooks/blur/useGaussianBlur/index.ts +++ b/packages/use-shader-fx/src/hooks/blur/useGaussianBlur/index.ts @@ -25,7 +25,7 @@ export const useGaussianBlur = ({ renderTargetOptions, materialParameters, radius = 1, - src, // TODO * ここでsrcを定義すると、uniformValuesにsrcがふくまれなくなっちゃう + // src, // TODO * ここでsrcを定義すると、uniformValuesにsrcがふくまれなくなっちゃう ...uniformValues }: GaussianBlurProps): HooksReturn< GaussianBlurValuesAndConfig, @@ -46,9 +46,6 @@ export const useGaussianBlur = ({ }, }); - //THINKS * レンダー中に処理しちゃっていいかも. そもそも不要かも. materialのコメントを確認. - material.setStep(size); - const [renderTarget, updateRenderTarget] = useDoubleFBO({ scene, camera, @@ -83,7 +80,7 @@ export const useGaussianBlur = ({ // draw vertical blur updateRenderTarget({ gl }, () => { - material.uniforms.src.value = src || new THREE.Texture(); + material.uniforms.src.value = uniformValues.src || new THREE.Texture(); material.uniforms.u_stepSize.value.set(0, 1); material.updateBasicFx(); }); @@ -97,7 +94,7 @@ export const useGaussianBlur = ({ return renderTarget.read.texture; }, - [setValues, updateRenderTarget, material, renderTarget, src] + [setValues, updateRenderTarget, material, renderTarget, uniformValues.src] ); return { diff --git a/packages/use-shader-fx/src/materials/impl/blur/gaussianBlur/GaussianBlurMaterial.ts b/packages/use-shader-fx/src/materials/impl/blur/gaussianBlur/GaussianBlurMaterial.ts index 981a0a7d..676ff053 100644 --- a/packages/use-shader-fx/src/materials/impl/blur/gaussianBlur/GaussianBlurMaterial.ts +++ b/packages/use-shader-fx/src/materials/impl/blur/gaussianBlur/GaussianBlurMaterial.ts @@ -17,9 +17,6 @@ type GaussianBlurUniforms = { u_weights: { value: number[]; }; - u_step: { - value: THREE.Vector2; - }; u_stepSize: { value: THREE.Vector2; }; @@ -54,9 +51,6 @@ export class GaussianBlurMaterial extends BasicFxMaterial { u_weights: { value: [0], }, - u_step: { - value: new THREE.Vector2(0, 0), - }, u_stepSize: { value: new THREE.Vector2(0), }, @@ -71,9 +65,7 @@ export class GaussianBlurMaterial extends BasicFxMaterial { setBlurRadius(kernelSize: number) { const weights = []; - let t = 0.0; - - console.log("setBlurRadius", kernelSize); + let t = 0.0; for (let i = kernelSize - 1; i >= 0; i--) { let r = 1.0 + 2.0 * i; @@ -90,23 +82,8 @@ export class GaussianBlurMaterial extends BasicFxMaterial { } // materiaに反映して更新を通知 - this.defines.KERNEL_SIZE = weights.length; // TODO * ここkerbelSizeをそのまま渡す方が直感的かな? + this.defines.KERNEL_SIZE = kernelSize; this.uniforms.u_weights.value = weights; this.needsUpdate = true; } - - // TODO * これは必要? resolutionをshaderで使っちゃえばいいのでは? - // TODO * ちなみに、FxMaterialには、texelSizeというuniformがあるので、それをそのまま使えば処理も不要になるかも updateResolutionのupdateResolutionメソッドを確認。これらのDefaultUniformsは、全てのshaderで自動でprefixとして挿入される。 - setStep(size: Size) { - this.uniforms.u_step.value.set( - 1 / - (size?.width || - this.uniforms.resolution.value.x || - window.innerWidth), - 1 / - (size?.height || - this.uniforms.resolution.value.y || - window.innerHeight) - ); - } } diff --git a/packages/use-shader-fx/src/materials/impl/blur/gaussianBlur/boxBlur.glsl.ts b/packages/use-shader-fx/src/materials/impl/blur/gaussianBlur/boxBlur.glsl.ts index d2eb8b2f..a7a035c3 100644 --- a/packages/use-shader-fx/src/materials/impl/blur/gaussianBlur/boxBlur.glsl.ts +++ b/packages/use-shader-fx/src/materials/impl/blur/gaussianBlur/boxBlur.glsl.ts @@ -6,9 +6,8 @@ export const vertex = ` } `; -export const fragment = ` - uniform sampler2D src; - uniform vec2 u_step; +export const fragment = ` + uniform sampler2D src; uniform vec2 u_stepSize; uniform vec2 sigma; uniform float u_weights[KERNEL_SIZE]; @@ -23,17 +22,17 @@ export const fragment = ` float sumW = 0.0; float actualWeight; vec2 stepSize = u_stepSize * sigma; - + for(int i = 0; i < KERNEL_SIZE - 1; i++){ w = u_weights[i]; - color = texture2D( src, vUv - count * u_step * stepSize ); + color = texture2D( src, vUv - count * texelSize * stepSize ); actualWeight = w * color.a; sum.rgb += color.rgb * actualWeight; sum.a += color.a * w; sumW += actualWeight; - color = texture2D( src, vUv + count * u_step * stepSize ); + color = texture2D( src, vUv + count * texelSize * stepSize ); actualWeight = w * color.a; sum.rgb += color.rgb * actualWeight; sum.a += color.a * w; From 71533d48ba2e2ee05a3be673a2a07ed80a028494 Mon Sep 17 00:00:00 2001 From: roku-ft Date: Mon, 18 Nov 2024 19:47:06 +0900 Subject: [PATCH 46/60] fix gaussianBlur --- .../src/materials/impl/blur/gaussianBlur/GaussianBlurMaterial.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/use-shader-fx/src/materials/impl/blur/gaussianBlur/GaussianBlurMaterial.ts b/packages/use-shader-fx/src/materials/impl/blur/gaussianBlur/GaussianBlurMaterial.ts index 676ff053..92f08ad5 100644 --- a/packages/use-shader-fx/src/materials/impl/blur/gaussianBlur/GaussianBlurMaterial.ts +++ b/packages/use-shader-fx/src/materials/impl/blur/gaussianBlur/GaussianBlurMaterial.ts @@ -5,7 +5,6 @@ import { FxMaterialProps } from "../../../core/FxMaterial"; import { BasicFxUniforms, BasicFxValues } from "../../../core/BasicFxLib"; import { NestUniformValues } from "../../../../shaders/uniformsUtils"; import { TexturePipelineSrc } from "../../../../misc"; -import { Size } from "../../../../hooks/types"; type GaussianBlurUniforms = { /** */ From f88524fe31c08ba41f640c3e20b52699ef6a3eb8 Mon Sep 17 00:00:00 2001 From: roku-ft Date: Mon, 18 Nov 2024 20:19:25 +0900 Subject: [PATCH 47/60] #146 add Playground component and RGB shift material implementation (unfinished) --- app/v2_rgbShift/Playground.tsx | 83 ++++++++++++++++++ app/v2_rgbShift/page.tsx | 39 ++++++++ .../impl/rgbShift/RGBShiftMaterial.ts | 12 ++- .../materials/impl/rgbShift/rgbShift.glsl.ts | 12 ++- public/dummy.png | Bin 0 -> 11336 bytes public/dummy2.png | Bin 0 -> 25636 bytes 6 files changed, 142 insertions(+), 4 deletions(-) create mode 100644 app/v2_rgbShift/Playground.tsx create mode 100644 app/v2_rgbShift/page.tsx create mode 100644 public/dummy.png create mode 100644 public/dummy2.png diff --git a/app/v2_rgbShift/Playground.tsx b/app/v2_rgbShift/Playground.tsx new file mode 100644 index 00000000..2a8c43ce --- /dev/null +++ b/app/v2_rgbShift/Playground.tsx @@ -0,0 +1,83 @@ +"use client"; + +import * as THREE from "three"; +import { useEffect, useRef, useState } from "react"; +import { useFrame, useThree, extend, createPortal } from "@react-three/fiber"; +import { + createFxMaterialImpl, + createBasicFxMaterialImpl, + FxMaterialImplValues, + BasicFxMaterialImplValues, + useRGBShift, +} from "@/packages/use-shader-fx/src"; +import { Float, OrbitControls, useTexture } from "@react-three/drei"; +import { useGaussianBlur } from "@/packages/use-shader-fx/src/hooks/blur/useGaussianBlur"; +import { useCoverTexture } from "@/packages/use-shader-fx/src/hooks/useCoverTexture"; +import { useNoise } from "@/packages/use-shader-fx/src"; +import gsap from "gsap"; + +const FxMaterialImpl = createFxMaterialImpl({ + fragmentShader: ` + uniform sampler2D src; + void main() { + + + gl_FragColor = texture2D(src, vUv); + } +`, +}); +const BasicFxMaterialImpl = createBasicFxMaterialImpl(); + +extend({ FxMaterialImpl, BasicFxMaterialImpl }); + +export const Playground = () => { + const { size, viewport, camera } = useThree(); + + const [app] = useTexture(["/dummy2.png"]); + + const noise = useNoise({ + size, + dpr: 1, + scale: 0.01, + }) + + const coverTexture = useCoverTexture({ + size, + dpr: 1, + src: app, + textureResolution: new THREE.Vector2(app.image.width, app.image.height), + }) + + const rgbShift = useRGBShift({ + size, + dpr: 2, + src: coverTexture.texture, + shiftPower: new THREE.Vector2(2, 2), + shiftPowerSrc: noise.texture, + }) + + + useFrame((state) => { + coverTexture.render(state); + noise.render(state); + rgbShift.render(state); + }); + + return ( + + + + + ); +}; + +declare global { + namespace JSX { + interface IntrinsicElements { + fxMaterialImpl: FxMaterialImplValues & + JSX.IntrinsicElements["shaderMaterial"]; + BasicFxMaterialImpl: BasicFxMaterialImplValues & + JSX.IntrinsicElements["shaderMaterial"]; + } + } +} diff --git a/app/v2_rgbShift/page.tsx b/app/v2_rgbShift/page.tsx new file mode 100644 index 00000000..6256d104 --- /dev/null +++ b/app/v2_rgbShift/page.tsx @@ -0,0 +1,39 @@ +import { ShaderFx } from "../ShaderFx"; +import { Playground } from "./Playground"; +import Image from "next/image"; + +export default function Page() { + return ( +
    + {/*
    + +
    */} + + + +
    + ); +} diff --git a/packages/use-shader-fx/src/materials/impl/rgbShift/RGBShiftMaterial.ts b/packages/use-shader-fx/src/materials/impl/rgbShift/RGBShiftMaterial.ts index 398d2dc8..f80b94ab 100644 --- a/packages/use-shader-fx/src/materials/impl/rgbShift/RGBShiftMaterial.ts +++ b/packages/use-shader-fx/src/materials/impl/rgbShift/RGBShiftMaterial.ts @@ -10,7 +10,11 @@ type RGBShiftUniforms = { /** */ src: { value: TexturePipelineSrc }; /** */ - shiftPower: { value: THREE.Vector2 }; + shiftPower: { value: THREE.Vector2 }; + shiftPowerSrc: { value: TexturePipelineSrc }; // TODO: not implemented yet + shiftPowerSrcR: { value: TexturePipelineSrc }; // TODO: not implemented yet + shiftPowerSrcG: { value: TexturePipelineSrc }; // TODO: not implemented yet + shiftPowerSrcB: { value: TexturePipelineSrc }; // TODO: not implemented yet } & BasicFxUniforms; export type RGBShiftValues = NestUniformValues & BasicFxValues; @@ -33,7 +37,11 @@ export class RGBShiftMaterial extends BasicFxMaterial { materialParameters, uniforms: { src: { value: null }, - shiftPower: { value: new THREE.Vector2(1, 1) }, + shiftPower: { value: new THREE.Vector2(1, 1) }, + shiftPowerSrc: { value: null },// TODO: not implemented yet + shiftPowerSrcR: { value: null },// TODO: not implemented yet + shiftPowerSrcG: { value: null },// TODO: not implemented yet + shiftPowerSrcB: { value: null },// TODO: not implemented yet } as RGBShiftUniforms, }); diff --git a/packages/use-shader-fx/src/materials/impl/rgbShift/rgbShift.glsl.ts b/packages/use-shader-fx/src/materials/impl/rgbShift/rgbShift.glsl.ts index 6a866635..5086f19f 100644 --- a/packages/use-shader-fx/src/materials/impl/rgbShift/rgbShift.glsl.ts +++ b/packages/use-shader-fx/src/materials/impl/rgbShift/rgbShift.glsl.ts @@ -12,10 +12,18 @@ export const fragment = ` uniform vec2 shiftPower; // TODO: add texture for each channel + // uniform sampler2D shiftPowerSrc; + // uniform sampler2D shiftPowerSrcR; + // uniform sampler2D shiftPowerSrcG; + // uniform sampler2D shiftPowerSrcB; - void main() { - + void main() { vec2 shift = shiftPower * 0.01; + + // shift.x = texture2D(shiftPowerSrc, vUv).r * 2.0 - 1.0; + // shift.y = texture2D(shiftPowerSrc, vUv).g * 2.0 - 1.0; + // shift = shift * 0.1; + vec4 r = texture2D(src, vUv + shift); vec4 g = texture2D(src, vUv); vec4 b = texture2D(src, vUv - shift); diff --git a/public/dummy.png b/public/dummy.png new file mode 100644 index 0000000000000000000000000000000000000000..8b85dd7be38bdf4c4d9275a67a163f376f5a94ab GIT binary patch literal 11336 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 z�X4&C>5=Y6q$z8PueJ#QO|^_Z{YLqBCEEuES`{y~}R)i;Q35P2Bpvq(?W`&;f2o zg|)4!1?6b)9n;L7r!xW1_2q_U?r(IDoCZNTCnC(A1dr(0nd%cF;*dm9Eykxs5J)A&t+#04wP^4?_TIXnN z{^R+FE`isKidu5yBf=Az-Dzi!?p+*&X0P>WCRmp7 z#ftw9$nHdZr;!1})#MQTP{jS5d`OWyVr( zBy`F!;&FpAJvZ88o;?~r7*Z|jtHe$tp%RgEuE`vG)NE<6HSr#65`P;-eCVWYTm(*V zrWS1(vyHvR1~v7e)+|VLT9uJcBPwOYKA5&1wfZfOpz?fsbZ){#@ji9Bl%wyp`~a`D zZ!Do^?p9QNw~F^0Ye$MYpP^Is{Xq=95&JKz`)K(1zPS9r0I2+@qWZ5nJ=B^l9~ccN zS++>}^r@7S7sBjqoUD0-2b!PK)HW{)R)78|jSPO_p){x(N?VzHP<|aIPjz6G>(mF6 zf|ZJRdrH*2a>`58Hk+Z*Uw7fDAU_7&Krp&oQa$-B*=Hsc+PQFIqM(MOCE9*FUsTW> z@JB8zCvm0wI~fjyEu!VrsjXc-fWS(`$`9G;L<0S=HVJO%OS|7T&BvF`b&Mug03HaU zTPKCG<#BTSTJ4=I&QgnflKatf3bACT<=jB08XOQ29j&0F@!Ln?n*2WGQK0uVS*Z9R z@g)FYJp;5_4d{<<5jGV8mI$Qo|5XU7LE>zZO0*LO!(SQ`4%38W14!Qu$TzxRws}+& zAkGI>%G4_W*Xp|gAkh)i62R>Ie(9&f`M@6&7B{(Vt~Pll!uK7rH$nhXbBwaDrtpo9z;WaI+<=q+$+YB;HU8I2F#qQ<&OaXQk4O96ko~Y< zKUCp|D*R9d;ST(8a{#IL{rIsHKX&3jlJLVn{_u}KjKX(a_@N3vRN;pz{BNj2t23=% jNHGCNLwRe~4s#bowkwqg@#Cxu$F5zr{;k~1?aBWFg4z)2 literal 0 HcmV?d00001 From de2814e123e4e4946c1670f841f63d8c5e0955bf Mon Sep 17 00:00:00 2001 From: roku-ft Date: Tue, 19 Nov 2024 15:34:58 +0900 Subject: [PATCH 48/60] add timeOffset uniform to NoiseMaterial for enhanced noise manipulation --- .../use-shader-fx/src/materials/impl/noise/NoiseMaterial.ts | 3 +++ packages/use-shader-fx/src/materials/impl/noise/noise.glsl.ts | 4 +++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/packages/use-shader-fx/src/materials/impl/noise/NoiseMaterial.ts b/packages/use-shader-fx/src/materials/impl/noise/NoiseMaterial.ts index a3f2804e..21c48c43 100644 --- a/packages/use-shader-fx/src/materials/impl/noise/NoiseMaterial.ts +++ b/packages/use-shader-fx/src/materials/impl/noise/NoiseMaterial.ts @@ -25,6 +25,8 @@ type NoiseUniforms = { warpDirection: { value: THREE.Vector2 }; /** strength of domain warping , default : `8.0` */ warpStrength: { value: number }; + /** offset of the time */ + timeOffset: { value: number }; } & BasicFxUniforms; export type NoiseValues = NestUniformValues & BasicFxValues; @@ -58,6 +60,7 @@ export class NoiseMaterial extends BasicFxMaterial { warpOctaves: { value: 2 }, warpDirection: { value: new THREE.Vector2(2.0, 2.0) }, warpStrength: { value: 8 }, + timeOffset: { value: 0 }, } as NoiseUniforms, }); this.type = NoiseMaterial.type; diff --git a/packages/use-shader-fx/src/materials/impl/noise/noise.glsl.ts b/packages/use-shader-fx/src/materials/impl/noise/noise.glsl.ts index 0d475218..72a3818c 100644 --- a/packages/use-shader-fx/src/materials/impl/noise/noise.glsl.ts +++ b/packages/use-shader-fx/src/materials/impl/noise/noise.glsl.ts @@ -17,6 +17,7 @@ export const noiseFragment = ` uniform vec2 warpDirection; uniform float warpStrength; uniform float scale; + uniform float timeOffset; const float per = 0.5; const float PI = 3.14159265359; @@ -45,11 +46,12 @@ export const noiseFragment = ` // Based on The Book of Shaders // https://thebookofshaders.com/13/ float noise(vec2 p, float time){ + float _time = time + timeOffset; float t = 0.0; for(int i = 0; i < noiseOctaves; i++){ float freq = pow(2.0, float(i)); float amp = pow(per, float(noiseOctaves - i)); - t += irnd(vec2(p.y / freq + time, p.x / freq + time)) * amp; + t += irnd(vec2(p.y / freq + _time, p.x / freq + _time)) * amp; } return t; } From 4fdbff9ccc5d50245e1cd33edcd39ede24275375 Mon Sep 17 00:00:00 2001 From: roku-ft Date: Tue, 19 Nov 2024 16:09:31 +0900 Subject: [PATCH 49/60] #146 refactor useRGBShift to support individual channel shifting --- app/v2_rgbShift/Playground.tsx | 59 ++++++++++++++----- .../src/hooks/useRGBShift/index.tsx | 19 ++---- .../impl/rgbShift/RGBShiftMaterial.ts | 26 ++++---- .../materials/impl/rgbShift/rgbShift.glsl.ts | 56 ++++++++++++------ 4 files changed, 103 insertions(+), 57 deletions(-) diff --git a/app/v2_rgbShift/Playground.tsx b/app/v2_rgbShift/Playground.tsx index 2a8c43ce..d7520dff 100644 --- a/app/v2_rgbShift/Playground.tsx +++ b/app/v2_rgbShift/Playground.tsx @@ -19,10 +19,9 @@ import gsap from "gsap"; const FxMaterialImpl = createFxMaterialImpl({ fragmentShader: ` uniform sampler2D src; - void main() { - - - gl_FragColor = texture2D(src, vUv); + void main() { + vec4 oC = texture2D(src, vUv); + gl_FragColor = oC; } `, }); @@ -35,38 +34,70 @@ export const Playground = () => { const [app] = useTexture(["/dummy2.png"]); + const coverTexture = useCoverTexture({ + size, + dpr: 1, + src: app, + textureResolution: new THREE.Vector2(app.image.width, app.image.height), + }) + const noise = useNoise({ size, dpr: 1, - scale: 0.01, + scale: 0.001, + timeOffset: 0, }) - const coverTexture = useCoverTexture({ + const noise2 = useNoise({ size, - dpr: 1, - src: app, - textureResolution: new THREE.Vector2(app.image.width, app.image.height), - }) + dpr: 1, + scale: 0.001, + timeOffset: .04, + }) + + const noise3 = useNoise({ + size, + dpr: 1, + scale: 0.001, + timeOffset: .08, + }) const rgbShift = useRGBShift({ size, dpr: 2, + shiftScale: .18, src: coverTexture.texture, shiftPower: new THREE.Vector2(2, 2), - shiftPowerSrc: noise.texture, + shiftPowerSrcR: noise.texture, + shiftPowerSrcG: noise2.texture, + shiftPowerSrcB: noise3.texture, + isUseShiftPowerSrcR: true, + isUseShiftPowerSrcG: true, + isUseShiftPowerSrcB: true, + }) + + const gBlur = useGaussianBlur({ + size, + dpr: 1, + radius: 3, + src: rgbShift.texture, + sigma: new THREE.Vector2(1, 1), }) - useFrame((state) => { + useFrame((state) => { coverTexture.render(state); noise.render(state); - rgbShift.render(state); + noise2.render(state); + noise3.render(state); + rgbShift.render(state); + gBlur.render(state); }); return ( - + ); }; diff --git a/packages/use-shader-fx/src/hooks/useRGBShift/index.tsx b/packages/use-shader-fx/src/hooks/useRGBShift/index.tsx index e8d9b4d0..a52a8cfa 100644 --- a/packages/use-shader-fx/src/hooks/useRGBShift/index.tsx +++ b/packages/use-shader-fx/src/hooks/useRGBShift/index.tsx @@ -4,14 +4,9 @@ import { getDpr } from "../../utils/getDpr"; import { RootState } from "../types"; import { RGBShiftMaterial, RGBShiftValues } from "../../materials"; import { useFxScene } from "../../utils/useFxScene"; -import { useMutableState } from "../../utils/useMutableState"; import { useSingleFBO } from "../../utils/useSingleFBO"; -type RGBShiftConfig = { -// blurIteration?: number; -}; - -type RGBShiftValuesAndConfig = RGBShiftValues & RGBShiftConfig; +type RGBShiftValuesAndConfig = RGBShiftValues; export type RGBShiftProps = HooksProps & RGBShiftValuesAndConfig; /** @@ -23,7 +18,6 @@ export const useRGBShift = ({ fboAutoSetSize, renderTargetOptions, materialParameters, -// blurIteration = 5, ...uniformValues }: RGBShiftProps): HooksReturn => { const _dpr = getDpr(dpr); @@ -45,17 +39,12 @@ export const useRGBShift = ({ ...renderTargetOptions, }); - const [config, setConfig] = useMutableState({ - // blurIteration, - }); - const setValues = useCallback( (newValues: RGBShiftValuesAndConfig) => { - const { ...rest } = newValues; - // setConfig({ blurIteration }); + const { ...rest } = newValues; material.setUniformValues(rest); }, - [material, setConfig] + [material] ); const render = useCallback( @@ -66,7 +55,7 @@ export const useRGBShift = ({ updateRenderTarget({ gl }); return renderTarget.texture; }, - [setValues, updateRenderTarget, material, renderTarget, config] + [setValues, updateRenderTarget, material, renderTarget] ); return { diff --git a/packages/use-shader-fx/src/materials/impl/rgbShift/RGBShiftMaterial.ts b/packages/use-shader-fx/src/materials/impl/rgbShift/RGBShiftMaterial.ts index f80b94ab..a703b29f 100644 --- a/packages/use-shader-fx/src/materials/impl/rgbShift/RGBShiftMaterial.ts +++ b/packages/use-shader-fx/src/materials/impl/rgbShift/RGBShiftMaterial.ts @@ -10,11 +10,14 @@ type RGBShiftUniforms = { /** */ src: { value: TexturePipelineSrc }; /** */ - shiftPower: { value: THREE.Vector2 }; - shiftPowerSrc: { value: TexturePipelineSrc }; // TODO: not implemented yet - shiftPowerSrcR: { value: TexturePipelineSrc }; // TODO: not implemented yet - shiftPowerSrcG: { value: TexturePipelineSrc }; // TODO: not implemented yet - shiftPowerSrcB: { value: TexturePipelineSrc }; // TODO: not implemented yet + shiftPower: { value: THREE.Vector2 }; + shiftPowerSrcR: { value: TexturePipelineSrc }; + isUseShiftPowerSrcR: { value: boolean }; + shiftPowerSrcG: { value: TexturePipelineSrc }; + isUseShiftPowerSrcG: { value: boolean }; + shiftPowerSrcB: { value: TexturePipelineSrc }; + isUseShiftPowerSrcB: { value: boolean }; + shiftScale: { value: number }; } & BasicFxUniforms; export type RGBShiftValues = NestUniformValues & BasicFxValues; @@ -37,11 +40,14 @@ export class RGBShiftMaterial extends BasicFxMaterial { materialParameters, uniforms: { src: { value: null }, - shiftPower: { value: new THREE.Vector2(1, 1) }, - shiftPowerSrc: { value: null },// TODO: not implemented yet - shiftPowerSrcR: { value: null },// TODO: not implemented yet - shiftPowerSrcG: { value: null },// TODO: not implemented yet - shiftPowerSrcB: { value: null },// TODO: not implemented yet + shiftPower: { value: new THREE.Vector2(1, 1) }, + shiftPowerSrcR: { value: null }, + isUseShiftPowerSrcR: { value: false }, + shiftPowerSrcG: { value: null }, + isUseShiftPowerSrcG: { value: false }, + shiftPowerSrcB: { value: null }, + isUseShiftPowerSrcB: { value: false }, + shiftScale: { value: 0.01 }, } as RGBShiftUniforms, }); diff --git a/packages/use-shader-fx/src/materials/impl/rgbShift/rgbShift.glsl.ts b/packages/use-shader-fx/src/materials/impl/rgbShift/rgbShift.glsl.ts index 5086f19f..2af358c0 100644 --- a/packages/use-shader-fx/src/materials/impl/rgbShift/rgbShift.glsl.ts +++ b/packages/use-shader-fx/src/materials/impl/rgbShift/rgbShift.glsl.ts @@ -11,24 +11,44 @@ export const fragment = ` uniform sampler2D src; uniform vec2 shiftPower; - // TODO: add texture for each channel - // uniform sampler2D shiftPowerSrc; - // uniform sampler2D shiftPowerSrcR; - // uniform sampler2D shiftPowerSrcG; - // uniform sampler2D shiftPowerSrcB; - - void main() { - vec2 shift = shiftPower * 0.01; - - // shift.x = texture2D(shiftPowerSrc, vUv).r * 2.0 - 1.0; - // shift.y = texture2D(shiftPowerSrc, vUv).g * 2.0 - 1.0; - // shift = shift * 0.1; - - vec4 r = texture2D(src, vUv + shift); - vec4 g = texture2D(src, vUv); - vec4 b = texture2D(src, vUv - shift); - vec4 outColor = vec4(r.r, g.g, b.b, 1.0); - + // TODO: add texture for each channel + uniform sampler2D shiftPowerSrcR; + uniform bool isUseShiftPowerSrcR; + uniform sampler2D shiftPowerSrcG; + uniform bool isUseShiftPowerSrcG; + uniform sampler2D shiftPowerSrcB; + uniform bool isUseShiftPowerSrcB; + uniform float shiftScale; + + void main() { + vec2 shift = shiftPower * shiftScale; + + float r = 0.0; + if(isUseShiftPowerSrcR){ + vec2 shiftR = (texture2D(shiftPowerSrcR, vUv).rg * 2.0 - 1.0) * shiftScale; + r = texture2D(src, vUv + shiftR).r; + } else { + r = texture2D(src, vUv + shift).r; + } + + float g = 0.0; + if(isUseShiftPowerSrcG){ + vec2 shiftG = (texture2D(shiftPowerSrcG, vUv).rg * 2.0 - 1.0) * shiftScale; + g = texture2D(src, vUv + shiftG).g; + } else { + g = texture2D(src, vUv + shift).g; + } + + float b = 0.0; + if(isUseShiftPowerSrcB){ + vec2 shiftB = (texture2D(shiftPowerSrcB, vUv).rg * 2.0 - 1.0) * shiftScale; + b = texture2D(src, vUv + shiftB).b; + } else { + b = texture2D(src, vUv + shift).b; + } + + + vec4 outColor = vec4(r, g, b, 1.0); gl_FragColor = outColor; } From 9dacdcac172de9608a05c5a1ea291988c2216645 Mon Sep 17 00:00:00 2001 From: roku-ft Date: Tue, 19 Nov 2024 16:56:22 +0900 Subject: [PATCH 50/60] refactor useGaussianBlur --- packages/use-shader-fx/src/hooks/blur/useGaussianBlur/index.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/use-shader-fx/src/hooks/blur/useGaussianBlur/index.ts b/packages/use-shader-fx/src/hooks/blur/useGaussianBlur/index.ts index 91bdbcd7..5558f932 100644 --- a/packages/use-shader-fx/src/hooks/blur/useGaussianBlur/index.ts +++ b/packages/use-shader-fx/src/hooks/blur/useGaussianBlur/index.ts @@ -24,8 +24,7 @@ export const useGaussianBlur = ({ fboAutoSetSize, renderTargetOptions, materialParameters, - radius = 1, - // src, // TODO * ここでsrcを定義すると、uniformValuesにsrcがふくまれなくなっちゃう + radius = 1, ...uniformValues }: GaussianBlurProps): HooksReturn< GaussianBlurValuesAndConfig, From 1daba20d09f02aaa05897da5cad6382dc6b1ddc2 Mon Sep 17 00:00:00 2001 From: roku-ft Date: Tue, 19 Nov 2024 17:30:19 +0900 Subject: [PATCH 51/60] fix import path for GaussianBlurMaterial to use correct GLSL file --- .../materials/impl/blur/gaussianBlur/GaussianBlurMaterial.ts | 2 +- .../blur/gaussianBlur/{boxBlur.glsl.ts => gaussianBlur.glsl.ts} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename packages/use-shader-fx/src/materials/impl/blur/gaussianBlur/{boxBlur.glsl.ts => gaussianBlur.glsl.ts} (100%) diff --git a/packages/use-shader-fx/src/materials/impl/blur/gaussianBlur/GaussianBlurMaterial.ts b/packages/use-shader-fx/src/materials/impl/blur/gaussianBlur/GaussianBlurMaterial.ts index 92f08ad5..9910559f 100644 --- a/packages/use-shader-fx/src/materials/impl/blur/gaussianBlur/GaussianBlurMaterial.ts +++ b/packages/use-shader-fx/src/materials/impl/blur/gaussianBlur/GaussianBlurMaterial.ts @@ -1,5 +1,5 @@ import * as THREE from "three"; -import { fragment, vertex } from "./boxBlur.glsl"; +import { fragment, vertex } from "./gaussianBlur.glsl"; import { BasicFxMaterial } from "../../../core/BasicFxMaterial"; import { FxMaterialProps } from "../../../core/FxMaterial"; import { BasicFxUniforms, BasicFxValues } from "../../../core/BasicFxLib"; diff --git a/packages/use-shader-fx/src/materials/impl/blur/gaussianBlur/boxBlur.glsl.ts b/packages/use-shader-fx/src/materials/impl/blur/gaussianBlur/gaussianBlur.glsl.ts similarity index 100% rename from packages/use-shader-fx/src/materials/impl/blur/gaussianBlur/boxBlur.glsl.ts rename to packages/use-shader-fx/src/materials/impl/blur/gaussianBlur/gaussianBlur.glsl.ts From 7fcb2018f7f39b15484f60a0a7e087961a169151 Mon Sep 17 00:00:00 2001 From: roku-ft Date: Tue, 19 Nov 2024 19:36:16 +0900 Subject: [PATCH 52/60] #147 add useBotionBlur --- app/v2_rgbShift/Playground.tsx | 38 +++++---- .../src/hooks/blur/useMotionBlur/index.tsx | 82 +++++++++++++++++++ packages/use-shader-fx/src/hooks/index.ts | 12 ++- .../blur/motionBlur/MotionBlurMaterial.ts | 55 +++++++++++++ .../impl/blur/motionBlur/motionBlur.glsl.ts | 20 +++++ packages/use-shader-fx/src/materials/index.js | 1 + 6 files changed, 191 insertions(+), 17 deletions(-) create mode 100644 packages/use-shader-fx/src/hooks/blur/useMotionBlur/index.tsx create mode 100644 packages/use-shader-fx/src/materials/impl/blur/motionBlur/MotionBlurMaterial.ts create mode 100644 packages/use-shader-fx/src/materials/impl/blur/motionBlur/motionBlur.glsl.ts diff --git a/app/v2_rgbShift/Playground.tsx b/app/v2_rgbShift/Playground.tsx index d7520dff..35aa7636 100644 --- a/app/v2_rgbShift/Playground.tsx +++ b/app/v2_rgbShift/Playground.tsx @@ -9,12 +9,12 @@ import { FxMaterialImplValues, BasicFxMaterialImplValues, useRGBShift, + useGaussianBlur } from "@/packages/use-shader-fx/src"; import { Float, OrbitControls, useTexture } from "@react-three/drei"; -import { useGaussianBlur } from "@/packages/use-shader-fx/src/hooks/blur/useGaussianBlur"; import { useCoverTexture } from "@/packages/use-shader-fx/src/hooks/useCoverTexture"; import { useNoise } from "@/packages/use-shader-fx/src"; -import gsap from "gsap"; +import { useMotionBlur } from "@/packages/use-shader-fx/src/hooks/blur/useMotionBlur"; const FxMaterialImpl = createFxMaterialImpl({ fragmentShader: ` @@ -44,28 +44,28 @@ export const Playground = () => { const noise = useNoise({ size, dpr: 1, - scale: 0.001, + scale: 0.005, timeOffset: 0, }) const noise2 = useNoise({ size, dpr: 1, - scale: 0.001, - timeOffset: .04, + scale: 0.005, + timeOffset: .03, }) const noise3 = useNoise({ size, dpr: 1, - scale: 0.001, - timeOffset: .08, + scale: 0.005, + timeOffset: .06, }) const rgbShift = useRGBShift({ size, dpr: 2, - shiftScale: .18, + shiftScale: .1, src: coverTexture.texture, shiftPower: new THREE.Vector2(2, 2), shiftPowerSrcR: noise.texture, @@ -76,28 +76,34 @@ export const Playground = () => { isUseShiftPowerSrcB: true, }) - const gBlur = useGaussianBlur({ + const gbBur = useGaussianBlur({ size, dpr: 1, - radius: 3, + radius: 2, + sigma: new THREE.Vector2(0, 0), src: rgbShift.texture, - sigma: new THREE.Vector2(1, 1), - }) - + }); + + const motionBlur = useMotionBlur({ + size, + dpr: 1, + src: gbBur.texture, + }); useFrame((state) => { coverTexture.render(state); noise.render(state); noise2.render(state); noise3.render(state); - rgbShift.render(state); - gBlur.render(state); + rgbShift.render(state); + gbBur.render(state); + motionBlur.render(state); }); return ( - + ); }; diff --git a/packages/use-shader-fx/src/hooks/blur/useMotionBlur/index.tsx b/packages/use-shader-fx/src/hooks/blur/useMotionBlur/index.tsx new file mode 100644 index 00000000..46ae301a --- /dev/null +++ b/packages/use-shader-fx/src/hooks/blur/useMotionBlur/index.tsx @@ -0,0 +1,82 @@ +import { useCallback } from "react"; +import { HooksProps, HooksReturn } from "../../types"; +import { + getDpr, + useDoubleFBO, + useFxScene, +} from "../../../utils"; +import { RootState } from "../../types"; +import { MotionBlurMaterial, MotionBlurValues } from "../../../materials"; + +type MotionBlurConfig = { +}; + +type MotionBlurValuesAndConfig = MotionBlurValues & MotionBlurConfig; + +export type MotionBlurProps = HooksProps & MotionBlurValuesAndConfig; + +export const useMotionBlur = ({ + size, + dpr, + fboAutoSetSize, + renderTargetOptions, + materialParameters, + ...uniformValues +}: MotionBlurProps): HooksReturn< + MotionBlurValuesAndConfig, + MotionBlurMaterial +> => { + const _dpr = getDpr(dpr); + + const { scene, material, camera } = useFxScene({ + size, + dpr: _dpr.shader, + material: MotionBlurMaterial, + uniformValues, + materialParameters: { + ...materialParameters, + }, + }); + + const [renderTarget, updateRenderTarget] = useDoubleFBO({ + scene, + camera, + size, + dpr: _dpr.fbo, + fboAutoSetSize, + ...renderTargetOptions, + }); + + const setValues = useCallback( + (newValues: MotionBlurValuesAndConfig) => { + const { ...rest } = newValues; + material.setUniformValues(rest); + }, + [material] + ); + + const render = useCallback( + (rootState: RootState, newValues?: MotionBlurValuesAndConfig) => { + const { gl } = rootState; + newValues && setValues(newValues); + + updateRenderTarget({gl}, ({read}) => { + material.uniforms.backBuffer.value = read; + material.updateBasicFx(); + }); + + return renderTarget.read.texture; + }, + [setValues, updateRenderTarget, material, renderTarget, uniformValues.src] + ); + + return { + render, + setValues, + texture: renderTarget.read.texture, + material, + scene, + camera, + renderTarget, + }; +}; diff --git a/packages/use-shader-fx/src/hooks/index.ts b/packages/use-shader-fx/src/hooks/index.ts index 16f544d8..a5ad6627 100644 --- a/packages/use-shader-fx/src/hooks/index.ts +++ b/packages/use-shader-fx/src/hooks/index.ts @@ -1,4 +1,6 @@ import { useBoxBlur, BoxBlurProps } from "./blur/useBoxBlur"; +import { useGaussianBlur, GaussianBlurProps } from "./blur/useGaussianBlur"; +import { useMotionBlur, MotionBlurProps } from "./blur/useMotionBlur"; import { useCoverTexture, CoverTextureProps } from "./useCoverTexture"; import { useFluid, FluidProps } from "./useFluid"; import { useNoise, NoiseProps } from "./useNoise"; @@ -11,7 +13,9 @@ export type FxTypes = | typeof useFluid | typeof useNoise | typeof useRawBlank - | typeof useRGBShift; + | typeof useRGBShift + | typeof useMotionBlur + | typeof useGaussianBlur; export type FxProps = T extends typeof useBoxBlur @@ -26,6 +30,10 @@ export type FxProps = ? RGBShiftProps : T extends typeof useRGBShift ? RawBlankProps + : T extends typeof useMotionBlur + ? MotionBlurProps + : T extends typeof useGaussianBlur + ? MotionBlurProps : never; export * from "./blur/useBoxBlur"; @@ -34,3 +42,5 @@ export * from "./useFluid"; export * from "./useNoise"; export * from "./useRawBlank"; export * from "./useRGBShift"; +export * from "./blur/useMotionBlur"; +export * from "./blur/useGaussianBlur"; diff --git a/packages/use-shader-fx/src/materials/impl/blur/motionBlur/MotionBlurMaterial.ts b/packages/use-shader-fx/src/materials/impl/blur/motionBlur/MotionBlurMaterial.ts new file mode 100644 index 00000000..0140e046 --- /dev/null +++ b/packages/use-shader-fx/src/materials/impl/blur/motionBlur/MotionBlurMaterial.ts @@ -0,0 +1,55 @@ +import * as THREE from "three"; +import { fragment, vertex } from "./motionBlur.glsl"; +import { BasicFxMaterial } from "../../../core/BasicFxMaterial"; +import { FxMaterialProps } from "../../../core/FxMaterial"; +import { BasicFxUniforms, BasicFxValues } from "../../../core/BasicFxLib"; +import { NestUniformValues } from "../../../../shaders/uniformsUtils"; +import { TexturePipelineSrc } from "../../../../misc"; + +type MotionBlurUniforms = { + /** */ + src: { value: TexturePipelineSrc }; + /** */ + backBuffer: { + value: TexturePipelineSrc + }; + mixRatio: { + value: number; + }; +} & BasicFxUniforms; + +export type MotionBlurValues = NestUniformValues & + BasicFxValues; + +export class MotionBlurMaterial extends BasicFxMaterial { + static get type() { + return "MotionBlurMaterial"; + } + + uniforms!: MotionBlurUniforms; + + constructor({ + uniformValues, + materialParameters = {}, + }: FxMaterialProps) { + super({ + vertexShader: vertex, + fragmentShader: fragment, + uniformValues, + materialParameters, + uniforms: { + src: { + value: null, + }, + backBuffer: { + value: new THREE.Texture(), + }, + mixRatio: { + value: 0.06, + }, + } as MotionBlurUniforms, + }); + + this.type = MotionBlurMaterial.type; + } +} diff --git a/packages/use-shader-fx/src/materials/impl/blur/motionBlur/motionBlur.glsl.ts b/packages/use-shader-fx/src/materials/impl/blur/motionBlur/motionBlur.glsl.ts new file mode 100644 index 00000000..5fc4f544 --- /dev/null +++ b/packages/use-shader-fx/src/materials/impl/blur/motionBlur/motionBlur.glsl.ts @@ -0,0 +1,20 @@ +import { ShaderLib } from "../../../../shaders/ShaderLib"; + +export const vertex = ` + void main() { + ${ShaderLib.plane_vertex} + } +`; + +export const fragment = ` + uniform sampler2D src; + uniform sampler2D backBuffer; + uniform float mixRatio; + + void main() { + vec4 color = texture2D(src, vUv); + vec4 prevColor = texture2D(backBuffer, vUv); + + gl_FragColor = mix(prevColor, color, mixRatio); + } +`; diff --git a/packages/use-shader-fx/src/materials/index.js b/packages/use-shader-fx/src/materials/index.js index f400b625..e33cb1aa 100644 --- a/packages/use-shader-fx/src/materials/index.js +++ b/packages/use-shader-fx/src/materials/index.js @@ -6,5 +6,6 @@ export * from "./impl/rawBlank/RawBlankMaterial"; export * from "./impl/fluid"; export * from "./impl/blur/boxBlur/BoxBlurMaterial"; export * from "./impl/blur/gaussianBlur/GaussianBlurMaterial"; +export * from "./impl/blur/motionBlur/MotionBlurMaterial"; export * from "./impl/cover/CoverTextureMaterial"; export * from "./impl/rgbShift/RGBShiftMaterial"; From 47f96bcee6b3acc96d0cdb285f10ca6ff5b8b903 Mon Sep 17 00:00:00 2001 From: roku-ft Date: Tue, 19 Nov 2024 19:40:08 +0900 Subject: [PATCH 53/60] #147 refactor useMotionBlur --- .../src/materials/impl/blur/motionBlur/motionBlur.glsl.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/use-shader-fx/src/materials/impl/blur/motionBlur/motionBlur.glsl.ts b/packages/use-shader-fx/src/materials/impl/blur/motionBlur/motionBlur.glsl.ts index 5fc4f544..8deb1bab 100644 --- a/packages/use-shader-fx/src/materials/impl/blur/motionBlur/motionBlur.glsl.ts +++ b/packages/use-shader-fx/src/materials/impl/blur/motionBlur/motionBlur.glsl.ts @@ -12,9 +12,9 @@ export const fragment = ` uniform float mixRatio; void main() { - vec4 color = texture2D(src, vUv); + vec4 currentColor = texture2D(src, vUv); vec4 prevColor = texture2D(backBuffer, vUv); - gl_FragColor = mix(prevColor, color, mixRatio); + gl_FragColor = mix(prevColor, currentColor, mixRatio); } `; From 0da64d37f007de4444511f07befcff7535a3a846 Mon Sep 17 00:00:00 2001 From: roku-ft Date: Thu, 21 Nov 2024 03:24:00 +0900 Subject: [PATCH 54/60] #149 add base of useDistortion --- .gitignore | 3 +- app/v2_distortion/Playground.tsx | 134 ++++++++++++ app/v2_distortion/page.tsx | 39 ++++ packages/use-shader-fx/src/hooks/index.ts | 7 +- .../src/hooks/useDistortion/index.tsx | 71 +++++++ .../impl/distortion/DistortionMaterial.ts | 52 +++++ .../impl/distortion/distortion.glsl.ts | 194 ++++++++++++++++++ packages/use-shader-fx/src/materials/index.js | 1 + public/dummy3.png | Bin 0 -> 11850 bytes 9 files changed, 499 insertions(+), 2 deletions(-) create mode 100644 app/v2_distortion/Playground.tsx create mode 100644 app/v2_distortion/page.tsx create mode 100644 packages/use-shader-fx/src/hooks/useDistortion/index.tsx create mode 100644 packages/use-shader-fx/src/materials/impl/distortion/DistortionMaterial.ts create mode 100644 packages/use-shader-fx/src/materials/impl/distortion/distortion.glsl.ts create mode 100644 public/dummy3.png diff --git a/.gitignore b/.gitignore index a5e26829..4d8fb2a8 100644 --- a/.gitignore +++ b/.gitignore @@ -41,4 +41,5 @@ storybook-static/ CreateShaderFx/ # exclude private demo -app/private/ \ No newline at end of file +app/private/ +public/private/ diff --git a/app/v2_distortion/Playground.tsx b/app/v2_distortion/Playground.tsx new file mode 100644 index 00000000..2667dbb2 --- /dev/null +++ b/app/v2_distortion/Playground.tsx @@ -0,0 +1,134 @@ +"use client"; + +import * as THREE from "three"; +import { useEffect, useRef, useState } from "react"; +import { useFrame, useThree, extend, createPortal } from "@react-three/fiber"; +import { + createFxMaterialImpl, + createBasicFxMaterialImpl, + FxMaterialImplValues, + BasicFxMaterialImplValues, + useRGBShift, + useGaussianBlur, + useDistortion +} from "@/packages/use-shader-fx/src"; +import { Float, OrbitControls, useTexture } from "@react-three/drei"; +import { useCoverTexture } from "@/packages/use-shader-fx/src/hooks/useCoverTexture"; +import { useNoise } from "@/packages/use-shader-fx/src"; +import { useMotionBlur } from "@/packages/use-shader-fx/src/hooks/blur/useMotionBlur"; + +const FxMaterialImpl = createFxMaterialImpl({ + fragmentShader: ` + uniform sampler2D src; + void main() { + vec4 oC = texture2D(src, vUv); + gl_FragColor = oC; + } +`, +}); +const BasicFxMaterialImpl = createBasicFxMaterialImpl(); + +extend({ FxMaterialImpl, BasicFxMaterialImpl }); + +export const Playground = () => { + const { size, viewport, camera } = useThree(); + + const [app] = useTexture(["/dummy3.png"]); + // const [app] = useTexture(["/funkun.jpg"]); + // const [app] = useTexture(["/private//fv.png"]); + + const coverTexture = useCoverTexture({ + size, + dpr: 1, + src: app, + textureResolution: new THREE.Vector2(app.image.width, app.image.height), + }) + + const noise = useNoise({ + size, + dpr: 1, + scale: 0.002, + timeStrength: 0.01, + timeOffset: 0, + }) + + const noise2 = useNoise({ + size, + dpr: 1, + scale: 0.002, + timeStrength: 0.01, + + timeOffset: .1, + }) + + const noise3 = useNoise({ + size, + dpr: 1, + scale: 0.002, + timeStrength: 0.01, + timeOffset: .2, + }) + + const rgbShift = useRGBShift({ + size, + dpr: 2, + shiftScale: .04, + src: coverTexture.texture, + shiftPower: new THREE.Vector2(2, 2), + shiftPowerSrcR: noise.texture, + shiftPowerSrcG: noise2.texture, + shiftPowerSrcB: noise3.texture, + isUseShiftPowerSrcR: true, + isUseShiftPowerSrcG: true, + isUseShiftPowerSrcB: true, + }) + + + const motionBlur = useMotionBlur({ + size, + dpr: 1, + src: rgbShift.texture, + }); + + const distortion = useDistortion({ + size, + dpr: 1, + src: motionBlur.texture, + scale: new THREE.Vector2(0.,0.2), + // scale: new THREE.Vector2(1.,3.0), + freq: new THREE.Vector2(120.,1.), + powNum: new THREE.Vector2(1.,1.), + timeStrength: new THREE.Vector2(1.0,1.0), + }) + + useFrame((state) => { + + + coverTexture.render(state); + noise.render(state); + noise2.render(state); + noise3.render(state); + rgbShift.render(state); + motionBlur.render(state); + distortion.render(state); + // gbBur.render(state); + }); + + return ( + + + + + ); +}; + +declare global { + namespace JSX { + interface IntrinsicElements { + fxMaterialImpl: FxMaterialImplValues & + JSX.IntrinsicElements["shaderMaterial"]; + BasicFxMaterialImpl: BasicFxMaterialImplValues & + JSX.IntrinsicElements["shaderMaterial"]; + } + } +} diff --git a/app/v2_distortion/page.tsx b/app/v2_distortion/page.tsx new file mode 100644 index 00000000..6256d104 --- /dev/null +++ b/app/v2_distortion/page.tsx @@ -0,0 +1,39 @@ +import { ShaderFx } from "../ShaderFx"; +import { Playground } from "./Playground"; +import Image from "next/image"; + +export default function Page() { + return ( +
    + {/*
    + +
    */} + + + +
    + ); +} diff --git a/packages/use-shader-fx/src/hooks/index.ts b/packages/use-shader-fx/src/hooks/index.ts index a5ad6627..024884d0 100644 --- a/packages/use-shader-fx/src/hooks/index.ts +++ b/packages/use-shader-fx/src/hooks/index.ts @@ -2,6 +2,7 @@ import { useBoxBlur, BoxBlurProps } from "./blur/useBoxBlur"; import { useGaussianBlur, GaussianBlurProps } from "./blur/useGaussianBlur"; import { useMotionBlur, MotionBlurProps } from "./blur/useMotionBlur"; import { useCoverTexture, CoverTextureProps } from "./useCoverTexture"; +import { DistortionProps, useDistortion } from "./useDistortion"; import { useFluid, FluidProps } from "./useFluid"; import { useNoise, NoiseProps } from "./useNoise"; import { useRawBlank, RawBlankProps } from "./useRawBlank"; @@ -15,7 +16,8 @@ export type FxTypes = | typeof useRawBlank | typeof useRGBShift | typeof useMotionBlur - | typeof useGaussianBlur; + | typeof useGaussianBlur + | typeof useDistortion; export type FxProps = T extends typeof useBoxBlur @@ -34,6 +36,8 @@ export type FxProps = ? MotionBlurProps : T extends typeof useGaussianBlur ? MotionBlurProps + : T extends typeof useDistortion + ? DistortionProps : never; export * from "./blur/useBoxBlur"; @@ -44,3 +48,4 @@ export * from "./useRawBlank"; export * from "./useRGBShift"; export * from "./blur/useMotionBlur"; export * from "./blur/useGaussianBlur"; +export * from "./useDistortion"; diff --git a/packages/use-shader-fx/src/hooks/useDistortion/index.tsx b/packages/use-shader-fx/src/hooks/useDistortion/index.tsx new file mode 100644 index 00000000..75b5c210 --- /dev/null +++ b/packages/use-shader-fx/src/hooks/useDistortion/index.tsx @@ -0,0 +1,71 @@ +import { useCallback } from "react"; +import { HooksProps, HooksReturn } from "../types"; +import { getDpr } from "../../utils/getDpr"; +import { RootState } from "../types"; +import { DistortionMaterial, DistortionValues } from "../../materials"; +import { useFxScene } from "../../utils/useFxScene"; +import { useSingleFBO } from "../../utils/useSingleFBO"; + +type DistortionValuesAndConfig = DistortionValues; +export type DistortionProps = HooksProps & DistortionValuesAndConfig; + +/** + * @link https://github.com/FunTechInc/use-shader-fx?tab=readme-ov-file#usage + */ +export const useDistortion = ({ + size, + dpr, + fboAutoSetSize, + renderTargetOptions, + materialParameters, + ...uniformValues +}: DistortionProps): HooksReturn => { + const _dpr = getDpr(dpr); + + const { scene, material, camera } = useFxScene({ + size, + dpr: _dpr.shader, + material: DistortionMaterial, + uniformValues, + materialParameters, + }); + + const [renderTarget, updateRenderTarget] = useSingleFBO({ + scene, + camera, + size, + dpr: _dpr.fbo, + fboAutoSetSize, + ...renderTargetOptions, + }); + + const setValues = useCallback( + (newValues: DistortionValuesAndConfig) => { + const { ...rest } = newValues; + material.setUniformValues(rest); + }, + [material] + ); + + const render = useCallback( + (rootState: RootState, newValues?: DistortionValuesAndConfig) => { + const { gl } = rootState; + newValues && setValues(newValues); + material.uniforms.time.value = rootState.clock.getElapsedTime(); + material.updateBasicFx(); + updateRenderTarget({ gl }); + return renderTarget.texture; + }, + [setValues, updateRenderTarget, material, renderTarget] + ); + + return { + render, + setValues, + texture: renderTarget.texture, + material, + scene, + camera, + renderTarget, + }; +}; diff --git a/packages/use-shader-fx/src/materials/impl/distortion/DistortionMaterial.ts b/packages/use-shader-fx/src/materials/impl/distortion/DistortionMaterial.ts new file mode 100644 index 00000000..cc3ae0e8 --- /dev/null +++ b/packages/use-shader-fx/src/materials/impl/distortion/DistortionMaterial.ts @@ -0,0 +1,52 @@ +import { fragment, vertex } from "./distortion.glsl"; +import { BasicFxMaterial } from "../../core/BasicFxMaterial"; +import { FxMaterialProps } from "../../core/FxMaterial"; +import { BasicFxUniforms, BasicFxValues } from "../../core/BasicFxLib"; +import { NestUniformValues } from "../../../shaders/uniformsUtils"; +import { TexturePipelineSrc } from "../../../misc"; +import * as THREE from 'three'; + +type DistortionUniforms = { + /** */ + src: { value: TexturePipelineSrc }; + /** */ + time: { value: number }; + scale: { value: THREE.Vector2 }; + freq: { value: THREE.Vector2 }; + timeStrength: { value: THREE.Vector2 }; + timeOffset: { value: number }; + powNum: { value: THREE.Vector2 }; +} & BasicFxUniforms; + +export type DistortionValues = NestUniformValues & BasicFxValues; + +export class DistortionMaterial extends BasicFxMaterial { + static get type() { + return "DistortionMaterial"; + } + + uniforms!: DistortionUniforms; + + constructor({ + uniformValues, + materialParameters = {}, + }: FxMaterialProps) { + super({ + vertexShader: vertex, + fragmentShader: fragment, + uniformValues, + materialParameters, + uniforms: { + src: { value: null }, + time: { value: 0 }, + scale: { value: new THREE.Vector2(1,1) }, + freq: { value: new THREE.Vector2(1,1) }, + timeStrength: { value: new THREE.Vector2(1,1) }, + timeOffset: { value: 0 }, + powNum: { value: new THREE.Vector2(1,1) }, + } as DistortionUniforms, + }); + + this.type = DistortionMaterial.type; + } +} diff --git a/packages/use-shader-fx/src/materials/impl/distortion/distortion.glsl.ts b/packages/use-shader-fx/src/materials/impl/distortion/distortion.glsl.ts new file mode 100644 index 00000000..3007fbc8 --- /dev/null +++ b/packages/use-shader-fx/src/materials/impl/distortion/distortion.glsl.ts @@ -0,0 +1,194 @@ +import { ShaderLib } from "../../../shaders/ShaderLib"; + +export const vertex = ` + void main() { + ${ShaderLib.plane_vertex} + } +`; + +export const fragment = ` + + uniform sampler2D src; + + uniform float time; + uniform vec2 scale; + uniform vec2 freq; + uniform vec2 timeStrength; + uniform float timeOffset; + uniform vec2 powNum; + + + // noise functions + // + // Description : Array and textureless GLSL 2D/3D/4D simplex + // noise functions. + // Author : Ian McEwan, Ashima Arts. + // Maintainer : ijm + // Lastmod : 20110822 (ijm) + // License : Copyright (C) 2011 Ashima Arts. All rights reserved. + // Distributed under the MIT License. See LICENSE file. + // https://github.com/ashima/webgl-noise + // + + vec3 mod289(vec3 x) { + return x - floor(x * (1.0 / 289.0)) * 289.0; + } + vec4 mod289(vec4 x) { + return x - floor(x * (1.0 / 289.0)) * 289.0; + } + vec4 permute(vec4 x) { + return mod289(((x*34.0)+1.0)*x); + } + + vec4 taylorInvSqrt(vec4 r) + { + return 1.79284291400159 - 0.85373472095314 * r; + } + + float snoise(vec3 v) { + const vec2 C = vec2(1.0/6.0, 1.0/3.0) ; + const vec4 D = vec4(0.0, 0.5, 1.0, 2.0); + + // First corner + vec3 i = floor(v + dot(v, C.yyy) ); + vec3 x0 = v - i + dot(i, C.xxx) ; + + // Other corners + vec3 g = step(x0.yzx, x0.xyz); + vec3 l = 1.0 - g; + vec3 i1 = min( g.xyz, l.zxy ); + vec3 i2 = max( g.xyz, l.zxy ); + + // x0 = x0 - 0.0 + 0.0 * C.xxx; + // x1 = x0 - i1 + 1.0 * C.xxx; + // x2 = x0 - i2 + 2.0 * C.xxx; + // x3 = x0 - 1.0 + 3.0 * C.xxx; + vec3 x1 = x0 - i1 + C.xxx; + vec3 x2 = x0 - i2 + C.yyy; // 2.0*C.x = 1/3 = C.y + vec3 x3 = x0 - D.yyy; // -1.0+3.0*C.x = -0.5 = -D.y + + // Permutations + i = mod289(i); + vec4 p = permute( permute( permute( + i.z + vec4(0.0, i1.z, i2.z, 1.0 )) + + i.y + vec4(0.0, i1.y, i2.y, 1.0 )) + + i.x + vec4(0.0, i1.x, i2.x, 1.0 )); + + // Gradients: 7x7 points over a square, mapped onto an octahedron. + // The ring size 17*17 = 289 is close to a multiple of 49 (49*6 = 294) + float n_ = 0.142857142857; // 1.0/7.0 + vec3 ns = n_ * D.wyz - D.xzx; + + vec4 j = p - 49.0 * floor(p * ns.z * ns.z); // mod(p,7*7) + + vec4 x_ = floor(j * ns.z); + vec4 y_ = floor(j - 7.0 * x_ ); // mod(j,N) + + vec4 x = x_ *ns.x + ns.yyyy; + vec4 y = y_ *ns.x + ns.yyyy; + vec4 h = 1.0 - abs(x) - abs(y); + + vec4 b0 = vec4( x.xy, y.xy ); + vec4 b1 = vec4( x.zw, y.zw ); + + //vec4 s0 = vec4(lessThan(b0,0.0))*2.0 - 1.0; + //vec4 s1 = vec4(lessThan(b1,0.0))*2.0 - 1.0; + vec4 s0 = floor(b0)*2.0 + 1.0; + vec4 s1 = floor(b1)*2.0 + 1.0; + vec4 sh = -step(h, vec4(0.0)); + + vec4 a0 = b0.xzyw + s0.xzyw*sh.xxyy ; + vec4 a1 = b1.xzyw + s1.xzyw*sh.zzww ; + + vec3 p0 = vec3(a0.xy,h.x); + vec3 p1 = vec3(a0.zw,h.y); + vec3 p2 = vec3(a1.xy,h.z); + vec3 p3 = vec3(a1.zw,h.w); + + //Normalise gradients + vec4 norm = taylorInvSqrt(vec4(dot(p0,p0), dot(p1,p1), dot(p2, p2), dot(p3,p3))); + p0 *= norm.x; + p1 *= norm.y; + p2 *= norm.z; + p3 *= norm.w; + + // Mix final noise value + vec4 m = max(0.6 - vec4(dot(x0,x0), dot(x1,x1), dot(x2,x2), dot(x3,x3)), 0.0); + m = m * m; + return 42.0 * dot( m*m, vec4( dot(p0,x0), dot(p1,x1), + dot(p2,x2), dot(p3,x3) ) ); + } + // end noise functions + + void main() { + + // TODO add uniform + // vec2 srcScale = vec2(1.0,1.0); + // + + float _time = time + timeOffset; + vec2 _scale = scale * 0.01; + + // vec2 dUv = vUv; + // convert to -1 to 1 space + // vec2 dUv = vUv * 2.0 - 1.0; + + vec2 shiftUv = vUv; + + shiftUv.x = + (snoise( + vec3( + vUv.y * freq.y, + vUv.x + time * timeStrength.x, + _time * timeStrength.x + 20. + ) + ) * 2.0 - 1.0) * _scale.x; + + shiftUv.y = + (snoise( + vec3( + vUv.x * freq.x, + vUv.y + time * timeStrength.y + 10., + _time * timeStrength.y + ) + ) * 2.0 - 1.0) * _scale.y; + + // 符号を保ったままpowを計算 + shiftUv = sign(shiftUv) * pow(abs(shiftUv), powNum); + + vec2 dUv = vUv + shiftUv; + vec4 outColor = texture2D(src, dUv); + + + // ピクセルをずらす + float n = snoise(vec3( + vUv.x * 40. , + vUv.y * .3, + ceil(time * 20.) * 0.1 + )); + float n2 = snoise(vec3( + time, + vUv.x * 40. , + vUv.y * .3 + )) * 0.3 + 0.7; + vec2 d2Uv = dUv; + if(n > n2) { + // ずらし先のピクセルを取得 + d2Uv.x += (snoise(vec3( + dUv.x * .1, + dUv.y, + ceil(time * 3.) * 0.1 + n + )) * 2.0 - 1.0) * 0.04; + d2Uv.y += (snoise(vec3( + dUv.x, + dUv.y * .2 + n * 10., + ceil(time * 1.) * 0.1 + )) * 2.0 - 1.0) * (0.04 * n + 0.01); + } + outColor = texture2D(src, d2Uv); + + + gl_FragColor = outColor; + // gl_FragColor = vec4(vec3(vUv.x * 2.0 - 1.0),1.0); + } +`; diff --git a/packages/use-shader-fx/src/materials/index.js b/packages/use-shader-fx/src/materials/index.js index e33cb1aa..8a5d5ce0 100644 --- a/packages/use-shader-fx/src/materials/index.js +++ b/packages/use-shader-fx/src/materials/index.js @@ -9,3 +9,4 @@ export * from "./impl/blur/gaussianBlur/GaussianBlurMaterial"; export * from "./impl/blur/motionBlur/MotionBlurMaterial"; export * from "./impl/cover/CoverTextureMaterial"; export * from "./impl/rgbShift/RGBShiftMaterial"; +export * from "./impl/distortion/DistortionMaterial"; diff --git a/public/dummy3.png b/public/dummy3.png new file mode 100644 index 0000000000000000000000000000000000000000..ef4e9fe693dc502a1ae60fc45ac8346307ce63bf GIT binary patch literal 11850 zcmeHN{ZCV87=4Sib`AtG7u{e`WSd*UP+=&or4$AfvP`CK1B@*wqs%eB?AThMABwXq zYGEM?I;C#=VLGw3HiJ=GN@OcPl);#hE0*!GCKPC)U};Nff!#~{H#97H-=yi&H#avo z=bm$(d(YEvKRm(++WzWx06^qkrXz&qnvX(=CZahA~(iSaia{V3&5&DHWZ zXV~*iWMh`-5$XCjdB;D`T2B&{G-n?D(ft!YtdP15JrBAX7vwl^^(pa!w+Pu260lLx z>*?slVJj*i%3EB32SEtHW`h7zjcCWY5HCkl@u}W|7)tbVo0LYvZ)}M|;6V@q$N~T% zfDoXb3B3S909gQqfIUA!FMtq07C<3DFTh?Ep%*|1HZKbjH6~l9AyHMu{QCP#NHNaT zVd5AA3$t@Hu@kvBgMTO;v|U_WHBGh(jYB*k&O`NY?9teO13hoFnJHs-my68)!f;Sx zsbV_ae02$XM`S~vbPKp`nKtz%k;4Ki2xzw0lOCgwbHu&$w_|C=%?_Bfgs(72;P(8q z={+zZ_x%1ACQ0DO+)3OaGjnNDov?2xPtLiIe5{%8HO#f^x%}awTW1DOo)PjQPROG# z7vX=zc8C2y_CFT zc2J|H>8qJS%gi*V^5SaMl9^JMWWAd-$74DWyV$17e~ov)4Oyo=KXI!_BM~r_k}o4Y zO?B48kE`=%#wytHfxXMF$-No=4(^^lnft1y24yOnDjj@Za*wj2-lva~ea1xY@_9=N zR9*?!(;ox$^$gej#53%Q5c@_A0r^ifAHck)rjyQLPpR?(j z@3kr>`z3<07JgZO?KP_&BxjTG6AQBHTp_>my6cfLMvs!2yz^#vxnr#5l;(~?+uh%- zogk{UqUf$!Ug4CoHlMJ}6P(`Zm8pLMSkz=H&UP3|)g?@1gOxT{c+R`=Vx^2Cu6f4M zSmahE%kPW$^KlU>@wTk+z7#l zji#P0W?r?U8-I*fmV0OeVW!iXZf+Uys11=uvKLJeKKTGPFG3d_!$1fi3pSe&maPs8 z9g`=$QEMkPXJ91&`}g>UPX%edacWOJ$v1@xP4UfDqtE+hRvCETfb}xb=S{mqedAbo zB8U-2D99ry5sU}WMxaAtJP^Syg24bgEqsXZh6S)e!Ul=?0c?=4L1H|B4HCXVVmtu< c_Xhd;azXv^pHpYCzkY+P^do7q)PnQ>0RnyY@Bjb+ literal 0 HcmV?d00001 From 6e6d7e744d7685882122422882c2a316661576df Mon Sep 17 00:00:00 2001 From: roku-ft Date: Thu, 21 Nov 2024 20:24:37 +0900 Subject: [PATCH 55/60] fix --- .../impl/distortion/DistortionMaterial.ts | 12 ++- .../impl/distortion/distortion.glsl.ts | 81 ++++++++++--------- .../materials/impl/rgbShift/rgbShift.glsl.ts | 6 +- 3 files changed, 55 insertions(+), 44 deletions(-) diff --git a/packages/use-shader-fx/src/materials/impl/distortion/DistortionMaterial.ts b/packages/use-shader-fx/src/materials/impl/distortion/DistortionMaterial.ts index cc3ae0e8..79ff1e22 100644 --- a/packages/use-shader-fx/src/materials/impl/distortion/DistortionMaterial.ts +++ b/packages/use-shader-fx/src/materials/impl/distortion/DistortionMaterial.ts @@ -15,7 +15,11 @@ type DistortionUniforms = { freq: { value: THREE.Vector2 }; timeStrength: { value: THREE.Vector2 }; timeOffset: { value: number }; - powNum: { value: THREE.Vector2 }; + powNum: { value: THREE.Vector2 }; + glitchSpeed: { value: number }; + glitchPower: { value: number }; + glitchThreshold: { value: number }; + glitchFreq: { value: THREE.Vector2 }; } & BasicFxUniforms; export type DistortionValues = NestUniformValues & BasicFxValues; @@ -43,7 +47,11 @@ export class DistortionMaterial extends BasicFxMaterial { freq: { value: new THREE.Vector2(1,1) }, timeStrength: { value: new THREE.Vector2(1,1) }, timeOffset: { value: 0 }, - powNum: { value: new THREE.Vector2(1,1) }, + powNum: { value: new THREE.Vector2(1,1) }, + glitchSpeed: { value: 1 }, + glitchPower: { value: 1.0 }, + glitchFreq: { value: new THREE.Vector2(100,10) }, + glitchThreshold: { value: 0.2 }, } as DistortionUniforms, }); diff --git a/packages/use-shader-fx/src/materials/impl/distortion/distortion.glsl.ts b/packages/use-shader-fx/src/materials/impl/distortion/distortion.glsl.ts index 3007fbc8..8e467d88 100644 --- a/packages/use-shader-fx/src/materials/impl/distortion/distortion.glsl.ts +++ b/packages/use-shader-fx/src/materials/impl/distortion/distortion.glsl.ts @@ -17,6 +17,12 @@ export const fragment = ` uniform float timeOffset; uniform vec2 powNum; + + uniform float glitchSpeed; + uniform float glitchPower; + uniform vec2 glitchFreq; + uniform float glitchThreshold; + // noise functions // @@ -122,36 +128,28 @@ export const fragment = ` void main() { - // TODO add uniform - // vec2 srcScale = vec2(1.0,1.0); - // - float _time = time + timeOffset; vec2 _scale = scale * 0.01; - // vec2 dUv = vUv; - // convert to -1 to 1 space - // vec2 dUv = vUv * 2.0 - 1.0; - vec2 shiftUv = vUv; shiftUv.x = - (snoise( + snoise( vec3( vUv.y * freq.y, vUv.x + time * timeStrength.x, _time * timeStrength.x + 20. ) - ) * 2.0 - 1.0) * _scale.x; + ) * _scale.x; shiftUv.y = - (snoise( + snoise( vec3( vUv.x * freq.x, vUv.y + time * timeStrength.y + 10., _time * timeStrength.y ) - ) * 2.0 - 1.0) * _scale.y; + ) * _scale.y; // 符号を保ったままpowを計算 shiftUv = sign(shiftUv) * pow(abs(shiftUv), powNum); @@ -160,35 +158,40 @@ export const fragment = ` vec4 outColor = texture2D(src, dUv); - // ピクセルをずらす - float n = snoise(vec3( - vUv.x * 40. , - vUv.y * .3, - ceil(time * 20.) * 0.1 - )); - float n2 = snoise(vec3( - time, - vUv.x * 40. , - vUv.y * .3 - )) * 0.3 + 0.7; - vec2 d2Uv = dUv; - if(n > n2) { - // ずらし先のピクセルを取得 - d2Uv.x += (snoise(vec3( - dUv.x * .1, - dUv.y, - ceil(time * 3.) * 0.1 + n - )) * 2.0 - 1.0) * 0.04; - d2Uv.y += (snoise(vec3( - dUv.x, - dUv.y * .2 + n * 10., - ceil(time * 1.) * 0.1 - )) * 2.0 - 1.0) * (0.04 * n + 0.01); + if(glitchPower > 0.0) { + + float cTime1 = ceil(time * 10. * glitchSpeed); + float cTime2 = ceil(time * 7. * glitchSpeed) + 13.; + + float gnx = (snoise(vec3( + floor(vUv.x * glitchFreq.x) / glitchFreq.x, + cTime2, + vUv.x * glitchFreq.x + )) + 1.0) * 0.5; + + float gny = (snoise(vec3( + floor(vUv.y * glitchFreq.y) / glitchFreq.y, + cTime2, + floor(vUv.y * glitchFreq.y) + )) + 1.0) * 0.5; + + float gn = (snoise(vec3( + cTime1, + floor(vUv.x * glitchFreq.x) / glitchFreq.x * gnx, + floor(vUv.y * glitchFreq.y) / glitchFreq.y * gny + )) + 1.0) * 0.5; + + vec2 d2Uv = dUv; + if(gn < glitchThreshold) { + d2Uv += vec2( + snoise(vec3(dUv.x + cTime2, vUv.y, cTime2 + gny)), + snoise(vec3(dUv.y + cTime1, vUv.x, cTime1 + gnx)) + ) * glitchPower * vec2(0.01); + outColor = texture2D(src, d2Uv); + } } - outColor = texture2D(src, d2Uv); - gl_FragColor = outColor; - // gl_FragColor = vec4(vec3(vUv.x * 2.0 - 1.0),1.0); + gl_FragColor = outColor; } `; diff --git a/packages/use-shader-fx/src/materials/impl/rgbShift/rgbShift.glsl.ts b/packages/use-shader-fx/src/materials/impl/rgbShift/rgbShift.glsl.ts index 2af358c0..337e157e 100644 --- a/packages/use-shader-fx/src/materials/impl/rgbShift/rgbShift.glsl.ts +++ b/packages/use-shader-fx/src/materials/impl/rgbShift/rgbShift.glsl.ts @@ -25,7 +25,7 @@ export const fragment = ` float r = 0.0; if(isUseShiftPowerSrcR){ - vec2 shiftR = (texture2D(shiftPowerSrcR, vUv).rg * 2.0 - 1.0) * shiftScale; + vec2 shiftR = (texture2D(shiftPowerSrcR, vUv).rg * 4.0 - 1.0) * shiftScale; r = texture2D(src, vUv + shiftR).r; } else { r = texture2D(src, vUv + shift).r; @@ -33,7 +33,7 @@ export const fragment = ` float g = 0.0; if(isUseShiftPowerSrcG){ - vec2 shiftG = (texture2D(shiftPowerSrcG, vUv).rg * 2.0 - 1.0) * shiftScale; + vec2 shiftG = (texture2D(shiftPowerSrcG, vUv).rg * 4.0 - 1.0) * shiftScale; g = texture2D(src, vUv + shiftG).g; } else { g = texture2D(src, vUv + shift).g; @@ -41,7 +41,7 @@ export const fragment = ` float b = 0.0; if(isUseShiftPowerSrcB){ - vec2 shiftB = (texture2D(shiftPowerSrcB, vUv).rg * 2.0 - 1.0) * shiftScale; + vec2 shiftB = (texture2D(shiftPowerSrcB, vUv).rg * 4.0 - 1.0) * shiftScale; b = texture2D(src, vUv + shiftB).b; } else { b = texture2D(src, vUv + shift).b; From f19b4958ab3e5416aa2044dbf0626a1b537687b7 Mon Sep 17 00:00:00 2001 From: roku-ft Date: Tue, 26 Nov 2024 19:24:03 +0900 Subject: [PATCH 56/60] add joinShaderPrefix function and refactor shader prefix handling --- .../src/materials/core/BasicFxLib.ts | 20 ++++++++----------- .../src/shaders/mergeShaderLib.ts | 14 +++++++++++-- 2 files changed, 20 insertions(+), 14 deletions(-) diff --git a/packages/use-shader-fx/src/materials/core/BasicFxLib.ts b/packages/use-shader-fx/src/materials/core/BasicFxLib.ts index a5baf6a0..cc02b71a 100644 --- a/packages/use-shader-fx/src/materials/core/BasicFxLib.ts +++ b/packages/use-shader-fx/src/materials/core/BasicFxLib.ts @@ -6,6 +6,10 @@ import { flattenUniformValues, } from "../../shaders/uniformsUtils"; +import { + joinShaderPrefix +} from '../../shaders/mergeShaderLib'; + /*=============================================== basic fxを追加するときはこことShaderChunk,Libを編集する ===============================================*/ @@ -101,10 +105,6 @@ function handleUpdateBasicFx( }; } -function filterEmptyLine(string: string) { - return string !== ""; -} - const BASICFX_SHADER_PREFIX = { mixSrc: "#define USF_USE_MIXSRC", mixDst: "#define USF_USE_MIXDST", @@ -115,20 +115,16 @@ function handleUpdateBasicFxPrefix(basicFxFlag: BasicFxFlag): { prefixFragment: string; } { const { mixSrc, mixDst } = basicFxFlag; - const prefixVertex = [ + const prefixVertex = joinShaderPrefix([ mixSrc ? BASICFX_SHADER_PREFIX.mixSrc : "", mixDst ? BASICFX_SHADER_PREFIX.mixDst : "", "\n", - ] - .filter(filterEmptyLine) - .join("\n"); - const prefixFragment = [ + ]); + const prefixFragment = joinShaderPrefix([ mixSrc ? BASICFX_SHADER_PREFIX.mixSrc : "", mixDst ? BASICFX_SHADER_PREFIX.mixDst : "", "\n", - ] - .filter(filterEmptyLine) - .join("\n"); + ]); return { prefixVertex, diff --git a/packages/use-shader-fx/src/shaders/mergeShaderLib.ts b/packages/use-shader-fx/src/shaders/mergeShaderLib.ts index 43ad89a0..a6095f03 100644 --- a/packages/use-shader-fx/src/shaders/mergeShaderLib.ts +++ b/packages/use-shader-fx/src/shaders/mergeShaderLib.ts @@ -4,7 +4,7 @@ import { ShaderLib } from "./ShaderLib"; * 共通でパースするShaderの共有部分を解決する * basicFx_fragment_begin, basicFx_fragment_endは含まない。これらは各FXでカスタマイズする必要があるため。 */ -function mergeShaderLib( +export function mergeShaderLib( vertexShader: string | undefined, fragmentShader: string | undefined, type: "default" | "basicFx" @@ -39,4 +39,14 @@ function mergeShaderLib( return [vertex, fragment]; } -export { mergeShaderLib }; + +/** + * Shaderのprefixを結合する + */ +export function joinShaderPrefix(prefix: string[]):string { + return prefix + .filter((string) => { + string !== ""; + }) + .join("\n"); +} From ffe11b5d11703727fc138dcb80ab1724d44dd6cd Mon Sep 17 00:00:00 2001 From: roku-ft Date: Fri, 29 Nov 2024 16:51:46 +0900 Subject: [PATCH 57/60] refactor mergeShaderLib to handle multiple types --- .../src/shaders/mergeShaderLib.ts | 27 +++++++++++-------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/packages/use-shader-fx/src/shaders/mergeShaderLib.ts b/packages/use-shader-fx/src/shaders/mergeShaderLib.ts index a6095f03..24e3e825 100644 --- a/packages/use-shader-fx/src/shaders/mergeShaderLib.ts +++ b/packages/use-shader-fx/src/shaders/mergeShaderLib.ts @@ -12,17 +12,22 @@ export function mergeShaderLib( let vertex, fragment = undefined; - const isDefault = type === "default"; - - const vertexPars = isDefault - ? ShaderLib.default_pars_vertex - : ShaderLib.basicFx_pars_vertex; - const vertexMain = isDefault - ? ShaderLib.default_vertex - : ShaderLib.basicFx_vertex; - const fragmentPars = isDefault - ? ShaderLib.default_pars_fragment - : ShaderLib.basicFx_pars_fragment; + const ShaderLibs = { + default: { + vertexPars: ShaderLib.default_pars_vertex, + vertexMain: ShaderLib.default_vertex, + fragmentPars: ShaderLib.default_pars_fragment, + }, + basicFx: { + vertexPars: ShaderLib.basicFx_pars_vertex, + vertexMain: ShaderLib.basicFx_vertex, + fragmentPars: ShaderLib.basicFx_pars_fragment, + } + }; + + const vertexPars = ShaderLibs[type].vertexPars; + const vertexMain = ShaderLibs[type].vertexMain; + const fragmentPars = ShaderLibs[type].fragmentPars; if (vertexShader) { vertex = vertexPars + `\n` + vertexShader; From d38f36d8d53e9693b81f245f4c05e7b6f6f92e4c Mon Sep 17 00:00:00 2001 From: takuma-hmng8 Date: Fri, 29 Nov 2024 18:54:28 +0900 Subject: [PATCH 58/60] add:idea of mask in BasicFx --- app/v2_mask/Playground.tsx | 95 +++++++++++++++++++++++++++++++++++++ app/v2_mask/page.tsx | 34 +++++++++++++ public/mask.jpg | Bin 0 -> 95490 bytes public/mask.png | Bin 0 -> 164570 bytes 4 files changed, 129 insertions(+) create mode 100644 app/v2_mask/Playground.tsx create mode 100644 app/v2_mask/page.tsx create mode 100644 public/mask.jpg create mode 100644 public/mask.png diff --git a/app/v2_mask/Playground.tsx b/app/v2_mask/Playground.tsx new file mode 100644 index 00000000..61ea315b --- /dev/null +++ b/app/v2_mask/Playground.tsx @@ -0,0 +1,95 @@ +"use client"; + +import * as THREE from "three"; +import { useEffect, useRef, useState } from "react"; +import { useFrame, useThree, extend, createPortal } from "@react-three/fiber"; +import { + createFxMaterialImpl, + FxMaterialImplValues, + useFluid, +} from "@/packages/use-shader-fx/src"; +import { useTexture } from "@react-three/drei"; + +const FxMaterialImpl = createFxMaterialImpl({ + uniforms: { + mask: { value: null }, + }, + fragmentShader: ` + uniform sampler2D src; + uniform sampler2D mask; + void main() { + vec2 vel = texture2D(src, vUv).xy; + float len = length(vel); + vel = vel * 0.5 + 0.5; + + vec3 color = vec3(vel.x, vel.y, 1.0); + color = mix(vec3(1.0), color, len); + + // fluid カラー + vec4 fluidColor = vec4(color, 1.0); + + // マスク + vec4 maskColor = texture2D(mask, vUv); + + // チャンネル α + vec4 outPut = fluidColor * maskColor.a; + + // チャンネル r + // vec4 outPut = fluidColor * maskColor.r; + + // チャンネル g + // vec4 outPut = fluidColor * maskColor.g; + + // チャンネル b + // vec4 outPut = fluidColor * maskColor.b; + + + gl_FragColor = outPut; + } +`, +}); + +extend({ MaskMaterialImpl: FxMaterialImpl }); + +/*=============================================== +Idea of Mask in BasicFx +- figmaみたいにmaskをかけることができる +- チャンネルを選択できる[ α | r | g | b ] +===============================================*/ + +export const Playground = () => { + const { size, viewport, camera } = useThree(); + + const [colorMask, alphaMask] = useTexture(["/mask.jpg", "/mask.png"]); + + const fluid = useFluid({ + size, + dpr: 0.5, + }); + + useFrame((state) => { + fluid.render(state); + }); + + return ( + + + + + ); +}; + +declare global { + namespace JSX { + interface IntrinsicElements { + maskMaterialImpl: { + mask: THREE.Texture | null; + } & FxMaterialImplValues & + JSX.IntrinsicElements["shaderMaterial"]; + } + } +} diff --git a/app/v2_mask/page.tsx b/app/v2_mask/page.tsx new file mode 100644 index 00000000..0fad2258 --- /dev/null +++ b/app/v2_mask/page.tsx @@ -0,0 +1,34 @@ +import { ShaderFx } from "../ShaderFx"; +import { Playground } from "./Playground"; +import Image from "next/image"; + +export default function Page() { + return ( +
    +
    + くぁwせdrftgyふじこlpくぁwせdrftgyふじこlpくぁwせdrftgyふじこlpくぁwせdrftgyふじこlpくぁwせdrftgyふじこlpくぁwせdrftgyふじこlpくぁwせdrftgyふじこlpくぁwせdrftgyふじこlpくぁwせdrftgyふじこlpくぁwせdrftgyふじこlp + くぁwせdrftgyふじこlpくぁwせdrftgyふじこlpくぁwせdrftgyふじこlpくぁwせdrftgyふじこlpくぁwせdrftgyふじこlpくぁwせdrftgyふじこlpくぁwせdrftgyふじこlpくぁwせdrftgyふじこlpくぁwせdrftgyふじこlpくぁwせdrftgyふじこlp + くぁwせdrftgyふじこlpくぁwせdrftgyふじこlpくぁwせdrftgyふじこlpくぁwせdrftgyふじこlpくぁwせdrftgyふじこlpくぁwせdrftgyふじこlpくぁwせdrftgyふじこlpくぁwせdrftgyふじこlpくぁwせdrftgyふじこlpくぁwせdrftgyふじこlp + くぁwせdrftgyふじこlpくぁwせdrftgyふじこlpくぁwせdrftgyふじこlpくぁwせdrftgyふじこlpくぁwせdrftgyふじこlpくぁwせdrftgyふじこlpくぁwせdrftgyふじこlpくぁwせdrftgyふじこlpくぁwせdrftgyふじこlpくぁwせdrftgyふじこlp + くぁwせdrftgyふじこlpくぁwせdrftgyふじこlpくぁwせdrftgyふじこlpくぁwせdrftgyふじこlpくぁwせdrftgyふじこlpくぁwせdrftgyふじこlpくぁwせdrftgyふじこlpくぁwせdrftgyふじこlpくぁwせdrftgyふじこlpくぁwせdrftgyふじこlp + くぁwせdrftgyふじこlpくぁwせdrftgyふじこlpくぁwせdrftgyふじこlpくぁwせdrftgyふじこlpくぁwせdrftgyふじこlpくぁwせdrftgyふじこlpくぁwせdrftgyふじこlpくぁwせdrftgyふじこlpくぁwせdrftgyふじこlpくぁwせdrftgyふじこlp +
    + + + +
    + ); +} diff --git a/public/mask.jpg b/public/mask.jpg new file mode 100644 index 0000000000000000000000000000000000000000..b6d1a22dd4e597965ef38dd5205026fcff8496f9 GIT binary patch literal 95490 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 OKa2H$|6+aV`~LvuN(!t1 literal 0 HcmV?d00001 diff --git a/public/mask.png b/public/mask.png new file mode 100644 index 0000000000000000000000000000000000000000..86573726369cb23994f3e544cfbd536230d1b8c8 GIT binary patch literal 164570 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

    $La^A@4UqQw=-;yJF@K__GCG%9Kv=4uFm?u+!)g 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 literal 0 HcmV?d00001 From 85ad6ca3215333a55b34c7566d57e9b798afe20b Mon Sep 17 00:00:00 2001 From: roku-ft Date: Fri, 29 Nov 2024 19:59:23 +0900 Subject: [PATCH 59/60] fix --- packages/use-shader-fx/src/shaders/mergeShaderLib.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/use-shader-fx/src/shaders/mergeShaderLib.ts b/packages/use-shader-fx/src/shaders/mergeShaderLib.ts index 24e3e825..9039d4b6 100644 --- a/packages/use-shader-fx/src/shaders/mergeShaderLib.ts +++ b/packages/use-shader-fx/src/shaders/mergeShaderLib.ts @@ -51,7 +51,7 @@ export function mergeShaderLib( export function joinShaderPrefix(prefix: string[]):string { return prefix .filter((string) => { - string !== ""; + return string !== ""; }) .join("\n"); } From f3db04d8614e410dc48031d859c421c9a1ed76b5 Mon Sep 17 00:00:00 2001 From: roku-ft Date: Mon, 2 Dec 2024 14:02:48 +0900 Subject: [PATCH 60/60] fix --- app/ShaderFx.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/ShaderFx.tsx b/app/ShaderFx.tsx index 5b8fe13a..3ace66a4 100644 --- a/app/ShaderFx.tsx +++ b/app/ShaderFx.tsx @@ -41,7 +41,8 @@ export const ShaderFx = ({ eventPrefix={eventSource ? "client" : "offset"} dpr={dpr} gl={{ preserveDrawingBuffer: preserveDrawingBuffer }} - shadows={shadows}> + shadows={shadows} + linear> { if (preserveDrawingBuffer) {

QYbuD3++er^1I%d82yb5o zr?KVUZCrDp9;$&Be#@&k!AWn7E=YCQ!kKOsKJj3vOL8^P{f;F0s6e-m!36W^H!C5H zJ{H1*iS}#N;R(aH$s*zr#67R)LTI_ynamvjRe!`Bvq5dhuPJ* zng~Z50aq&>Ob}g!w{iPp8Gk*4eO$s}n3Q=&8-6({0nGxU%e+f4yfk|mT77=W^iW)l z>>z#>82~*Bp>r=}O-glVw|)~-1A^qfaC;VPZcCA8-yXGfzv7galh|MjmmaCZ!u)&t z4L*S~dqw#4P;wJt^&aYHP65Kc6N%L&_3ZbP_S3I}?>Pvd`b@*+Yiig_D_u+=t9UcwsnU^2rgLvY(*q15VA3+po7PTy(WvQbqC5aLxXX&c=QLhtc46tEK~IX zWLcTQ`$XZ^U*hK##j+PgcCtB_A{hIBzRCHLn8MWE?enSElJ~e-DNdiNed; zBTpdhFS2svy$wb?Ul{);0LGmPqmgS~udzW=jP(pgiFrLHo25~yc^4l6qdcmFpbRsg z;4Z)V)uhU@?`vI#OB8;db1(} zVoFVq7MKi)gZ|~4&HXC_37kBGW|pfc%dmbGElEIRFY*W*Ck~tX6*?YCN^9hgR>My) z0K755Ikk$^dkLCv6kPt({K$|YAlPENk7YdJkGabrn(JzCye(5UnhnoYDcHWqP!^ReG({6j9o-b0wYMQD1K*}MAyjmL;rm^k)6Ey z&)pt*MzCLuhvMR}`YvXyhc{;IpWm8{!@&v$xnA@4L%Qu2+-yGQ1#7AfVVq}USOL@f zgA7m~)H|1)A8P5WZtaWrB^F1o3O{9ap+J8t*IcU!HjE+4kk+)^2~Y#JLX2%u{J+jS zbwPP}z98=fYZeHKaxgs>%mBW7Q0w2~L{CB?)%hlso=f(cs}4tvvsvN5*&&LUdn2Bm zG#nvlt;XtXGK4N}`N-M(vmZUr19LuC2Z1C0&JN^y-wsYJUVsa6EBqapF z8<_&g_^mA$fHx)T53CB-Jtz;cRmCk&qYVioZV_c%2Ake-AelImFf{LKa{smX$51Cj z#glP1F3eNDj#{l}4#BalMa-@hF7cNsPb%@GpA_w$!LX+hR}R~XP8BG7f{OFRC-Iuk zH@jbs4Hwjcn%nTVFnZ=|+s*6G{9Bz?H@l40KacX=Onm8G>za7%+Z~5-E55K1mLeFvF(30|+=0^6s zfVYCuFL3cN8Q`=#wILCjMwMGST4@NWdq;#BVJ+3|R*?X+%0}eGm!fOfexu(NK&q-5 z1(hf;ca0!$iJ1ih0FcPm$tXq$nr>Z#hi)@m69&D(x$?W}&caKZ033$aolMN#lh?%M zL1e`s6(xCgePU)3aKx101YIDO=9|^QURw6LTZe;Eh|b<Y5bYtp$;45pIR}!MVN@9VH26;6hf;7G^0~9){Bpc?;R#buG^|wguxyyM!OincA zZF}mGRt8SsE~tTZg>fm~4X;}hKh9I52Y-ylkh^?KS<@+dF8|zLq zqM-mnIur)^JBOFF|9K(Bl49`@!C`nV0tS$JftZcycq*P5Qm!s@gUNwabF@|M);D&M z8O+?OfIeXRZ?FD4n`%;{jPl#TI11N)uYa8nyC*dghk6ikTYy=Y;$f-5YzeV$3ta-> z*#v=I?=nOHvy>VA53mOK=L1zIT7?Y%=1NJR8PyZv-+?(rL2_@!CK4XimJvy$*|0i+ zRJ`v{#5Rcaql4;E8zprZD@?mRN06EObx~Bp^;sK!?$81IlsM1{lcZ5X4-$-(;3-cj zv&cgW^v~pn6hdd9#yfwm=b4i0)`b2&Y=aW;x6TM-C>kAVAEFUsSn|+bT({p)e4>q~ zYNFc<=dtd5972=lCVWiQ{3ktNGCxNSsdg}Pf!33j%f4U&N{@>QWcB)tNN$=d(#0=C zotY$JCU~BaL#q{>)(5Cn8tXdZfDTp-$dCZ0#!XUMTkZE!ggxOyF2(m%eg*&`(1}PJ zQO0J1ZlZiRjG?;22EPOo&JB=25jl0^F)Bqg@WespLVy@*Rutb?4SdK#z^RD7$ri*O zwV%(M>nv|4wv=F&Nv!JF66r(PT|F$ofJnqt_iGky8GH?6!Mg+^>Vny`8O}Ni#{vQ= zoFfiI7~H_V!eJVaAnjvyLlKQTqm>Z1?khj(ofDU^82~mYjO^Y(&Y<}OBiI`Gb!ZPk)h7bjIhXcb#xT`FPTMIV8vPtO4KNpTs9pz(Af2-33X>(8AM5aHB_N6;TK+&Poyp$~|*UIzm4Ogf2{eNrt%7mEXV897V+8 zDZZo5++>@0CV}jn@TvVUVr{k-7tGrTlNge+^{CPWB0d;M`<#L`uX@4AX6FZtv{NyT ziPq6V31Gm*OUiKH0-#K-BTMHBe8W=UAmYO7^1LQG@I*!0D_B?xgEO@q>(x6$J|W1? zrxk!aCD(>O0KQI-I!Kol_~t4o84;pOzp!Hmk|Fk~C=Q2Eggkb3UU*Sf7Ipvuko+>O z+#;Ni5Nae6jSO%G3hofO-e%M=hb~r6)3GGIEYwf>HEg1vxj?ydnI6XYtT8y`~ zUurZHjvSwg^hV_tZYL^xA_hYuZN$poCK*;PJczg$@&7eQc&CJy4~s1n}vR>f*n?6<9_~ z4lso?L!Q$}%!y=pi%Ks&e>~<*?rll?5UX*fWMivXeo7ON%=Ar3eJB>vYaM9pJGyx* zU}R0!lI-=dQ0q=o#jtvT`+F1pE%!>7-mQp)ZnYlP4?sG=vL#3gdkBjjG&C|Gc-b0v z-hb>D2Bf+B`# z6Z!SsT3NH0AyG?WqXUp$o(S@`RxYB3g3d4xN*$jvirxu;FfvEwqw~{yr$`Q$lRy_O z2&n5Havr-lP4T4s7?I@@Bx^cp%KdbnvRSLBjf~da;8w|qYR=7A>xAu)@*;qpi}X* zcArM)1P44u!7d??kU~M@S{ud7|9DWXrWnpUcY-pB7#){~du8rEtuq)Cn^Bg3q10tb zFdDI9^}*Do8bbqd%JkkNO*lwrmN^THeQ4iWN> z8)P|{*vmhuO&@Pv8-8!T45W!zL$D{;URaVuGI8lFs*b3{!JSGw!`0it<3292MH2r` zftnk-H3gC6u2U@>F1mS{+ILN`w$rDBC|?+)Ofe z1POx?209@b?b-8-m`Iqai6PZqw>@O0f}WM0vieJth#ZUal=xEUrCk9f*x}rUElRyC zQ{%qpZ^gm+J=Wp!C9xYq`u;*jFW`>g&fo8_E&KMBprf#@Vd|m-6+(eHFRf`|S_1}? z00}fexpdwNK@4-xu9Bc}zF~7yd-$BcLwWlvXENyYrGy|+Kv?H%SVdP{jyk^vDV5r~ zDDbcE{W8h=_k83?Q(X_n){Fmz<%`$vZcZmO4fc0Ikw$-jK{+e_zABu<@%!AGHcU(E zAH~M3(<~yXsTkUZ0T1=P3W_*=h+62J8f)qz5|R+%r|*w(1JBe88RP$;mTf0p%n6V} z`0EbN@Huro{yplK_8sx)v8bF zt7NWh{c8FbxAPpycKhr42(VaD7bkuZl?9`vO7w(=$!9L<#M#igXK^RI z@c5oHpt&Y-wff$zD7o#pd%Zft$?u@dS{AP3eYYl)me=HaQ zoEOcF9Czhe-d1@xt>-u@Tt#Avc#=+}Ht(M$&3gSfM*7q_CE!)mW!`$8O5ylY^AJH>COF z0Dkldf(%-#5RO?hV)PY`h79fFH+M2h+>6WGlGH^$AaX~jWZub-Un`yil-jzeE51>2w zWzKHBHi|o(ke`E<%p_k@_^9wqZLg?I>Gxi5C6~WM=)zsi93SBt8Hbb3R#XdY0x2`_ z;n5~S_Qx_f%qODrF!c{_8h8MlQ_%n-&8@A!&jKj+)!ls91HrFNQ6Xj0`8t4%_GV38yMX( zA1AL^nK7fEOE4B@R2FnttSt*!?C~8Ud=-p+G2f+?F#lbEl#82*9A%y_uhuiG({?g%BPW@FilOI$76e8k zdRfv+Y17rKgi4ZG*XGdAqQ+J+@HKQWX@qmL8oT3Y0is~ce<{v)0VNJ0Gk2t_+i^YO z3I|!R&cqv1vhzC3t}S>V8UORJ^$q1?D_dB%e?(I+NCskH#wFKVOkOI^L2%BbB}r;Y z2^zjk@GmH#^SPqd+;sL(P(#hA@#d9bMNRDpjX=W$M=7pJ`2PE6SU z-XwT)oe*s7Wp~=KIo~C#7UgnC24n+ci6DG#|4$vNB3-ZxMqg!a)uK)H&=Zi%KXykn zE~iFSf%XZwTd}u#G)L3~IcGj$OGkgam$BE66tz(xHA_Ic(56yEBNNo5q|9`hFzk8+ zzyW@CKNc>ue1``BWO?(deFfSaU}H#srW1iFx-CJ8Df%PW#DH{)Lt9NVsO#bZ=B@B+mzP_PeTwiQGGWT$*t-vBnX7h}!1o zW)JoN^YhNAJbM=D0KBbly)h3lo-rR3zBwXdPssp2;Z^wlKjIQD0m7&k*mDGhJ7sqH z-G6&*0T=iTMB(lnIApNI_un@g(;vjrgw(;T(9aP8D`TJa!wyi<3}dN5M}7igUsg> zx#pMVHKtR4&LP`zH|dVT)-eRNSF8pQ+pVIC2wJ{-b^^`fKJeNrl9(^Xn<4@Xp=OZu zNx@-sLl@3zim-)d^5wNZ+uuBM>+`y_BRlnD?3(KD#{xtw)%?S-$eyk|U!Y8%O+n!( zDOZ-ROdq8cIrpW*J6%wPA3X51JeiI&WHW zJ@dB1l*T4QOmPY17&m;Uq$wFCPVTI@p2X(3uV7xHtjS^uS;2!g3{sO*Bk#Z8KU zg6{lj+=i0TPJ|J|rKu=WIM@1{`rC8uqGqw&3_pbT+-6dtLaKaI3tlfAT!UQHL{I+w zFW+W*S;9QGqR$hkcNj<*@AtL$ub*-?)<@&+D$+XGLtKqC!NtjY5a^Y=Ch)cgdMa2= zs#v9qr~wQEl;oC1zGLTshm(Y?(Ib2pX3}<3peSd9j{e$$3^4ys_BcY091l(|Cqx(b z(&B?g)`@|c$|2;5rATHL?AwLF$N78STX+=~>~wr zEcA!6*FbS^HDEmSiMEwZcNpGW_D^kr9Tujq6keAQ>#L>!_NqI)h;ZwHnjEDd5g6|A zI)+J?rug|KE`TD|Q37c!jAT4O_%wJ-0OVVPbX6HJ~H z8>G>;<|tg;*zs?jvKT@PsFyLG>47!E?7JA`Vi1REf=L#on!lUzOG8daD3f6;|DhKV%?D%ZOh z@gPCJ6GYprUrwxDbpLjO>?sMx#}h(%BA4Ym&0+nOBKDXEF0eL8dd<+Iw-)cvh5RroapqhUfJ?EfQPe6H&*DCiVvv=0Y&r~ks{K8xb z4&aYc=enBOmNH06N#_AeF$C9D!aeP{uBQn zRn#33+IanP>fclSzIt}~tJTK0=OKj7-f>2mNYpqT1as79&>jp9LzxQlQ>+s(GvWN)Y<9dv=Uc9t>bkn;ADcHOpwFEDhm0lGY zJTt}GFpsthR}loRGx2bsF#6G)tX1KkEl3^3+mg3CRo=kgH+hH^7ziy-K{J>&BTov# zn3%YkewAUzt48_1fwD73gx|EMl}LDql=u$q9EyL@YMD_bnL9hTZ+W=y@W3cH>eYai zK*S6F(UAi6&4SMH6-kv*yV%FrUJ>t6YCL3VJTm__$Me;TgT?Vn5BJMc>C|vF^c6Cx zfEp{YLdN~)BrkrUGW&9PsN9u*+tuL?JUihXLeC5(Y&Fk8*1vxx60bOFyAB9#JM$KZ z&_Ke0?tRc!7g*4B8C+NA1qSpW@f-BQEft8S^Y)iF;ClhPfM*N-#zFTJQ|!eJN-T#qxwYoCGB)!&R-|)M|NA?BaMK1(N|~(SwaqOPWZu zTDMzI_kZ>H0DmMCv6$zG5*c4^gf$U&S*K$SJmgq_k}$RHGo%LaCc^TI?{mqI?~Fa& zp=)j;nu7`~nE5m%y<0%E*%5y$(mJBG**hHdmWcNawanU5MLAi6kMcFzTvZYoN>I<- zbp7hxL*Vj8T*r!7&FVJkd$?|b-+aENGCAfFo&O%oK*17*g78MH`*5`DOX>%Bev6??ZptN_+^Oa>t$3b>E}B;td6$Tm@*+ zcY&sHfC=9836&(`uorLqkn|9#1Q6aX>Z2hST0AD45&Pcyo^73XXiPl}TUUe-#MUP@ zSo6zxg&M6!&u-DIhXul=+5tKQzV|>zAtPBFJY(1R;hvRLaAYrfR2AUz*z6mF8`6r6 ziRD#v{Q48;`SEuwkYQ?eLrt1%1qk|ZmkxKs6l61^3U@8w>k<&ThM{c_7M5mK=^_Tc zF*Xfa)U#LuZqHC;3mOUSB%E4Jb)|8`yRr&CB$9|?f+}om(VTA ze!KrmKZD-oS4I_lCDwSeu+Ee);w3)6y?~HdA2B`OfL>3Z?g7NmGaYa~51`&kd&PmZ zZ!GuCWI{H3@U|1uHfpuGnQsI zzb4T7pF;$%Am@rMyOK6V(fM!0GT3i@k+>85I<|k<-`0dR&j(o97&r);ot9#Og4B_e zgZTyHr}6O?MLTi%ke}saDK^HAEb1iF!~cEZdC>O*bwCHE0Ip7*RRNY4q(_&wQBw^x zm)&3QB%p$R;TmFOJ=}Wv<@_J5P#LOw@b^czyvJD;;@a(BnoPQEkMEpP;gM?pRK(Fe zb#Yc@`Y!t#t|WYK1+yM$C$aC$4d;D)*q)U zzs3{`!Pkx9Qz;=*@TqqtUf`+3?1z9*HattiVqJ285`0ls0;Bfm~I{G!IC6j5|tg8h8LtK|9mNG zfOvNF6Y?h3H64L98KpNSv}C&NfuDR{2dzKCS1Fi!!Euk6=B7n>79stn=mDVl{rbDP z8Za)Y+PVZp!VK;2XkwX!?CCQ}2A>GXLeDWKp3UV29c_dGzTKQSQ&Zv^l?Atr-k^;5 zV_=N)OW+UTkvHBMO<;J7P?UYytp>20JdoqVzqj$d15*=iuyJ_(0L)xp(OrogdE(Ng zu@M9gIv7ree4E0>>wk7P2dwFF9TLq)E8_a@AfOVPn9zm(x|EThxN$jmawu8ThUUnu zt_|c0ON;F0zdLjfyOgYEaiYes8t>2(P2*%*(n=T%(Co?4?e6REs*_Oi7AqIx0EuOS zcVqt)NYTz^Ev4~X4Sx-q+01@U9fW{?(ggih)(+kXDhdG&lDv6^2bIh-gSlU3E-z8i zFpn-gD?#anA^0T-OOS$R!lY;=2++I_)F%vd$bEm=EUQ_rVR{ppb(7U)RcC`SM5?b02S?OG+yMIc70<>ZsB z{Yg@oVGx=5gP8R~q}sfpLOKm=J$T#UqIp);4b>X+tg_jarCitHJ+m&8Z3XmKJ_lQ? zmW2dtYe=o^iviVFR^9Cw2Wn3l3p#*%#&rCuQBbx|sGOf>Ng2$H!J^eR_hWC(TNcO| z2`Um12-ZkI*jn8=C<*M0EAXKJA1iIjAm(w%pgtzOu@$1*hW?Uz>)^Gn$eb?>zoC0B z5>g4mqL11TYZ0ts4`8(m4@&{y9IOI@%UA8~XgDC7VgZV9Qwf`1I}%pT_vZro?3K^vk4B(*Q zM*0CQ=FKhusg%&n5sJ(awX&cp7;7JYdV229dbSgA`*n%2SnjlF>$iw=FY{V0eGnUB z1nQ$=vvM_|L#XSI_o_naQ_k<3A(b06ybXgZFakH!@u85~rM|c3a z;Cw6|+OP%#*SRP-XQRltJu8`zE^DJ)()e7TIFS4+^Jpd4^FWPIXWVjDev&J^6nM*X z_Sujwz#W1#6GZkVrh{wU&c7IuXjK{+^~}aeX&UZV+)9&1V<%lFd+xA{HU{GQ14HSqh+W7i^3Q&u^Z&XCyUGBLBfaw!MJ9w z+jpJ)Pv}4Z_woZxf)loL5n!@VU8KVE?s>AN`YH03ZVR4xuOO)>nSi;(lkS?8Vi2P^jof?LPv;f>Qm*4^5LJ!>n-kf>v{`XNlkhv2HuR2qB?^+Y$ z+tc0kYv=onT`c734|==#xxT4@2t*=TsTp2D3;vpv$e<1+EE$Uqo2y5xw$wNy+B^o^ z-zeb&dsQe`T!D(t&~eBB9S{8BLXhq6rOGIY(-Hgnl&t{YA|*C0i7 zFu=4c(FYW;%<3EeS9^vo7L5unWI&ZzVq_y1N)SEV4Ip&|5O)Eoy_x;}4)pO-N0GST z^z1>o z#jS+nFKpg__BImz(H|_{0YRuOzxG8b0wqUiw}g=l7WQRQt&9`B8>8oTdY?;YJn5p8 z?@?aOtdT3X0n#ZHXrQ-zxZQ$o_KkypBv1}1}R>h znA#`HV2g>pCx&JHO6=tqqeyw8@;Ai1@W#IT-WX6+dXK7un&lE?Nhb<#+^$BUqUoPB7=Z0TM- zYVsG(=T!?erX2cB8>!B?=c&}6%8)`CXUoV5o9)BNBg+|>bm5}4YNR9*R>R{iS(drJ zz8bq2v;2gncfC*4H7bG@E_=%}J$;o)AGJimo+eQfNk4l8-u9{#Z9rE4l|yh)cCz0DJ>3~EST5SYRB za?s)N;&UV?jEvtHeauV6IYOND!F7E%FrTo;Y=s>%KGrt1?g(c7{aJfSG{{^JAt4H) zRM&9iF_L4(Q&ij@`Ym>FgIUaAbo%1P`5(OJtbhL#w@8N~6P9Tr#3Wv<^}i>8hN$IF zAO9Ag&msP-KwzLGno}rjV~atO1t5N2bbW2-+ualJh)}|_W>V%si%ji8&%;Quxk8B$ zsNcR^ohWxmE}`0a5rf`b_NVjr04v))xw8JvD3dPIev@VKWwUGhEQ-V^s}l7&iK9!( zycQ<#_Ugm_*cFv{+kE2H$X(qP-<1gB(614CF7VAMFWr;AQdeGrmM3x!#*~41XCK< zdMI__epZYgeg0CHl8b7jUo1K3!bYvH>68mih-lhHJsU;1_LIgWh{Jz<`^jPD4rfjh zh#RVe4w^aJYwNUs1wcQ`FhWA3O9SySRkUIV1^GapA14`K(GiFO>{3o8E%|2eXkhr5 ze(yjXVpkm7XaMd9Qf(3fEfW@aPP{0nay;4Hyj-?1XRHapz-AP*i9bB$^E>hja-&J4`E-Q!4XCrU1P8G$c?VdO;}SAml$_SlY2E08`jM zcSv{p{vod$b{;APEQtmM8d!wPBgniY3E(J+S66h~C@#LWyG9eo4-=0AH}8-DN=TN& z7-cNDvyD=wzvhbGMNrphL)_P3KjcD0jt-tGs;pgtW)1Q$5NXYi93|j25?VYYN(5@C zs_By@OiPx|2V7Ik-5;Z--U*O~|Fs0>FuE1zoLFC44^;yy{6 z;6*{!;KaEhad6FKg-7O@;Q;0$mrA`9-3hH3oQ1u17P|yk?Gv(EQ)TN60gw+h|Cs=^ zX*P^jqTF|}>8>%h=gmh1)@xm4i7#ntu&>Ui z3)5gq2Z46}gz}9<>I(cesgVS$7UX)Q%v%3;GU%fG=}jEVAVzgmMS0AU4{GoHOQSpW z)CT@pP;p9l>Yj;yB$q|wjoHl) z989ecqMsHBH3T)@HGl=vI-uvf&)y?WuajY?itM0YkfHrv2xK<0sKUJEd!6ieXP36| zA_E@bv5IOeEGIm0iSWG{OfkB4ZPtxc-%+2GB3k1{(b%tayF?G8E{tD&!wLC11T*&9 zwZwVQ5fxaeC9CiSG9Sfu=P3U{7d}a6wTPl=(fUFPXbUME1_UydH!J(7tl;ZT&iWs= zl~;g6RXw|5z7WPxHMSFw4z3;XKbV&JoQv9NzE}&v!IuSWDoRSFpV0puE#kgDm6gsCA&&G5^SxD4%KVTN| z(lKZdg}2}lkPr$C+k)`M+Yee0w8 z2KiU$XaRh5LJ_v!+Fm;a84nNfbysb*5iKNIh7WtCEvKzad%FM7)d2!6mZ#ra($(8&a>Y*gD}?&&HJfQ;+*lB zGDV}1U2vbr|IDn7r2<3!?lHZ$XsHZk&<*vKHb;`P)MTdr6kR+ENB0;BTFaT0G4$*O z<|5hOZq$MncYAkLf17jogd~xC4)KT>K|aYA2L)pCwQDzHADp#2(2A4Ps%zQr7+opz zQ~N6eJh!EJ%%v8Klr210@t);8n);g!hl*~tm?m2pC0IA zHGSq!b$ll}M5*nT4_C?wMD+`O?x^iqr!g{Rae)j!>A_GHU1EPp@W2T!En7XC_KZ4l%YMIqDk1{9S%n zDAdIK5qr5ojgai;ueD0uqxP5vz)3Bj{Hc6x8#x`B9DtcU8~A(4a!?ol;WDc{JQrWA zG;OK7-&zypV;;1eh5xqXe!1&C-w=Lj-aM~3cFXlRRJ#n-;zOQ zybp3T1e?^v+wzQ2TfZ8%@`xpn zacFMYTIoc)LTYQ+Pwb8JCbnIrX}C@+vRh1eLKlv|KS7|({?9yPVVTXLX#XC$4s9#ug3~El)7Omdi#vbf;NG{z!=X53i z@+xj027G0!!D8@8CJ70t>IVzETt!0U>0F3B66ZG^sSnWxN*|~>qFhgUGqH}Pe%d~3 zvk5kSc?y?tr8TH*`Oe>VziH<`gR5-$3CRjm`XAmP)_vyX<%DG)Kk%q+8%jgMj9q4Z z+ymDX5FT;PnAE1`+c8#ttW-v)38=)jgXecQsZ-d32kJ_!SR4sUAdElXIlC6&!zzxD8A$@!2EwNx* z1axfGm0Jz1c5MXve&nz9_OQgW)%B5JH;klZh|g$Ri;L?FDpiN+gljja5&|BJ3rm5S5?VOD?ln#w#`9`r_m~ zs6?{A4W9>;Z|d(ZthB07WGPGELn5nPPvlQMCB?2%q!r7TOtT0~e}fJam7bL|8I9jQ z=2l@p_4X{h;(%zk>9=RV?9y#Joxw7`QIWFGo*8UgIPJn)xGbP#cWAa<|EBKWb0f-6 z9x;JWKZ17Ijz05ew4jkMcg5+Hls1W#ieKmNt!cdNpB{4D3-7~`UFM#Rxw&v<*hn{Y z<`OwBo1x30aMcoMo~{oetbGcFCVAIs-XYnYQq=_UY4@RZUPqyl#l|Tdj}C~Tc%)|0 z7WOzG`n)dDezueJITRRlTs$XPkCzO*gEH8K?>FeH+<-hg@M5V(ND`9ozHk>@(-I39 zv(5_4Xote)n>n92@+?mAe_1j5JxXq+?jcCm7CjWgB$e!Q$1P`&6vTt??+9ZM0l**$M=AR-&k zegcEoAl73eQ2t#&-{#CZL2I8s$%?E%oq-~6h}{I@w*DHdlc0N zYug(kuuE#=Kg1AlT&doz_UVD1Eb`auvpu18amK&%lF<@j989@hFLk{ZDtmJ3bN%7Z(Q}Mn-pccLsM>274!SMrLkqZbl{+ zMiv%&Knr?jPdgVw4|+Ri(*GXh|BfSS>TK*}>EL2%Z%6c>aSe^^U0wJ{Nd7a?|33bE zKV2-%{@+Y?&J6#x(+tM;wv7MzgprwniSd8O26W~9Pc4tUlcgzO=KqY(&&>N@E&qRY i|1%FS<9{aq|Ln|vAL)P90uGfQhL`bwzczjtp#KBdf-IK+ literal 45860 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