Skip to content

Commit 099d8ea

Browse files
author
takuma-hmng8
committed
add useMorphParticles
1 parent 42f9251 commit 099d8ea

File tree

7 files changed

+306
-145
lines changed

7 files changed

+306
-145
lines changed

app/useMorphParticles/Playground.tsx

Lines changed: 54 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ import {
1414
MORPHPARTICLES_PARAMS,
1515
MorphParticlesParams,
1616
useBeat,
17+
useFluid,
18+
usePointer,
1719
} from "@/packages/use-shader-fx/src";
1820
import { FxMaterial, FxMaterialProps } from "./FxMaterial";
1921
import GUI from "lil-gui";
@@ -37,66 +39,83 @@ const setGUI = (gui: GUI) => {
3739
gui.add(CONFIG, "warpStrength", 0, 10, 0.01);
3840
gui.add(CONFIG, "warpPositionFrequency", 0, 10, 0.01);
3941
gui.add(CONFIG, "warpTimeFrequency", 0, 10, 0.01);
42+
gui.add(CONFIG, "displacementColorIntensity", 0, 40, 0.01);
4043
};
4144
const setConfig = () => {
4245
return {
4346
...CONFIG,
4447
} as MorphParticlesParams;
4548
};
46-
47-
/*===============================================
48-
TODO
49-
- useMorphParticles
50-
v morphする
51-
- tjの40
52-
v picture
53-
v 全体にマップするtexture
54-
v particleにマップするtexture
55-
-
56-
- wobble
57-
- 4Dノイズかける(時間が入るから)
58-
- wobble3Dの仕組みを利用する
59-
v color
60-
v 4色双線形補間
61-
v particleのサイズ
62-
v 球体にするレベル
63-
===============================================*/
49+
const morphList = [
50+
new THREE.PlaneGeometry(5, 5, 100, 100).attributes.position
51+
.array as Float32Array,
52+
new THREE.TorusGeometry(2.5, 1, 50, 30).attributes.position
53+
.array as Float32Array,
54+
];
55+
const uvList = [
56+
new THREE.PlaneGeometry(5, 5, 100, 100).attributes.uv.array as Float32Array,
57+
new THREE.TorusGeometry(2.5, 1, 50, 30).attributes.uv.array as Float32Array,
58+
];
6459

6560
export const Playground = () => {
6661
const updateGUI = useGUI(setGUI);
67-
const ref = useRef<FxMaterialProps>();
6862
const [funkun, funkunAlpha] = useLoader(THREE.TextureLoader, [
6963
"/funkun.jpg",
7064
"/funkun-alpha.jpg",
7165
]);
72-
const { size, viewport, gl } = useThree();
66+
const { size, viewport, scene } = useThree();
7367

74-
const morphList = [
75-
new THREE.PlaneGeometry(5, 5, 100, 100).attributes.position
76-
.array as Float32Array,
77-
new THREE.TorusGeometry(2.5, 1, 50, 30).attributes.position
78-
.array as Float32Array,
79-
];
68+
const [updateFluid, setFluid, { output: fluid }] = useFluid({
69+
size,
70+
dpr: viewport.dpr,
71+
});
72+
73+
const colorVec = new THREE.Vector3(0, 0, 0);
74+
setFluid({
75+
fluid_color: (velocity: THREE.Vector2) => {
76+
const rCol = Math.max(0.0, Math.abs(velocity.x) * 200);
77+
const gCol = Math.max(0.0, Math.abs(velocity.y) * 100);
78+
const bCol = Math.max(0.0, (rCol + gCol) / 2);
79+
return colorVec.set(rCol, gCol, bCol);
80+
},
81+
});
8082

8183
const [updatePoints, points] = useCreateMorphParticles({
8284
scene: false,
8385
size,
8486
dpr: viewport.dpr,
8587
geometry: new THREE.IcosahedronGeometry(2.5, 50),
86-
// positions: morphList,
88+
positions: morphList,
89+
uvs: uvList,
8790
// geometry: new THREE.PlaneGeometry(5, 5, 100, 100),
8891
});
92+
8993
const beat = useBeat(140, "easeOutCubic");
94+
const updatePointer = usePointer();
95+
const refPointer = useRef(new THREE.Vector2(0, 0));
96+
const handlePointerMove = (e: any) => {
97+
if (!e?.pointer) {
98+
return;
99+
}
100+
refPointer.current = e.pointer;
101+
};
102+
90103
useFrame((props) => {
91104
const b = beat(props.clock);
105+
updateFluid(props, {
106+
pointerValues: updatePointer(refPointer.current),
107+
});
108+
// updateFluid(props);
92109
updatePoints(props, {
93110
...setConfig(),
94-
// picture: funkun,
95-
// alphaPicture: funkunAlpha,
96-
map: funkun,
97-
alphaMap: funkunAlpha,
111+
displacement: fluid,
112+
picture: funkun,
113+
alphaPicture: funkunAlpha,
114+
// map: funkun,
115+
// alphaMap: funkunAlpha,
98116
beat: b.beat,
99117
morphProgress: Math.max(Math.sin(props.clock.getElapsedTime() / 2), 0),
118+
// morphProgress: 0.5,
100119
});
101120
updateGUI();
102121
});
@@ -105,6 +124,10 @@ export const Playground = () => {
105124
<mesh>
106125
<OrbitControls />
107126
<primitive object={points.points} />
127+
<primitive
128+
onPointerMove={handlePointerMove}
129+
object={points.interactiveMesh}
130+
/>
108131
</mesh>
109132
);
110133
};

