1
1
"use client" ;
2
2
3
3
import * as THREE from "three" ;
4
- import { memo } from "react" ;
5
- import { Environment , OrbitControls } from "@react-three/drei" ;
6
- import { useFrame } from "@react-three/fiber" ;
7
- import { useStickers } from "./useStickers" ;
4
+ import { useMemo , useRef } from "react" ;
5
+ import { OrbitControls } from "@react-three/drei" ;
6
+ import { useFrame , createPortal , extend , useThree } from "@react-three/fiber" ;
7
+ import { useStickers } from "./StickerBall/ useStickers" ;
8
8
import { CanvasState } from "./CanvasState" ;
9
9
import { StickerBall } from "./StickerBall" ;
10
- import { Easing , Utils } from "@/packages/use-shader-fx/src" ;
10
+ import {
11
+ Easing ,
12
+ Utils ,
13
+ useResizeBoundary ,
14
+ useSingleFBO ,
15
+ } from "@/packages/use-shader-fx/src" ;
16
+ import { Background } from "./Background" ;
17
+ import { FxMaterial , FxMaterialProps } from "./romanticism/FxMaterial" ;
18
+ import { useRomanticism } from "./romanticism/useRomanticism" ;
11
19
12
- const Background = memo ( ( { stickerMap } : { stickerMap : THREE . Texture } ) => {
13
- return (
14
- < >
15
- < Environment preset = "warehouse" environmentIntensity = { 0.5 } />
16
- < mesh scale = { 100 } >
17
- < sphereGeometry args = { [ 3 , 32 , 32 ] } />
18
- < meshBasicMaterial
19
- color = { new THREE . Color ( 0x444444 ) }
20
- map = { stickerMap }
21
- side = { THREE . BackSide }
22
- />
23
- </ mesh >
24
- </ >
25
- ) ;
26
- } ) ;
27
- Background . displayName = "Background" ;
20
+ extend ( { FxMaterial } ) ;
28
21
29
22
export const Playground = ( ) => {
30
- const { stickerMap , normalMap , isReady , silhouette } = useStickers ( ) ;
23
+ const { camera , size , viewport , gl } = useThree ( ) ;
31
24
32
25
const canvasState = CanvasState . getInstance ( ) ;
33
26
34
- useFrame ( ( { camera, clock } , delta ) => {
27
+ // 1000以上リサイズした場合のみリサイズする
28
+ const resizeBoundary = useResizeBoundary ( {
29
+ gl,
30
+ size,
31
+ boundFor : "larger" ,
32
+ threshold : 1000 ,
33
+ } ) ;
34
+
35
+ // stickers
36
+ const { stickerMap, normalMap, isReady, silhouette } =
37
+ useStickers ( resizeBoundary ) ;
38
+
39
+ // offscreen to stickers
40
+ const offscreenScene = useMemo ( ( ) => new THREE . Scene ( ) , [ ] ) ;
41
+ const [ portalStickers , updatePortalStickers ] = useSingleFBO ( {
42
+ scene : offscreenScene ,
43
+ camera,
44
+ size,
45
+ dpr : viewport . dpr ,
46
+ depthBuffer : true ,
47
+ isSizeUpdate : resizeBoundary . isUpdate ,
48
+ } ) ;
49
+
50
+ // romanticism
51
+ const romanticism = useRomanticism ( portalStickers . texture ) ;
52
+ const materialRef = useRef < FxMaterialProps > ( null ) ;
53
+
54
+ useFrame ( ( { camera, clock, pointer, gl } ) => {
35
55
if ( ! isReady ) {
36
56
return ;
37
57
}
38
58
39
- // control camera state
40
- if ( canvasState . cameraState . point . z < canvasState . CAMERA_Z . default ) {
41
- canvasState . cameraState . point . z += delta ;
59
+ // update portalized stickers
60
+ updatePortalStickers ( gl ) ;
61
+
62
+ // update romanticism
63
+ if ( materialRef . current ) {
64
+ materialRef . current . u_time = clock . getElapsedTime ( ) ;
42
65
}
43
- camera . position . lerp ( canvasState . cameraState . point , 0.16 ) ;
66
+
67
+ // control camera state
68
+ const _pointer = pointer . clone ( ) . multiplyScalar ( 0.32 ) ;
69
+ canvasState . cameraState . point . lerp (
70
+ {
71
+ ..._pointer , // uncomment this line to enable camera movement
72
+ // x: 0,
73
+ // y: 0,
74
+ z : canvasState . CAMERA_Z . default ,
75
+ } ,
76
+ 0.12
77
+ ) ;
78
+ camera . position . lerp ( canvasState . cameraState . point , 0.14 ) ;
44
79
camera . lookAt ( 0 , 0 , 0 ) ;
45
80
46
81
// control clock state
@@ -61,23 +96,37 @@ export const Playground = () => {
61
96
}
62
97
} ) ;
63
98
return (
64
- < mesh visible = { isReady } >
65
- < StickerBall
66
- stickerMap = { stickerMap }
67
- normalMap = { normalMap }
68
- silhouetteMap = { silhouette }
69
- />
70
- < Background stickerMap = { stickerMap } />
71
- < OrbitControls
72
- enabled = { true }
73
- enableZoom = { false }
74
- enablePan = { false }
75
- rotateSpeed = { 0.12 }
76
- minAzimuthAngle = { - 0.785 } // -45
77
- maxAzimuthAngle = { 0.785 } // 45
78
- minPolarAngle = { 1.134 } // 65
79
- maxPolarAngle = { 1.919 } // 110
80
- />
81
- </ mesh >
99
+ < >
100
+ { createPortal (
101
+ < mesh visible = { isReady } >
102
+ < StickerBall
103
+ stickerMap = { stickerMap }
104
+ normalMap = { normalMap }
105
+ silhouetteMap = { silhouette }
106
+ />
107
+ < Background stickerMap = { stickerMap } scene = { offscreenScene } />
108
+ < OrbitControls
109
+ enabled = { true }
110
+ enableZoom = { false }
111
+ enablePan = { false }
112
+ rotateSpeed = { 0.12 }
113
+ minAzimuthAngle = { - 0.785 } // -45
114
+ maxAzimuthAngle = { 0.785 } // 45
115
+ minPolarAngle = { 1.134 } // 65
116
+ maxPolarAngle = { 1.919 } // 110
117
+ />
118
+ </ mesh > ,
119
+ offscreenScene
120
+ ) }
121
+ < mesh visible = { isReady } >
122
+ < planeGeometry args = { [ 2 , 2 ] } />
123
+ < fxMaterial
124
+ ref = { materialRef }
125
+ u_romance = { romanticism }
126
+ u_original = { portalStickers . texture }
127
+ key = { FxMaterial . key }
128
+ />
129
+ </ mesh >
130
+ </ >
82
131
) ;
83
132
} ;
0 commit comments