1
1
import * as THREE from "three" ;
2
- import { useRef } from "react" ;
2
+ import { useMemo , useRef , useState , useEffect } from "react" ;
3
3
import { useFrame , useThree } from "@react-three/fiber" ;
4
4
import {
5
5
useNoise ,
6
6
useFluid ,
7
7
useFxBlending ,
8
8
useColorStrata ,
9
9
useBrightnessPicker ,
10
+ useSingleFBO ,
10
11
} from "@/packages/use-shader-fx/src" ;
11
12
13
+ function Box ( props : any ) {
14
+ // This reference will give us direct access to the mesh
15
+ const meshRef = useRef < THREE . Mesh > ( ) ;
16
+ // Set up state for the hovered and active state
17
+ const [ hovered , setHover ] = useState ( false ) ;
18
+ const [ active , setActive ] = useState ( false ) ;
19
+ // Subscribe this component to the render-loop, rotate the mesh every frame
20
+ useFrame ( ( state , delta ) => {
21
+ meshRef . current ! . rotation . x += delta ;
22
+ meshRef . current ! . rotation . y -= delta ;
23
+ } ) ;
24
+ // Return view, these are regular three.js elements expressed in JSX
25
+ return (
26
+ < mesh
27
+ { ...props }
28
+ ref = { meshRef }
29
+ scale = { active ? 2 : 1.5 }
30
+ onClick = { ( event ) => setActive ( ! active ) }
31
+ onPointerOver = { ( event ) => setHover ( true ) }
32
+ onPointerOut = { ( event ) => setHover ( false ) } >
33
+ < boxGeometry args = { [ 1 , 1 , 1 ] } />
34
+ < meshStandardMaterial color = { hovered ? "hotpink" : "orange" } />
35
+ </ mesh >
36
+ ) ;
37
+ }
38
+
12
39
export const Home = ( ) => {
13
40
const ref = useRef < THREE . ShaderMaterial > ( null ) ;
14
- const { size, dpr } = useThree ( ( state ) => {
15
- return { size : state . size , dpr : state . viewport . dpr } ;
16
- } ) ;
41
+ const { size, viewport, camera } = useThree ( ) ;
42
+ const dpr = viewport . dpr ;
17
43
const [ updateNoise , setNoise ] = useNoise ( { size, dpr } ) ;
18
44
const [ updateFluid , setFluid ] = useFluid ( { size, dpr } ) ;
19
45
const [ updateFxBlending , setFxBlending ] = useFxBlending ( { size, dpr } ) ;
@@ -54,6 +80,20 @@ export const Home = () => {
54
80
noiseStrength : new THREE . Vector2 ( 1 , 1 ) ,
55
81
} ) ;
56
82
83
+ // This scene is rendered offscreen
84
+ const offscreenScene = useMemo ( ( ) => new THREE . Scene ( ) , [ ] ) ;
85
+ const offscreenMesh = useRef < THREE . Mesh > ( null ) ;
86
+ // create FBO for offscreen rendering
87
+ const [ _ , updateRenderTarget ] = useSingleFBO ( {
88
+ scene : offscreenScene ,
89
+ camera,
90
+ size,
91
+ dpr : viewport . dpr ,
92
+ } ) ;
93
+ useEffect ( ( ) => {
94
+ offscreenScene . add ( offscreenMesh . current ! ) ;
95
+ } , [ offscreenScene ] ) ;
96
+
57
97
useFrame ( ( props ) => {
58
98
const noise = updateNoise ( props ) ;
59
99
const fluid = updateFluid ( props ) ;
@@ -69,34 +109,184 @@ export const Home = () => {
69
109
noise : noise ,
70
110
} ) ;
71
111
ref . current ! . uniforms . u_fx . value = colorStrata ;
112
+ ref . current ! . uniforms . u_texture . value = updateRenderTarget ( props . gl ) ;
72
113
} ) ;
73
114
74
115
return (
75
- < mesh >
76
- < planeGeometry args = { [ 2 , 2 ] } />
77
- < shaderMaterial
78
- ref = { ref }
79
- vertexShader = { `
116
+ < >
117
+ < mesh ref = { offscreenMesh } >
118
+ < ambientLight intensity = { Math . PI } />
119
+ < spotLight
120
+ position = { [ 10 , 10 , 10 ] }
121
+ angle = { 0.15 }
122
+ penumbra = { 1 }
123
+ decay = { 0 }
124
+ intensity = { Math . PI }
125
+ />
126
+ < pointLight
127
+ position = { [ - 10 , - 10 , - 10 ] }
128
+ decay = { 0 }
129
+ intensity = { Math . PI }
130
+ />
131
+ < Box position = { [ - 1.5 , 0 , 0 ] } />
132
+ < Box position = { [ 1.5 , 0 , 0 ] } />
133
+ </ mesh >
134
+ < mesh >
135
+ < planeGeometry args = { [ 2 , 2 ] } />
136
+ < shaderMaterial
137
+ ref = { ref }
138
+ transparent
139
+ vertexShader = { `
80
140
varying vec2 vUv;
81
141
void main() {
82
142
vUv = uv;
83
143
gl_Position = vec4(position, 1.0);
84
144
}
85
145
` }
86
- fragmentShader = { `
146
+ fragmentShader = { `
87
147
precision highp float;
88
148
varying vec2 vUv;
89
149
uniform sampler2D u_fx;
150
+ uniform sampler2D u_texture;
90
151
91
152
void main() {
92
153
vec2 uv = vUv;
93
- gl_FragColor = texture2D(u_fx, uv);
154
+ vec3 noiseMap = texture2D(u_fx, uv).rgb;
155
+ vec3 nNoiseMap = noiseMap * 2.0 - 1.0;
156
+ uv = uv * 2.0 - 1.0;
157
+ uv *= mix(vec2(1.0), abs(nNoiseMap.rg), 1.);
158
+ uv = (uv + 1.0) / 2.0;
159
+
160
+ vec3 texColor = texture2D(u_texture, uv).rgb;
161
+ vec3 color = mix(texColor,noiseMap,0.5);
162
+
163
+ float luminance = length(color);
164
+
165
+ float edge0 = 0.0;
166
+ float edge1 = .2;
167
+ float alpha = smoothstep(edge0, edge1, luminance);
168
+
169
+ gl_FragColor = vec4(color,alpha);
170
+
94
171
}
95
172
` }
96
- uniforms = { {
97
- u_fx : { value : null } ,
98
- } }
99
- />
100
- </ mesh >
173
+ uniforms = { {
174
+ u_texture : { value : null } ,
175
+ u_fx : { value : null } ,
176
+ } }
177
+ />
178
+ </ mesh >
179
+ </ >
101
180
) ;
102
181
} ;
182
+
183
+ // import * as THREE from "three";
184
+ // import { useEffect, useMemo, useRef, useState } from "react";
185
+ // import { useFrame, useThree } from "@react-three/fiber";
186
+ // import { useNoise, useSingleFBO } from "@/packages/use-shader-fx/src";
187
+
188
+ // function Box(props: any) {
189
+ // // This reference will give us direct access to the mesh
190
+ // const meshRef = useRef<THREE.Mesh>();
191
+ // // Set up state for the hovered and active state
192
+ // const [hovered, setHover] = useState(false);
193
+ // const [active, setActive] = useState(false);
194
+ // // Subscribe this component to the render-loop, rotate the mesh every frame
195
+ // useFrame((state, delta) => (meshRef.current!.rotation.x += delta));
196
+ // // Return view, these are regular three.js elements expressed in JSX
197
+ // return (
198
+ // <mesh
199
+ // {...props}
200
+ // ref={meshRef}
201
+ // scale={active ? 1.5 : 1}
202
+ // onClick={(event) => setActive(!active)}
203
+ // onPointerOver={(event) => setHover(true)}
204
+ // onPointerOut={(event) => setHover(false)}>
205
+ // <boxGeometry args={[1, 1, 1]} />
206
+ // <meshStandardMaterial color={hovered ? "hotpink" : "orange"} />
207
+ // </mesh>
208
+ // );
209
+ // }
210
+
211
+ // export const Home = () => {
212
+ // const { size, viewport, camera, gl } = useThree();
213
+
214
+ // // This scene is rendered offscreen
215
+ // const offscreenScene = useMemo(() => new THREE.Scene(), []);
216
+ // const offscreenMesh = useRef<THREE.Mesh>(null);
217
+ // // create FBO for offscreen rendering
218
+ // const [_, updateRenderTarget] = useSingleFBO({
219
+ // scene: offscreenScene,
220
+ // camera,
221
+ // size,
222
+ // dpr: viewport.dpr,
223
+ // });
224
+ // useEffect(() => {
225
+ // offscreenScene.add(offscreenMesh.current!);
226
+ // }, [offscreenScene]);
227
+
228
+ // // generate noise
229
+ // const shaderMaterial = useRef<THREE.ShaderMaterial>(null);
230
+ // const [updateNoise] = useNoise({ size, dpr: viewport.dpr });
231
+
232
+ // useFrame((props) => {
233
+ // shaderMaterial.current!.uniforms.u_fx.value = updateNoise(props);
234
+ // shaderMaterial.current!.uniforms.u_texture.value = updateRenderTarget(gl);
235
+ // });
236
+
237
+ // return (
238
+ // <>
239
+ // <mesh ref={offscreenMesh}>
240
+ // <ambientLight intensity={Math.PI / 2} />
241
+ // <spotLight
242
+ // position={[10, 10, 10]}
243
+ // angle={0.15}
244
+ // penumbra={1}
245
+ // decay={0}
246
+ // intensity={Math.PI}
247
+ // />
248
+ // <pointLight
249
+ // position={[-10, -10, -10]}
250
+ // decay={0}
251
+ // intensity={Math.PI}
252
+ // />
253
+ // <Box position={[-1.2, 0, 0]} />
254
+ // <Box position={[1.2, 0, 0]} />
255
+ // </mesh>
256
+ // <mesh>
257
+ // <planeGeometry args={[2, 2]} />
258
+ // <shaderMaterial
259
+ // ref={shaderMaterial}
260
+ // transparent
261
+ // vertexShader={`
262
+ // varying vec2 vUv;
263
+ // void main() {
264
+ // vUv = uv;
265
+ // gl_Position = vec4(position, 1.0);
266
+ // }
267
+ // `}
268
+ // fragmentShader={`
269
+ // precision highp float;
270
+ // varying vec2 vUv;
271
+ // uniform sampler2D u_fx;
272
+ // uniform sampler2D u_texture;
273
+
274
+ // void main() {
275
+ // vec2 uv = vUv;
276
+ // vec3 noiseMap = texture2D(u_fx, uv).rgb;
277
+ // vec3 nNoiseMap = noiseMap * 2.0 - 1.0;
278
+ // uv = uv * 2.0 - 1.0;
279
+ // uv *= mix(vec2(1.0), abs(nNoiseMap.rg), .6);
280
+ // uv = (uv + 1.0) / 2.0;
281
+ // gl_FragColor = texture2D(u_texture, uv);
282
+ // }
283
+ // `}
284
+ // uniforms={{
285
+ // u_texture: { value: null },
286
+ // u_fx: { value: null },
287
+ // }}
288
+ // />
289
+ // </mesh>
290
+ // </>
291
+ // );
292
+ // };
0 commit comments