@react-three/drei 9.89.3 → 9.90.1
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 +46 -5
- package/core/Cloud.cjs.js +1 -1
- package/core/Cloud.js +17 -5
- package/core/Instances.cjs.js +1 -1
- package/core/Instances.js +14 -7
- package/core/Splat.cjs.js +1 -0
- package/core/Splat.d.ts +58 -0
- package/core/Splat.js +505 -0
- package/core/index.cjs.js +1 -1
- package/core/index.d.ts +1 -0
- package/core/index.js +2 -0
- package/helpers/deprecated.cjs.js +1 -0
- package/helpers/deprecated.d.ts +4 -0
- package/helpers/deprecated.js +14 -0
- package/index.cjs.js +1 -1
- package/index.js +1 -0
- package/native/index.cjs.js +1 -1
- package/native/index.js +2 -0
- package/package.json +1 -1
- package/react-three-drei-0.0.0-semantic-release.tgz +0 -0
- package/web/index.cjs.js +1 -1
- package/web/index.js +2 -0
package/README.md
CHANGED
|
@@ -77,7 +77,7 @@ The `native` route of the library **does not** export `Html` or `Loader`. The de
|
|
|
77
77
|
<li><a href="#outlines">Outlines</a></li>
|
|
78
78
|
<li><a href="#trail">Trail</a></li>
|
|
79
79
|
<li><a href="#sampler">Sampler</a></li>
|
|
80
|
-
<li><a href="#computedattribute">
|
|
80
|
+
<li><a href="#computedattribute">ComputedAttribute</a></li>
|
|
81
81
|
<li><a href="#clone">Clone</a></li>
|
|
82
82
|
<li><a href="#useanimations">useAnimations</a></li>
|
|
83
83
|
<li><a href="#marchingcubes">MarchingCubes</a></li>
|
|
@@ -85,6 +85,7 @@ The `native` route of the library **does not** export `Html` or `Loader`. The de
|
|
|
85
85
|
<li><a href="#svg">Svg</a></li>
|
|
86
86
|
<li><a href="#gltf">Gltf</a></li>
|
|
87
87
|
<li><a href="#asciirenderer">AsciiRenderer</a></li>
|
|
88
|
+
<li><a href="#splat">Splat</a></li>
|
|
88
89
|
</ul>
|
|
89
90
|
<li><a href="#shaders">Shaders</a></li>
|
|
90
91
|
<ul>
|
|
@@ -1770,8 +1771,8 @@ The decal box has to intersect the surface, otherwise it will not be visible. if
|
|
|
1770
1771
|
rotation={[0, 0, 0]} // Rotation of the decal (can be a vector or a degree in radians)
|
|
1771
1772
|
scale={1} // Scale of the decal
|
|
1772
1773
|
>
|
|
1773
|
-
<meshBasicMaterial
|
|
1774
|
-
map={texture}
|
|
1774
|
+
<meshBasicMaterial
|
|
1775
|
+
map={texture}
|
|
1775
1776
|
polygonOffset
|
|
1776
1777
|
polygonOffsetFactor={-1} // The material should take precedence over the original
|
|
1777
1778
|
/>
|
|
@@ -1849,6 +1850,46 @@ type AsciiRendererProps = {
|
|
|
1849
1850
|
<AsciiRenderer />
|
|
1850
1851
|
```
|
|
1851
1852
|
|
|
1853
|
+
#### Splat
|
|
1854
|
+
|
|
1855
|
+
<p>
|
|
1856
|
+
<a href="https://codesandbox.io/s/qp4jmf"><img width="20%" src="https://codesandbox.io/api/v1/sandboxes/qp4jmf/screenshot.png" alt="Demo"/></a>
|
|
1857
|
+
</p>
|
|
1858
|
+
|
|
1859
|
+
A declarative abstraction around [antimatter15/splat](https://github.com/antimatter15/splat). It supports re-use, multiple splats with correct depth sorting, splats can move and behave as a regular object3d's, supports alphahash & alphatest, and stream-loading.
|
|
1860
|
+
|
|
1861
|
+
```tsx
|
|
1862
|
+
type SplatProps = {
|
|
1863
|
+
/** Url towards a *.splat file, no support for *.ply */
|
|
1864
|
+
src: string
|
|
1865
|
+
/** Whether to use tone mapping, default: false */
|
|
1866
|
+
toneMapped?: boolean
|
|
1867
|
+
/** Alpha test value, , default: 0 */
|
|
1868
|
+
alphaTest?: number
|
|
1869
|
+
/** Whether to use alpha hashing, default: false */
|
|
1870
|
+
alphaHash?: boolean
|
|
1871
|
+
/** Chunk size for lazy loading, prevents chokings the worker, default: 25000 (25kb) */
|
|
1872
|
+
chunkSize?: number
|
|
1873
|
+
} & JSX.IntrinsicElements['mesh']
|
|
1874
|
+
```
|
|
1875
|
+
|
|
1876
|
+
```jsx
|
|
1877
|
+
<Splat src="https://huggingface.co/cakewalk/splat-data/resolve/main/nike.splat" />
|
|
1878
|
+
```
|
|
1879
|
+
|
|
1880
|
+
In order to depth sort multiple splats correectly you can either use alphaTest, for instance with a low value. But keep in mind that this can show a slight outline under some viewing conditions.
|
|
1881
|
+
|
|
1882
|
+
```jsx
|
|
1883
|
+
<Splat alphaTest={0.1} src="foo.splat" />
|
|
1884
|
+
<Splat alphaTest={0.1} src="bar.splat" />
|
|
1885
|
+
```
|
|
1886
|
+
|
|
1887
|
+
You can also use alphaHash, but this can be slower and create some noise, you would typically get rid of the noise in postprocessing with a TAA pass. You don't have to use alphaHash on all splats.
|
|
1888
|
+
|
|
1889
|
+
```jsx
|
|
1890
|
+
<Splat alphaHash src="foo.splat" />
|
|
1891
|
+
```
|
|
1892
|
+
|
|
1852
1893
|
# Shaders
|
|
1853
1894
|
|
|
1854
1895
|
#### MeshReflectorMaterial
|
|
@@ -2371,13 +2412,13 @@ Enable shadows using the `castShadow` and `recieveShadow` prop.
|
|
|
2371
2412
|
|
|
2372
2413
|
> Note: Html 'blending' mode only correctly occludes rectangular HTML elements by default. Use the `geometry` prop to swap the backing geometry to a custom one if your Html has a different shape.
|
|
2373
2414
|
|
|
2374
|
-
If transform mode is enabled, the dimensions of the rendered html will depend on the position relative to the camera, the camera fov and the distanceFactor. For example, an Html component placed at (0,0,0) and with a distanceFactor of 10, rendered inside a scene with a perspective camera positioned at (0,0,2.45) and a FOV of 75, will have the same dimensions as a "plain" html element like in [this example](https://codesandbox.io/s/drei-html-magic-number-6mzt6m).
|
|
2415
|
+
If transform mode is enabled, the dimensions of the rendered html will depend on the position relative to the camera, the camera fov and the distanceFactor. For example, an Html component placed at (0,0,0) and with a distanceFactor of 10, rendered inside a scene with a perspective camera positioned at (0,0,2.45) and a FOV of 75, will have the same dimensions as a "plain" html element like in [this example](https://codesandbox.io/s/drei-html-magic-number-6mzt6m).
|
|
2375
2416
|
|
|
2376
2417
|
A caveat of transform mode is that on some devices and browsers, the rendered html may appear blurry, as discussed in [#859](https://github.com/pmndrs/drei/issues/859). The issue can be at least mitigated by scaling down the Html parent and scaling up the html children:
|
|
2377
2418
|
|
|
2378
2419
|
```jsx
|
|
2379
2420
|
<Html transform scale={0.5}>
|
|
2380
|
-
<div style={{ transform:
|
|
2421
|
+
<div style={{ transform: 'scale(2)' }}>Some text</div>
|
|
2381
2422
|
</Html>
|
|
2382
2423
|
```
|
|
2383
2424
|
|
package/core/Cloud.cjs.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("@babel/runtime/helpers/extends"),t=require("react"),r=require("three"),n=require("@react-three/fiber"),a=require("./useTexture.cjs.js"),o=require("uuid");function
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("@babel/runtime/helpers/extends"),t=require("react"),r=require("three"),n=require("@react-three/fiber"),a=require("./useTexture.cjs.js"),o=require("uuid"),u=require("../helpers/deprecated.cjs.js");function i(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}function c(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 s=i(e),l=c(t);const d=new r.Matrix4,f=new r.Vector3,p=new r.Quaternion,m=new r.Vector3,g=new r.Quaternion,h=new r.Vector3,y=l.createContext(null),x=l.forwardRef((({children:e,material:t=r.MeshLambertMaterial,texture:o="https://rawcdn.githack.com/pmndrs/drei-assets/9225a9f1fbd449d9411125c2f419b843d0308c9f/cloud.png",range:i,limit:c=200,...x},v)=>{var b,M;const w=l.useMemo((()=>class extends t{constructor(){super();const e=parseInt(r.REVISION.replace(/\D+/g,""))>=154?"opaque_fragment":"output_fragment";this.onBeforeCompile=t=>{t.vertexShader="attribute float opacity;\n varying float vOpacity;\n "+t.vertexShader.replace("#include <fog_vertex>","#include <fog_vertex>\n vOpacity = opacity;\n "),t.fragmentShader="varying float vOpacity;\n "+t.fragmentShader.replace(`#include <${e}>`,`#include <${e}>\n gl_FragColor = vec4(outgoingLight, diffuseColor.a * vOpacity);\n `)}}}),[t]);n.extend({CloudMaterial:w});const E=l.useRef(null),C=l.useRef([]),A=l.useMemo((()=>new Float32Array(Array.from({length:c},(()=>1)))),[c]),O=l.useMemo((()=>new Float32Array(Array.from({length:c},(()=>[1,1,1])).flat())),[c]),j=a.useTexture(o);let R,U=0,V=0;const _=new r.Quaternion,q=new r.Vector3(0,0,1),F=new r.Vector3;n.useFrame(((e,t)=>{for(U=e.clock.getElapsedTime(),d.copy(E.current.matrixWorld).invert(),e.camera.matrixWorld.decompose(m,g,h),V=0;V<C.current.length;V++)R=C.current[V],R.ref.current.matrixWorld.decompose(f,p,h),f.add(F.copy(R.position).applyQuaternion(p).multiply(h)),p.copy(g).multiply(_.setFromAxisAngle(q,R.rotation+=t*R.rotationFactor)),h.multiplyScalar(R.volume+(1+Math.sin(U*R.density*R.speed))/2*R.growth),R.matrix.compose(f,p,h).premultiply(d),R.dist=f.distanceTo(m);for(C.current.sort(((e,t)=>t.dist-e.dist)),V=0;V<C.current.length;V++)R=C.current[V],A[V]=R.opacity*(R.dist<R.fade-1?R.dist/R.fade:1),E.current.setMatrixAt(V,R.matrix),E.current.setColorAt(V,R.color);E.current.geometry.attributes.opacity.needsUpdate=!0,E.current.instanceMatrix.needsUpdate=!0,E.current.instanceColor&&(E.current.instanceColor.needsUpdate=!0)})),l.useLayoutEffect((()=>{const e=Math.min(c,void 0!==i?i:c,C.current.length);E.current.count=e,u.setUpdateRange(E.current.instanceMatrix,{offset:0,count:16*e}),E.current.instanceColor&&u.setUpdateRange(E.current.instanceColor,{offset:0,count:3*e}),u.setUpdateRange(E.current.geometry.attributes.opacity,{offset:0,count:e})}));let S=[null!==(b=j.image.width)&&void 0!==b?b:1,null!==(M=j.image.height)&&void 0!==M?M:1],D=Math.max(S[0],S[1]);return S=[S[0]/D,S[1]/D],l.createElement("group",s.default({ref:v},x),l.createElement(y.Provider,{value:C},e,l.createElement("instancedMesh",{matrixAutoUpdate:!1,ref:E,args:[null,null,c]},l.createElement("instancedBufferAttribute",{usage:r.DynamicDrawUsage,attach:"instanceColor",args:[O,3]}),l.createElement("planeGeometry",{args:[...S]},l.createElement("instancedBufferAttribute",{usage:r.DynamicDrawUsage,attach:"attributes-opacity",args:[A,1]})),l.createElement("cloudMaterial",{key:t.name,map:j,transparent:!0,depthWrite:!1}))))})),v=l.forwardRef((({opacity:e=1,speed:t=0,bounds:a=[5,1,1],segments:u=20,color:i="#ffffff",fade:c=10,volume:d=6,smallestVolume:f=.25,distribute:p=null,growth:m=4,concentrate:g="inside",seed:h=Math.random(),...x},v)=>{function b(){const e=1e4*Math.sin(h++);return e-Math.floor(e)}const M=l.useContext(y),w=l.useRef(null),[E]=l.useState((()=>o.v4())),C=l.useMemo((()=>[...new Array(u)].map(((e,t)=>({segments:u,bounds:new r.Vector3(1,1,1),position:new r.Vector3,uuid:E,index:t,ref:w,dist:0,matrix:new r.Matrix4,color:new r.Color,rotation:t*(Math.PI/u)})))),[u,E]);return l.useLayoutEffect((()=>{C.forEach(((r,o)=>{var s;n.applyProps(r,{volume:d,color:i,speed:t,growth:m,opacity:e,fade:c,bounds:a,density:Math.max(.5,b()),rotationFactor:Math.max(.2,.5*b())*t});const l=null==p?void 0:p(r,o);(l||u>1)&&r.position.copy(r.bounds).multiply(null!==(s=null==l?void 0:l.point)&&void 0!==s?s:{x:2*b()-1,y:2*b()-1,z:2*b()-1});const h=Math.abs(r.position.x),y=Math.abs(r.position.y),x=Math.abs(r.position.z),v=Math.max(h,y,x);r.length=1,h===v&&(r.length-=h/r.bounds.x),y===v&&(r.length-=y/r.bounds.y),x===v&&(r.length-=x/r.bounds.z),r.volume=(void 0!==(null==l?void 0:l.volume)?l.volume:Math.max(Math.max(0,f),"random"===g?b():"inside"===g?r.length:1-r.length))*d}))}),[g,a,c,i,e,m,d,h,u,t]),l.useLayoutEffect((()=>{const e=C;return M.current=[...M.current,...e],()=>{M.current=M.current.filter((e=>e.uuid!==E))}}),[C]),l.useImperativeHandle(v,(()=>w.current),[]),l.createElement("group",s.default({ref:w},x))})),b=l.forwardRef(((e,t)=>l.useContext(y)?l.createElement(v,s.default({ref:t},e)):l.createElement(x,null,l.createElement(v,s.default({ref:t},e)))));exports.Cloud=b,exports.CloudInstance=v,exports.Clouds=x;
|
package/core/Cloud.js
CHANGED
|
@@ -4,6 +4,7 @@ import { REVISION, Quaternion, Vector3, DynamicDrawUsage, MeshLambertMaterial, M
|
|
|
4
4
|
import { extend, useFrame, applyProps } from '@react-three/fiber';
|
|
5
5
|
import { useTexture } from './useTexture.js';
|
|
6
6
|
import { v4 } from 'uuid';
|
|
7
|
+
import { setUpdateRange } from '../helpers/deprecated.js';
|
|
7
8
|
|
|
8
9
|
const CLOUD_URL = 'https://rawcdn.githack.com/pmndrs/drei-assets/9225a9f1fbd449d9411125c2f419b843d0308c9f/cloud.png';
|
|
9
10
|
const parentMatrix = /* @__PURE__ */new Matrix4();
|
|
@@ -88,11 +89,22 @@ const Clouds = /* @__PURE__ */React.forwardRef(({
|
|
|
88
89
|
if (instance.current.instanceColor) instance.current.instanceColor.needsUpdate = true;
|
|
89
90
|
});
|
|
90
91
|
React.useLayoutEffect(() => {
|
|
91
|
-
const
|
|
92
|
-
instance.current.count =
|
|
93
|
-
instance.current.instanceMatrix
|
|
94
|
-
|
|
95
|
-
|
|
92
|
+
const count = Math.min(limit, range !== undefined ? range : limit, clouds.current.length);
|
|
93
|
+
instance.current.count = count;
|
|
94
|
+
setUpdateRange(instance.current.instanceMatrix, {
|
|
95
|
+
offset: 0,
|
|
96
|
+
count: count * 16
|
|
97
|
+
});
|
|
98
|
+
if (instance.current.instanceColor) {
|
|
99
|
+
setUpdateRange(instance.current.instanceColor, {
|
|
100
|
+
offset: 0,
|
|
101
|
+
count: count * 3
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
setUpdateRange(instance.current.geometry.attributes.opacity, {
|
|
105
|
+
offset: 0,
|
|
106
|
+
count: count
|
|
107
|
+
});
|
|
96
108
|
});
|
|
97
109
|
let imageBounds = [(_image$width = cloudTexture.image.width) !== null && _image$width !== void 0 ? _image$width : 1, (_image$height = cloudTexture.image.height) !== null && _image$height !== void 0 ? _image$height : 1];
|
|
98
110
|
let max = Math.max(imageBounds[0], imageBounds[1]);
|
package/core/Instances.cjs.js
CHANGED
|
@@ -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"),a=require("react-merge-refs"),c=require("react-composer");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"),a=require("react-merge-refs"),c=require("react-composer"),i=require("../helpers/deprecated.cjs.js");function s(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}function o(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 u=s(e),l=o(t),f=o(r),d=s(a),m=s(c);const y=new l.Matrix4,p=new l.Matrix4,h=[],x=new l.Mesh;class g extends l.Group{constructor(){super(),this.color=new l.Color("white"),this.instance={current:void 0},this.instanceKey={current:void 0}}get geometry(){var e;return null==(e=this.instance.current)?void 0:e.geometry}raycast(e,t){const r=this.instance.current;if(!r)return;if(!r.geometry||!r.material)return;x.geometry=r.geometry;const n=r.matrixWorld,a=r.userData.instances.indexOf(this.instanceKey);if(!(-1===a||a>r.count)){r.getMatrixAt(a,y),p.multiplyMatrices(n,y),x.matrixWorld=p,r.material instanceof l.Material?x.material.side=r.material.side:x.material.side=r.material[0].side,x.raycast(e,h);for(let e=0,r=h.length;e<r;e++){const r=h[e];r.instanceId=a,r.object=this,t.push(r)}h.length=0}}}const M=f.createContext(null),b=new l.Matrix4,w=new l.Matrix4,v=new l.Matrix4,j=new l.Vector3,E=new l.Quaternion,A=new l.Vector3,O=f.forwardRef((({context:e,children:t,...r},a)=>{f.useMemo((()=>n.extend({PositionMesh:g})),[]);const c=f.useRef(),{subscribe:i,getParent:s}=f.useContext(e||M);return f.useLayoutEffect((()=>i(c)),[]),f.createElement("positionMesh",u.default({instance:s(),instanceKey:c,ref:d.default([a,c])},r),t)})),P=f.forwardRef((({children:e,range:t,limit:r=1e3,frames:a=1/0,...c},s)=>{const[{context:o,instance:m}]=f.useState((()=>{const e=f.createContext(null);return{context:e,instance:f.forwardRef(((t,r)=>f.createElement(O,u.default({context:e},t,{ref:r}))))}})),y=f.useRef(null),[p,h]=f.useState([]),[[x,g]]=f.useState((()=>{const e=new Float32Array(16*r);for(let t=0;t<r;t++)v.identity().toArray(e,16*t);return[e,new Float32Array([...new Array(3*r)].map((()=>1)))]}));f.useEffect((()=>{y.current.instanceMatrix.needsUpdate=!0}));let P=0,R=0;n.useFrame((()=>{if(a===1/0||P<a){y.current.updateMatrix(),y.current.updateMatrixWorld(),b.copy(y.current.matrixWorld).invert(),R=Math.min(r,void 0!==t?t:r,p.length),y.current.count=R,i.setUpdateRange(y.current.instanceMatrix,{offset:0,count:16*R}),i.setUpdateRange(y.current.instanceColor,{offset:0,count:3*R});for(let e=0;e<p.length;e++){const t=p[e].current;t.matrixWorld.decompose(j,E,A),w.compose(j,E,A).premultiply(b),w.toArray(x,16*e),y.current.instanceMatrix.needsUpdate=!0,t.color.toArray(g,3*e),y.current.instanceColor.needsUpdate=!0}P++}}));const U=f.useMemo((()=>({getParent:()=>y,subscribe:e=>(h((t=>[...t,e])),()=>h((t=>t.filter((t=>t.current!==e.current)))))})),[]);return f.createElement("instancedMesh",u.default({userData:{instances:p},matrixAutoUpdate:!1,ref:d.default([s,y]),args:[null,null,0],raycast:()=>null},c),f.createElement("instancedBufferAttribute",{attach:"instanceMatrix",count:x.length/16,array:x,itemSize:16,usage:l.DynamicDrawUsage}),f.createElement("instancedBufferAttribute",{attach:"instanceColor",count:g.length/3,array:g,itemSize:3,usage:l.DynamicDrawUsage}),"function"==typeof e?f.createElement(o.Provider,{value:U},e(m)):f.createElement(M.Provider,{value:U},e))})),R=f.forwardRef((function({meshes:e,children:t,...r},n){const a=Array.isArray(e);if(!a)for(const t of Object.keys(e))e[t].isMesh||delete e[t];return f.createElement("group",{ref:n},f.createElement(m.default,{components:(a?e:Object.values(e)).map((({geometry:e,material:t})=>f.createElement(P,u.default({key:e.uuid,geometry:e,material:t},r))))},(r=>a?t(...r):t(Object.keys(e).filter((t=>e[t].isMesh)).reduce(((e,t,n)=>({...e,[t]:r[n]})),{})))))}));exports.Instance=O,exports.Instances=P,exports.Merged=R;
|
package/core/Instances.js
CHANGED
|
@@ -4,6 +4,7 @@ import * as React from 'react';
|
|
|
4
4
|
import { extend, useFrame } from '@react-three/fiber';
|
|
5
5
|
import mergeRefs from 'react-merge-refs';
|
|
6
6
|
import Composer from 'react-composer';
|
|
7
|
+
import { setUpdateRange } from '../helpers/deprecated.js';
|
|
7
8
|
|
|
8
9
|
const _instanceLocalMatrix = /* @__PURE__ */new THREE.Matrix4();
|
|
9
10
|
const _instanceWorldMatrix = /* @__PURE__ */new THREE.Matrix4();
|
|
@@ -114,17 +115,23 @@ const Instances = /* @__PURE__ */React.forwardRef(({
|
|
|
114
115
|
// We might be a frame too late? 🤷♂️
|
|
115
116
|
parentRef.current.instanceMatrix.needsUpdate = true;
|
|
116
117
|
});
|
|
118
|
+
let iterations = 0;
|
|
117
119
|
let count = 0;
|
|
118
|
-
let updateRange = 0;
|
|
119
120
|
useFrame(() => {
|
|
120
|
-
if (frames === Infinity ||
|
|
121
|
+
if (frames === Infinity || iterations < frames) {
|
|
121
122
|
parentRef.current.updateMatrix();
|
|
122
123
|
parentRef.current.updateMatrixWorld();
|
|
123
124
|
parentMatrix.copy(parentRef.current.matrixWorld).invert();
|
|
124
|
-
|
|
125
|
-
parentRef.current.count =
|
|
126
|
-
parentRef.current.instanceMatrix
|
|
127
|
-
|
|
125
|
+
count = Math.min(limit, range !== undefined ? range : limit, instances.length);
|
|
126
|
+
parentRef.current.count = count;
|
|
127
|
+
setUpdateRange(parentRef.current.instanceMatrix, {
|
|
128
|
+
offset: 0,
|
|
129
|
+
count: count * 16
|
|
130
|
+
});
|
|
131
|
+
setUpdateRange(parentRef.current.instanceColor, {
|
|
132
|
+
offset: 0,
|
|
133
|
+
count: count * 3
|
|
134
|
+
});
|
|
128
135
|
for (let i = 0; i < instances.length; i++) {
|
|
129
136
|
const instance = instances[i].current;
|
|
130
137
|
// Multiply the inverse of the InstancedMesh world matrix or else
|
|
@@ -136,7 +143,7 @@ const Instances = /* @__PURE__ */React.forwardRef(({
|
|
|
136
143
|
instance.color.toArray(colors, i * 3);
|
|
137
144
|
parentRef.current.instanceColor.needsUpdate = true;
|
|
138
145
|
}
|
|
139
|
-
|
|
146
|
+
iterations++;
|
|
140
147
|
}
|
|
141
148
|
});
|
|
142
149
|
const api = React.useMemo(() => ({
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("@babel/runtime/helpers/extends"),t=require("three"),n=require("react"),r=require("@react-three/fiber"),o=require("./shaderMaterial.cjs.js");function a(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}function l(e){if(e&&e.__esModule)return e;var t=Object.create(null);return e&&Object.keys(e).forEach((function(n){if("default"!==n){var r=Object.getOwnPropertyDescriptor(e,n);Object.defineProperty(t,n,r.get?r:{enumerable:!0,get:function(){return e[n]}})}})),t.default=e,Object.freeze(t)}var c=a(e),s=l(t),i=l(n);const u=o.shaderMaterial({alphaTest:0,viewport:new s.Vector2(1980,1080),focal:1e3,centerAndScaleTexture:null,covAndColorTexture:null},"\n precision highp sampler2D;\n precision highp usampler2D;\n out vec4 vColor;\n out vec3 vPosition;\n uniform vec2 resolution;\n uniform vec2 viewport;\n uniform float focal;\n attribute uint splatIndex;\n uniform sampler2D centerAndScaleTexture;\n uniform usampler2D covAndColorTexture; \n\n vec2 unpackInt16(in uint value) {\n int v = int(value);\n int v0 = v >> 16;\n int v1 = (v & 0xFFFF);\n if((v & 0x8000) != 0)\n v1 |= 0xFFFF0000;\n return vec2(float(v1), float(v0));\n }\n\n void main () {\n ivec2 texSize = textureSize(centerAndScaleTexture, 0);\n ivec2 texPos = ivec2(splatIndex%uint(texSize.x), splatIndex/uint(texSize.x));\n vec4 centerAndScaleData = texelFetch(centerAndScaleTexture, texPos, 0);\n vec4 center = vec4(centerAndScaleData.xyz, 1);\n vec4 camspace = modelViewMatrix * center;\n vec4 pos2d = projectionMatrix * camspace;\n\n float bounds = 1.2 * pos2d.w;\n if (pos2d.z < -pos2d.w || pos2d.x < -bounds || pos2d.x > bounds\n || pos2d.y < -bounds || pos2d.y > bounds) {\n gl_Position = vec4(0.0, 0.0, 2.0, 1.0);\n return;\n }\n\n uvec4 covAndColorData = texelFetch(covAndColorTexture, texPos, 0);\n vec2 cov3D_M11_M12 = unpackInt16(covAndColorData.x) * centerAndScaleData.w;\n vec2 cov3D_M13_M22 = unpackInt16(covAndColorData.y) * centerAndScaleData.w;\n vec2 cov3D_M23_M33 = unpackInt16(covAndColorData.z) * centerAndScaleData.w;\n mat3 Vrk = mat3(\n cov3D_M11_M12.x, cov3D_M11_M12.y, cov3D_M13_M22.x,\n cov3D_M11_M12.y, cov3D_M13_M22.y, cov3D_M23_M33.x,\n cov3D_M13_M22.x, cov3D_M23_M33.x, cov3D_M23_M33.y\n );\n\n mat3 J = mat3(\n focal / camspace.z, 0., -(focal * camspace.x) / (camspace.z * camspace.z),\n 0., focal / camspace.z, -(focal * camspace.y) / (camspace.z * camspace.z),\n 0., 0., 0.\n );\n\n mat3 W = transpose(mat3(modelViewMatrix));\n mat3 T = W * J;\n mat3 cov = transpose(T) * Vrk * T;\n vec2 vCenter = vec2(pos2d) / pos2d.w;\n float diagonal1 = cov[0][0] + 0.3;\n float offDiagonal = cov[0][1];\n float diagonal2 = cov[1][1] + 0.3;\n float mid = 0.5 * (diagonal1 + diagonal2);\n float radius = length(vec2((diagonal1 - diagonal2) / 2.0, offDiagonal));\n float lambda1 = mid + radius;\n float lambda2 = max(mid - radius, 0.1);\n vec2 diagonalVector = normalize(vec2(offDiagonal, lambda1 - diagonal1));\n vec2 v1 = min(sqrt(2.0 * lambda1), 1024.0) * diagonalVector;\n vec2 v2 = min(sqrt(2.0 * lambda2), 1024.0) * vec2(diagonalVector.y, -diagonalVector.x);\n uint colorUint = covAndColorData.w;\n vColor = vec4(\n float(colorUint & uint(0xFF)) / 255.0,\n float((colorUint >> uint(8)) & uint(0xFF)) / 255.0,\n float((colorUint >> uint(16)) & uint(0xFF)) / 255.0,\n float(colorUint >> uint(24)) / 255.0\n );\n vPosition = position;\n\n gl_Position = vec4(\n vCenter \n + position.x * v2 / viewport * 2.0 \n + position.y * v1 / viewport * 2.0, pos2d.z / pos2d.w, 1.0);\n }\n ",`\n #include <alphatest_pars_fragment>\n #include <alphahash_pars_fragment>\n in vec4 vColor;\n in vec3 vPosition;\n void main () {\n float A = -dot(vPosition.xy, vPosition.xy);\n if (A < -4.0) discard;\n float B = exp(A) * vColor.a;\n vec4 diffuseColor = vec4(vColor.rgb, B);\n #include <alphatest_fragment>\n #include <alphahash_fragment>\n gl_FragColor = diffuseColor;\n #include <tonemapping_fragment>\n #include <${parseInt(s.REVISION.replace(/\D+/g,""))>=154?"colorspace_fragment":"encodings_fragment"}>\n }\n `);function d(e){let t=null,n=0;e.onmessage=r=>{if("push"==r.data.method){0===n&&(t=new Float32Array(r.data.length));const e=new Float32Array(r.data.matrices);t.set(e,n),n+=e.length}else if("sort"==r.data.method&&null!==t){const n=function(e,n=!1){const r=t.length/16;let o=-1/0,a=1/0;const l=new Float32Array(r),c=new Int32Array(l.buffer),s=new Int32Array(r);let i=0;for(let c=0;c<r;c++){const r=e[0]*t[16*c+12]+e[1]*t[16*c+13]+e[2]*t[16*c+14]+e[3];(n||r<0&&t[16*c+15]>-1e-4*r)&&(l[i]=r,s[i]=c,i++,r>o&&(o=r),r<a&&(a=r))}const u=65535/(o-a),d=new Uint32Array(65536);for(let e=0;e<i;e++)c[e]=(l[e]-a)*u|0,d[c[e]]++;const f=new Uint32Array(65536);for(let e=1;e<65536;e++)f[e]=f[e-1]+d[e-1];const x=new Uint32Array(i);for(let e=0;e<i;e++)x[f[c[e]]++]=s[e];return x}(new Float32Array(r.data.view),r.data.hashed);e.postMessage({indices:n,key:r.data.key},[n.buffer])}}}class f extends s.Loader{constructor(...e){super(...e),this.gl=null,this.chunkSize=25e3}load(e,t,n,r){const o={gl:this.gl,url:this.manager.resolveURL(e),worker:new Worker(URL.createObjectURL(new Blob(["(",d.toString(),")(self)"],{type:"application/javascript"}))),manager:this.manager,update:(e,t,n)=>function(e,t,n,r){if(e.updateMatrixWorld(),t.gl.getCurrentViewport(n.viewport),n.material.viewport.x=n.viewport.z,n.material.viewport.y=n.viewport.w,n.material.focal=n.viewport.w/2*Math.abs(e.projectionMatrix.elements[5]),n.ready){if(r&&n.sorted)return;n.ready=!1;const e=new Float32Array([n.modelViewMatrix.elements[2],-n.modelViewMatrix.elements[6],n.modelViewMatrix.elements[10],n.modelViewMatrix.elements[14]]);t.worker.postMessage({method:"sort",src:t.url,key:n.uuid,view:e.buffer,hashed:r},[e.buffer]),r&&t.loaded&&(n.sorted=!0)}}(t,o,e,n),connect:e=>function(e,t){e.loading||async function(e){e.loading=!0;let t=0,n=0;const r=[];let o=0;const a=0!==e.totalDownloadBytes;for(;;)try{const{value:l,done:c}=await e.stream.read();if(c)break;if(t+=l.length,null!=e.totalDownloadBytes){const n=t/e.totalDownloadBytes*100;if(e.onProgress&&n-o>1){const r=new ProgressEvent("progress",{lengthComputable:a,loaded:t,total:e.totalDownloadBytes});e.onProgress(r),o=n}}r.push(l);const s=t-n;if(null!=e.totalDownloadBytes&&s>e.rowLength*e.chunkSize){let t=Math.floor(s/e.rowLength);const o=new Uint8Array(s);let l=0;for(const e of r)o.set(e,l),l+=e.length;if(r.length=0,s>t*e.rowLength){const n=new Uint8Array(s-t*e.rowLength);n.set(o.subarray(s-n.length,s),0),r.push(n)}const c=new Uint8Array(t*e.rowLength);c.set(o.subarray(0,c.byteLength),0);const i=x(e,c.buffer,t);if(e.worker.postMessage({method:"push",src:e.url,length:16*e.numVertices,matrices:i.buffer},[i.buffer]),n+=t*e.rowLength,e.onProgress){const t=new ProgressEvent("progress",{lengthComputable:a,loaded:e.totalDownloadBytes,total:e.totalDownloadBytes});e.onProgress(t)}}}catch(e){console.error(e);break}if(t-n>0){let t=new Uint8Array(r.reduce(((e,t)=>e+t.length),0)),n=0;for(const e of r)t.set(e,n),n+=e.length;let o=Math.floor(t.byteLength/e.rowLength);const a=x(e,t.buffer,o);e.worker.postMessage({method:"push",src:e.url,length:16*o,matrices:a.buffer},[a.buffer])}e.loaded=!0,e.manager.itemEnd(e.url)}(e);t.ready=!1,t.pm=new s.Matrix4,t.vm1=new s.Matrix4,t.vm2=new s.Matrix4,t.viewport=new s.Vector4;let n=new Uint32Array(e.bufferTextureWidth*e.bufferTextureHeight);const r=new s.InstancedBufferAttribute(n,1,!1);r.setUsage(s.DynamicDrawUsage);const o=t.geometry=new s.InstancedBufferGeometry,a=new Float32Array(18),l=new s.BufferAttribute(a,3);function c(e){if(t&&e.data.key===t.uuid){let n=new Uint32Array(e.data.indices);o.attributes.splatIndex.set(n),o.attributes.splatIndex.needsUpdate=!0,o.instanceCount=n.length,t.ready=!0}}async function i(){for(;;){const t=e.gl.properties.get(e.centerAndScaleTexture),n=e.gl.properties.get(e.covAndColorTexture);if(null!=t&&t.__webglTexture&&null!=n&&n.__webglTexture&&e.loadedVertexCount>0)break;await new Promise((e=>setTimeout(e,10)))}t.ready=!0}return o.setAttribute("position",l),l.setXYZ(2,-2,2,0),l.setXYZ(1,2,2,0),l.setXYZ(0,-2,-2,0),l.setXYZ(5,-2,-2,0),l.setXYZ(4,2,2,0),l.setXYZ(3,2,-2,0),l.needsUpdate=!0,o.setAttribute("splatIndex",r),o.instanceCount=1,e.worker.addEventListener("message",c),i(),()=>e.worker.removeEventListener("message",c)}(o,e),loading:!1,loaded:!1,loadedVertexCount:0,chunkSize:this.chunkSize,totalDownloadBytes:0,numVertices:0,rowLength:32,maxVertexes:0,bufferTextureWidth:0,bufferTextureHeight:0,stream:null,centerAndScaleData:null,covAndColorData:null,covAndColorTexture:null,centerAndScaleTexture:null,onProgress:n};(async function(e){e.manager.itemStart(e.url);const t=await fetch(e.url);if(null===t.body)throw"Failed to fetch file";let n=t.headers.get("Content-Length");const r=n?parseInt(n):void 0;if(null==r)throw"Failed to get content length";e.stream=t.body.getReader(),e.totalDownloadBytes=r,e.numVertices=Math.floor(e.totalDownloadBytes/e.rowLength);const o=e.gl.getContext();let a=o.getParameter(o.MAX_TEXTURE_SIZE);e.maxVertexes=a*a,e.numVertices>e.maxVertexes&&(e.numVertices=e.maxVertexes);return e.bufferTextureWidth=a,e.bufferTextureHeight=Math.floor((e.numVertices-1)/a)+1,e.centerAndScaleData=new Float32Array(e.bufferTextureWidth*e.bufferTextureHeight*4),e.covAndColorData=new Uint32Array(e.bufferTextureWidth*e.bufferTextureHeight*4),e.centerAndScaleTexture=new s.DataTexture(e.centerAndScaleData,e.bufferTextureWidth,e.bufferTextureHeight,s.RGBAFormat,s.FloatType),e.centerAndScaleTexture.needsUpdate=!0,e.covAndColorTexture=new s.DataTexture(e.covAndColorData,e.bufferTextureWidth,e.bufferTextureHeight,s.RGBAIntegerFormat,s.UnsignedIntType),e.covAndColorTexture.internalFormat="RGBA32UI",e.covAndColorTexture.needsUpdate=!0,e})(o).then(t).catch((e=>{null==r||r(e),o.manager.itemError(o.url)}))}}function x(e,t,n){const r=e.gl.getContext();if(e.loadedVertexCount+n>e.maxVertexes&&(n=e.maxVertexes-e.loadedVertexCount),n<=0)throw"Failed to parse file";const o=new Uint8Array(t),a=new Float32Array(t),l=new Float32Array(16*n),c=new Uint8Array(e.covAndColorData.buffer),i=new Int16Array(e.covAndColorData.buffer);for(let t=0;t<n;t++){const n=new s.Quaternion(-(o[32*t+28+1]-128)/128,(o[32*t+28+2]-128)/128,(o[32*t+28+3]-128)/128,-(o[32*t+28+0]-128)/128);n.invert();const r=new s.Vector3(a[8*t+0],a[8*t+1],-a[8*t+2]),u=new s.Vector3(a[8*t+3+0],a[8*t+3+1],a[8*t+3+2]),d=new s.Matrix4;d.makeRotationFromQuaternion(n),d.transpose(),d.scale(u);const f=d.clone();d.transpose(),d.premultiply(f),d.setPosition(r);const x=[0,1,2,5,6,10];let p=0;for(let e=0;e<x.length;e++)Math.abs(d.elements[x[e]])>p&&(p=Math.abs(d.elements[x[e]]));let g=4*e.loadedVertexCount+4*t;e.centerAndScaleData[g+0]=r.x,e.centerAndScaleData[g+1]=-r.y,e.centerAndScaleData[g+2]=r.z,e.centerAndScaleData[g+3]=p/32767,g=8*e.loadedVertexCount+4*t*2;for(let e=0;e<x.length;e++)i[g+e]=32767*d.elements[x[e]]/p;g=16*e.loadedVertexCount+4*(4*t+3);const m=new s.Color(o[32*t+24+0]/255,o[32*t+24+1]/255,o[32*t+24+2]/255);m.convertSRGBToLinear(),c[g+0]=255*m.r,c[g+1]=255*m.g,c[g+2]=255*m.b,c[g+3]=o[32*t+24+3],d.elements[15]=Math.max(u.x,u.y,u.z)*o[32*t+24+3]/255;for(let e=0;e<16;e++)l[16*t+e]=d.elements[e]}for(;n>0;){let t=0,o=0;const a=e.loadedVertexCount%e.bufferTextureWidth,l=Math.floor(e.loadedVertexCount/e.bufferTextureWidth);e.loadedVertexCount%e.bufferTextureWidth!=0?(t=Math.min(e.bufferTextureWidth,a+n)-a,o=1):Math.floor(n/e.bufferTextureWidth)>0?(t=e.bufferTextureWidth,o=Math.floor(n/e.bufferTextureWidth)):(t=n%e.bufferTextureWidth,o=1);const c=e.gl.properties.get(e.centerAndScaleTexture);r.bindTexture(r.TEXTURE_2D,c.__webglTexture),r.texSubImage2D(r.TEXTURE_2D,0,a,l,t,o,r.RGBA,r.FLOAT,e.centerAndScaleData,4*e.loadedVertexCount);const s=e.gl.properties.get(e.covAndColorTexture);r.bindTexture(r.TEXTURE_2D,s.__webglTexture),r.texSubImage2D(r.TEXTURE_2D,0,a,l,t,o,r.RGBA_INTEGER,r.UNSIGNED_INT,e.covAndColorData,4*e.loadedVertexCount),e.gl.resetState(),e.loadedVertexCount+=t*o,n-=t*o}return l}exports.Splat=function({src:e,toneMapped:t=!1,alphaTest:n=0,alphaHash:o=!1,chunkSize:a=25e3,...l}){r.extend({SplatMaterial:u});const d=i.useRef(null),x=r.useThree((e=>e.gl)),p=r.useThree((e=>e.camera)),g=r.useLoader(f,e,(e=>{e.gl=x,e.chunkSize=a}));return i.useLayoutEffect((()=>g.connect(d.current)),[e]),r.useFrame((()=>g.update(d.current,p,o))),i.createElement("mesh",c.default({ref:d,frustumCulled:!1},l),i.createElement("splatMaterial",{key:`${e}/${n}/${o}${u.key}`,transparent:!o,depthTest:!0,alphaTest:o?0:n,centerAndScaleTexture:g.centerAndScaleTexture,covAndColorTexture:g.covAndColorTexture,depthWrite:!!o||n>0,blending:o?s.NormalBlending:s.CustomBlending,blendSrcAlpha:s.OneFactor,alphaHash:!!o,toneMapped:t}))};
|
package/core/Splat.d.ts
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import * as THREE from 'three';
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
export type SplatMaterialType = {
|
|
4
|
+
alphaTest?: number;
|
|
5
|
+
alphaHash?: boolean;
|
|
6
|
+
centerAndScaleTexture?: THREE.DataTexture;
|
|
7
|
+
covAndColorTexture?: THREE.DataTexture;
|
|
8
|
+
viewport?: THREE.Vector2;
|
|
9
|
+
focal?: number;
|
|
10
|
+
};
|
|
11
|
+
export type TargetMesh = THREE.Mesh<THREE.InstancedBufferGeometry, THREE.ShaderMaterial & SplatMaterialType> & {
|
|
12
|
+
ready: boolean;
|
|
13
|
+
sorted: boolean;
|
|
14
|
+
pm: THREE.Matrix4;
|
|
15
|
+
vm1: THREE.Matrix4;
|
|
16
|
+
vm2: THREE.Matrix4;
|
|
17
|
+
viewport: THREE.Vector4;
|
|
18
|
+
};
|
|
19
|
+
export type SharedState = {
|
|
20
|
+
url: string;
|
|
21
|
+
gl: THREE.WebGLRenderer;
|
|
22
|
+
worker: Worker;
|
|
23
|
+
manager: THREE.LoadingManager;
|
|
24
|
+
stream: ReadableStreamDefaultReader<Uint8Array>;
|
|
25
|
+
loading: boolean;
|
|
26
|
+
loaded: boolean;
|
|
27
|
+
loadedVertexCount: number;
|
|
28
|
+
rowLength: number;
|
|
29
|
+
maxVertexes: number;
|
|
30
|
+
chunkSize: number;
|
|
31
|
+
totalDownloadBytes: number;
|
|
32
|
+
numVertices: number;
|
|
33
|
+
bufferTextureWidth: number;
|
|
34
|
+
bufferTextureHeight: number;
|
|
35
|
+
centerAndScaleData: Float32Array;
|
|
36
|
+
covAndColorData: Uint32Array;
|
|
37
|
+
covAndColorTexture: THREE.DataTexture;
|
|
38
|
+
centerAndScaleTexture: THREE.DataTexture;
|
|
39
|
+
connect(target: TargetMesh): () => void;
|
|
40
|
+
update(target: TargetMesh, camera: THREE.Camera, hashed: boolean): void;
|
|
41
|
+
onProgress?: (event: ProgressEvent) => void;
|
|
42
|
+
};
|
|
43
|
+
declare global {
|
|
44
|
+
namespace JSX {
|
|
45
|
+
interface IntrinsicElements {
|
|
46
|
+
splatMaterial: SplatMaterialType & JSX.IntrinsicElements['shaderMaterial'];
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
type SplatProps = {
|
|
51
|
+
src: string;
|
|
52
|
+
toneMapped?: boolean;
|
|
53
|
+
alphaTest?: number;
|
|
54
|
+
alphaHash?: boolean;
|
|
55
|
+
chunkSize?: number;
|
|
56
|
+
} & JSX.IntrinsicElements['mesh'];
|
|
57
|
+
export declare function Splat({ src, toneMapped, alphaTest, alphaHash, chunkSize, ...props }: SplatProps): React.JSX.Element;
|
|
58
|
+
export {};
|