packages/use-shader-fx/src/fxs/3D/useMorphParticles/index.ts

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,16 +34,22 @@ export type MorphParticlesParams = {
3434
warpStrength?: number;
3535
warpPositionFrequency?: number;
3636
warpTimeFrequency?: number;
37+
/** 変位させる。カラーチャンネルを利用して頂点を操作しますよ. 変位の強さはこのtextureのg channelによって変化します */
38+
displacement?: THREE.Texture | false;
39+
/** displacement textureのcolor chを反映させる強度 */
40+
displacementColorIntensity?: number;
3741
};
3842

3943
export type MorphParticlesObject = {
4044
scene: THREE.Scene;
4145
points: THREE.Points;
46+
interactiveMesh: THREE.Mesh;
4247
material: MorphParticlesMaterial;
4348
camera: THREE.Camera;
4449
renderTarget: THREE.WebGLRenderTarget;
4550
output: THREE.Texture;
4651
positions: Float32Array[];
52+
uvs: Float32Array[];
4753
};
4854

4955
export const MORPHPARTICLES_PARAMS: MorphParticlesParams = {
@@ -66,11 +72,15 @@ export const MORPHPARTICLES_PARAMS: MorphParticlesParams = {
6672
warpStrength: 0.5,
6773
warpPositionFrequency: 0.5,
6874
warpTimeFrequency: 0.5,
75+
// displacement
76+
displacement: false,
77+
displacementColorIntensity: 0,
6978
};
7079

7180
interface UseMorphParticlesProps extends HooksProps {
7281
geometry?: THREE.BufferGeometry;
7382
positions?: Float32Array[];
83+
uvs?: Float32Array[];
7484
}
7585

7686
const DEFAULT_GEOMETRY = new THREE.SphereGeometry(1, 32, 32);
@@ -84,15 +94,24 @@ export const useMorphParticles = ({
8494
samples = 0,
8595
geometry = DEFAULT_GEOMETRY,
8696
positions,
97+
uvs,
8798
}: UseMorphParticlesProps): HooksReturn<
8899
MorphParticlesParams,
89100
MorphParticlesObject
90101
> => {
91102
const scene = useMemo(() => new THREE.Scene(), []);
92103
const camera = useCamera(size, "PerspectiveCamera");
93104

94-
const [updateUniform, { points, material, positions: generatedPositions }] =
95-
useCreateMorphParticles({ scene, size, dpr, geometry, positions });
105+
const [
106+
updateUniform,
107+
{
108+
points,
109+
interactiveMesh,
110+
material,
111+
positions: generatedPositions,
112+
uvs: generatedUvs,
113+
},
114+
] = useCreateMorphParticles({ scene, size, dpr, geometry, positions, uvs });
96115

97116
const [params, setParams] = useParams<MorphParticlesParams>(
98117
MORPHPARTICLES_PARAMS
@@ -122,12 +141,14 @@ export const useMorphParticles = ({
122141
setParams,
123142
{
124143
scene,
125-
points: points as THREE.Points,
144+
points,
145+
interactiveMesh,
126146
material,
127147
camera,
128148
renderTarget,
129149
output: renderTarget.texture,
130150
positions: generatedPositions,
151+
uvs: generatedUvs,
131152
},
132153
];
133154
};

packages/use-shader-fx/src/fxs/3D/useMorphParticles/shader/main.frag

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,18 @@
11
precision highp float;
22
precision highp int;
33

4-
varying vec3 vPosition;
54
varying vec3 vColor;
65
varying float vPictureAlpha;
6+
varying vec3 vDisplacementColor;
7+
varying float vDisplacementIntensity;
78

89
uniform float uBlurAlpha;
910
uniform float uBlurRadius;
1011
uniform sampler2D uMap;
1112
uniform bool uIsMap;
1213
uniform sampler2D uAlphaMap;
1314
uniform bool uIsAlphaMap;
15+
uniform float uDisplacementColorIntensity;
1416

1517
void main() {
1618
vec2 uv = gl_PointCoord;
@@ -23,6 +25,10 @@ void main() {
2325
// mapがある場合はmapする
2426
vec3 finalColor = uIsMap ? texture2D(uMap,uv).rgb : vColor;
2527

28+
// displacementがtrueの場合はfinalCOlorとmixする
29+
float mixIntensity = clamp(uDisplacementColorIntensity * vDisplacementIntensity,0.,1.);
30+
finalColor = vDisplacementIntensity > 0. ? mix(finalColor,vDisplacementColor,mixIntensity) : finalColor;
31+
2632
// alpha mapを取得する
2733
float alphaMap = uIsAlphaMap ? texture2D(uAlphaMap,uv).g : 1.;
2834

packages/use-shader-fx/src/fxs/3D/useMorphParticles/shader/main.vert

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,18 +21,34 @@ uniform float uWarpPositionFrequency;
2121
uniform float uWarpTimeFrequency;
2222
uniform float uWarpStrength;
2323

24-
varying vec3 vPosition;
24+
uniform sampler2D uDisplacement;
25+
uniform bool uIsDisplacement;
26+
2527
varying vec3 vColor;
2628
varying float vPictureAlpha;
29+
varying vec3 vDisplacementColor;
30+
varying float vDisplacementIntensity;
2731

2832
// #usf <morphPositions>
33+
// #usf <morphUvs>
2934
// #usf <getWobble>
3035

3136
void main() {
3237
vec3 newPosition = position;
33-
// #usf <morphTransition>
38+
vec2 newUv = uv;
39+
// #usf <morphPositionTransition>
40+
// #usf <morphUvTransition>
41+
42+
// ここで`newPosition`に対してdisplacement
43+
vec3 displacement = uIsDisplacement ? texture2D(uDisplacement, newUv).rgb : vec3(0.0);
44+
float displacementIntensity = smoothstep(0., 1., displacement.g);
45+
vDisplacementColor = displacement;
46+
vDisplacementIntensity = displacementIntensity;
3447

35-
vPosition = newPosition;
48+
//この時点でdisplacementは0 ~ 1なので、それを-1~1にする
49+
displacement = displacement * 2.-1.;
50+
displacement *= displacementIntensity;
51+
newPosition += displacement;
3652

3753
// Final position
3854
vec4 modelPosition = modelMatrix * vec4(newPosition, 1.0);
@@ -44,10 +60,10 @@ void main() {
4460
gl_Position = projectedPosition += wobble;
4561

4662
// カラー pictureがtrueの場合 はpictureをそうでない場合は、4色の線形保管
47-
vColor = uIsPicture ? texture2D(uPicture, uv).rgb : mix(mix(uColor0, uColor1, newPosition.x), mix(uColor2, uColor3, newPosition.y), newPosition.z);
63+
vColor = uIsPicture ? texture2D(uPicture, newUv).rgb : mix(mix(uColor0, uColor1, newPosition.x), mix(uColor2, uColor3, newPosition.y), newPosition.z);
4864

4965
// pictureのgチャンネルでAlphaを設定する
50-
vPictureAlpha = uIsAlphaPicture ? texture2D(uAlphaPicture, uv).g : 1.;
66+
vPictureAlpha = uIsAlphaPicture ? texture2D(uAlphaPicture, newUv).g : 1.;
5167

5268
// point sizeにpicturealphaもかける。aplhamapによってサイズも調整可能に
5369
gl_PointSize = uPointSize * vPictureAlpha * uResolution.y;

packages/use-shader-fx/src/fxs/3D/useMorphParticles/useCreateMorphParticles.ts

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,17 @@ type UseCreateMorphParticlesProps = {
1515
scene?: THREE.Scene | false;
1616
geometry?: THREE.BufferGeometry;
1717
positions?: Float32Array[];
18+
uvs?: Float32Array[];
1819
};
1920

2021
type UseCreateMorphParticlesReturn = [
2122
(props: RootState | null, params: MorphParticlesParams) => void,
2223
{
2324
points: THREE.Points;
25+
interactiveMesh: THREE.Mesh;
2426
material: MorphParticlesMaterial;
2527
positions: Float32Array[];
28+
uvs: Float32Array[];
2629
}
2730
];
2831

@@ -32,13 +35,20 @@ export const useCreateMorphParticles = ({
3235
scene = false,
3336
geometry = DEFAULT_GEOMETRY,
3437
positions,
38+
uvs,
3539
}: UseCreateMorphParticlesProps): UseCreateMorphParticlesReturn => {
3640
const material = useMaterial({ size, dpr });
37-
const { object: points, positions: generatedPositions } = useCreateObject({
41+
const {
42+
object: points,
43+
interactiveMesh,
44+
positions: generatedPositions,
45+
uvs: generatedUvs,
46+
} = useCreateObject({
3847
scene,
3948
geometry,
4049
material,
4150
positions,
51+
uvs,
4252
});
4353

4454
const updateUniform = useCallback(
@@ -115,19 +125,34 @@ export const useCreateMorphParticles = ({
115125
"uWarpTimeFrequency",
116126
params.warpTimeFrequency
117127
);
128+
// displacement
129+
if (params.displacement) {
130+
setUniform(material, "uDisplacement", params.displacement);
131+
setUniform(material, "uIsDisplacement", true);
132+
} else {
133+
setUniform(material, "uIsDisplacement", false);
134+
}
135+
params.displacementColorIntensity &&
136+
setUniform(
137+
material,
138+
"uDisplacementColorIntensity",
139+
params.displacementColorIntensity
140+
);
118141
},
119142
[material]
120143
);
121144

122-
//初期化時に デフォルト値への更新を保証したいので、 `MORPHPARTICLES_PARAMS`で更新する
145+
//初期化時に デフォルト値への更新を保証したいので、`MORPHPARTICLES_PARAMS`で更新する
123146
useEffect(() => updateUniform(null, MORPHPARTICLES_PARAMS), [updateUniform]);
124147

125148
return [
126149
updateUniform,
127150
{
128151
points: points as THREE.Points,
152+
interactiveMesh: interactiveMesh as THREE.Mesh,
129153
material,
130154
positions: generatedPositions,
155+
uvs: generatedUvs,
131156
},
132157
];
133158
};

0 commit comments

Comments
 (0)