@react-three/drei 9.86.0 → 9.86.2

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 CHANGED
@@ -4471,7 +4471,9 @@ attribute vec3 color;
4471
4471
  [![](https://img.shields.io/badge/-storybook-%23ff69b4)](https://drei.pmnd.rs/?path=/story/staging-cloud--cloud-st) ![](https://img.shields.io/badge/-suspense-brightgreen)
4472
4472
 
4473
4473
  <p>
4474
+ <a href="https://codesandbox.io/s/gwthnh"><img width="20%" src="https://codesandbox.io/api/v1/sandboxes/gwthnh/screenshot.png" alt="Demo"/></a>
4474
4475
  <a href="https://codesandbox.io/s/mbfzf"><img width="20%" src="https://codesandbox.io/api/v1/sandboxes/mbfzf/screenshot.png" alt="Demo"/></a>
4476
+
4475
4477
  </p>
4476
4478
 
4477
4479
  Particle based cloud.
@@ -4495,17 +4497,24 @@ type CloudProps = JSX.IntrinsicElements['group'] & {
4495
4497
  segments?: number
4496
4498
  /** The box3 bounds of the cloud, default: [5, 1, 1] */
4497
4499
  bounds?: ReactThreeFiber.Vector3
4500
+ /** How to arrange segment volume inside the bounds, default: inside (cloud are smaller at the edges) */
4501
+ concentrate?: 'random' | 'inside' | 'outside'
4498
4502
  /** The general scale of the segments */
4499
4503
  scale?: ReactThreeFiber.Vector3
4500
4504
  /** The volume/thickness of the segments, default: 6 */
4501
4505
  volume?: number
4506
+ /** The smallest volume when distributing clouds, default: 0.25 */
4507
+ smallestVolume?: number
4508
+ /** An optional function that allows you to distribute points and volumes (overriding all settings), default: null
4509
+ * Both point and volume are factors, point x/y/z can be between -1 and 1, volume between 0 and 1 */
4510
+ distribute?: (cloud: CloudState, index: number) => { point: Vector3; volume?: number }
4502
4511
  /** Growth factor for animated clouds (speed > 0), default: 4 */
4503
4512
  growth?: number
4504
- /** Animation factor, default: 0.1 */
4513
+ /** Animation factor, default: 0 */
4505
4514
  speed?: number
4506
4515
  /** Camera distance until the segments will fade, default: 10 */
4507
4516
  fade?: number
4508
- /** Opacity, default: 0.8 */
4517
+ /** Opacity, default: 1 */
4509
4518
  opacity?: number
4510
4519
  /** Color, default: white */
4511
4520
  color?: ReactThreeFiber.Color
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 u(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 i=u(e),s=c(t);const l=new r.Matrix4,d=new r.Vector3,f=new r.Quaternion,p=new r.Vector3,m=new r.Quaternion,g=new r.Vector3,h=s.createContext(null),y=s.forwardRef((({children:e,material:t=r.MeshLambertMaterial,texture:o="https://rawcdn.githack.com/pmndrs/drei-assets/9225a9f1fbd449d9411125c2f419b843d0308c9f/cloud.png",range:u,limit:c=200,...y},x)=>{var b,M;const v=s.useMemo((()=>class extends t{constructor(){super(),this.onBeforeCompile=e=>{e.vertexShader="attribute float opacity;\n varying float vOpacity;\n "+e.vertexShader.replace("#include <fog_vertex>","#include <fog_vertex>\n vOpacity = opacity;\n "),e.fragmentShader="varying float vOpacity;\n "+e.fragmentShader.replace("#include <opaque_fragment>","#include <opaque_fragment>\n gl_FragColor = vec4(outgoingLight, diffuseColor.a * vOpacity);\n ")}}}),[t]);n.extend({CloudMaterial:v});const w=s.useRef(null),C=s.useRef([]),E=s.useMemo((()=>new Float32Array(Array.from({length:c},(()=>1)))),[c]),A=s.useMemo((()=>new Float32Array(Array.from({length:c},(()=>[1,1,1])).flat())),[c]),O=a.useTexture(o);let j,R=0,_=0;const q=new r.Quaternion,F=new r.Vector3(0,0,1),V=new r.Vector3;n.useFrame(((e,t)=>{for(R=e.clock.getElapsedTime(),l.copy(w.current.matrixWorld).invert(),e.camera.matrixWorld.decompose(p,m,g),_=0;_<C.current.length;_++)j=C.current[_],j.ref.current.matrixWorld.decompose(d,f,g),d.add(V.copy(j.position).applyQuaternion(f)),f.copy(m).multiply(q.setFromAxisAngle(F,j.rotation+=t*j.rotationFactor)),g.addScalar(j.volume+(1+Math.sin(R*j.density*j.speed))/2*j.growth),j.matrix.compose(d,f,g).premultiply(l),j.dist=d.distanceTo(p);for(C.current.sort(((e,t)=>t.dist-e.dist)),_=0;_<C.current.length;_++)j=C.current[_],E[_]=j.opacity*(j.dist<j.fade-1?j.dist/j.fade:1),w.current.setMatrixAt(_,j.matrix),w.current.setColorAt(_,j.color);w.current.geometry.attributes.opacity.needsUpdate=!0,w.current.instanceMatrix.needsUpdate=!0,w.current.instanceColor&&(w.current.instanceColor.needsUpdate=!0)})),s.useLayoutEffect((()=>{const e=Math.min(c,void 0!==u?u:c,C.current.length);w.current.count=e,w.current.instanceMatrix.updateRange.count=16*e,w.current.instanceColor&&(w.current.instanceColor.updateRange.count=3*e),w.current.geometry.attributes.opacity.updateRange.count=e}));let P=[null!==(b=O.image.width)&&void 0!==b?b:1,null!==(M=O.image.height)&&void 0!==M?M:1],S=Math.max(P[0],P[1]);return P=[P[0]/S,P[1]/S],s.createElement("group",i.default({ref:x},y),s.createElement(h.Provider,{value:C},e,s.createElement("instancedMesh",{matrixAutoUpdate:!1,ref:w,args:[null,null,c]},s.createElement("instancedBufferAttribute",{usage:r.DynamicDrawUsage,attach:"instanceColor",args:[A,3]}),s.createElement("planeGeometry",{args:[...P]},s.createElement("instancedBufferAttribute",{usage:r.DynamicDrawUsage,attach:"attributes-opacity",args:[E,1]})),s.createElement("cloudMaterial",{key:t.name,map:O,transparent:!0,depthWrite:!1}))))})),x=s.forwardRef((({opacity:e=1,speed:t=0,bounds:a=[5,1,1],segments:u=20,color:c="#ffffff",fade:l=10,volume:d=6,growth:f=4,seed:p=Math.random(),...m},g)=>{function y(){const e=1e4*Math.sin(p++);return e-Math.floor(e)}const x=s.useContext(h),b=s.useRef(null),[M]=s.useState((()=>o.v4())),v=s.useMemo((()=>[...new Array(u)].map(((e,t)=>({segments:u,bounds:new r.Vector3(1,1,1),position:new r.Vector3,uuid:M,index:t,ref:b,dist:0,matrix:new r.Matrix4,color:new r.Color,rotation:t*(Math.PI/u)})))),[u,M]);return s.useLayoutEffect((()=>{v.forEach(((r,o)=>{n.applyProps(r,{color:c,speed:t,growth:f,opacity:e,fade:l,bounds:a,density:Math.max(.5,y()),rotationFactor:Math.max(.2,.5*y())*t}),u>1&&r.position.copy(r.bounds).multiply({x:2*y()-1,y:2*y()-1,z:2*y()-1});const i=Math.abs(r.position.x),s=Math.abs(r.position.y),p=Math.abs(r.position.z),m=Math.max(i,s,p);r.length=1,i===m&&(r.length-=i/r.bounds.x),s===m&&(r.length-=s/r.bounds.y),p===m&&(r.length-=p/r.bounds.z),r.volume=Math.max(.25,r.length)*d}))}),[a,l,c,e,f,d,p,u,t]),s.useLayoutEffect((()=>{const e=v;return x.current=[...x.current,...e],()=>{x.current=x.current.filter((e=>e.uuid!==M))}}),[v]),s.useImperativeHandle(g,(()=>b.current),[]),s.createElement("group",i.default({ref:b},m))})),b=s.forwardRef(((e,t)=>s.useContext(h)?s.createElement(x,i.default({ref:t},e)):s.createElement(y,null,s.createElement(x,i.default({ref:t},e)))));exports.Cloud=b,exports.CloudInstance=x,exports.Clouds=y;
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 u(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}function i(e){if(e&&e.__esModule)return e;var t=Object.create(null);return e&&Object.keys(e).forEach((function(r){if("default"!==r){var n=Object.getOwnPropertyDescriptor(e,r);Object.defineProperty(t,r,n.get?n:{enumerable:!0,get:function(){return e[r]}})}})),t.default=e,Object.freeze(t)}var c=u(e),l=i(t);const s=new r.Matrix4,d=new r.Vector3,f=new r.Quaternion,m=new r.Vector3,p=new r.Quaternion,g=new r.Vector3,h=l.createContext(null),y=l.forwardRef((({children:e,material:t=r.MeshLambertMaterial,texture:o="https://rawcdn.githack.com/pmndrs/drei-assets/9225a9f1fbd449d9411125c2f419b843d0308c9f/cloud.png",range:u,limit:i=200,...y},x)=>{var v,b;const M=l.useMemo((()=>class extends t{constructor(){super(),this.onBeforeCompile=e=>{e.vertexShader="attribute float opacity;\n varying float vOpacity;\n "+e.vertexShader.replace("#include <fog_vertex>","#include <fog_vertex>\n vOpacity = opacity;\n "),e.fragmentShader="varying float vOpacity;\n "+e.fragmentShader.replace("#include <opaque_fragment>","#include <opaque_fragment>\n gl_FragColor = vec4(outgoingLight, diffuseColor.a * vOpacity);\n ")}}}),[t]);n.extend({CloudMaterial:M});const w=l.useRef(null),C=l.useRef([]),E=l.useMemo((()=>new Float32Array(Array.from({length:i},(()=>1)))),[i]),A=l.useMemo((()=>new Float32Array(Array.from({length:i},(()=>[1,1,1])).flat())),[i]),O=a.useTexture(o);let j,R=0,_=0;const q=new r.Quaternion,V=new r.Vector3(0,0,1),F=new r.Vector3;n.useFrame(((e,t)=>{for(R=e.clock.getElapsedTime(),s.copy(w.current.matrixWorld).invert(),e.camera.matrixWorld.decompose(m,p,g),_=0;_<C.current.length;_++)j=C.current[_],j.ref.current.matrixWorld.decompose(d,f,g),d.add(F.copy(j.position).applyQuaternion(f)),f.copy(p).multiply(q.setFromAxisAngle(V,j.rotation+=t*j.rotationFactor)),g.addScalar(j.volume+(1+Math.sin(R*j.density*j.speed))/2*j.growth),j.matrix.compose(d,f,g).premultiply(s),j.dist=d.distanceTo(m);for(C.current.sort(((e,t)=>t.dist-e.dist)),_=0;_<C.current.length;_++)j=C.current[_],E[_]=j.opacity*(j.dist<j.fade-1?j.dist/j.fade:1),w.current.setMatrixAt(_,j.matrix),w.current.setColorAt(_,j.color);w.current.geometry.attributes.opacity.needsUpdate=!0,w.current.instanceMatrix.needsUpdate=!0,w.current.instanceColor&&(w.current.instanceColor.needsUpdate=!0)})),l.useLayoutEffect((()=>{const e=Math.min(i,void 0!==u?u:i,C.current.length);w.current.count=e,w.current.instanceMatrix.updateRange.count=16*e,w.current.instanceColor&&(w.current.instanceColor.updateRange.count=3*e),w.current.geometry.attributes.opacity.updateRange.count=e}));let P=[null!==(v=O.image.width)&&void 0!==v?v:1,null!==(b=O.image.height)&&void 0!==b?b:1],S=Math.max(P[0],P[1]);return P=[P[0]/S,P[1]/S],l.createElement("group",c.default({ref:x},y),l.createElement(h.Provider,{value:C},e,l.createElement("instancedMesh",{matrixAutoUpdate:!1,ref:w,args:[null,null,i]},l.createElement("instancedBufferAttribute",{usage:r.DynamicDrawUsage,attach:"instanceColor",args:[A,3]}),l.createElement("planeGeometry",{args:[...P]},l.createElement("instancedBufferAttribute",{usage:r.DynamicDrawUsage,attach:"attributes-opacity",args:[E,1]})),l.createElement("cloudMaterial",{key:t.name,map:O,transparent:!0,depthWrite:!1}))))})),x=l.forwardRef((({opacity:e=1,speed:t=0,bounds:a=[5,1,1],segments:u=20,color:i="#ffffff",fade:s=10,volume:d=6,smallestVolume:f=.25,distribute:m=null,growth:p=4,concentrate:g="inside",seed:y=Math.random(),...x},v)=>{function b(){const e=1e4*Math.sin(y++);return e-Math.floor(e)}const M=l.useContext(h),w=l.useRef(null),[C]=l.useState((()=>o.v4())),E=l.useMemo((()=>[...new Array(u)].map(((e,t)=>({segments:u,bounds:new r.Vector3(1,1,1),position:new r.Vector3,uuid:C,index:t,ref:w,dist:0,matrix:new r.Matrix4,color:new r.Color,rotation:t*(Math.PI/u)})))),[u,C]);return l.useLayoutEffect((()=>{E.forEach(((r,o)=>{var c;n.applyProps(r,{volume:d,color:i,speed:t,growth:p,opacity:e,fade:s,bounds:a,density:Math.max(.5,b()),rotationFactor:Math.max(.2,.5*b())*t});const l=null==m?void 0:m(r,o);(l||u>1)&&r.position.copy(r.bounds).multiply(null!==(c=null==l?void 0:l.point)&&void 0!==c?c:{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,s,i,e,p,d,y,u,t]),l.useLayoutEffect((()=>{const e=E;return M.current=[...M.current,...e],()=>{M.current=M.current.filter((e=>e.uuid!==C))}}),[E]),l.useImperativeHandle(v,(()=>w.current),[]),l.createElement("group",c.default({ref:w},x))})),v=l.forwardRef(((e,t)=>l.useContext(h)?l.createElement(x,c.default({ref:t},e)):l.createElement(y,null,l.createElement(x,c.default({ref:t},e)))));exports.Cloud=v,exports.CloudInstance=x,exports.Clouds=y;
package/core/Cloud.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import * as React from 'react';
2
- import { Group, Material, MeshLambertMaterial } from 'three';
2
+ import { Color, Group, Vector3, Material, MeshLambertMaterial, Matrix4 } from 'three';
3
3
  import { MaterialNode, ReactThreeFiber } from '@react-three/fiber';
4
4
  declare global {
5
5
  namespace JSX {
@@ -8,6 +8,26 @@ declare global {
8
8
  }
9
9
  }
10
10
  }
11
+ type CloudState = {
12
+ uuid: string;
13
+ index: number;
14
+ segments: number;
15
+ dist: number;
16
+ matrix: Matrix4;
17
+ bounds: Vector3;
18
+ position: Vector3;
19
+ volume: number;
20
+ length: number;
21
+ ref: React.MutableRefObject<Group>;
22
+ speed: number;
23
+ growth: number;
24
+ opacity: number;
25
+ fade: number;
26
+ density: number;
27
+ rotation: number;
28
+ rotationFactor: number;
29
+ color: Color;
30
+ };
11
31
  type CloudsProps = JSX.IntrinsicElements['group'] & {
12
32
  texture?: string;
13
33
  limit?: number;
@@ -18,8 +38,14 @@ type CloudProps = JSX.IntrinsicElements['group'] & {
18
38
  seed?: number;
19
39
  segments?: number;
20
40
  bounds?: ReactThreeFiber.Vector3;
41
+ concentrate?: 'random' | 'inside' | 'outside';
21
42
  scale?: ReactThreeFiber.Vector3;
22
43
  volume?: number;
44
+ smallestVolume?: number;
45
+ distribute?: (cloud: CloudState, index: number) => {
46
+ point: Vector3;
47
+ volume?: number;
48
+ };
23
49
  growth?: number;
24
50
  speed?: number;
25
51
  fade?: number;
package/core/Cloud.js CHANGED
@@ -147,7 +147,10 @@ const CloudInstance = /*@__PURE__*/React.forwardRef(({
147
147
  color = '#ffffff',
148
148
  fade = 10,
149
149
  volume = 6,
150
+ smallestVolume = 0.25,
151
+ distribute = null,
150
152
  growth = 4,
153
+ concentrate = 'inside',
151
154
  seed = Math.random(),
152
155
  ...props
153
156
  }, fref) => {
@@ -174,7 +177,9 @@ const CloudInstance = /*@__PURE__*/React.forwardRef(({
174
177
  }, [segments, uuid]);
175
178
  React.useLayoutEffect(() => {
176
179
  clouds.forEach((cloud, index) => {
180
+ var _distributed$point;
177
181
  applyProps(cloud, {
182
+ volume,
178
183
  color,
179
184
  speed,
180
185
  growth,
@@ -185,7 +190,9 @@ const CloudInstance = /*@__PURE__*/React.forwardRef(({
185
190
  rotationFactor: Math.max(0.2, 0.5 * random()) * speed
186
191
  });
187
192
  // Only distribute randomly if there are multiple segments
188
- if (segments > 1) cloud.position.copy(cloud.bounds).multiply({
193
+
194
+ const distributed = distribute == null ? void 0 : distribute(cloud, index);
195
+ if (distributed || segments > 1) cloud.position.copy(cloud.bounds).multiply((_distributed$point = distributed == null ? void 0 : distributed.point) !== null && _distributed$point !== void 0 ? _distributed$point : {
189
196
  x: random() * 2 - 1,
190
197
  y: random() * 2 - 1,
191
198
  z: random() * 2 - 1
@@ -198,9 +205,9 @@ const CloudInstance = /*@__PURE__*/React.forwardRef(({
198
205
  if (xDiff === max) cloud.length -= xDiff / cloud.bounds.x;
199
206
  if (yDiff === max) cloud.length -= yDiff / cloud.bounds.y;
200
207
  if (zDiff === max) cloud.length -= zDiff / cloud.bounds.z;
201
- cloud.volume = Math.max(0.25, cloud.length) * volume;
208
+ cloud.volume = ((distributed == null ? void 0 : distributed.volume) !== undefined ? distributed.volume : Math.max(Math.max(0, smallestVolume), concentrate === 'random' ? random() : concentrate === 'inside' ? cloud.length : 1 - cloud.length)) * volume;
202
209
  });
203
- }, [bounds, fade, color, opacity, growth, volume, seed, segments, speed]);
210
+ }, [concentrate, bounds, fade, color, opacity, growth, volume, seed, segments, speed]);
204
211
  React.useLayoutEffect(() => {
205
212
  const temp = clouds;
206
213
  parent.current = [...parent.current, ...temp];