Skip to content

Commit 7759369

Browse files
authoredDec 25, 2023
Merge pull request #43 from takuma-hmng8/dev
domSyncerのDOMRect更新をintersect外でも実行するように変更
2 parents dda9039 + 4084de6 commit 7759369

File tree

10 files changed

+186
-56
lines changed

10 files changed

+186
-56
lines changed
 

‎app/playground/Playground.tsx

+1-25
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ import GUI from "lil-gui";
2222
import { useGUI } from "@/utils/useGUI";
2323

2424
const CONFIG = {
25-
noise: structuredClone(NOISE_PARAMS) as NoiseParams,
2625
colorStrata: {
2726
...structuredClone(COLORSTRATA_PARAMS),
2827
laminateLayer: 20,
@@ -36,17 +35,6 @@ const CONFIG = {
3635
};
3736

3837
const setGUI = (gui: GUI) => {
39-
// noise
40-
const noise = gui.addFolder("noise");
41-
noise.add(CONFIG.noise, "scale", 0, 0.1, 0.0001);
42-
noise.add(CONFIG.noise, "timeStrength", 0, 10, 0.01);
43-
noise.add(CONFIG.noise, "noiseOctaves", 1, 10, 1);
44-
noise.add(CONFIG.noise, "fbmOctaves", 1, 10, 1);
45-
noise.add(CONFIG.noise, "warpOctaves", 1, 10, 1);
46-
const warpDirection = noise.addFolder("warpDirection");
47-
warpDirection.add(CONFIG.noise.warpDirection!, "x", 1, 10, 0.1);
48-
warpDirection.add(CONFIG.noise.warpDirection!, "y", 1, 10, 0.1);
49-
noise.add(CONFIG.noise, "warpStrength", 1, 50, 0.1);
5038
//color strata
5139
const colorStrata = gui.addFolder("colorStrata");
5240
colorStrata.add(CONFIG.colorStrata, "laminateLayer", 0, 20, 1);
@@ -74,7 +62,6 @@ const setGUI = (gui: GUI) => {
7462

7563
const setConfig = () => {
7664
return {
77-
noise: { ...CONFIG.noise },
7865
colorStrata: { ...CONFIG.colorStrata },
7966
};
8067
};
@@ -86,21 +73,10 @@ export const Playground = () => {
8673
const { size, dpr } = useThree((state) => {
8774
return { size: state.size, dpr: state.viewport.dpr };
8875
});
89-
const [updateNoise] = useNoise({ size, dpr });
90-
const [updateFluid] = useFluid({ size, dpr });
91-
const [updateFxBlending, setFxBlending] = useFxBlending({ size, dpr });
76+
9277
const [updateColorStrata] = useColorStrata({ size, dpr });
93-
// const [updateBrightnessPicker] = useBrightnessPicker({ size, dpr });
9478

9579
useFrame((props) => {
96-
const noise = updateNoise(props, {
97-
...setConfig().noise,
98-
});
99-
// const fluid = updateFluid(props);
100-
// const blending = updateFxBlending(props, {
101-
// texture: fluid,
102-
// map: noise,
103-
// });
10480
const colorStrata = updateColorStrata(props, {
10581
...setConfig().colorStrata,
10682
texture: false,

‎app/playground2/Playground.tsx

+142
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
"use client";
2+
3+
import * as THREE from "three";
4+
import { useRef } from "react";
5+
import { useFrame, useThree } from "@react-three/fiber";
6+
import {
7+
useFluid,
8+
useFxBlending,
9+
useColorStrata,
10+
} from "@/packages/use-shader-fx/src";
11+
import {
12+
FluidParams,
13+
FLUID_PARAMS,
14+
} from "@/packages/use-shader-fx/src/hooks/useFluid";
15+
import {
16+
ColorStrataParams,
17+
COLORSTRATA_PARAMS,
18+
} from "@/packages/use-shader-fx/src/hooks/useColorStrata";
19+
import {
20+
FxBlendingParams,
21+
FXBLENDING_PARAMS,
22+
} from "@/packages/use-shader-fx/src/hooks/useFxBlending";
23+
import GUI from "lil-gui";
24+
import { useGUI } from "@/utils/useGUI";
25+
26+
const CONFIG = {
27+
fluid: structuredClone(FLUID_PARAMS) as FluidParams,
28+
colorStrata: {
29+
...structuredClone(COLORSTRATA_PARAMS),
30+
laminateLayer: 20,
31+
laminateInterval: new THREE.Vector2(0.1, 0.1),
32+
laminateDetail: new THREE.Vector2(0.7, 0.7),
33+
distortion: new THREE.Vector2(10.0, 10.0),
34+
colorFactor: new THREE.Vector3(1, 1, 1),
35+
timeStrength: new THREE.Vector2(1, 1),
36+
noiseStrength: new THREE.Vector2(1, 1),
37+
} as ColorStrataParams,
38+
fxBlending: structuredClone(FXBLENDING_PARAMS) as FxBlendingParams,
39+
};
40+
41+
const setGUI = (gui: GUI) => {
42+
//fluid
43+
const fluid = gui.addFolder("fluid");
44+
fluid.add(CONFIG.fluid, "density_dissipation", 0, 1, 0.01);
45+
fluid.add(CONFIG.fluid, "velocity_dissipation", 0, 1, 0.01);
46+
fluid.add(CONFIG.fluid, "velocity_acceleration", 0, 100, 1);
47+
fluid.add(CONFIG.fluid, "pressure_dissipation", 0, 1, 0.01);
48+
fluid.add(CONFIG.fluid, "pressure_iterations", 0, 30, 1);
49+
fluid.add(CONFIG.fluid, "curl_strength", 0, 100, 1);
50+
fluid.add(CONFIG.fluid, "splat_radius", 0, 0.2, 0.001);
51+
//color strata
52+
const colorStrata = gui.addFolder("colorStrata");
53+
colorStrata.add(CONFIG.colorStrata, "laminateLayer", 0, 20, 1);
54+
colorStrata.add(CONFIG.colorStrata, "scale", 0, 1, 0.01);
55+
const laminateInterval = colorStrata.addFolder("laminateInterval");
56+
laminateInterval.add(CONFIG.colorStrata.laminateInterval!, "x", 0, 2, 0.01);
57+
laminateInterval.add(CONFIG.colorStrata.laminateInterval!, "y", 0, 2, 0.01);
58+
const laminateDetail = colorStrata.addFolder("laminateDetail");
59+
laminateDetail.add(CONFIG.colorStrata.laminateDetail!, "x", 0, 10, 0.1);
60+
laminateDetail.add(CONFIG.colorStrata.laminateDetail!, "y", 0, 10, 0.1);
61+
const distortion = colorStrata.addFolder("distortion");
62+
distortion.add(CONFIG.colorStrata.distortion!, "x", 0, 10, 0.01);
63+
distortion.add(CONFIG.colorStrata.distortion!, "y", 0, 10, 0.01);
64+
const colorFactor = colorStrata.addFolder("colorFactor");
65+
colorFactor.add(CONFIG.colorStrata.colorFactor!, "x", 0, 10, 0.01);
66+
colorFactor.add(CONFIG.colorStrata.colorFactor!, "y", 0, 10, 0.01);
67+
colorFactor.add(CONFIG.colorStrata.colorFactor!, "z", 0, 10, 0.01);
68+
const timeStrength = colorStrata.addFolder("timeStrength");
69+
timeStrength.add(CONFIG.colorStrata.timeStrength!, "x", 0, 2, 0.01);
70+
timeStrength.add(CONFIG.colorStrata.timeStrength!, "y", 0, 2, 0.01);
71+
const noiseStrength = colorStrata.addFolder("noiseStrength");
72+
noiseStrength.add(CONFIG.colorStrata.noiseStrength!, "x", 0, 5, 0.01);
73+
noiseStrength.add(CONFIG.colorStrata.noiseStrength!, "y", 0, 5, 0.01);
74+
// fx blending
75+
const fxBlending = gui.addFolder("fxBlending");
76+
fxBlending.add(CONFIG.fxBlending, "mapIntensity", 0, 10, 0.01);
77+
};
78+
79+
const setConfig = () => {
80+
return {
81+
fluid: { ...CONFIG.fluid },
82+
colorStrata: { ...CONFIG.colorStrata },
83+
fxBlending: { ...CONFIG.fxBlending },
84+
};
85+
};
86+
87+
export const Playground = () => {
88+
const updateGUI = useGUI(setGUI);
89+
90+
const ref = useRef<THREE.ShaderMaterial>(null);
91+
const { size, dpr } = useThree((state) => {
92+
return { size: state.size, dpr: state.viewport.dpr };
93+
});
94+
const [updateFluid] = useFluid({ size, dpr });
95+
const [updateFxBlending] = useFxBlending({ size, dpr });
96+
const [updateColorStrata] = useColorStrata({ size, dpr });
97+
98+
useFrame((props) => {
99+
const fluid = updateFluid(props, {
100+
...setConfig().fluid,
101+
});
102+
const colorStrata = updateColorStrata(props, {
103+
...setConfig().colorStrata,
104+
});
105+
const blending = updateFxBlending(props, {
106+
...setConfig().fxBlending,
107+
texture: colorStrata,
108+
map: fluid,
109+
});
110+
ref.current!.uniforms.u_fx.value = blending;
111+
updateGUI();
112+
});
113+
114+
return (
115+
<mesh>
116+
<planeGeometry args={[2, 2]} />
117+
<shaderMaterial
118+
ref={ref}
119+
vertexShader={`
120+
varying vec2 vUv;
121+
void main() {
122+
vUv = uv;
123+
gl_Position = vec4(position, 1.0);
124+
}
125+
`}
126+
fragmentShader={`
127+
precision highp float;
128+
varying vec2 vUv;
129+
uniform sampler2D u_fx;
130+
131+
void main() {
132+
vec2 uv = vUv;
133+
gl_FragColor = texture2D(u_fx, uv);
134+
}
135+
`}
136+
uniforms={{
137+
u_fx: { value: null },
138+
}}
139+
/>
140+
</mesh>
141+
);
142+
};

‎app/playground2/page.tsx

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import { ShaderFx } from "../ShaderFx";
2+
import { Playground } from "./Playground";
3+
4+
export default function Page() {
5+
return (
6+
<div style={{ width: "100%", height: "100svh", overflow: "hidden" }}>
7+
<ShaderFx>
8+
<Playground />
9+
</ShaderFx>
10+
</div>
11+
);
12+
}

‎packages/use-shader-fx/build/use-shader-fx.js

+20-22
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎packages/use-shader-fx/build/use-shader-fx.js.map

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎packages/use-shader-fx/build/use-shader-fx.umd.cjs

+1-1
Original file line numberDiff line numberDiff line change
@@ -515,7 +515,7 @@ void main() {
515515
alpha *= textureAlpha;
516516
517517
gl_FragColor = vec4(textureColor, alpha);
518-
}`;const Qe=({params:t,size:i,scene:r})=>{r.children.length>0&&(r.children.forEach(e=>{e instanceof n.Mesh&&(e.geometry.dispose(),e.material.dispose())}),r.remove(...r.children)),t.texture.forEach((e,a)=>{const c=new n.Mesh(new n.PlaneGeometry(1,1),new n.ShaderMaterial({vertexShader:Ze,fragmentShader:Je,transparent:!0,uniforms:{u_texture:{value:e},u_textureResolution:{value:new n.Vector2(0,0)},u_resolution:{value:new n.Vector2(0,0)},u_borderRadius:{value:t.boderRadius[a]?t.boderRadius[a]:0}}}));r.add(c)})},en=()=>{const t=u.useRef([]),i=u.useRef([]);return u.useCallback(({isIntersectingRef:e,isIntersectingOnceRef:a,params:c})=>{t.current.length>0&&t.current.forEach((o,l)=>{o.unobserve(i.current[l])}),i.current=[],t.current=[];const v=new Array(c.dom.length).fill(!1);e.current=[...v],a.current=[...v],c.dom.forEach((o,l)=>{const d=m=>{m.forEach(g=>{c.onIntersect[l]&&c.onIntersect[l](g),e.current[l]=g.isIntersecting})},f=new IntersectionObserver(d,{rootMargin:"0px",threshold:0});f.observe(o),t.current.push(f),i.current.push(o)})},[])},nn=()=>{const t=u.useRef([]),i=u.useCallback(({params:r,size:e,resolutionRef:a,scene:c,isIntersectingRef:v})=>{c.children.length!==t.current.length&&(t.current=new Array(c.children.length)),c.children.forEach((o,l)=>{const d=r.dom[l];if(!d)throw new Error("DOM is null.");if(v.current[l]){const f=d.getBoundingClientRect();if(t.current[l]=f,o.scale.set(f.width,f.height,1),o.position.set(f.left+f.width*.5-e.width*.5,-f.top-f.height*.5+e.height*.5,0),r.rotation[l]&&o.rotation.copy(r.rotation[l]),o instanceof n.Mesh){const m=o.material;s(m,"u_texture",r.texture[l]),s(m,"u_textureResolution",r.resolution[l]),s(m,"u_resolution",a.current.set(f.width,f.height)),s(m,"u_borderRadius",r.boderRadius[l]?r.boderRadius[l]:0)}}})},[]);return[t.current,i]},tn=()=>{const t=u.useRef([]),i=u.useRef([]),r=u.useCallback((e,a=!1)=>{t.current.forEach((v,o)=>{v&&(i.current[o]=!0)});const c=a?[...i.current]:[...t.current];return e<0?c:c[e]},[]);return{isIntersectingRef:t,isIntersectingOnceRef:i,isIntersecting:r}},K={texture:[],dom:[],resolution:[],boderRadius:[],rotation:[],onIntersect:[]},rn=({size:t,dpr:i},r=[])=>{const e=u.useMemo(()=>new n.Scene,[]),a=_(t),[c,v]=R({scene:e,camera:a,size:t,dpr:i,isSizeUpdate:!0}),[o,l]=b(K),[d,f]=nn(),m=u.useRef(new n.Vector2(0,0)),[g,x]=u.useState(!0);u.useEffect(()=>{x(!0)},r);const M=en(),{isIntersectingOnceRef:y,isIntersectingRef:T,isIntersecting:C}=tn();return[u.useCallback((U,O)=>{const{gl:D,size:h}=U;return O&&l(O),Ke(o),g&&(Qe({params:o,size:h,scene:e}),M({isIntersectingRef:T,isIntersectingOnceRef:y,params:o}),x(!1)),f({params:o,size:h,resolutionRef:m,scene:e,isIntersectingRef:T}),v(D)},[v,l,M,f,g,e,o,y,T]),l,{scene:e,camera:a,renderTarget:c,isIntersecting:C,DOMRects:d}]};var on=`precision mediump float;
518+
}`;const Qe=({params:t,size:i,scene:r})=>{r.children.length>0&&(r.children.forEach(e=>{e instanceof n.Mesh&&(e.geometry.dispose(),e.material.dispose())}),r.remove(...r.children)),t.texture.forEach((e,a)=>{const c=new n.Mesh(new n.PlaneGeometry(1,1),new n.ShaderMaterial({vertexShader:Ze,fragmentShader:Je,transparent:!0,uniforms:{u_texture:{value:e},u_textureResolution:{value:new n.Vector2(0,0)},u_resolution:{value:new n.Vector2(0,0)},u_borderRadius:{value:t.boderRadius[a]?t.boderRadius[a]:0}}}));r.add(c)})},en=()=>{const t=u.useRef([]),i=u.useRef([]);return u.useCallback(({isIntersectingRef:e,isIntersectingOnceRef:a,params:c})=>{t.current.length>0&&t.current.forEach((o,l)=>{o.unobserve(i.current[l])}),i.current=[],t.current=[];const v=new Array(c.dom.length).fill(!1);e.current=[...v],a.current=[...v],c.dom.forEach((o,l)=>{const d=m=>{m.forEach(g=>{c.onIntersect[l]&&c.onIntersect[l](g),e.current[l]=g.isIntersecting})},f=new IntersectionObserver(d,{rootMargin:"0px",threshold:0});f.observe(o),t.current.push(f),i.current.push(o)})},[])},nn=()=>{const t=u.useRef([]),i=u.useCallback(({params:r,size:e,resolutionRef:a,scene:c,isIntersectingRef:v})=>{c.children.length!==t.current.length&&(t.current=new Array(c.children.length)),c.children.forEach((o,l)=>{const d=r.dom[l];if(!d)throw new Error("DOM is null.");const f=d.getBoundingClientRect();if(t.current[l]=f,v.current[l]&&(o.scale.set(f.width,f.height,1),o.position.set(f.left+f.width*.5-e.width*.5,-f.top-f.height*.5+e.height*.5,0),r.rotation[l]&&o.rotation.copy(r.rotation[l]),o instanceof n.Mesh)){const m=o.material;s(m,"u_texture",r.texture[l]),s(m,"u_textureResolution",r.resolution[l]),s(m,"u_resolution",a.current.set(f.width,f.height)),s(m,"u_borderRadius",r.boderRadius[l]?r.boderRadius[l]:0)}})},[]);return[t.current,i]},tn=()=>{const t=u.useRef([]),i=u.useRef([]),r=u.useCallback((e,a=!1)=>{t.current.forEach((v,o)=>{v&&(i.current[o]=!0)});const c=a?[...i.current]:[...t.current];return e<0?c:c[e]},[]);return{isIntersectingRef:t,isIntersectingOnceRef:i,isIntersecting:r}},K={texture:[],dom:[],resolution:[],boderRadius:[],rotation:[],onIntersect:[]},rn=({size:t,dpr:i},r=[])=>{const e=u.useMemo(()=>new n.Scene,[]),a=_(t),[c,v]=R({scene:e,camera:a,size:t,dpr:i,isSizeUpdate:!0}),[o,l]=b(K),[d,f]=nn(),m=u.useRef(new n.Vector2(0,0)),[g,x]=u.useState(!0);u.useEffect(()=>{x(!0)},r);const M=en(),{isIntersectingOnceRef:y,isIntersectingRef:T,isIntersecting:C}=tn();return[u.useCallback((U,O)=>{const{gl:D,size:h}=U;return O&&l(O),Ke(o),g&&(Qe({params:o,size:h,scene:e}),M({isIntersectingRef:T,isIntersectingOnceRef:y,params:o}),x(!1)),f({params:o,size:h,resolutionRef:m,scene:e,isIntersectingRef:T}),v(D)},[v,l,M,f,g,e,o,y,T]),l,{scene:e,camera:a,renderTarget:c,isIntersecting:C,DOMRects:d}]};var on=`precision mediump float;
519519
520520
varying vec2 vUv;
521521

‎packages/use-shader-fx/build/use-shader-fx.umd.cjs.map

+1-1
Large diffs are not rendered by default.

‎packages/use-shader-fx/package-lock.json

+2-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎packages/use-shader-fx/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@hmng8/use-shader-fx",
3-
"version": "1.0.26",
3+
"version": "1.0.27",
44
"description": "wide variety of shader effects for React",
55
"main": "./build/use-shader-fx.umd.cjs",
66
"module": "./build/use-shader-fx.js",

‎packages/use-shader-fx/src/hooks/useDomSyncer/utils/useUpdateDomRect.ts

+5-3
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ export const useUpdateDomRect = (): UseUpdateDomRectReturn => {
2626

2727
const updateDomRects: UpdateDomRect = useCallback(
2828
({ params, size, resolutionRef, scene, isIntersectingRef }) => {
29+
// Initialize domRects if the number of children in the scene is different from the number of DOMRect
2930
if (scene.children.length !== domRects.current!.length) {
3031
domRects.current = new Array(scene.children.length);
3132
}
@@ -36,10 +37,11 @@ export const useUpdateDomRect = (): UseUpdateDomRectReturn => {
3637
throw new Error("DOM is null.");
3738
}
3839

39-
if (isIntersectingRef.current[i]) {
40-
const rect = domElement.getBoundingClientRect();
41-
domRects.current[i] = rect;
40+
// DOMRect is updated even outside the intersection
41+
const rect = domElement.getBoundingClientRect();
42+
domRects.current[i] = rect;
4243

44+
if (isIntersectingRef.current[i]) {
4345
mesh.scale.set(rect.width, rect.height, 1.0);
4446
mesh.position.set(
4547
rect.left + rect.width * 0.5 - size.width * 0.5,

0 commit comments

Comments
 (0)