Initial project import
This commit is contained in:
231
node_modules/@react-three/drei/core/Cloud.js
generated
vendored
Normal file
231
node_modules/@react-three/drei/core/Cloud.js
generated
vendored
Normal file
@@ -0,0 +1,231 @@
|
||||
import _extends from '@babel/runtime/helpers/esm/extends';
|
||||
import * as React from 'react';
|
||||
import { REVISION, Quaternion, Vector3, DynamicDrawUsage, MeshLambertMaterial, Matrix4, Color } from 'three';
|
||||
import { extend, useFrame, applyProps } from '@react-three/fiber';
|
||||
import { useTexture } from './Texture.js';
|
||||
import { setUpdateRange } from '../helpers/deprecated.js';
|
||||
|
||||
const CLOUD_URL = 'https://rawcdn.githack.com/pmndrs/drei-assets/9225a9f1fbd449d9411125c2f419b843d0308c9f/cloud.png';
|
||||
const parentMatrix = /* @__PURE__ */new Matrix4();
|
||||
const translation = /* @__PURE__ */new Vector3();
|
||||
const rotation = /* @__PURE__ */new Quaternion();
|
||||
const cpos = /* @__PURE__ */new Vector3();
|
||||
const cquat = /* @__PURE__ */new Quaternion();
|
||||
const scale = /* @__PURE__ */new Vector3();
|
||||
const context = /* @__PURE__ */React.createContext(null);
|
||||
const Clouds = /* @__PURE__ */React.forwardRef(({
|
||||
children,
|
||||
material = MeshLambertMaterial,
|
||||
texture = CLOUD_URL,
|
||||
range,
|
||||
limit = 200,
|
||||
frustumCulled,
|
||||
...props
|
||||
}, fref) => {
|
||||
var _image$width, _image$height;
|
||||
const CloudMaterial = React.useMemo(() => {
|
||||
return class extends material {
|
||||
constructor() {
|
||||
super();
|
||||
const opaque_fragment = parseInt(REVISION.replace(/\D+/g, '')) >= 154 ? 'opaque_fragment' : 'output_fragment';
|
||||
this.onBeforeCompile = shader => {
|
||||
shader.vertexShader = `attribute float cloudOpacity;
|
||||
varying float vOpacity;
|
||||
` + shader.vertexShader.replace('#include <fog_vertex>', `#include <fog_vertex>
|
||||
vOpacity = cloudOpacity;
|
||||
`);
|
||||
shader.fragmentShader = `varying float vOpacity;
|
||||
` + shader.fragmentShader.replace(`#include <${opaque_fragment}>`, `#include <${opaque_fragment}>
|
||||
gl_FragColor = vec4(outgoingLight, diffuseColor.a * vOpacity);
|
||||
`);
|
||||
};
|
||||
}
|
||||
};
|
||||
}, [material]);
|
||||
extend({
|
||||
CloudMaterial
|
||||
});
|
||||
const instance = React.useRef(null);
|
||||
const clouds = React.useRef([]);
|
||||
const opacities = React.useMemo(() => new Float32Array(Array.from({
|
||||
length: limit
|
||||
}, () => 1)), [limit]);
|
||||
const colors = React.useMemo(() => new Float32Array(Array.from({
|
||||
length: limit
|
||||
}, () => [1, 1, 1]).flat()), [limit]);
|
||||
const cloudTexture = useTexture(texture);
|
||||
let t = 0;
|
||||
let index = 0;
|
||||
let config;
|
||||
const qat = new Quaternion();
|
||||
const dir = new Vector3(0, 0, 1);
|
||||
const pos = new Vector3();
|
||||
useFrame((state, delta) => {
|
||||
t = state.clock.elapsedTime;
|
||||
parentMatrix.copy(instance.current.matrixWorld).invert();
|
||||
state.camera.matrixWorld.decompose(cpos, cquat, scale);
|
||||
for (index = 0; index < clouds.current.length; index++) {
|
||||
config = clouds.current[index];
|
||||
config.ref.current.matrixWorld.decompose(translation, rotation, scale);
|
||||
translation.add(pos.copy(config.position).applyQuaternion(rotation).multiply(scale));
|
||||
rotation.copy(cquat).multiply(qat.setFromAxisAngle(dir, config.rotation += delta * config.rotationFactor));
|
||||
scale.multiplyScalar(config.volume + (1 + Math.sin(t * config.density * config.speed)) / 2 * config.growth);
|
||||
config.matrix.compose(translation, rotation, scale).premultiply(parentMatrix);
|
||||
config.dist = translation.distanceTo(cpos);
|
||||
}
|
||||
|
||||
// Depth-sort. Instances have no specific draw order, w/o sorting z would be random
|
||||
clouds.current.sort((a, b) => b.dist - a.dist);
|
||||
for (index = 0; index < clouds.current.length; index++) {
|
||||
config = clouds.current[index];
|
||||
opacities[index] = config.opacity * (config.dist < config.fade - 1 ? config.dist / config.fade : 1);
|
||||
instance.current.setMatrixAt(index, config.matrix);
|
||||
instance.current.setColorAt(index, config.color);
|
||||
}
|
||||
|
||||
// Update instance
|
||||
instance.current.geometry.attributes.cloudOpacity.needsUpdate = true;
|
||||
instance.current.instanceMatrix.needsUpdate = true;
|
||||
if (instance.current.instanceColor) instance.current.instanceColor.needsUpdate = true;
|
||||
});
|
||||
React.useLayoutEffect(() => {
|
||||
const count = Math.min(limit, range !== undefined ? range : limit, clouds.current.length);
|
||||
instance.current.count = count;
|
||||
setUpdateRange(instance.current.instanceMatrix, {
|
||||
start: 0,
|
||||
count: count * 16
|
||||
});
|
||||
if (instance.current.instanceColor) {
|
||||
setUpdateRange(instance.current.instanceColor, {
|
||||
start: 0,
|
||||
count: count * 3
|
||||
});
|
||||
}
|
||||
setUpdateRange(instance.current.geometry.attributes.cloudOpacity, {
|
||||
start: 0,
|
||||
count: count
|
||||
});
|
||||
});
|
||||
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];
|
||||
const max = Math.max(imageBounds[0], imageBounds[1]);
|
||||
imageBounds = [imageBounds[0] / max, imageBounds[1] / max];
|
||||
return /*#__PURE__*/React.createElement("group", _extends({
|
||||
ref: fref
|
||||
}, props), /*#__PURE__*/React.createElement(context.Provider, {
|
||||
value: clouds
|
||||
}, children, /*#__PURE__*/React.createElement("instancedMesh", {
|
||||
matrixAutoUpdate: false,
|
||||
ref: instance,
|
||||
args: [null, null, limit],
|
||||
frustumCulled: frustumCulled
|
||||
}, /*#__PURE__*/React.createElement("instancedBufferAttribute", {
|
||||
usage: DynamicDrawUsage,
|
||||
attach: "instanceColor",
|
||||
args: [colors, 3]
|
||||
}), /*#__PURE__*/React.createElement("planeGeometry", {
|
||||
args: [...imageBounds]
|
||||
}, /*#__PURE__*/React.createElement("instancedBufferAttribute", {
|
||||
usage: DynamicDrawUsage,
|
||||
attach: "attributes-cloudOpacity",
|
||||
args: [opacities, 1]
|
||||
})), /*#__PURE__*/React.createElement("cloudMaterial", {
|
||||
key: material.name,
|
||||
map: cloudTexture,
|
||||
transparent: true,
|
||||
depthWrite: false
|
||||
}))));
|
||||
});
|
||||
const CloudInstance = /* @__PURE__ */React.forwardRef(({
|
||||
opacity = 1,
|
||||
speed = 0,
|
||||
bounds = [5, 1, 1],
|
||||
segments = 20,
|
||||
color = '#ffffff',
|
||||
fade = 10,
|
||||
volume = 6,
|
||||
smallestVolume = 0.25,
|
||||
distribute = null,
|
||||
growth = 4,
|
||||
concentrate = 'inside',
|
||||
seed = Math.random(),
|
||||
...props
|
||||
}, fref) => {
|
||||
function random() {
|
||||
const x = Math.sin(seed++) * 10000;
|
||||
return x - Math.floor(x);
|
||||
}
|
||||
const parent = React.useContext(context);
|
||||
const ref = React.useRef(null);
|
||||
const uuid = React.useId();
|
||||
const clouds = React.useMemo(() => {
|
||||
return [...new Array(segments)].map((_, index) => ({
|
||||
segments,
|
||||
bounds: new Vector3(1, 1, 1),
|
||||
position: new Vector3(),
|
||||
uuid,
|
||||
index,
|
||||
ref,
|
||||
dist: 0,
|
||||
matrix: new Matrix4(),
|
||||
color: new Color(),
|
||||
rotation: index * (Math.PI / segments)
|
||||
}));
|
||||
}, [segments, uuid]);
|
||||
React.useLayoutEffect(() => {
|
||||
clouds.forEach((cloud, index) => {
|
||||
applyProps(cloud, {
|
||||
volume,
|
||||
color,
|
||||
speed,
|
||||
growth,
|
||||
opacity,
|
||||
fade,
|
||||
bounds,
|
||||
density: Math.max(0.5, random()),
|
||||
rotationFactor: Math.max(0.2, 0.5 * random()) * speed
|
||||
});
|
||||
// Only distribute randomly if there are multiple segments
|
||||
|
||||
const distributed = distribute == null ? void 0 : distribute(cloud, index);
|
||||
if (distributed || segments > 1) {
|
||||
var _distributed$point;
|
||||
cloud.position.copy(cloud.bounds).multiply((_distributed$point = distributed == null ? void 0 : distributed.point) !== null && _distributed$point !== void 0 ? _distributed$point : {
|
||||
x: random() * 2 - 1,
|
||||
y: random() * 2 - 1,
|
||||
z: random() * 2 - 1
|
||||
});
|
||||
}
|
||||
const xDiff = Math.abs(cloud.position.x);
|
||||
const yDiff = Math.abs(cloud.position.y);
|
||||
const zDiff = Math.abs(cloud.position.z);
|
||||
const max = Math.max(xDiff, yDiff, zDiff);
|
||||
cloud.length = 1;
|
||||
if (xDiff === max) cloud.length -= xDiff / cloud.bounds.x;
|
||||
if (yDiff === max) cloud.length -= yDiff / cloud.bounds.y;
|
||||
if (zDiff === max) cloud.length -= zDiff / cloud.bounds.z;
|
||||
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;
|
||||
});
|
||||
}, [concentrate, bounds, fade, color, opacity, growth, volume, seed, segments, speed]);
|
||||
React.useLayoutEffect(() => {
|
||||
const temp = clouds;
|
||||
parent.current = [...parent.current, ...temp];
|
||||
return () => {
|
||||
parent.current = parent.current.filter(item => item.uuid !== uuid);
|
||||
};
|
||||
}, [clouds]);
|
||||
React.useImperativeHandle(fref, () => ref.current, []);
|
||||
return /*#__PURE__*/React.createElement("group", _extends({
|
||||
ref: ref
|
||||
}, props));
|
||||
});
|
||||
const Cloud = /* @__PURE__ */React.forwardRef((props, fref) => {
|
||||
const parent = React.useContext(context);
|
||||
if (parent) return /*#__PURE__*/React.createElement(CloudInstance, _extends({
|
||||
ref: fref
|
||||
}, props));
|
||||
return /*#__PURE__*/React.createElement(Clouds, null, /*#__PURE__*/React.createElement(CloudInstance, _extends({
|
||||
ref: fref
|
||||
}, props)));
|
||||
});
|
||||
|
||||
export { Cloud, CloudInstance, Clouds };
|
||||
Reference in New Issue
Block a user