@react-three/drei 11.0.0-alpha.5 → 11.0.0-alpha.6
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 +17 -1
- package/core/index.d.mts +194 -51
- package/core/index.d.ts +194 -51
- package/core/index.mjs +543 -240
- package/experimental/index.d.mts +20 -0
- package/experimental/index.d.ts +20 -0
- package/external/index.d.mts +38 -2
- package/external/index.d.ts +38 -2
- package/external/index.mjs +3 -4
- package/index.d.mts +211 -53
- package/index.d.ts +211 -53
- package/index.mjs +544 -241
- package/legacy/index.d.mts +211 -56
- package/legacy/index.d.ts +211 -56
- package/legacy/index.mjs +687 -260
- package/native/index.d.mts +219 -130
- package/native/index.d.ts +219 -130
- package/native/index.mjs +1225 -416
- package/package.json +7 -7
- package/webgpu/index.d.mts +249 -129
- package/webgpu/index.d.ts +249 -129
- package/webgpu/index.mjs +1468 -516
package/webgpu/index.mjs
CHANGED
|
@@ -2,9 +2,8 @@ import * as React from 'react';
|
|
|
2
2
|
import { forwardRef, useImperativeHandle, useMemo, useEffect, useCallback, useRef, useLayoutEffect, useState, Fragment, createContext, useContext } from 'react';
|
|
3
3
|
import { useThree, useFrame, extend, createPortal, applyProps, useInstanceHandle, context as context$a, useLoader, addEffect, addAfterEffect } from '@react-three/fiber';
|
|
4
4
|
import * as THREE from 'three/webgpu';
|
|
5
|
-
import { MeshBasicNodeMaterial, RenderTarget, MeshNormalNodeMaterial, QuadMesh, MeshPhysicalNodeMaterial, Frustum, Matrix4, Line2NodeMaterial, Vector3, Vector4, Vector2, Color, InstancedInterleavedBuffer, InterleavedBufferAttribute, Object3D,
|
|
5
|
+
import { MeshBasicNodeMaterial, RenderTarget, MeshPhongNodeMaterial, MeshNormalNodeMaterial, QuadMesh, MeshPhysicalNodeMaterial, Frustum, Matrix4, CubeRenderTarget, Line2NodeMaterial, Vector3, Vector4, Vector2, Color, InstancedInterleavedBuffer, InterleavedBufferAttribute, Object3D, HalfFloatType, CubeCamera as CubeCamera$1, EventDispatcher, Euler, Quaternion, MathUtils, TextureLoader, Texture as Texture$1, MeshLambertMaterial, DynamicDrawUsage, CatmullRomCurve3, CubicBezierCurve3, QuadraticBezierCurve3, Shape as Shape$1, CanvasTexture, PerspectiveCamera as PerspectiveCamera$1, OrthographicCamera as OrthographicCamera$1, REVISION, AudioListener, AudioLoader, AnimationMixer, BufferAttribute, Box3, Sphere as Sphere$1, InstancedBufferAttribute, DoubleSide, DepthTexture, DepthFormat, UnsignedShortType, CubeTextureLoader, DefaultLoadingManager, Ray, Raycaster, Camera, CubeReflectionMapping, EquirectangularReflectionMapping, Scene, RepeatWrapping, SpriteNodeMaterial, AdditiveBlending, ShadowNode, CylinderGeometry } from 'three/webgpu';
|
|
6
6
|
import { ArcballControls as ArcballControls$1 } from 'three/examples/jsm/controls/ArcballControls.js';
|
|
7
|
-
import { useGesture } from '@use-gesture/react';
|
|
8
7
|
import { FirstPersonControls as FirstPersonControls$1 } from 'three/examples/jsm/controls/FirstPersonControls.js';
|
|
9
8
|
import { FlyControls as FlyControls$1 } from 'three/examples/jsm/controls/FlyControls.js';
|
|
10
9
|
import { create as create$1 } from 'zustand';
|
|
@@ -13,10 +12,11 @@ import { MapControls as MapControls$1 } from 'three/examples/jsm/controls/MapCon
|
|
|
13
12
|
import { misc, easing } from 'maath';
|
|
14
13
|
import { OrbitControls as OrbitControls$1 } from 'three/addons/controls/OrbitControls.js';
|
|
15
14
|
import { PointerLockControls as PointerLockControls$1 } from 'three/examples/jsm/controls/PointerLockControls.js';
|
|
15
|
+
import { useGesture } from '@use-gesture/react';
|
|
16
16
|
import * as ReactDOM from 'react-dom/client';
|
|
17
17
|
import { TrackballControls as TrackballControls$1 } from 'three/examples/jsm/controls/TrackballControls.js';
|
|
18
18
|
import { SimplexNoise } from 'three/examples/jsm/math/SimplexNoise.js';
|
|
19
|
-
import { uniform, Fn, float, vec4, uniformTexture, uv, vec2 as vec2$2, texture, positionWorld, mul, add, negate, dot, refract, div,
|
|
19
|
+
import { uniform, Fn, float, vec4, uniformTexture, uv, vec2 as vec2$2, texture, Discard, max, sub, mix, output, positionWorld, mul, add, negate, dot, refract, div, length, cross, select, vec3, normalize, normalWorld, cameraPosition, screenCoordinate, mx_fractal_noise_vec3, int, thickness, pow, roughness, Loop, ior, screenUV, screenSize, cameraProjectionMatrix, cameraViewMatrix, attenuationColor, attenuationDistance, diffuseColor, transmission, fract, sin, modelWorldMatrix, log, exp, DFGLUT, reflector, clamp, equirectUV, reflect, smoothstep, round, distance, positionLocal, mx_noise_vec3, cos, mat3, normalLocal, attribute, modelViewMatrix, varying, min, frontFacing, fwidth, abs, saturate, positionView, positionGeometry, reference, renderGroup, interleavedGradientNoise, vogelDiskSample, step } from 'three/tsl';
|
|
20
20
|
import { Line2 } from 'three/examples/jsm/lines/webgpu/Line2.js';
|
|
21
21
|
import { LineSegments2 } from 'three/examples/jsm/lines/webgpu/LineSegments2.js';
|
|
22
22
|
import { LineGeometry } from 'three/examples/jsm/lines/LineGeometry.js';
|
|
@@ -31,7 +31,6 @@ import { TransformControls as TransformControls$1 } from 'three/examples/jsm/con
|
|
|
31
31
|
import * as SkeletonUtils from 'three/examples/jsm/utils/SkeletonUtils.js';
|
|
32
32
|
import { MeshSurfaceSampler } from 'three/examples/jsm/math/MeshSurfaceSampler.js';
|
|
33
33
|
import { SVGLoader } from 'three/examples/jsm/loaders/SVGLoader.js';
|
|
34
|
-
import { Events } from 'hls.js';
|
|
35
34
|
import { FBXLoader } from 'three/examples/jsm/loaders/FBXLoader.js';
|
|
36
35
|
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';
|
|
37
36
|
import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader.js';
|
|
@@ -50,6 +49,7 @@ import { SkyMesh } from 'three/examples/jsm/objects/SkyMesh.js';
|
|
|
50
49
|
import { SelectionBox } from 'three/examples/jsm/interactive/SelectionBox.js';
|
|
51
50
|
import { shallow } from 'zustand/shallow';
|
|
52
51
|
import { hashBlur } from 'three/examples/jsm/tsl/display/hashBlur.js';
|
|
52
|
+
import PhysicalLightingModel from 'three/src/nodes/functions/PhysicalLightingModel.js';
|
|
53
53
|
|
|
54
54
|
class DepthNodeMaterial extends MeshBasicNodeMaterial {
|
|
55
55
|
_opacity;
|
|
@@ -238,28 +238,354 @@ const ContactShadows = /* @__PURE__ */ React.forwardRef(
|
|
|
238
238
|
}
|
|
239
239
|
);
|
|
240
240
|
|
|
241
|
+
const discardFragment = /* @__PURE__ */ Fn(() => {
|
|
242
|
+
Discard();
|
|
243
|
+
return vec4(0, 0, 0, 0);
|
|
244
|
+
});
|
|
245
|
+
const DiscardMaterial = /* @__PURE__ */ new MeshBasicNodeMaterial({
|
|
246
|
+
fragmentNode: discardFragment()
|
|
247
|
+
});
|
|
248
|
+
|
|
249
|
+
function isLight(object) {
|
|
250
|
+
return object.isLight;
|
|
251
|
+
}
|
|
252
|
+
function isGeometry$1(object) {
|
|
253
|
+
return !!object.geometry;
|
|
254
|
+
}
|
|
241
255
|
const accumulativeContext = /* @__PURE__ */ React.createContext(
|
|
242
256
|
null
|
|
243
257
|
);
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
258
|
+
class SoftShadowMaterialImpl extends MeshBasicNodeMaterial {
|
|
259
|
+
_color;
|
|
260
|
+
_blend;
|
|
261
|
+
_alphaTest;
|
|
262
|
+
_opacity;
|
|
263
|
+
_map;
|
|
264
|
+
constructor() {
|
|
265
|
+
super();
|
|
266
|
+
this._color = uniform(new THREE.Color());
|
|
267
|
+
this._blend = uniform(2);
|
|
268
|
+
this._alphaTest = uniform(0.75);
|
|
269
|
+
this._opacity = uniform(0);
|
|
270
|
+
this._map = uniformTexture(new THREE.Texture());
|
|
271
|
+
this.transparent = true;
|
|
272
|
+
this.depthWrite = false;
|
|
273
|
+
this._buildShader();
|
|
274
|
+
}
|
|
275
|
+
_buildShader() {
|
|
276
|
+
const colorUniform = this._color;
|
|
277
|
+
const blendUniform = this._blend;
|
|
278
|
+
const alphaTestUniform = this._alphaTest;
|
|
279
|
+
const opacityUniform = this._opacity;
|
|
280
|
+
const mapTex = this._map;
|
|
281
|
+
this.colorNode = Fn(() => {
|
|
282
|
+
const texCoord = uv();
|
|
283
|
+
const sampled = texture(mapTex, texCoord);
|
|
284
|
+
const rgb = colorUniform.mul(sampled.r).mul(blendUniform);
|
|
285
|
+
const sum = sampled.r.add(sampled.g).add(sampled.b);
|
|
286
|
+
const alpha = max(float(0), float(1).sub(sum.div(alphaTestUniform))).mul(opacityUniform);
|
|
287
|
+
return vec4(rgb, alpha);
|
|
288
|
+
})();
|
|
289
|
+
}
|
|
290
|
+
get shadowColor() {
|
|
291
|
+
return this._color.value;
|
|
292
|
+
}
|
|
293
|
+
set shadowColor(v) {
|
|
294
|
+
if (v instanceof THREE.Color) {
|
|
295
|
+
this._color.value.copy(v);
|
|
296
|
+
} else {
|
|
297
|
+
this._color.value.set(v);
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
get blend() {
|
|
301
|
+
return this._blend.value;
|
|
302
|
+
}
|
|
303
|
+
set blend(v) {
|
|
304
|
+
this._blend.value = v;
|
|
305
|
+
}
|
|
306
|
+
get alphaTest() {
|
|
307
|
+
return this._alphaTest.value;
|
|
308
|
+
}
|
|
309
|
+
set alphaTest(v) {
|
|
310
|
+
this._alphaTest.value = v;
|
|
311
|
+
}
|
|
312
|
+
get opacity() {
|
|
313
|
+
return this._opacity.value;
|
|
314
|
+
}
|
|
315
|
+
set opacity(v) {
|
|
316
|
+
if (!this._opacity) this._opacity = uniform(v);
|
|
317
|
+
else this._opacity.value = v;
|
|
318
|
+
}
|
|
319
|
+
get map() {
|
|
320
|
+
if (!this._map) {
|
|
321
|
+
this._map = uniformTexture(new THREE.Texture());
|
|
322
|
+
}
|
|
323
|
+
return this._map.value;
|
|
324
|
+
}
|
|
325
|
+
set map(v) {
|
|
326
|
+
this._map.value = v;
|
|
249
327
|
}
|
|
250
328
|
}
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
)
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
329
|
+
class ProgressiveShadowMaterial extends MeshPhongNodeMaterial {
|
|
330
|
+
_previousShadowMap;
|
|
331
|
+
_averagingWindow;
|
|
332
|
+
constructor(initialTexture) {
|
|
333
|
+
super();
|
|
334
|
+
this._previousShadowMap = texture(initialTexture);
|
|
335
|
+
this._averagingWindow = uniform(100);
|
|
336
|
+
this.fog = false;
|
|
337
|
+
this._buildShader();
|
|
338
|
+
}
|
|
339
|
+
_buildShader() {
|
|
340
|
+
const previousMapTex = this._previousShadowMap;
|
|
341
|
+
const averagingWindowUniform = this._averagingWindow;
|
|
342
|
+
const uvNode = uv();
|
|
343
|
+
this.vertexNode = vec4(sub(uvNode, vec2$2(0.5)).mul(2), 1, 1);
|
|
344
|
+
this.outputNode = vec4(mix(previousMapTex.sample(uv()), output, float(1).div(averagingWindowUniform)));
|
|
345
|
+
}
|
|
346
|
+
get previousShadowMap() {
|
|
347
|
+
return this._previousShadowMap.value;
|
|
348
|
+
}
|
|
349
|
+
set previousShadowMap(v) {
|
|
350
|
+
this._previousShadowMap.value = v;
|
|
351
|
+
}
|
|
352
|
+
get averagingWindow() {
|
|
353
|
+
return this._averagingWindow.value;
|
|
354
|
+
}
|
|
355
|
+
set averagingWindow(v) {
|
|
356
|
+
this._averagingWindow.value = v;
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
class ProgressiveLightMap {
|
|
360
|
+
renderer;
|
|
361
|
+
res;
|
|
362
|
+
scene;
|
|
363
|
+
object;
|
|
364
|
+
buffer1Active;
|
|
365
|
+
progressiveLightMap1;
|
|
366
|
+
progressiveLightMap2;
|
|
367
|
+
discardMat;
|
|
368
|
+
targetMat;
|
|
369
|
+
clearColor;
|
|
370
|
+
clearAlpha;
|
|
371
|
+
lights;
|
|
372
|
+
meshes;
|
|
373
|
+
constructor(renderer, scene, res = 1024) {
|
|
374
|
+
this.renderer = renderer;
|
|
375
|
+
this.res = res;
|
|
376
|
+
this.scene = scene;
|
|
377
|
+
this.buffer1Active = false;
|
|
378
|
+
this.lights = [];
|
|
379
|
+
this.meshes = [];
|
|
380
|
+
this.object = null;
|
|
381
|
+
this.clearColor = new THREE.Color();
|
|
382
|
+
this.clearAlpha = 0;
|
|
383
|
+
const textureParams = {
|
|
384
|
+
type: THREE.HalfFloatType,
|
|
385
|
+
magFilter: THREE.NearestFilter,
|
|
386
|
+
minFilter: THREE.NearestFilter
|
|
387
|
+
};
|
|
388
|
+
this.progressiveLightMap1 = new RenderTarget(this.res, this.res, textureParams);
|
|
389
|
+
this.progressiveLightMap2 = new RenderTarget(this.res, this.res, textureParams);
|
|
390
|
+
this.discardMat = DiscardMaterial;
|
|
391
|
+
this.targetMat = new ProgressiveShadowMaterial(this.progressiveLightMap1.texture);
|
|
392
|
+
}
|
|
393
|
+
clear() {
|
|
394
|
+
this.renderer.getClearColor(this.clearColor);
|
|
395
|
+
this.clearAlpha = this.renderer.getClearAlpha();
|
|
396
|
+
this.renderer.setClearColor("black", 1);
|
|
397
|
+
this.renderer.setRenderTarget(this.progressiveLightMap1);
|
|
398
|
+
this.renderer.clear();
|
|
399
|
+
this.renderer.setRenderTarget(this.progressiveLightMap2);
|
|
400
|
+
this.renderer.clear();
|
|
401
|
+
this.renderer.setRenderTarget(null);
|
|
402
|
+
this.renderer.setClearColor(this.clearColor, this.clearAlpha);
|
|
403
|
+
this.lights = [];
|
|
404
|
+
this.meshes = [];
|
|
405
|
+
this.scene.traverse((object) => {
|
|
406
|
+
if (isGeometry$1(object)) {
|
|
407
|
+
this.meshes.push({ object, material: object.material });
|
|
408
|
+
} else if (isLight(object)) {
|
|
409
|
+
this.lights.push({ object, intensity: object.intensity });
|
|
410
|
+
}
|
|
411
|
+
});
|
|
412
|
+
}
|
|
413
|
+
prepare() {
|
|
414
|
+
this.lights.forEach((light) => light.object.intensity = 0);
|
|
415
|
+
this.meshes.forEach((mesh) => mesh.object.material = this.discardMat);
|
|
416
|
+
}
|
|
417
|
+
finish() {
|
|
418
|
+
this.lights.forEach((light) => light.object.intensity = light.intensity);
|
|
419
|
+
this.meshes.forEach((mesh) => mesh.object.material = mesh.material);
|
|
420
|
+
}
|
|
421
|
+
configure(object) {
|
|
422
|
+
this.object = object;
|
|
423
|
+
}
|
|
424
|
+
update(camera, blendWindow = 100) {
|
|
425
|
+
if (!this.object) return;
|
|
426
|
+
this.targetMat.averagingWindow = blendWindow;
|
|
427
|
+
const originalMaterial = this.object.material;
|
|
428
|
+
this.object.material = this.targetMat;
|
|
429
|
+
const oldFrustumCulled = this.object.frustumCulled;
|
|
430
|
+
this.object.frustumCulled = false;
|
|
431
|
+
const activeMap = this.buffer1Active ? this.progressiveLightMap1 : this.progressiveLightMap2;
|
|
432
|
+
const inactiveMap = this.buffer1Active ? this.progressiveLightMap2 : this.progressiveLightMap1;
|
|
433
|
+
const oldBg = this.scene.background;
|
|
434
|
+
this.scene.background = null;
|
|
435
|
+
this.renderer.setRenderTarget(activeMap);
|
|
436
|
+
this.targetMat.previousShadowMap = inactiveMap.texture;
|
|
437
|
+
this.buffer1Active = !this.buffer1Active;
|
|
438
|
+
this.renderer.render(this.scene, camera);
|
|
439
|
+
this.renderer.setRenderTarget(null);
|
|
440
|
+
this.scene.background = oldBg;
|
|
441
|
+
this.object.frustumCulled = oldFrustumCulled;
|
|
442
|
+
this.object.material = originalMaterial;
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
const AccumulativeShadows = /* @__PURE__ */ React.forwardRef(
|
|
446
|
+
({
|
|
447
|
+
children,
|
|
448
|
+
temporal,
|
|
449
|
+
frames = 40,
|
|
450
|
+
limit = Infinity,
|
|
451
|
+
blend = 20,
|
|
452
|
+
scale = 10,
|
|
453
|
+
opacity = 1,
|
|
454
|
+
alphaTest = 0.75,
|
|
455
|
+
color = "black",
|
|
456
|
+
colorBlend = 2,
|
|
457
|
+
resolution = 1024,
|
|
458
|
+
toneMapped = true,
|
|
459
|
+
...props
|
|
460
|
+
}, forwardRef) => {
|
|
461
|
+
const gl = useThree((state) => state.gl);
|
|
462
|
+
const scene = useThree((state) => state.scene);
|
|
463
|
+
const camera = useThree((state) => state.camera);
|
|
464
|
+
const invalidate = useThree((state) => state.invalidate);
|
|
465
|
+
const gPlane = React.useRef(null);
|
|
466
|
+
const gLights = React.useRef(null);
|
|
467
|
+
const [softShadowMat] = React.useState(() => new SoftShadowMaterialImpl());
|
|
468
|
+
const [plm] = React.useState(() => new ProgressiveLightMap(gl, scene, resolution));
|
|
469
|
+
React.useLayoutEffect(() => {
|
|
470
|
+
plm.configure(gPlane.current);
|
|
471
|
+
}, [plm]);
|
|
472
|
+
React.useEffect(() => {
|
|
473
|
+
softShadowMat.shadowColor = color;
|
|
474
|
+
softShadowMat.blend = colorBlend;
|
|
475
|
+
softShadowMat.map = plm.progressiveLightMap2.texture;
|
|
476
|
+
softShadowMat.toneMapped = toneMapped;
|
|
477
|
+
}, [softShadowMat, color, colorBlend, plm, toneMapped]);
|
|
478
|
+
const api = React.useMemo(
|
|
479
|
+
() => ({
|
|
480
|
+
lights: /* @__PURE__ */ new Map(),
|
|
481
|
+
temporal: !!temporal,
|
|
482
|
+
frames: Math.max(2, frames),
|
|
483
|
+
blend: Math.max(2, frames === Infinity ? blend : frames),
|
|
484
|
+
count: 0,
|
|
485
|
+
getMesh: () => gPlane.current,
|
|
486
|
+
reset: () => {
|
|
487
|
+
plm.clear();
|
|
488
|
+
softShadowMat.opacity = 0;
|
|
489
|
+
softShadowMat.alphaTest = 0;
|
|
490
|
+
api.count = 0;
|
|
491
|
+
},
|
|
492
|
+
update: (frames2 = 1) => {
|
|
493
|
+
if (!api.temporal) {
|
|
494
|
+
softShadowMat.opacity = opacity;
|
|
495
|
+
softShadowMat.alphaTest = alphaTest;
|
|
496
|
+
} else {
|
|
497
|
+
softShadowMat.opacity = Math.min(opacity, softShadowMat.opacity + opacity / api.blend);
|
|
498
|
+
softShadowMat.alphaTest = Math.min(alphaTest, softShadowMat.alphaTest + alphaTest / api.blend);
|
|
499
|
+
}
|
|
500
|
+
gLights.current.visible = true;
|
|
501
|
+
plm.prepare();
|
|
502
|
+
for (let i = 0; i < frames2; i++) {
|
|
503
|
+
api.lights.forEach((light) => light.update());
|
|
504
|
+
plm.update(camera, api.blend);
|
|
505
|
+
}
|
|
506
|
+
gLights.current.visible = false;
|
|
507
|
+
plm.finish();
|
|
508
|
+
}
|
|
509
|
+
}),
|
|
510
|
+
[plm, camera, scene, temporal, frames, blend, opacity, alphaTest, softShadowMat]
|
|
511
|
+
);
|
|
512
|
+
React.useLayoutEffect(() => {
|
|
513
|
+
api.reset();
|
|
514
|
+
if (!api.temporal && api.frames !== Infinity) api.update(api.blend);
|
|
515
|
+
});
|
|
516
|
+
React.useImperativeHandle(forwardRef, () => api, [api]);
|
|
517
|
+
useFrame(() => {
|
|
518
|
+
if ((api.temporal || api.frames === Infinity) && api.count < api.frames && api.count < limit) {
|
|
519
|
+
invalidate();
|
|
520
|
+
api.update();
|
|
521
|
+
api.count++;
|
|
522
|
+
}
|
|
523
|
+
});
|
|
524
|
+
return /* @__PURE__ */ React.createElement("group", { ...props }, /* @__PURE__ */ React.createElement("group", { traverse: () => null, ref: gLights }, /* @__PURE__ */ React.createElement(accumulativeContext.Provider, { value: api }, children)), /* @__PURE__ */ React.createElement("mesh", { receiveShadow: true, ref: gPlane, scale, rotation: [-Math.PI / 2, 0, 0] }, /* @__PURE__ */ React.createElement("planeGeometry", null), /* @__PURE__ */ React.createElement("primitive", { object: softShadowMat, attach: "material" })));
|
|
525
|
+
}
|
|
526
|
+
);
|
|
527
|
+
const RandomizedLight = /* @__PURE__ */ React.forwardRef(
|
|
528
|
+
({
|
|
529
|
+
castShadow = true,
|
|
530
|
+
bias = 1e-3,
|
|
531
|
+
mapSize = 512,
|
|
532
|
+
size = 5,
|
|
533
|
+
near = 0.5,
|
|
534
|
+
far = 500,
|
|
535
|
+
frames = 1,
|
|
536
|
+
position = [0, 0, 0],
|
|
537
|
+
radius = 1,
|
|
538
|
+
amount = 8,
|
|
539
|
+
intensity = Math.PI,
|
|
540
|
+
ambient = 0.5,
|
|
541
|
+
...props
|
|
542
|
+
}, forwardRef) => {
|
|
543
|
+
const gLights = React.useRef(null);
|
|
544
|
+
const length = new THREE.Vector3(...position).length();
|
|
545
|
+
const parent = React.useContext(accumulativeContext);
|
|
546
|
+
const update = React.useCallback(() => {
|
|
547
|
+
let light;
|
|
548
|
+
if (gLights.current) {
|
|
549
|
+
for (let l = 0; l < gLights.current.children.length; l++) {
|
|
550
|
+
light = gLights.current.children[l];
|
|
551
|
+
if (Math.random() > ambient) {
|
|
552
|
+
light.position.set(
|
|
553
|
+
position[0] + THREE.MathUtils.randFloatSpread(radius),
|
|
554
|
+
position[1] + THREE.MathUtils.randFloatSpread(radius),
|
|
555
|
+
position[2] + THREE.MathUtils.randFloatSpread(radius)
|
|
556
|
+
);
|
|
557
|
+
} else {
|
|
558
|
+
let lambda = Math.acos(2 * Math.random() - 1) - Math.PI / 2;
|
|
559
|
+
let phi = 2 * Math.PI * Math.random();
|
|
560
|
+
light.position.set(
|
|
561
|
+
Math.cos(lambda) * Math.cos(phi) * length,
|
|
562
|
+
Math.abs(Math.cos(lambda) * Math.sin(phi) * length),
|
|
563
|
+
Math.sin(lambda) * length
|
|
564
|
+
);
|
|
565
|
+
}
|
|
566
|
+
}
|
|
567
|
+
}
|
|
568
|
+
}, [radius, ambient, length, ...position]);
|
|
569
|
+
const api = React.useMemo(() => ({ update }), [update]);
|
|
570
|
+
React.useImperativeHandle(forwardRef, () => api, [api]);
|
|
571
|
+
React.useLayoutEffect(() => {
|
|
572
|
+
const group = gLights.current;
|
|
573
|
+
if (parent) parent.lights?.set(group.uuid, api);
|
|
574
|
+
return () => void parent?.lights?.delete(group.uuid);
|
|
575
|
+
}, [parent, api]);
|
|
576
|
+
return /* @__PURE__ */ React.createElement("group", { ref: gLights, ...props }, Array.from({ length: amount }, (_, index) => /* @__PURE__ */ React.createElement(
|
|
577
|
+
"directionalLight",
|
|
578
|
+
{
|
|
579
|
+
key: index,
|
|
580
|
+
castShadow,
|
|
581
|
+
"shadow-bias": bias,
|
|
582
|
+
"shadow-mapSize": [mapSize, mapSize],
|
|
583
|
+
intensity: intensity / amount
|
|
584
|
+
},
|
|
585
|
+
/* @__PURE__ */ React.createElement("orthographicCamera", { attach: "shadow-camera", args: [-size, size, size, -size, near, far] })
|
|
586
|
+
)));
|
|
587
|
+
}
|
|
588
|
+
);
|
|
263
589
|
|
|
264
590
|
function useFBO(width, height, settings) {
|
|
265
591
|
const size = useThree((state) => state.size);
|
|
@@ -408,10 +734,10 @@ class CausticsProjectionMaterial extends MeshBasicNodeMaterial {
|
|
|
408
734
|
this._causticsTextureB.value = v;
|
|
409
735
|
}
|
|
410
736
|
get color() {
|
|
411
|
-
return this._color
|
|
737
|
+
return this._color?.value;
|
|
412
738
|
}
|
|
413
739
|
set color(v) {
|
|
414
|
-
this._color.value = v;
|
|
740
|
+
if (this._color) this._color.value = v;
|
|
415
741
|
}
|
|
416
742
|
get lightProjMatrix() {
|
|
417
743
|
return this._lightProjMatrix.value;
|
|
@@ -824,29 +1150,307 @@ const Caustics = /* @__PURE__ */ React.forwardRef(
|
|
|
824
1150
|
}
|
|
825
1151
|
);
|
|
826
1152
|
|
|
827
|
-
const
|
|
828
|
-
|
|
1153
|
+
const EnvironmentBRDF = /* @__PURE__ */ Fn((inputs) => {
|
|
1154
|
+
const { dotNV, specularColor, specularF90, roughness: roughness2 } = inputs;
|
|
1155
|
+
const fab = DFGLUT({ dotNV, roughness: roughness2 });
|
|
1156
|
+
return specularColor.mul(fab.x).add(specularF90.mul(fab.y));
|
|
829
1157
|
});
|
|
830
|
-
|
|
831
|
-
const
|
|
1158
|
+
const rand = /* @__PURE__ */ Fn((inputs) => {
|
|
1159
|
+
const [seed, fragCoord] = inputs;
|
|
832
1160
|
return fract(sin(dot(vec3(fragCoord.xy, seed), vec3(12.9898, 78.233, 45.164))).mul(43758.5453));
|
|
833
1161
|
});
|
|
834
|
-
const applyVolumeAttenuation = /* @__PURE__ */ Fn(
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
1162
|
+
const applyVolumeAttenuation = /* @__PURE__ */ Fn((inputs) => {
|
|
1163
|
+
const [radiance, transmissionDistance, attColor, attDistance] = inputs;
|
|
1164
|
+
const isInfinite = attDistance.greaterThan(1e10);
|
|
1165
|
+
const safeColor = max(attColor, vec3(1e-4));
|
|
1166
|
+
const attenuationCoefficient = log(safeColor).negate().div(attDistance);
|
|
1167
|
+
const transmittance = exp(attenuationCoefficient.negate().mul(transmissionDistance));
|
|
1168
|
+
return select(isInfinite, radiance, transmittance.mul(radiance));
|
|
1169
|
+
});
|
|
1170
|
+
const getVolumeTransmissionRay = /* @__PURE__ */ Fn((inputs) => {
|
|
1171
|
+
const [n, v, thicknessVal, iorVal] = inputs;
|
|
1172
|
+
const refractionVector = refract(v.negate(), normalize(n), float(1).div(iorVal));
|
|
1173
|
+
const refractLen = length(refractionVector);
|
|
1174
|
+
const safeRefractionVector = select(
|
|
1175
|
+
refractLen.greaterThan(1e-3),
|
|
1176
|
+
refractionVector,
|
|
1177
|
+
v.negate()
|
|
1178
|
+
// Fallback: ray goes straight through
|
|
1179
|
+
);
|
|
1180
|
+
const modelScale = vec3(
|
|
1181
|
+
length(modelWorldMatrix[0].xyz),
|
|
1182
|
+
length(modelWorldMatrix[1].xyz),
|
|
1183
|
+
length(modelWorldMatrix[2].xyz)
|
|
1184
|
+
);
|
|
1185
|
+
return normalize(safeRefractionVector).mul(thicknessVal.mul(modelScale));
|
|
1186
|
+
});
|
|
1187
|
+
const getRefractionUV = /* @__PURE__ */ Fn((inputs) => {
|
|
1188
|
+
const [norm, viewDir, iorVal, thicknessVal, position] = inputs;
|
|
1189
|
+
const transmissionRay = getVolumeTransmissionRay(norm, viewDir, thicknessVal, iorVal);
|
|
1190
|
+
const refractedRayExit = position.add(transmissionRay);
|
|
1191
|
+
const ndcPos = cameraProjectionMatrix.mul(cameraViewMatrix.mul(vec4(refractedRayExit, 1)));
|
|
1192
|
+
const safeW = max(ndcPos.w, float(1e-3));
|
|
1193
|
+
const refractionCoords = vec2$2(ndcPos.xy.div(safeW)).toVar();
|
|
1194
|
+
refractionCoords.addAssign(1);
|
|
1195
|
+
refractionCoords.divAssign(2);
|
|
1196
|
+
refractionCoords.assign(vec2$2(refractionCoords.x, refractionCoords.y.oneMinus()));
|
|
1197
|
+
refractionCoords.assign(refractionCoords.clamp(1e-3, 0.999));
|
|
1198
|
+
return refractionCoords;
|
|
1199
|
+
});
|
|
1200
|
+
class TransmissionLightingModel extends PhysicalLightingModel {
|
|
1201
|
+
_bufferTex;
|
|
1202
|
+
_chromaticAberration;
|
|
1203
|
+
_anisotropicBlur;
|
|
1204
|
+
_timeUniform;
|
|
1205
|
+
_distortion;
|
|
1206
|
+
_distortionScale;
|
|
1207
|
+
_temporalDistortion;
|
|
1208
|
+
_samples;
|
|
1209
|
+
_debugMode;
|
|
1210
|
+
constructor(options, transmissionUniforms) {
|
|
1211
|
+
super(
|
|
1212
|
+
options.clearcoat ?? false,
|
|
1213
|
+
options.sheen ?? false,
|
|
1214
|
+
options.iridescence ?? false,
|
|
1215
|
+
options.anisotropy ?? false,
|
|
1216
|
+
true,
|
|
1217
|
+
// transmission always true for our material
|
|
1218
|
+
options.dispersion ?? false
|
|
1219
|
+
);
|
|
1220
|
+
this._bufferTex = transmissionUniforms.bufferTex;
|
|
1221
|
+
this._chromaticAberration = transmissionUniforms.chromaticAberration;
|
|
1222
|
+
this._anisotropicBlur = transmissionUniforms.anisotropicBlur;
|
|
1223
|
+
this._timeUniform = transmissionUniforms.timeUniform;
|
|
1224
|
+
this._distortion = transmissionUniforms.distortion;
|
|
1225
|
+
this._distortionScale = transmissionUniforms.distortionScale;
|
|
1226
|
+
this._temporalDistortion = transmissionUniforms.temporalDistortion;
|
|
1227
|
+
this._samples = transmissionUniforms.samples;
|
|
1228
|
+
this._debugMode = transmissionUniforms.debugMode;
|
|
1229
|
+
}
|
|
1230
|
+
start(builder) {
|
|
1231
|
+
if (this.clearcoat === true) {
|
|
1232
|
+
this.clearcoatRadiance = vec3().toVar("clearcoatRadiance");
|
|
1233
|
+
this.clearcoatSpecularDirect = vec3().toVar("clearcoatSpecularDirect");
|
|
1234
|
+
this.clearcoatSpecularIndirect = vec3().toVar("clearcoatSpecularIndirect");
|
|
1235
|
+
}
|
|
1236
|
+
if (this.sheen === true) {
|
|
1237
|
+
this.sheenSpecularDirect = vec3().toVar("sheenSpecularDirect");
|
|
1238
|
+
this.sheenSpecularIndirect = vec3().toVar("sheenSpecularIndirect");
|
|
1239
|
+
}
|
|
1240
|
+
if (this.transmission === true) {
|
|
1241
|
+
const position = positionWorld;
|
|
1242
|
+
const v = normalize(cameraPosition.sub(positionWorld));
|
|
1243
|
+
const n = normalWorld;
|
|
1244
|
+
const context = builder.context;
|
|
1245
|
+
const bufferTex = this._bufferTex;
|
|
1246
|
+
const chromaticAberrationUniform = this._chromaticAberration;
|
|
1247
|
+
const anisotropicBlurUniform = this._anisotropicBlur;
|
|
1248
|
+
const timeUniform = this._timeUniform;
|
|
1249
|
+
const distortionUniform = this._distortion;
|
|
1250
|
+
const distortionScaleUniform = this._distortionScale;
|
|
1251
|
+
const temporalDistortionUniform = this._temporalDistortion;
|
|
1252
|
+
const sampleCount = this._samples;
|
|
1253
|
+
const debugModeUniform = this._debugMode;
|
|
1254
|
+
const getCustomTransmission = Fn(() => {
|
|
1255
|
+
const transmissionAccum = vec3(0).toVar("transmissionAccum");
|
|
1256
|
+
const fragCoord = screenCoordinate.xy;
|
|
1257
|
+
const runningSeed = float(0).toVar("runningSeed");
|
|
1258
|
+
const randomCoords = rand(runningSeed, fragCoord);
|
|
1259
|
+
runningSeed.addAssign(1);
|
|
1260
|
+
const temporalOffset = vec3(timeUniform, timeUniform.negate(), timeUniform.negate()).mul(
|
|
1261
|
+
temporalDistortionUniform
|
|
1262
|
+
);
|
|
1263
|
+
const noiseInput = position.mul(distortionScaleUniform).add(temporalOffset);
|
|
1264
|
+
const distortionNormal = select(
|
|
1265
|
+
distortionUniform.greaterThan(0),
|
|
1266
|
+
mx_fractal_noise_vec3(noiseInput, int(4), float(2), float(0.5)).mul(distortionUniform),
|
|
1267
|
+
vec3(0)
|
|
1268
|
+
);
|
|
1269
|
+
const thicknessSmear = thickness.mul(max(pow(roughness, 0.33), anisotropicBlurUniform));
|
|
1270
|
+
Loop(sampleCount, ({ i }) => {
|
|
1271
|
+
const fi = float(i);
|
|
1272
|
+
const progress = fi.add(randomCoords).div(float(sampleCount));
|
|
1273
|
+
const randX = rand(runningSeed, fragCoord).sub(0.5);
|
|
1274
|
+
runningSeed.addAssign(1);
|
|
1275
|
+
const randY = rand(runningSeed, fragCoord).sub(0.5);
|
|
1276
|
+
runningSeed.addAssign(1);
|
|
1277
|
+
const randZ = rand(runningSeed, fragCoord).sub(0.5);
|
|
1278
|
+
runningSeed.addAssign(1);
|
|
1279
|
+
const randW = rand(runningSeed, fragCoord);
|
|
1280
|
+
runningSeed.addAssign(1);
|
|
1281
|
+
const randomDir = normalize(vec3(randX, randY, randZ)).mul(pow(randW, 0.33));
|
|
1282
|
+
const sampleNorm = normalize(n.add(roughness.mul(roughness).mul(2).mul(randomDir)).add(distortionNormal));
|
|
1283
|
+
const sampleThickness = thickness.add(thicknessSmear.mul(progress));
|
|
1284
|
+
const iorR = ior;
|
|
1285
|
+
const iorG = ior.mul(float(1).add(chromaticAberrationUniform.mul(progress)));
|
|
1286
|
+
const iorB = ior.mul(float(1).add(chromaticAberrationUniform.mul(2).mul(progress)));
|
|
1287
|
+
const uvR = getRefractionUV(sampleNorm, v, iorR, sampleThickness, position);
|
|
1288
|
+
const uvG = getRefractionUV(sampleNorm, v, iorG, sampleThickness, position);
|
|
1289
|
+
const uvB = getRefractionUV(sampleNorm, v, iorB, sampleThickness, position);
|
|
1290
|
+
const sampleR = texture(bufferTex, uvR);
|
|
1291
|
+
const sampleG = texture(bufferTex, uvG);
|
|
1292
|
+
const sampleB = texture(bufferTex, uvB);
|
|
1293
|
+
transmissionAccum.x.addAssign(sampleR.r);
|
|
1294
|
+
transmissionAccum.y.addAssign(sampleG.g);
|
|
1295
|
+
transmissionAccum.z.addAssign(sampleB.b);
|
|
1296
|
+
});
|
|
1297
|
+
const avgTransmission = transmissionAccum.div(float(sampleCount));
|
|
1298
|
+
const debugUV = getRefractionUV(n, v, ior, thickness, position);
|
|
1299
|
+
const debugNdotV = n.dot(v);
|
|
1300
|
+
const isNeg = debugNdotV.lessThan(0);
|
|
1301
|
+
const sampleUVFlipped = vec2$2(screenUV.x, screenUV.y.oneMinus()).clamp(1e-3, 0.999);
|
|
1302
|
+
const directSampleFlipped = texture(bufferTex, sampleUVFlipped);
|
|
1303
|
+
const testRay = getVolumeTransmissionRay(n, v, thickness, ior);
|
|
1304
|
+
const rayLen = length(testRay);
|
|
1305
|
+
const manualUV = screenCoordinate.xy.div(screenSize);
|
|
1306
|
+
const noFlipUV = screenUV.clamp(1e-3, 0.999);
|
|
1307
|
+
const flippedUV = vec2$2(screenUV.x, screenUV.y.oneMinus()).clamp(1e-3, 0.999);
|
|
1308
|
+
const useFlipped = screenUV.x.greaterThan(0.5);
|
|
1309
|
+
const splitSampleUV = select(useFlipped, flippedUV, noFlipUV);
|
|
1310
|
+
const splitSample = texture(bufferTex, splitSampleUV);
|
|
1311
|
+
const directSampleNoFlip = texture(bufferTex, screenUV.clamp(1e-3, 0.999));
|
|
1312
|
+
const centerSample = texture(bufferTex, vec2$2(0.5, 0.5));
|
|
1313
|
+
const transmissionRayDbg = getVolumeTransmissionRay(n, v, thickness, ior);
|
|
1314
|
+
const refractedRayExitDbg = position.add(transmissionRayDbg);
|
|
1315
|
+
const ndcPosDbg = cameraProjectionMatrix.mul(cameraViewMatrix.mul(vec4(refractedRayExitDbg, 1)));
|
|
1316
|
+
const safeWDbg = max(ndcPosDbg.w, float(1e-3));
|
|
1317
|
+
const rawCoordsDbg = vec2$2(ndcPosDbg.xy.div(safeWDbg)).toVar();
|
|
1318
|
+
rawCoordsDbg.addAssign(1);
|
|
1319
|
+
rawCoordsDbg.divAssign(2);
|
|
1320
|
+
rawCoordsDbg.assign(vec2$2(rawCoordsDbg.x, rawCoordsDbg.y.oneMinus()));
|
|
1321
|
+
const outOfRange = rawCoordsDbg.x.lessThan(0).or(rawCoordsDbg.x.greaterThan(1)).or(rawCoordsDbg.y.lessThan(0)).or(rawCoordsDbg.y.greaterThan(1));
|
|
1322
|
+
const clipPosDbg = cameraProjectionMatrix.mul(cameraViewMatrix.mul(vec4(position, 1)));
|
|
1323
|
+
const safeWDbg2 = max(clipPosDbg.w, float(1e-3));
|
|
1324
|
+
const projUVDbg = vec2$2(clipPosDbg.xy.div(safeWDbg2)).toVar();
|
|
1325
|
+
projUVDbg.addAssign(1);
|
|
1326
|
+
projUVDbg.divAssign(2);
|
|
1327
|
+
projUVDbg.assign(vec2$2(projUVDbg.x, projUVDbg.y.oneMinus()));
|
|
1328
|
+
projUVDbg.assign(projUVDbg.clamp(1e-3, 0.999));
|
|
1329
|
+
const projectedSample = texture(bufferTex, projUVDbg);
|
|
1330
|
+
const wNorm = clipPosDbg.w.div(10).add(0.5).clamp(0, 1);
|
|
1331
|
+
const isBehind = clipPosDbg.w.lessThan(0);
|
|
1332
|
+
const rawNdcX = clipPosDbg.x.div(safeWDbg2);
|
|
1333
|
+
const rawNdcY = clipPosDbg.y.div(safeWDbg2);
|
|
1334
|
+
const result = vec4(0, 0, 0, 1).toVar();
|
|
1335
|
+
result.assign(
|
|
1336
|
+
select(
|
|
1337
|
+
debugModeUniform.equal(1),
|
|
1338
|
+
vec4(avgTransmission, float(1)),
|
|
1339
|
+
select(
|
|
1340
|
+
debugModeUniform.equal(2),
|
|
1341
|
+
vec4(debugUV.x, debugUV.y, float(0), float(1)),
|
|
1342
|
+
select(
|
|
1343
|
+
debugModeUniform.equal(3),
|
|
1344
|
+
vec4(
|
|
1345
|
+
select(isNeg, debugNdotV.abs(), float(0)),
|
|
1346
|
+
select(isNeg, float(0), debugNdotV),
|
|
1347
|
+
float(0),
|
|
1348
|
+
float(1)
|
|
1349
|
+
),
|
|
1350
|
+
select(
|
|
1351
|
+
debugModeUniform.equal(4),
|
|
1352
|
+
vec4(v.mul(0.5).add(0.5), float(1)),
|
|
1353
|
+
select(
|
|
1354
|
+
debugModeUniform.equal(5),
|
|
1355
|
+
vec4(n.mul(0.5).add(0.5), float(1)),
|
|
1356
|
+
select(
|
|
1357
|
+
debugModeUniform.equal(6),
|
|
1358
|
+
vec4(directSampleFlipped.rgb, float(1)),
|
|
1359
|
+
select(
|
|
1360
|
+
debugModeUniform.equal(7),
|
|
1361
|
+
vec4(rayLen, rayLen, rayLen, float(1)),
|
|
1362
|
+
select(
|
|
1363
|
+
debugModeUniform.equal(8),
|
|
1364
|
+
vec4(screenUV.x, screenUV.y, float(0), float(1)),
|
|
1365
|
+
select(
|
|
1366
|
+
debugModeUniform.equal(9),
|
|
1367
|
+
vec4(screenSize.x.div(2e3), screenSize.y.div(2e3), float(0), float(1)),
|
|
1368
|
+
select(
|
|
1369
|
+
debugModeUniform.equal(10),
|
|
1370
|
+
vec4(manualUV.x, manualUV.y, float(0), float(1)),
|
|
1371
|
+
select(
|
|
1372
|
+
debugModeUniform.equal(11),
|
|
1373
|
+
vec4(splitSample.rgb, float(1)),
|
|
1374
|
+
select(
|
|
1375
|
+
debugModeUniform.equal(12),
|
|
1376
|
+
vec4(directSampleNoFlip.rgb, float(1)),
|
|
1377
|
+
select(
|
|
1378
|
+
debugModeUniform.equal(13),
|
|
1379
|
+
vec4(
|
|
1380
|
+
select(outOfRange, float(1), float(0)),
|
|
1381
|
+
rawCoordsDbg.x.clamp(0, 1),
|
|
1382
|
+
rawCoordsDbg.y.clamp(0, 1),
|
|
1383
|
+
float(1)
|
|
1384
|
+
),
|
|
1385
|
+
select(
|
|
1386
|
+
debugModeUniform.equal(14),
|
|
1387
|
+
vec4(
|
|
1388
|
+
select(isBehind, float(1), float(0)),
|
|
1389
|
+
wNorm,
|
|
1390
|
+
select(isBehind, float(0), float(1)),
|
|
1391
|
+
float(1)
|
|
1392
|
+
),
|
|
1393
|
+
select(
|
|
1394
|
+
debugModeUniform.equal(15),
|
|
1395
|
+
vec4(centerSample.rgb, float(1)),
|
|
1396
|
+
select(
|
|
1397
|
+
debugModeUniform.equal(16),
|
|
1398
|
+
vec4(projectedSample.rgb, float(1)),
|
|
1399
|
+
select(
|
|
1400
|
+
debugModeUniform.equal(17),
|
|
1401
|
+
// Raw NDC as color: map [-1,1] to [0,1]
|
|
1402
|
+
vec4(rawNdcX.add(1).div(2), rawNdcY.add(1).div(2), float(0.5), float(1)),
|
|
1403
|
+
select(
|
|
1404
|
+
debugModeUniform.equal(18),
|
|
1405
|
+
// Solid magenta - if black here, shader isn't running
|
|
1406
|
+
vec4(1, 0, 1, 1),
|
|
1407
|
+
select(
|
|
1408
|
+
debugModeUniform.equal(19),
|
|
1409
|
+
// Tinted FBO sample: mix sample with UV color
|
|
1410
|
+
vec4(
|
|
1411
|
+
directSampleFlipped.r.add(screenUV.x.mul(0.3)),
|
|
1412
|
+
directSampleFlipped.g.add(screenUV.y.mul(0.3)),
|
|
1413
|
+
directSampleFlipped.b,
|
|
1414
|
+
float(1)
|
|
1415
|
+
),
|
|
1416
|
+
vec4(0, 0, 0, 1)
|
|
1417
|
+
// Placeholder for mode 0
|
|
1418
|
+
)
|
|
1419
|
+
)
|
|
1420
|
+
)
|
|
1421
|
+
)
|
|
1422
|
+
)
|
|
1423
|
+
)
|
|
1424
|
+
)
|
|
1425
|
+
)
|
|
1426
|
+
)
|
|
1427
|
+
)
|
|
1428
|
+
)
|
|
1429
|
+
)
|
|
1430
|
+
)
|
|
1431
|
+
)
|
|
1432
|
+
)
|
|
1433
|
+
)
|
|
1434
|
+
)
|
|
1435
|
+
)
|
|
1436
|
+
)
|
|
1437
|
+
);
|
|
1438
|
+
const attenuated = applyVolumeAttenuation(avgTransmission, thickness, attenuationColor, attenuationDistance);
|
|
1439
|
+
const NdotV = n.dot(v).abs().clamp(1e-3, 1);
|
|
1440
|
+
const glassF0 = vec3(0.04);
|
|
1441
|
+
const brdf = EnvironmentBRDF({ dotNV: NdotV, specularColor: glassF0, specularF90: float(1), roughness });
|
|
1442
|
+
const transmissionResult = brdf.oneMinus().mul(attenuated).mul(diffuseColor.rgb);
|
|
1443
|
+
const normalOutput = vec4(transmissionResult, float(1));
|
|
1444
|
+
return select(debugModeUniform.greaterThan(0), result, normalOutput);
|
|
1445
|
+
});
|
|
1446
|
+
context.backdrop = getCustomTransmission();
|
|
1447
|
+
context.backdropAlpha = transmission;
|
|
1448
|
+
diffuseColor.a.mulAssign(mix(1, context.backdrop.a, transmission));
|
|
1449
|
+
}
|
|
846
1450
|
}
|
|
847
|
-
|
|
1451
|
+
}
|
|
848
1452
|
class MeshTransmissionMaterialImpl extends MeshPhysicalNodeMaterial {
|
|
849
|
-
|
|
1453
|
+
// Custom uniforms
|
|
850
1454
|
_chromaticAberration;
|
|
851
1455
|
_anisotropicBlur;
|
|
852
1456
|
_time;
|
|
@@ -854,13 +1458,13 @@ class MeshTransmissionMaterialImpl extends MeshPhysicalNodeMaterial {
|
|
|
854
1458
|
_distortionScale;
|
|
855
1459
|
_temporalDistortion;
|
|
856
1460
|
_buffer;
|
|
1461
|
+
// Texture node
|
|
857
1462
|
_transmissionValue;
|
|
858
|
-
|
|
859
|
-
_attenuationColor;
|
|
860
|
-
_samples;
|
|
861
|
-
_transmissionSampler;
|
|
1463
|
+
_debugMode;
|
|
862
1464
|
/** Type flag for identification */
|
|
863
1465
|
isMeshTransmissionMaterial = true;
|
|
1466
|
+
_samples;
|
|
1467
|
+
_transmissionSampler;
|
|
864
1468
|
constructor(samples = 6, transmissionSampler = false) {
|
|
865
1469
|
super();
|
|
866
1470
|
this._samples = samples;
|
|
@@ -871,179 +1475,106 @@ class MeshTransmissionMaterialImpl extends MeshPhysicalNodeMaterial {
|
|
|
871
1475
|
this._distortion = uniform(0);
|
|
872
1476
|
this._distortionScale = uniform(0.5);
|
|
873
1477
|
this._temporalDistortion = uniform(0);
|
|
874
|
-
this.
|
|
1478
|
+
this._debugMode = uniform(0);
|
|
1479
|
+
const placeholderTexture = new THREE.DataTexture(new Uint8Array([255, 255, 255, 255]), 1, 1);
|
|
1480
|
+
placeholderTexture.needsUpdate = true;
|
|
1481
|
+
this._buffer = uniformTexture(placeholderTexture);
|
|
875
1482
|
this._transmissionValue = uniform(1);
|
|
876
|
-
this.
|
|
877
|
-
this._attenuationColor = uniform(new THREE.Color("white"));
|
|
878
|
-
this.transmission = transmissionSampler ? 1 : 0;
|
|
1483
|
+
this.transmission = transmissionSampler ? 1 : 1e-3;
|
|
879
1484
|
this.roughness = 0;
|
|
880
1485
|
this.thickness = 0;
|
|
881
|
-
this.
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
Loop(samples, ({ i }) => {
|
|
922
|
-
const fi = float(i);
|
|
923
|
-
const randX = rand({ seed: runningSeed, fragCoord }).sub(0.5);
|
|
924
|
-
runningSeed.addAssign(1);
|
|
925
|
-
const randY = rand({ seed: runningSeed, fragCoord }).sub(0.5);
|
|
926
|
-
runningSeed.addAssign(1);
|
|
927
|
-
const randZ = rand({ seed: runningSeed, fragCoord }).sub(0.5);
|
|
928
|
-
runningSeed.addAssign(1);
|
|
929
|
-
const randW = rand({ seed: runningSeed, fragCoord });
|
|
930
|
-
runningSeed.addAssign(1);
|
|
931
|
-
const randomDir = normalize(vec3(randX, randY, randZ)).mul(pow(randW, 0.33));
|
|
932
|
-
const sampleNorm = normalize(
|
|
933
|
-
n.add(roughnessFactor.mul(roughnessFactor).mul(2).mul(randomDir)).add(distortionNormal)
|
|
934
|
-
);
|
|
935
|
-
const refractionDir = refract(v.negate(), sampleNorm, float(1).div(iorVal));
|
|
936
|
-
const sampleThickness = thicknessVal.add(thicknessSmear.mul(fi.add(randomCoords)).div(float(samples)));
|
|
937
|
-
const refractedExit = pos.add(refractionDir.mul(sampleThickness));
|
|
938
|
-
const clipPos = cameraProjectionMatrix.mul(cameraViewMatrix.mul(vec4(refractedExit, 1)));
|
|
939
|
-
const ndcPos = clipPos.xyz.div(clipPos.w);
|
|
940
|
-
const refractionUV = ndcPos.xy.mul(0.5).add(0.5);
|
|
941
|
-
const sampledColor = texture(bufferTex, refractionUV);
|
|
942
|
-
const transmissionR = sampledColor.r;
|
|
943
|
-
const chromaticOffsetG = chromaticAberrationUniform.mul(fi.add(randomCoords)).div(float(samples));
|
|
944
|
-
const iorG = iorVal.mul(float(1).add(chromaticOffsetG));
|
|
945
|
-
const refractionDirG = refract(v.negate(), sampleNorm, float(1).div(iorG));
|
|
946
|
-
const refractedExitG = pos.add(refractionDirG.mul(sampleThickness));
|
|
947
|
-
const clipPosG = cameraProjectionMatrix.mul(cameraViewMatrix.mul(vec4(refractedExitG, 1)));
|
|
948
|
-
const ndcPosG = clipPosG.xyz.div(clipPosG.w);
|
|
949
|
-
const refractionUVG = ndcPosG.xy.mul(0.5).add(0.5);
|
|
950
|
-
const transmissionG = texture(bufferTex, refractionUVG).g;
|
|
951
|
-
const chromaticOffsetB = chromaticAberrationUniform.mul(2).mul(fi.add(randomCoords)).div(float(samples));
|
|
952
|
-
const iorB = iorVal.mul(float(1).add(chromaticOffsetB));
|
|
953
|
-
const refractionDirB = refract(v.negate(), sampleNorm, float(1).div(iorB));
|
|
954
|
-
const refractedExitB = pos.add(refractionDirB.mul(sampleThickness));
|
|
955
|
-
const clipPosB = cameraProjectionMatrix.mul(cameraViewMatrix.mul(vec4(refractedExitB, 1)));
|
|
956
|
-
const ndcPosB = clipPosB.xyz.div(clipPosB.w);
|
|
957
|
-
const refractionUVB = ndcPosB.xy.mul(0.5).add(0.5);
|
|
958
|
-
const transmissionB = texture(bufferTex, refractionUVB).b;
|
|
959
|
-
transmission.x.addAssign(transmissionR);
|
|
960
|
-
transmission.y.addAssign(transmissionG);
|
|
961
|
-
transmission.z.addAssign(transmissionB);
|
|
962
|
-
});
|
|
963
|
-
const avgTransmission = transmission.div(float(samples));
|
|
964
|
-
const transmissionRayLength = thicknessVal;
|
|
965
|
-
const attenuatedTransmission = applyVolumeAttenuation({
|
|
966
|
-
radiance: avgTransmission,
|
|
967
|
-
transmissionDistance: transmissionRayLength,
|
|
968
|
-
attenuationColor: attenuationColorUniform,
|
|
969
|
-
attenuationDistance: attenuationDistanceUniform
|
|
970
|
-
});
|
|
971
|
-
const baseDiffuse = diffuseColor.rgb;
|
|
972
|
-
const finalColor = mix(baseDiffuse, attenuatedTransmission, transmissionUniform);
|
|
973
|
-
return vec4(finalColor, diffuseColor.a);
|
|
974
|
-
})();
|
|
1486
|
+
this.ior = 1.5;
|
|
1487
|
+
this.transparent = true;
|
|
1488
|
+
}
|
|
1489
|
+
setupLightingModel() {
|
|
1490
|
+
if (this._transmissionSampler) {
|
|
1491
|
+
return super.setupLightingModel();
|
|
1492
|
+
}
|
|
1493
|
+
return new TransmissionLightingModel(
|
|
1494
|
+
{
|
|
1495
|
+
clearcoat: this.useClearcoat,
|
|
1496
|
+
sheen: this.useSheen,
|
|
1497
|
+
iridescence: this.useIridescence,
|
|
1498
|
+
anisotropy: this.useAnisotropy,
|
|
1499
|
+
dispersion: this.useDispersion
|
|
1500
|
+
},
|
|
1501
|
+
{
|
|
1502
|
+
bufferTex: this._buffer,
|
|
1503
|
+
chromaticAberration: this._chromaticAberration,
|
|
1504
|
+
anisotropicBlur: this._anisotropicBlur,
|
|
1505
|
+
timeUniform: this._time,
|
|
1506
|
+
distortion: this._distortion,
|
|
1507
|
+
distortionScale: this._distortionScale,
|
|
1508
|
+
temporalDistortion: this._temporalDistortion,
|
|
1509
|
+
samples: this._samples,
|
|
1510
|
+
debugMode: this._debugMode
|
|
1511
|
+
}
|
|
1512
|
+
);
|
|
1513
|
+
}
|
|
1514
|
+
//* Property Accessors ==============================
|
|
1515
|
+
get time() {
|
|
1516
|
+
return this._time.value;
|
|
1517
|
+
}
|
|
1518
|
+
set time(v) {
|
|
1519
|
+
this._time.value = v;
|
|
1520
|
+
}
|
|
1521
|
+
get buffer() {
|
|
1522
|
+
return this._buffer.value;
|
|
1523
|
+
}
|
|
1524
|
+
set buffer(v) {
|
|
1525
|
+
this._buffer.value = v;
|
|
975
1526
|
}
|
|
976
|
-
//* Uniform Accessors ==============================
|
|
977
|
-
/** Chromatic aberration strength, default: 0.05 */
|
|
978
1527
|
get chromaticAberration() {
|
|
979
1528
|
return this._chromaticAberration.value;
|
|
980
1529
|
}
|
|
981
1530
|
set chromaticAberration(v) {
|
|
982
1531
|
this._chromaticAberration.value = v;
|
|
983
1532
|
}
|
|
984
|
-
/** Anisotropic blur amount, default: 0.1 */
|
|
985
1533
|
get anisotropicBlur() {
|
|
986
1534
|
return this._anisotropicBlur.value;
|
|
987
1535
|
}
|
|
988
1536
|
set anisotropicBlur(v) {
|
|
989
1537
|
this._anisotropicBlur.value = v;
|
|
990
1538
|
}
|
|
991
|
-
/** Animation time (set from useFrame), default: 0 */
|
|
992
|
-
get time() {
|
|
993
|
-
return this._time.value;
|
|
994
|
-
}
|
|
995
|
-
set time(v) {
|
|
996
|
-
this._time.value = v;
|
|
997
|
-
}
|
|
998
|
-
/** Noise distortion amount, default: 0 */
|
|
999
1539
|
get distortion() {
|
|
1000
1540
|
return this._distortion.value;
|
|
1001
1541
|
}
|
|
1002
1542
|
set distortion(v) {
|
|
1003
1543
|
this._distortion.value = v;
|
|
1004
1544
|
}
|
|
1005
|
-
/** Distortion noise scale, default: 0.5 */
|
|
1006
1545
|
get distortionScale() {
|
|
1007
1546
|
return this._distortionScale.value;
|
|
1008
1547
|
}
|
|
1009
1548
|
set distortionScale(v) {
|
|
1010
1549
|
this._distortionScale.value = v;
|
|
1011
1550
|
}
|
|
1012
|
-
/** Temporal distortion speed, default: 0 */
|
|
1013
1551
|
get temporalDistortion() {
|
|
1014
1552
|
return this._temporalDistortion.value;
|
|
1015
1553
|
}
|
|
1016
1554
|
set temporalDistortion(v) {
|
|
1017
1555
|
this._temporalDistortion.value = v;
|
|
1018
1556
|
}
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
return this._buffer.value;
|
|
1557
|
+
get debugMode() {
|
|
1558
|
+
return this._debugMode.value;
|
|
1022
1559
|
}
|
|
1023
|
-
set
|
|
1024
|
-
this.
|
|
1560
|
+
set debugMode(v) {
|
|
1561
|
+
this._debugMode.value = v;
|
|
1025
1562
|
}
|
|
1026
|
-
|
|
1563
|
+
// Expose _transmission for legacy compatibility
|
|
1564
|
+
// This stores the user's intended transmission value, separate from the base class's transmission
|
|
1565
|
+
// which is kept at 0.001 to enable the transmission code path without triggering Three's internal rendering
|
|
1027
1566
|
get _transmission() {
|
|
1567
|
+
if (!this._transmissionValue) {
|
|
1568
|
+
this._transmissionValue = uniform(1);
|
|
1569
|
+
}
|
|
1028
1570
|
return this._transmissionValue.value;
|
|
1029
1571
|
}
|
|
1030
1572
|
set _transmission(v) {
|
|
1573
|
+
if (!this._transmissionValue) {
|
|
1574
|
+
this._transmissionValue = uniform(1);
|
|
1575
|
+
}
|
|
1031
1576
|
this._transmissionValue.value = v;
|
|
1032
1577
|
}
|
|
1033
|
-
/** Attenuation distance for Beer's law absorption */
|
|
1034
|
-
get attenuationDistance() {
|
|
1035
|
-
return this._attenuationDistance.value;
|
|
1036
|
-
}
|
|
1037
|
-
set attenuationDistance(v) {
|
|
1038
|
-
this._attenuationDistance.value = v;
|
|
1039
|
-
}
|
|
1040
|
-
/** Attenuation color for Beer's law absorption */
|
|
1041
|
-
get attenuationColor() {
|
|
1042
|
-
return this._attenuationColor.value;
|
|
1043
|
-
}
|
|
1044
|
-
set attenuationColor(v) {
|
|
1045
|
-
this._attenuationColor.value = v;
|
|
1046
|
-
}
|
|
1047
1578
|
}
|
|
1048
1579
|
const MeshTransmissionMaterial = /* @__PURE__ */ React.forwardRef(
|
|
1049
1580
|
({
|
|
@@ -1051,8 +1582,8 @@ const MeshTransmissionMaterial = /* @__PURE__ */ React.forwardRef(
|
|
|
1051
1582
|
transmissionSampler = false,
|
|
1052
1583
|
backside = false,
|
|
1053
1584
|
side = THREE.FrontSide,
|
|
1054
|
-
transmission = 1,
|
|
1055
|
-
thickness = 0,
|
|
1585
|
+
transmission: transmission2 = 1,
|
|
1586
|
+
thickness: thickness2 = 0,
|
|
1056
1587
|
backsideThickness = 0,
|
|
1057
1588
|
backsideEnvMapIntensity = 1,
|
|
1058
1589
|
samples = 10,
|
|
@@ -1061,48 +1592,111 @@ const MeshTransmissionMaterial = /* @__PURE__ */ React.forwardRef(
|
|
|
1061
1592
|
background,
|
|
1062
1593
|
anisotropy,
|
|
1063
1594
|
anisotropicBlur,
|
|
1595
|
+
debugMode = 0,
|
|
1064
1596
|
...props
|
|
1065
1597
|
}, fref) => {
|
|
1066
1598
|
extend({ MeshTransmissionMaterial: MeshTransmissionMaterialImpl });
|
|
1067
1599
|
const ref = React.useRef(null);
|
|
1068
|
-
const
|
|
1069
|
-
const
|
|
1070
|
-
const
|
|
1600
|
+
const backsideMaterialRef = React.useRef(null);
|
|
1601
|
+
const { size, viewport } = useThree();
|
|
1602
|
+
const screenWidth = size.width * viewport.dpr;
|
|
1603
|
+
const screenHeight = size.height * viewport.dpr;
|
|
1604
|
+
const fboWidth = resolution || screenWidth;
|
|
1605
|
+
const fboHeight = resolution ? Math.round(resolution / screenWidth * screenHeight) : screenHeight;
|
|
1606
|
+
const fboBack = useFBO(
|
|
1607
|
+
backsideResolution || fboWidth,
|
|
1608
|
+
backsideResolution ? Math.round(backsideResolution / screenWidth * screenHeight) : fboHeight
|
|
1609
|
+
);
|
|
1610
|
+
const fboMain = useFBO(fboWidth, fboHeight);
|
|
1611
|
+
React.useEffect(() => {
|
|
1612
|
+
if (backside && ref.current && !backsideMaterialRef.current) {
|
|
1613
|
+
backsideMaterialRef.current = new MeshTransmissionMaterialImpl(samples, transmissionSampler);
|
|
1614
|
+
backsideMaterialRef.current.buffer = fboBack.texture;
|
|
1615
|
+
}
|
|
1616
|
+
return () => {
|
|
1617
|
+
if (backsideMaterialRef.current) {
|
|
1618
|
+
backsideMaterialRef.current.dispose();
|
|
1619
|
+
backsideMaterialRef.current = null;
|
|
1620
|
+
}
|
|
1621
|
+
};
|
|
1622
|
+
}, [backside, samples, transmissionSampler]);
|
|
1623
|
+
React.useEffect(() => {
|
|
1624
|
+
if (backsideMaterialRef.current) {
|
|
1625
|
+
backsideMaterialRef.current.buffer = fboBack.texture;
|
|
1626
|
+
}
|
|
1627
|
+
}, [fboBack.texture]);
|
|
1071
1628
|
let oldBg;
|
|
1072
1629
|
let oldEnvMapIntensity;
|
|
1073
1630
|
let oldTone;
|
|
1074
1631
|
let parent;
|
|
1075
1632
|
useFrame((state) => {
|
|
1076
1633
|
ref.current.time = state.elapsed;
|
|
1634
|
+
const renderer = state.renderer;
|
|
1635
|
+
if (backsideMaterialRef.current) {
|
|
1636
|
+
backsideMaterialRef.current.time = state.elapsed;
|
|
1637
|
+
}
|
|
1077
1638
|
if (ref.current.buffer === fboMain.texture && !transmissionSampler) {
|
|
1078
1639
|
parent = ref.current.__r3f?.parent?.object;
|
|
1079
|
-
if (parent)
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1640
|
+
if (!parent) return;
|
|
1641
|
+
oldTone = renderer.toneMapping;
|
|
1642
|
+
oldBg = state.scene.background;
|
|
1643
|
+
oldEnvMapIntensity = ref.current.envMapIntensity;
|
|
1644
|
+
renderer.toneMapping = THREE.NoToneMapping;
|
|
1645
|
+
if (background)
|
|
1646
|
+
state.scene.background = background;
|
|
1647
|
+
parent.material = DiscardMaterial;
|
|
1648
|
+
const camera = state.camera;
|
|
1649
|
+
const isOrtho = camera.isOrthographicCamera;
|
|
1650
|
+
let oldLeft, oldRight, oldTop, oldBottom;
|
|
1651
|
+
if (isOrtho) {
|
|
1652
|
+
oldLeft = camera.left;
|
|
1653
|
+
oldRight = camera.right;
|
|
1654
|
+
oldTop = camera.top;
|
|
1655
|
+
oldBottom = camera.bottom;
|
|
1656
|
+
const fboAspect = fboWidth / fboHeight;
|
|
1657
|
+
const screenAspect = screenWidth / screenHeight;
|
|
1658
|
+
if (Math.abs(fboAspect - screenAspect) > 1e-3) {
|
|
1659
|
+
const viewHeight = oldTop - oldBottom;
|
|
1660
|
+
const newHalfWidth = viewHeight * fboAspect / 2;
|
|
1661
|
+
const centerX = (oldLeft + oldRight) / 2;
|
|
1662
|
+
camera.left = centerX - newHalfWidth;
|
|
1663
|
+
camera.right = centerX + newHalfWidth;
|
|
1664
|
+
camera.updateProjectionMatrix();
|
|
1094
1665
|
}
|
|
1095
|
-
|
|
1096
|
-
|
|
1666
|
+
}
|
|
1667
|
+
if (backside && backsideMaterialRef.current) {
|
|
1668
|
+
renderer.setRenderTarget(fboBack);
|
|
1669
|
+
renderer.clear();
|
|
1670
|
+
state.renderer.render(state.scene, state.camera);
|
|
1671
|
+
parent.material = backsideMaterialRef.current;
|
|
1672
|
+
backsideMaterialRef.current.thickness = backsideThickness;
|
|
1673
|
+
backsideMaterialRef.current.side = THREE.BackSide;
|
|
1674
|
+
backsideMaterialRef.current.envMapIntensity = backsideEnvMapIntensity;
|
|
1675
|
+
renderer.setRenderTarget(fboMain);
|
|
1676
|
+
renderer.clear();
|
|
1677
|
+
state.renderer.render(state.scene, state.camera);
|
|
1097
1678
|
parent.material = ref.current;
|
|
1098
|
-
ref.current.thickness =
|
|
1679
|
+
ref.current.thickness = thickness2;
|
|
1099
1680
|
ref.current.side = side;
|
|
1100
|
-
ref.current.buffer = fboMain.texture;
|
|
1101
1681
|
ref.current.envMapIntensity = oldEnvMapIntensity;
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1682
|
+
} else {
|
|
1683
|
+
renderer.setRenderTarget(fboMain);
|
|
1684
|
+
renderer.clear();
|
|
1685
|
+
state.renderer.render(state.scene, state.camera);
|
|
1686
|
+
parent.material = ref.current;
|
|
1687
|
+
ref.current.thickness = thickness2;
|
|
1688
|
+
ref.current.side = side;
|
|
1689
|
+
}
|
|
1690
|
+
if (isOrtho && Math.abs(fboWidth / fboHeight - screenWidth / screenHeight) > 1e-3) {
|
|
1691
|
+
camera.left = oldLeft;
|
|
1692
|
+
camera.right = oldRight;
|
|
1693
|
+
camera.top = oldTop;
|
|
1694
|
+
camera.bottom = oldBottom;
|
|
1695
|
+
camera.updateProjectionMatrix();
|
|
1105
1696
|
}
|
|
1697
|
+
state.scene.background = oldBg;
|
|
1698
|
+
renderer.setRenderTarget(null);
|
|
1699
|
+
renderer.toneMapping = oldTone;
|
|
1106
1700
|
}
|
|
1107
1701
|
});
|
|
1108
1702
|
React.useImperativeHandle(fref, () => ref.current, []);
|
|
@@ -1113,11 +1707,11 @@ const MeshTransmissionMaterial = /* @__PURE__ */ React.forwardRef(
|
|
|
1113
1707
|
ref,
|
|
1114
1708
|
...props,
|
|
1115
1709
|
buffer: buffer || fboMain.texture,
|
|
1116
|
-
_transmission:
|
|
1117
|
-
anisotropicBlur: anisotropicBlur ?? anisotropy
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1710
|
+
_transmission: transmission2,
|
|
1711
|
+
anisotropicBlur: anisotropicBlur ?? anisotropy,
|
|
1712
|
+
thickness: thickness2,
|
|
1713
|
+
side,
|
|
1714
|
+
debugMode
|
|
1121
1715
|
}
|
|
1122
1716
|
);
|
|
1123
1717
|
}
|
|
@@ -1368,25 +1962,16 @@ const MeshReflectorMaterial = /* @__PURE__ */ React.forwardRef(
|
|
|
1368
1962
|
}
|
|
1369
1963
|
);
|
|
1370
1964
|
|
|
1371
|
-
const fresnelEffect = /* @__PURE__ */ Fn((
|
|
1372
|
-
const [viewDir, normal, power] = inputs;
|
|
1965
|
+
const fresnelEffect = /* @__PURE__ */ Fn(([viewDir, normal, power]) => {
|
|
1373
1966
|
const NdotV = float(1).add(dot(viewDir, normal));
|
|
1374
1967
|
return pow(NdotV, power);
|
|
1375
1968
|
});
|
|
1376
|
-
const
|
|
1377
|
-
const [direction] = inputs;
|
|
1378
|
-
const dir = normalize(direction);
|
|
1379
|
-
const u = float(0.5).add(dir.z.atan2(dir.x).div(float(2).mul(Math.PI)));
|
|
1380
|
-
const v = float(0.5).sub(dir.y.asin().div(Math.PI));
|
|
1381
|
-
return vec2$2(u, v);
|
|
1382
|
-
});
|
|
1383
|
-
const approximateRefraction = /* @__PURE__ */ Fn((inputs) => {
|
|
1384
|
-
const [rayDir, normal, iorValue, bounceCount, thickness] = inputs;
|
|
1969
|
+
const approximateRefraction = /* @__PURE__ */ Fn(([rayDir, normal, iorValue, bounceCount]) => {
|
|
1385
1970
|
const entryDir = refract(rayDir, normal, float(1).div(iorValue)).toVar();
|
|
1386
1971
|
const entryValid = length(entryDir).greaterThan(0);
|
|
1387
1972
|
const exitNormal = normal.negate().toVar();
|
|
1388
1973
|
const currentDir = entryDir.toVar();
|
|
1389
|
-
Loop(int(bounceCount), ({ i }) => {
|
|
1974
|
+
Loop({ start: 0, end: int(bounceCount), type: "int" }, ({ i }) => {
|
|
1390
1975
|
const fi = float(i).add(1);
|
|
1391
1976
|
const exitDir = refract(currentDir, exitNormal, iorValue);
|
|
1392
1977
|
const canExit = length(exitDir).greaterThan(0);
|
|
@@ -1405,8 +1990,6 @@ class MeshRefractionMaterialImpl extends MeshPhysicalNodeMaterial {
|
|
|
1405
1990
|
_aberrationStrength;
|
|
1406
1991
|
_color;
|
|
1407
1992
|
_opacityValue;
|
|
1408
|
-
_resolution;
|
|
1409
|
-
_thickness;
|
|
1410
1993
|
_fastChroma;
|
|
1411
1994
|
/** Type flag for identification */
|
|
1412
1995
|
isMeshRefractionMaterial = true;
|
|
@@ -1420,8 +2003,6 @@ class MeshRefractionMaterialImpl extends MeshPhysicalNodeMaterial {
|
|
|
1420
2003
|
this._aberrationStrength = uniform(0.01);
|
|
1421
2004
|
this._color = uniform(new THREE.Color("white"));
|
|
1422
2005
|
this._opacityValue = uniform(1);
|
|
1423
|
-
this._resolution = uniform(new THREE.Vector2(1, 1));
|
|
1424
|
-
this._thickness = uniform(1);
|
|
1425
2006
|
this.transparent = true;
|
|
1426
2007
|
this.side = THREE.FrontSide;
|
|
1427
2008
|
this._buildRefractionShader();
|
|
@@ -1434,20 +2015,13 @@ class MeshRefractionMaterialImpl extends MeshPhysicalNodeMaterial {
|
|
|
1434
2015
|
const aberrationUniform = this._aberrationStrength;
|
|
1435
2016
|
const colorUniform = this._color;
|
|
1436
2017
|
const opacityUniform = this._opacityValue;
|
|
1437
|
-
const thicknessUniform = this._thickness;
|
|
1438
2018
|
const fastChroma = this._fastChroma;
|
|
1439
2019
|
this.outputNode = Fn(() => {
|
|
1440
2020
|
const worldPos = positionWorld;
|
|
1441
2021
|
const worldNormal = normalize(normalWorld);
|
|
1442
2022
|
const viewDir = normalize(worldPos.sub(cameraPosition));
|
|
1443
2023
|
const baseColor = colorUniform.toVar();
|
|
1444
|
-
const refractedDirG = approximateRefraction(
|
|
1445
|
-
viewDir,
|
|
1446
|
-
worldNormal,
|
|
1447
|
-
max(iorUniform, 1),
|
|
1448
|
-
bouncesUniform,
|
|
1449
|
-
thicknessUniform
|
|
1450
|
-
);
|
|
2024
|
+
const refractedDirG = approximateRefraction(viewDir, worldNormal, max(iorUniform, 1), bouncesUniform);
|
|
1451
2025
|
const aberration = aberrationUniform;
|
|
1452
2026
|
const refractedDirR = vec3(0, 0, 0).toVar();
|
|
1453
2027
|
const refractedDirB = vec3(0, 0, 0).toVar();
|
|
@@ -1461,8 +2035,7 @@ class MeshRefractionMaterialImpl extends MeshPhysicalNodeMaterial {
|
|
|
1461
2035
|
viewDir,
|
|
1462
2036
|
worldNormal,
|
|
1463
2037
|
max(iorUniform.mul(float(1).sub(aberration)), 1),
|
|
1464
|
-
bouncesUniform
|
|
1465
|
-
thicknessUniform
|
|
2038
|
+
bouncesUniform
|
|
1466
2039
|
)
|
|
1467
2040
|
);
|
|
1468
2041
|
refractedDirB.assign(
|
|
@@ -1470,14 +2043,13 @@ class MeshRefractionMaterialImpl extends MeshPhysicalNodeMaterial {
|
|
|
1470
2043
|
viewDir,
|
|
1471
2044
|
worldNormal,
|
|
1472
2045
|
max(iorUniform.mul(float(1).add(aberration)), 1),
|
|
1473
|
-
bouncesUniform
|
|
1474
|
-
thicknessUniform
|
|
2046
|
+
bouncesUniform
|
|
1475
2047
|
)
|
|
1476
2048
|
);
|
|
1477
2049
|
}
|
|
1478
|
-
const uvR =
|
|
1479
|
-
const uvG =
|
|
1480
|
-
const uvB =
|
|
2050
|
+
const uvR = equirectUV(refractedDirR);
|
|
2051
|
+
const uvG = equirectUV(refractedDirG);
|
|
2052
|
+
const uvB = equirectUV(refractedDirB);
|
|
1481
2053
|
const envColorR = texture(envMapTex, uvR).r;
|
|
1482
2054
|
const envColorG = texture(envMapTex, uvG).g;
|
|
1483
2055
|
const envColorB = texture(envMapTex, uvB).b;
|
|
@@ -1541,20 +2113,6 @@ class MeshRefractionMaterialImpl extends MeshPhysicalNodeMaterial {
|
|
|
1541
2113
|
set opacity(v) {
|
|
1542
2114
|
this._opacityValue.value = v;
|
|
1543
2115
|
}
|
|
1544
|
-
/** Resolution for screen-space calculations */
|
|
1545
|
-
get resolution() {
|
|
1546
|
-
return this._resolution.value;
|
|
1547
|
-
}
|
|
1548
|
-
set resolution(v) {
|
|
1549
|
-
this._resolution.value = v;
|
|
1550
|
-
}
|
|
1551
|
-
/** Approximate thickness for refraction calculations */
|
|
1552
|
-
get thickness() {
|
|
1553
|
-
return this._thickness.value;
|
|
1554
|
-
}
|
|
1555
|
-
set thickness(v) {
|
|
1556
|
-
this._thickness.value = v;
|
|
1557
|
-
}
|
|
1558
2116
|
}
|
|
1559
2117
|
const MeshRefractionMaterial = /* @__PURE__ */ React.forwardRef(
|
|
1560
2118
|
({
|
|
@@ -1570,12 +2128,6 @@ const MeshRefractionMaterial = /* @__PURE__ */ React.forwardRef(
|
|
|
1570
2128
|
}, fref) => {
|
|
1571
2129
|
extend({ MeshRefractionMaterial: MeshRefractionMaterialImpl });
|
|
1572
2130
|
const ref = React.useRef(null);
|
|
1573
|
-
const size = useThree((state) => state.size);
|
|
1574
|
-
React.useEffect(() => {
|
|
1575
|
-
if (ref.current) {
|
|
1576
|
-
ref.current.resolution = new THREE.Vector2(size.width, size.height);
|
|
1577
|
-
}
|
|
1578
|
-
}, [size]);
|
|
1579
2131
|
React.useEffect(() => {
|
|
1580
2132
|
if (ref.current && envMap) {
|
|
1581
2133
|
ref.current.envMap = envMap;
|
|
@@ -1827,10 +2379,10 @@ class PortalMaterialImpl extends MeshBasicNodeMaterial {
|
|
|
1827
2379
|
this._blur.value = v;
|
|
1828
2380
|
}
|
|
1829
2381
|
get map() {
|
|
1830
|
-
return this._map
|
|
2382
|
+
return this._map?.value;
|
|
1831
2383
|
}
|
|
1832
2384
|
set map(v) {
|
|
1833
|
-
this._map.value = v ?? new THREE.Texture();
|
|
2385
|
+
if (this._map) this._map.value = v ?? new THREE.Texture();
|
|
1834
2386
|
}
|
|
1835
2387
|
get sdf() {
|
|
1836
2388
|
return this._sdf.value;
|
|
@@ -2610,11 +3162,11 @@ const RenderCubeTexture = /* @__PURE__ */ React.forwardRef(
|
|
|
2610
3162
|
depthBuffer,
|
|
2611
3163
|
generateMipmaps
|
|
2612
3164
|
};
|
|
2613
|
-
const fboA2 = new
|
|
3165
|
+
const fboA2 = new CubeRenderTarget(fboSize, settings);
|
|
2614
3166
|
fboA2.texture.isRenderTargetTexture = !flip;
|
|
2615
3167
|
fboA2.texture.flipY = true;
|
|
2616
3168
|
fboA2.texture.type = THREE.HalfFloatType;
|
|
2617
|
-
const fboB2 = new
|
|
3169
|
+
const fboB2 = new CubeRenderTarget(fboSize, settings);
|
|
2618
3170
|
fboB2.texture.isRenderTargetTexture = !flip;
|
|
2619
3171
|
fboB2.texture.flipY = true;
|
|
2620
3172
|
fboB2.texture.type = THREE.HalfFloatType;
|
|
@@ -3064,7 +3616,7 @@ function useCubeCamera({ resolution = 256, near = 0.1, far = 1e3, envMap, fog }
|
|
|
3064
3616
|
const gl = useThree(({ gl: gl2 }) => gl2);
|
|
3065
3617
|
const scene = useThree(({ scene: scene2 }) => scene2);
|
|
3066
3618
|
const fbo = useMemo(() => {
|
|
3067
|
-
const fbo2 = new
|
|
3619
|
+
const fbo2 = new CubeRenderTarget(resolution);
|
|
3068
3620
|
fbo2.texture.type = HalfFloatType;
|
|
3069
3621
|
return fbo2;
|
|
3070
3622
|
}, [resolution]);
|
|
@@ -3363,11 +3915,11 @@ const DeviceOrientationControls = /* @__PURE__ */ React.forwardRef(
|
|
|
3363
3915
|
);
|
|
3364
3916
|
|
|
3365
3917
|
const initialModelPosition = /* @__PURE__ */ new THREE.Vector3();
|
|
3366
|
-
const mousePosition2D = /* @__PURE__ */ new THREE.Vector2();
|
|
3367
3918
|
const mousePosition3D = /* @__PURE__ */ new THREE.Vector3();
|
|
3368
3919
|
const dragOffset = /* @__PURE__ */ new THREE.Vector3();
|
|
3369
3920
|
const dragPlaneNormal = /* @__PURE__ */ new THREE.Vector3();
|
|
3370
3921
|
const dragPlane = /* @__PURE__ */ new THREE.Plane();
|
|
3922
|
+
const startPointerPos = /* @__PURE__ */ new THREE.Vector3();
|
|
3371
3923
|
const DragControls = React.forwardRef(
|
|
3372
3924
|
({
|
|
3373
3925
|
autoTransform = true,
|
|
@@ -3383,90 +3935,132 @@ const DragControls = React.forwardRef(
|
|
|
3383
3935
|
...props
|
|
3384
3936
|
}, fRef) => {
|
|
3385
3937
|
const defaultControls = useThree((state) => state.controls);
|
|
3386
|
-
const { camera,
|
|
3938
|
+
const { camera, invalidate } = useThree();
|
|
3387
3939
|
const ref = React.useRef(null);
|
|
3388
|
-
const
|
|
3389
|
-
|
|
3390
|
-
|
|
3391
|
-
|
|
3392
|
-
|
|
3393
|
-
|
|
3394
|
-
|
|
3395
|
-
|
|
3396
|
-
|
|
3397
|
-
|
|
3398
|
-
|
|
3399
|
-
|
|
3400
|
-
|
|
3401
|
-
|
|
3402
|
-
|
|
3403
|
-
|
|
3404
|
-
|
|
3405
|
-
|
|
3406
|
-
|
|
3407
|
-
|
|
3408
|
-
|
|
3409
|
-
|
|
3410
|
-
|
|
3411
|
-
|
|
3412
|
-
|
|
3413
|
-
|
|
3414
|
-
|
|
3415
|
-
|
|
3416
|
-
|
|
3417
|
-
|
|
3418
|
-
|
|
3419
|
-
|
|
3420
|
-
|
|
3421
|
-
}
|
|
3422
|
-
dragPlane.setFromNormalAndCoplanarPoint(dragPlaneNormal, mousePosition3D);
|
|
3423
|
-
raycaster.ray.intersectPlane(dragPlane, mousePosition3D);
|
|
3424
|
-
const previousLocalMatrix = ref.current.matrix.clone();
|
|
3425
|
-
const previousWorldMatrix = ref.current.matrixWorld.clone();
|
|
3426
|
-
const intendedNewPosition = new THREE.Vector3(
|
|
3427
|
-
mousePosition3D.x - dragOffset.x,
|
|
3428
|
-
mousePosition3D.y - dragOffset.y,
|
|
3429
|
-
mousePosition3D.z - dragOffset.z
|
|
3430
|
-
);
|
|
3431
|
-
if (dragLimits) {
|
|
3432
|
-
intendedNewPosition.x = dragLimits[0] ? Math.max(Math.min(intendedNewPosition.x, dragLimits[0][1]), dragLimits[0][0]) : intendedNewPosition.x;
|
|
3433
|
-
intendedNewPosition.y = dragLimits[1] ? Math.max(Math.min(intendedNewPosition.y, dragLimits[1][1]), dragLimits[1][0]) : intendedNewPosition.y;
|
|
3434
|
-
intendedNewPosition.z = dragLimits[2] ? Math.max(Math.min(intendedNewPosition.z, dragLimits[2][1]), dragLimits[2][0]) : intendedNewPosition.z;
|
|
3435
|
-
}
|
|
3436
|
-
if (autoTransform) {
|
|
3437
|
-
ref.current.matrix.setPosition(intendedNewPosition);
|
|
3438
|
-
const deltaLocalMatrix = ref.current.matrix.clone().multiply(previousLocalMatrix.invert());
|
|
3439
|
-
const deltaWorldMatrix = ref.current.matrix.clone().multiply(previousWorldMatrix.invert());
|
|
3440
|
-
onDrag && onDrag(ref.current.matrix, deltaLocalMatrix, ref.current.matrixWorld, deltaWorldMatrix);
|
|
3441
|
-
} else {
|
|
3442
|
-
const tempMatrix = new THREE.Matrix4().copy(ref.current.matrix);
|
|
3443
|
-
tempMatrix.setPosition(intendedNewPosition);
|
|
3444
|
-
const deltaLocalMatrix = tempMatrix.clone().multiply(previousLocalMatrix.invert());
|
|
3445
|
-
const deltaWorldMatrix = tempMatrix.clone().multiply(previousWorldMatrix.invert());
|
|
3446
|
-
onDrag && onDrag(tempMatrix, deltaLocalMatrix, ref.current.matrixWorld, deltaWorldMatrix);
|
|
3940
|
+
const dragState = React.useRef({
|
|
3941
|
+
active: false,
|
|
3942
|
+
intentional: false,
|
|
3943
|
+
// Has moved past threshold
|
|
3944
|
+
pointerId: -1
|
|
3945
|
+
});
|
|
3946
|
+
const threshold = dragConfig?.threshold ?? 0;
|
|
3947
|
+
const filterTaps = dragConfig?.filterTaps ?? true;
|
|
3948
|
+
const handlePointerDown = React.useCallback(
|
|
3949
|
+
(event) => {
|
|
3950
|
+
event.stopPropagation();
|
|
3951
|
+
event.target.setPointerCapture(event.pointerId);
|
|
3952
|
+
dragState.current.active = true;
|
|
3953
|
+
dragState.current.intentional = threshold === 0;
|
|
3954
|
+
dragState.current.pointerId = event.pointerId;
|
|
3955
|
+
if (defaultControls) defaultControls.enabled = false;
|
|
3956
|
+
ref.current.matrix.decompose(initialModelPosition, new THREE.Quaternion(), new THREE.Vector3());
|
|
3957
|
+
mousePosition3D.copy(event.point);
|
|
3958
|
+
startPointerPos.copy(event.point);
|
|
3959
|
+
dragOffset.copy(mousePosition3D).sub(initialModelPosition);
|
|
3960
|
+
if (!axisLock) {
|
|
3961
|
+
camera.getWorldDirection(dragPlaneNormal).negate();
|
|
3962
|
+
} else {
|
|
3963
|
+
switch (axisLock) {
|
|
3964
|
+
case "x":
|
|
3965
|
+
dragPlaneNormal.set(1, 0, 0);
|
|
3966
|
+
break;
|
|
3967
|
+
case "y":
|
|
3968
|
+
dragPlaneNormal.set(0, 1, 0);
|
|
3969
|
+
break;
|
|
3970
|
+
case "z":
|
|
3971
|
+
dragPlaneNormal.set(0, 0, 1);
|
|
3972
|
+
break;
|
|
3447
3973
|
}
|
|
3448
|
-
invalidate();
|
|
3449
|
-
},
|
|
3450
|
-
onDragEnd: () => {
|
|
3451
|
-
if (defaultControls) defaultControls.enabled = true;
|
|
3452
|
-
onDragEnd && onDragEnd();
|
|
3453
|
-
invalidate();
|
|
3454
3974
|
}
|
|
3975
|
+
dragPlane.setFromNormalAndCoplanarPoint(dragPlaneNormal, mousePosition3D);
|
|
3976
|
+
if (dragState.current.intentional) {
|
|
3977
|
+
onDragStart && onDragStart(initialModelPosition);
|
|
3978
|
+
}
|
|
3979
|
+
invalidate();
|
|
3455
3980
|
},
|
|
3456
|
-
|
|
3457
|
-
|
|
3458
|
-
|
|
3459
|
-
|
|
3460
|
-
|
|
3981
|
+
[defaultControls, camera, axisLock, threshold, onDragStart, invalidate]
|
|
3982
|
+
);
|
|
3983
|
+
const handlePointerMove = React.useCallback(
|
|
3984
|
+
(event) => {
|
|
3985
|
+
if (!dragState.current.active || event.pointerId !== dragState.current.pointerId) return;
|
|
3986
|
+
const intersection = event.ray.intersectPlane(dragPlane, mousePosition3D);
|
|
3987
|
+
if (!intersection) return;
|
|
3988
|
+
if (!dragState.current.intentional) {
|
|
3989
|
+
const distance = mousePosition3D.distanceTo(startPointerPos);
|
|
3990
|
+
if (distance < threshold) return;
|
|
3991
|
+
dragState.current.intentional = true;
|
|
3992
|
+
onDragStart && onDragStart(initialModelPosition);
|
|
3461
3993
|
}
|
|
3462
|
-
|
|
3994
|
+
const previousLocalMatrix = ref.current.matrix.clone();
|
|
3995
|
+
const previousWorldMatrix = ref.current.matrixWorld.clone();
|
|
3996
|
+
const intendedNewPosition = new THREE.Vector3(
|
|
3997
|
+
mousePosition3D.x - dragOffset.x,
|
|
3998
|
+
mousePosition3D.y - dragOffset.y,
|
|
3999
|
+
mousePosition3D.z - dragOffset.z
|
|
4000
|
+
);
|
|
4001
|
+
if (dragLimits) {
|
|
4002
|
+
intendedNewPosition.x = dragLimits[0] ? Math.max(Math.min(intendedNewPosition.x, dragLimits[0][1]), dragLimits[0][0]) : intendedNewPosition.x;
|
|
4003
|
+
intendedNewPosition.y = dragLimits[1] ? Math.max(Math.min(intendedNewPosition.y, dragLimits[1][1]), dragLimits[1][0]) : intendedNewPosition.y;
|
|
4004
|
+
intendedNewPosition.z = dragLimits[2] ? Math.max(Math.min(intendedNewPosition.z, dragLimits[2][1]), dragLimits[2][0]) : intendedNewPosition.z;
|
|
4005
|
+
}
|
|
4006
|
+
if (autoTransform) {
|
|
4007
|
+
ref.current.matrix.setPosition(intendedNewPosition);
|
|
4008
|
+
const deltaLocalMatrix = ref.current.matrix.clone().multiply(previousLocalMatrix.invert());
|
|
4009
|
+
const deltaWorldMatrix = ref.current.matrix.clone().multiply(previousWorldMatrix.invert());
|
|
4010
|
+
onDrag && onDrag(ref.current.matrix, deltaLocalMatrix, ref.current.matrixWorld, deltaWorldMatrix);
|
|
4011
|
+
} else {
|
|
4012
|
+
const tempMatrix = new THREE.Matrix4().copy(ref.current.matrix);
|
|
4013
|
+
tempMatrix.setPosition(intendedNewPosition);
|
|
4014
|
+
const deltaLocalMatrix = tempMatrix.clone().multiply(previousLocalMatrix.invert());
|
|
4015
|
+
const deltaWorldMatrix = tempMatrix.clone().multiply(previousWorldMatrix.invert());
|
|
4016
|
+
onDrag && onDrag(tempMatrix, deltaLocalMatrix, ref.current.matrixWorld, deltaWorldMatrix);
|
|
4017
|
+
}
|
|
4018
|
+
invalidate();
|
|
4019
|
+
},
|
|
4020
|
+
[autoTransform, dragLimits, threshold, onDragStart, onDrag, invalidate]
|
|
4021
|
+
);
|
|
4022
|
+
const handlePointerUp = React.useCallback(
|
|
4023
|
+
(event) => {
|
|
4024
|
+
if (!dragState.current.active || event.pointerId !== dragState.current.pointerId) return;
|
|
4025
|
+
event.target.releasePointerCapture(event.pointerId);
|
|
4026
|
+
const wasIntentional = dragState.current.intentional;
|
|
4027
|
+
dragState.current.active = false;
|
|
4028
|
+
dragState.current.intentional = false;
|
|
4029
|
+
dragState.current.pointerId = -1;
|
|
4030
|
+
if (defaultControls) defaultControls.enabled = true;
|
|
4031
|
+
if (wasIntentional || !filterTaps) {
|
|
4032
|
+
onDragEnd && onDragEnd();
|
|
4033
|
+
}
|
|
4034
|
+
invalidate();
|
|
4035
|
+
},
|
|
4036
|
+
[defaultControls, filterTaps, onDragEnd, invalidate]
|
|
3463
4037
|
);
|
|
4038
|
+
const handlePointerEnter = React.useCallback(() => {
|
|
4039
|
+
onHover && onHover(true);
|
|
4040
|
+
}, [onHover]);
|
|
4041
|
+
const handlePointerLeave = React.useCallback(() => {
|
|
4042
|
+
onHover && onHover(false);
|
|
4043
|
+
}, [onHover]);
|
|
3464
4044
|
React.useImperativeHandle(fRef, () => ref.current, []);
|
|
3465
4045
|
React.useLayoutEffect(() => {
|
|
3466
4046
|
if (!matrix) return;
|
|
3467
4047
|
ref.current.matrix = matrix;
|
|
3468
4048
|
}, [matrix]);
|
|
3469
|
-
return /* @__PURE__ */ React.createElement(
|
|
4049
|
+
return /* @__PURE__ */ React.createElement(
|
|
4050
|
+
"group",
|
|
4051
|
+
{
|
|
4052
|
+
ref,
|
|
4053
|
+
onPointerDown: handlePointerDown,
|
|
4054
|
+
onPointerMove: handlePointerMove,
|
|
4055
|
+
onPointerUp: handlePointerUp,
|
|
4056
|
+
onPointerEnter: handlePointerEnter,
|
|
4057
|
+
onPointerLeave: handlePointerLeave,
|
|
4058
|
+
matrix,
|
|
4059
|
+
matrixAutoUpdate: false,
|
|
4060
|
+
...props
|
|
4061
|
+
},
|
|
4062
|
+
children
|
|
4063
|
+
);
|
|
3470
4064
|
}
|
|
3471
4065
|
);
|
|
3472
4066
|
|
|
@@ -3584,7 +4178,7 @@ function KeyboardControls({ map, children, onChange, domElement }) {
|
|
|
3584
4178
|
source.removeEventListener("keyup", upHandler);
|
|
3585
4179
|
window.removeEventListener("blur", blurHandler);
|
|
3586
4180
|
};
|
|
3587
|
-
}, [domElement, key]);
|
|
4181
|
+
}, [domElement, key, onChange]);
|
|
3588
4182
|
return /* @__PURE__ */ React.createElement(context$8.Provider, { value: api, children });
|
|
3589
4183
|
}
|
|
3590
4184
|
function useKeyboardControls(sel) {
|
|
@@ -3606,20 +4200,28 @@ const MapControls = /* @__PURE__ */ React.forwardRef((props = { enableDamping: t
|
|
|
3606
4200
|
const controls = React.useMemo(() => new MapControls$1(explCamera), [explCamera]);
|
|
3607
4201
|
React.useEffect(() => {
|
|
3608
4202
|
controls.connect(explDomElement);
|
|
4203
|
+
return () => void controls.dispose();
|
|
4204
|
+
}, [explDomElement, controls]);
|
|
4205
|
+
React.useEffect(() => {
|
|
3609
4206
|
const callback = (e) => {
|
|
3610
4207
|
invalidate();
|
|
3611
4208
|
if (onChange) onChange(e);
|
|
3612
4209
|
};
|
|
4210
|
+
const onStartCb = (e) => {
|
|
4211
|
+
if (onStart) onStart(e);
|
|
4212
|
+
};
|
|
4213
|
+
const onEndCb = (e) => {
|
|
4214
|
+
if (onEnd) onEnd(e);
|
|
4215
|
+
};
|
|
3613
4216
|
controls.addEventListener("change", callback);
|
|
3614
|
-
|
|
3615
|
-
|
|
4217
|
+
controls.addEventListener("start", onStartCb);
|
|
4218
|
+
controls.addEventListener("end", onEndCb);
|
|
3616
4219
|
return () => {
|
|
3617
|
-
controls.
|
|
4220
|
+
controls.removeEventListener("start", onStartCb);
|
|
4221
|
+
controls.removeEventListener("end", onEndCb);
|
|
3618
4222
|
controls.removeEventListener("change", callback);
|
|
3619
|
-
if (onStart) controls.removeEventListener("start", onStart);
|
|
3620
|
-
if (onEnd) controls.removeEventListener("end", onEnd);
|
|
3621
4223
|
};
|
|
3622
|
-
}, [onChange, onStart, onEnd, controls, invalidate
|
|
4224
|
+
}, [onChange, onStart, onEnd, controls, invalidate]);
|
|
3623
4225
|
React.useEffect(() => {
|
|
3624
4226
|
if (makeDefault) {
|
|
3625
4227
|
const old = get().controls;
|
|
@@ -3627,7 +4229,9 @@ const MapControls = /* @__PURE__ */ React.forwardRef((props = { enableDamping: t
|
|
|
3627
4229
|
return () => set({ controls: old });
|
|
3628
4230
|
}
|
|
3629
4231
|
}, [makeDefault, controls]);
|
|
3630
|
-
useFrame(() =>
|
|
4232
|
+
useFrame(() => {
|
|
4233
|
+
if (controls.enabled) controls.update();
|
|
4234
|
+
}, -1);
|
|
3631
4235
|
return /* @__PURE__ */ React.createElement("primitive", { ref, object: controls, enableDamping: true, ...rest });
|
|
3632
4236
|
});
|
|
3633
4237
|
|
|
@@ -3753,20 +4357,16 @@ const OrbitControls = /* @__PURE__ */ React.forwardRef(
|
|
|
3753
4357
|
onEnd,
|
|
3754
4358
|
...restProps
|
|
3755
4359
|
}, ref) => {
|
|
3756
|
-
const invalidate = useThree(
|
|
3757
|
-
const defaultCamera = useThree((state) => state.camera);
|
|
3758
|
-
const gl = useThree((state) => state.gl);
|
|
3759
|
-
const events = useThree((state) => state.events);
|
|
3760
|
-
const setEvents = useThree((state) => state.setEvents);
|
|
3761
|
-
const set = useThree((state) => state.set);
|
|
3762
|
-
const get = useThree((state) => state.get);
|
|
3763
|
-
const performance = useThree((state) => state.performance);
|
|
4360
|
+
const { invalidate, camera: defaultCamera, renderer, events, setEvents, set, get, performance } = useThree();
|
|
3764
4361
|
const explCamera = camera || defaultCamera;
|
|
3765
|
-
const explDomElement = domElement || events.connected ||
|
|
4362
|
+
const explDomElement = domElement || events.connected || renderer.domElement;
|
|
3766
4363
|
const controls = React.useMemo(() => new OrbitControls$1(explCamera), [explCamera]);
|
|
3767
|
-
useFrame(
|
|
3768
|
-
|
|
3769
|
-
|
|
4364
|
+
useFrame(
|
|
4365
|
+
() => {
|
|
4366
|
+
if (controls.enabled) controls.update();
|
|
4367
|
+
},
|
|
4368
|
+
{ before: "update" }
|
|
4369
|
+
);
|
|
3770
4370
|
React.useEffect(() => {
|
|
3771
4371
|
if (keyEvents) {
|
|
3772
4372
|
controls.connect(keyEvents === true ? explDomElement : keyEvents);
|
|
@@ -3880,9 +4480,8 @@ function PresentationControls({
|
|
|
3880
4480
|
azimuth = [-Infinity, Infinity],
|
|
3881
4481
|
damping = 0.25
|
|
3882
4482
|
}) {
|
|
3883
|
-
const events = useThree(
|
|
3884
|
-
const
|
|
3885
|
-
const explDomElement = domElement || events.connected || gl.domElement;
|
|
4483
|
+
const { events, renderer, invalidate } = useThree();
|
|
4484
|
+
const explDomElement = domElement || events.connected || renderer.domElement;
|
|
3886
4485
|
const { size } = useThree();
|
|
3887
4486
|
const rPolar = React.useMemo(
|
|
3888
4487
|
() => [rotation[0] + polar[0], rotation[0] + polar[1]],
|
|
@@ -3899,18 +4498,20 @@ function PresentationControls({
|
|
|
3899
4498
|
React.useEffect(() => {
|
|
3900
4499
|
if (global && cursor && enabled) {
|
|
3901
4500
|
explDomElement.style.cursor = "grab";
|
|
3902
|
-
|
|
4501
|
+
renderer.domElement.style.cursor = "";
|
|
3903
4502
|
return () => {
|
|
3904
4503
|
explDomElement.style.cursor = "default";
|
|
3905
|
-
|
|
4504
|
+
renderer.domElement.style.cursor = "default";
|
|
3906
4505
|
};
|
|
3907
4506
|
}
|
|
3908
4507
|
}, [global, cursor, explDomElement, enabled]);
|
|
3909
4508
|
const [animation] = React.useState({ scale: 1, rotation: rInitial, damping });
|
|
3910
4509
|
const ref = React.useRef(null);
|
|
3911
4510
|
useFrame((state, delta) => {
|
|
3912
|
-
|
|
3913
|
-
easing.
|
|
4511
|
+
let changed = false;
|
|
4512
|
+
changed ||= easing.damp3(ref.current.scale, animation.scale, animation.damping, delta);
|
|
4513
|
+
changed ||= easing.dampE(ref.current.rotation, animation.rotation, animation.damping, delta);
|
|
4514
|
+
if (changed) state.invalidate();
|
|
3914
4515
|
});
|
|
3915
4516
|
const bind = useGesture(
|
|
3916
4517
|
{
|
|
@@ -3918,6 +4519,7 @@ function PresentationControls({
|
|
|
3918
4519
|
if (cursor && !global && enabled) explDomElement.style.cursor = last ? "auto" : "grab";
|
|
3919
4520
|
},
|
|
3920
4521
|
onDrag: ({ down, delta: [x, y], memo: [oldY, oldX] = animation.rotation || rInitial }) => {
|
|
4522
|
+
invalidate();
|
|
3921
4523
|
if (!enabled) return [y, x];
|
|
3922
4524
|
if (cursor) explDomElement.style.cursor = down ? "grabbing" : "grab";
|
|
3923
4525
|
x = MathUtils.clamp(oldX + x / size.width * Math.PI * speed, ...rAzimuth);
|
|
@@ -3926,9 +4528,12 @@ function PresentationControls({
|
|
|
3926
4528
|
animation.rotation = snap && !down ? rInitial : [y, x, 0];
|
|
3927
4529
|
animation.damping = snap && !down && typeof snap !== "boolean" ? snap : damping;
|
|
3928
4530
|
return [y, x];
|
|
4531
|
+
},
|
|
4532
|
+
onDragEnd: () => {
|
|
4533
|
+
invalidate();
|
|
3929
4534
|
}
|
|
3930
4535
|
},
|
|
3931
|
-
{ target: global ? explDomElement : void 0 }
|
|
4536
|
+
{ target: global ? explDomElement : void 0, enabled }
|
|
3932
4537
|
);
|
|
3933
4538
|
return /* @__PURE__ */ React.createElement("group", { ref, ...bind?.() }, children);
|
|
3934
4539
|
}
|
|
@@ -3937,6 +4542,10 @@ function roundToPixelRatio(value) {
|
|
|
3937
4542
|
const ratio = window.devicePixelRatio || 1;
|
|
3938
4543
|
return Math.round(value * ratio) / ratio;
|
|
3939
4544
|
}
|
|
4545
|
+
function getMaxAnisotropy(renderer) {
|
|
4546
|
+
const r = renderer;
|
|
4547
|
+
return r?.getMaxAnisotropy?.() ?? r?.capabilities?.getMaxAnisotropy?.() ?? 1;
|
|
4548
|
+
}
|
|
3940
4549
|
|
|
3941
4550
|
const context$7 = /* @__PURE__ */ React.createContext(null);
|
|
3942
4551
|
const rootCache = /* @__PURE__ */ new WeakMap();
|
|
@@ -3963,6 +4572,7 @@ function ScrollControls({
|
|
|
3963
4572
|
const [fixed] = React.useState(() => document.createElement("div"));
|
|
3964
4573
|
const target = gl.domElement.parentNode;
|
|
3965
4574
|
const scroll = React.useRef(0);
|
|
4575
|
+
const disableScrollUpdate = React.useRef(false);
|
|
3966
4576
|
const state = React.useMemo(() => {
|
|
3967
4577
|
const state2 = {
|
|
3968
4578
|
el,
|
|
@@ -4044,16 +4654,20 @@ function ScrollControls({
|
|
|
4044
4654
|
const scrollLength = el[horizontal ? "scrollWidth" : "scrollHeight"];
|
|
4045
4655
|
const scrollThreshold = scrollLength - containerLength;
|
|
4046
4656
|
let current = 0;
|
|
4047
|
-
let disableScroll =
|
|
4657
|
+
let disableScroll = false;
|
|
4048
4658
|
let firstRun = true;
|
|
4049
4659
|
const onScroll = () => {
|
|
4050
4660
|
if (!enabled || firstRun) return;
|
|
4661
|
+
if (disableScrollUpdate.current) {
|
|
4662
|
+
disableScrollUpdate.current = false;
|
|
4663
|
+
return;
|
|
4664
|
+
}
|
|
4051
4665
|
invalidate();
|
|
4052
4666
|
current = el[horizontal ? "scrollLeft" : "scrollTop"];
|
|
4053
4667
|
scroll.current = current / scrollThreshold;
|
|
4054
4668
|
if (infinite) {
|
|
4055
4669
|
if (!disableScroll) {
|
|
4056
|
-
if (current >= scrollThreshold) {
|
|
4670
|
+
if (current >= scrollThreshold - 1) {
|
|
4057
4671
|
const damp = 1 - state.offset;
|
|
4058
4672
|
el[horizontal ? "scrollLeft" : "scrollTop"] = 1;
|
|
4059
4673
|
scroll.current = state.offset = -damp;
|
|
@@ -4070,11 +4684,34 @@ function ScrollControls({
|
|
|
4070
4684
|
};
|
|
4071
4685
|
el.addEventListener("scroll", onScroll, { passive: true });
|
|
4072
4686
|
requestAnimationFrame(() => firstRun = false);
|
|
4073
|
-
const
|
|
4074
|
-
|
|
4687
|
+
const onResize = () => {
|
|
4688
|
+
if (!el) return;
|
|
4689
|
+
const scrollLength2 = el[horizontal ? "scrollWidth" : "scrollHeight"];
|
|
4690
|
+
const containerLength2 = el[horizontal ? "clientWidth" : "clientHeight"];
|
|
4691
|
+
disableScrollUpdate.current = true;
|
|
4692
|
+
el[horizontal ? "scrollLeft" : "scrollTop"] = state.offset * (scrollLength2 - containerLength2);
|
|
4693
|
+
};
|
|
4694
|
+
const onWheel = (e) => {
|
|
4695
|
+
if (horizontal) {
|
|
4696
|
+
const previous = el.scrollLeft;
|
|
4697
|
+
el.scrollLeft += e.deltaY / 2;
|
|
4698
|
+
if (infinite && previous === el.scrollLeft) {
|
|
4699
|
+
onScroll();
|
|
4700
|
+
}
|
|
4701
|
+
} else if (infinite) {
|
|
4702
|
+
if (el.scrollTop <= 1 && e.deltaY < 0) {
|
|
4703
|
+
onScroll();
|
|
4704
|
+
} else if (el.scrollTop >= el.scrollHeight - el.clientHeight - 1 && e.deltaY > 0) {
|
|
4705
|
+
onScroll();
|
|
4706
|
+
}
|
|
4707
|
+
}
|
|
4708
|
+
};
|
|
4709
|
+
if (horizontal || infinite) el.addEventListener("wheel", onWheel, { passive: true });
|
|
4710
|
+
if (horizontal) window.addEventListener("resize", onResize);
|
|
4075
4711
|
return () => {
|
|
4076
4712
|
el.removeEventListener("scroll", onScroll);
|
|
4077
|
-
if (horizontal) el.removeEventListener("wheel", onWheel);
|
|
4713
|
+
if (horizontal || infinite) el.removeEventListener("wheel", onWheel);
|
|
4714
|
+
if (horizontal) window.removeEventListener("resize", onResize);
|
|
4078
4715
|
};
|
|
4079
4716
|
}
|
|
4080
4717
|
}, [el, events, size, infinite, state, invalidate, horizontal, enabled]);
|
|
@@ -4491,10 +5128,10 @@ const CloudInstance = /* @__PURE__ */ React.forwardRef(
|
|
|
4491
5128
|
return /* @__PURE__ */ React.createElement("group", { ref, ...props });
|
|
4492
5129
|
}
|
|
4493
5130
|
);
|
|
4494
|
-
const Cloud = /* @__PURE__ */ React.forwardRef((props, fref) => {
|
|
5131
|
+
const Cloud = /* @__PURE__ */ React.forwardRef(({ materialFactory, ...props }, fref) => {
|
|
4495
5132
|
const parent = React.useContext(context$6);
|
|
4496
5133
|
if (parent) return /* @__PURE__ */ React.createElement(CloudInstance, { ref: fref, ...props });
|
|
4497
|
-
return /* @__PURE__ */ React.createElement(Clouds,
|
|
5134
|
+
return /* @__PURE__ */ React.createElement(Clouds, { materialFactory }, /* @__PURE__ */ React.createElement(CloudInstance, { ref: fref, ...props }));
|
|
4498
5135
|
});
|
|
4499
5136
|
|
|
4500
5137
|
const CatmullRomLine = /* @__PURE__ */ React.forwardRef(function CatmullRomLine2({
|
|
@@ -5016,7 +5653,7 @@ const Text3D = /* @__PURE__ */ React.forwardRef(
|
|
|
5016
5653
|
return {
|
|
5017
5654
|
font,
|
|
5018
5655
|
size,
|
|
5019
|
-
height,
|
|
5656
|
+
depth: height,
|
|
5020
5657
|
bevelThickness,
|
|
5021
5658
|
bevelSize,
|
|
5022
5659
|
bevelEnabled,
|
|
@@ -5199,7 +5836,7 @@ const FaceMaterial = ({
|
|
|
5199
5836
|
"meshBasicMaterial",
|
|
5200
5837
|
{
|
|
5201
5838
|
map: texture,
|
|
5202
|
-
"map-anisotropy":
|
|
5839
|
+
"map-anisotropy": getMaxAnisotropy(renderer),
|
|
5203
5840
|
attach: `material-${index}`,
|
|
5204
5841
|
color: hover ? hoverColor : "white",
|
|
5205
5842
|
transparent: true,
|
|
@@ -5310,7 +5947,7 @@ function AxisHead({
|
|
|
5310
5947
|
"spriteMaterial",
|
|
5311
5948
|
{
|
|
5312
5949
|
map: texture,
|
|
5313
|
-
"map-anisotropy":
|
|
5950
|
+
"map-anisotropy": getMaxAnisotropy(renderer),
|
|
5314
5951
|
alphaTest: 0.3,
|
|
5315
5952
|
opacity: label ? 1 : 0.75,
|
|
5316
5953
|
toneMapped: false
|
|
@@ -5455,6 +6092,7 @@ const Html = /* @__PURE__ */ React.forwardRef(
|
|
|
5455
6092
|
}, ref) => {
|
|
5456
6093
|
const { gl, camera, scene, size, raycaster, events, viewport } = useThree();
|
|
5457
6094
|
const forceEven = useThree((state) => state.internal.forceEven);
|
|
6095
|
+
const { frustum } = useThree();
|
|
5458
6096
|
const [el] = React.useState(() => document.createElement(as));
|
|
5459
6097
|
const root = React.useRef(null);
|
|
5460
6098
|
const group = React.useRef(null);
|
|
@@ -5484,22 +6122,18 @@ const Html = /* @__PURE__ */ React.forwardRef(
|
|
|
5484
6122
|
if (group.current) {
|
|
5485
6123
|
if (!root.current) {
|
|
5486
6124
|
root.current = ReactDOM.createRoot(el);
|
|
5487
|
-
|
|
5488
|
-
|
|
5489
|
-
|
|
5490
|
-
|
|
5491
|
-
|
|
5492
|
-
|
|
6125
|
+
scene.updateMatrixWorld();
|
|
6126
|
+
if (transform) {
|
|
6127
|
+
el.style.cssText = `position:absolute;top:0;left:0;pointer-events:none;overflow:hidden;`;
|
|
6128
|
+
} else {
|
|
6129
|
+
el.style.cssText = `position:absolute;top:0;left:0;transform:translate3d(0,-9999px,0);transform-origin:0 0;`;
|
|
6130
|
+
}
|
|
5493
6131
|
}
|
|
5494
6132
|
if (target) {
|
|
5495
6133
|
if (prepend) target.prepend(el);
|
|
5496
6134
|
else target.appendChild(el);
|
|
5497
6135
|
}
|
|
5498
6136
|
return () => {
|
|
5499
|
-
if (root.current) {
|
|
5500
|
-
root.current.unmount();
|
|
5501
|
-
root.current = null;
|
|
5502
|
-
}
|
|
5503
6137
|
if (target && target.contains(el)) {
|
|
5504
6138
|
target.removeChild(el);
|
|
5505
6139
|
}
|
|
@@ -5633,8 +6267,7 @@ const Html = /* @__PURE__ */ React.forwardRef(
|
|
|
5633
6267
|
if (transformOuterRef.current) {
|
|
5634
6268
|
const el2 = transformOuterRef.current.children[0];
|
|
5635
6269
|
if (el2?.clientWidth && el2?.clientHeight) {
|
|
5636
|
-
|
|
5637
|
-
if (isOrthographicCamera || geometry) {
|
|
6270
|
+
if (geometry) {
|
|
5638
6271
|
if (props.scale) {
|
|
5639
6272
|
if (!Array.isArray(props.scale)) {
|
|
5640
6273
|
occlusionMeshRef.current.scale.setScalar(1 / props.scale);
|
|
@@ -5666,64 +6299,7 @@ const Html = /* @__PURE__ */ React.forwardRef(
|
|
|
5666
6299
|
}
|
|
5667
6300
|
}
|
|
5668
6301
|
});
|
|
5669
|
-
|
|
5670
|
-
() => ({
|
|
5671
|
-
vertexShader: !transform ? (
|
|
5672
|
-
/* glsl */
|
|
5673
|
-
`
|
|
5674
|
-
/*
|
|
5675
|
-
This shader is from the THREE's SpriteMaterial.
|
|
5676
|
-
We need to turn the backing plane into a Sprite
|
|
5677
|
-
(make it always face the camera) if "transfrom"
|
|
5678
|
-
is false.
|
|
5679
|
-
*/
|
|
5680
|
-
#include <common>
|
|
5681
|
-
|
|
5682
|
-
void main() {
|
|
5683
|
-
vec2 center = vec2(0., 1.);
|
|
5684
|
-
float rotation = 0.0;
|
|
5685
|
-
|
|
5686
|
-
// This is somewhat arbitrary, but it seems to work well
|
|
5687
|
-
// Need to figure out how to derive this dynamically if it even matters
|
|
5688
|
-
float size = 0.03;
|
|
5689
|
-
|
|
5690
|
-
vec4 mvPosition = modelViewMatrix * vec4( 0.0, 0.0, 0.0, 1.0 );
|
|
5691
|
-
vec2 scale;
|
|
5692
|
-
scale.x = length( vec3( modelMatrix[ 0 ].x, modelMatrix[ 0 ].y, modelMatrix[ 0 ].z ) );
|
|
5693
|
-
scale.y = length( vec3( modelMatrix[ 1 ].x, modelMatrix[ 1 ].y, modelMatrix[ 1 ].z ) );
|
|
5694
|
-
|
|
5695
|
-
bool isPerspective = isPerspectiveMatrix( projectionMatrix );
|
|
5696
|
-
if ( isPerspective ) scale *= - mvPosition.z;
|
|
5697
|
-
|
|
5698
|
-
vec2 alignedPosition = ( position.xy - ( center - vec2( 0.5 ) ) ) * scale * size;
|
|
5699
|
-
vec2 rotatedPosition;
|
|
5700
|
-
rotatedPosition.x = cos( rotation ) * alignedPosition.x - sin( rotation ) * alignedPosition.y;
|
|
5701
|
-
rotatedPosition.y = sin( rotation ) * alignedPosition.x + cos( rotation ) * alignedPosition.y;
|
|
5702
|
-
mvPosition.xy += rotatedPosition;
|
|
5703
|
-
|
|
5704
|
-
gl_Position = projectionMatrix * mvPosition;
|
|
5705
|
-
}
|
|
5706
|
-
`
|
|
5707
|
-
) : void 0,
|
|
5708
|
-
fragmentShader: (
|
|
5709
|
-
/* glsl */
|
|
5710
|
-
`
|
|
5711
|
-
void main() {
|
|
5712
|
-
gl_FragColor = vec4(0.0, 0.0, 0.0, 0.0);
|
|
5713
|
-
}
|
|
5714
|
-
`
|
|
5715
|
-
)
|
|
5716
|
-
}),
|
|
5717
|
-
[transform]
|
|
5718
|
-
);
|
|
5719
|
-
return /* @__PURE__ */ React.createElement("group", { ...props, ref: group }, occlude && !isRayCastOcclusion && /* @__PURE__ */ React.createElement("mesh", { castShadow, receiveShadow, ref: occlusionMeshRef }, geometry || /* @__PURE__ */ React.createElement("planeGeometry", null), material || /* @__PURE__ */ React.createElement(
|
|
5720
|
-
"shaderMaterial",
|
|
5721
|
-
{
|
|
5722
|
-
side: DoubleSide,
|
|
5723
|
-
vertexShader: shaders.vertexShader,
|
|
5724
|
-
fragmentShader: shaders.fragmentShader
|
|
5725
|
-
}
|
|
5726
|
-
)));
|
|
6302
|
+
return /* @__PURE__ */ React.createElement("group", { ...props, ref: group }, occlude && !isRayCastOcclusion && /* @__PURE__ */ React.createElement("mesh", { castShadow, receiveShadow, ref: occlusionMeshRef }, geometry || /* @__PURE__ */ React.createElement("planeGeometry", null), material));
|
|
5727
6303
|
}
|
|
5728
6304
|
);
|
|
5729
6305
|
|
|
@@ -6576,6 +7152,7 @@ const mW = /* @__PURE__ */ new THREE.Matrix4();
|
|
|
6576
7152
|
const mL = /* @__PURE__ */ new THREE.Matrix4();
|
|
6577
7153
|
const mL0Inv = /* @__PURE__ */ new THREE.Matrix4();
|
|
6578
7154
|
const mdL = /* @__PURE__ */ new THREE.Matrix4();
|
|
7155
|
+
const mdW = /* @__PURE__ */ new THREE.Matrix4();
|
|
6579
7156
|
const mG = /* @__PURE__ */ new THREE.Matrix4();
|
|
6580
7157
|
const bb = /* @__PURE__ */ new THREE.Box3();
|
|
6581
7158
|
const bbObj = /* @__PURE__ */ new THREE.Box3();
|
|
@@ -6690,7 +7267,8 @@ const PivotControls = /* @__PURE__ */ React.forwardRef(
|
|
|
6690
7267
|
onDragStart && onDragStart(props2);
|
|
6691
7268
|
invalidate();
|
|
6692
7269
|
},
|
|
6693
|
-
onDrag: (
|
|
7270
|
+
onDrag: (mdW_) => {
|
|
7271
|
+
mdW.copy(mdW_);
|
|
6694
7272
|
mP.copy(parentRef.current.matrixWorld);
|
|
6695
7273
|
mPInv.copy(mP).invert();
|
|
6696
7274
|
mW.copy(mW0).premultiply(mdW);
|
|
@@ -6702,12 +7280,12 @@ const PivotControls = /* @__PURE__ */ React.forwardRef(
|
|
|
6702
7280
|
}
|
|
6703
7281
|
const target = resolveObject(object);
|
|
6704
7282
|
if (target) target.matrix.copy(mL);
|
|
6705
|
-
onDrag && onDrag(mL, mdL, mW, mdW);
|
|
7283
|
+
onDrag && onDrag({ local: mL, deltaLocal: mdL, world: mW, deltaWorld: mdW });
|
|
6706
7284
|
invalidate();
|
|
6707
7285
|
},
|
|
6708
7286
|
onDragEnd: () => {
|
|
6709
7287
|
dragState.current = null;
|
|
6710
|
-
if (onDragEnd) onDragEnd();
|
|
7288
|
+
if (onDragEnd) onDragEnd({ local: mL, deltaLocal: mdL, world: mW, deltaWorld: mdW });
|
|
6711
7289
|
invalidate();
|
|
6712
7290
|
},
|
|
6713
7291
|
onHover: (props2) => {
|
|
@@ -6818,7 +7396,9 @@ const TransformControls = /* @__PURE__ */ React.forwardRef(
|
|
|
6818
7396
|
const group = React.useRef(null);
|
|
6819
7397
|
React.useLayoutEffect(() => {
|
|
6820
7398
|
if (object) {
|
|
6821
|
-
controls.attach(
|
|
7399
|
+
controls.attach(
|
|
7400
|
+
object instanceof THREE.Object3D ? object : object.current
|
|
7401
|
+
);
|
|
6822
7402
|
} else if (group.current instanceof THREE.Object3D) {
|
|
6823
7403
|
controls.attach(group.current);
|
|
6824
7404
|
}
|
|
@@ -6917,7 +7497,7 @@ const PointMaterial = /* @__PURE__ */ React.forwardRef((props, ref) => {
|
|
|
6917
7497
|
return /* @__PURE__ */ React.createElement("primitive", { ...props, object: material, ref, attach: "material" });
|
|
6918
7498
|
});
|
|
6919
7499
|
|
|
6920
|
-
const PositionalAudio = /* @__PURE__ */ React.forwardRef(({ url, distance = 1, loop =
|
|
7500
|
+
const PositionalAudio = /* @__PURE__ */ React.forwardRef(({ url, distance = 1, loop = false, autoplay, ...props }, ref) => {
|
|
6921
7501
|
const sound = React.useRef(null);
|
|
6922
7502
|
React.useImperativeHandle(ref, () => sound.current, []);
|
|
6923
7503
|
const camera = useThree(({ camera: camera2 }) => camera2);
|
|
@@ -6929,7 +7509,9 @@ const PositionalAudio = /* @__PURE__ */ React.forwardRef(({ url, distance = 1, l
|
|
|
6929
7509
|
_sound.setBuffer(Array.isArray(buffer) ? buffer[0] : buffer);
|
|
6930
7510
|
_sound.setRefDistance(distance);
|
|
6931
7511
|
_sound.setLoop(loop);
|
|
6932
|
-
if (autoplay && !_sound.isPlaying)
|
|
7512
|
+
if (autoplay && !_sound.isPlaying) {
|
|
7513
|
+
_sound.play();
|
|
7514
|
+
}
|
|
6933
7515
|
}
|
|
6934
7516
|
}, [buffer, camera, distance, loop]);
|
|
6935
7517
|
React.useEffect(() => {
|
|
@@ -6998,7 +7580,6 @@ const tempMatrix = /* @__PURE__ */ new THREE.Matrix4();
|
|
|
6998
7580
|
const translation = /* @__PURE__ */ new THREE.Vector3();
|
|
6999
7581
|
const rotation = /* @__PURE__ */ new THREE.Quaternion();
|
|
7000
7582
|
const scale = /* @__PURE__ */ new THREE.Vector3();
|
|
7001
|
-
const isInstancedBufferAttribute = (attr) => attr.isInstancedBufferAttribute;
|
|
7002
7583
|
const Instance = /* @__PURE__ */ React.forwardRef(({ context, children, ...props }, ref) => {
|
|
7003
7584
|
React.useMemo(() => extend({ PositionMesh }), []);
|
|
7004
7585
|
const group = React.useRef(null);
|
|
@@ -7018,24 +7599,20 @@ const Instances = /* @__PURE__ */ React.forwardRef(({ context, children, range,
|
|
|
7018
7599
|
const parentRef = React.useRef(null);
|
|
7019
7600
|
React.useImperativeHandle(ref, () => parentRef.current, []);
|
|
7020
7601
|
const [instances, setInstances] = React.useState([]);
|
|
7602
|
+
const boundsDirty = React.useRef(true);
|
|
7021
7603
|
const [[matrices, colors]] = React.useState(() => {
|
|
7022
7604
|
const mArray = new Float32Array(limit * 16);
|
|
7023
7605
|
for (let i = 0; i < limit; i++) tempMatrix.identity().toArray(mArray, i * 16);
|
|
7024
7606
|
return [mArray, new Float32Array([...new Array(limit * 3)].map(() => 1))];
|
|
7025
7607
|
});
|
|
7026
7608
|
React.useEffect(() => {
|
|
7027
|
-
parentRef.current.instanceMatrix.needsUpdate = true;
|
|
7609
|
+
if (parentRef.current) parentRef.current.instanceMatrix.needsUpdate = true;
|
|
7028
7610
|
});
|
|
7029
7611
|
let iterations = 0;
|
|
7030
7612
|
let count = 0;
|
|
7031
|
-
const attributes = React.useRef([]);
|
|
7032
|
-
React.useLayoutEffect(() => {
|
|
7033
|
-
attributes.current = Object.entries(parentRef.current.geometry.attributes).filter(
|
|
7034
|
-
([_name, value]) => isInstancedBufferAttribute(value)
|
|
7035
|
-
);
|
|
7036
|
-
});
|
|
7037
7613
|
useFrame(() => {
|
|
7038
7614
|
if (frames === Infinity || iterations < frames) {
|
|
7615
|
+
if (!parentRef.current) return;
|
|
7039
7616
|
parentRef.current.updateMatrix();
|
|
7040
7617
|
parentRef.current.updateMatrixWorld();
|
|
7041
7618
|
parentMatrix.copy(parentRef.current.matrixWorld).invert();
|
|
@@ -7056,13 +7633,22 @@ const Instances = /* @__PURE__ */ React.forwardRef(({ context, children, range,
|
|
|
7056
7633
|
}
|
|
7057
7634
|
iterations++;
|
|
7058
7635
|
}
|
|
7636
|
+
if (boundsDirty.current && (frames === Infinity || iterations === frames)) {
|
|
7637
|
+
boundsDirty.current = false;
|
|
7638
|
+
if (parentRef.current.boundingBox) parentRef.current.computeBoundingBox();
|
|
7639
|
+
if (parentRef.current.boundingSphere) parentRef.current.computeBoundingSphere();
|
|
7640
|
+
}
|
|
7059
7641
|
});
|
|
7060
7642
|
const api = React.useMemo(
|
|
7061
7643
|
() => ({
|
|
7062
7644
|
getParent: () => parentRef,
|
|
7063
7645
|
subscribe: (ref2) => {
|
|
7064
7646
|
setInstances((instances2) => [...instances2, ref2]);
|
|
7065
|
-
|
|
7647
|
+
boundsDirty.current = true;
|
|
7648
|
+
return () => {
|
|
7649
|
+
setInstances((instances2) => instances2.filter((item) => item.current !== ref2.current));
|
|
7650
|
+
boundsDirty.current = true;
|
|
7651
|
+
};
|
|
7066
7652
|
}
|
|
7067
7653
|
}),
|
|
7068
7654
|
[]
|
|
@@ -7087,10 +7673,23 @@ const Merged = /* @__PURE__ */ React.forwardRef(function Merged2({ meshes, child
|
|
|
7087
7673
|
if (!isArray) {
|
|
7088
7674
|
for (const key of Object.keys(meshes)) if (!meshes[key].isMesh) delete meshes[key];
|
|
7089
7675
|
}
|
|
7090
|
-
const render = (args) =>
|
|
7091
|
-
|
|
7092
|
-
|
|
7093
|
-
|
|
7676
|
+
const render = (args) => {
|
|
7677
|
+
if (isArray) {
|
|
7678
|
+
return children(
|
|
7679
|
+
...args
|
|
7680
|
+
);
|
|
7681
|
+
}
|
|
7682
|
+
const instanceMap = {};
|
|
7683
|
+
const keys = Object.keys(meshes).filter((key) => meshes[key].isMesh);
|
|
7684
|
+
keys.forEach((key, i) => {
|
|
7685
|
+
instanceMap[key] = args[i];
|
|
7686
|
+
});
|
|
7687
|
+
return children(instanceMap);
|
|
7688
|
+
};
|
|
7689
|
+
const components = (isArray ? meshes : Object.values(meshes)).map((mesh) => {
|
|
7690
|
+
const { geometry, material } = mesh;
|
|
7691
|
+
return /* @__PURE__ */ React.createElement(Instances, { key: geometry.uuid, geometry, material, ...props });
|
|
7692
|
+
});
|
|
7094
7693
|
return /* @__PURE__ */ React.createElement("group", { ref }, renderRecursive(render, components));
|
|
7095
7694
|
});
|
|
7096
7695
|
function renderRecursive(render, components, results = []) {
|
|
@@ -8164,12 +8763,13 @@ function Sampler({ children, weight, transform, instances, mesh, count = 16, ...
|
|
|
8164
8763
|
return /* @__PURE__ */ React.createElement("group", { ref: group, ...props }, children);
|
|
8165
8764
|
}
|
|
8166
8765
|
|
|
8766
|
+
const pathStyle = (path) => path.userData?.style;
|
|
8167
8767
|
const Svg = /* @__PURE__ */ forwardRef(
|
|
8168
8768
|
function R3FSvg({ src, skipFill, skipStrokes, fillMaterial, strokeMaterial, fillMeshProps, strokeMeshProps, ...props }, ref) {
|
|
8169
8769
|
const svg = useLoader(SVGLoader, !src.startsWith("<svg") ? src : `data:image/svg+xml;utf8,${src}`);
|
|
8170
8770
|
const strokeGeometries = useMemo(
|
|
8171
8771
|
() => skipStrokes ? [] : svg.paths.map(
|
|
8172
|
-
(path) => path
|
|
8772
|
+
(path) => pathStyle(path)?.stroke === void 0 || pathStyle(path).stroke === "none" ? null : path.subPaths.map((subPath) => SVGLoader.pointsToStroke(subPath.getPoints(), pathStyle(path)))
|
|
8173
8773
|
),
|
|
8174
8774
|
[svg, skipStrokes]
|
|
8175
8775
|
);
|
|
@@ -8177,21 +8777,21 @@ const Svg = /* @__PURE__ */ forwardRef(
|
|
|
8177
8777
|
return () => strokeGeometries.forEach((group) => group && group.map((g) => g.dispose()));
|
|
8178
8778
|
}, [strokeGeometries]);
|
|
8179
8779
|
let renderOrder = 0;
|
|
8180
|
-
return /* @__PURE__ */ React.createElement("object3D", { ref, ...props }, /* @__PURE__ */ React.createElement("object3D", { scale: [1, -1, 1] }, svg.paths.map((path, p) => /* @__PURE__ */ React.createElement(Fragment, { key: p }, !skipFill && path
|
|
8780
|
+
return /* @__PURE__ */ React.createElement("object3D", { ref, ...props }, /* @__PURE__ */ React.createElement("object3D", { scale: [1, -1, 1] }, svg.paths.map((path, p) => /* @__PURE__ */ React.createElement(Fragment, { key: p }, !skipFill && pathStyle(path)?.fill !== void 0 && pathStyle(path).fill !== "none" && SVGLoader.createShapes(path).map((shape, s) => /* @__PURE__ */ React.createElement("mesh", { key: s, ...fillMeshProps, renderOrder: renderOrder++ }, /* @__PURE__ */ React.createElement("shapeGeometry", { args: [shape] }), /* @__PURE__ */ React.createElement(
|
|
8181
8781
|
"meshBasicMaterial",
|
|
8182
8782
|
{
|
|
8183
|
-
color: path.
|
|
8184
|
-
opacity: path.
|
|
8783
|
+
color: pathStyle(path).fill,
|
|
8784
|
+
opacity: pathStyle(path).fillOpacity,
|
|
8185
8785
|
transparent: true,
|
|
8186
8786
|
side: DoubleSide,
|
|
8187
8787
|
depthWrite: false,
|
|
8188
8788
|
...fillMaterial
|
|
8189
8789
|
}
|
|
8190
|
-
))), !skipStrokes && path
|
|
8790
|
+
))), !skipStrokes && pathStyle(path)?.stroke !== void 0 && pathStyle(path).stroke !== "none" && path.subPaths.map((_subPath, s) => /* @__PURE__ */ React.createElement("mesh", { key: s, geometry: strokeGeometries[p][s], ...strokeMeshProps, renderOrder: renderOrder++ }, /* @__PURE__ */ React.createElement(
|
|
8191
8791
|
"meshBasicMaterial",
|
|
8192
8792
|
{
|
|
8193
|
-
color: path.
|
|
8194
|
-
opacity: path.
|
|
8793
|
+
color: pathStyle(path).stroke,
|
|
8794
|
+
opacity: pathStyle(path).strokeOpacity,
|
|
8195
8795
|
transparent: true,
|
|
8196
8796
|
side: DoubleSide,
|
|
8197
8797
|
depthWrite: false,
|
|
@@ -8362,7 +8962,7 @@ function Preload({ all, scene, camera }) {
|
|
|
8362
8962
|
});
|
|
8363
8963
|
}
|
|
8364
8964
|
gl.compile(scene || dScene, camera || dCamera);
|
|
8365
|
-
const cubeRenderTarget = new
|
|
8965
|
+
const cubeRenderTarget = new CubeRenderTarget(128);
|
|
8366
8966
|
const cubeCamera = new CubeCamera$1(0.01, 1e5, cubeRenderTarget);
|
|
8367
8967
|
cubeCamera.update(gl, scene || dScene);
|
|
8368
8968
|
cubeRenderTarget.dispose();
|
|
@@ -8414,8 +9014,8 @@ function useVideoTexture(srcOrSrcObject, {
|
|
|
8414
9014
|
});
|
|
8415
9015
|
if (src && IS_BROWSER && src.endsWith(".m3u8")) {
|
|
8416
9016
|
const hls = hlsRef.current = await getHls(hlsConfig);
|
|
8417
|
-
if (hls) {
|
|
8418
|
-
hls.on(Events.MEDIA_ATTACHED, () => void hls.loadSource(src));
|
|
9017
|
+
if (hls && _HLSModule) {
|
|
9018
|
+
hls.on(_HLSModule.Events.MEDIA_ATTACHED, () => void hls.loadSource(src));
|
|
8419
9019
|
hls.attachMedia(video2);
|
|
8420
9020
|
}
|
|
8421
9021
|
}
|
|
@@ -8635,9 +9235,125 @@ function Fbx({
|
|
|
8635
9235
|
return /* @__PURE__ */ React.createElement(Clone, { ...props, object });
|
|
8636
9236
|
}
|
|
8637
9237
|
|
|
9238
|
+
const SERVICE_KEY = "__drei_ktx2_service__";
|
|
9239
|
+
const DEFAULT_TRANSCODER_PATH = "https://cdn.jsdelivr.net/gh/pmndrs/drei-assets@master/basis/";
|
|
9240
|
+
class KTX2LoaderServiceImpl {
|
|
9241
|
+
loader = null;
|
|
9242
|
+
renderer = null;
|
|
9243
|
+
_isReady = false;
|
|
9244
|
+
transcoderPath = DEFAULT_TRANSCODER_PATH;
|
|
9245
|
+
pendingCallbacks = [];
|
|
9246
|
+
/**
|
|
9247
|
+
* Get or create the singleton KTX2Loader instance.
|
|
9248
|
+
* The loader is created lazily on first access.
|
|
9249
|
+
*/
|
|
9250
|
+
getLoader() {
|
|
9251
|
+
if (!this.loader) {
|
|
9252
|
+
this.loader = new KTX2Loader();
|
|
9253
|
+
this.loader.setTranscoderPath(this.transcoderPath);
|
|
9254
|
+
}
|
|
9255
|
+
return this.loader;
|
|
9256
|
+
}
|
|
9257
|
+
/**
|
|
9258
|
+
* Register a renderer and call detectSupport.
|
|
9259
|
+
* Should be called from within React context (useLayoutEffect).
|
|
9260
|
+
* Flushes any queued callbacks.
|
|
9261
|
+
*/
|
|
9262
|
+
registerRenderer(renderer) {
|
|
9263
|
+
if (this._isReady && this.renderer === renderer) {
|
|
9264
|
+
return;
|
|
9265
|
+
}
|
|
9266
|
+
this.renderer = renderer;
|
|
9267
|
+
const loader = this.getLoader();
|
|
9268
|
+
loader.detectSupport(renderer);
|
|
9269
|
+
this._isReady = true;
|
|
9270
|
+
this.flushPendingCallbacks();
|
|
9271
|
+
}
|
|
9272
|
+
/**
|
|
9273
|
+
* Check if the service is ready (has renderer registered).
|
|
9274
|
+
*/
|
|
9275
|
+
isReady() {
|
|
9276
|
+
return this._isReady;
|
|
9277
|
+
}
|
|
9278
|
+
/**
|
|
9279
|
+
* Get the registered renderer, if any.
|
|
9280
|
+
*/
|
|
9281
|
+
getRenderer() {
|
|
9282
|
+
return this.renderer;
|
|
9283
|
+
}
|
|
9284
|
+
/**
|
|
9285
|
+
* Register a callback to run when renderer becomes available.
|
|
9286
|
+
* If renderer is already available, runs immediately.
|
|
9287
|
+
*/
|
|
9288
|
+
onReady(callback) {
|
|
9289
|
+
if (this._isReady) {
|
|
9290
|
+
callback();
|
|
9291
|
+
} else {
|
|
9292
|
+
this.pendingCallbacks.push(callback);
|
|
9293
|
+
}
|
|
9294
|
+
}
|
|
9295
|
+
/**
|
|
9296
|
+
* Process all pending callbacks.
|
|
9297
|
+
*/
|
|
9298
|
+
flushPendingCallbacks() {
|
|
9299
|
+
const callbacks = this.pendingCallbacks;
|
|
9300
|
+
this.pendingCallbacks = [];
|
|
9301
|
+
for (const callback of callbacks) {
|
|
9302
|
+
try {
|
|
9303
|
+
callback();
|
|
9304
|
+
} catch (error) {
|
|
9305
|
+
console.error("KTX2LoaderService: Error in pending callback:", error);
|
|
9306
|
+
}
|
|
9307
|
+
}
|
|
9308
|
+
}
|
|
9309
|
+
/**
|
|
9310
|
+
* Set the transcoder path for basis/ktx2 decoding.
|
|
9311
|
+
*/
|
|
9312
|
+
setTranscoderPath(path) {
|
|
9313
|
+
this.transcoderPath = path;
|
|
9314
|
+
if (this.loader) {
|
|
9315
|
+
this.loader.setTranscoderPath(path);
|
|
9316
|
+
}
|
|
9317
|
+
}
|
|
9318
|
+
/**
|
|
9319
|
+
* Get the current transcoder path.
|
|
9320
|
+
*/
|
|
9321
|
+
getTranscoderPath() {
|
|
9322
|
+
return this.transcoderPath;
|
|
9323
|
+
}
|
|
9324
|
+
/**
|
|
9325
|
+
* Dispose of the loader and reset state.
|
|
9326
|
+
* Useful for testing or cleanup.
|
|
9327
|
+
*/
|
|
9328
|
+
dispose() {
|
|
9329
|
+
if (this.loader) {
|
|
9330
|
+
this.loader.dispose();
|
|
9331
|
+
}
|
|
9332
|
+
const path = this.transcoderPath;
|
|
9333
|
+
this.loader = null;
|
|
9334
|
+
this.renderer = null;
|
|
9335
|
+
this._isReady = false;
|
|
9336
|
+
this.transcoderPath = path;
|
|
9337
|
+
this.pendingCallbacks = [];
|
|
9338
|
+
}
|
|
9339
|
+
}
|
|
9340
|
+
const KTX2LoaderService = globalThis[SERVICE_KEY] || (globalThis[SERVICE_KEY] = new KTX2LoaderServiceImpl());
|
|
9341
|
+
|
|
8638
9342
|
let dracoLoader = null;
|
|
8639
9343
|
let decoderPath = "https://www.gstatic.com/draco/versioned/decoders/1.5.5/";
|
|
8640
|
-
|
|
9344
|
+
let legacyApiWarned = false;
|
|
9345
|
+
function isOptionsObject(arg) {
|
|
9346
|
+
return typeof arg === "object" && arg !== null && !Array.isArray(arg);
|
|
9347
|
+
}
|
|
9348
|
+
function warnLegacyApi() {
|
|
9349
|
+
if (!legacyApiWarned) {
|
|
9350
|
+
legacyApiWarned = true;
|
|
9351
|
+
console.warn(
|
|
9352
|
+
"useGLTF: Boolean arguments are deprecated. Use options object instead:\n useGLTF(path, { draco: true, meshopt: true, ktx2: true })"
|
|
9353
|
+
);
|
|
9354
|
+
}
|
|
9355
|
+
}
|
|
9356
|
+
function extensions(useDraco = true, useMeshopt = true, useKTX2 = false, extendLoader, renderer) {
|
|
8641
9357
|
return (loader) => {
|
|
8642
9358
|
if (extendLoader) {
|
|
8643
9359
|
extendLoader(loader);
|
|
@@ -8653,36 +9369,110 @@ function extensions(useDraco = true, useMeshopt = true, extendLoader) {
|
|
|
8653
9369
|
const decoder = typeof MeshoptDecoder === "function" ? MeshoptDecoder() : MeshoptDecoder;
|
|
8654
9370
|
loader.setMeshoptDecoder(decoder);
|
|
8655
9371
|
}
|
|
9372
|
+
if (useKTX2) {
|
|
9373
|
+
const ktx2Loader = KTX2LoaderService.getLoader();
|
|
9374
|
+
if (typeof useKTX2 === "string") {
|
|
9375
|
+
ktx2Loader.setTranscoderPath(useKTX2);
|
|
9376
|
+
}
|
|
9377
|
+
if (renderer) {
|
|
9378
|
+
ktx2Loader.detectSupport(renderer);
|
|
9379
|
+
}
|
|
9380
|
+
loader.setKTX2Loader(ktx2Loader);
|
|
9381
|
+
}
|
|
8656
9382
|
};
|
|
8657
9383
|
}
|
|
8658
|
-
|
|
8659
|
-
|
|
9384
|
+
function useGLTF(path, optionsOrDraco, useMeshoptArg, useKTX2Arg, extendLoaderArg) {
|
|
9385
|
+
let draco = true;
|
|
9386
|
+
let meshopt = true;
|
|
9387
|
+
let ktx2 = false;
|
|
9388
|
+
let extendLoader;
|
|
9389
|
+
if (isOptionsObject(optionsOrDraco)) {
|
|
9390
|
+
draco = optionsOrDraco.draco ?? true;
|
|
9391
|
+
meshopt = optionsOrDraco.meshopt ?? true;
|
|
9392
|
+
ktx2 = optionsOrDraco.ktx2 ?? false;
|
|
9393
|
+
extendLoader = optionsOrDraco.extendLoader;
|
|
9394
|
+
} else if (optionsOrDraco !== void 0) {
|
|
9395
|
+
warnLegacyApi();
|
|
9396
|
+
draco = optionsOrDraco;
|
|
9397
|
+
meshopt = useMeshoptArg ?? true;
|
|
9398
|
+
ktx2 = useKTX2Arg ?? false;
|
|
9399
|
+
extendLoader = extendLoaderArg;
|
|
9400
|
+
}
|
|
9401
|
+
const renderer = useThree((state) => state.renderer);
|
|
9402
|
+
useLayoutEffect(() => {
|
|
9403
|
+
if (ktx2) {
|
|
9404
|
+
KTX2LoaderService.registerRenderer(renderer);
|
|
9405
|
+
}
|
|
9406
|
+
}, [ktx2, renderer]);
|
|
9407
|
+
return useLoader(GLTFLoader, path, extensions(draco, meshopt, ktx2, extendLoader, ktx2 ? renderer : void 0));
|
|
9408
|
+
}
|
|
9409
|
+
useGLTF.preload = (path, optionsOrDraco, useMeshoptArg, useKTX2Arg, extendLoaderArg) => {
|
|
9410
|
+
let draco = true;
|
|
9411
|
+
let meshopt = true;
|
|
9412
|
+
let ktx2 = false;
|
|
9413
|
+
let extendLoader;
|
|
9414
|
+
if (isOptionsObject(optionsOrDraco)) {
|
|
9415
|
+
draco = optionsOrDraco.draco ?? true;
|
|
9416
|
+
meshopt = optionsOrDraco.meshopt ?? true;
|
|
9417
|
+
ktx2 = optionsOrDraco.ktx2 ?? false;
|
|
9418
|
+
extendLoader = optionsOrDraco.extendLoader;
|
|
9419
|
+
} else if (optionsOrDraco !== void 0) {
|
|
9420
|
+
warnLegacyApi();
|
|
9421
|
+
draco = optionsOrDraco;
|
|
9422
|
+
meshopt = useMeshoptArg ?? true;
|
|
9423
|
+
ktx2 = useKTX2Arg ?? false;
|
|
9424
|
+
extendLoader = extendLoaderArg;
|
|
9425
|
+
}
|
|
9426
|
+
if (ktx2) {
|
|
9427
|
+
KTX2LoaderService.onReady(() => {
|
|
9428
|
+
const renderer = KTX2LoaderService.getRenderer();
|
|
9429
|
+
useLoader.preload(GLTFLoader, path, extensions(draco, meshopt, ktx2, extendLoader, renderer));
|
|
9430
|
+
});
|
|
9431
|
+
} else {
|
|
9432
|
+
useLoader.preload(GLTFLoader, path, extensions(draco, meshopt, false, extendLoader));
|
|
9433
|
+
}
|
|
9434
|
+
};
|
|
8660
9435
|
useGLTF.clear = (path) => useLoader.clear(GLTFLoader, path);
|
|
8661
9436
|
useGLTF.setDecoderPath = (path) => {
|
|
8662
9437
|
decoderPath = path;
|
|
8663
9438
|
};
|
|
9439
|
+
useGLTF.setKTX2TranscoderPath = (path) => {
|
|
9440
|
+
KTX2LoaderService.setTranscoderPath(path);
|
|
9441
|
+
};
|
|
8664
9442
|
const Gltf = /* @__PURE__ */ React.forwardRef(
|
|
8665
|
-
({ src, useDraco, useMeshOpt, extendLoader, ...props }, ref) => {
|
|
8666
|
-
const
|
|
9443
|
+
({ src, useDraco, useMeshOpt, extendLoader, options, ...props }, ref) => {
|
|
9444
|
+
const opts = options ?? {
|
|
9445
|
+
draco: useDraco,
|
|
9446
|
+
meshopt: useMeshOpt,
|
|
9447
|
+
extendLoader
|
|
9448
|
+
};
|
|
9449
|
+
const { scene } = useGLTF(src, opts);
|
|
8667
9450
|
return /* @__PURE__ */ React.createElement(Clone, { ref, ...props, object: scene });
|
|
8668
9451
|
}
|
|
8669
9452
|
);
|
|
8670
9453
|
|
|
8671
|
-
let transcoderPath = "https://cdn.jsdelivr.net/gh/pmndrs/drei-assets@master/basis/";
|
|
8672
9454
|
function useKTX2(input, basisPath = true, extendLoader) {
|
|
8673
9455
|
const renderer = useThree((state) => state.renderer);
|
|
9456
|
+
useLayoutEffect(() => {
|
|
9457
|
+
KTX2LoaderService.registerRenderer(renderer);
|
|
9458
|
+
}, [renderer]);
|
|
8674
9459
|
const textures = useLoader(KTX2Loader, IsObject(input) ? Object.values(input) : input, (loader) => {
|
|
8675
9460
|
if (extendLoader) {
|
|
8676
9461
|
extendLoader(loader);
|
|
8677
9462
|
}
|
|
8678
9463
|
if (basisPath) {
|
|
8679
|
-
|
|
9464
|
+
const path = typeof basisPath === "string" ? basisPath : KTX2LoaderService.getTranscoderPath();
|
|
9465
|
+
loader.setTranscoderPath(path);
|
|
8680
9466
|
}
|
|
8681
9467
|
loader.detectSupport(renderer);
|
|
8682
9468
|
});
|
|
8683
9469
|
useEffect(() => {
|
|
8684
9470
|
const array = Array.isArray(textures) ? textures : [textures];
|
|
8685
|
-
array.forEach((texture) =>
|
|
9471
|
+
array.forEach((texture) => {
|
|
9472
|
+
if ("initTexture" in renderer) {
|
|
9473
|
+
renderer.initTexture(texture);
|
|
9474
|
+
}
|
|
9475
|
+
});
|
|
8686
9476
|
}, [renderer, textures]);
|
|
8687
9477
|
if (IsObject(input)) {
|
|
8688
9478
|
const keys = Object.keys(input);
|
|
@@ -8693,23 +9483,81 @@ function useKTX2(input, basisPath = true, extendLoader) {
|
|
|
8693
9483
|
return textures;
|
|
8694
9484
|
}
|
|
8695
9485
|
}
|
|
8696
|
-
useKTX2.preload = (url, basisPath = true, extendLoader) =>
|
|
8697
|
-
|
|
8698
|
-
|
|
8699
|
-
|
|
8700
|
-
|
|
8701
|
-
|
|
8702
|
-
|
|
8703
|
-
|
|
9486
|
+
useKTX2.preload = (url, basisPath = true, extendLoader) => {
|
|
9487
|
+
KTX2LoaderService.onReady(() => {
|
|
9488
|
+
const renderer = KTX2LoaderService.getRenderer();
|
|
9489
|
+
useLoader.preload(KTX2Loader, url, (loader) => {
|
|
9490
|
+
if (extendLoader) {
|
|
9491
|
+
extendLoader(loader);
|
|
9492
|
+
}
|
|
9493
|
+
if (basisPath) {
|
|
9494
|
+
const path = typeof basisPath === "string" ? basisPath : KTX2LoaderService.getTranscoderPath();
|
|
9495
|
+
loader.setTranscoderPath(path);
|
|
9496
|
+
}
|
|
9497
|
+
if (renderer) {
|
|
9498
|
+
loader.detectSupport(renderer);
|
|
9499
|
+
}
|
|
9500
|
+
});
|
|
9501
|
+
});
|
|
9502
|
+
};
|
|
8704
9503
|
useKTX2.clear = (input) => useLoader.clear(KTX2Loader, input);
|
|
8705
9504
|
useKTX2.setTranscoderPath = (path) => {
|
|
8706
|
-
|
|
9505
|
+
KTX2LoaderService.setTranscoderPath(path);
|
|
8707
9506
|
};
|
|
8708
9507
|
const Ktx2 = ({ children, input, basisPath, extendLoader }) => {
|
|
8709
9508
|
const texture = useKTX2(input, basisPath, extendLoader);
|
|
8710
9509
|
return /* @__PURE__ */ React.createElement(React.Fragment, null, children?.(texture));
|
|
8711
9510
|
};
|
|
8712
9511
|
|
|
9512
|
+
const useVariants = (model, inVariant) => {
|
|
9513
|
+
const [activeVariant, setActiveVariant] = useState(null);
|
|
9514
|
+
const [materials, setMaterials] = useState([]);
|
|
9515
|
+
useEffect(() => {
|
|
9516
|
+
model.parser.getDependencies("material").then((materials2) => {
|
|
9517
|
+
setMaterials(materials2);
|
|
9518
|
+
});
|
|
9519
|
+
}, [model]);
|
|
9520
|
+
const variants = useMemo(() => {
|
|
9521
|
+
return model.userData.gltfExtensions?.KHR_materials_variants?.variants;
|
|
9522
|
+
}, [model]);
|
|
9523
|
+
const applyVariant = useCallback(
|
|
9524
|
+
(variantIndex) => {
|
|
9525
|
+
model.scene.traverse(async (object) => {
|
|
9526
|
+
if (!("isMesh" in object) || !object.userData.gltfExtensions) return;
|
|
9527
|
+
const meshObject = object;
|
|
9528
|
+
const meshVariantDef = meshObject.userData.gltfExtensions.KHR_materials_variants;
|
|
9529
|
+
if (!meshVariantDef) return;
|
|
9530
|
+
if (!meshObject.userData.originalMaterial) meshObject.userData.originalMaterial = meshObject.material;
|
|
9531
|
+
const mapping = meshVariantDef.mappings.find((mapping2) => mapping2.variants.includes(variantIndex));
|
|
9532
|
+
if (mapping) {
|
|
9533
|
+
meshObject.material = await model.parser.getDependency("material", mapping.material);
|
|
9534
|
+
model.parser.assignFinalMaterial(meshObject);
|
|
9535
|
+
} else meshObject.material = meshObject.userData.originalMaterial;
|
|
9536
|
+
if (Array.isArray(meshObject.material)) for (const mat of meshObject.material) mat.needsUpdate = true;
|
|
9537
|
+
else meshObject.material.needsUpdate = true;
|
|
9538
|
+
});
|
|
9539
|
+
},
|
|
9540
|
+
[model]
|
|
9541
|
+
);
|
|
9542
|
+
const setVariant = useCallback(
|
|
9543
|
+
(variantName) => {
|
|
9544
|
+
if (!variants) return;
|
|
9545
|
+
const newVariant = variantName && variants.some((v) => v.name === variantName) ? variantName : null;
|
|
9546
|
+
setActiveVariant(newVariant);
|
|
9547
|
+
},
|
|
9548
|
+
[variants]
|
|
9549
|
+
);
|
|
9550
|
+
useEffect(() => {
|
|
9551
|
+
if (!variants) return;
|
|
9552
|
+
const variantIndex = variants.findIndex((v) => v.name === activeVariant);
|
|
9553
|
+
applyVariant(variantIndex > -1 ? variantIndex : 0);
|
|
9554
|
+
}, [variants, activeVariant, applyVariant]);
|
|
9555
|
+
useEffect(() => {
|
|
9556
|
+
setVariant(inVariant ?? null);
|
|
9557
|
+
}, [inVariant, setVariant]);
|
|
9558
|
+
return { variants, activeVariant, setVariant, materials };
|
|
9559
|
+
};
|
|
9560
|
+
|
|
8713
9561
|
const WebcamVideoTexture = /* @__PURE__ */ forwardRef(
|
|
8714
9562
|
({
|
|
8715
9563
|
constraints = {
|
|
@@ -8897,6 +9745,7 @@ function useEffectfulState(fn, deps = [], cb) {
|
|
|
8897
9745
|
}
|
|
8898
9746
|
|
|
8899
9747
|
function Stats({ showPanel = 0, className, parent }) {
|
|
9748
|
+
React.useEffect(() => void console.warn("drei: <Stats /> is deprecated, use <StatsGl /> instead."), []);
|
|
8900
9749
|
const stats = useEffectfulState(() => new StatsImpl(), []);
|
|
8901
9750
|
React.useEffect(() => {
|
|
8902
9751
|
if (stats) {
|
|
@@ -8925,6 +9774,7 @@ const StatsGl = /* @__PURE__ */ React.forwardRef(
|
|
|
8925
9774
|
const stats2 = new Stats$1({
|
|
8926
9775
|
...props
|
|
8927
9776
|
});
|
|
9777
|
+
stats2.init(renderer);
|
|
8928
9778
|
return stats2;
|
|
8929
9779
|
}, [renderer]);
|
|
8930
9780
|
React.useImperativeHandle(fref, () => stats.domElement, [stats]);
|
|
@@ -8942,7 +9792,7 @@ const StatsGl = /* @__PURE__ */ React.forwardRef(
|
|
|
8942
9792
|
return () => {
|
|
8943
9793
|
if (classNames.length) stats.domElement.classList.remove(...classNames);
|
|
8944
9794
|
node?.removeChild(stats.domElement);
|
|
8945
|
-
stats.
|
|
9795
|
+
stats.dispose();
|
|
8946
9796
|
};
|
|
8947
9797
|
}
|
|
8948
9798
|
}, [parent, stats, className, id, clearStatsGlStyle]);
|
|
@@ -8950,7 +9800,7 @@ const StatsGl = /* @__PURE__ */ React.forwardRef(
|
|
|
8950
9800
|
() => {
|
|
8951
9801
|
stats.begin();
|
|
8952
9802
|
},
|
|
8953
|
-
{ before: "
|
|
9803
|
+
{ before: "update" }
|
|
8954
9804
|
);
|
|
8955
9805
|
useFrame(
|
|
8956
9806
|
() => {
|
|
@@ -9115,8 +9965,9 @@ const TUNNEL_KEY = "__drei_view_tunnel__";
|
|
|
9115
9965
|
const tracked = globalThis[TUNNEL_KEY] || (globalThis[TUNNEL_KEY] = tunnel());
|
|
9116
9966
|
function computeContainerPosition(canvasSize, trackRect, forceEven) {
|
|
9117
9967
|
const { right, top: trackTop, left: trackLeft, bottom: trackBottom, width, height } = trackRect;
|
|
9118
|
-
const isOffscreen = trackRect.bottom < 0 || trackTop > canvasSize.height || right < 0 || trackRect.left > canvasSize.width;
|
|
9119
9968
|
const canvasBottom = canvasSize.top + canvasSize.height;
|
|
9969
|
+
const canvasRight = canvasSize.left + canvasSize.width;
|
|
9970
|
+
const isOffscreen = trackBottom < canvasSize.top || trackTop > canvasBottom || right < canvasSize.left || trackLeft > canvasRight;
|
|
9120
9971
|
const rawBottom = canvasBottom - trackBottom;
|
|
9121
9972
|
const rawLeft = trackLeft - canvasSize.left;
|
|
9122
9973
|
const rawTop = trackTop - canvasSize.top;
|
|
@@ -9676,12 +10527,12 @@ useEnvironment.preload = (preloadOptions) => {
|
|
|
9676
10527
|
if (extensions) extensions(loader2);
|
|
9677
10528
|
});
|
|
9678
10529
|
};
|
|
9679
|
-
const
|
|
10530
|
+
const clearDefaultOptions = {
|
|
9680
10531
|
files: defaultFiles,
|
|
9681
10532
|
preset: void 0
|
|
9682
10533
|
};
|
|
9683
10534
|
useEnvironment.clear = (clearOptions) => {
|
|
9684
|
-
const options = { ...
|
|
10535
|
+
const options = { ...clearDefaultOptions, ...clearOptions };
|
|
9685
10536
|
let { files } = options;
|
|
9686
10537
|
const { preset } = options;
|
|
9687
10538
|
if (preset) {
|
|
@@ -9804,7 +10655,7 @@ function EnvironmentPortal({
|
|
|
9804
10655
|
const camera = React.useRef(null);
|
|
9805
10656
|
const [virtualScene] = React.useState(() => new Scene());
|
|
9806
10657
|
const fbo = React.useMemo(() => {
|
|
9807
|
-
const fbo2 = new
|
|
10658
|
+
const fbo2 = new CubeRenderTarget(resolution);
|
|
9808
10659
|
fbo2.texture.type = HalfFloatType;
|
|
9809
10660
|
return fbo2;
|
|
9810
10661
|
}, [resolution]);
|
|
@@ -10375,9 +11226,14 @@ function Select({
|
|
|
10375
11226
|
const oldControlsEnabled = controls?.enabled;
|
|
10376
11227
|
let isDown = false;
|
|
10377
11228
|
function prepareRay(event, vec) {
|
|
10378
|
-
const
|
|
11229
|
+
const canvas = gl.domElement;
|
|
11230
|
+
const rect = canvas.getBoundingClientRect();
|
|
11231
|
+
const x = event.clientX - rect.left;
|
|
11232
|
+
const y = event.clientY - rect.top;
|
|
10379
11233
|
const { width, height } = size;
|
|
10380
|
-
|
|
11234
|
+
const normalizedX = x / width * 2 - 1;
|
|
11235
|
+
const normalizedY = -(y / height) * 2 + 1;
|
|
11236
|
+
vec.set(normalizedX, normalizedY, -1);
|
|
10381
11237
|
}
|
|
10382
11238
|
function onSelectStart(event) {
|
|
10383
11239
|
if (controls) controls.enabled = false;
|
|
@@ -11229,7 +12085,7 @@ const ImageWithUrl = /* @__PURE__ */ React.forwardRef(
|
|
|
11229
12085
|
return /* @__PURE__ */ React.createElement(ImageBase, { ...props, texture, ref });
|
|
11230
12086
|
}
|
|
11231
12087
|
);
|
|
11232
|
-
const ImageWithTexture = /* @__PURE__ */ React.forwardRef(({
|
|
12088
|
+
const ImageWithTexture = /* @__PURE__ */ React.forwardRef(({ ...props }, ref) => {
|
|
11233
12089
|
return /* @__PURE__ */ React.createElement(ImageBase, { ...props, ref });
|
|
11234
12090
|
});
|
|
11235
12091
|
const Image = /* @__PURE__ */ React.forwardRef((props, ref) => {
|
|
@@ -11357,6 +12213,24 @@ class SpotLightMaterial extends MeshBasicNodeMaterial {
|
|
|
11357
12213
|
}
|
|
11358
12214
|
}
|
|
11359
12215
|
|
|
12216
|
+
function createHtmlNodeMaterial(transform) {
|
|
12217
|
+
const mat = transform ? new MeshBasicNodeMaterial() : new SpriteNodeMaterial();
|
|
12218
|
+
mat.side = DoubleSide;
|
|
12219
|
+
mat.transparent = true;
|
|
12220
|
+
mat.depthWrite = true;
|
|
12221
|
+
mat.fragmentNode = vec4(0, 0, 0, 0);
|
|
12222
|
+
return mat;
|
|
12223
|
+
}
|
|
12224
|
+
const HtmlMaterial = ({ transform }) => {
|
|
12225
|
+
const material = React.useMemo(() => createHtmlNodeMaterial(transform), [transform]);
|
|
12226
|
+
React.useEffect(() => {
|
|
12227
|
+
return () => {
|
|
12228
|
+
material.dispose();
|
|
12229
|
+
};
|
|
12230
|
+
}, [material]);
|
|
12231
|
+
return /* @__PURE__ */ React.createElement("primitive", { object: material, attach: "material" });
|
|
12232
|
+
};
|
|
12233
|
+
|
|
11360
12234
|
class StarfieldMaterial extends SpriteNodeMaterial {
|
|
11361
12235
|
//* Uniforms ==============================
|
|
11362
12236
|
_time = uniform(0);
|
|
@@ -11433,16 +12307,16 @@ class SparklesMaterial extends SpriteNodeMaterial {
|
|
|
11433
12307
|
return pos;
|
|
11434
12308
|
})();
|
|
11435
12309
|
this.scaleNode = Fn(() => {
|
|
11436
|
-
const
|
|
11437
|
-
const
|
|
11438
|
-
const
|
|
11439
|
-
const size =
|
|
12310
|
+
const pixelSize = particleSize.mul(25).mul(this._pixelRatio);
|
|
12311
|
+
const projY = cameraProjectionMatrix.element(1).y;
|
|
12312
|
+
const viewportH = screenSize.y;
|
|
12313
|
+
const size = pixelSize.mul(2).div(projY.mul(viewportH));
|
|
11440
12314
|
return vec2$2(size);
|
|
11441
12315
|
})();
|
|
11442
12316
|
this.colorNode = Fn(() => {
|
|
11443
12317
|
const quadUV = uv();
|
|
11444
12318
|
const distanceToCenter = length(quadUV.sub(vec2$2(0.5)));
|
|
11445
|
-
const strength = float(0.05).div(distanceToCenter).sub(0.1);
|
|
12319
|
+
const strength = clamp(float(0.05).div(distanceToCenter).sub(0.1), 0, 1);
|
|
11446
12320
|
return vec4(particleColor, strength.mul(particleOpacity));
|
|
11447
12321
|
})();
|
|
11448
12322
|
}
|
|
@@ -11713,17 +12587,95 @@ const Grid = /* @__PURE__ */ React.forwardRef(
|
|
|
11713
12587
|
}
|
|
11714
12588
|
);
|
|
11715
12589
|
|
|
11716
|
-
|
|
11717
|
-
|
|
11718
|
-
|
|
11719
|
-
|
|
11720
|
-
|
|
12590
|
+
const createPCSSFilter = (size, samples, focus) => {
|
|
12591
|
+
const sampleCount = Math.min(Math.max(samples, 1), 20);
|
|
12592
|
+
return Fn(({ depthTexture, shadowCoord, shadow, depthLayer }) => {
|
|
12593
|
+
const sampleDepth = (uv2) => {
|
|
12594
|
+
const tex = texture(depthTexture, uv2);
|
|
12595
|
+
const depth = depthTexture.isArrayTexture ? tex.depth(depthLayer) : tex;
|
|
12596
|
+
return depth.r;
|
|
12597
|
+
};
|
|
12598
|
+
const mapSize = reference("mapSize", "vec2", shadow).setGroup(renderGroup);
|
|
12599
|
+
const texelSize = vec2$2(1).div(mapSize);
|
|
12600
|
+
const phi = interleavedGradientNoise(screenCoordinate.xy).mul(6.28318530718);
|
|
12601
|
+
const uv = shadowCoord.xy;
|
|
12602
|
+
const zReceiver = shadowCoord.z.add(1).mul(0.5);
|
|
12603
|
+
const blockerSearchRadius = texelSize.x.mul(size).mul(2);
|
|
12604
|
+
const blockerDepthSum = float(focus).toVar("blockerDepthSum");
|
|
12605
|
+
const blockerCount = float(0).toVar("blockerCount");
|
|
12606
|
+
for (let i = 0; i < sampleCount; i++) {
|
|
12607
|
+
const offset = vogelDiskSample(int(i), int(sampleCount), phi).mul(blockerSearchRadius);
|
|
12608
|
+
const sampleUV = uv.add(offset);
|
|
12609
|
+
const sampleDepthVal = sampleDepth(sampleUV);
|
|
12610
|
+
const isBlocker = step(sampleDepthVal, zReceiver).sub(step(zReceiver, sampleDepthVal)).max(0);
|
|
12611
|
+
blockerDepthSum.addAssign(sampleDepthVal.mul(isBlocker));
|
|
12612
|
+
blockerCount.addAssign(isBlocker);
|
|
12613
|
+
}
|
|
12614
|
+
const avgBlockerDepth = blockerDepthSum.div(blockerCount.max(1));
|
|
12615
|
+
const penumbraRatio = zReceiver.sub(avgBlockerDepth).div(avgBlockerDepth.max(1e-4));
|
|
12616
|
+
const filterRadius = texelSize.x.mul(float(1).add(penumbraRatio.mul(1.25).mul(size)));
|
|
12617
|
+
const shadowSum = float(0).toVar("shadowSum");
|
|
12618
|
+
for (let i = 0; i < sampleCount; i++) {
|
|
12619
|
+
const offset = vogelDiskSample(int(i), int(sampleCount), phi).mul(filterRadius);
|
|
12620
|
+
const sampleUV = uv.add(offset);
|
|
12621
|
+
const sampleDepthVal = sampleDepth(sampleUV);
|
|
12622
|
+
shadowSum.addAssign(step(zReceiver, sampleDepthVal));
|
|
12623
|
+
}
|
|
12624
|
+
const shadowResult = shadowSum.div(sampleCount);
|
|
12625
|
+
const hasBlockers = blockerCount.greaterThan(0.5);
|
|
12626
|
+
return hasBlockers.select(shadowResult, float(1));
|
|
12627
|
+
});
|
|
12628
|
+
};
|
|
12629
|
+
class PCSSShadowNode extends ShadowNode {
|
|
12630
|
+
size;
|
|
12631
|
+
samples;
|
|
12632
|
+
focus;
|
|
12633
|
+
constructor(light, { size = 25, samples = 10, focus = 0 } = {}) {
|
|
12634
|
+
super(light, light.shadow);
|
|
12635
|
+
this.size = size;
|
|
12636
|
+
this.samples = samples;
|
|
12637
|
+
this.focus = focus;
|
|
12638
|
+
}
|
|
12639
|
+
/**
|
|
12640
|
+
* Override to disable hardware depth comparison.
|
|
12641
|
+
* PCSS needs raw depth values for blocker search, so we can't use comparison samplers.
|
|
12642
|
+
*/
|
|
12643
|
+
setupRenderTarget(shadow, builder) {
|
|
12644
|
+
const parentMethod = Object.getPrototypeOf(Object.getPrototypeOf(this)).setupRenderTarget;
|
|
12645
|
+
const result = parentMethod.call(this, shadow, builder);
|
|
12646
|
+
if (result.depthTexture) {
|
|
12647
|
+
result.depthTexture.compareFunction = null;
|
|
12648
|
+
}
|
|
12649
|
+
return result;
|
|
12650
|
+
}
|
|
12651
|
+
/**
|
|
12652
|
+
* Override to use our PCSS filter instead of the default filter.
|
|
12653
|
+
*/
|
|
12654
|
+
getShadowFilterFn(_type) {
|
|
12655
|
+
return createPCSSFilter(this.size, this.samples, this.focus);
|
|
11721
12656
|
}
|
|
11722
12657
|
}
|
|
11723
|
-
|
|
11724
|
-
|
|
11725
|
-
|
|
11726
|
-
)
|
|
12658
|
+
|
|
12659
|
+
function SoftShadows({ size = 25, samples = 10, focus = 0 }) {
|
|
12660
|
+
const scene = useThree((state) => state.scene);
|
|
12661
|
+
React.useLayoutEffect(() => {
|
|
12662
|
+
const originalShadowNodes = /* @__PURE__ */ new Map();
|
|
12663
|
+
scene.traverse((obj) => {
|
|
12664
|
+
const light = obj;
|
|
12665
|
+
if (light.isLight && light.castShadow && light.shadow) {
|
|
12666
|
+
originalShadowNodes.set(light.uuid, light.shadow.shadowNode);
|
|
12667
|
+
light.shadow.shadowNode = new PCSSShadowNode(light, { size, samples, focus });
|
|
12668
|
+
}
|
|
12669
|
+
});
|
|
12670
|
+
return () => {
|
|
12671
|
+
scene.traverse((obj) => {
|
|
12672
|
+
const light = obj;
|
|
12673
|
+
if (originalShadowNodes.has(light.uuid)) {
|
|
12674
|
+
light.shadow.shadowNode = originalShadowNodes.get(light.uuid);
|
|
12675
|
+
}
|
|
12676
|
+
});
|
|
12677
|
+
};
|
|
12678
|
+
}, [scene, size, samples, focus]);
|
|
11727
12679
|
return null;
|
|
11728
12680
|
}
|
|
11729
12681
|
|
|
@@ -11985,4 +12937,4 @@ const Sparkles = /* @__PURE__ */ React.forwardRef(({ noise = 1, count = 100, spe
|
|
|
11985
12937
|
);
|
|
11986
12938
|
});
|
|
11987
12939
|
|
|
11988
|
-
export { AccumulativeShadows, AdaptiveDpr, AdaptiveEvents, ArcballControls, BBAnchor, Backdrop, BakeShadows, Billboard, Bounds, Box, CameraShake, Capsule, CatmullRomLine, Caustics, CausticsMaterial, CausticsNormalMaterial, CausticsProjectionMaterial, Center, Circle, Clone, Cloud, CloudInstance, Clouds, ComputedAttribute, Cone, ContactShadows, ConvolutionMaterial, CubeCamera, CubeTexture, CubicBezierLine, CurveModifier, CycleRaycast, Cylinder, Decal, Detailed, DetectGPU, DeviceOrientationControls, DiscardMaterial, Dodecahedron, DragControls, Edges, Environment, EnvironmentCube, EnvironmentMap, EnvironmentPortal, Example, Extrude, FakeCloudMaterial, Fbo, Fbx, FirstPersonControls, Fisheye, Float, FlyControls, GizmoHelper, GizmoViewcube, GizmoViewport, Gltf, GradientTexture, GradientType, Grid, Helper, Html, Hud, Icosahedron, Image, Instance, InstancedAttribute, Instances, IsObject, KeyboardControls, Ktx2, Lathe, Lightformer, Line, Loader, MapControls, Mask, MatcapTexture, Merged, MeshDistortMaterial, MeshPortalMaterial, MeshReflectorMaterial, MeshReflectorMaterial$1 as MeshReflectorMaterialImpl, MeshRefractionMaterial, MeshTransmissionMaterial, MeshWobbleMaterial, MotionPathControls, NormalTexture, Octahedron, OrbitControls, OrthographicCamera, Outlines, PerformanceMonitor, PerspectiveCamera, PivotControls, Plane, Point, PointMaterial, PointMaterialImpl, PointerLockControls, Points, PointsBuffer, Polyhedron, PositionMesh, PositionPoint, PositionalAudio, Preload, PresentationControls, Progress, QuadraticBezierLine, RandomizedLight, RenderCubeTexture, RenderTexture, Resize, Ring, RoundedBox, RoundedBoxGeometry, Sampler, ScreenQuad, ScreenSizer, ScreenSpace, ScreenVideoTexture, Scroll, ScrollControls, Segment, SegmentObject, Segments, Select, Shadow, Shape, Sky, SoftShadows, Sparkles, SparklesMaterial, Sphere, SpotLight, SpotLightMaterial, SpriteAnimator, Stage, StarfieldMaterial, Stars, Stats, StatsGl, Svg, Tetrahedron, Text3D, Texture, Torus, TorusKnot, TrackballControls, Trail, TrailTexture, TransformControls, Tube, VideoTexture, View, WebcamVideoTexture, Wireframe, WireframeMaterial, WireframeMaterialShaders, accumulativeContext, calcPosFromAngles, checkIfFrameIsEmpty, createInstances, getFirstFrame, meshBounds, presetsObj, setBarycentricCoordinates, setWireframeOverride, useAnimations, useAspect, useBounds, useContextBridge, useCubeCamera, useCubeTexture, useCursor, useCustomRaycast, useDepthBuffer, useDetectGPU, useEnvironment, useFBO, useFBX, useFont, useGLTF, useGizmoContext, useHelper, useIntersect, useKTX2, useKeyboardControls, useMask, useMatcapTexture, useMotion, useNormalTexture, usePerformanceMonitor, useProgress, useScroll, useSelect, useSpriteAnimator, useSpriteLoader, useSurfaceSampler, useTexture, useTrail, useTrailTexture, useVideoTexture, useWireframeUniforms };
|
|
12940
|
+
export { AccumulativeShadows, AdaptiveDpr, AdaptiveEvents, ArcballControls, BBAnchor, Backdrop, BakeShadows, Billboard, Bounds, Box, CameraShake, Capsule, CatmullRomLine, Caustics, CausticsMaterial, CausticsNormalMaterial, CausticsProjectionMaterial, Center, Circle, Clone, Cloud, CloudInstance, Clouds, ComputedAttribute, Cone, ContactShadows, ConvolutionMaterial, CubeCamera, CubeTexture, CubicBezierLine, CurveModifier, CycleRaycast, Cylinder, Decal, Detailed, DetectGPU, DeviceOrientationControls, DiscardMaterial, Dodecahedron, DragControls, Edges, Environment, EnvironmentCube, EnvironmentMap, EnvironmentPortal, Example, Extrude, FakeCloudMaterial, Fbo, Fbx, FirstPersonControls, Fisheye, Float, FlyControls, GizmoHelper, GizmoViewcube, GizmoViewport, Gltf, GradientTexture, GradientType, Grid, Helper, Html, HtmlMaterial, Hud, Icosahedron, Image, Instance, InstancedAttribute, Instances, IsObject, KeyboardControls, Ktx2, Lathe, Lightformer, Line, Loader, MapControls, Mask, MatcapTexture, Merged, MeshDistortMaterial, MeshPortalMaterial, MeshReflectorMaterial, MeshReflectorMaterial$1 as MeshReflectorMaterialImpl, MeshRefractionMaterial, MeshTransmissionMaterial, MeshWobbleMaterial, MotionPathControls, NormalTexture, Octahedron, OrbitControls, OrthographicCamera, Outlines, PCSSShadowNode, PerformanceMonitor, PerspectiveCamera, PivotControls, Plane, Point, PointMaterial, PointMaterialImpl, PointerLockControls, Points, PointsBuffer, Polyhedron, PositionMesh, PositionPoint, PositionalAudio, Preload, PresentationControls, Progress, QuadraticBezierLine, RandomizedLight, RenderCubeTexture, RenderTexture, Resize, Ring, RoundedBox, RoundedBoxGeometry, Sampler, ScreenQuad, ScreenSizer, ScreenSpace, ScreenVideoTexture, Scroll, ScrollControls, Segment, SegmentObject, Segments, Select, Shadow, Shape, Sky, SoftShadows, Sparkles, SparklesMaterial, Sphere, SpotLight, SpotLightMaterial, SpriteAnimator, Stage, StarfieldMaterial, Stars, Stats, StatsGl, Svg, Tetrahedron, Text3D, Texture, Torus, TorusKnot, TrackballControls, Trail, TrailTexture, TransformControls, Tube, VideoTexture, View, WebcamVideoTexture, Wireframe, WireframeMaterial, WireframeMaterialShaders, accumulativeContext, calcPosFromAngles, checkIfFrameIsEmpty, createInstances, getFirstFrame, meshBounds, presetsObj, setBarycentricCoordinates, setWireframeOverride, useAnimations, useAspect, useBounds, useContextBridge, useCubeCamera, useCubeTexture, useCursor, useCustomRaycast, useDepthBuffer, useDetectGPU, useEnvironment, useFBO, useFBX, useFont, useGLTF, useGizmoContext, useHelper, useIntersect, useKTX2, useKeyboardControls, useMask, useMatcapTexture, useMotion, useNormalTexture, usePerformanceMonitor, useProgress, useScroll, useSelect, useSpriteAnimator, useSpriteLoader, useSurfaceSampler, useTexture, useTrail, useTrailTexture, useVariants, useVideoTexture, useWireframeUniforms };
|