@react-three/drei 9.74.16 → 9.76.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +135 -9
- package/core/CameraControls.cjs.js +1 -1
- package/core/CameraControls.d.ts +1 -1
- package/core/CameraControls.js +20 -3
- package/core/CubeCamera.d.ts +1 -1
- package/core/MeshPortalMaterial.cjs.js +1 -1
- package/core/MeshPortalMaterial.d.ts +6 -1
- package/core/MeshPortalMaterial.js +122 -10
- package/index.cjs.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -157,7 +157,7 @@ The `native` route of the library **does not** export `Html` or `Loader`. The de
|
|
|
157
157
|
<li><a href="#view">View</a></li>
|
|
158
158
|
<li><a href="#rendertexture">RenderTexture</a></li>
|
|
159
159
|
<li><a href="#mask">Mask</a></li>
|
|
160
|
-
<li><a href="#
|
|
160
|
+
<li><a href="#meshportalmaterial">MeshPortalMaterial</a></li>
|
|
161
161
|
</ul>
|
|
162
162
|
<li><a href="#modifiers">Modifiers</a></li>
|
|
163
163
|
<ul>
|
|
@@ -609,7 +609,7 @@ The camera follows your face.
|
|
|
609
609
|
<a href="https://codesandbox.io/s/zhjbhy"><img width="20%" src="https://github-production-user-asset-6210df.s3.amazonaws.com/76580/244052845-5cc535d7-3c97-46e3-a267-52e707c2d9b2.png" alt="demo"/></a>
|
|
610
610
|
</p>
|
|
611
611
|
|
|
612
|
-
Pre-requisite: wrap into a `FaceLandmarker` provider
|
|
612
|
+
Pre-requisite: wrap into a [`FaceLandmarker`](#facelandmarker) provider
|
|
613
613
|
|
|
614
614
|
```tsx
|
|
615
615
|
<FaceLandmarker>...</FaceLandmarker>
|
|
@@ -675,7 +675,73 @@ type FaceControlsApi = THREE.EventDispatcher & {
|
|
|
675
675
|
}
|
|
676
676
|
```
|
|
677
677
|
|
|
678
|
-
|
|
678
|
+
##### FaceControls events
|
|
679
|
+
|
|
680
|
+
Two `THREE.Event`s are dispatched on FaceControls ref object:
|
|
681
|
+
|
|
682
|
+
- `{ type: "stream", stream: MediaStream }` -- when webcam's `.getUserMedia()` stream begins
|
|
683
|
+
- `{ type: "videoFrame", texture: THREE.VideoTexture, time: number }` -- each time a new video frame is sent to the compositor (thanks to rVFC)
|
|
684
|
+
|
|
685
|
+
> **Note** <br>rVFC
|
|
686
|
+
>
|
|
687
|
+
> Internally, `FaceControls` uses [`requestVideoFrameCallback`](https://caniuse.com/mdn-api_htmlvideoelement_requestvideoframecallback), you may need [a polyfill](https://github.com/ThaUnknown/rvfc-polyfill) (for Firefox).
|
|
688
|
+
|
|
689
|
+
##### FaceControls[manualDetect]
|
|
690
|
+
|
|
691
|
+
By default, `detect` is called on each `"videoFrame"`. You can disable this by `manualDetect` and call `detect` yourself.
|
|
692
|
+
|
|
693
|
+
For example:
|
|
694
|
+
|
|
695
|
+
```jsx
|
|
696
|
+
const controls = useThree((state) => state.controls)
|
|
697
|
+
|
|
698
|
+
const onVideoFrame = useCallback((event) => {
|
|
699
|
+
controls.detect(event.texture.source.data, event.time)
|
|
700
|
+
}, [controls])
|
|
701
|
+
|
|
702
|
+
<FaceControls makeDefault
|
|
703
|
+
manualDetect
|
|
704
|
+
onVideoFrame={onVideoFrame}
|
|
705
|
+
/>
|
|
706
|
+
```
|
|
707
|
+
|
|
708
|
+
##### FaceControls[manualUpdate]
|
|
709
|
+
|
|
710
|
+
By default, `update` is called each rAF `useFrame` frame, with damping. You can disable this by `manualUpdate` and update the camera yourself.
|
|
711
|
+
|
|
712
|
+
For example:
|
|
713
|
+
|
|
714
|
+
```jsx
|
|
715
|
+
const controls = useThree((state) => state.controls)
|
|
716
|
+
|
|
717
|
+
const [current] = useState(() => new THREE.Object3D())
|
|
718
|
+
|
|
719
|
+
useFrame((_, delta) => {
|
|
720
|
+
const target = controls?.computeTarget()
|
|
721
|
+
|
|
722
|
+
if (target) {
|
|
723
|
+
//
|
|
724
|
+
// A. Define your own damping
|
|
725
|
+
//
|
|
726
|
+
|
|
727
|
+
const eps = 1e-9
|
|
728
|
+
easing.damp3(current.position, target.position, .25, delta, undefined, undefined, eps)
|
|
729
|
+
easing.dampE(current.rotation, target.rotation, .25, delta, undefined, undefined, eps)
|
|
730
|
+
camera.position.copy(current.position)
|
|
731
|
+
camera.rotation.copy(current.rotation)
|
|
732
|
+
|
|
733
|
+
//
|
|
734
|
+
// B. Or maybe with no damping at all?
|
|
735
|
+
//
|
|
736
|
+
|
|
737
|
+
// controls.update(delta, target)
|
|
738
|
+
// camera.position.copy(target.position)
|
|
739
|
+
// camera.rotation.copy(target.rotation)
|
|
740
|
+
}
|
|
741
|
+
})
|
|
742
|
+
|
|
743
|
+
<FaceControls makeDefault manualUpdate />
|
|
744
|
+
```
|
|
679
745
|
|
|
680
746
|
# Gizmos
|
|
681
747
|
|
|
@@ -2544,6 +2610,46 @@ const buffer = useSurfaceSampler(
|
|
|
2544
2610
|
|
|
2545
2611
|
A @mediapipe/tasks-vision [`FaceLandmarker`](https://developers.google.com/mediapipe/api/solutions/js/tasks-vision.facelandmarker) provider, as well as a `useFaceLandmarker` hook.
|
|
2546
2612
|
|
|
2613
|
+
```tsx
|
|
2614
|
+
<FaceLandmarker>{/* ... */}</FaceLandmarker>
|
|
2615
|
+
```
|
|
2616
|
+
|
|
2617
|
+
It will instanciate a FaceLandmarker object with the following defaults:
|
|
2618
|
+
|
|
2619
|
+
```tsx
|
|
2620
|
+
{
|
|
2621
|
+
basePath: "https://cdn.jsdelivr.net/npm/@mediapipe/tasks-vision@x.y.z/wasm", // x.y.z will value the @mediapipe/tasks-vision version, eg: 0.10.2
|
|
2622
|
+
options: {
|
|
2623
|
+
baseOptions: {
|
|
2624
|
+
modelAssetPath: "https://storage.googleapis.com/mediapipe-models/face_landmarker/face_landmarker/float16/1/face_landmarker.task",
|
|
2625
|
+
delegate: "GPU",
|
|
2626
|
+
},
|
|
2627
|
+
runningMode: "VIDEO",
|
|
2628
|
+
outputFaceBlendshapes: true,
|
|
2629
|
+
outputFacialTransformationMatrixes: true,
|
|
2630
|
+
}
|
|
2631
|
+
}
|
|
2632
|
+
```
|
|
2633
|
+
|
|
2634
|
+
You can override defaults, like for example self-host tasks-vision's `wasm/` and `face_landmarker.task` model in you `public/` directory:
|
|
2635
|
+
|
|
2636
|
+
```sh
|
|
2637
|
+
$ ln -s ../node_modules/@mediapipe/tasks-vision/wasm/ public/tasks-vision-wasm
|
|
2638
|
+
$ curl https://storage.googleapis.com/mediapipe-models/face_landmarker/face_landmarker/float16/1/face_landmarker.task -o public/face_landmarker.task
|
|
2639
|
+
```
|
|
2640
|
+
|
|
2641
|
+
```tsx
|
|
2642
|
+
import { FaceLandmarkerDefaults } from '@react-three/drei'
|
|
2643
|
+
|
|
2644
|
+
const visionBasePath = new URL("/tasks-vision-wasm", import.meta.url).toString()
|
|
2645
|
+
const modelAssetPath = new URL("/face_landmarker.task", import.meta.url).toString()
|
|
2646
|
+
|
|
2647
|
+
const faceLandmarkerOptions = { ...FaceLandmarkerDefaults.options };
|
|
2648
|
+
faceLandmarkerOptions.baseOptions.modelAssetPath = modelAssetPath;
|
|
2649
|
+
|
|
2650
|
+
<FaceLandmarker basePath={visionBasePath} options={faceLandmarkerOptions}>
|
|
2651
|
+
```
|
|
2652
|
+
|
|
2547
2653
|
# Loading
|
|
2548
2654
|
|
|
2549
2655
|
#### Loader
|
|
@@ -2624,12 +2730,19 @@ useGLTF.preload(url)
|
|
|
2624
2730
|
> You can accomplish this by adding two `<link>` tags to your `<head>` tag, as below. The version in those URLs must exactly match what [useGLTF](src/core/useGLTF.tsx#L18) uses for this to work. If you're using create-react-app, `public/index.html` file contains the `<head>` tag.
|
|
2625
2731
|
>
|
|
2626
2732
|
> ```html
|
|
2627
|
-
> <link
|
|
2628
|
-
>
|
|
2733
|
+
> <link
|
|
2734
|
+
> rel="prefetch"
|
|
2735
|
+
> crossorigin="anonymous"
|
|
2736
|
+
> href="https://www.gstatic.com/draco/versioned/decoders/1.5.5/draco_wasm_wrapper.js"
|
|
2737
|
+
> />
|
|
2738
|
+
> <link
|
|
2739
|
+
> rel="prefetch"
|
|
2740
|
+
> crossorigin="anonymous"
|
|
2741
|
+
> href="https://www.gstatic.com/draco/versioned/decoders/1.5.5/draco_decoder.wasm"
|
|
2742
|
+
> />
|
|
2629
2743
|
> ```
|
|
2630
2744
|
>
|
|
2631
2745
|
> It is recommended that you check your browser's network tab to confirm that the correct URLs are being used, and that the files do get loaded from the prefetch cache on subsequent requests.
|
|
2632
|
-
|
|
2633
2746
|
|
|
2634
2747
|
#### useFBX
|
|
2635
2748
|
|
|
@@ -3338,14 +3451,19 @@ Invert masks individually by providing a 2nd boolean argument to the `useMask` h
|
|
|
3338
3451
|
const stencil = useMask(1, true)
|
|
3339
3452
|
```
|
|
3340
3453
|
|
|
3341
|
-
####
|
|
3454
|
+
#### MeshPortalMaterial
|
|
3342
3455
|
|
|
3343
3456
|
<p>
|
|
3457
|
+
<a href="https://codesandbox.io/s/9m4tpc"><img width="20%" src="https://codesandbox.io/api/v1/sandboxes/9m4tpc/screenshot.png" alt="Demo"/></a>
|
|
3458
|
+
<a href="https://codesandbox.io/s/drc6qg"><img width="20%" src="https://codesandbox.io/api/v1/sandboxes/drc6qg/screenshot.png" alt="Demo"/></a>
|
|
3344
3459
|
<a href="https://codesandbox.io/s/ik11ln"><img width="20%" src="https://codesandbox.io/api/v1/sandboxes/ik11ln/screenshot.png" alt="Demo"/></a>
|
|
3345
3460
|
</p>
|
|
3346
3461
|
|
|
3347
3462
|
```tsx
|
|
3348
|
-
export type PortalProps = JSX.IntrinsicElements['
|
|
3463
|
+
export type PortalProps = JSX.IntrinsicElements['shaderMaterial'] & {
|
|
3464
|
+
/** Mix the portals own scene with the world scene, 0 = world scene render,
|
|
3465
|
+
* 0.5 = both scenes render, 1 = portal scene renders, defaults to 0 */
|
|
3466
|
+
blend?: number
|
|
3349
3467
|
/** Edge fade blur, 0 = no blur (default) */
|
|
3350
3468
|
blur?: number
|
|
3351
3469
|
/** SDF resolution, the smaller the faster is the start-up time (default: 512) */
|
|
@@ -3356,6 +3474,8 @@ export type PortalProps = JSX.IntrinsicElements['portalMaterialImpl'] & {
|
|
|
3356
3474
|
eventPriority?: number
|
|
3357
3475
|
/** Optional render priority, defaults to 0 */
|
|
3358
3476
|
renderPriority?: number
|
|
3477
|
+
/** Optionally diable events inside the portal, defaults to false */
|
|
3478
|
+
events?: boolean
|
|
3359
3479
|
}
|
|
3360
3480
|
```
|
|
3361
3481
|
|
|
@@ -3378,6 +3498,12 @@ You can optionally fade or blur the edges of the portal by providing a `blur` pr
|
|
|
3378
3498
|
<MeshPortalMaterial transparent blur={0.5}>
|
|
3379
3499
|
```
|
|
3380
3500
|
|
|
3501
|
+
It is also possible to _enter_ the portal. If blend is 0 your scene will render as usual, if blend is higher it will start to blend the root scene and the portal scene, if blend is 1 it will only render the portal scene. If you put a ref on the material you can transition entering the portal, for instance lerping blend if the camera is close, or on click.
|
|
3502
|
+
|
|
3503
|
+
```jsx
|
|
3504
|
+
<MeshPortalMaterial blend={1}>
|
|
3505
|
+
```
|
|
3506
|
+
|
|
3381
3507
|
# Staging
|
|
3382
3508
|
|
|
3383
3509
|
#### Center
|
|
@@ -3961,7 +4087,7 @@ Treat the output of the shader like an alpha map where `1` is opaque and `0` is
|
|
|
3961
4087
|
|
|
3962
4088
|
```glsl
|
|
3963
4089
|
gl_FragColor = vec4(vec3(1.), 1.); // Opaque
|
|
3964
|
-
gl_FragColor = vec4(vec3(0.), 1.); //
|
|
4090
|
+
gl_FragColor = vec4(vec3(0.), 1.); // Transparent
|
|
3965
4091
|
```
|
|
3966
4092
|
|
|
3967
4093
|
#### Environment
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("@babel/runtime/helpers/extends"),t=require("three"),r=require("react"),n=require("@react-three/fiber"),o=require("camera-controls");function
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("@babel/runtime/helpers/extends"),t=require("three"),r=require("react"),n=require("@react-three/fiber"),o=require("camera-controls");function a(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}function s(e){if(e&&e.__esModule)return e;var t=Object.create(null);return e&&Object.keys(e).forEach((function(r){if("default"!==r){var n=Object.getOwnPropertyDescriptor(e,r);Object.defineProperty(t,r,n.get?n:{enumerable:!0,get:function(){return e[r]}})}})),t.default=e,Object.freeze(t)}var c=a(e),u=s(r),i=a(o);const l=r.forwardRef(((e,o)=>{r.useMemo((()=>{const e={Box3:t.Box3,MathUtils:{clamp:t.MathUtils.clamp},Matrix4:t.Matrix4,Quaternion:t.Quaternion,Raycaster:t.Raycaster,Sphere:t.Sphere,Spherical:t.Spherical,Vector2:t.Vector2,Vector3:t.Vector3,Vector4:t.Vector4};i.default.install({THREE:e}),n.extend({CameraControlsImpl:i.default})}),[]);const{camera:a,domElement:s,makeDefault:l,onStart:d,onEnd:f,onChange:m,regress:v,...E}=e,p=n.useThree((e=>e.camera)),h=n.useThree((e=>e.gl)),b=n.useThree((e=>e.invalidate)),L=n.useThree((e=>e.events)),T=n.useThree((e=>e.setEvents)),g=n.useThree((e=>e.set)),j=n.useThree((e=>e.get)),x=n.useThree((e=>e.performance)),M=a||p,y=s||L.connected||h.domElement,O=r.useMemo((()=>new i.default(M)),[M]);return n.useFrame(((e,t)=>{O.enabled&&O.update(t)}),-1),r.useEffect((()=>(O.connect(y),()=>{O.disconnect()})),[y,O]),r.useEffect((()=>{const e=e=>{b(),v&&x.regress(),m&&m(e)},t=e=>{d&&d(e)},r=e=>{f&&f(e)};return O.addEventListener("update",e),O.addEventListener("controlstart",t),O.addEventListener("controlend",r),O.addEventListener("control",e),O.addEventListener("transitionstart",e),O.addEventListener("wake",e),()=>{O.removeEventListener("update",e),O.removeEventListener("controlstart",t),O.removeEventListener("controlend",r),O.removeEventListener("control",e),O.removeEventListener("transitionstart",e),O.removeEventListener("wake",e)}}),[O,d,f,b,T,v,m]),r.useEffect((()=>{if(l){const e=j().controls;return g({controls:O}),()=>g({controls:e})}}),[l,O]),u.createElement("primitive",c.default({ref:o,object:O},E))}));exports.CameraControls=l;
|
package/core/CameraControls.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { OrthographicCamera, PerspectiveCamera } from 'three';
|
|
2
2
|
import * as React from 'react';
|
|
3
3
|
import { ReactThreeFiber } from '@react-three/fiber';
|
|
4
4
|
import CameraControlsImpl from 'camera-controls';
|
package/core/CameraControls.js
CHANGED
|
@@ -1,14 +1,31 @@
|
|
|
1
1
|
import _extends from '@babel/runtime/helpers/esm/extends';
|
|
2
|
-
import
|
|
2
|
+
import { Box3, MathUtils, Matrix4, Quaternion, Raycaster, Sphere, Spherical, Vector2, Vector3, Vector4 } from 'three';
|
|
3
3
|
import * as React from 'react';
|
|
4
4
|
import { forwardRef, useMemo, useEffect } from 'react';
|
|
5
5
|
import { extend, useThree, useFrame } from '@react-three/fiber';
|
|
6
6
|
import CameraControlsImpl from 'camera-controls';
|
|
7
7
|
|
|
8
8
|
const CameraControls = /*#__PURE__*/forwardRef((props, ref) => {
|
|
9
|
+
// useMemo is used here instead of useEffect, otherwise the useMemo below runs first and throws
|
|
9
10
|
useMemo(() => {
|
|
11
|
+
// to allow for tree shaking, we only import the subset of THREE that is used by camera-controls
|
|
12
|
+
// see https://github.com/yomotsu/camera-controls#important
|
|
13
|
+
const subsetOfTHREE = {
|
|
14
|
+
Box3,
|
|
15
|
+
MathUtils: {
|
|
16
|
+
clamp: MathUtils.clamp
|
|
17
|
+
},
|
|
18
|
+
Matrix4,
|
|
19
|
+
Quaternion,
|
|
20
|
+
Raycaster,
|
|
21
|
+
Sphere,
|
|
22
|
+
Spherical,
|
|
23
|
+
Vector2,
|
|
24
|
+
Vector3,
|
|
25
|
+
Vector4
|
|
26
|
+
};
|
|
10
27
|
CameraControlsImpl.install({
|
|
11
|
-
THREE
|
|
28
|
+
THREE: subsetOfTHREE
|
|
12
29
|
});
|
|
13
30
|
extend({
|
|
14
31
|
CameraControlsImpl
|
|
@@ -42,7 +59,7 @@ const CameraControls = /*#__PURE__*/forwardRef((props, ref) => {
|
|
|
42
59
|
controls.connect(explDomElement);
|
|
43
60
|
return () => void controls.disconnect();
|
|
44
61
|
}, [explDomElement, controls]);
|
|
45
|
-
|
|
62
|
+
useEffect(() => {
|
|
46
63
|
const callback = e => {
|
|
47
64
|
invalidate();
|
|
48
65
|
if (regress) performance.regress();
|
package/core/CubeCamera.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Texture } from 'three';
|
|
2
2
|
import * as React from 'react';
|
|
3
3
|
import { CubeCameraOptions } from './useCubeCamera';
|
|
4
|
-
declare type Props = JSX.IntrinsicElements['group'] & {
|
|
4
|
+
declare type Props = Omit<JSX.IntrinsicElements['group'], 'children'> & {
|
|
5
5
|
children: (tex: Texture) => React.ReactNode;
|
|
6
6
|
frames?: number;
|
|
7
7
|
} & CubeCameraOptions;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("@babel/runtime/helpers/extends"),r=require("three"),t=require("react"),n=require("@react-three/fiber"),a=require("./useFBO.cjs.js"),i=require("./RenderTexture.cjs.js"),l=require("./shaderMaterial.cjs.js"),o=require("three-stdlib");function u(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}function s(e){if(e&&e.__esModule)return e;var r=Object.create(null);return e&&Object.keys(e).forEach((function(t){if("default"!==t){var n=Object.getOwnPropertyDescriptor(e,t);Object.defineProperty(r,t,n.get?n:{enumerable:!0,get:function(){return e[t]}})}})),r.default=e,Object.freeze(r)}var v=u(e),m=s(r),d=s(t);const c=l.shaderMaterial({blur:0,map:null,sdf:null,size:0,resolution:new m.Vector2},"varying vec2 vUv;\n void main() {\n gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);\n vUv = uv;\n }","uniform sampler2D sdf;\n uniform sampler2D map;\n uniform float blur;\n uniform float size;\n uniform float time;\n uniform vec2 resolution;\n varying vec2 vUv;\n #include <packing>\n void main() {\n vec2 uv = gl_FragCoord.xy / resolution.xy;\n vec4 t = texture2D(map, uv);\n float k = blur;\n float d = texture2D(sdf, vUv).r/size;\n float alpha = 1.0 - smoothstep(0.0, 1.0, clamp(d/k + 1.0, 0.0, 1.0));\n gl_FragColor = vec4(t.rgb, blur == 0.0 ? t.a : t.a * alpha);\n #include <tonemapping_fragment>\n #include <encodings_fragment>\n }"),f=d.forwardRef((({children:e,blur:r=0,eventPriority:t,renderPriority:l,worldUnits:o=!1,resolution:u=512,...s},f)=>{n.extend({PortalMaterialImpl:c});const p=d.useRef(null),{gl:F,size:h,events:y,viewport:w}=n.useThree(),M=a.useFBO(u,u);return d.useLayoutEffect((()=>{var e;let t=null==(e=p.current)?void 0:e.__r3f.parent;if(t&&r&&null===p.current.sdf){const e=new m.Mesh(t.geometry,new m.MeshBasicMaterial),r=(new m.Box3).setFromBufferAttribute(e.geometry.attributes.position),n=new m.OrthographicCamera(r.min.x*(1+2/u),r.max.x*(1+2/u),r.max.y*(1+2/u),r.min.y*(1+2/u),.1,1e3);n.position.set(0,0,1),n.lookAt(0,0,0),F.setRenderTarget(M),F.render(e,n);const a=g(u,u,F)(M.texture),i=new Float32Array(u*u);F.readRenderTargetPixels(a,0,0,u,u,i);let l=1/0;for(let e=0;e<i.length;e++)i[e]<l&&(l=i[e]);l=-l,p.current.size=l,p.current.sdf=a.texture,F.setRenderTarget(null)}}),[u,r]),d.useImperativeHandle(f,(()=>p.current)),d.createElement("portalMaterialImpl",v.default({ref:p,blur:r,resolution:[h.width*w.dpr,h.height*w.dpr],toneMapped:!1,attach:"material"},s),d.createElement(i.RenderTexture,{attach:"map",eventPriority:t,renderPriority:l,compute:y.compute},e,d.createElement(x,{material:p,worldUnits:o})))}));function x({material:e,worldUnits:r}){const t=n.useThree((e=>e.scene));return d.useLayoutEffect((()=>{t.matrixAutoUpdate=!1}),[]),n.useFrame((()=>{var n;let a=null==e||null==(n=e.current)?void 0:n.__r3f.parent;a&&(r?t.matrixWorld.identity():t.matrixWorld.copy(a.matrixWorld))})),d.createElement(d.Fragment,null)}const g=(e,r,t)=>{let n=new m.WebGLRenderTarget(e,r,{minFilter:m.LinearMipmapLinearFilter,magFilter:m.LinearFilter,type:m.FloatType,format:m.RedFormat,generateMipmaps:!0}),a=new m.WebGLRenderTarget(e,r,{minFilter:m.NearestFilter,magFilter:m.NearestFilter}),i=new m.WebGLRenderTarget(e,r,{minFilter:m.NearestFilter,magFilter:m.NearestFilter}),l=new m.WebGLRenderTarget(e,r,{minFilter:m.NearestFilter,magFilter:m.NearestFilter}),u=new m.WebGLRenderTarget(e,r,{minFilter:m.NearestFilter,magFilter:m.NearestFilter}),s=new m.WebGLRenderTarget(e,r,{minFilter:m.NearestFilter,magFilter:m.NearestFilter,type:m.FloatType,format:m.RedFormat}),v=new m.WebGLRenderTarget(e,r,{minFilter:m.NearestFilter,magFilter:m.NearestFilter,type:m.FloatType,format:m.RedFormat});const d=new o.FullScreenQuad(new m.ShaderMaterial({uniforms:{tex:{value:null}},vertexShader:"\n varying vec2 vUv;\n void main() {\n vUv = uv;\n gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n }",fragmentShader:"\n uniform sampler2D tex;\n varying vec2 vUv;\n #include <packing>\n void main() {\n gl_FragColor = pack2HalfToRGBA(vUv * (round(texture2D(tex, vUv).x)));\n }"})),c=new o.FullScreenQuad(new m.ShaderMaterial({uniforms:{tex:{value:null}},vertexShader:"\n varying vec2 vUv;\n void main() {\n vUv = uv;\n gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n }",fragmentShader:"\n uniform sampler2D tex;\n varying vec2 vUv;\n #include <packing>\n void main() {\n gl_FragColor = pack2HalfToRGBA(vUv * (1.0 - round(texture2D(tex, vUv).x)));\n }"})),f=new o.FullScreenQuad(new m.ShaderMaterial({uniforms:{tex:{value:null},offset:{value:0},level:{value:0},maxSteps:{value:0}},vertexShader:"\n varying vec2 vUv;\n void main() {\n vUv = uv;\n gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n }",fragmentShader:`\n varying vec2 vUv;\n uniform sampler2D tex;\n uniform float offset;\n uniform float level;\n uniform float maxSteps;\n #include <packing>\n void main() {\n float closestDist = 9999999.9;\n vec2 closestPos = vec2(0.0);\n for (float x = -1.0; x <= 1.0; x += 1.0) {\n for (float y = -1.0; y <= 1.0; y += 1.0) {\n vec2 voffset = vUv;\n voffset += vec2(x, y) * vec2(${1/e}, ${1/r}) * offset;\n vec2 pos = unpackRGBATo2Half(texture2D(tex, voffset));\n float dist = distance(pos.xy, vUv);\n if(pos.x != 0.0 && pos.y != 0.0 && dist < closestDist) {\n closestDist = dist;\n closestPos = pos;\n }\n }\n }\n gl_FragColor = pack2HalfToRGBA(closestPos);\n }`})),x=new o.FullScreenQuad(new m.ShaderMaterial({uniforms:{tex:{value:null},size:{value:new m.Vector2(e,r)}},vertexShader:"\n varying vec2 vUv;\n void main() {\n vUv = uv;\n gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n }",fragmentShader:"\n varying vec2 vUv;\n uniform sampler2D tex;\n uniform vec2 size;\n #include <packing>\n void main() {\n gl_FragColor = vec4(distance(size * unpackRGBATo2Half(texture2D(tex, vUv)), size * vUv), 0.0, 0.0, 0.0);\n }"})),g=new o.FullScreenQuad(new m.ShaderMaterial({uniforms:{inside:{value:v.texture},outside:{value:s.texture},tex:{value:null}},vertexShader:"\n varying vec2 vUv;\n void main() {\n vUv = uv;\n gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n }",fragmentShader:"\n varying vec2 vUv;\n uniform sampler2D inside;\n uniform sampler2D outside;\n uniform sampler2D tex;\n #include <packing>\n void main() {\n float i = texture2D(inside, vUv).x;\n float o =texture2D(outside, vUv).x;\n if (texture2D(tex, vUv).x == 0.0) {\n gl_FragColor = vec4(o, 0.0, 0.0, 0.0);\n } else {\n gl_FragColor = vec4(-i, 0.0, 0.0, 0.0);\n }\n }"}));return o=>{let p=n;o.minFilter=m.NearestFilter,o.magFilter=m.NearestFilter,d.material.uniforms.tex.value=o,t.setRenderTarget(a),d.render(t);const F=Math.ceil(Math.log(Math.max(e,r))/Math.log(2));let h=a,y=null;for(let e=0;e<F;e++){const r=Math.pow(2,F-e-1);y=h===a?l:a,f.material.uniforms.level.value=e,f.material.uniforms.maxSteps.value=F,f.material.uniforms.offset.value=r,f.material.uniforms.tex.value=h.texture,t.setRenderTarget(y),f.render(t),h=y}t.setRenderTarget(s),x.material.uniforms.tex.value=y.texture,x.render(t),c.material.uniforms.tex.value=o,t.setRenderTarget(i),c.render(t),h=i;for(let e=0;e<F;e++){const r=Math.pow(2,F-e-1);y=h===i?u:i,f.material.uniforms.level.value=e,f.material.uniforms.maxSteps.value=F,f.material.uniforms.offset.value=r,f.material.uniforms.tex.value=h.texture,t.setRenderTarget(y),f.render(t),h=y}return t.setRenderTarget(v),x.material.uniforms.tex.value=y.texture,x.render(t),t.setRenderTarget(p),g.material.uniforms.tex.value=o,g.render(t),t.setRenderTarget(null),p}};exports.MeshPortalMaterial=f;
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("@babel/runtime/helpers/extends"),r=require("three"),t=require("react"),n=require("@react-three/fiber"),a=require("./useIntersect.cjs.js"),i=require("./useFBO.cjs.js"),l=require("./RenderTexture.cjs.js"),o=require("./shaderMaterial.cjs.js"),u=require("three-stdlib");function s(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}function v(e){if(e&&e.__esModule)return e;var r=Object.create(null);return e&&Object.keys(e).forEach((function(t){if("default"!==t){var n=Object.getOwnPropertyDescriptor(e,t);Object.defineProperty(r,t,n.get?n:{enumerable:!0,get:function(){return e[t]}})}})),r.default=e,Object.freeze(r)}var c=s(e),d=v(r),m=v(t);const f=o.shaderMaterial({blur:0,map:null,sdf:null,blend:0,size:0,resolution:new d.Vector2},"varying vec2 vUv;\n void main() {\n gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);\n vUv = uv;\n }","uniform sampler2D sdf;\n uniform sampler2D map;\n uniform float blur;\n uniform float size;\n uniform float time;\n uniform vec2 resolution;\n varying vec2 vUv;\n #include <packing>\n void main() {\n vec2 uv = gl_FragCoord.xy / resolution.xy;\n vec4 t = texture2D(map, uv);\n float k = blur;\n float d = texture2D(sdf, vUv).r/size;\n float alpha = 1.0 - smoothstep(0.0, 1.0, clamp(d/k + 1.0, 0.0, 1.0));\n gl_FragColor = vec4(t.rgb, blur == 0.0 ? t.a : t.a * alpha);\n #include <tonemapping_fragment>\n #include <encodings_fragment>\n }"),g=m.forwardRef((({children:e,events:r,blur:t=0,eventPriority:o=0,renderPriority:u=0,worldUnits:s=!1,resolution:v=512,...g},F)=>{n.extend({PortalMaterialImpl:f});const h=m.useRef(null),{scene:y,gl:b,size:w,viewport:M,setEvents:U}=n.useThree(),T=i.useFBO(v,v),[R,S]=m.useState(0);n.useFrame((()=>{const e=h.current.blend>0?Math.max(1,u):0;R!==e&&S(e)})),m.useEffect((()=>{void 0!==r&&U({enabled:!r})}),[r]);const[_,D]=m.useState(!0),j=a.useIntersect(D);m.useLayoutEffect((()=>{var e;j.current=null==(e=h.current)?void 0:e.__r3f.parent}),[]),m.useLayoutEffect((()=>{if(j.current&&t&&null===h.current.sdf){const e=new d.Mesh(j.current.geometry,new d.MeshBasicMaterial),r=(new d.Box3).setFromBufferAttribute(e.geometry.attributes.position),t=new d.OrthographicCamera(r.min.x*(1+2/v),r.max.x*(1+2/v),r.max.y*(1+2/v),r.min.y*(1+2/v),.1,1e3);t.position.set(0,0,1),t.lookAt(0,0,0),b.setRenderTarget(T),b.render(e,t);const n=p(v,v,b)(T.texture),a=new Float32Array(v*v);b.readRenderTargetPixels(n,0,0,v,v,a);let i=1/0;for(let e=0;e<a.length;e++)a[e]<i&&(i=a[e]);i=-i,h.current.size=i,h.current.sdf=n.texture,b.setRenderTarget(null)}}),[v,t]),m.useImperativeHandle(F,(()=>h.current));const P=m.useCallback(((e,r,t)=>{var n;if(!j.current)return!1;if(r.pointer.set(e.offsetX/r.size.width*2-1,-e.offsetY/r.size.height*2+1),r.raycaster.setFromCamera(r.pointer,r.camera),0===(null==(n=h.current)?void 0:n.blend)){const[e]=r.raycaster.intersectObject(j.current);if(!e)return r.raycaster.camera=void 0,!1}}),[]);return m.createElement("portalMaterialImpl",c.default({ref:h,blur:t,blend:0,resolution:[w.width*M.dpr,w.height*M.dpr],toneMapped:!1,attach:"material"},g),m.createElement(l.RenderTexture,{attach:"map",frames:_?1/0:0,eventPriority:o,renderPriority:u,compute:P},e,m.createElement(x,{events:r,rootScene:y,priority:R,material:h,worldUnits:s})))}));function x({events:e,rootScene:r,material:t,priority:a,worldUnits:l}){const o=n.useThree((e=>e.scene)),s=n.useThree((e=>e.setEvents)),v=i.useFBO(),c=i.useFBO();m.useLayoutEffect((()=>{o.matrixAutoUpdate=!1}),[]),m.useEffect((()=>{void 0!==e&&s({enabled:e})}),[e]);const[f,g]=m.useMemo((()=>{const e={value:0};return[new u.FullScreenQuad(new d.ShaderMaterial({uniforms:{a:{value:v.texture},b:{value:c.texture},blend:e},vertexShader:"\n varying vec2 vUv;\n void main() {\n vUv = uv;\n gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n }",fragmentShader:"\n uniform sampler2D a;\n uniform sampler2D b;\n uniform float blend;\n varying vec2 vUv;\n #include <packing>\n void main() {\n vec4 ta = texture2D(a, vUv);\n vec4 tb = texture2D(b, vUv);\n gl_FragColor = mix(tb, ta, blend);\n #include <encodings_fragment>\n }"})),e]}),[]);return n.useFrame((e=>{var n;let i=null==t||null==(n=t.current)?void 0:n.__r3f.parent;var u,s,d;i&&(l?o.matrixWorld.identity():o.matrixWorld.copy(i.matrixWorld),a&&((null==(u=t.current)?void 0:u.blend)>0&&(null==(s=t.current)?void 0:s.blend)<1&&i?(g.value=t.current.blend,e.gl.setRenderTarget(v),e.gl.render(o,e.camera),e.gl.setRenderTarget(c),e.gl.render(r,e.camera),e.gl.setRenderTarget(null),f.render(e.gl)):1===(null==(d=t.current)?void 0:d.blend)&&e.gl.render(o,e.camera)))}),a),m.createElement(m.Fragment,null)}const p=(e,r,t)=>{let n=new d.WebGLRenderTarget(e,r,{minFilter:d.LinearMipmapLinearFilter,magFilter:d.LinearFilter,type:d.FloatType,format:d.RedFormat,generateMipmaps:!0}),a=new d.WebGLRenderTarget(e,r,{minFilter:d.NearestFilter,magFilter:d.NearestFilter}),i=new d.WebGLRenderTarget(e,r,{minFilter:d.NearestFilter,magFilter:d.NearestFilter}),l=new d.WebGLRenderTarget(e,r,{minFilter:d.NearestFilter,magFilter:d.NearestFilter}),o=new d.WebGLRenderTarget(e,r,{minFilter:d.NearestFilter,magFilter:d.NearestFilter}),s=new d.WebGLRenderTarget(e,r,{minFilter:d.NearestFilter,magFilter:d.NearestFilter,type:d.FloatType,format:d.RedFormat}),v=new d.WebGLRenderTarget(e,r,{minFilter:d.NearestFilter,magFilter:d.NearestFilter,type:d.FloatType,format:d.RedFormat});const c=new u.FullScreenQuad(new d.ShaderMaterial({uniforms:{tex:{value:null}},vertexShader:"\n varying vec2 vUv;\n void main() {\n vUv = uv;\n gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n }",fragmentShader:"\n uniform sampler2D tex;\n varying vec2 vUv;\n #include <packing>\n void main() {\n gl_FragColor = pack2HalfToRGBA(vUv * (round(texture2D(tex, vUv).x)));\n }"})),m=new u.FullScreenQuad(new d.ShaderMaterial({uniforms:{tex:{value:null}},vertexShader:"\n varying vec2 vUv;\n void main() {\n vUv = uv;\n gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n }",fragmentShader:"\n uniform sampler2D tex;\n varying vec2 vUv;\n #include <packing>\n void main() {\n gl_FragColor = pack2HalfToRGBA(vUv * (1.0 - round(texture2D(tex, vUv).x)));\n }"})),f=new u.FullScreenQuad(new d.ShaderMaterial({uniforms:{tex:{value:null},offset:{value:0},level:{value:0},maxSteps:{value:0}},vertexShader:"\n varying vec2 vUv;\n void main() {\n vUv = uv;\n gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n }",fragmentShader:`\n varying vec2 vUv;\n uniform sampler2D tex;\n uniform float offset;\n uniform float level;\n uniform float maxSteps;\n #include <packing>\n void main() {\n float closestDist = 9999999.9;\n vec2 closestPos = vec2(0.0);\n for (float x = -1.0; x <= 1.0; x += 1.0) {\n for (float y = -1.0; y <= 1.0; y += 1.0) {\n vec2 voffset = vUv;\n voffset += vec2(x, y) * vec2(${1/e}, ${1/r}) * offset;\n vec2 pos = unpackRGBATo2Half(texture2D(tex, voffset));\n float dist = distance(pos.xy, vUv);\n if(pos.x != 0.0 && pos.y != 0.0 && dist < closestDist) {\n closestDist = dist;\n closestPos = pos;\n }\n }\n }\n gl_FragColor = pack2HalfToRGBA(closestPos);\n }`})),g=new u.FullScreenQuad(new d.ShaderMaterial({uniforms:{tex:{value:null},size:{value:new d.Vector2(e,r)}},vertexShader:"\n varying vec2 vUv;\n void main() {\n vUv = uv;\n gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n }",fragmentShader:"\n varying vec2 vUv;\n uniform sampler2D tex;\n uniform vec2 size;\n #include <packing>\n void main() {\n gl_FragColor = vec4(distance(size * unpackRGBATo2Half(texture2D(tex, vUv)), size * vUv), 0.0, 0.0, 0.0);\n }"})),x=new u.FullScreenQuad(new d.ShaderMaterial({uniforms:{inside:{value:v.texture},outside:{value:s.texture},tex:{value:null}},vertexShader:"\n varying vec2 vUv;\n void main() {\n vUv = uv;\n gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n }",fragmentShader:"\n varying vec2 vUv;\n uniform sampler2D inside;\n uniform sampler2D outside;\n uniform sampler2D tex;\n #include <packing>\n void main() {\n float i = texture2D(inside, vUv).x;\n float o =texture2D(outside, vUv).x;\n if (texture2D(tex, vUv).x == 0.0) {\n gl_FragColor = vec4(o, 0.0, 0.0, 0.0);\n } else {\n gl_FragColor = vec4(-i, 0.0, 0.0, 0.0);\n }\n }"}));return u=>{let p=n;u.minFilter=d.NearestFilter,u.magFilter=d.NearestFilter,c.material.uniforms.tex.value=u,t.setRenderTarget(a),c.render(t);const F=Math.ceil(Math.log(Math.max(e,r))/Math.log(2));let h=a,y=null;for(let e=0;e<F;e++){const r=Math.pow(2,F-e-1);y=h===a?l:a,f.material.uniforms.level.value=e,f.material.uniforms.maxSteps.value=F,f.material.uniforms.offset.value=r,f.material.uniforms.tex.value=h.texture,t.setRenderTarget(y),f.render(t),h=y}t.setRenderTarget(s),g.material.uniforms.tex.value=y.texture,g.render(t),m.material.uniforms.tex.value=u,t.setRenderTarget(i),m.render(t),h=i;for(let e=0;e<F;e++){const r=Math.pow(2,F-e-1);y=h===i?o:i,f.material.uniforms.level.value=e,f.material.uniforms.maxSteps.value=F,f.material.uniforms.offset.value=r,f.material.uniforms.tex.value=h.texture,t.setRenderTarget(y),f.render(t),h=y}return t.setRenderTarget(v),g.material.uniforms.tex.value=y.texture,g.render(t),t.setRenderTarget(p),x.material.uniforms.tex.value=u,x.render(t),t.setRenderTarget(null),p}};exports.MeshPortalMaterial=g;
|
|
@@ -4,6 +4,7 @@ import { ReactThreeFiber } from '@react-three/fiber';
|
|
|
4
4
|
export declare type PortalMaterialType = {
|
|
5
5
|
resolution: ReactThreeFiber.Vector2;
|
|
6
6
|
blur: number;
|
|
7
|
+
blend: number;
|
|
7
8
|
size?: number;
|
|
8
9
|
sdf?: THREE.Texture;
|
|
9
10
|
map?: THREE.Texture;
|
|
@@ -16,16 +17,20 @@ declare global {
|
|
|
16
17
|
}
|
|
17
18
|
}
|
|
18
19
|
export declare type PortalProps = JSX.IntrinsicElements['shaderMaterial'] & {
|
|
20
|
+
blend?: number;
|
|
19
21
|
blur?: number;
|
|
20
22
|
resolution?: number;
|
|
21
23
|
worldUnits?: boolean;
|
|
22
24
|
eventPriority?: number;
|
|
23
25
|
renderPriority?: number;
|
|
26
|
+
events?: boolean;
|
|
24
27
|
};
|
|
25
28
|
export declare const MeshPortalMaterial: React.ForwardRefExoticComponent<Pick<ReactThreeFiber.ExtendedColors<ReactThreeFiber.Overwrite<Partial<THREE.ShaderMaterial>, ReactThreeFiber.NodeProps<THREE.ShaderMaterial, [THREE.ShaderMaterialParameters]>>> & {
|
|
29
|
+
blend?: number | undefined;
|
|
26
30
|
blur?: number | undefined;
|
|
27
31
|
resolution?: number | undefined;
|
|
28
32
|
worldUnits?: boolean | undefined;
|
|
29
33
|
eventPriority?: number | undefined;
|
|
30
34
|
renderPriority?: number | undefined;
|
|
31
|
-
|
|
35
|
+
events?: boolean | undefined;
|
|
36
|
+
}, "attach" | "args" | "children" | "key" | "onUpdate" | "events" | keyof THREE.ShaderMaterial | "blur" | "resolution" | "worldUnits" | "renderPriority" | "blend" | "eventPriority"> & React.RefAttributes<PortalMaterialType>>;
|
|
@@ -2,6 +2,7 @@ import _extends from '@babel/runtime/helpers/esm/extends';
|
|
|
2
2
|
import * as THREE from 'three';
|
|
3
3
|
import * as React from 'react';
|
|
4
4
|
import { extend, useThree, useFrame } from '@react-three/fiber';
|
|
5
|
+
import { useIntersect } from './useIntersect.js';
|
|
5
6
|
import { useFBO } from './useFBO.js';
|
|
6
7
|
import { RenderTexture } from './RenderTexture.js';
|
|
7
8
|
import { shaderMaterial } from './shaderMaterial.js';
|
|
@@ -11,6 +12,7 @@ const PortalMaterialImpl = shaderMaterial({
|
|
|
11
12
|
blur: 0,
|
|
12
13
|
map: null,
|
|
13
14
|
sdf: null,
|
|
15
|
+
blend: 0,
|
|
14
16
|
size: 0,
|
|
15
17
|
resolution: new THREE.Vector2()
|
|
16
18
|
}, `varying vec2 vUv;
|
|
@@ -37,9 +39,10 @@ const PortalMaterialImpl = shaderMaterial({
|
|
|
37
39
|
}`);
|
|
38
40
|
const MeshPortalMaterial = /*#__PURE__*/React.forwardRef(({
|
|
39
41
|
children,
|
|
42
|
+
events = undefined,
|
|
40
43
|
blur = 0,
|
|
41
|
-
eventPriority,
|
|
42
|
-
renderPriority,
|
|
44
|
+
eventPriority = 0,
|
|
45
|
+
renderPriority = 0,
|
|
43
46
|
worldUnits = false,
|
|
44
47
|
resolution = 512,
|
|
45
48
|
...props
|
|
@@ -49,20 +52,39 @@ const MeshPortalMaterial = /*#__PURE__*/React.forwardRef(({
|
|
|
49
52
|
});
|
|
50
53
|
const ref = React.useRef(null);
|
|
51
54
|
const {
|
|
55
|
+
scene,
|
|
52
56
|
gl,
|
|
53
57
|
size,
|
|
54
|
-
|
|
55
|
-
|
|
58
|
+
viewport,
|
|
59
|
+
setEvents
|
|
56
60
|
} = useThree();
|
|
57
61
|
const maskRenderTarget = useFBO(resolution, resolution);
|
|
62
|
+
const [priority, setPriority] = React.useState(0);
|
|
63
|
+
useFrame(() => {
|
|
64
|
+
// If blend is > 0 then the portal is being entered, the render-priority must change
|
|
65
|
+
const p = ref.current.blend > 0 ? Math.max(1, renderPriority) : 0;
|
|
66
|
+
if (priority !== p) setPriority(p);
|
|
67
|
+
});
|
|
68
|
+
React.useEffect(() => {
|
|
69
|
+
if (events !== undefined) setEvents({
|
|
70
|
+
enabled: !events
|
|
71
|
+
});
|
|
72
|
+
}, [events]);
|
|
73
|
+
const [visible, setVisible] = React.useState(true); // See if the parent mesh is in the camera frustum
|
|
74
|
+
|
|
75
|
+
const parent = useIntersect(setVisible);
|
|
58
76
|
React.useLayoutEffect(() => {
|
|
59
77
|
var _ref$current;
|
|
60
78
|
|
|
61
|
-
|
|
62
|
-
|
|
79
|
+
// Since the ref above is not tied to a mesh directly (we're inside a material),
|
|
80
|
+
// it has to be tied to the parent mesh here
|
|
81
|
+
parent.current = (_ref$current = ref.current) == null ? void 0 : _ref$current.__r3f.parent;
|
|
82
|
+
}, []);
|
|
83
|
+
React.useLayoutEffect(() => {
|
|
84
|
+
if (!parent.current) return; // Apply the SDF mask only once
|
|
63
85
|
|
|
64
86
|
if (blur && ref.current.sdf === null) {
|
|
65
|
-
const tempMesh = new THREE.Mesh(
|
|
87
|
+
const tempMesh = new THREE.Mesh(parent.current.geometry, new THREE.MeshBasicMaterial());
|
|
66
88
|
const boundingBox = new THREE.Box3().setFromBufferAttribute(tempMesh.geometry.attributes.position);
|
|
67
89
|
const orthoCam = new THREE.OrthographicCamera(boundingBox.min.x * (1 + 2 / resolution), boundingBox.max.x * (1 + 2 / resolution), boundingBox.max.y * (1 + 2 / resolution), boundingBox.min.y * (1 + 2 / resolution), 0.1, 1000);
|
|
68
90
|
orthoCam.position.set(0, 0, 1);
|
|
@@ -87,40 +109,130 @@ const MeshPortalMaterial = /*#__PURE__*/React.forwardRef(({
|
|
|
87
109
|
}
|
|
88
110
|
}, [resolution, blur]);
|
|
89
111
|
React.useImperativeHandle(fref, () => ref.current);
|
|
112
|
+
const compute = React.useCallback((event, state, previous) => {
|
|
113
|
+
var _ref$current2;
|
|
114
|
+
|
|
115
|
+
if (!parent.current) return false;
|
|
116
|
+
state.pointer.set(event.offsetX / state.size.width * 2 - 1, -(event.offsetY / state.size.height) * 2 + 1);
|
|
117
|
+
state.raycaster.setFromCamera(state.pointer, state.camera);
|
|
118
|
+
|
|
119
|
+
if (((_ref$current2 = ref.current) == null ? void 0 : _ref$current2.blend) === 0) {
|
|
120
|
+
// We run a quick check against the parent, if it isn't hit there's no need to raycast at all
|
|
121
|
+
const [intersection] = state.raycaster.intersectObject(parent.current);
|
|
122
|
+
|
|
123
|
+
if (!intersection) {
|
|
124
|
+
// Cancel out the raycast camera if the parent mesh isn't hit
|
|
125
|
+
state.raycaster.camera = undefined;
|
|
126
|
+
return false;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}, []);
|
|
90
130
|
return /*#__PURE__*/React.createElement("portalMaterialImpl", _extends({
|
|
91
131
|
ref: ref,
|
|
92
132
|
blur: blur,
|
|
133
|
+
blend: 0,
|
|
93
134
|
resolution: [size.width * viewport.dpr, size.height * viewport.dpr],
|
|
94
135
|
toneMapped: false,
|
|
95
136
|
attach: "material"
|
|
96
137
|
}, props), /*#__PURE__*/React.createElement(RenderTexture, {
|
|
97
138
|
attach: "map",
|
|
139
|
+
frames: visible ? Infinity : 0,
|
|
98
140
|
eventPriority: eventPriority,
|
|
99
141
|
renderPriority: renderPriority,
|
|
100
|
-
compute:
|
|
142
|
+
compute: compute
|
|
101
143
|
}, children, /*#__PURE__*/React.createElement(CopyMatrix, {
|
|
144
|
+
events: events,
|
|
145
|
+
rootScene: scene,
|
|
146
|
+
priority: priority,
|
|
102
147
|
material: ref,
|
|
103
148
|
worldUnits: worldUnits
|
|
104
149
|
})));
|
|
105
150
|
});
|
|
106
151
|
|
|
107
152
|
function CopyMatrix({
|
|
153
|
+
events = undefined,
|
|
154
|
+
rootScene,
|
|
108
155
|
material,
|
|
156
|
+
priority,
|
|
109
157
|
worldUnits
|
|
110
158
|
}) {
|
|
111
159
|
const scene = useThree(state => state.scene);
|
|
160
|
+
const setEvents = useThree(state => state.setEvents);
|
|
161
|
+
const buffer1 = useFBO();
|
|
162
|
+
const buffer2 = useFBO();
|
|
112
163
|
React.useLayoutEffect(() => {
|
|
113
164
|
scene.matrixAutoUpdate = false;
|
|
114
165
|
}, []);
|
|
115
|
-
|
|
166
|
+
React.useEffect(() => {
|
|
167
|
+
if (events !== undefined) setEvents({
|
|
168
|
+
enabled: events
|
|
169
|
+
});
|
|
170
|
+
}, [events]);
|
|
171
|
+
const [quad, blend] = React.useMemo(() => {
|
|
172
|
+
// This fullscree-quad is used to blend the two textures
|
|
173
|
+
const blend = {
|
|
174
|
+
value: 0
|
|
175
|
+
};
|
|
176
|
+
const quad = new FullScreenQuad(new THREE.ShaderMaterial({
|
|
177
|
+
uniforms: {
|
|
178
|
+
a: {
|
|
179
|
+
value: buffer1.texture
|
|
180
|
+
},
|
|
181
|
+
b: {
|
|
182
|
+
value: buffer2.texture
|
|
183
|
+
},
|
|
184
|
+
blend
|
|
185
|
+
},
|
|
186
|
+
vertexShader:
|
|
187
|
+
/*glsl*/
|
|
188
|
+
`
|
|
189
|
+
varying vec2 vUv;
|
|
190
|
+
void main() {
|
|
191
|
+
vUv = uv;
|
|
192
|
+
gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
|
|
193
|
+
}`,
|
|
194
|
+
fragmentShader:
|
|
195
|
+
/*glsl*/
|
|
196
|
+
`
|
|
197
|
+
uniform sampler2D a;
|
|
198
|
+
uniform sampler2D b;
|
|
199
|
+
uniform float blend;
|
|
200
|
+
varying vec2 vUv;
|
|
201
|
+
#include <packing>
|
|
202
|
+
void main() {
|
|
203
|
+
vec4 ta = texture2D(a, vUv);
|
|
204
|
+
vec4 tb = texture2D(b, vUv);
|
|
205
|
+
gl_FragColor = mix(tb, ta, blend);
|
|
206
|
+
#include <encodings_fragment>
|
|
207
|
+
}`
|
|
208
|
+
}));
|
|
209
|
+
return [quad, blend];
|
|
210
|
+
}, []);
|
|
211
|
+
useFrame(state => {
|
|
116
212
|
var _material$current;
|
|
117
213
|
|
|
118
214
|
let parent = material == null ? void 0 : (_material$current = material.current) == null ? void 0 : _material$current.__r3f.parent;
|
|
119
215
|
|
|
120
216
|
if (parent) {
|
|
121
217
|
if (!worldUnits) scene.matrixWorld.copy(parent.matrixWorld);else scene.matrixWorld.identity();
|
|
218
|
+
|
|
219
|
+
if (priority) {
|
|
220
|
+
var _material$current2, _material$current3, _material$current4;
|
|
221
|
+
|
|
222
|
+
if (((_material$current2 = material.current) == null ? void 0 : _material$current2.blend) > 0 && ((_material$current3 = material.current) == null ? void 0 : _material$current3.blend) < 1 && parent) {
|
|
223
|
+
blend.value = material.current.blend;
|
|
224
|
+
state.gl.setRenderTarget(buffer1);
|
|
225
|
+
state.gl.render(scene, state.camera);
|
|
226
|
+
state.gl.setRenderTarget(buffer2);
|
|
227
|
+
state.gl.render(rootScene, state.camera);
|
|
228
|
+
state.gl.setRenderTarget(null);
|
|
229
|
+
quad.render(state.gl);
|
|
230
|
+
} else if (((_material$current4 = material.current) == null ? void 0 : _material$current4.blend) === 1) {
|
|
231
|
+
state.gl.render(scene, state.camera);
|
|
232
|
+
}
|
|
233
|
+
}
|
|
122
234
|
}
|
|
123
|
-
});
|
|
235
|
+
}, priority);
|
|
124
236
|
return /*#__PURE__*/React.createElement(React.Fragment, null);
|
|
125
237
|
}
|
|
126
238
|
|