@react-three/drei 9.74.11 → 9.74.13
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/core/CatmullRomLine.js +2 -0
- package/core/Cloud.js +3 -0
- package/core/CubeCamera.js +1 -0
- package/core/CubicBezierLine.js +2 -0
- package/core/Environment.js +1 -0
- package/core/Example.js +6 -0
- package/core/FaceControls.cjs.js +1 -1
- package/core/FaceControls.js +2 -0
- package/core/FaceLandmarker.cjs.js +1 -1
- package/core/FaceLandmarker.js +3 -2
- package/core/Facemesh.js +2 -0
- package/core/GizmoHelper.js +3 -0
- package/core/GizmoViewcube.js +4 -0
- package/core/GizmoViewport.js +4 -0
- package/core/Gltf.js +4 -0
- package/core/MeshDiscardMaterial.js +2 -0
- package/core/MeshDistortMaterial.js +2 -1
- package/core/MeshReflectorMaterial.js +1 -0
- package/core/MeshRefractionMaterial.js +2 -0
- package/core/MeshTransmissionMaterial.js +1 -0
- package/core/OrthographicCamera.js +1 -0
- package/core/PerspectiveCamera.js +1 -0
- package/core/QuadraticBezierLine.js +2 -0
- package/core/Reflector.js +1 -0
- package/core/SpotLight.js +2 -1
- package/core/Stage.js +7 -0
- package/core/Text3D.js +1 -0
- package/core/Wireframe.js +1 -0
- package/core/index.cjs.js +1 -1
- package/core/index.js +0 -1
- package/core/useKTX2.js +1 -0
- package/core/useMatcapTexture.js +2 -0
- package/core/useNormalTexture.js +1 -0
- package/index.cjs.js +1 -1
- package/materials/DiscardMaterial.js +1 -0
- package/materials/MeshRefractionMaterial.js +1 -1
- package/native/index.cjs.js +1 -1
- package/native/index.js +0 -1
- package/package.json +9 -9
- package/src/core/AccumulativeShadows.js +311 -0
- package/src/core/AdaptiveDpr.js +28 -0
- package/src/core/AdaptiveEvents.js +20 -0
- package/src/core/ArcballControls.js +67 -0
- package/src/core/AsciiRenderer.js +60 -0
- package/src/core/BBAnchor.js +37 -0
- package/src/core/Backdrop.js +36 -0
- package/src/core/BakeShadows.js +16 -0
- package/src/core/Billboard.js +41 -0
- package/src/core/Bounds.js +245 -0
- package/src/core/CameraControls.js +92 -0
- package/src/core/CameraShake.js +61 -0
- package/src/core/CatmullRomLine.js +44 -0
- package/src/core/Caustics.js +375 -0
- package/src/core/Center.js +66 -0
- package/src/core/Clone.js +102 -0
- package/src/core/Cloud.js +59 -0
- package/src/core/ComputedAttribute.js +34 -0
- package/src/core/ContactShadows.js +114 -0
- package/src/core/CubeCamera.js +43 -0
- package/src/core/CubicBezierLine.js +28 -0
- package/src/core/CurveModifier.js +34 -0
- package/src/core/Decal.js +92 -0
- package/src/core/Detailed.js +34 -0
- package/src/core/DeviceOrientationControls.js +51 -0
- package/src/core/Edges.js +36 -0
- package/src/core/Effects.js +93 -0
- package/src/core/Environment.js +132 -0
- package/src/core/Example.js +42 -0
- package/src/core/FaceControls.js +315 -0
- package/src/core/FaceLandmarker.js +43 -0
- package/src/core/Facemesh.js +4545 -0
- package/src/core/FirstPersonControls.js +38 -0
- package/src/core/Float.js +36 -0
- package/src/core/FlyControls.js +55 -0
- package/src/core/GizmoHelper.js +111 -0
- package/src/core/GizmoViewcube.js +152 -0
- package/src/core/GizmoViewport.js +152 -0
- package/src/core/Gltf.js +20 -0
- package/src/core/GradientTexture.js +33 -0
- package/src/core/Grid.js +112 -0
- package/src/core/Hud.js +58 -0
- package/src/core/Image.js +119 -0
- package/src/core/Instances.js +215 -0
- package/src/core/Lightformer.js +51 -0
- package/src/core/Line.js +68 -0
- package/src/core/MapControls.js +64 -0
- package/src/core/MarchingCubes.js +76 -0
- package/src/core/Mask.js +42 -0
- package/src/core/MeshDiscardMaterial.js +15 -0
- package/src/core/MeshDistortMaterial.js +79 -0
- package/src/core/MeshPortalMaterial.js +381 -0
- package/src/core/MeshReflectorMaterial.js +182 -0
- package/src/core/MeshRefractionMaterial.js +79 -0
- package/src/core/MeshTransmissionMaterial.js +395 -0
- package/src/core/MeshWobbleMaterial.js +65 -0
- package/src/core/OrbitControls.js +82 -0
- package/src/core/OrthographicCamera.js +77 -0
- package/src/core/PerformanceMonitor.js +121 -0
- package/src/core/PerspectiveCamera.js +73 -0
- package/src/core/PointMaterial.js +36 -0
- package/src/core/PointerLockControls.js +90 -0
- package/src/core/Points.js +227 -0
- package/src/core/PositionalAudio.js +51 -0
- package/src/core/Preload.js +45 -0
- package/src/core/QuadraticBezierLine.js +44 -0
- package/src/core/Reflector.js +182 -0
- package/src/core/RenderTexture.js +96 -0
- package/src/core/Resize.js +39 -0
- package/src/core/RoundedBox.js +52 -0
- package/src/core/Sampler.js +85 -0
- package/src/core/ScreenQuad.js +24 -0
- package/src/core/ScreenSpace.js +25 -0
- package/src/core/Segments.js +102 -0
- package/src/core/Shadow.js +42 -0
- package/src/core/Sky.js +39 -0
- package/src/core/Sparkles.js +139 -0
- package/src/core/SpotLight.js +231 -0
- package/src/core/SpriteAnimator.js +342 -0
- package/src/core/Stage.js +135 -0
- package/src/core/Stars.js +108 -0
- package/src/core/Stats.js +30 -0
- package/src/core/Svg.js +59 -0
- package/src/core/Text.js +58 -0
- package/src/core/Text3D.js +76 -0
- package/src/core/TrackballControls.js +72 -0
- package/src/core/Trail.js +161 -0
- package/src/core/TransformControls.js +106 -0
- package/src/core/Wireframe.js +185 -0
- package/src/core/meshBounds.js +38 -0
- package/src/core/shaderMaterial.js +39 -0
- package/src/core/shapes.js +68 -0
- package/src/core/softShadows.js +161 -0
- package/src/core/useAnimations.js +56 -0
- package/src/core/useAspect.js +10 -0
- package/src/core/useBVH.js +90 -0
- package/src/core/useBoxProjectedEnv.js +98 -0
- package/src/core/useCamera.js +27 -0
- package/src/core/useContextBridge.js +21 -0
- package/src/core/useCubeCamera.js +49 -0
- package/src/core/useCubeTexture.js +18 -0
- package/src/core/useDepthBuffer.js +38 -0
- package/src/core/useDetectGPU.js +6 -0
- package/src/core/useEnvironment.js +48 -0
- package/src/core/useFBO.js +53 -0
- package/src/core/useFBX.js +12 -0
- package/src/core/useFont.js +20 -0
- package/src/core/useGLTF.js +37 -0
- package/src/core/useHelper.js +31 -0
- package/src/core/useIntersect.js +39 -0
- package/src/core/useKTX2.js +38 -0
- package/src/core/useMatcapTexture.js +45 -0
- package/src/core/useNormalTexture.js +30 -0
- package/src/core/useProgress.js +50 -0
- package/src/core/useTexture.js +35 -0
- package/src/core/useTrailTexture.js +164 -0
- package/src/core/useVideoTexture.js +41 -0
- package/src/helpers/environment-assets.js +14 -0
- package/src/helpers/useEffectfulState.js +18 -0
- package/src/materials/BlurPass.js +75 -0
- package/src/materials/ConvolutionMaterial.js +99 -0
- package/src/materials/DiscardMaterial.js +5 -0
- package/src/materials/MeshReflectorMaterial.js +290 -0
- package/src/materials/MeshRefractionMaterial.js +171 -0
- package/src/materials/SpotLightMaterial.js +111 -0
- package/src/materials/WireframeMaterial.js +235 -0
- package/src/web/CycleRaycast.js +97 -0
- package/src/web/Html.js +417 -0
- package/src/web/KeyboardControls.js +101 -0
- package/src/web/Loader.js +98 -0
- package/src/web/PresentationControls.js +86 -0
- package/src/web/ScrollControls.js +246 -0
- package/src/web/Select.js +175 -0
- package/src/web/View.js +206 -0
- package/src/web/pivotControls/AxisArrow.js +202 -0
- package/src/web/pivotControls/AxisRotator.js +235 -0
- package/src/web/pivotControls/PlaneSlider.js +211 -0
- package/src/web/pivotControls/context.js +5 -0
- package/src/web/pivotControls/index.js +223 -0
- package/src/web/useCursor.js +12 -0
- package/web/Loader.js +2 -0
- package/web/index.cjs.js +1 -1
- package/web/index.js +0 -1
- package/web/pivotControls/AxisArrow.js +3 -0
- package/web/pivotControls/AxisRotator.js +3 -0
- package/web/pivotControls/PlaneSlider.js +3 -0
- package/web/pivotControls/index.js +5 -0
- /package/{helpers → src/helpers}/glsl/DefaultSpotlightShadowShadows.glsl.js +0 -0
- /package/{helpers → src/helpers}/glsl/distort.vert.glsl.js +0 -0
- /package/{index.js → src/index.js} +0 -0
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
import _extends from '@babel/runtime/helpers/esm/extends';
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
import * as THREE from 'three';
|
|
4
|
+
import * as FIBER from '@react-three/fiber';
|
|
5
|
+
import { WireframeMaterial, WireframeMaterialShaders, useWireframeUniforms, setWireframeOverride } from '../materials/WireframeMaterial.js';
|
|
6
|
+
|
|
7
|
+
FIBER.extend({
|
|
8
|
+
MeshWireframeMaterial: WireframeMaterial
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
function isWithGeometry(object) {
|
|
12
|
+
return !!(object != null && object.geometry);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function isGeometry(object) {
|
|
16
|
+
return !!(object != null && object.isBufferGeometry);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function isRefObject(object) {
|
|
20
|
+
return !!(object != null && object.current);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function isRef(object) {
|
|
24
|
+
return (object == null ? void 0 : object.current) !== undefined;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function isWireframeGeometry(geometry) {
|
|
28
|
+
return geometry.type === 'WireframeGeometry';
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function getUniforms() {
|
|
32
|
+
const u = {};
|
|
33
|
+
|
|
34
|
+
for (const key in WireframeMaterialShaders.uniforms) {
|
|
35
|
+
u[key] = {
|
|
36
|
+
value: WireframeMaterialShaders.uniforms[key]
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
return u;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function getBarycentricCoordinates(geometry, removeEdge) {
|
|
44
|
+
const position = geometry.getAttribute('position');
|
|
45
|
+
const count = position.count;
|
|
46
|
+
const barycentric = [];
|
|
47
|
+
|
|
48
|
+
for (let i = 0; i < count; i++) {
|
|
49
|
+
const even = i % 2 === 0;
|
|
50
|
+
const Q = removeEdge ? 1 : 0;
|
|
51
|
+
|
|
52
|
+
if (even) {
|
|
53
|
+
barycentric.push(0, 0, 1, 0, 1, 0, 1, 0, Q);
|
|
54
|
+
} else {
|
|
55
|
+
barycentric.push(0, 1, 0, 0, 0, 1, 1, 0, Q);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
return new THREE.BufferAttribute(Float32Array.from(barycentric), 3);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function getInputGeometry(inputGeometry) {
|
|
63
|
+
const geo = isRefObject(inputGeometry) ? inputGeometry.current : inputGeometry;
|
|
64
|
+
|
|
65
|
+
if (!isGeometry(geo)) {
|
|
66
|
+
// Disallow WireframeGeometry
|
|
67
|
+
if (isWireframeGeometry(geo)) {
|
|
68
|
+
throw new Error('Wireframe: WireframeGeometry is not supported.');
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
const parent = geo.parent;
|
|
72
|
+
|
|
73
|
+
if (isWithGeometry(parent)) {
|
|
74
|
+
// Disallow WireframeGeometry
|
|
75
|
+
if (isWireframeGeometry(parent.geometry)) {
|
|
76
|
+
throw new Error('Wireframe: WireframeGeometry is not supported.');
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
return parent.geometry;
|
|
80
|
+
}
|
|
81
|
+
} else {
|
|
82
|
+
return geo;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function setBarycentricCoordinates(geometry, simplify) {
|
|
87
|
+
if (geometry.index) {
|
|
88
|
+
console.warn('Wireframe: Requires non-indexed geometry, converting to non-indexed geometry.');
|
|
89
|
+
const nonIndexedGeo = geometry.toNonIndexed();
|
|
90
|
+
geometry.copy(nonIndexedGeo);
|
|
91
|
+
geometry.setIndex(null);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
const newBarycentric = getBarycentricCoordinates(geometry, simplify);
|
|
95
|
+
geometry.setAttribute('barycentric', newBarycentric);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
function WireframeWithCustomGeo({
|
|
99
|
+
geometry: customGeometry,
|
|
100
|
+
simplify = false,
|
|
101
|
+
...props
|
|
102
|
+
}) {
|
|
103
|
+
const [geometry, setGeometry] = React.useState(null);
|
|
104
|
+
React.useLayoutEffect(() => {
|
|
105
|
+
const geom = getInputGeometry(customGeometry);
|
|
106
|
+
|
|
107
|
+
if (!geom) {
|
|
108
|
+
throw new Error('Wireframe: geometry prop must be a BufferGeometry or a ref to a BufferGeometry.');
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
setBarycentricCoordinates(geom, simplify);
|
|
112
|
+
|
|
113
|
+
if (isRef(customGeometry)) {
|
|
114
|
+
setGeometry(geom);
|
|
115
|
+
}
|
|
116
|
+
}, [simplify, customGeometry]);
|
|
117
|
+
const drawnGeo = isRef(customGeometry) ? geometry : customGeometry;
|
|
118
|
+
return /*#__PURE__*/React.createElement(React.Fragment, null, drawnGeo && /*#__PURE__*/React.createElement("mesh", {
|
|
119
|
+
geometry: drawnGeo
|
|
120
|
+
}, /*#__PURE__*/React.createElement("meshWireframeMaterial", _extends({
|
|
121
|
+
attach: "material",
|
|
122
|
+
transparent: true,
|
|
123
|
+
side: THREE.DoubleSide,
|
|
124
|
+
polygonOffset: true //
|
|
125
|
+
,
|
|
126
|
+
polygonOffsetFactor: -4
|
|
127
|
+
}, props, {
|
|
128
|
+
extensions: {
|
|
129
|
+
derivatives: true,
|
|
130
|
+
fragDepth: false,
|
|
131
|
+
drawBuffers: false,
|
|
132
|
+
shaderTextureLOD: false
|
|
133
|
+
}
|
|
134
|
+
}))));
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
function WireframeWithoutCustomGeo({
|
|
138
|
+
simplify = false,
|
|
139
|
+
...props
|
|
140
|
+
}) {
|
|
141
|
+
const objectRef = React.useRef(null);
|
|
142
|
+
const uniforms = React.useMemo(() => getUniforms(), [WireframeMaterialShaders.uniforms]);
|
|
143
|
+
useWireframeUniforms(uniforms, props);
|
|
144
|
+
React.useLayoutEffect(() => {
|
|
145
|
+
const geom = getInputGeometry(objectRef);
|
|
146
|
+
|
|
147
|
+
if (!geom) {
|
|
148
|
+
throw new Error('Wireframe: Must be a child of a Mesh, Line or Points object or specify a geometry prop.');
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
const og = geom.clone();
|
|
152
|
+
setBarycentricCoordinates(geom, simplify);
|
|
153
|
+
return () => {
|
|
154
|
+
geom.copy(og);
|
|
155
|
+
og.dispose();
|
|
156
|
+
};
|
|
157
|
+
}, [simplify]);
|
|
158
|
+
React.useLayoutEffect(() => {
|
|
159
|
+
const parentMesh = objectRef.current.parent;
|
|
160
|
+
const og = parentMesh.material.clone();
|
|
161
|
+
setWireframeOverride(parentMesh.material, uniforms);
|
|
162
|
+
return () => {
|
|
163
|
+
parentMesh.material.dispose();
|
|
164
|
+
parentMesh.material = og;
|
|
165
|
+
};
|
|
166
|
+
}, []);
|
|
167
|
+
return /*#__PURE__*/React.createElement("object3D", {
|
|
168
|
+
ref: objectRef
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
function Wireframe({
|
|
173
|
+
geometry: customGeometry,
|
|
174
|
+
...props
|
|
175
|
+
}) {
|
|
176
|
+
if (customGeometry) {
|
|
177
|
+
return /*#__PURE__*/React.createElement(WireframeWithCustomGeo, _extends({
|
|
178
|
+
geometry: customGeometry
|
|
179
|
+
}, props));
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
return /*#__PURE__*/React.createElement(WireframeWithoutCustomGeo, props);
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
export { Wireframe };
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { Matrix4, Ray, Sphere, Vector3 } from 'three';
|
|
2
|
+
|
|
3
|
+
const _inverseMatrix = new Matrix4();
|
|
4
|
+
|
|
5
|
+
const _ray = new Ray();
|
|
6
|
+
|
|
7
|
+
const _sphere = new Sphere();
|
|
8
|
+
|
|
9
|
+
const _vA = new Vector3();
|
|
10
|
+
|
|
11
|
+
function meshBounds(raycaster, intersects) {
|
|
12
|
+
const geometry = this.geometry;
|
|
13
|
+
const material = this.material;
|
|
14
|
+
const matrixWorld = this.matrixWorld;
|
|
15
|
+
if (material === undefined) return; // Checking boundingSphere distance to ray
|
|
16
|
+
|
|
17
|
+
if (geometry.boundingSphere === null) geometry.computeBoundingSphere();
|
|
18
|
+
|
|
19
|
+
_sphere.copy(geometry.boundingSphere);
|
|
20
|
+
|
|
21
|
+
_sphere.applyMatrix4(matrixWorld);
|
|
22
|
+
|
|
23
|
+
if (raycaster.ray.intersectsSphere(_sphere) === false) return;
|
|
24
|
+
|
|
25
|
+
_inverseMatrix.copy(matrixWorld).invert();
|
|
26
|
+
|
|
27
|
+
_ray.copy(raycaster.ray).applyMatrix4(_inverseMatrix); // Check boundingBox before continuing
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
if (geometry.boundingBox !== null && _ray.intersectBox(geometry.boundingBox, _vA) === null) return;
|
|
31
|
+
intersects.push({
|
|
32
|
+
distance: _vA.distanceTo(raycaster.ray.origin),
|
|
33
|
+
point: _vA.clone(),
|
|
34
|
+
object: this
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export { meshBounds };
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import * as THREE from 'three';
|
|
2
|
+
|
|
3
|
+
function shaderMaterial(uniforms, vertexShader, fragmentShader, onInit) {
|
|
4
|
+
const material = class material extends THREE.ShaderMaterial {
|
|
5
|
+
constructor(parameters = {}) {
|
|
6
|
+
const entries = Object.entries(uniforms); // Create unforms and shaders
|
|
7
|
+
|
|
8
|
+
super({
|
|
9
|
+
uniforms: entries.reduce((acc, [name, value]) => {
|
|
10
|
+
const uniform = THREE.UniformsUtils.clone({
|
|
11
|
+
[name]: {
|
|
12
|
+
value
|
|
13
|
+
}
|
|
14
|
+
});
|
|
15
|
+
return { ...acc,
|
|
16
|
+
...uniform
|
|
17
|
+
};
|
|
18
|
+
}, {}),
|
|
19
|
+
vertexShader,
|
|
20
|
+
fragmentShader
|
|
21
|
+
}); // Create getter/setters
|
|
22
|
+
|
|
23
|
+
this.key = '';
|
|
24
|
+
entries.forEach(([name]) => Object.defineProperty(this, name, {
|
|
25
|
+
get: () => this.uniforms[name].value,
|
|
26
|
+
set: v => this.uniforms[name].value = v
|
|
27
|
+
})); // Assign parameters, this might include uniforms
|
|
28
|
+
|
|
29
|
+
Object.assign(this, parameters); // Call onInit
|
|
30
|
+
|
|
31
|
+
if (onInit) onInit(this);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
};
|
|
35
|
+
material.key = THREE.MathUtils.generateUUID();
|
|
36
|
+
return material;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export { shaderMaterial };
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import _extends from '@babel/runtime/helpers/esm/extends';
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
import * as THREE from 'three';
|
|
4
|
+
|
|
5
|
+
function create(type, effect) {
|
|
6
|
+
const El = type + 'Geometry';
|
|
7
|
+
return /*#__PURE__*/React.forwardRef(({
|
|
8
|
+
args,
|
|
9
|
+
children,
|
|
10
|
+
...props
|
|
11
|
+
}, fref) => {
|
|
12
|
+
const ref = React.useRef(null);
|
|
13
|
+
React.useImperativeHandle(fref, () => ref.current);
|
|
14
|
+
React.useLayoutEffect(() => void (effect == null ? void 0 : effect(ref.current)));
|
|
15
|
+
return /*#__PURE__*/React.createElement("mesh", _extends({
|
|
16
|
+
ref: ref
|
|
17
|
+
}, props), /*#__PURE__*/React.createElement(El, {
|
|
18
|
+
attach: "geometry",
|
|
19
|
+
args: args
|
|
20
|
+
}), children);
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const Box = create('box');
|
|
25
|
+
const Circle = create('circle');
|
|
26
|
+
const Cone = create('cone');
|
|
27
|
+
const Cylinder = create('cylinder');
|
|
28
|
+
const Sphere = create('sphere');
|
|
29
|
+
const Plane = create('plane');
|
|
30
|
+
const Tube = create('tube');
|
|
31
|
+
const Torus = create('torus');
|
|
32
|
+
const TorusKnot = create('torusKnot');
|
|
33
|
+
const Tetrahedron = create('tetrahedron');
|
|
34
|
+
const Ring = create('ring');
|
|
35
|
+
const Polyhedron = create('polyhedron');
|
|
36
|
+
const Icosahedron = create('icosahedron');
|
|
37
|
+
const Octahedron = create('octahedron');
|
|
38
|
+
const Dodecahedron = create('dodecahedron');
|
|
39
|
+
const Extrude = create('extrude');
|
|
40
|
+
const Lathe = create('lathe');
|
|
41
|
+
const Capsule = create('capsule');
|
|
42
|
+
const Shape = create('shape', ({
|
|
43
|
+
geometry
|
|
44
|
+
}) => {
|
|
45
|
+
// Calculate UVs (by https://discourse.threejs.org/u/prisoner849)
|
|
46
|
+
// https://discourse.threejs.org/t/custom-shape-in-image-not-working/49348/10
|
|
47
|
+
const pos = geometry.attributes.position;
|
|
48
|
+
const b3 = new THREE.Box3().setFromBufferAttribute(pos);
|
|
49
|
+
const b3size = new THREE.Vector3();
|
|
50
|
+
b3.getSize(b3size);
|
|
51
|
+
const uv = [];
|
|
52
|
+
let x = 0,
|
|
53
|
+
y = 0,
|
|
54
|
+
u = 0,
|
|
55
|
+
v = 0;
|
|
56
|
+
|
|
57
|
+
for (let i = 0; i < pos.count; i++) {
|
|
58
|
+
x = pos.getX(i);
|
|
59
|
+
y = pos.getY(i);
|
|
60
|
+
u = (x - b3.min.x) / b3size.x;
|
|
61
|
+
v = (y - b3.min.y) / b3size.y;
|
|
62
|
+
uv.push(u, v);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
geometry.setAttribute('uv', new THREE.Float32BufferAttribute(uv, 2));
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
export { Box, Capsule, Circle, Cone, Cylinder, Dodecahedron, Extrude, Icosahedron, Lathe, Octahedron, Plane, Polyhedron, Ring, Shape, Sphere, Tetrahedron, Torus, TorusKnot, Tube };
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import * as THREE from 'three';
|
|
3
|
+
import { useThree } from '@react-three/fiber';
|
|
4
|
+
|
|
5
|
+
/* Integration and compilation: @N8Programs
|
|
6
|
+
Inspired by:
|
|
7
|
+
https://github.com/mrdoob/three.js/blob/dev/examples/webgl_shadowmap_pcss.html
|
|
8
|
+
https://developer.nvidia.com/gpugems/gpugems2/part-ii-shading-lighting-and-shadows/chapter-17-efficient-soft-edged-shadows-using
|
|
9
|
+
https://developer.download.nvidia.com/whitepapers/2008/PCSS_Integration.pdf
|
|
10
|
+
https://github.com/mrdoob/three.js/blob/master/examples/webgl_shadowmap_pcss.html [spidersharma03]
|
|
11
|
+
https://spline.design/
|
|
12
|
+
Concept:
|
|
13
|
+
https://www.gamedev.net/tutorials/programming/graphics/contact-hardening-soft-shadows-made-fast-r4906/
|
|
14
|
+
Vogel Disk Implementation:
|
|
15
|
+
https://www.shadertoy.com/view/4l3yRM [ashalah]
|
|
16
|
+
High-Frequency Noise Implementation:
|
|
17
|
+
https://www.shadertoy.com/view/tt3fDH [spawner64]
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
const pcss = ({
|
|
21
|
+
focus = 0,
|
|
22
|
+
size = 25,
|
|
23
|
+
samples = 10
|
|
24
|
+
} = {}) => `
|
|
25
|
+
#define PENUMBRA_FILTER_SIZE float(${size})
|
|
26
|
+
#define RGB_NOISE_FUNCTION(uv) (randRGB(uv))
|
|
27
|
+
vec3 randRGB(vec2 uv) {
|
|
28
|
+
return vec3(
|
|
29
|
+
fract(sin(dot(uv, vec2(12.75613, 38.12123))) * 13234.76575),
|
|
30
|
+
fract(sin(dot(uv, vec2(19.45531, 58.46547))) * 43678.23431),
|
|
31
|
+
fract(sin(dot(uv, vec2(23.67817, 78.23121))) * 93567.23423)
|
|
32
|
+
);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
vec3 lowPassRandRGB(vec2 uv) {
|
|
36
|
+
// 3x3 convolution (average)
|
|
37
|
+
// can be implemented as separable with an extra buffer for a total of 6 samples instead of 9
|
|
38
|
+
vec3 result = vec3(0);
|
|
39
|
+
result += RGB_NOISE_FUNCTION(uv + vec2(-1.0, -1.0));
|
|
40
|
+
result += RGB_NOISE_FUNCTION(uv + vec2(-1.0, 0.0));
|
|
41
|
+
result += RGB_NOISE_FUNCTION(uv + vec2(-1.0, +1.0));
|
|
42
|
+
result += RGB_NOISE_FUNCTION(uv + vec2( 0.0, -1.0));
|
|
43
|
+
result += RGB_NOISE_FUNCTION(uv + vec2( 0.0, 0.0));
|
|
44
|
+
result += RGB_NOISE_FUNCTION(uv + vec2( 0.0, +1.0));
|
|
45
|
+
result += RGB_NOISE_FUNCTION(uv + vec2(+1.0, -1.0));
|
|
46
|
+
result += RGB_NOISE_FUNCTION(uv + vec2(+1.0, 0.0));
|
|
47
|
+
result += RGB_NOISE_FUNCTION(uv + vec2(+1.0, +1.0));
|
|
48
|
+
result *= 0.111111111; // 1.0 / 9.0
|
|
49
|
+
return result;
|
|
50
|
+
}
|
|
51
|
+
vec3 highPassRandRGB(vec2 uv) {
|
|
52
|
+
// by subtracting the low-pass signal from the original signal, we're being left with the high-pass signal
|
|
53
|
+
// hp(x) = x - lp(x)
|
|
54
|
+
return RGB_NOISE_FUNCTION(uv) - lowPassRandRGB(uv) + 0.5;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
vec2 vogelDiskSample(int sampleIndex, int sampleCount, float angle) {
|
|
59
|
+
const float goldenAngle = 2.399963f; // radians
|
|
60
|
+
float r = sqrt(float(sampleIndex) + 0.5f) / sqrt(float(sampleCount));
|
|
61
|
+
float theta = float(sampleIndex) * goldenAngle + angle;
|
|
62
|
+
float sine = sin(theta);
|
|
63
|
+
float cosine = cos(theta);
|
|
64
|
+
return vec2(cosine, sine) * r;
|
|
65
|
+
}
|
|
66
|
+
float penumbraSize( const in float zReceiver, const in float zBlocker ) { // Parallel plane estimation
|
|
67
|
+
return (zReceiver - zBlocker) / zBlocker;
|
|
68
|
+
}
|
|
69
|
+
float findBlocker(sampler2D shadowMap, vec2 uv, float compare, float angle) {
|
|
70
|
+
float texelSize = 1.0 / float(textureSize(shadowMap, 0).x);
|
|
71
|
+
float blockerDepthSum = float(${focus});
|
|
72
|
+
float blockers = 0.0;
|
|
73
|
+
|
|
74
|
+
int j = 0;
|
|
75
|
+
vec2 offset = vec2(0.);
|
|
76
|
+
float depth = 0.;
|
|
77
|
+
|
|
78
|
+
#pragma unroll_loop_start
|
|
79
|
+
for(int i = 0; i < ${samples}; i ++) {
|
|
80
|
+
offset = (vogelDiskSample(j, ${samples}, angle) * texelSize) * 2.0 * PENUMBRA_FILTER_SIZE;
|
|
81
|
+
depth = unpackRGBAToDepth( texture2D( shadowMap, uv + offset));
|
|
82
|
+
if (depth < compare) {
|
|
83
|
+
blockerDepthSum += depth;
|
|
84
|
+
blockers++;
|
|
85
|
+
}
|
|
86
|
+
j++;
|
|
87
|
+
}
|
|
88
|
+
#pragma unroll_loop_end
|
|
89
|
+
|
|
90
|
+
if (blockers > 0.0) {
|
|
91
|
+
return blockerDepthSum / blockers;
|
|
92
|
+
}
|
|
93
|
+
return -1.0;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
float vogelFilter(sampler2D shadowMap, vec2 uv, float zReceiver, float filterRadius, float angle) {
|
|
98
|
+
float texelSize = 1.0 / float(textureSize(shadowMap, 0).x);
|
|
99
|
+
float shadow = 0.0f;
|
|
100
|
+
int j = 0;
|
|
101
|
+
vec2 vogelSample = vec2(0.0);
|
|
102
|
+
vec2 offset = vec2(0.0);
|
|
103
|
+
#pragma unroll_loop_start
|
|
104
|
+
for (int i = 0; i < ${samples}; i++) {
|
|
105
|
+
vogelSample = vogelDiskSample(j, ${samples}, angle) * texelSize;
|
|
106
|
+
offset = vogelSample * (1.0 + filterRadius * float(${size}));
|
|
107
|
+
shadow += step( zReceiver, unpackRGBAToDepth( texture2D( shadowMap, uv + offset ) ) );
|
|
108
|
+
j++;
|
|
109
|
+
}
|
|
110
|
+
#pragma unroll_loop_end
|
|
111
|
+
return shadow * 1.0 / ${samples}.0;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
float PCSS (sampler2D shadowMap, vec4 coords) {
|
|
115
|
+
vec2 uv = coords.xy;
|
|
116
|
+
float zReceiver = coords.z; // Assumed to be eye-space z in this code
|
|
117
|
+
float angle = highPassRandRGB(gl_FragCoord.xy).r * PI2;
|
|
118
|
+
float avgBlockerDepth = findBlocker(shadowMap, uv, zReceiver, angle);
|
|
119
|
+
if (avgBlockerDepth == -1.0) {
|
|
120
|
+
return 1.0;
|
|
121
|
+
}
|
|
122
|
+
float penumbraRatio = penumbraSize(zReceiver, avgBlockerDepth);
|
|
123
|
+
return vogelFilter(shadowMap, uv, zReceiver, 1.25 * penumbraRatio, angle);
|
|
124
|
+
}`;
|
|
125
|
+
|
|
126
|
+
function reset(gl, scene, camera) {
|
|
127
|
+
scene.traverse(object => {
|
|
128
|
+
if (object.material) {
|
|
129
|
+
gl.properties.remove(object.material);
|
|
130
|
+
object.material.dispose == null ? void 0 : object.material.dispose();
|
|
131
|
+
}
|
|
132
|
+
});
|
|
133
|
+
gl.info.programs.length = 0;
|
|
134
|
+
gl.compile(scene, camera);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
function SoftShadows({
|
|
138
|
+
focus = 0,
|
|
139
|
+
samples = 10,
|
|
140
|
+
size = 25
|
|
141
|
+
}) {
|
|
142
|
+
const gl = useThree(state => state.gl);
|
|
143
|
+
const scene = useThree(state => state.scene);
|
|
144
|
+
const camera = useThree(state => state.camera);
|
|
145
|
+
React.useEffect(() => {
|
|
146
|
+
const original = THREE.ShaderChunk.shadowmap_pars_fragment;
|
|
147
|
+
THREE.ShaderChunk.shadowmap_pars_fragment = THREE.ShaderChunk.shadowmap_pars_fragment.replace('#ifdef USE_SHADOWMAP', '#ifdef USE_SHADOWMAP\n' + pcss({
|
|
148
|
+
size,
|
|
149
|
+
samples,
|
|
150
|
+
focus
|
|
151
|
+
})).replace('#if defined( SHADOWMAP_TYPE_PCF )', '\nreturn PCSS(shadowMap, shadowCoord);\n#if defined( SHADOWMAP_TYPE_PCF )');
|
|
152
|
+
reset(gl, scene, camera);
|
|
153
|
+
return () => {
|
|
154
|
+
THREE.ShaderChunk.shadowmap_pars_fragment = original;
|
|
155
|
+
reset(gl, scene, camera);
|
|
156
|
+
};
|
|
157
|
+
}, [focus, size, samples]);
|
|
158
|
+
return null;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
export { SoftShadows };
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { Object3D, AnimationMixer } from 'three';
|
|
3
|
+
import { useFrame } from '@react-three/fiber';
|
|
4
|
+
|
|
5
|
+
function useAnimations(clips, root) {
|
|
6
|
+
const ref = React.useRef();
|
|
7
|
+
const [actualRef] = React.useState(() => root ? root instanceof Object3D ? {
|
|
8
|
+
current: root
|
|
9
|
+
} : root : ref); // eslint-disable-next-line prettier/prettier
|
|
10
|
+
|
|
11
|
+
const [mixer] = React.useState(() => new AnimationMixer(undefined));
|
|
12
|
+
React.useLayoutEffect(() => void (mixer._root = actualRef.current), [mixer, root]);
|
|
13
|
+
const lazyActions = React.useRef({});
|
|
14
|
+
const [api] = React.useState(() => {
|
|
15
|
+
const actions = {};
|
|
16
|
+
clips.forEach(clip => Object.defineProperty(actions, clip.name, {
|
|
17
|
+
enumerable: true,
|
|
18
|
+
|
|
19
|
+
get() {
|
|
20
|
+
if (actualRef.current) {
|
|
21
|
+
return lazyActions.current[clip.name] || (lazyActions.current[clip.name] = mixer.clipAction(clip, actualRef.current));
|
|
22
|
+
}
|
|
23
|
+
},
|
|
24
|
+
|
|
25
|
+
configurable: true
|
|
26
|
+
}));
|
|
27
|
+
return {
|
|
28
|
+
ref: actualRef,
|
|
29
|
+
clips,
|
|
30
|
+
actions,
|
|
31
|
+
names: clips.map(c => c.name),
|
|
32
|
+
mixer
|
|
33
|
+
};
|
|
34
|
+
});
|
|
35
|
+
useFrame((state, delta) => mixer.update(delta));
|
|
36
|
+
React.useEffect(() => {
|
|
37
|
+
const currentRoot = actualRef.current;
|
|
38
|
+
return () => {
|
|
39
|
+
// Clean up only when clips change, wipe out lazy actions and uncache clips
|
|
40
|
+
lazyActions.current = {};
|
|
41
|
+
Object.values(api.actions).forEach(action => {
|
|
42
|
+
if (currentRoot) {
|
|
43
|
+
mixer.uncacheAction(action, currentRoot);
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
};
|
|
47
|
+
}, [clips]);
|
|
48
|
+
React.useEffect(() => {
|
|
49
|
+
return () => {
|
|
50
|
+
mixer.stopAllAction();
|
|
51
|
+
};
|
|
52
|
+
}, [mixer]);
|
|
53
|
+
return api;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export { useAnimations };
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { useThree } from '@react-three/fiber';
|
|
2
|
+
|
|
3
|
+
function useAspect(width, height, factor = 1) {
|
|
4
|
+
const v = useThree(state => state.viewport);
|
|
5
|
+
const adaptedHeight = height * (v.aspect > width / height ? v.width / width : v.height / height);
|
|
6
|
+
const adaptedWidth = width * (v.aspect > width / height ? v.width / width : v.height / height);
|
|
7
|
+
return [adaptedWidth * factor, adaptedHeight * factor, 1];
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export { useAspect };
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import _extends from '@babel/runtime/helpers/esm/extends';
|
|
2
|
+
import { useThree } from '@react-three/fiber';
|
|
3
|
+
import * as React from 'react';
|
|
4
|
+
import { Mesh } from 'three';
|
|
5
|
+
import { SAH, acceleratedRaycast, computeBoundsTree, disposeBoundsTree } from 'three-mesh-bvh';
|
|
6
|
+
|
|
7
|
+
const isMesh = child => child.isMesh;
|
|
8
|
+
/**
|
|
9
|
+
* @deprecated Use the Bvh component instead
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
function useBVH(mesh, options) {
|
|
14
|
+
options = {
|
|
15
|
+
strategy: SAH,
|
|
16
|
+
verbose: false,
|
|
17
|
+
setBoundingBox: true,
|
|
18
|
+
maxDepth: 40,
|
|
19
|
+
maxLeafTris: 10,
|
|
20
|
+
...options
|
|
21
|
+
};
|
|
22
|
+
React.useEffect(() => {
|
|
23
|
+
if (mesh.current) {
|
|
24
|
+
mesh.current.raycast = acceleratedRaycast;
|
|
25
|
+
const geometry = mesh.current.geometry;
|
|
26
|
+
geometry.computeBoundsTree = computeBoundsTree;
|
|
27
|
+
geometry.disposeBoundsTree = disposeBoundsTree;
|
|
28
|
+
geometry.computeBoundsTree(options);
|
|
29
|
+
return () => {
|
|
30
|
+
if (geometry.boundsTree) {
|
|
31
|
+
geometry.disposeBoundsTree();
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
}, [mesh, JSON.stringify(options)]);
|
|
36
|
+
}
|
|
37
|
+
const Bvh = /*#__PURE__*/React.forwardRef(({
|
|
38
|
+
enabled = true,
|
|
39
|
+
firstHitOnly = false,
|
|
40
|
+
children,
|
|
41
|
+
strategy = SAH,
|
|
42
|
+
verbose = false,
|
|
43
|
+
setBoundingBox = true,
|
|
44
|
+
maxDepth = 40,
|
|
45
|
+
maxLeafTris = 10,
|
|
46
|
+
...props
|
|
47
|
+
}, fref) => {
|
|
48
|
+
const ref = React.useRef(null);
|
|
49
|
+
const raycaster = useThree(state => state.raycaster);
|
|
50
|
+
React.useImperativeHandle(fref, () => ref.current, []);
|
|
51
|
+
React.useEffect(() => {
|
|
52
|
+
if (enabled) {
|
|
53
|
+
const options = {
|
|
54
|
+
strategy,
|
|
55
|
+
verbose,
|
|
56
|
+
setBoundingBox,
|
|
57
|
+
maxDepth,
|
|
58
|
+
maxLeafTris
|
|
59
|
+
};
|
|
60
|
+
const group = ref.current; // This can only safely work if the component is used once, but there is no alternative.
|
|
61
|
+
// Hijacking the raycast method to do it for individual meshes is not an option as it would
|
|
62
|
+
// cost too much memory ...
|
|
63
|
+
|
|
64
|
+
raycaster.firstHitOnly = firstHitOnly;
|
|
65
|
+
group.traverse(child => {
|
|
66
|
+
// Only include meshes that do not yet have a boundsTree and whose raycast is standard issue
|
|
67
|
+
if (isMesh(child) && !child.geometry.boundsTree && child.raycast === Mesh.prototype.raycast) {
|
|
68
|
+
child.raycast = acceleratedRaycast;
|
|
69
|
+
child.geometry.computeBoundsTree = computeBoundsTree;
|
|
70
|
+
child.geometry.disposeBoundsTree = disposeBoundsTree;
|
|
71
|
+
child.geometry.computeBoundsTree(options);
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
return () => {
|
|
75
|
+
delete raycaster.firstHitOnly;
|
|
76
|
+
group.traverse(child => {
|
|
77
|
+
if (isMesh(child) && child.geometry.boundsTree) {
|
|
78
|
+
child.geometry.disposeBoundsTree();
|
|
79
|
+
child.raycast = Mesh.prototype.raycast;
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
return /*#__PURE__*/React.createElement("group", _extends({
|
|
86
|
+
ref: ref
|
|
87
|
+
}, props), children);
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
export { Bvh, useBVH };
|