@react-three/drei 9.74.15 → 9.75.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 +75 -5
- package/core/Caustics.cjs.js +1 -1
- package/core/Caustics.js +32 -16
- 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>
|
|
@@ -2036,7 +2036,7 @@ type ExampleApi = {
|
|
|
2036
2036
|
<a href="https://codesandbox.io/s/qyz5r"><img width="20%" src="https://codesandbox.io/api/v1/sandboxes/qyz5r/screenshot.png" alt="Demo"/></a>
|
|
2037
2037
|
<a href="https://codesandbox.io/s/9keg6"><img width="20%" src="https://codesandbox.io/api/v1/sandboxes/9keg6/screenshot.png" alt="Demo"/></a>
|
|
2038
2038
|
<a href="https://codesandbox.io/s/6oei7"><img width="20%" src="https://codesandbox.io/api/v1/sandboxes/6oei7/screenshot.png" alt="Demo"/></a>
|
|
2039
|
-
<a href="https://codesandbox.io/s/
|
|
2039
|
+
<a href="https://codesandbox.io/s/wp9mkp"><img width="20%" src="https://codesandbox.io/api/v1/sandboxes/wp9mkp/screenshot.png" alt="demo"/></a>
|
|
2040
2040
|
</p>
|
|
2041
2041
|
|
|
2042
2042
|
Allows you to tie HTML content to any object of your scene. It will be projected to the objects whereabouts automatically.
|
|
@@ -2544,6 +2544,46 @@ const buffer = useSurfaceSampler(
|
|
|
2544
2544
|
|
|
2545
2545
|
A @mediapipe/tasks-vision [`FaceLandmarker`](https://developers.google.com/mediapipe/api/solutions/js/tasks-vision.facelandmarker) provider, as well as a `useFaceLandmarker` hook.
|
|
2546
2546
|
|
|
2547
|
+
```tsx
|
|
2548
|
+
<FaceLandmarker>{/* ... */}</FaceLandmarker>
|
|
2549
|
+
```
|
|
2550
|
+
|
|
2551
|
+
It will instanciate a FaceLandmarker object with the following defaults:
|
|
2552
|
+
|
|
2553
|
+
```tsx
|
|
2554
|
+
{
|
|
2555
|
+
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
|
|
2556
|
+
options: {
|
|
2557
|
+
baseOptions: {
|
|
2558
|
+
modelAssetPath: "https://storage.googleapis.com/mediapipe-models/face_landmarker/face_landmarker/float16/1/face_landmarker.task",
|
|
2559
|
+
delegate: "GPU",
|
|
2560
|
+
},
|
|
2561
|
+
runningMode: "VIDEO",
|
|
2562
|
+
outputFaceBlendshapes: true,
|
|
2563
|
+
outputFacialTransformationMatrixes: true,
|
|
2564
|
+
}
|
|
2565
|
+
}
|
|
2566
|
+
```
|
|
2567
|
+
|
|
2568
|
+
You can override defaults, like for example self-host tasks-vision's `wasm/` and `face_landmarker.task` model in you `public/` directory:
|
|
2569
|
+
|
|
2570
|
+
```sh
|
|
2571
|
+
$ ln -s ../node_modules/@mediapipe/tasks-vision/wasm/ public/tasks-vision-wasm
|
|
2572
|
+
$ curl https://storage.googleapis.com/mediapipe-models/face_landmarker/face_landmarker/float16/1/face_landmarker.task -o public/face_landmarker.task
|
|
2573
|
+
```
|
|
2574
|
+
|
|
2575
|
+
```tsx
|
|
2576
|
+
import { FaceLandmarkerDefaults } from '@react-three/drei'
|
|
2577
|
+
|
|
2578
|
+
const visionBasePath = new URL("/tasks-vision-wasm", import.meta.url).toString()
|
|
2579
|
+
const modelAssetPath = new URL("/face_landmarker.task", import.meta.url).toString()
|
|
2580
|
+
|
|
2581
|
+
const faceLandmarkerOptions = { ...FaceLandmarkerDefaults.options };
|
|
2582
|
+
faceLandmarkerOptions.baseOptions.modelAssetPath = modelAssetPath;
|
|
2583
|
+
|
|
2584
|
+
<FaceLandmarker basePath={visionBasePath} options={faceLandmarkerOptions}>
|
|
2585
|
+
```
|
|
2586
|
+
|
|
2547
2587
|
# Loading
|
|
2548
2588
|
|
|
2549
2589
|
#### Loader
|
|
@@ -2619,6 +2659,25 @@ useGLTF(url, '/draco-gltf')
|
|
|
2619
2659
|
useGLTF.preload(url)
|
|
2620
2660
|
```
|
|
2621
2661
|
|
|
2662
|
+
> **Note** <br>If you are using the CDN loaded draco binaries, you can get a small speedup in loading time by prefetching them.
|
|
2663
|
+
>
|
|
2664
|
+
> 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.
|
|
2665
|
+
>
|
|
2666
|
+
> ```html
|
|
2667
|
+
> <link
|
|
2668
|
+
> rel="prefetch"
|
|
2669
|
+
> crossorigin="anonymous"
|
|
2670
|
+
> href="https://www.gstatic.com/draco/versioned/decoders/1.5.5/draco_wasm_wrapper.js"
|
|
2671
|
+
> />
|
|
2672
|
+
> <link
|
|
2673
|
+
> rel="prefetch"
|
|
2674
|
+
> crossorigin="anonymous"
|
|
2675
|
+
> href="https://www.gstatic.com/draco/versioned/decoders/1.5.5/draco_decoder.wasm"
|
|
2676
|
+
> />
|
|
2677
|
+
> ```
|
|
2678
|
+
>
|
|
2679
|
+
> 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.
|
|
2680
|
+
|
|
2622
2681
|
#### useFBX
|
|
2623
2682
|
|
|
2624
2683
|
[](https://drei.pmnd.rs/?path=/story/loaders-fbx)
|
|
@@ -3326,14 +3385,17 @@ Invert masks individually by providing a 2nd boolean argument to the `useMask` h
|
|
|
3326
3385
|
const stencil = useMask(1, true)
|
|
3327
3386
|
```
|
|
3328
3387
|
|
|
3329
|
-
####
|
|
3388
|
+
#### MeshPortalMaterial
|
|
3330
3389
|
|
|
3331
3390
|
<p>
|
|
3332
3391
|
<a href="https://codesandbox.io/s/ik11ln"><img width="20%" src="https://codesandbox.io/api/v1/sandboxes/ik11ln/screenshot.png" alt="Demo"/></a>
|
|
3333
3392
|
</p>
|
|
3334
3393
|
|
|
3335
3394
|
```tsx
|
|
3336
|
-
export type PortalProps = JSX.IntrinsicElements['
|
|
3395
|
+
export type PortalProps = JSX.IntrinsicElements['shaderMaterial'] & {
|
|
3396
|
+
/** Mix the portals own scene with the world scene, 0 = world scene render,
|
|
3397
|
+
* 0.5 = both scenes render, 1 = portal scene renders, defaults to 0 */
|
|
3398
|
+
blend?: number
|
|
3337
3399
|
/** Edge fade blur, 0 = no blur (default) */
|
|
3338
3400
|
blur?: number
|
|
3339
3401
|
/** SDF resolution, the smaller the faster is the start-up time (default: 512) */
|
|
@@ -3344,6 +3406,8 @@ export type PortalProps = JSX.IntrinsicElements['portalMaterialImpl'] & {
|
|
|
3344
3406
|
eventPriority?: number
|
|
3345
3407
|
/** Optional render priority, defaults to 0 */
|
|
3346
3408
|
renderPriority?: number
|
|
3409
|
+
/** Optionally diable events inside the portal, defaults to false */
|
|
3410
|
+
events?: boolean
|
|
3347
3411
|
}
|
|
3348
3412
|
```
|
|
3349
3413
|
|
|
@@ -3366,6 +3430,12 @@ You can optionally fade or blur the edges of the portal by providing a `blur` pr
|
|
|
3366
3430
|
<MeshPortalMaterial transparent blur={0.5}>
|
|
3367
3431
|
```
|
|
3368
3432
|
|
|
3433
|
+
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.
|
|
3434
|
+
|
|
3435
|
+
```jsx
|
|
3436
|
+
<MeshPortalMaterial blend={1}>
|
|
3437
|
+
```
|
|
3438
|
+
|
|
3369
3439
|
# Staging
|
|
3370
3440
|
|
|
3371
3441
|
#### Center
|
package/core/Caustics.cjs.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("@babel/runtime/helpers/extends"),r=require("three"),n=require("react"),t=require("@react-three/fiber"),o=require("./useFBO.cjs.js"),i=require("./useHelper.cjs.js"),a=require("./shaderMaterial.cjs.js"),l=require("./Edges.cjs.js"),c=require("three-stdlib");function s(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}function u(e){if(e&&e.__esModule)return e;var r=Object.create(null);return e&&Object.keys(e).forEach((function(n){if("default"!==n){var t=Object.getOwnPropertyDescriptor(e,n);Object.defineProperty(r,n,t.get?t:{enumerable:!0,get:function(){return e[n]}})}})),r.default=e,Object.freeze(r)}var d=s(e),m=u(r),p=u(n);function v(e=m.FrontSide){const r={value:new m.Matrix4};return Object.assign(new m.MeshNormalMaterial({side:e}),{viewMatrix:r,onBeforeCompile:e=>{e.uniforms.viewMatrix=r,e.fragmentShader="vec3 inverseTransformDirection( in vec3 dir, in mat4 matrix ) {\n return normalize( ( vec4( dir, 0.0 ) * matrix ).xyz );\n }\n"+e.fragmentShader.replace("#include <normal_fragment_maps>","#include <normal_fragment_maps>\n normal = inverseTransformDirection( normal, viewMatrix );\n")}})}const f=a.shaderMaterial({causticsTexture:null,causticsTextureB:null,color:new m.Color,lightProjMatrix:new m.Matrix4,lightViewMatrix:new m.Matrix4},"varying vec3 vWorldPosition; \n void main() {\n gl_Position = projectionMatrix * viewMatrix * modelMatrix * vec4(position, 1.);\n vec4 worldPosition = modelMatrix * vec4(position, 1.);\n vWorldPosition = worldPosition.xyz;\n }","varying vec3 vWorldPosition;\n uniform vec3 color;\n uniform sampler2D causticsTexture; \n uniform sampler2D causticsTextureB; \n uniform mat4 lightProjMatrix;\n uniform mat4 lightViewMatrix;\n void main() {\n // Apply caustics \n vec4 lightSpacePos = lightProjMatrix * lightViewMatrix * vec4(vWorldPosition, 1.0);\n lightSpacePos.xyz /= lightSpacePos.w;\n lightSpacePos.xyz = lightSpacePos.xyz * 0.5 + 0.5; \n vec3 front = texture2D(causticsTexture, lightSpacePos.xy).rgb;\n vec3 back = texture2D(causticsTextureB, lightSpacePos.xy).rgb;\n gl_FragColor = vec4((front + back) * color, 1.0);\n #include <tonemapping_fragment>\n #include <encodings_fragment>\n }"),x=a.shaderMaterial({cameraMatrixWorld:new m.Matrix4,cameraProjectionMatrixInv:new m.Matrix4,normalTexture:null,depthTexture:null,lightDir:new m.Vector3(0,1,0),lightPlaneNormal:new m.Vector3(0,1,0),lightPlaneConstant:0,near:.1,far:100,modelMatrix:new m.Matrix4,worldRadius:1/40,ior:1.1,bounces:0,resolution:1024,size:10,intensity:.5},"\n varying vec2 vUv;\n void main() {\n vUv = uv;\n gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);\n }"," \n uniform mat4 cameraMatrixWorld;\n uniform mat4 cameraProjectionMatrixInv;\n uniform vec3 lightDir;\n uniform vec3 lightPlaneNormal;\n uniform float lightPlaneConstant;\n uniform float near;\n uniform float far;\n uniform float time;\n uniform float worldRadius;\n uniform float resolution;\n uniform float size;\n uniform float intensity;\n uniform float ior;\n precision highp isampler2D;\n precision highp usampler2D;\n uniform sampler2D normalTexture;\n uniform sampler2D depthTexture;\n uniform float bounces;\n varying vec2 vUv;\n vec3 WorldPosFromDepth(float depth, vec2 coord) {\n float z = depth * 2.0 - 1.0;\n vec4 clipSpacePosition = vec4(coord * 2.0 - 1.0, z, 1.0);\n vec4 viewSpacePosition = cameraProjectionMatrixInv * clipSpacePosition;\n // Perspective division\n viewSpacePosition /= viewSpacePosition.w;\n vec4 worldSpacePosition = cameraMatrixWorld * viewSpacePosition;\n return worldSpacePosition.xyz;\n } \n float sdPlane( vec3 p, vec3 n, float h ) {\n // n must be normalized\n return dot(p,n) + h;\n }\n float planeIntersect( vec3 ro, vec3 rd, vec4 p ) {\n return -(dot(ro,p.xyz)+p.w)/dot(rd,p.xyz);\n }\n vec3 totalInternalReflection(vec3 ro, vec3 rd, vec3 pos, vec3 normal, float ior, out vec3 rayOrigin, out vec3 rayDirection) {\n rayOrigin = ro;\n rayDirection = rd;\n rayDirection = refract(rayDirection, normal, 1.0 / ior);\n rayOrigin = pos + rayDirection * 0.1;\n return rayDirection;\n }\n void main() {\n // Each sample consists of random offset in the x and y direction\n float caustic = 0.0;\n float causticTexelSize = (1.0 / resolution) * size * 2.0;\n float texelsNeeded = worldRadius / causticTexelSize;\n float sampleRadius = texelsNeeded / resolution;\n float sum = 0.0;\n if (texture2D(depthTexture, vUv).x == 1.0) {\n gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0);\n return;\n }\n vec2 offset1 = vec2(-0.5, -0.5);//vec2(rand() - 0.5, rand() - 0.5);\n vec2 offset2 = vec2(-0.5, 0.5);//vec2(rand() - 0.5, rand() - 0.5);\n vec2 offset3 = vec2(0.5, 0.5);//vec2(rand() - 0.5, rand() - 0.5);\n vec2 offset4 = vec2(0.5, -0.5);//vec2(rand() - 0.5, rand() - 0.5);\n vec2 uv1 = vUv + offset1 * sampleRadius;\n vec2 uv2 = vUv + offset2 * sampleRadius;\n vec2 uv3 = vUv + offset3 * sampleRadius;\n vec2 uv4 = vUv + offset4 * sampleRadius;\n vec3 normal1 = texture2D(normalTexture, uv1, -10.0).rgb * 2.0 - 1.0;\n vec3 normal2 = texture2D(normalTexture, uv2, -10.0).rgb * 2.0 - 1.0;\n vec3 normal3 = texture2D(normalTexture, uv3, -10.0).rgb * 2.0 - 1.0;\n vec3 normal4 = texture2D(normalTexture, uv4, -10.0).rgb * 2.0 - 1.0;\n float depth1 = texture2D(depthTexture, uv1, -10.0).x;\n float depth2 = texture2D(depthTexture, uv2, -10.0).x;\n float depth3 = texture2D(depthTexture, uv3, -10.0).x;\n float depth4 = texture2D(depthTexture, uv4, -10.0).x;\n // Sanity check the depths\n if (depth1 == 1.0 || depth2 == 1.0 || depth3 == 1.0 || depth4 == 1.0) {\n gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0);\n return;\n }\n vec3 pos1 = WorldPosFromDepth(depth1, uv1);\n vec3 pos2 = WorldPosFromDepth(depth2, uv2);\n vec3 pos3 = WorldPosFromDepth(depth3, uv3);\n vec3 pos4 = WorldPosFromDepth(depth4, uv4);\n vec3 originPos1 = WorldPosFromDepth(0.0, uv1);\n vec3 originPos2 = WorldPosFromDepth(0.0, uv2);\n vec3 originPos3 = WorldPosFromDepth(0.0, uv3);\n vec3 originPos4 = WorldPosFromDepth(0.0, uv4);\n vec3 endPos1, endPos2, endPos3, endPos4;\n vec3 endDir1, endDir2, endDir3, endDir4;\n totalInternalReflection(originPos1, lightDir, pos1, normal1, ior, endPos1, endDir1);\n totalInternalReflection(originPos2, lightDir, pos2, normal2, ior, endPos2, endDir2);\n totalInternalReflection(originPos3, lightDir, pos3, normal3, ior, endPos3, endDir3);\n totalInternalReflection(originPos4, lightDir, pos4, normal4, ior, endPos4, endDir4);\n float lightPosArea = length(cross(originPos2 - originPos1, originPos3 - originPos1)) + length(cross(originPos3 - originPos1, originPos4 - originPos1));\n float t1 = planeIntersect(endPos1, endDir1, vec4(lightPlaneNormal, lightPlaneConstant));\n float t2 = planeIntersect(endPos2, endDir2, vec4(lightPlaneNormal, lightPlaneConstant));\n float t3 = planeIntersect(endPos3, endDir3, vec4(lightPlaneNormal, lightPlaneConstant));\n float t4 = planeIntersect(endPos4, endDir4, vec4(lightPlaneNormal, lightPlaneConstant));\n vec3 finalPos1 = endPos1 + endDir1 * t1;\n vec3 finalPos2 = endPos2 + endDir2 * t2;\n vec3 finalPos3 = endPos3 + endDir3 * t3;\n vec3 finalPos4 = endPos4 + endDir4 * t4;\n float finalArea = length(cross(finalPos2 - finalPos1, finalPos3 - finalPos1)) + length(cross(finalPos3 - finalPos1, finalPos4 - finalPos1));\n caustic += intensity * (lightPosArea / finalArea);\n // Calculate the area of the triangle in light spaces\n gl_FragColor = vec4(vec3(max(caustic, 0.0)), 1.0);\n }"),h={depth:!0,minFilter:m.LinearFilter,magFilter:m.LinearFilter,encoding:m.LinearEncoding,type:m.UnsignedByteType},g={minFilter:m.LinearMipmapLinearFilter,magFilter:m.LinearFilter,encoding:m.LinearEncoding,format:m.RGBAFormat,type:m.FloatType,generateMipmaps:!0},P=p.forwardRef((({debug:e,children:r,frames:n=1,ior:a=1.1,color:s="white",causticsOnly:u=!1,backside:P=!1,backsideIOR:y=1.1,worldRadius:M=.3125,intensity:w=.05,resolution:D=2024,lightSource:T=[5,5,5],...F},S)=>{t.extend({CausticsProjectionMaterial:f});const b=p.useRef(null),j=p.useRef(null),z=p.useRef(null),R=p.useRef(null),W=t.useThree((e=>e.gl)),I=i.useHelper(e&&j,m.CameraHelper),O=o.useFBO(D,D,h),C=o.useFBO(D,D,h),V=o.useFBO(D,D,g),B=o.useFBO(D,D,g),[_]=p.useState((()=>v())),[E]=p.useState((()=>v(m.BackSide))),[A]=p.useState((()=>new x)),[N]=p.useState((()=>new c.FullScreenQuad(A)));p.useLayoutEffect((()=>{b.current.updateWorldMatrix(!1,!0)}));let k=0;const q=new m.Vector3,L=new m.Frustum,U=new m.Matrix4,H=new m.Plane,G=new m.Vector3,Q=new m.Vector3,J=new m.Box3,K=new m.Vector3;return t.useFrame(((r,t)=>{if(n===1/0||k++<n){var o,i;Array.isArray(T)?G.fromArray(T).normalize():G.copy(b.current.worldToLocal(T.current.getWorldPosition(q)).normalize()),Q.copy(G).multiplyScalar(-1);let r=[];null==(o=z.current.parent)||o.matrixWorld.identity(),J.setFromObject(z.current,!0),r.push(new m.Vector3(J.min.x,J.min.y,J.min.z)),r.push(new m.Vector3(J.min.x,J.min.y,J.max.z)),r.push(new m.Vector3(J.min.x,J.max.y,J.min.z)),r.push(new m.Vector3(J.min.x,J.max.y,J.max.z)),r.push(new m.Vector3(J.max.x,J.min.y,J.min.z)),r.push(new m.Vector3(J.max.x,J.min.y,J.max.z)),r.push(new m.Vector3(J.max.x,J.max.y,J.min.z)),r.push(new m.Vector3(J.max.x,J.max.y,J.max.z));const n=r.map((e=>e.clone()));J.getCenter(K),r=r.map((e=>e.clone().sub(K)));const t=H.set(Q,0),l=r.map((e=>t.projectPoint(e,new m.Vector3))),c=l.reduce(((e,r)=>e.add(r)),q.set(0,0,0)).divideScalar(l.length),s=l.map((e=>e.distanceTo(c))).reduce(((e,r)=>Math.max(e,r))),d=r.map((e=>e.dot(G))).reduce(((e,r)=>Math.max(e,r)));j.current.position.copy(G.clone().multiplyScalar(d).add(K)),j.current.lookAt(z.current.localToWorld(K.clone()));const p=U.lookAt(j.current.position,K,q.set(0,1,0));j.current.left=-s,j.current.right=s,j.current.top=s,j.current.bottom=-s;const v=q.set(0,s,0).applyMatrix4(p),f=(j.current.position.y+v.y)/G.y;j.current.near=.1,j.current.far=f,j.current.updateProjectionMatrix(),j.current.updateMatrixWorld();const x=n.map((e=>e.add(G.clone().multiplyScalar(-e.y/G.y)))),h=x.reduce(((e,r)=>e.add(r)),q.set(0,0,0)).divideScalar(x.length),g=2*x.map((e=>Math.hypot(e.x-h.x,e.z-h.z))).reduce(((e,r)=>Math.max(e,r)));R.current.scale.setScalar(g),R.current.position.copy(h),e&&(null==(i=I.current)||i.update()),E.viewMatrix.value=_.viewMatrix.value=j.current.matrixWorldInverse;const F=L.setFromProjectionMatrix(U.multiplyMatrices(j.current.projectionMatrix,j.current.matrixWorldInverse)).planes[4];A.cameraMatrixWorld=j.current.matrixWorld,A.cameraProjectionMatrixInv=j.current.projectionMatrixInverse,A.lightDir=Q,A.lightPlaneNormal=F.normal,A.lightPlaneConstant=F.constant,A.near=j.current.near,A.far=j.current.far,A.resolution=D,A.size=s,A.intensity=w,A.worldRadius=M,z.current.visible=!0,W.setRenderTarget(O),W.clear(),z.current.overrideMaterial=_,W.render(z.current,j.current),W.setRenderTarget(C),W.clear(),P&&(z.current.overrideMaterial=E,W.render(z.current,j.current)),z.current.overrideMaterial=null,A.ior=a,R.current.material.lightProjMatrix=j.current.projectionMatrix,R.current.material.lightViewMatrix=j.current.matrixWorldInverse,A.normalTexture=O.texture,A.depthTexture=O.depthTexture,W.setRenderTarget(V),W.clear(),N.render(W),A.ior=y,A.normalTexture=C.texture,A.depthTexture=C.depthTexture,W.setRenderTarget(B),W.clear(),P&&N.render(W),W.setRenderTarget(null),u&&(z.current.visible=!1)}})),p.useImperativeHandle(S,(()=>b.current),[]),p.createElement("group",d.default({ref:b},F),p.createElement("scene",{ref:z},p.createElement("orthographicCamera",{ref:j,up:[0,1,0]}),r),p.createElement("mesh",{renderOrder:2,ref:R,"rotation-x":-Math.PI/2},p.createElement("planeGeometry",null),p.createElement("causticsProjectionMaterial",{transparent:!0,color:s,causticsTexture:V.texture,causticsTextureB:B.texture,blending:m.CustomBlending,blendSrc:m.OneFactor,blendDst:m.SrcAlphaFactor,depthWrite:!1}),e&&p.createElement(l.Edges,null,p.createElement("lineBasicMaterial",{color:"#ffff00",toneMapped:!1}))))}));exports.Caustics=P;
|
|
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"),o=require("./useFBO.cjs.js"),i=require("./useHelper.cjs.js"),a=require("./shaderMaterial.cjs.js"),l=require("./Edges.cjs.js"),c=require("three-stdlib");function s(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}function u(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 d=s(e),m=u(r),p=u(t);function v(e=m.FrontSide){const r={value:new m.Matrix4};return Object.assign(new m.MeshNormalMaterial({side:e}),{viewMatrix:r,onBeforeCompile:e=>{e.uniforms.viewMatrix=r,e.fragmentShader="vec3 inverseTransformDirection( in vec3 dir, in mat4 matrix ) {\n return normalize( ( vec4( dir, 0.0 ) * matrix ).xyz );\n }\n"+e.fragmentShader.replace("#include <normal_fragment_maps>","#include <normal_fragment_maps>\n normal = inverseTransformDirection( normal, viewMatrix );\n")}})}const f=a.shaderMaterial({causticsTexture:null,causticsTextureB:null,color:new m.Color,lightProjMatrix:new m.Matrix4,lightViewMatrix:new m.Matrix4},"varying vec3 vWorldPosition; \n void main() {\n gl_Position = projectionMatrix * viewMatrix * modelMatrix * vec4(position, 1.);\n vec4 worldPosition = modelMatrix * vec4(position, 1.);\n vWorldPosition = worldPosition.xyz;\n }","varying vec3 vWorldPosition;\n uniform vec3 color;\n uniform sampler2D causticsTexture; \n uniform sampler2D causticsTextureB; \n uniform mat4 lightProjMatrix;\n uniform mat4 lightViewMatrix;\n void main() {\n // Apply caustics \n vec4 lightSpacePos = lightProjMatrix * lightViewMatrix * vec4(vWorldPosition, 1.0);\n lightSpacePos.xyz /= lightSpacePos.w;\n lightSpacePos.xyz = lightSpacePos.xyz * 0.5 + 0.5; \n vec3 front = texture2D(causticsTexture, lightSpacePos.xy).rgb;\n vec3 back = texture2D(causticsTextureB, lightSpacePos.xy).rgb;\n gl_FragColor = vec4((front + back) * color, 1.0);\n #include <tonemapping_fragment>\n #include <encodings_fragment>\n }"),x=a.shaderMaterial({cameraMatrixWorld:new m.Matrix4,cameraProjectionMatrixInv:new m.Matrix4,normalTexture:null,depthTexture:null,lightDir:new m.Vector3(0,1,0),lightPlaneNormal:new m.Vector3(0,1,0),lightPlaneConstant:0,near:.1,far:100,modelMatrix:new m.Matrix4,worldRadius:1/40,ior:1.1,bounces:0,resolution:1024,size:10,intensity:.5},"\n varying vec2 vUv;\n void main() {\n vUv = uv;\n gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);\n }"," \n uniform mat4 cameraMatrixWorld;\n uniform mat4 cameraProjectionMatrixInv;\n uniform vec3 lightDir;\n uniform vec3 lightPlaneNormal;\n uniform float lightPlaneConstant;\n uniform float near;\n uniform float far;\n uniform float time;\n uniform float worldRadius;\n uniform float resolution;\n uniform float size;\n uniform float intensity;\n uniform float ior;\n precision highp isampler2D;\n precision highp usampler2D;\n uniform sampler2D normalTexture;\n uniform sampler2D depthTexture;\n uniform float bounces;\n varying vec2 vUv;\n vec3 WorldPosFromDepth(float depth, vec2 coord) {\n float z = depth * 2.0 - 1.0;\n vec4 clipSpacePosition = vec4(coord * 2.0 - 1.0, z, 1.0);\n vec4 viewSpacePosition = cameraProjectionMatrixInv * clipSpacePosition;\n // Perspective division\n viewSpacePosition /= viewSpacePosition.w;\n vec4 worldSpacePosition = cameraMatrixWorld * viewSpacePosition;\n return worldSpacePosition.xyz;\n } \n float sdPlane( vec3 p, vec3 n, float h ) {\n // n must be normalized\n return dot(p,n) + h;\n }\n float planeIntersect( vec3 ro, vec3 rd, vec4 p ) {\n return -(dot(ro,p.xyz)+p.w)/dot(rd,p.xyz);\n }\n vec3 totalInternalReflection(vec3 ro, vec3 rd, vec3 pos, vec3 normal, float ior, out vec3 rayOrigin, out vec3 rayDirection) {\n rayOrigin = ro;\n rayDirection = rd;\n rayDirection = refract(rayDirection, normal, 1.0 / ior);\n rayOrigin = pos + rayDirection * 0.1;\n return rayDirection;\n }\n void main() {\n // Each sample consists of random offset in the x and y direction\n float caustic = 0.0;\n float causticTexelSize = (1.0 / resolution) * size * 2.0;\n float texelsNeeded = worldRadius / causticTexelSize;\n float sampleRadius = texelsNeeded / resolution;\n float sum = 0.0;\n if (texture2D(depthTexture, vUv).x == 1.0) {\n gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0);\n return;\n }\n vec2 offset1 = vec2(-0.5, -0.5);//vec2(rand() - 0.5, rand() - 0.5);\n vec2 offset2 = vec2(-0.5, 0.5);//vec2(rand() - 0.5, rand() - 0.5);\n vec2 offset3 = vec2(0.5, 0.5);//vec2(rand() - 0.5, rand() - 0.5);\n vec2 offset4 = vec2(0.5, -0.5);//vec2(rand() - 0.5, rand() - 0.5);\n vec2 uv1 = vUv + offset1 * sampleRadius;\n vec2 uv2 = vUv + offset2 * sampleRadius;\n vec2 uv3 = vUv + offset3 * sampleRadius;\n vec2 uv4 = vUv + offset4 * sampleRadius;\n vec3 normal1 = texture2D(normalTexture, uv1, -10.0).rgb * 2.0 - 1.0;\n vec3 normal2 = texture2D(normalTexture, uv2, -10.0).rgb * 2.0 - 1.0;\n vec3 normal3 = texture2D(normalTexture, uv3, -10.0).rgb * 2.0 - 1.0;\n vec3 normal4 = texture2D(normalTexture, uv4, -10.0).rgb * 2.0 - 1.0;\n float depth1 = texture2D(depthTexture, uv1, -10.0).x;\n float depth2 = texture2D(depthTexture, uv2, -10.0).x;\n float depth3 = texture2D(depthTexture, uv3, -10.0).x;\n float depth4 = texture2D(depthTexture, uv4, -10.0).x;\n // Sanity check the depths\n if (depth1 == 1.0 || depth2 == 1.0 || depth3 == 1.0 || depth4 == 1.0) {\n gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0);\n return;\n }\n vec3 pos1 = WorldPosFromDepth(depth1, uv1);\n vec3 pos2 = WorldPosFromDepth(depth2, uv2);\n vec3 pos3 = WorldPosFromDepth(depth3, uv3);\n vec3 pos4 = WorldPosFromDepth(depth4, uv4);\n vec3 originPos1 = WorldPosFromDepth(0.0, uv1);\n vec3 originPos2 = WorldPosFromDepth(0.0, uv2);\n vec3 originPos3 = WorldPosFromDepth(0.0, uv3);\n vec3 originPos4 = WorldPosFromDepth(0.0, uv4);\n vec3 endPos1, endPos2, endPos3, endPos4;\n vec3 endDir1, endDir2, endDir3, endDir4;\n totalInternalReflection(originPos1, lightDir, pos1, normal1, ior, endPos1, endDir1);\n totalInternalReflection(originPos2, lightDir, pos2, normal2, ior, endPos2, endDir2);\n totalInternalReflection(originPos3, lightDir, pos3, normal3, ior, endPos3, endDir3);\n totalInternalReflection(originPos4, lightDir, pos4, normal4, ior, endPos4, endDir4);\n float lightPosArea = length(cross(originPos2 - originPos1, originPos3 - originPos1)) + length(cross(originPos3 - originPos1, originPos4 - originPos1));\n float t1 = planeIntersect(endPos1, endDir1, vec4(lightPlaneNormal, lightPlaneConstant));\n float t2 = planeIntersect(endPos2, endDir2, vec4(lightPlaneNormal, lightPlaneConstant));\n float t3 = planeIntersect(endPos3, endDir3, vec4(lightPlaneNormal, lightPlaneConstant));\n float t4 = planeIntersect(endPos4, endDir4, vec4(lightPlaneNormal, lightPlaneConstant));\n vec3 finalPos1 = endPos1 + endDir1 * t1;\n vec3 finalPos2 = endPos2 + endDir2 * t2;\n vec3 finalPos3 = endPos3 + endDir3 * t3;\n vec3 finalPos4 = endPos4 + endDir4 * t4;\n float finalArea = length(cross(finalPos2 - finalPos1, finalPos3 - finalPos1)) + length(cross(finalPos3 - finalPos1, finalPos4 - finalPos1));\n caustic += intensity * (lightPosArea / finalArea);\n // Calculate the area of the triangle in light spaces\n gl_FragColor = vec4(vec3(max(caustic, 0.0)), 1.0);\n }"),g={depth:!0,minFilter:m.LinearFilter,magFilter:m.LinearFilter,encoding:m.LinearEncoding,type:m.UnsignedByteType},h={minFilter:m.LinearMipmapLinearFilter,magFilter:m.LinearFilter,encoding:m.LinearEncoding,format:m.RGBAFormat,type:m.FloatType,generateMipmaps:!0},P=p.forwardRef((({debug:e,children:r,frames:t=1,ior:a=1.1,color:s="white",causticsOnly:u=!1,backside:P=!1,backsideIOR:y=1.1,worldRadius:M=.3125,intensity:D=.05,resolution:w=2024,lightSource:T=[5,5,5],...F},S)=>{n.extend({CausticsProjectionMaterial:f});const b=p.useRef(null),j=p.useRef(null),z=p.useRef(null),R=p.useRef(null),W=n.useThree((e=>e.gl)),I=i.useHelper(e&&j,m.CameraHelper),O=o.useFBO(w,w,g),C=o.useFBO(w,w,g),B=o.useFBO(w,w,h),V=o.useFBO(w,w,h),[_]=p.useState((()=>v())),[E]=p.useState((()=>v(m.BackSide))),[A]=p.useState((()=>new x)),[N]=p.useState((()=>new c.FullScreenQuad(A)));p.useLayoutEffect((()=>{b.current.updateWorldMatrix(!1,!0)}));let k=0;const q=new m.Vector3,L=new m.Frustum,U=new m.Matrix4,H=new m.Plane,G=new m.Vector3,Q=new m.Vector3,J=new m.Box3,K=new m.Vector3,X=[],Y=[],Z=[],$=[],ee=new m.Vector3;for(let e=0;e<8;e++)X.push(new m.Vector3),Y.push(new m.Vector3),Z.push(new m.Vector3),$.push(new m.Vector3);return n.useFrame((()=>{if(t===1/0||k++<t){var r,n;Array.isArray(T)?G.fromArray(T).normalize():G.copy(b.current.worldToLocal(T.current.getWorldPosition(q)).normalize()),Q.copy(G).multiplyScalar(-1),null==(r=z.current.parent)||r.matrixWorld.identity(),J.setFromObject(z.current,!0),X[0].set(J.min.x,J.min.y,J.min.z),X[1].set(J.min.x,J.min.y,J.max.z),X[2].set(J.min.x,J.max.y,J.min.z),X[3].set(J.min.x,J.max.y,J.max.z),X[4].set(J.max.x,J.min.y,J.min.z),X[5].set(J.max.x,J.min.y,J.max.z),X[6].set(J.max.x,J.max.y,J.min.z),X[7].set(J.max.x,J.max.y,J.max.z);for(let e=0;e<8;e++)Y[e].copy(X[e]);J.getCenter(K),X.map((e=>e.sub(K)));const t=H.set(Q,0);X.map(((e,r)=>t.projectPoint(e,Z[r])));const o=Z.reduce(((e,r)=>e.add(r)),q.set(0,0,0)).divideScalar(Z.length),i=Z.map((e=>e.distanceTo(o))).reduce(((e,r)=>Math.max(e,r))),l=X.map((e=>e.dot(G))).reduce(((e,r)=>Math.max(e,r)));j.current.position.copy(ee.copy(G).multiplyScalar(l).add(K)),j.current.lookAt(z.current.localToWorld(K));const c=U.lookAt(j.current.position,K,q.set(0,1,0));j.current.left=-i,j.current.right=i,j.current.top=i,j.current.bottom=-i;const s=q.set(0,i,0).applyMatrix4(c),d=(j.current.position.y+s.y)/G.y;j.current.near=.1,j.current.far=d,j.current.updateProjectionMatrix(),j.current.updateMatrixWorld();const m=Y.map(((e,r)=>e.add($[r].copy(G).multiplyScalar(-e.y/G.y)))),p=m.reduce(((e,r)=>e.add(r)),q.set(0,0,0)).divideScalar(m.length),v=2*m.map((e=>Math.hypot(e.x-p.x,e.z-p.z))).reduce(((e,r)=>Math.max(e,r)));R.current.scale.setScalar(v),R.current.position.copy(p),e&&(null==(n=I.current)||n.update()),E.viewMatrix.value=_.viewMatrix.value=j.current.matrixWorldInverse;const f=L.setFromProjectionMatrix(U.multiplyMatrices(j.current.projectionMatrix,j.current.matrixWorldInverse)).planes[4];A.cameraMatrixWorld=j.current.matrixWorld,A.cameraProjectionMatrixInv=j.current.projectionMatrixInverse,A.lightDir=Q,A.lightPlaneNormal=f.normal,A.lightPlaneConstant=f.constant,A.near=j.current.near,A.far=j.current.far,A.resolution=w,A.size=i,A.intensity=D,A.worldRadius=M,z.current.visible=!0,W.setRenderTarget(O),W.clear(),z.current.overrideMaterial=_,W.render(z.current,j.current),W.setRenderTarget(C),W.clear(),P&&(z.current.overrideMaterial=E,W.render(z.current,j.current)),z.current.overrideMaterial=null,A.ior=a,R.current.material.lightProjMatrix=j.current.projectionMatrix,R.current.material.lightViewMatrix=j.current.matrixWorldInverse,A.normalTexture=O.texture,A.depthTexture=O.depthTexture,W.setRenderTarget(B),W.clear(),N.render(W),A.ior=y,A.normalTexture=C.texture,A.depthTexture=C.depthTexture,W.setRenderTarget(V),W.clear(),P&&N.render(W),W.setRenderTarget(null),u&&(z.current.visible=!1)}})),p.useImperativeHandle(S,(()=>b.current),[]),p.createElement("group",d.default({ref:b},F),p.createElement("scene",{ref:z},p.createElement("orthographicCamera",{ref:j,up:[0,1,0]}),r),p.createElement("mesh",{renderOrder:2,ref:R,"rotation-x":-Math.PI/2},p.createElement("planeGeometry",null),p.createElement("causticsProjectionMaterial",{transparent:!0,color:s,causticsTexture:B.texture,causticsTextureB:V.texture,blending:m.CustomBlending,blendSrc:m.OneFactor,blendDst:m.SrcAlphaFactor,depthWrite:!1}),e&&p.createElement(l.Edges,null,p.createElement("lineBasicMaterial",{color:"#ffff00",toneMapped:!1}))))}));exports.Caustics=P;
|
package/core/Caustics.js
CHANGED
|
@@ -245,34 +245,50 @@ const Caustics = /*#__PURE__*/React.forwardRef(({
|
|
|
245
245
|
const lightDirInv = new THREE.Vector3();
|
|
246
246
|
const bounds = new THREE.Box3();
|
|
247
247
|
const focusPos = new THREE.Vector3();
|
|
248
|
-
|
|
248
|
+
const boundsVertices = [];
|
|
249
|
+
const worldVerts = [];
|
|
250
|
+
const projectedVerts = [];
|
|
251
|
+
const lightDirs = [];
|
|
252
|
+
const cameraPos = new THREE.Vector3();
|
|
253
|
+
|
|
254
|
+
for (let i = 0; i < 8; i++) {
|
|
255
|
+
boundsVertices.push(new THREE.Vector3());
|
|
256
|
+
worldVerts.push(new THREE.Vector3());
|
|
257
|
+
projectedVerts.push(new THREE.Vector3());
|
|
258
|
+
lightDirs.push(new THREE.Vector3());
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
useFrame(() => {
|
|
249
262
|
if (frames === Infinity || count++ < frames) {
|
|
250
263
|
var _scene$current$parent, _helper$current;
|
|
251
264
|
|
|
252
265
|
if (Array.isArray(lightSource)) lightDir.fromArray(lightSource).normalize();else lightDir.copy(ref.current.worldToLocal(lightSource.current.getWorldPosition(v)).normalize());
|
|
253
266
|
lightDirInv.copy(lightDir).multiplyScalar(-1);
|
|
254
|
-
let boundsVertices = [];
|
|
255
267
|
(_scene$current$parent = scene.current.parent) == null ? void 0 : _scene$current$parent.matrixWorld.identity();
|
|
256
268
|
bounds.setFromObject(scene.current, true);
|
|
257
|
-
boundsVertices.
|
|
258
|
-
boundsVertices.
|
|
259
|
-
boundsVertices.
|
|
260
|
-
boundsVertices.
|
|
261
|
-
boundsVertices.
|
|
262
|
-
boundsVertices.
|
|
263
|
-
boundsVertices.
|
|
264
|
-
boundsVertices.
|
|
265
|
-
|
|
269
|
+
boundsVertices[0].set(bounds.min.x, bounds.min.y, bounds.min.z);
|
|
270
|
+
boundsVertices[1].set(bounds.min.x, bounds.min.y, bounds.max.z);
|
|
271
|
+
boundsVertices[2].set(bounds.min.x, bounds.max.y, bounds.min.z);
|
|
272
|
+
boundsVertices[3].set(bounds.min.x, bounds.max.y, bounds.max.z);
|
|
273
|
+
boundsVertices[4].set(bounds.max.x, bounds.min.y, bounds.min.z);
|
|
274
|
+
boundsVertices[5].set(bounds.max.x, bounds.min.y, bounds.max.z);
|
|
275
|
+
boundsVertices[6].set(bounds.max.x, bounds.max.y, bounds.min.z);
|
|
276
|
+
boundsVertices[7].set(bounds.max.x, bounds.max.y, bounds.max.z);
|
|
277
|
+
|
|
278
|
+
for (let i = 0; i < 8; i++) {
|
|
279
|
+
worldVerts[i].copy(boundsVertices[i]);
|
|
280
|
+
}
|
|
281
|
+
|
|
266
282
|
bounds.getCenter(focusPos);
|
|
267
|
-
boundsVertices
|
|
283
|
+
boundsVertices.map(v => v.sub(focusPos));
|
|
268
284
|
const lightPlane = lpP.set(lightDirInv, 0);
|
|
269
|
-
|
|
285
|
+
boundsVertices.map((v, i) => lightPlane.projectPoint(v, projectedVerts[i]));
|
|
270
286
|
const centralVert = projectedVerts.reduce((a, b) => a.add(b), v.set(0, 0, 0)).divideScalar(projectedVerts.length);
|
|
271
287
|
const radius = projectedVerts.map(v => v.distanceTo(centralVert)).reduce((a, b) => Math.max(a, b));
|
|
272
288
|
const dirLength = boundsVertices.map(x => x.dot(lightDir)).reduce((a, b) => Math.max(a, b)); // Shadows
|
|
273
289
|
|
|
274
|
-
camera.current.position.copy(
|
|
275
|
-
camera.current.lookAt(scene.current.localToWorld(focusPos
|
|
290
|
+
camera.current.position.copy(cameraPos.copy(lightDir).multiplyScalar(dirLength).add(focusPos));
|
|
291
|
+
camera.current.lookAt(scene.current.localToWorld(focusPos));
|
|
276
292
|
const dirMatrix = lpM.lookAt(camera.current.position, focusPos, v.set(0, 1, 0));
|
|
277
293
|
camera.current.left = -radius;
|
|
278
294
|
camera.current.right = radius;
|
|
@@ -285,7 +301,7 @@ const Caustics = /*#__PURE__*/React.forwardRef(({
|
|
|
285
301
|
camera.current.updateProjectionMatrix();
|
|
286
302
|
camera.current.updateMatrixWorld(); // Now find size of ground plane
|
|
287
303
|
|
|
288
|
-
const groundProjectedCoords = worldVerts.map(v => v.add(
|
|
304
|
+
const groundProjectedCoords = worldVerts.map((v, i) => v.add(lightDirs[i].copy(lightDir).multiplyScalar(-v.y / lightDir.y)));
|
|
289
305
|
const centerPos = groundProjectedCoords.reduce((a, b) => a.add(b), v.set(0, 0, 0)).divideScalar(groundProjectedCoords.length);
|
|
290
306
|
const maxSize = 2 * groundProjectedCoords.map(v => Math.hypot(v.x - centerPos.x, v.z - centerPos.z)).reduce((a, b) => Math.max(a, b));
|
|
291
307
|
plane.current.scale.setScalar(maxSize);
|
|
@@ -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
|
|