three-cad-viewer 4.3.6 → 4.3.8

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.
@@ -3,7 +3,7 @@
3
3
  * Copyright 2010-2026 Three.js Authors
4
4
  * SPDX-License-Identifier: MIT
5
5
  */
6
- const REVISION = '183';
6
+ const REVISION = '184';
7
7
 
8
8
  /**
9
9
  * Represents mouse buttons and interaction types in context of controls.
@@ -3005,13 +3005,7 @@ const MathUtils = {
3005
3005
  */
3006
3006
  class Vector2 {
3007
3007
 
3008
- /**
3009
- * Constructs a new 2D vector.
3010
- *
3011
- * @param {number} [x=0] - The x value of this vector.
3012
- * @param {number} [y=0] - The y value of this vector.
3013
- */
3014
- constructor( x = 0, y = 0 ) {
3008
+ static {
3015
3009
 
3016
3010
  /**
3017
3011
  * This flag can be used for type testing.
@@ -3022,6 +3016,16 @@ class Vector2 {
3022
3016
  */
3023
3017
  Vector2.prototype.isVector2 = true;
3024
3018
 
3019
+ }
3020
+
3021
+ /**
3022
+ * Constructs a new 2D vector.
3023
+ *
3024
+ * @param {number} [x=0] - The x value of this vector.
3025
+ * @param {number} [y=0] - The y value of this vector.
3026
+ */
3027
+ constructor( x = 0, y = 0 ) {
3028
+
3025
3029
  /**
3026
3030
  * The x value of this vector.
3027
3031
  *
@@ -4782,14 +4786,7 @@ class Quaternion {
4782
4786
  */
4783
4787
  class Vector3 {
4784
4788
 
4785
- /**
4786
- * Constructs a new 3D vector.
4787
- *
4788
- * @param {number} [x=0] - The x value of this vector.
4789
- * @param {number} [y=0] - The y value of this vector.
4790
- * @param {number} [z=0] - The z value of this vector.
4791
- */
4792
- constructor( x = 0, y = 0, z = 0 ) {
4789
+ static {
4793
4790
 
4794
4791
  /**
4795
4792
  * This flag can be used for type testing.
@@ -4800,6 +4797,17 @@ class Vector3 {
4800
4797
  */
4801
4798
  Vector3.prototype.isVector3 = true;
4802
4799
 
4800
+ }
4801
+
4802
+ /**
4803
+ * Constructs a new 3D vector.
4804
+ *
4805
+ * @param {number} [x=0] - The x value of this vector.
4806
+ * @param {number} [y=0] - The y value of this vector.
4807
+ * @param {number} [z=0] - The z value of this vector.
4808
+ */
4809
+ constructor( x = 0, y = 0, z = 0 ) {
4810
+
4803
4811
  /**
4804
4812
  * The x value of this vector.
4805
4813
  *
@@ -6040,6 +6048,19 @@ const _quaternion$5 = /*@__PURE__*/ new Quaternion();
6040
6048
  */
6041
6049
  class Matrix3 {
6042
6050
 
6051
+ static {
6052
+
6053
+ /**
6054
+ * This flag can be used for type testing.
6055
+ *
6056
+ * @type {boolean}
6057
+ * @readonly
6058
+ * @default true
6059
+ */
6060
+ Matrix3.prototype.isMatrix3 = true;
6061
+
6062
+ }
6063
+
6043
6064
  /**
6044
6065
  * Constructs a new 3x3 matrix. The arguments are supposed to be
6045
6066
  * in row-major order. If no arguments are provided, the constructor
@@ -6057,15 +6078,6 @@ class Matrix3 {
6057
6078
  */
6058
6079
  constructor( n11, n12, n13, n21, n22, n23, n31, n32, n33 ) {
6059
6080
 
6060
- /**
6061
- * This flag can be used for type testing.
6062
- *
6063
- * @type {boolean}
6064
- * @readonly
6065
- * @default true
6066
- */
6067
- Matrix3.prototype.isMatrix3 = true;
6068
-
6069
6081
  /**
6070
6082
  * A column-major list of matrix values.
6071
6083
  *
@@ -7055,7 +7067,7 @@ class Source {
7055
7067
 
7056
7068
  } else if ( ( typeof VideoFrame !== 'undefined' ) && ( data instanceof VideoFrame ) ) {
7057
7069
 
7058
- target.set( data.displayHeight, data.displayWidth, 0 );
7070
+ target.set( data.displayWidth, data.displayHeight, 0 );
7059
7071
 
7060
7072
  } else if ( data !== null ) {
7061
7073
 
@@ -7543,6 +7555,15 @@ class Texture extends EventDispatcher {
7543
7555
  */
7544
7556
  this.pmremVersion = 0;
7545
7557
 
7558
+ /**
7559
+ * Whether the texture should use one of the 16 bit integer formats which are normalized
7560
+ * to [0, 1] or [-1, 1] (depending on signed/unsigned) when sampled.
7561
+ *
7562
+ * @type {boolean}
7563
+ * @default false
7564
+ */
7565
+ this.normalized = false;
7566
+
7546
7567
  }
7547
7568
 
7548
7569
  /**
@@ -7583,14 +7604,14 @@ class Texture extends EventDispatcher {
7583
7604
 
7584
7605
  }
7585
7606
 
7586
- set image( value = null ) {
7607
+ set image( value ) {
7587
7608
 
7588
7609
  this.source.data = value;
7589
7610
 
7590
7611
  }
7591
7612
 
7592
7613
  /**
7593
- * Updates the texture transformation matrix from the from the properties {@link Texture#offset},
7614
+ * Updates the texture transformation matrix from the properties {@link Texture#offset},
7594
7615
  * {@link Texture#repeat}, {@link Texture#rotation}, and {@link Texture#center}.
7595
7616
  */
7596
7617
  updateMatrix() {
@@ -7658,6 +7679,7 @@ class Texture extends EventDispatcher {
7658
7679
  this.format = source.format;
7659
7680
  this.internalFormat = source.internalFormat;
7660
7681
  this.type = source.type;
7682
+ this.normalized = source.normalized;
7661
7683
 
7662
7684
  this.offset.copy( source.offset );
7663
7685
  this.repeat.copy( source.repeat );
@@ -7776,6 +7798,7 @@ class Texture extends EventDispatcher {
7776
7798
  format: this.format,
7777
7799
  internalFormat: this.internalFormat,
7778
7800
  type: this.type,
7801
+ normalized: this.normalized,
7779
7802
  colorSpace: this.colorSpace,
7780
7803
 
7781
7804
  minFilter: this.minFilter,
@@ -7999,15 +8022,7 @@ Texture.DEFAULT_ANISOTROPY = 1;
7999
8022
  */
8000
8023
  class Vector4 {
8001
8024
 
8002
- /**
8003
- * Constructs a new 4D vector.
8004
- *
8005
- * @param {number} [x=0] - The x value of this vector.
8006
- * @param {number} [y=0] - The y value of this vector.
8007
- * @param {number} [z=0] - The z value of this vector.
8008
- * @param {number} [w=1] - The w value of this vector.
8009
- */
8010
- constructor( x = 0, y = 0, z = 0, w = 1 ) {
8025
+ static {
8011
8026
 
8012
8027
  /**
8013
8028
  * This flag can be used for type testing.
@@ -8018,6 +8033,18 @@ class Vector4 {
8018
8033
  */
8019
8034
  Vector4.prototype.isVector4 = true;
8020
8035
 
8036
+ }
8037
+
8038
+ /**
8039
+ * Constructs a new 4D vector.
8040
+ *
8041
+ * @param {number} [x=0] - The x value of this vector.
8042
+ * @param {number} [y=0] - The y value of this vector.
8043
+ * @param {number} [z=0] - The z value of this vector.
8044
+ * @param {number} [w=1] - The w value of this vector.
8045
+ */
8046
+ constructor( x = 0, y = 0, z = 0, w = 1 ) {
8047
+
8021
8048
  /**
8022
8049
  * The x value of this vector.
8023
8050
  *
@@ -9398,6 +9425,7 @@ class RenderTarget extends EventDispatcher {
9398
9425
  if ( source.depthTexture !== null ) this.depthTexture = source.depthTexture.clone();
9399
9426
 
9400
9427
  this.samples = source.samples;
9428
+ this.multiview = source.multiview;
9401
9429
 
9402
9430
  return this;
9403
9431
 
@@ -9814,6 +9842,19 @@ class WebGL3DRenderTarget extends WebGLRenderTarget {
9814
9842
  */
9815
9843
  class Matrix4 {
9816
9844
 
9845
+ static {
9846
+
9847
+ /**
9848
+ * This flag can be used for type testing.
9849
+ *
9850
+ * @type {boolean}
9851
+ * @readonly
9852
+ * @default true
9853
+ */
9854
+ Matrix4.prototype.isMatrix4 = true;
9855
+
9856
+ }
9857
+
9817
9858
  /**
9818
9859
  * Constructs a new 4x4 matrix. The arguments are supposed to be
9819
9860
  * in row-major order. If no arguments are provided, the constructor
@@ -9838,15 +9879,6 @@ class Matrix4 {
9838
9879
  */
9839
9880
  constructor( n11, n12, n13, n14, n21, n22, n23, n24, n31, n32, n33, n34, n41, n42, n43, n44 ) {
9840
9881
 
9841
- /**
9842
- * This flag can be used for type testing.
9843
- *
9844
- * @type {boolean}
9845
- * @readonly
9846
- * @default true
9847
- */
9848
- Matrix4.prototype.isMatrix4 = true;
9849
-
9850
9882
  /**
9851
9883
  * A column-major list of matrix values.
9852
9884
  *
@@ -13226,11 +13258,7 @@ class Object3D extends EventDispatcher {
13226
13258
  this.quaternion.copy( source.quaternion );
13227
13259
  this.scale.copy( source.scale );
13228
13260
 
13229
- if ( source.pivot !== null ) {
13230
-
13231
- this.pivot = source.pivot.clone();
13232
-
13233
- }
13261
+ this.pivot = ( source.pivot !== null ) ? source.pivot.clone() : null;
13234
13262
 
13235
13263
  this.matrix.copy( source.matrix );
13236
13264
  this.matrixWorld.copy( source.matrixWorld );
@@ -13448,6 +13476,7 @@ class WebXRController {
13448
13476
  this._grip.linearVelocity = new Vector3();
13449
13477
  this._grip.hasAngularVelocity = false;
13450
13478
  this._grip.angularVelocity = new Vector3();
13479
+ this._grip.eventsEnabled = false;
13451
13480
 
13452
13481
  }
13453
13482
 
@@ -13660,6 +13689,17 @@ class WebXRController {
13660
13689
 
13661
13690
  }
13662
13691
 
13692
+ // grip update event if enabled
13693
+ if ( grip.eventsEnabled ) {
13694
+
13695
+ grip.dispatchEvent( {
13696
+ type: 'gripUpdated',
13697
+ data: inputSource,
13698
+ target: this
13699
+ } );
13700
+
13701
+ }
13702
+
13663
13703
  }
13664
13704
 
13665
13705
  }
@@ -15290,7 +15330,7 @@ class Triangle {
15290
15330
  _v1$5.subVectors( a, b );
15291
15331
 
15292
15332
  // strictly front facing
15293
- return ( _v0$2.cross( _v1$5 ).dot( direction ) < 0 ) ? true : false;
15333
+ return _v0$2.cross( _v1$5 ).dot( direction ) < 0;
15294
15334
 
15295
15335
  }
15296
15336
 
@@ -16622,7 +16662,7 @@ let _id$2 = 0;
16622
16662
  * When working with vector-like data, the `fromBufferAttribute( attribute, index )`
16623
16663
  * helper methods on vector and color class might be helpful. E.g. {@link Vector3#fromBufferAttribute}.
16624
16664
  */
16625
- class BufferAttribute {
16665
+ class BufferAttribute extends EventDispatcher {
16626
16666
 
16627
16667
  /**
16628
16668
  * Constructs a new buffer attribute.
@@ -16633,6 +16673,8 @@ class BufferAttribute {
16633
16673
  */
16634
16674
  constructor( array, itemSize, normalized = false ) {
16635
16675
 
16676
+ super();
16677
+
16636
16678
  if ( Array.isArray( array ) ) {
16637
16679
 
16638
16680
  throw new TypeError( 'THREE.BufferAttribute: array should be a Typed Array.' );
@@ -17279,6 +17321,15 @@ class BufferAttribute {
17279
17321
 
17280
17322
  }
17281
17323
 
17324
+ /**
17325
+ * Disposes of the buffer attribute. Available only in {@link WebGPURenderer}.
17326
+ */
17327
+ dispose() {
17328
+
17329
+ this.dispatchEvent( { type: 'dispose' } );
17330
+
17331
+ }
17332
+
17282
17333
  }
17283
17334
 
17284
17335
  /**
@@ -23402,12 +23453,12 @@ function checkGeometryIntersection( object, material, raycaster, ray, uv, uv1, n
23402
23453
 
23403
23454
  }
23404
23455
 
23405
- const _basePosition = /*@__PURE__*/ new Vector3();
23456
+ const _baseVector = /*@__PURE__*/ new Vector4();
23406
23457
 
23407
23458
  const _skinIndex = /*@__PURE__*/ new Vector4();
23408
23459
  const _skinWeight = /*@__PURE__*/ new Vector4();
23409
23460
 
23410
- const _vector3$1 = /*@__PURE__*/ new Vector3();
23461
+ const _vector4 = /*@__PURE__*/ new Vector4();
23411
23462
  const _matrix4 = /*@__PURE__*/ new Matrix4();
23412
23463
  const _vertex = /*@__PURE__*/ new Vector3();
23413
23464
 
@@ -23703,12 +23754,12 @@ class SkinnedMesh extends Mesh {
23703
23754
 
23704
23755
  /**
23705
23756
  * Applies the bone transform associated with the given index to the given
23706
- * vertex position. Returns the updated vector.
23757
+ * vector. Can be used to transform positions or direction vectors by providing
23758
+ * a Vector4 with 1 or 0 in the w component respectively. Returns the updated vector.
23707
23759
  *
23708
23760
  * @param {number} index - The vertex index.
23709
- * @param {Vector3} target - The target object that is used to store the method's result.
23710
- * the skinned mesh's world matrix will be used instead.
23711
- * @return {Vector3} The updated vertex position.
23761
+ * @param {Vector3|Vector4} target - The target object that is used to store the method's result.
23762
+ * @return {Vector3|Vector4} The updated vertex attribute data.
23712
23763
  */
23713
23764
  applyBoneTransform( index, target ) {
23714
23765
 
@@ -23718,9 +23769,19 @@ class SkinnedMesh extends Mesh {
23718
23769
  _skinIndex.fromBufferAttribute( geometry.attributes.skinIndex, index );
23719
23770
  _skinWeight.fromBufferAttribute( geometry.attributes.skinWeight, index );
23720
23771
 
23721
- _basePosition.copy( target ).applyMatrix4( this.bindMatrix );
23772
+ if ( target.isVector4 ) {
23773
+
23774
+ _baseVector.copy( target );
23775
+ target.set( 0, 0, 0, 0 );
23722
23776
 
23723
- target.set( 0, 0, 0 );
23777
+ } else {
23778
+
23779
+ _baseVector.set( ...target, 1 );
23780
+ target.set( 0, 0, 0 );
23781
+
23782
+ }
23783
+
23784
+ _baseVector.applyMatrix4( this.bindMatrix );
23724
23785
 
23725
23786
  for ( let i = 0; i < 4; i ++ ) {
23726
23787
 
@@ -23732,12 +23793,19 @@ class SkinnedMesh extends Mesh {
23732
23793
 
23733
23794
  _matrix4.multiplyMatrices( skeleton.bones[ boneIndex ].matrixWorld, skeleton.boneInverses[ boneIndex ] );
23734
23795
 
23735
- target.addScaledVector( _vector3$1.copy( _basePosition ).applyMatrix4( _matrix4 ), weight );
23796
+ target.addScaledVector( _vector4.copy( _baseVector ).applyMatrix4( _matrix4 ), weight );
23736
23797
 
23737
23798
  }
23738
23799
 
23739
23800
  }
23740
23801
 
23802
+ if ( target.isVector4 ) {
23803
+
23804
+ // ensure the homogenous coordinate remains unchanged after vector operations
23805
+ target.w = _baseVector.w;
23806
+
23807
+ }
23808
+
23741
23809
  return target.applyMatrix4( this.bindMatrixInverse );
23742
23810
 
23743
23811
  }
@@ -24518,10 +24586,19 @@ class InstancedMesh extends Mesh {
24518
24586
  *
24519
24587
  * @param {number} index - The instance index.
24520
24588
  * @param {Color} color - The target object that is used to store the method's result.
24589
+ * @return {Color} A reference to the target color.
24521
24590
  */
24522
24591
  getColorAt( index, color ) {
24523
24592
 
24524
- color.fromArray( this.instanceColor.array, index * 3 );
24593
+ if ( this.instanceColor === null ) {
24594
+
24595
+ return color.setRGB( 1, 1, 1 );
24596
+
24597
+ } else {
24598
+
24599
+ return color.fromArray( this.instanceColor.array, index * 3 );
24600
+
24601
+ }
24525
24602
 
24526
24603
  }
24527
24604
 
@@ -24530,10 +24607,11 @@ class InstancedMesh extends Mesh {
24530
24607
  *
24531
24608
  * @param {number} index - The instance index.
24532
24609
  * @param {Matrix4} matrix - The target object that is used to store the method's result.
24610
+ * @return {Matrix4} A reference to the target matrix.
24533
24611
  */
24534
24612
  getMatrixAt( index, matrix ) {
24535
24613
 
24536
- matrix.fromArray( this.instanceMatrix.array, index * 16 );
24614
+ return matrix.fromArray( this.instanceMatrix.array, index * 16 );
24537
24615
 
24538
24616
  }
24539
24617
 
@@ -24619,6 +24697,7 @@ class InstancedMesh extends Mesh {
24619
24697
  *
24620
24698
  * @param {number} index - The instance index.
24621
24699
  * @param {Color} color - The instance color.
24700
+ * @return {InstancedMesh} A reference to this instanced mesh.
24622
24701
  */
24623
24702
  setColorAt( index, color ) {
24624
24703
 
@@ -24629,19 +24708,22 @@ class InstancedMesh extends Mesh {
24629
24708
  }
24630
24709
 
24631
24710
  color.toArray( this.instanceColor.array, index * 3 );
24711
+ return this;
24632
24712
 
24633
24713
  }
24634
24714
 
24635
24715
  /**
24636
24716
  * Sets the given local transformation matrix to the defined instance. Make sure you set the `needsUpdate` flag of
24637
- * {@link InstancedMesh#instanceMatrix} to `true` after updating all the colors.
24717
+ * {@link InstancedMesh#instanceMatrix} to `true` after updating all the matrices.
24638
24718
  *
24639
24719
  * @param {number} index - The instance index.
24640
24720
  * @param {Matrix4} matrix - The local transformation.
24721
+ * @return {InstancedMesh} A reference to this instanced mesh.
24641
24722
  */
24642
24723
  setMatrixAt( index, matrix ) {
24643
24724
 
24644
24725
  matrix.toArray( this.instanceMatrix.array, index * 16 );
24726
+ return this;
24645
24727
 
24646
24728
  }
24647
24729
 
@@ -24652,6 +24734,7 @@ class InstancedMesh extends Mesh {
24652
24734
  * @param {number} index - The instance index.
24653
24735
  * @param {Mesh} object - A mesh which `morphTargetInfluences` property containing the morph target weights
24654
24736
  * of a single instance.
24737
+ * @return {InstancedMesh} A reference to this instanced mesh.
24655
24738
  */
24656
24739
  setMorphAt( index, object ) {
24657
24740
 
@@ -24682,6 +24765,7 @@ class InstancedMesh extends Mesh {
24682
24765
  array[ dataIndex ] = morphBaseInfluence;
24683
24766
 
24684
24767
  array.set( objectInfluences, dataIndex + 1 );
24768
+ return this;
24685
24769
 
24686
24770
  }
24687
24771
 
@@ -24917,9 +25001,10 @@ class Plane {
24917
25001
  *
24918
25002
  * @param {Line3} line - The line to compute the intersection for.
24919
25003
  * @param {Vector3} target - The target vector that is used to store the method's result.
24920
- * @return {?Vector3} The intersection point.
25004
+ * @param {boolean} [clampToLine=true] - Whether to clamp the intersection to the line segment.
25005
+ * @return {?Vector3} The intersection point. Returns `null` if no intersection is detected.
24921
25006
  */
24922
- intersectLine( line, target ) {
25007
+ intersectLine( line, target, clampToLine = true ) {
24923
25008
 
24924
25009
  const direction = line.delta( _vector1 );
24925
25010
 
@@ -24941,7 +25026,7 @@ class Plane {
24941
25026
 
24942
25027
  const t = - ( line.start.dot( this.normal ) + this.constant ) / denominator;
24943
25028
 
24944
- if ( t < 0 || t > 1 ) {
25029
+ if ( ( clampToLine === true ) && ( t < 0 || t > 1 ) ) {
24945
25030
 
24946
25031
  return null;
24947
25032
 
@@ -25861,7 +25946,6 @@ class BatchedMesh extends Mesh {
25861
25946
  this._multiDrawCounts = new Int32Array( maxInstanceCount );
25862
25947
  this._multiDrawStarts = new Int32Array( maxInstanceCount );
25863
25948
  this._multiDrawCount = 0;
25864
- this._multiDrawInstances = null;
25865
25949
 
25866
25950
  // Local matrix per geometry by using data texture
25867
25951
  this._matricesTexture = null;
@@ -26722,7 +26806,23 @@ class BatchedMesh extends Mesh {
26722
26806
  getColorAt( instanceId, color ) {
26723
26807
 
26724
26808
  this.validateInstanceId( instanceId );
26725
- return color.fromArray( this._colorsTexture.image.data, instanceId * 4 );
26809
+ if ( this._colorsTexture === null ) {
26810
+
26811
+ if ( color.isVector4 ) {
26812
+
26813
+ return color.set( 1, 1, 1, 1 );
26814
+
26815
+ } else {
26816
+
26817
+ return color.setRGB( 1, 1, 1 );
26818
+
26819
+ }
26820
+
26821
+ } else {
26822
+
26823
+ return color.fromArray( this._colorsTexture.image.data, instanceId * 4 );
26824
+
26825
+ }
26726
26826
 
26727
26827
  }
26728
26828
 
@@ -28749,6 +28849,77 @@ class CanvasTexture extends Texture {
28749
28849
 
28750
28850
  }
28751
28851
 
28852
+ /**
28853
+ * Creates a texture from an HTML element.
28854
+ *
28855
+ * This is almost the same as the base texture class, except that it sets {@link Texture#needsUpdate}
28856
+ * to `true` immediately and listens for the parent canvas's paint events to trigger updates.
28857
+ *
28858
+ * @augments Texture
28859
+ */
28860
+ class HTMLTexture extends Texture {
28861
+
28862
+ /**
28863
+ * Constructs a new texture.
28864
+ *
28865
+ * @param {HTMLElement} [element] - The HTML element.
28866
+ * @param {number} [mapping=Texture.DEFAULT_MAPPING] - The texture mapping.
28867
+ * @param {number} [wrapS=ClampToEdgeWrapping] - The wrapS value.
28868
+ * @param {number} [wrapT=ClampToEdgeWrapping] - The wrapT value.
28869
+ * @param {number} [magFilter=LinearFilter] - The mag filter value.
28870
+ * @param {number} [minFilter=LinearMipmapLinearFilter] - The min filter value.
28871
+ * @param {number} [format=RGBAFormat] - The texture format.
28872
+ * @param {number} [type=UnsignedByteType] - The texture type.
28873
+ * @param {number} [anisotropy=Texture.DEFAULT_ANISOTROPY] - The anisotropy value.
28874
+ */
28875
+ constructor( element, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy ) {
28876
+
28877
+ super( element, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy );
28878
+
28879
+ /**
28880
+ * This flag can be used for type testing.
28881
+ *
28882
+ * @type {boolean}
28883
+ * @readonly
28884
+ * @default true
28885
+ */
28886
+ this.isHTMLTexture = true;
28887
+ this.generateMipmaps = false;
28888
+
28889
+ this.needsUpdate = true;
28890
+
28891
+ const parent = element ? element.parentNode : null;
28892
+
28893
+ if ( parent !== null && 'requestPaint' in parent ) {
28894
+
28895
+ parent.onpaint = () => {
28896
+
28897
+ this.needsUpdate = true;
28898
+
28899
+ };
28900
+
28901
+ parent.requestPaint();
28902
+
28903
+ }
28904
+
28905
+ }
28906
+
28907
+ dispose() {
28908
+
28909
+ const parent = this.image ? this.image.parentNode : null;
28910
+
28911
+ if ( parent !== null && 'onpaint' in parent ) {
28912
+
28913
+ parent.onpaint = null;
28914
+
28915
+ }
28916
+
28917
+ super.dispose();
28918
+
28919
+ }
28920
+
28921
+ }
28922
+
28752
28923
  /**
28753
28924
  * This class can be used to automatically save the depth information of a
28754
28925
  * rendering into a texture.
@@ -31414,6 +31585,7 @@ function CubicPoly() {
31414
31585
  //
31415
31586
 
31416
31587
  const tmp = /*@__PURE__*/ new Vector3();
31588
+ const tmp2 = /*@__PURE__*/ new Vector3();
31417
31589
  const px$1 = /*@__PURE__*/ new CubicPoly();
31418
31590
  const py = /*@__PURE__*/ new CubicPoly();
31419
31591
  const pz = /*@__PURE__*/ new CubicPoly();
@@ -31538,8 +31710,8 @@ class CatmullRomCurve3 extends Curve {
31538
31710
  } else {
31539
31711
 
31540
31712
  // extrapolate first point
31541
- tmp.subVectors( points[ 0 ], points[ 1 ] ).add( points[ 0 ] );
31542
- p0 = tmp;
31713
+ tmp2.subVectors( points[ 0 ], points[ 1 ] ).add( points[ 0 ] );
31714
+ p0 = tmp2;
31543
31715
 
31544
31716
  }
31545
31717
 
@@ -37122,10 +37294,7 @@ function cloneUniforms( src ) {
37122
37294
 
37123
37295
  const property = src[ u ][ p ];
37124
37296
 
37125
- if ( property && ( property.isColor ||
37126
- property.isMatrix3 || property.isMatrix4 ||
37127
- property.isVector2 || property.isVector3 || property.isVector4 ||
37128
- property.isTexture || property.isQuaternion ) ) {
37297
+ if ( isThreeObject( property ) ) {
37129
37298
 
37130
37299
  if ( property.isRenderTargetTexture ) {
37131
37300
 
@@ -37140,7 +37309,23 @@ function cloneUniforms( src ) {
37140
37309
 
37141
37310
  } else if ( Array.isArray( property ) ) {
37142
37311
 
37143
- dst[ u ][ p ] = property.slice();
37312
+ if ( isThreeObject( property[ 0 ] ) ) {
37313
+
37314
+ const clonedProperty = [];
37315
+
37316
+ for ( let i = 0, l = property.length; i < l; i ++ ) {
37317
+
37318
+ clonedProperty[ i ] = property[ i ].clone();
37319
+
37320
+ }
37321
+
37322
+ dst[ u ][ p ] = clonedProperty;
37323
+
37324
+ } else {
37325
+
37326
+ dst[ u ][ p ] = property.slice();
37327
+
37328
+ }
37144
37329
 
37145
37330
  } else {
37146
37331
 
@@ -37184,6 +37369,15 @@ function mergeUniforms( uniforms ) {
37184
37369
 
37185
37370
  }
37186
37371
 
37372
+ function isThreeObject( property ) {
37373
+
37374
+ return ( property && ( property.isColor ||
37375
+ property.isMatrix3 || property.isMatrix4 ||
37376
+ property.isVector2 || property.isVector3 || property.isVector4 ||
37377
+ property.isTexture || property.isQuaternion ) );
37378
+
37379
+ }
37380
+
37187
37381
  function cloneUniformsGroups( src ) {
37188
37382
 
37189
37383
  const dst = [];
@@ -39078,7 +39272,7 @@ class MeshToonMaterial extends Material {
39078
39272
 
39079
39273
  /**
39080
39274
  * Gradient map for toon shading. It's required to set
39081
- * {@link Texture#minFilter} and {@link Texture#magFilter} to {@linkNearestFilter}
39275
+ * {@link Texture#minFilter} and {@link Texture#magFilter} to {@link NearestFilter}
39082
39276
  * when using this type of texture.
39083
39277
  *
39084
39278
  * @type {?Texture}
@@ -43878,7 +44072,6 @@ class FileLoader extends Loader {
43878
44072
  * @param {function(any)} onLoad - Executed when the loading process has been finished.
43879
44073
  * @param {onProgressCallback} [onProgress] - Executed while the loading is in progress.
43880
44074
  * @param {onErrorCallback} [onError] - Executed when errors occur.
43881
- * @return {any|undefined} The cached resource if available.
43882
44075
  */
43883
44076
  load( url, onLoad, onProgress, onError ) {
43884
44077
 
@@ -43902,7 +44095,7 @@ class FileLoader extends Loader {
43902
44095
 
43903
44096
  }, 0 );
43904
44097
 
43905
- return cached;
44098
+ return;
43906
44099
 
43907
44100
  }
43908
44101
 
@@ -44719,19 +44912,20 @@ class DataTextureLoader extends Loader {
44719
44912
 
44720
44913
  texData = scope.parse( buffer );
44721
44914
 
44722
- } catch ( error ) {
44915
+ } catch ( e ) {
44723
44916
 
44724
44917
  if ( onError !== undefined ) {
44725
44918
 
44726
- onError( error );
44919
+ onError( e );
44727
44920
 
44728
44921
  } else {
44729
44922
 
44730
- error( error );
44731
- return;
44923
+ error( e );
44732
44924
 
44733
44925
  }
44734
44926
 
44927
+ return;
44928
+
44735
44929
  }
44736
44930
 
44737
44931
  if ( texData.image !== undefined ) {
@@ -47465,7 +47659,7 @@ class MaterialLoader extends Loader {
47465
47659
 
47466
47660
  if ( typeof json.vertexColors === 'number' ) {
47467
47661
 
47468
- material.vertexColors = ( json.vertexColors > 0 ) ? true : false;
47662
+ material.vertexColors = json.vertexColors > 0;
47469
47663
 
47470
47664
  } else {
47471
47665
 
@@ -48031,6 +48225,8 @@ class BufferGeometryLoader extends Loader {
48031
48225
 
48032
48226
  }
48033
48227
 
48228
+ const _customGeometries = {};
48229
+
48034
48230
  /**
48035
48231
  * A loader for loading a JSON resource in the [JSON Object/Scene format](https://github.com/mrdoob/three.js/wiki/JSON-Object-Scene-format-4).
48036
48232
  * The files are internally loaded via {@link FileLoader}.
@@ -48087,11 +48283,11 @@ class ObjectLoader extends Loader {
48087
48283
 
48088
48284
  json = JSON.parse( text );
48089
48285
 
48090
- } catch ( error ) {
48286
+ } catch ( e ) {
48091
48287
 
48092
- if ( onError !== undefined ) onError( error );
48288
+ if ( onError !== undefined ) onError( e );
48093
48289
 
48094
- error( 'ObjectLoader: Can\'t parse ' + url + '.', error.message );
48290
+ error( 'ObjectLoader: Can\'t parse ' + url + '.', e.message );
48095
48291
 
48096
48292
  return;
48097
48293
 
@@ -48241,6 +48437,20 @@ class ObjectLoader extends Loader {
48241
48437
 
48242
48438
  }
48243
48439
 
48440
+ /**
48441
+ * Registers the given geometry at the internal
48442
+ * geometry library.
48443
+ *
48444
+ * @static
48445
+ * @param {string} type - The geometry type.
48446
+ * @param {BufferGeometry.constructor} geometryClass - The geometry class.
48447
+ */
48448
+ static registerGeometry( type, geometryClass ) {
48449
+
48450
+ _customGeometries[ type ] = geometryClass;
48451
+
48452
+ }
48453
+
48244
48454
  // internals
48245
48455
 
48246
48456
  parseShapes( json ) {
@@ -48321,9 +48531,13 @@ class ObjectLoader extends Loader {
48321
48531
 
48322
48532
  geometry = Geometries[ data.type ].fromJSON( data, shapes );
48323
48533
 
48534
+ } else if ( data.type in _customGeometries ) {
48535
+
48536
+ geometry = _customGeometries[ data.type ].fromJSON( data, shapes );
48537
+
48324
48538
  } else {
48325
48539
 
48326
- warn( `ObjectLoader: Unsupported geometry type "${ data.type }"` );
48540
+ warn( `ObjectLoader: Unknown geometry type "${ data.type }". Use .registerGeometry() before starting the deserialization process.` );
48327
48541
 
48328
48542
  }
48329
48543
 
@@ -48703,6 +48917,7 @@ class ObjectLoader extends Loader {
48703
48917
  if ( data.premultiplyAlpha !== undefined ) texture.premultiplyAlpha = data.premultiplyAlpha;
48704
48918
  if ( data.unpackAlignment !== undefined ) texture.unpackAlignment = data.unpackAlignment;
48705
48919
  if ( data.compareFunction !== undefined ) texture.compareFunction = data.compareFunction;
48920
+ if ( data.normalized !== undefined ) texture.normalized = data.normalized;
48706
48921
 
48707
48922
  if ( data.userData !== undefined ) texture.userData = data.userData;
48708
48923
 
@@ -49330,6 +49545,9 @@ class ImageBitmapLoader extends Loader {
49330
49545
  * Sets the given loader options. The structure of the object must match the `options` parameter of
49331
49546
  * [createImageBitmap](https://developer.mozilla.org/en-US/docs/Web/API/Window/createImageBitmap).
49332
49547
  *
49548
+ * Note: When caching is enabled, the cache key is based on the URL only. Loading the same URL with
49549
+ * different options will return the cached result of the first request.
49550
+ *
49333
49551
  * @param {Object} options - The loader options to set.
49334
49552
  * @return {ImageBitmapLoader} A reference to this image bitmap loader.
49335
49553
  */
@@ -49348,7 +49566,6 @@ class ImageBitmapLoader extends Loader {
49348
49566
  * @param {function(ImageBitmap)} onLoad - Executed when the loading process has been finished.
49349
49567
  * @param {onProgressCallback} onProgress - Unsupported in this loader.
49350
49568
  * @param {onErrorCallback} onError - Executed when errors occur.
49351
- * @return {ImageBitmap|undefined} The image bitmap.
49352
49569
  */
49353
49570
  load( url, onLoad, onProgress, onError ) {
49354
49571
 
@@ -49386,8 +49603,6 @@ class ImageBitmapLoader extends Loader {
49386
49603
 
49387
49604
  scope.manager.itemEnd( url );
49388
49605
 
49389
- return imageBitmap;
49390
-
49391
49606
  }
49392
49607
 
49393
49608
  } );
@@ -49405,7 +49620,7 @@ class ImageBitmapLoader extends Loader {
49405
49620
 
49406
49621
  }, 0 );
49407
49622
 
49408
- return cached;
49623
+ return;
49409
49624
 
49410
49625
  }
49411
49626
 
@@ -49430,8 +49645,6 @@ class ImageBitmapLoader extends Loader {
49430
49645
 
49431
49646
  scope.manager.itemEnd( url );
49432
49647
 
49433
- return imageBitmap;
49434
-
49435
49648
  } ).catch( function ( e ) {
49436
49649
 
49437
49650
  if ( onError ) onError( e );
@@ -49478,7 +49691,7 @@ class AudioContext {
49478
49691
  /**
49479
49692
  * Returns the global native audio context.
49480
49693
  *
49481
- * @return {AudioContext} The native audio context.
49694
+ * @return {Window.AudioContext} The native audio context.
49482
49695
  */
49483
49696
  static getContext() {
49484
49697
 
@@ -49495,7 +49708,7 @@ class AudioContext {
49495
49708
  /**
49496
49709
  * Allows to set the global native audio context from outside.
49497
49710
  *
49498
- * @param {AudioContext} value - The native context to set.
49711
+ * @param {Window.AudioContext} value - The native context to set.
49499
49712
  */
49500
49713
  static setContext( value ) {
49501
49714
 
@@ -49562,11 +49775,21 @@ class AudioLoader extends Loader {
49562
49775
  const bufferCopy = buffer.slice( 0 );
49563
49776
 
49564
49777
  const context = AudioContext.getContext();
49778
+
49779
+ const decodeUrl = url + '#decode';
49780
+ scope.manager.itemStart( decodeUrl ); // prevent loading manager from completing too early, see #33378
49781
+
49565
49782
  context.decodeAudioData( bufferCopy, function ( audioBuffer ) {
49566
49783
 
49567
49784
  onLoad( audioBuffer );
49785
+ scope.manager.itemEnd( decodeUrl );
49786
+
49787
+ } ).catch( function ( e ) {
49568
49788
 
49569
- } ).catch( handleError );
49789
+ handleError( e );
49790
+ scope.manager.itemEnd( decodeUrl );
49791
+
49792
+ } );
49570
49793
 
49571
49794
  } catch ( e ) {
49572
49795
 
@@ -50043,135 +50266,186 @@ class ArrayCamera extends PerspectiveCamera {
50043
50266
  }
50044
50267
 
50045
50268
  /**
50046
- * Class for keeping track of time.
50269
+ * This class is an alternative to {@link Clock} with a different API design and behavior.
50270
+ * The goal is to avoid the conceptual flaws that became apparent in `Clock` over time.
50047
50271
  *
50048
- * @deprecated since r183.
50272
+ * - `Timer` has an `update()` method that updates its internal state. That makes it possible to
50273
+ * call `getDelta()` and `getElapsed()` multiple times per simulation step without getting different values.
50274
+ * - The class can make use of the Page Visibility API to avoid large time delta values when the app
50275
+ * is inactive (e.g. tab switched or browser hidden).
50276
+ *
50277
+ * ```js
50278
+ * const timer = new Timer();
50279
+ * timer.connect( document ); // use Page Visibility API
50280
+ * ```
50049
50281
  */
50050
- class Clock {
50282
+ let Timer$2 = class Timer {
50051
50283
 
50052
50284
  /**
50053
- * Constructs a new clock.
50285
+ * Constructs a new timer.
50286
+ */
50287
+ constructor() {
50288
+
50289
+ this._previousTime = 0;
50290
+ this._currentTime = 0;
50291
+ this._startTime = performance.now();
50292
+
50293
+ this._delta = 0;
50294
+ this._elapsed = 0;
50295
+
50296
+ this._timescale = 1;
50297
+
50298
+ this._document = null;
50299
+ this._pageVisibilityHandler = null;
50300
+
50301
+ }
50302
+
50303
+ /**
50304
+ * Connect the timer to the given document.Calling this method is not mandatory to
50305
+ * use the timer but enables the usage of the Page Visibility API to avoid large time
50306
+ * delta values.
50054
50307
  *
50055
- * @deprecated since 183.
50056
- * @param {boolean} [autoStart=true] - Whether to automatically start the clock when
50057
- * `getDelta()` is called for the first time.
50308
+ * @param {Document} document - The document.
50058
50309
  */
50059
- constructor( autoStart = true ) {
50310
+ connect( document ) {
50060
50311
 
50061
- /**
50062
- * If set to `true`, the clock starts automatically when `getDelta()` is called
50063
- * for the first time.
50064
- *
50065
- * @type {boolean}
50066
- * @default true
50067
- */
50068
- this.autoStart = autoStart;
50312
+ this._document = document;
50069
50313
 
50070
- /**
50071
- * Holds the time at which the clock's `start()` method was last called.
50072
- *
50073
- * @type {number}
50074
- * @default 0
50075
- */
50076
- this.startTime = 0;
50314
+ // use Page Visibility API to avoid large time delta values
50077
50315
 
50078
- /**
50079
- * Holds the time at which the clock's `start()`, `getElapsedTime()` or
50080
- * `getDelta()` methods were last called.
50081
- *
50082
- * @type {number}
50083
- * @default 0
50084
- */
50085
- this.oldTime = 0;
50316
+ if ( document.hidden !== undefined ) {
50086
50317
 
50087
- /**
50088
- * Keeps track of the total time that the clock has been running.
50089
- *
50090
- * @type {number}
50091
- * @default 0
50092
- */
50093
- this.elapsedTime = 0;
50318
+ this._pageVisibilityHandler = handleVisibilityChange.bind( this );
50094
50319
 
50095
- /**
50096
- * Whether the clock is running or not.
50097
- *
50098
- * @type {boolean}
50099
- * @default true
50100
- */
50101
- this.running = false;
50320
+ document.addEventListener( 'visibilitychange', this._pageVisibilityHandler, false );
50102
50321
 
50103
- warn( 'THREE.Clock: This module has been deprecated. Please use THREE.Timer instead.' ); // @deprecated, r183
50322
+ }
50104
50323
 
50105
50324
  }
50106
50325
 
50107
50326
  /**
50108
- * Starts the clock. When `autoStart` is set to `true`, the method is automatically
50109
- * called by the class.
50327
+ * Disconnects the timer from the DOM and also disables the usage of the Page Visibility API.
50110
50328
  */
50111
- start() {
50329
+ disconnect() {
50112
50330
 
50113
- this.startTime = performance.now();
50331
+ if ( this._pageVisibilityHandler !== null ) {
50114
50332
 
50115
- this.oldTime = this.startTime;
50116
- this.elapsedTime = 0;
50117
- this.running = true;
50333
+ this._document.removeEventListener( 'visibilitychange', this._pageVisibilityHandler );
50334
+ this._pageVisibilityHandler = null;
50335
+
50336
+ }
50337
+
50338
+ this._document = null;
50118
50339
 
50119
50340
  }
50120
50341
 
50121
50342
  /**
50122
- * Stops the clock.
50343
+ * Returns the time delta in seconds.
50344
+ *
50345
+ * @return {number} The time delta in second.
50123
50346
  */
50124
- stop() {
50347
+ getDelta() {
50125
50348
 
50126
- this.getElapsedTime();
50127
- this.running = false;
50128
- this.autoStart = false;
50349
+ return this._delta / 1000;
50129
50350
 
50130
50351
  }
50131
50352
 
50132
50353
  /**
50133
50354
  * Returns the elapsed time in seconds.
50134
50355
  *
50135
- * @return {number} The elapsed time.
50356
+ * @return {number} The elapsed time in second.
50136
50357
  */
50137
- getElapsedTime() {
50358
+ getElapsed() {
50138
50359
 
50139
- this.getDelta();
50140
- return this.elapsedTime;
50360
+ return this._elapsed / 1000;
50141
50361
 
50142
50362
  }
50143
50363
 
50144
50364
  /**
50145
- * Returns the delta time in seconds.
50365
+ * Returns the timescale.
50146
50366
  *
50147
- * @return {number} The delta time.
50367
+ * @return {number} The timescale.
50148
50368
  */
50149
- getDelta() {
50369
+ getTimescale() {
50150
50370
 
50151
- let diff = 0;
50371
+ return this._timescale;
50152
50372
 
50153
- if ( this.autoStart && ! this.running ) {
50373
+ }
50154
50374
 
50155
- this.start();
50156
- return 0;
50375
+ /**
50376
+ * Sets the given timescale which scale the time delta computation
50377
+ * in `update()`.
50378
+ *
50379
+ * @param {number} timescale - The timescale to set.
50380
+ * @return {Timer} A reference to this timer.
50381
+ */
50382
+ setTimescale( timescale ) {
50157
50383
 
50158
- }
50384
+ this._timescale = timescale;
50159
50385
 
50160
- if ( this.running ) {
50386
+ return this;
50161
50387
 
50162
- const newTime = performance.now();
50388
+ }
50163
50389
 
50164
- diff = ( newTime - this.oldTime ) / 1000;
50165
- this.oldTime = newTime;
50390
+ /**
50391
+ * Resets the time computation for the current simulation step.
50392
+ *
50393
+ * @return {Timer} A reference to this timer.
50394
+ */
50395
+ reset() {
50166
50396
 
50167
- this.elapsedTime += diff;
50397
+ this._currentTime = performance.now() - this._startTime;
50398
+
50399
+ return this;
50400
+
50401
+ }
50402
+
50403
+ /**
50404
+ * Can be used to free all internal resources. Usually called when
50405
+ * the timer instance isn't required anymore.
50406
+ */
50407
+ dispose() {
50408
+
50409
+ this.disconnect();
50410
+
50411
+ }
50412
+
50413
+ /**
50414
+ * Updates the internal state of the timer. This method should be called
50415
+ * once per simulation step and before you perform queries against the timer
50416
+ * (e.g. via `getDelta()`).
50417
+ *
50418
+ * @param {number} timestamp - The current time in milliseconds. Can be obtained
50419
+ * from the `requestAnimationFrame` callback argument. If not provided, the current
50420
+ * time will be determined with `performance.now`.
50421
+ * @return {Timer} A reference to this timer.
50422
+ */
50423
+ update( timestamp ) {
50424
+
50425
+ if ( this._pageVisibilityHandler !== null && this._document.hidden === true ) {
50426
+
50427
+ this._delta = 0;
50428
+
50429
+ } else {
50430
+
50431
+ this._previousTime = this._currentTime;
50432
+ this._currentTime = ( timestamp !== undefined ? timestamp : performance.now() ) - this._startTime;
50433
+
50434
+ this._delta = ( this._currentTime - this._previousTime ) * this._timescale;
50435
+ this._elapsed += this._delta; // _elapsed is the accumulation of all previous deltas
50168
50436
 
50169
50437
  }
50170
50438
 
50171
- return diff;
50439
+ return this;
50172
50440
 
50173
50441
  }
50174
50442
 
50443
+ };
50444
+
50445
+ function handleVisibilityChange() {
50446
+
50447
+ if ( this._document.hidden === false ) this.reset();
50448
+
50175
50449
  }
50176
50450
 
50177
50451
  const _position$1 = /*@__PURE__*/ new Vector3();
@@ -50241,7 +50515,7 @@ class AudioListener extends Object3D {
50241
50515
 
50242
50516
  // private
50243
50517
 
50244
- this._clock = new Clock();
50518
+ this._timer = new Timer$2();
50245
50519
 
50246
50520
  }
50247
50521
 
@@ -50346,9 +50620,11 @@ class AudioListener extends Object3D {
50346
50620
 
50347
50621
  super.updateMatrixWorld( force );
50348
50622
 
50623
+ this._timer.update();
50624
+
50349
50625
  const listener = this.context.listener;
50350
50626
 
50351
- this.timeDelta = this._clock.getDelta();
50627
+ this.timeDelta = this._timer.getDelta();
50352
50628
 
50353
50629
  this.matrixWorld.decompose( _position$1, _quaternion$1$1, _scale$1 );
50354
50630
 
@@ -53120,6 +53396,15 @@ class AnimationAction {
53120
53396
 
53121
53397
  const interpolant = tracks[ i ].createInterpolant( null );
53122
53398
  interpolants[ i ] = interpolant;
53399
+
53400
+ // preserve interpolant settings (like tangent data from BezierInterpolant)
53401
+
53402
+ if ( interpolant.settings ) {
53403
+
53404
+ Object.assign( interpolantSettings, interpolant.settings );
53405
+
53406
+ }
53407
+
53123
53408
  interpolant.settings = interpolantSettings;
53124
53409
 
53125
53410
  }
@@ -53926,6 +54211,7 @@ class AnimationAction {
53926
54211
 
53927
54212
  } else {
53928
54213
 
54214
+ this._loopCount = loopCount;
53929
54215
  this.time = time;
53930
54216
 
53931
54217
  }
@@ -53973,7 +54259,7 @@ class AnimationAction {
53973
54259
 
53974
54260
  } else {
53975
54261
 
53976
- settings.endingEnd = WrapAroundEnding;
54262
+ settings.endingEnd = WrapAroundEnding;
53977
54263
 
53978
54264
  }
53979
54265
 
@@ -55621,186 +55907,135 @@ function intersect( object, raycaster, intersects, recursive ) {
55621
55907
  }
55622
55908
 
55623
55909
  /**
55624
- * This class is an alternative to {@link Clock} with a different API design and behavior.
55625
- * The goal is to avoid the conceptual flaws that became apparent in `Clock` over time.
55626
- *
55627
- * - `Timer` has an `update()` method that updates its internal state. That makes it possible to
55628
- * call `getDelta()` and `getElapsed()` multiple times per simulation step without getting different values.
55629
- * - The class can make use of the Page Visibility API to avoid large time delta values when the app
55630
- * is inactive (e.g. tab switched or browser hidden).
55910
+ * Class for keeping track of time.
55631
55911
  *
55632
- * ```js
55633
- * const timer = new Timer();
55634
- * timer.connect( document ); // use Page Visibility API
55635
- * ```
55912
+ * @deprecated since r183.
55636
55913
  */
55637
- let Timer$2 = class Timer {
55638
-
55639
- /**
55640
- * Constructs a new timer.
55641
- */
55642
- constructor() {
55643
-
55644
- this._previousTime = 0;
55645
- this._currentTime = 0;
55646
- this._startTime = performance.now();
55647
-
55648
- this._delta = 0;
55649
- this._elapsed = 0;
55650
-
55651
- this._timescale = 1;
55652
-
55653
- this._document = null;
55654
- this._pageVisibilityHandler = null;
55655
-
55656
- }
55914
+ class Clock {
55657
55915
 
55658
55916
  /**
55659
- * Connect the timer to the given document.Calling this method is not mandatory to
55660
- * use the timer but enables the usage of the Page Visibility API to avoid large time
55661
- * delta values.
55917
+ * Constructs a new clock.
55662
55918
  *
55663
- * @param {Document} document - The document.
55919
+ * @deprecated since 183.
55920
+ * @param {boolean} [autoStart=true] - Whether to automatically start the clock when
55921
+ * `getDelta()` is called for the first time.
55664
55922
  */
55665
- connect( document ) {
55923
+ constructor( autoStart = true ) {
55666
55924
 
55667
- this._document = document;
55925
+ /**
55926
+ * If set to `true`, the clock starts automatically when `getDelta()` is called
55927
+ * for the first time.
55928
+ *
55929
+ * @type {boolean}
55930
+ * @default true
55931
+ */
55932
+ this.autoStart = autoStart;
55668
55933
 
55669
- // use Page Visibility API to avoid large time delta values
55934
+ /**
55935
+ * Holds the time at which the clock's `start()` method was last called.
55936
+ *
55937
+ * @type {number}
55938
+ * @default 0
55939
+ */
55940
+ this.startTime = 0;
55670
55941
 
55671
- if ( document.hidden !== undefined ) {
55942
+ /**
55943
+ * Holds the time at which the clock's `start()`, `getElapsedTime()` or
55944
+ * `getDelta()` methods were last called.
55945
+ *
55946
+ * @type {number}
55947
+ * @default 0
55948
+ */
55949
+ this.oldTime = 0;
55672
55950
 
55673
- this._pageVisibilityHandler = handleVisibilityChange.bind( this );
55951
+ /**
55952
+ * Keeps track of the total time that the clock has been running.
55953
+ *
55954
+ * @type {number}
55955
+ * @default 0
55956
+ */
55957
+ this.elapsedTime = 0;
55674
55958
 
55675
- document.addEventListener( 'visibilitychange', this._pageVisibilityHandler, false );
55959
+ /**
55960
+ * Whether the clock is running or not.
55961
+ *
55962
+ * @type {boolean}
55963
+ * @default true
55964
+ */
55965
+ this.running = false;
55676
55966
 
55677
- }
55967
+ warn( 'Clock: This module has been deprecated. Please use THREE.Timer instead.' ); // @deprecated, r183
55678
55968
 
55679
55969
  }
55680
55970
 
55681
55971
  /**
55682
- * Disconnects the timer from the DOM and also disables the usage of the Page Visibility API.
55972
+ * Starts the clock. When `autoStart` is set to `true`, the method is automatically
55973
+ * called by the class.
55683
55974
  */
55684
- disconnect() {
55685
-
55686
- if ( this._pageVisibilityHandler !== null ) {
55687
-
55688
- this._document.removeEventListener( 'visibilitychange', this._pageVisibilityHandler );
55689
- this._pageVisibilityHandler = null;
55975
+ start() {
55690
55976
 
55691
- }
55977
+ this.startTime = performance.now();
55692
55978
 
55693
- this._document = null;
55979
+ this.oldTime = this.startTime;
55980
+ this.elapsedTime = 0;
55981
+ this.running = true;
55694
55982
 
55695
55983
  }
55696
55984
 
55697
55985
  /**
55698
- * Returns the time delta in seconds.
55699
- *
55700
- * @return {number} The time delta in second.
55986
+ * Stops the clock.
55701
55987
  */
55702
- getDelta() {
55988
+ stop() {
55703
55989
 
55704
- return this._delta / 1000;
55990
+ this.getElapsedTime();
55991
+ this.running = false;
55992
+ this.autoStart = false;
55705
55993
 
55706
55994
  }
55707
55995
 
55708
55996
  /**
55709
55997
  * Returns the elapsed time in seconds.
55710
55998
  *
55711
- * @return {number} The elapsed time in second.
55712
- */
55713
- getElapsed() {
55714
-
55715
- return this._elapsed / 1000;
55716
-
55717
- }
55718
-
55719
- /**
55720
- * Returns the timescale.
55721
- *
55722
- * @return {number} The timescale.
55723
- */
55724
- getTimescale() {
55725
-
55726
- return this._timescale;
55727
-
55728
- }
55729
-
55730
- /**
55731
- * Sets the given timescale which scale the time delta computation
55732
- * in `update()`.
55733
- *
55734
- * @param {number} timescale - The timescale to set.
55735
- * @return {Timer} A reference to this timer.
55999
+ * @return {number} The elapsed time.
55736
56000
  */
55737
- setTimescale( timescale ) {
55738
-
55739
- this._timescale = timescale;
56001
+ getElapsedTime() {
55740
56002
 
55741
- return this;
56003
+ this.getDelta();
56004
+ return this.elapsedTime;
55742
56005
 
55743
56006
  }
55744
56007
 
55745
56008
  /**
55746
- * Resets the time computation for the current simulation step.
56009
+ * Returns the delta time in seconds.
55747
56010
  *
55748
- * @return {Timer} A reference to this timer.
55749
- */
55750
- reset() {
55751
-
55752
- this._currentTime = performance.now() - this._startTime;
55753
-
55754
- return this;
55755
-
55756
- }
55757
-
55758
- /**
55759
- * Can be used to free all internal resources. Usually called when
55760
- * the timer instance isn't required anymore.
56011
+ * @return {number} The delta time.
55761
56012
  */
55762
- dispose() {
56013
+ getDelta() {
55763
56014
 
55764
- this.disconnect();
56015
+ let diff = 0;
55765
56016
 
55766
- }
56017
+ if ( this.autoStart && ! this.running ) {
55767
56018
 
55768
- /**
55769
- * Updates the internal state of the timer. This method should be called
55770
- * once per simulation step and before you perform queries against the timer
55771
- * (e.g. via `getDelta()`).
55772
- *
55773
- * @param {number} timestamp - The current time in milliseconds. Can be obtained
55774
- * from the `requestAnimationFrame` callback argument. If not provided, the current
55775
- * time will be determined with `performance.now`.
55776
- * @return {Timer} A reference to this timer.
55777
- */
55778
- update( timestamp ) {
56019
+ this.start();
56020
+ return 0;
55779
56021
 
55780
- if ( this._pageVisibilityHandler !== null && this._document.hidden === true ) {
56022
+ }
55781
56023
 
55782
- this._delta = 0;
56024
+ if ( this.running ) {
55783
56025
 
55784
- } else {
56026
+ const newTime = performance.now();
55785
56027
 
55786
- this._previousTime = this._currentTime;
55787
- this._currentTime = ( timestamp !== undefined ? timestamp : performance.now() ) - this._startTime;
56028
+ diff = ( newTime - this.oldTime ) / 1000;
56029
+ this.oldTime = newTime;
55788
56030
 
55789
- this._delta = ( this._currentTime - this._previousTime ) * this._timescale;
55790
- this._elapsed += this._delta; // _elapsed is the accumulation of all previous deltas
56031
+ this.elapsedTime += diff;
55791
56032
 
55792
56033
  }
55793
56034
 
55794
- return this;
56035
+ return diff;
55795
56036
 
55796
56037
  }
55797
56038
 
55798
- };
55799
-
55800
- function handleVisibilityChange() {
55801
-
55802
- if ( this._document.hidden === false ) this.reset();
55803
-
55804
56039
  }
55805
56040
 
55806
56041
  /**
@@ -56094,6 +56329,19 @@ class Cylindrical {
56094
56329
  */
56095
56330
  class Matrix2 {
56096
56331
 
56332
+ static {
56333
+
56334
+ /**
56335
+ * This flag can be used for type testing.
56336
+ *
56337
+ * @type {boolean}
56338
+ * @readonly
56339
+ * @default true
56340
+ */
56341
+ Matrix2.prototype.isMatrix2 = true;
56342
+
56343
+ }
56344
+
56097
56345
  /**
56098
56346
  * Constructs a new 2x2 matrix. The arguments are supposed to be
56099
56347
  * in row-major order. If no arguments are provided, the constructor
@@ -56106,15 +56354,6 @@ class Matrix2 {
56106
56354
  */
56107
56355
  constructor( n11, n12, n21, n22 ) {
56108
56356
 
56109
- /**
56110
- * This flag can be used for type testing.
56111
- *
56112
- * @type {boolean}
56113
- * @readonly
56114
- * @default true
56115
- */
56116
- Matrix2.prototype.isMatrix2 = true;
56117
-
56118
56357
  /**
56119
56358
  * A column-major list of matrix values.
56120
56359
  *
@@ -56710,6 +56949,9 @@ class Line3 {
56710
56949
  _startEnd.subVectors( this.end, this.start );
56711
56950
 
56712
56951
  const startEnd2 = _startEnd.dot( _startEnd );
56952
+
56953
+ if ( startEnd2 === 0 ) return 0;
56954
+
56713
56955
  const startEnd_startP = _startEnd.dot( _startP );
56714
56956
 
56715
56957
  let t = startEnd_startP / startEnd2;
@@ -59492,6 +59734,7 @@ function WebGLAnimation() {
59492
59734
 
59493
59735
  if ( isAnimating === true ) return;
59494
59736
  if ( animationLoop === null ) return;
59737
+ if ( context === null ) return;
59495
59738
 
59496
59739
  requestId = context.requestAnimationFrame( onAnimationFrame );
59497
59740
 
@@ -59501,7 +59744,7 @@ function WebGLAnimation() {
59501
59744
 
59502
59745
  stop: function () {
59503
59746
 
59504
- context.cancelAnimationFrame( requestId );
59747
+ if ( context !== null ) context.cancelAnimationFrame( requestId );
59505
59748
 
59506
59749
  isAnimating = false;
59507
59750
 
@@ -59822,9 +60065,9 @@ var colorspace_fragment = "gl_FragColor = linearToOutputTexel( gl_FragColor );";
59822
60065
 
59823
60066
  var colorspace_pars_fragment = "vec4 LinearTransferOETF( in vec4 value ) {\n\treturn value;\n}\nvec4 sRGBTransferEOTF( in vec4 value ) {\n\treturn vec4( mix( pow( value.rgb * 0.9478672986 + vec3( 0.0521327014 ), vec3( 2.4 ) ), value.rgb * 0.0773993808, vec3( lessThanEqual( value.rgb, vec3( 0.04045 ) ) ) ), value.a );\n}\nvec4 sRGBTransferOETF( in vec4 value ) {\n\treturn vec4( mix( pow( value.rgb, vec3( 0.41666 ) ) * 1.055 - vec3( 0.055 ), value.rgb * 12.92, vec3( lessThanEqual( value.rgb, vec3( 0.0031308 ) ) ) ), value.a );\n}";
59824
60067
 
59825
- var envmap_fragment = "#ifdef USE_ENVMAP\n\t#ifdef ENV_WORLDPOS\n\t\tvec3 cameraToFrag;\n\t\tif ( isOrthographic ) {\n\t\t\tcameraToFrag = normalize( vec3( - viewMatrix[ 0 ][ 2 ], - viewMatrix[ 1 ][ 2 ], - viewMatrix[ 2 ][ 2 ] ) );\n\t\t} else {\n\t\t\tcameraToFrag = normalize( vWorldPosition - cameraPosition );\n\t\t}\n\t\tvec3 worldNormal = inverseTransformDirection( normal, viewMatrix );\n\t\t#ifdef ENVMAP_MODE_REFLECTION\n\t\t\tvec3 reflectVec = reflect( cameraToFrag, worldNormal );\n\t\t#else\n\t\t\tvec3 reflectVec = refract( cameraToFrag, worldNormal, refractionRatio );\n\t\t#endif\n\t#else\n\t\tvec3 reflectVec = vReflect;\n\t#endif\n\t#ifdef ENVMAP_TYPE_CUBE\n\t\tvec4 envColor = textureCube( envMap, envMapRotation * vec3( flipEnvMap * reflectVec.x, reflectVec.yz ) );\n\t\t#ifdef ENVMAP_BLENDING_MULTIPLY\n\t\t\toutgoingLight = mix( outgoingLight, outgoingLight * envColor.xyz, specularStrength * reflectivity );\n\t\t#elif defined( ENVMAP_BLENDING_MIX )\n\t\t\toutgoingLight = mix( outgoingLight, envColor.xyz, specularStrength * reflectivity );\n\t\t#elif defined( ENVMAP_BLENDING_ADD )\n\t\t\toutgoingLight += envColor.xyz * specularStrength * reflectivity;\n\t\t#endif\n\t#endif\n#endif";
60068
+ var envmap_fragment = "#ifdef USE_ENVMAP\n\t#ifdef ENV_WORLDPOS\n\t\tvec3 cameraToFrag;\n\t\tif ( isOrthographic ) {\n\t\t\tcameraToFrag = normalize( vec3( - viewMatrix[ 0 ][ 2 ], - viewMatrix[ 1 ][ 2 ], - viewMatrix[ 2 ][ 2 ] ) );\n\t\t} else {\n\t\t\tcameraToFrag = normalize( vWorldPosition - cameraPosition );\n\t\t}\n\t\tvec3 worldNormal = inverseTransformDirection( normal, viewMatrix );\n\t\t#ifdef ENVMAP_MODE_REFLECTION\n\t\t\tvec3 reflectVec = reflect( cameraToFrag, worldNormal );\n\t\t#else\n\t\t\tvec3 reflectVec = refract( cameraToFrag, worldNormal, refractionRatio );\n\t\t#endif\n\t#else\n\t\tvec3 reflectVec = vReflect;\n\t#endif\n\t#ifdef ENVMAP_TYPE_CUBE\n\t\tvec4 envColor = textureCube( envMap, envMapRotation * reflectVec );\n\t\t#ifdef ENVMAP_BLENDING_MULTIPLY\n\t\t\toutgoingLight = mix( outgoingLight, outgoingLight * envColor.xyz, specularStrength * reflectivity );\n\t\t#elif defined( ENVMAP_BLENDING_MIX )\n\t\t\toutgoingLight = mix( outgoingLight, envColor.xyz, specularStrength * reflectivity );\n\t\t#elif defined( ENVMAP_BLENDING_ADD )\n\t\t\toutgoingLight += envColor.xyz * specularStrength * reflectivity;\n\t\t#endif\n\t#endif\n#endif";
59826
60069
 
59827
- var envmap_common_pars_fragment = "#ifdef USE_ENVMAP\n\tuniform float envMapIntensity;\n\tuniform float flipEnvMap;\n\tuniform mat3 envMapRotation;\n\t#ifdef ENVMAP_TYPE_CUBE\n\t\tuniform samplerCube envMap;\n\t#else\n\t\tuniform sampler2D envMap;\n\t#endif\n#endif";
60070
+ var envmap_common_pars_fragment = "#ifdef USE_ENVMAP\n\tuniform float envMapIntensity;\n\tuniform mat3 envMapRotation;\n\t#ifdef ENVMAP_TYPE_CUBE\n\t\tuniform samplerCube envMap;\n\t#else\n\t\tuniform sampler2D envMap;\n\t#endif\n#endif";
59828
60071
 
59829
60072
  var envmap_pars_fragment = "#ifdef USE_ENVMAP\n\tuniform float reflectivity;\n\t#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG ) || defined( LAMBERT )\n\t\t#define ENV_WORLDPOS\n\t#endif\n\t#ifdef ENV_WORLDPOS\n\t\tvarying vec3 vWorldPosition;\n\t\tuniform float refractionRatio;\n\t#else\n\t\tvarying vec3 vReflect;\n\t#endif\n#endif";
59830
60073
 
@@ -59848,7 +60091,7 @@ var lights_lambert_fragment = "LambertMaterial material;\nmaterial.diffuseColor
59848
60091
 
59849
60092
  var lights_lambert_pars_fragment = "varying vec3 vViewPosition;\nstruct LambertMaterial {\n\tvec3 diffuseColor;\n\tfloat specularStrength;\n};\nvoid RE_Direct_Lambert( const in IncidentLight directLight, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in LambertMaterial material, inout ReflectedLight reflectedLight ) {\n\tfloat dotNL = saturate( dot( geometryNormal, directLight.direction ) );\n\tvec3 irradiance = dotNL * directLight.color;\n\treflectedLight.directDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\nvoid RE_IndirectDiffuse_Lambert( const in vec3 irradiance, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in LambertMaterial material, inout ReflectedLight reflectedLight ) {\n\treflectedLight.indirectDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\n#define RE_Direct\t\t\t\tRE_Direct_Lambert\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_Lambert";
59850
60093
 
59851
- var lights_pars_begin = "uniform bool receiveShadow;\nuniform vec3 ambientLightColor;\n#if defined( USE_LIGHT_PROBES )\n\tuniform vec3 lightProbe[ 9 ];\n#endif\nvec3 shGetIrradianceAt( in vec3 normal, in vec3 shCoefficients[ 9 ] ) {\n\tfloat x = normal.x, y = normal.y, z = normal.z;\n\tvec3 result = shCoefficients[ 0 ] * 0.886227;\n\tresult += shCoefficients[ 1 ] * 2.0 * 0.511664 * y;\n\tresult += shCoefficients[ 2 ] * 2.0 * 0.511664 * z;\n\tresult += shCoefficients[ 3 ] * 2.0 * 0.511664 * x;\n\tresult += shCoefficients[ 4 ] * 2.0 * 0.429043 * x * y;\n\tresult += shCoefficients[ 5 ] * 2.0 * 0.429043 * y * z;\n\tresult += shCoefficients[ 6 ] * ( 0.743125 * z * z - 0.247708 );\n\tresult += shCoefficients[ 7 ] * 2.0 * 0.429043 * x * z;\n\tresult += shCoefficients[ 8 ] * 0.429043 * ( x * x - y * y );\n\treturn result;\n}\nvec3 getLightProbeIrradiance( const in vec3 lightProbe[ 9 ], const in vec3 normal ) {\n\tvec3 worldNormal = inverseTransformDirection( normal, viewMatrix );\n\tvec3 irradiance = shGetIrradianceAt( worldNormal, lightProbe );\n\treturn irradiance;\n}\nvec3 getAmbientLightIrradiance( const in vec3 ambientLightColor ) {\n\tvec3 irradiance = ambientLightColor;\n\treturn irradiance;\n}\nfloat getDistanceAttenuation( const in float lightDistance, const in float cutoffDistance, const in float decayExponent ) {\n\tfloat distanceFalloff = 1.0 / max( pow( lightDistance, decayExponent ), 0.01 );\n\tif ( cutoffDistance > 0.0 ) {\n\t\tdistanceFalloff *= pow2( saturate( 1.0 - pow4( lightDistance / cutoffDistance ) ) );\n\t}\n\treturn distanceFalloff;\n}\nfloat getSpotAttenuation( const in float coneCosine, const in float penumbraCosine, const in float angleCosine ) {\n\treturn smoothstep( coneCosine, penumbraCosine, angleCosine );\n}\n#if NUM_DIR_LIGHTS > 0\n\tstruct DirectionalLight {\n\t\tvec3 direction;\n\t\tvec3 color;\n\t};\n\tuniform DirectionalLight directionalLights[ NUM_DIR_LIGHTS ];\n\tvoid getDirectionalLightInfo( const in DirectionalLight directionalLight, out IncidentLight light ) {\n\t\tlight.color = directionalLight.color;\n\t\tlight.direction = directionalLight.direction;\n\t\tlight.visible = true;\n\t}\n#endif\n#if NUM_POINT_LIGHTS > 0\n\tstruct PointLight {\n\t\tvec3 position;\n\t\tvec3 color;\n\t\tfloat distance;\n\t\tfloat decay;\n\t};\n\tuniform PointLight pointLights[ NUM_POINT_LIGHTS ];\n\tvoid getPointLightInfo( const in PointLight pointLight, const in vec3 geometryPosition, out IncidentLight light ) {\n\t\tvec3 lVector = pointLight.position - geometryPosition;\n\t\tlight.direction = normalize( lVector );\n\t\tfloat lightDistance = length( lVector );\n\t\tlight.color = pointLight.color;\n\t\tlight.color *= getDistanceAttenuation( lightDistance, pointLight.distance, pointLight.decay );\n\t\tlight.visible = ( light.color != vec3( 0.0 ) );\n\t}\n#endif\n#if NUM_SPOT_LIGHTS > 0\n\tstruct SpotLight {\n\t\tvec3 position;\n\t\tvec3 direction;\n\t\tvec3 color;\n\t\tfloat distance;\n\t\tfloat decay;\n\t\tfloat coneCos;\n\t\tfloat penumbraCos;\n\t};\n\tuniform SpotLight spotLights[ NUM_SPOT_LIGHTS ];\n\tvoid getSpotLightInfo( const in SpotLight spotLight, const in vec3 geometryPosition, out IncidentLight light ) {\n\t\tvec3 lVector = spotLight.position - geometryPosition;\n\t\tlight.direction = normalize( lVector );\n\t\tfloat angleCos = dot( light.direction, spotLight.direction );\n\t\tfloat spotAttenuation = getSpotAttenuation( spotLight.coneCos, spotLight.penumbraCos, angleCos );\n\t\tif ( spotAttenuation > 0.0 ) {\n\t\t\tfloat lightDistance = length( lVector );\n\t\t\tlight.color = spotLight.color * spotAttenuation;\n\t\t\tlight.color *= getDistanceAttenuation( lightDistance, spotLight.distance, spotLight.decay );\n\t\t\tlight.visible = ( light.color != vec3( 0.0 ) );\n\t\t} else {\n\t\t\tlight.color = vec3( 0.0 );\n\t\t\tlight.visible = false;\n\t\t}\n\t}\n#endif\n#if NUM_RECT_AREA_LIGHTS > 0\n\tstruct RectAreaLight {\n\t\tvec3 color;\n\t\tvec3 position;\n\t\tvec3 halfWidth;\n\t\tvec3 halfHeight;\n\t};\n\tuniform sampler2D ltc_1;\tuniform sampler2D ltc_2;\n\tuniform RectAreaLight rectAreaLights[ NUM_RECT_AREA_LIGHTS ];\n#endif\n#if NUM_HEMI_LIGHTS > 0\n\tstruct HemisphereLight {\n\t\tvec3 direction;\n\t\tvec3 skyColor;\n\t\tvec3 groundColor;\n\t};\n\tuniform HemisphereLight hemisphereLights[ NUM_HEMI_LIGHTS ];\n\tvec3 getHemisphereLightIrradiance( const in HemisphereLight hemiLight, const in vec3 normal ) {\n\t\tfloat dotNL = dot( normal, hemiLight.direction );\n\t\tfloat hemiDiffuseWeight = 0.5 * dotNL + 0.5;\n\t\tvec3 irradiance = mix( hemiLight.groundColor, hemiLight.skyColor, hemiDiffuseWeight );\n\t\treturn irradiance;\n\t}\n#endif";
60094
+ var lights_pars_begin = "uniform bool receiveShadow;\nuniform vec3 ambientLightColor;\n#if defined( USE_LIGHT_PROBES )\n\tuniform vec3 lightProbe[ 9 ];\n#endif\nvec3 shGetIrradianceAt( in vec3 normal, in vec3 shCoefficients[ 9 ] ) {\n\tfloat x = normal.x, y = normal.y, z = normal.z;\n\tvec3 result = shCoefficients[ 0 ] * 0.886227;\n\tresult += shCoefficients[ 1 ] * 2.0 * 0.511664 * y;\n\tresult += shCoefficients[ 2 ] * 2.0 * 0.511664 * z;\n\tresult += shCoefficients[ 3 ] * 2.0 * 0.511664 * x;\n\tresult += shCoefficients[ 4 ] * 2.0 * 0.429043 * x * y;\n\tresult += shCoefficients[ 5 ] * 2.0 * 0.429043 * y * z;\n\tresult += shCoefficients[ 6 ] * ( 0.743125 * z * z - 0.247708 );\n\tresult += shCoefficients[ 7 ] * 2.0 * 0.429043 * x * z;\n\tresult += shCoefficients[ 8 ] * 0.429043 * ( x * x - y * y );\n\treturn result;\n}\nvec3 getLightProbeIrradiance( const in vec3 lightProbe[ 9 ], const in vec3 normal ) {\n\tvec3 worldNormal = inverseTransformDirection( normal, viewMatrix );\n\tvec3 irradiance = shGetIrradianceAt( worldNormal, lightProbe );\n\treturn irradiance;\n}\nvec3 getAmbientLightIrradiance( const in vec3 ambientLightColor ) {\n\tvec3 irradiance = ambientLightColor;\n\treturn irradiance;\n}\nfloat getDistanceAttenuation( const in float lightDistance, const in float cutoffDistance, const in float decayExponent ) {\n\tfloat distanceFalloff = 1.0 / max( pow( lightDistance, decayExponent ), 0.01 );\n\tif ( cutoffDistance > 0.0 ) {\n\t\tdistanceFalloff *= pow2( saturate( 1.0 - pow4( lightDistance / cutoffDistance ) ) );\n\t}\n\treturn distanceFalloff;\n}\nfloat getSpotAttenuation( const in float coneCosine, const in float penumbraCosine, const in float angleCosine ) {\n\treturn smoothstep( coneCosine, penumbraCosine, angleCosine );\n}\n#if NUM_DIR_LIGHTS > 0\n\tstruct DirectionalLight {\n\t\tvec3 direction;\n\t\tvec3 color;\n\t};\n\tuniform DirectionalLight directionalLights[ NUM_DIR_LIGHTS ];\n\tvoid getDirectionalLightInfo( const in DirectionalLight directionalLight, out IncidentLight light ) {\n\t\tlight.color = directionalLight.color;\n\t\tlight.direction = directionalLight.direction;\n\t\tlight.visible = true;\n\t}\n#endif\n#if NUM_POINT_LIGHTS > 0\n\tstruct PointLight {\n\t\tvec3 position;\n\t\tvec3 color;\n\t\tfloat distance;\n\t\tfloat decay;\n\t};\n\tuniform PointLight pointLights[ NUM_POINT_LIGHTS ];\n\tvoid getPointLightInfo( const in PointLight pointLight, const in vec3 geometryPosition, out IncidentLight light ) {\n\t\tvec3 lVector = pointLight.position - geometryPosition;\n\t\tlight.direction = normalize( lVector );\n\t\tfloat lightDistance = length( lVector );\n\t\tlight.color = pointLight.color;\n\t\tlight.color *= getDistanceAttenuation( lightDistance, pointLight.distance, pointLight.decay );\n\t\tlight.visible = ( light.color != vec3( 0.0 ) );\n\t}\n#endif\n#if NUM_SPOT_LIGHTS > 0\n\tstruct SpotLight {\n\t\tvec3 position;\n\t\tvec3 direction;\n\t\tvec3 color;\n\t\tfloat distance;\n\t\tfloat decay;\n\t\tfloat coneCos;\n\t\tfloat penumbraCos;\n\t};\n\tuniform SpotLight spotLights[ NUM_SPOT_LIGHTS ];\n\tvoid getSpotLightInfo( const in SpotLight spotLight, const in vec3 geometryPosition, out IncidentLight light ) {\n\t\tvec3 lVector = spotLight.position - geometryPosition;\n\t\tlight.direction = normalize( lVector );\n\t\tfloat angleCos = dot( light.direction, spotLight.direction );\n\t\tfloat spotAttenuation = getSpotAttenuation( spotLight.coneCos, spotLight.penumbraCos, angleCos );\n\t\tif ( spotAttenuation > 0.0 ) {\n\t\t\tfloat lightDistance = length( lVector );\n\t\t\tlight.color = spotLight.color * spotAttenuation;\n\t\t\tlight.color *= getDistanceAttenuation( lightDistance, spotLight.distance, spotLight.decay );\n\t\t\tlight.visible = ( light.color != vec3( 0.0 ) );\n\t\t} else {\n\t\t\tlight.color = vec3( 0.0 );\n\t\t\tlight.visible = false;\n\t\t}\n\t}\n#endif\n#if NUM_RECT_AREA_LIGHTS > 0\n\tstruct RectAreaLight {\n\t\tvec3 color;\n\t\tvec3 position;\n\t\tvec3 halfWidth;\n\t\tvec3 halfHeight;\n\t};\n\tuniform sampler2D ltc_1;\tuniform sampler2D ltc_2;\n\tuniform RectAreaLight rectAreaLights[ NUM_RECT_AREA_LIGHTS ];\n#endif\n#if NUM_HEMI_LIGHTS > 0\n\tstruct HemisphereLight {\n\t\tvec3 direction;\n\t\tvec3 skyColor;\n\t\tvec3 groundColor;\n\t};\n\tuniform HemisphereLight hemisphereLights[ NUM_HEMI_LIGHTS ];\n\tvec3 getHemisphereLightIrradiance( const in HemisphereLight hemiLight, const in vec3 normal ) {\n\t\tfloat dotNL = dot( normal, hemiLight.direction );\n\t\tfloat hemiDiffuseWeight = 0.5 * dotNL + 0.5;\n\t\tvec3 irradiance = mix( hemiLight.groundColor, hemiLight.skyColor, hemiDiffuseWeight );\n\t\treturn irradiance;\n\t}\n#endif\n#include <lightprobes_pars_fragment>";
59852
60095
 
59853
60096
  var envmap_physical_pars_fragment = "#ifdef USE_ENVMAP\n\tvec3 getIBLIrradiance( const in vec3 normal ) {\n\t\t#ifdef ENVMAP_TYPE_CUBE_UV\n\t\t\tvec3 worldNormal = inverseTransformDirection( normal, viewMatrix );\n\t\t\tvec4 envMapColor = textureCubeUV( envMap, envMapRotation * worldNormal, 1.0 );\n\t\t\treturn PI * envMapColor.rgb * envMapIntensity;\n\t\t#else\n\t\t\treturn vec3( 0.0 );\n\t\t#endif\n\t}\n\tvec3 getIBLRadiance( const in vec3 viewDir, const in vec3 normal, const in float roughness ) {\n\t\t#ifdef ENVMAP_TYPE_CUBE_UV\n\t\t\tvec3 reflectVec = reflect( - viewDir, normal );\n\t\t\treflectVec = normalize( mix( reflectVec, normal, pow4( roughness ) ) );\n\t\t\treflectVec = inverseTransformDirection( reflectVec, viewMatrix );\n\t\t\tvec4 envMapColor = textureCubeUV( envMap, envMapRotation * reflectVec, roughness );\n\t\t\treturn envMapColor.rgb * envMapIntensity;\n\t\t#else\n\t\t\treturn vec3( 0.0 );\n\t\t#endif\n\t}\n\t#ifdef USE_ANISOTROPY\n\t\tvec3 getIBLAnisotropyRadiance( const in vec3 viewDir, const in vec3 normal, const in float roughness, const in vec3 bitangent, const in float anisotropy ) {\n\t\t\t#ifdef ENVMAP_TYPE_CUBE_UV\n\t\t\t\tvec3 bentNormal = cross( bitangent, viewDir );\n\t\t\t\tbentNormal = normalize( cross( bentNormal, bitangent ) );\n\t\t\t\tbentNormal = normalize( mix( bentNormal, normal, pow2( pow2( 1.0 - anisotropy * ( 1.0 - roughness ) ) ) ) );\n\t\t\t\treturn getIBLRadiance( viewDir, bentNormal, roughness );\n\t\t\t#else\n\t\t\t\treturn vec3( 0.0 );\n\t\t\t#endif\n\t\t}\n\t#endif\n#endif";
59854
60097
 
@@ -59862,14 +60105,16 @@ var lights_phong_pars_fragment = "varying vec3 vViewPosition;\nstruct BlinnPhong
59862
60105
 
59863
60106
  var lights_physical_fragment = "PhysicalMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb;\nmaterial.diffuseContribution = diffuseColor.rgb * ( 1.0 - metalnessFactor );\nmaterial.metalness = metalnessFactor;\nvec3 dxy = max( abs( dFdx( nonPerturbedNormal ) ), abs( dFdy( nonPerturbedNormal ) ) );\nfloat geometryRoughness = max( max( dxy.x, dxy.y ), dxy.z );\nmaterial.roughness = max( roughnessFactor, 0.0525 );material.roughness += geometryRoughness;\nmaterial.roughness = min( material.roughness, 1.0 );\n#ifdef IOR\n\tmaterial.ior = ior;\n\t#ifdef USE_SPECULAR\n\t\tfloat specularIntensityFactor = specularIntensity;\n\t\tvec3 specularColorFactor = specularColor;\n\t\t#ifdef USE_SPECULAR_COLORMAP\n\t\t\tspecularColorFactor *= texture2D( specularColorMap, vSpecularColorMapUv ).rgb;\n\t\t#endif\n\t\t#ifdef USE_SPECULAR_INTENSITYMAP\n\t\t\tspecularIntensityFactor *= texture2D( specularIntensityMap, vSpecularIntensityMapUv ).a;\n\t\t#endif\n\t\tmaterial.specularF90 = mix( specularIntensityFactor, 1.0, metalnessFactor );\n\t#else\n\t\tfloat specularIntensityFactor = 1.0;\n\t\tvec3 specularColorFactor = vec3( 1.0 );\n\t\tmaterial.specularF90 = 1.0;\n\t#endif\n\tmaterial.specularColor = min( pow2( ( material.ior - 1.0 ) / ( material.ior + 1.0 ) ) * specularColorFactor, vec3( 1.0 ) ) * specularIntensityFactor;\n\tmaterial.specularColorBlended = mix( material.specularColor, diffuseColor.rgb, metalnessFactor );\n#else\n\tmaterial.specularColor = vec3( 0.04 );\n\tmaterial.specularColorBlended = mix( material.specularColor, diffuseColor.rgb, metalnessFactor );\n\tmaterial.specularF90 = 1.0;\n#endif\n#ifdef USE_CLEARCOAT\n\tmaterial.clearcoat = clearcoat;\n\tmaterial.clearcoatRoughness = clearcoatRoughness;\n\tmaterial.clearcoatF0 = vec3( 0.04 );\n\tmaterial.clearcoatF90 = 1.0;\n\t#ifdef USE_CLEARCOATMAP\n\t\tmaterial.clearcoat *= texture2D( clearcoatMap, vClearcoatMapUv ).x;\n\t#endif\n\t#ifdef USE_CLEARCOAT_ROUGHNESSMAP\n\t\tmaterial.clearcoatRoughness *= texture2D( clearcoatRoughnessMap, vClearcoatRoughnessMapUv ).y;\n\t#endif\n\tmaterial.clearcoat = saturate( material.clearcoat );\tmaterial.clearcoatRoughness = max( material.clearcoatRoughness, 0.0525 );\n\tmaterial.clearcoatRoughness += geometryRoughness;\n\tmaterial.clearcoatRoughness = min( material.clearcoatRoughness, 1.0 );\n#endif\n#ifdef USE_DISPERSION\n\tmaterial.dispersion = dispersion;\n#endif\n#ifdef USE_IRIDESCENCE\n\tmaterial.iridescence = iridescence;\n\tmaterial.iridescenceIOR = iridescenceIOR;\n\t#ifdef USE_IRIDESCENCEMAP\n\t\tmaterial.iridescence *= texture2D( iridescenceMap, vIridescenceMapUv ).r;\n\t#endif\n\t#ifdef USE_IRIDESCENCE_THICKNESSMAP\n\t\tmaterial.iridescenceThickness = (iridescenceThicknessMaximum - iridescenceThicknessMinimum) * texture2D( iridescenceThicknessMap, vIridescenceThicknessMapUv ).g + iridescenceThicknessMinimum;\n\t#else\n\t\tmaterial.iridescenceThickness = iridescenceThicknessMaximum;\n\t#endif\n#endif\n#ifdef USE_SHEEN\n\tmaterial.sheenColor = sheenColor;\n\t#ifdef USE_SHEEN_COLORMAP\n\t\tmaterial.sheenColor *= texture2D( sheenColorMap, vSheenColorMapUv ).rgb;\n\t#endif\n\tmaterial.sheenRoughness = clamp( sheenRoughness, 0.0001, 1.0 );\n\t#ifdef USE_SHEEN_ROUGHNESSMAP\n\t\tmaterial.sheenRoughness *= texture2D( sheenRoughnessMap, vSheenRoughnessMapUv ).a;\n\t#endif\n#endif\n#ifdef USE_ANISOTROPY\n\t#ifdef USE_ANISOTROPYMAP\n\t\tmat2 anisotropyMat = mat2( anisotropyVector.x, anisotropyVector.y, - anisotropyVector.y, anisotropyVector.x );\n\t\tvec3 anisotropyPolar = texture2D( anisotropyMap, vAnisotropyMapUv ).rgb;\n\t\tvec2 anisotropyV = anisotropyMat * normalize( 2.0 * anisotropyPolar.rg - vec2( 1.0 ) ) * anisotropyPolar.b;\n\t#else\n\t\tvec2 anisotropyV = anisotropyVector;\n\t#endif\n\tmaterial.anisotropy = length( anisotropyV );\n\tif( material.anisotropy == 0.0 ) {\n\t\tanisotropyV = vec2( 1.0, 0.0 );\n\t} else {\n\t\tanisotropyV /= material.anisotropy;\n\t\tmaterial.anisotropy = saturate( material.anisotropy );\n\t}\n\tmaterial.alphaT = mix( pow2( material.roughness ), 1.0, pow2( material.anisotropy ) );\n\tmaterial.anisotropyT = tbn[ 0 ] * anisotropyV.x + tbn[ 1 ] * anisotropyV.y;\n\tmaterial.anisotropyB = tbn[ 1 ] * anisotropyV.x - tbn[ 0 ] * anisotropyV.y;\n#endif";
59864
60107
 
59865
- var lights_physical_pars_fragment = "uniform sampler2D dfgLUT;\nstruct PhysicalMaterial {\n\tvec3 diffuseColor;\n\tvec3 diffuseContribution;\n\tvec3 specularColor;\n\tvec3 specularColorBlended;\n\tfloat roughness;\n\tfloat metalness;\n\tfloat specularF90;\n\tfloat dispersion;\n\t#ifdef USE_CLEARCOAT\n\t\tfloat clearcoat;\n\t\tfloat clearcoatRoughness;\n\t\tvec3 clearcoatF0;\n\t\tfloat clearcoatF90;\n\t#endif\n\t#ifdef USE_IRIDESCENCE\n\t\tfloat iridescence;\n\t\tfloat iridescenceIOR;\n\t\tfloat iridescenceThickness;\n\t\tvec3 iridescenceFresnel;\n\t\tvec3 iridescenceF0;\n\t\tvec3 iridescenceFresnelDielectric;\n\t\tvec3 iridescenceFresnelMetallic;\n\t#endif\n\t#ifdef USE_SHEEN\n\t\tvec3 sheenColor;\n\t\tfloat sheenRoughness;\n\t#endif\n\t#ifdef IOR\n\t\tfloat ior;\n\t#endif\n\t#ifdef USE_TRANSMISSION\n\t\tfloat transmission;\n\t\tfloat transmissionAlpha;\n\t\tfloat thickness;\n\t\tfloat attenuationDistance;\n\t\tvec3 attenuationColor;\n\t#endif\n\t#ifdef USE_ANISOTROPY\n\t\tfloat anisotropy;\n\t\tfloat alphaT;\n\t\tvec3 anisotropyT;\n\t\tvec3 anisotropyB;\n\t#endif\n};\nvec3 clearcoatSpecularDirect = vec3( 0.0 );\nvec3 clearcoatSpecularIndirect = vec3( 0.0 );\nvec3 sheenSpecularDirect = vec3( 0.0 );\nvec3 sheenSpecularIndirect = vec3(0.0 );\nvec3 Schlick_to_F0( const in vec3 f, const in float f90, const in float dotVH ) {\n float x = clamp( 1.0 - dotVH, 0.0, 1.0 );\n float x2 = x * x;\n float x5 = clamp( x * x2 * x2, 0.0, 0.9999 );\n return ( f - vec3( f90 ) * x5 ) / ( 1.0 - x5 );\n}\nfloat V_GGX_SmithCorrelated( const in float alpha, const in float dotNL, const in float dotNV ) {\n\tfloat a2 = pow2( alpha );\n\tfloat gv = dotNL * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNV ) );\n\tfloat gl = dotNV * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNL ) );\n\treturn 0.5 / max( gv + gl, EPSILON );\n}\nfloat D_GGX( const in float alpha, const in float dotNH ) {\n\tfloat a2 = pow2( alpha );\n\tfloat denom = pow2( dotNH ) * ( a2 - 1.0 ) + 1.0;\n\treturn RECIPROCAL_PI * a2 / pow2( denom );\n}\n#ifdef USE_ANISOTROPY\n\tfloat V_GGX_SmithCorrelated_Anisotropic( const in float alphaT, const in float alphaB, const in float dotTV, const in float dotBV, const in float dotTL, const in float dotBL, const in float dotNV, const in float dotNL ) {\n\t\tfloat gv = dotNL * length( vec3( alphaT * dotTV, alphaB * dotBV, dotNV ) );\n\t\tfloat gl = dotNV * length( vec3( alphaT * dotTL, alphaB * dotBL, dotNL ) );\n\t\tfloat v = 0.5 / ( gv + gl );\n\t\treturn v;\n\t}\n\tfloat D_GGX_Anisotropic( const in float alphaT, const in float alphaB, const in float dotNH, const in float dotTH, const in float dotBH ) {\n\t\tfloat a2 = alphaT * alphaB;\n\t\thighp vec3 v = vec3( alphaB * dotTH, alphaT * dotBH, a2 * dotNH );\n\t\thighp float v2 = dot( v, v );\n\t\tfloat w2 = a2 / v2;\n\t\treturn RECIPROCAL_PI * a2 * pow2 ( w2 );\n\t}\n#endif\n#ifdef USE_CLEARCOAT\n\tvec3 BRDF_GGX_Clearcoat( const in vec3 lightDir, const in vec3 viewDir, const in vec3 normal, const in PhysicalMaterial material) {\n\t\tvec3 f0 = material.clearcoatF0;\n\t\tfloat f90 = material.clearcoatF90;\n\t\tfloat roughness = material.clearcoatRoughness;\n\t\tfloat alpha = pow2( roughness );\n\t\tvec3 halfDir = normalize( lightDir + viewDir );\n\t\tfloat dotNL = saturate( dot( normal, lightDir ) );\n\t\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\t\tfloat dotNH = saturate( dot( normal, halfDir ) );\n\t\tfloat dotVH = saturate( dot( viewDir, halfDir ) );\n\t\tvec3 F = F_Schlick( f0, f90, dotVH );\n\t\tfloat V = V_GGX_SmithCorrelated( alpha, dotNL, dotNV );\n\t\tfloat D = D_GGX( alpha, dotNH );\n\t\treturn F * ( V * D );\n\t}\n#endif\nvec3 BRDF_GGX( const in vec3 lightDir, const in vec3 viewDir, const in vec3 normal, const in PhysicalMaterial material ) {\n\tvec3 f0 = material.specularColorBlended;\n\tfloat f90 = material.specularF90;\n\tfloat roughness = material.roughness;\n\tfloat alpha = pow2( roughness );\n\tvec3 halfDir = normalize( lightDir + viewDir );\n\tfloat dotNL = saturate( dot( normal, lightDir ) );\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tfloat dotNH = saturate( dot( normal, halfDir ) );\n\tfloat dotVH = saturate( dot( viewDir, halfDir ) );\n\tvec3 F = F_Schlick( f0, f90, dotVH );\n\t#ifdef USE_IRIDESCENCE\n\t\tF = mix( F, material.iridescenceFresnel, material.iridescence );\n\t#endif\n\t#ifdef USE_ANISOTROPY\n\t\tfloat dotTL = dot( material.anisotropyT, lightDir );\n\t\tfloat dotTV = dot( material.anisotropyT, viewDir );\n\t\tfloat dotTH = dot( material.anisotropyT, halfDir );\n\t\tfloat dotBL = dot( material.anisotropyB, lightDir );\n\t\tfloat dotBV = dot( material.anisotropyB, viewDir );\n\t\tfloat dotBH = dot( material.anisotropyB, halfDir );\n\t\tfloat V = V_GGX_SmithCorrelated_Anisotropic( material.alphaT, alpha, dotTV, dotBV, dotTL, dotBL, dotNV, dotNL );\n\t\tfloat D = D_GGX_Anisotropic( material.alphaT, alpha, dotNH, dotTH, dotBH );\n\t#else\n\t\tfloat V = V_GGX_SmithCorrelated( alpha, dotNL, dotNV );\n\t\tfloat D = D_GGX( alpha, dotNH );\n\t#endif\n\treturn F * ( V * D );\n}\nvec2 LTC_Uv( const in vec3 N, const in vec3 V, const in float roughness ) {\n\tconst float LUT_SIZE = 64.0;\n\tconst float LUT_SCALE = ( LUT_SIZE - 1.0 ) / LUT_SIZE;\n\tconst float LUT_BIAS = 0.5 / LUT_SIZE;\n\tfloat dotNV = saturate( dot( N, V ) );\n\tvec2 uv = vec2( roughness, sqrt( 1.0 - dotNV ) );\n\tuv = uv * LUT_SCALE + LUT_BIAS;\n\treturn uv;\n}\nfloat LTC_ClippedSphereFormFactor( const in vec3 f ) {\n\tfloat l = length( f );\n\treturn max( ( l * l + f.z ) / ( l + 1.0 ), 0.0 );\n}\nvec3 LTC_EdgeVectorFormFactor( const in vec3 v1, const in vec3 v2 ) {\n\tfloat x = dot( v1, v2 );\n\tfloat y = abs( x );\n\tfloat a = 0.8543985 + ( 0.4965155 + 0.0145206 * y ) * y;\n\tfloat b = 3.4175940 + ( 4.1616724 + y ) * y;\n\tfloat v = a / b;\n\tfloat theta_sintheta = ( x > 0.0 ) ? v : 0.5 * inversesqrt( max( 1.0 - x * x, 1e-7 ) ) - v;\n\treturn cross( v1, v2 ) * theta_sintheta;\n}\nvec3 LTC_Evaluate( const in vec3 N, const in vec3 V, const in vec3 P, const in mat3 mInv, const in vec3 rectCoords[ 4 ] ) {\n\tvec3 v1 = rectCoords[ 1 ] - rectCoords[ 0 ];\n\tvec3 v2 = rectCoords[ 3 ] - rectCoords[ 0 ];\n\tvec3 lightNormal = cross( v1, v2 );\n\tif( dot( lightNormal, P - rectCoords[ 0 ] ) < 0.0 ) return vec3( 0.0 );\n\tvec3 T1, T2;\n\tT1 = normalize( V - N * dot( V, N ) );\n\tT2 = - cross( N, T1 );\n\tmat3 mat = mInv * transpose( mat3( T1, T2, N ) );\n\tvec3 coords[ 4 ];\n\tcoords[ 0 ] = mat * ( rectCoords[ 0 ] - P );\n\tcoords[ 1 ] = mat * ( rectCoords[ 1 ] - P );\n\tcoords[ 2 ] = mat * ( rectCoords[ 2 ] - P );\n\tcoords[ 3 ] = mat * ( rectCoords[ 3 ] - P );\n\tcoords[ 0 ] = normalize( coords[ 0 ] );\n\tcoords[ 1 ] = normalize( coords[ 1 ] );\n\tcoords[ 2 ] = normalize( coords[ 2 ] );\n\tcoords[ 3 ] = normalize( coords[ 3 ] );\n\tvec3 vectorFormFactor = vec3( 0.0 );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 0 ], coords[ 1 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 1 ], coords[ 2 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 2 ], coords[ 3 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 3 ], coords[ 0 ] );\n\tfloat result = LTC_ClippedSphereFormFactor( vectorFormFactor );\n\treturn vec3( result );\n}\n#if defined( USE_SHEEN )\nfloat D_Charlie( float roughness, float dotNH ) {\n\tfloat alpha = pow2( roughness );\n\tfloat invAlpha = 1.0 / alpha;\n\tfloat cos2h = dotNH * dotNH;\n\tfloat sin2h = max( 1.0 - cos2h, 0.0078125 );\n\treturn ( 2.0 + invAlpha ) * pow( sin2h, invAlpha * 0.5 ) / ( 2.0 * PI );\n}\nfloat V_Neubelt( float dotNV, float dotNL ) {\n\treturn saturate( 1.0 / ( 4.0 * ( dotNL + dotNV - dotNL * dotNV ) ) );\n}\nvec3 BRDF_Sheen( const in vec3 lightDir, const in vec3 viewDir, const in vec3 normal, vec3 sheenColor, const in float sheenRoughness ) {\n\tvec3 halfDir = normalize( lightDir + viewDir );\n\tfloat dotNL = saturate( dot( normal, lightDir ) );\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tfloat dotNH = saturate( dot( normal, halfDir ) );\n\tfloat D = D_Charlie( sheenRoughness, dotNH );\n\tfloat V = V_Neubelt( dotNV, dotNL );\n\treturn sheenColor * ( D * V );\n}\n#endif\nfloat IBLSheenBRDF( const in vec3 normal, const in vec3 viewDir, const in float roughness ) {\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tfloat r2 = roughness * roughness;\n\tfloat rInv = 1.0 / ( roughness + 0.1 );\n\tfloat a = -1.9362 + 1.0678 * roughness + 0.4573 * r2 - 0.8469 * rInv;\n\tfloat b = -0.6014 + 0.5538 * roughness - 0.4670 * r2 - 0.1255 * rInv;\n\tfloat DG = exp( a * dotNV + b );\n\treturn saturate( DG );\n}\nvec3 EnvironmentBRDF( const in vec3 normal, const in vec3 viewDir, const in vec3 specularColor, const in float specularF90, const in float roughness ) {\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tvec2 fab = texture2D( dfgLUT, vec2( roughness, dotNV ) ).rg;\n\treturn specularColor * fab.x + specularF90 * fab.y;\n}\n#ifdef USE_IRIDESCENCE\nvoid computeMultiscatteringIridescence( const in vec3 normal, const in vec3 viewDir, const in vec3 specularColor, const in float specularF90, const in float iridescence, const in vec3 iridescenceF0, const in float roughness, inout vec3 singleScatter, inout vec3 multiScatter ) {\n#else\nvoid computeMultiscattering( const in vec3 normal, const in vec3 viewDir, const in vec3 specularColor, const in float specularF90, const in float roughness, inout vec3 singleScatter, inout vec3 multiScatter ) {\n#endif\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tvec2 fab = texture2D( dfgLUT, vec2( roughness, dotNV ) ).rg;\n\t#ifdef USE_IRIDESCENCE\n\t\tvec3 Fr = mix( specularColor, iridescenceF0, iridescence );\n\t#else\n\t\tvec3 Fr = specularColor;\n\t#endif\n\tvec3 FssEss = Fr * fab.x + specularF90 * fab.y;\n\tfloat Ess = fab.x + fab.y;\n\tfloat Ems = 1.0 - Ess;\n\tvec3 Favg = Fr + ( 1.0 - Fr ) * 0.047619;\tvec3 Fms = FssEss * Favg / ( 1.0 - Ems * Favg );\n\tsingleScatter += FssEss;\n\tmultiScatter += Fms * Ems;\n}\nvec3 BRDF_GGX_Multiscatter( const in vec3 lightDir, const in vec3 viewDir, const in vec3 normal, const in PhysicalMaterial material ) {\n\tvec3 singleScatter = BRDF_GGX( lightDir, viewDir, normal, material );\n\tfloat dotNL = saturate( dot( normal, lightDir ) );\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tvec2 dfgV = texture2D( dfgLUT, vec2( material.roughness, dotNV ) ).rg;\n\tvec2 dfgL = texture2D( dfgLUT, vec2( material.roughness, dotNL ) ).rg;\n\tvec3 FssEss_V = material.specularColorBlended * dfgV.x + material.specularF90 * dfgV.y;\n\tvec3 FssEss_L = material.specularColorBlended * dfgL.x + material.specularF90 * dfgL.y;\n\tfloat Ess_V = dfgV.x + dfgV.y;\n\tfloat Ess_L = dfgL.x + dfgL.y;\n\tfloat Ems_V = 1.0 - Ess_V;\n\tfloat Ems_L = 1.0 - Ess_L;\n\tvec3 Favg = material.specularColorBlended + ( 1.0 - material.specularColorBlended ) * 0.047619;\n\tvec3 Fms = FssEss_V * FssEss_L * Favg / ( 1.0 - Ems_V * Ems_L * Favg + EPSILON );\n\tfloat compensationFactor = Ems_V * Ems_L;\n\tvec3 multiScatter = Fms * compensationFactor;\n\treturn singleScatter + multiScatter;\n}\n#if NUM_RECT_AREA_LIGHTS > 0\n\tvoid RE_Direct_RectArea_Physical( const in RectAreaLight rectAreaLight, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\t\tvec3 normal = geometryNormal;\n\t\tvec3 viewDir = geometryViewDir;\n\t\tvec3 position = geometryPosition;\n\t\tvec3 lightPos = rectAreaLight.position;\n\t\tvec3 halfWidth = rectAreaLight.halfWidth;\n\t\tvec3 halfHeight = rectAreaLight.halfHeight;\n\t\tvec3 lightColor = rectAreaLight.color;\n\t\tfloat roughness = material.roughness;\n\t\tvec3 rectCoords[ 4 ];\n\t\trectCoords[ 0 ] = lightPos + halfWidth - halfHeight;\t\trectCoords[ 1 ] = lightPos - halfWidth - halfHeight;\n\t\trectCoords[ 2 ] = lightPos - halfWidth + halfHeight;\n\t\trectCoords[ 3 ] = lightPos + halfWidth + halfHeight;\n\t\tvec2 uv = LTC_Uv( normal, viewDir, roughness );\n\t\tvec4 t1 = texture2D( ltc_1, uv );\n\t\tvec4 t2 = texture2D( ltc_2, uv );\n\t\tmat3 mInv = mat3(\n\t\t\tvec3( t1.x, 0, t1.y ),\n\t\t\tvec3( 0, 1, 0 ),\n\t\t\tvec3( t1.z, 0, t1.w )\n\t\t);\n\t\tvec3 fresnel = ( material.specularColorBlended * t2.x + ( material.specularF90 - material.specularColorBlended ) * t2.y );\n\t\treflectedLight.directSpecular += lightColor * fresnel * LTC_Evaluate( normal, viewDir, position, mInv, rectCoords );\n\t\treflectedLight.directDiffuse += lightColor * material.diffuseContribution * LTC_Evaluate( normal, viewDir, position, mat3( 1.0 ), rectCoords );\n\t\t#ifdef USE_CLEARCOAT\n\t\t\tvec3 Ncc = geometryClearcoatNormal;\n\t\t\tvec2 uvClearcoat = LTC_Uv( Ncc, viewDir, material.clearcoatRoughness );\n\t\t\tvec4 t1Clearcoat = texture2D( ltc_1, uvClearcoat );\n\t\t\tvec4 t2Clearcoat = texture2D( ltc_2, uvClearcoat );\n\t\t\tmat3 mInvClearcoat = mat3(\n\t\t\t\tvec3( t1Clearcoat.x, 0, t1Clearcoat.y ),\n\t\t\t\tvec3( 0, 1, 0 ),\n\t\t\t\tvec3( t1Clearcoat.z, 0, t1Clearcoat.w )\n\t\t\t);\n\t\t\tvec3 fresnelClearcoat = material.clearcoatF0 * t2Clearcoat.x + ( material.clearcoatF90 - material.clearcoatF0 ) * t2Clearcoat.y;\n\t\t\tclearcoatSpecularDirect += lightColor * fresnelClearcoat * LTC_Evaluate( Ncc, viewDir, position, mInvClearcoat, rectCoords );\n\t\t#endif\n\t}\n#endif\nvoid RE_Direct_Physical( const in IncidentLight directLight, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\tfloat dotNL = saturate( dot( geometryNormal, directLight.direction ) );\n\tvec3 irradiance = dotNL * directLight.color;\n\t#ifdef USE_CLEARCOAT\n\t\tfloat dotNLcc = saturate( dot( geometryClearcoatNormal, directLight.direction ) );\n\t\tvec3 ccIrradiance = dotNLcc * directLight.color;\n\t\tclearcoatSpecularDirect += ccIrradiance * BRDF_GGX_Clearcoat( directLight.direction, geometryViewDir, geometryClearcoatNormal, material );\n\t#endif\n\t#ifdef USE_SHEEN\n \n \t\tsheenSpecularDirect += irradiance * BRDF_Sheen( directLight.direction, geometryViewDir, geometryNormal, material.sheenColor, material.sheenRoughness );\n \n \t\tfloat sheenAlbedoV = IBLSheenBRDF( geometryNormal, geometryViewDir, material.sheenRoughness );\n \t\tfloat sheenAlbedoL = IBLSheenBRDF( geometryNormal, directLight.direction, material.sheenRoughness );\n \n \t\tfloat sheenEnergyComp = 1.0 - max3( material.sheenColor ) * max( sheenAlbedoV, sheenAlbedoL );\n \n \t\tirradiance *= sheenEnergyComp;\n \n \t#endif\n\treflectedLight.directSpecular += irradiance * BRDF_GGX_Multiscatter( directLight.direction, geometryViewDir, geometryNormal, material );\n\treflectedLight.directDiffuse += irradiance * BRDF_Lambert( material.diffuseContribution );\n}\nvoid RE_IndirectDiffuse_Physical( const in vec3 irradiance, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\tvec3 diffuse = irradiance * BRDF_Lambert( material.diffuseContribution );\n\t#ifdef USE_SHEEN\n\t\tfloat sheenAlbedo = IBLSheenBRDF( geometryNormal, geometryViewDir, material.sheenRoughness );\n\t\tfloat sheenEnergyComp = 1.0 - max3( material.sheenColor ) * sheenAlbedo;\n\t\tdiffuse *= sheenEnergyComp;\n\t#endif\n\treflectedLight.indirectDiffuse += diffuse;\n}\nvoid RE_IndirectSpecular_Physical( const in vec3 radiance, const in vec3 irradiance, const in vec3 clearcoatRadiance, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in PhysicalMaterial material, inout ReflectedLight reflectedLight) {\n\t#ifdef USE_CLEARCOAT\n\t\tclearcoatSpecularIndirect += clearcoatRadiance * EnvironmentBRDF( geometryClearcoatNormal, geometryViewDir, material.clearcoatF0, material.clearcoatF90, material.clearcoatRoughness );\n\t#endif\n\t#ifdef USE_SHEEN\n\t\tsheenSpecularIndirect += irradiance * material.sheenColor * IBLSheenBRDF( geometryNormal, geometryViewDir, material.sheenRoughness ) * RECIPROCAL_PI;\n \t#endif\n\tvec3 singleScatteringDielectric = vec3( 0.0 );\n\tvec3 multiScatteringDielectric = vec3( 0.0 );\n\tvec3 singleScatteringMetallic = vec3( 0.0 );\n\tvec3 multiScatteringMetallic = vec3( 0.0 );\n\t#ifdef USE_IRIDESCENCE\n\t\tcomputeMultiscatteringIridescence( geometryNormal, geometryViewDir, material.specularColor, material.specularF90, material.iridescence, material.iridescenceFresnelDielectric, material.roughness, singleScatteringDielectric, multiScatteringDielectric );\n\t\tcomputeMultiscatteringIridescence( geometryNormal, geometryViewDir, material.diffuseColor, material.specularF90, material.iridescence, material.iridescenceFresnelMetallic, material.roughness, singleScatteringMetallic, multiScatteringMetallic );\n\t#else\n\t\tcomputeMultiscattering( geometryNormal, geometryViewDir, material.specularColor, material.specularF90, material.roughness, singleScatteringDielectric, multiScatteringDielectric );\n\t\tcomputeMultiscattering( geometryNormal, geometryViewDir, material.diffuseColor, material.specularF90, material.roughness, singleScatteringMetallic, multiScatteringMetallic );\n\t#endif\n\tvec3 singleScattering = mix( singleScatteringDielectric, singleScatteringMetallic, material.metalness );\n\tvec3 multiScattering = mix( multiScatteringDielectric, multiScatteringMetallic, material.metalness );\n\tvec3 totalScatteringDielectric = singleScatteringDielectric + multiScatteringDielectric;\n\tvec3 diffuse = material.diffuseContribution * ( 1.0 - totalScatteringDielectric );\n\tvec3 cosineWeightedIrradiance = irradiance * RECIPROCAL_PI;\n\tvec3 indirectSpecular = radiance * singleScattering;\n\tindirectSpecular += multiScattering * cosineWeightedIrradiance;\n\tvec3 indirectDiffuse = diffuse * cosineWeightedIrradiance;\n\t#ifdef USE_SHEEN\n\t\tfloat sheenAlbedo = IBLSheenBRDF( geometryNormal, geometryViewDir, material.sheenRoughness );\n\t\tfloat sheenEnergyComp = 1.0 - max3( material.sheenColor ) * sheenAlbedo;\n\t\tindirectSpecular *= sheenEnergyComp;\n\t\tindirectDiffuse *= sheenEnergyComp;\n\t#endif\n\treflectedLight.indirectSpecular += indirectSpecular;\n\treflectedLight.indirectDiffuse += indirectDiffuse;\n}\n#define RE_Direct\t\t\t\tRE_Direct_Physical\n#define RE_Direct_RectArea\t\tRE_Direct_RectArea_Physical\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_Physical\n#define RE_IndirectSpecular\t\tRE_IndirectSpecular_Physical\nfloat computeSpecularOcclusion( const in float dotNV, const in float ambientOcclusion, const in float roughness ) {\n\treturn saturate( pow( dotNV + ambientOcclusion, exp2( - 16.0 * roughness - 1.0 ) ) - 1.0 + ambientOcclusion );\n}";
60108
+ var lights_physical_pars_fragment = "uniform sampler2D dfgLUT;\nstruct PhysicalMaterial {\n\tvec3 diffuseColor;\n\tvec3 diffuseContribution;\n\tvec3 specularColor;\n\tvec3 specularColorBlended;\n\tfloat roughness;\n\tfloat metalness;\n\tfloat specularF90;\n\tfloat dispersion;\n\t#ifdef USE_CLEARCOAT\n\t\tfloat clearcoat;\n\t\tfloat clearcoatRoughness;\n\t\tvec3 clearcoatF0;\n\t\tfloat clearcoatF90;\n\t#endif\n\t#ifdef USE_IRIDESCENCE\n\t\tfloat iridescence;\n\t\tfloat iridescenceIOR;\n\t\tfloat iridescenceThickness;\n\t\tvec3 iridescenceFresnel;\n\t\tvec3 iridescenceF0;\n\t\tvec3 iridescenceFresnelDielectric;\n\t\tvec3 iridescenceFresnelMetallic;\n\t#endif\n\t#ifdef USE_SHEEN\n\t\tvec3 sheenColor;\n\t\tfloat sheenRoughness;\n\t#endif\n\t#ifdef IOR\n\t\tfloat ior;\n\t#endif\n\t#ifdef USE_TRANSMISSION\n\t\tfloat transmission;\n\t\tfloat transmissionAlpha;\n\t\tfloat thickness;\n\t\tfloat attenuationDistance;\n\t\tvec3 attenuationColor;\n\t#endif\n\t#ifdef USE_ANISOTROPY\n\t\tfloat anisotropy;\n\t\tfloat alphaT;\n\t\tvec3 anisotropyT;\n\t\tvec3 anisotropyB;\n\t#endif\n};\nvec3 clearcoatSpecularDirect = vec3( 0.0 );\nvec3 clearcoatSpecularIndirect = vec3( 0.0 );\nvec3 sheenSpecularDirect = vec3( 0.0 );\nvec3 sheenSpecularIndirect = vec3(0.0 );\nvec3 Schlick_to_F0( const in vec3 f, const in float f90, const in float dotVH ) {\n float x = clamp( 1.0 - dotVH, 0.0, 1.0 );\n float x2 = x * x;\n float x5 = clamp( x * x2 * x2, 0.0, 0.9999 );\n return ( f - vec3( f90 ) * x5 ) / ( 1.0 - x5 );\n}\nfloat V_GGX_SmithCorrelated( const in float alpha, const in float dotNL, const in float dotNV ) {\n\tfloat a2 = pow2( alpha );\n\tfloat gv = dotNL * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNV ) );\n\tfloat gl = dotNV * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNL ) );\n\treturn 0.5 / max( gv + gl, EPSILON );\n}\nfloat D_GGX( const in float alpha, const in float dotNH ) {\n\tfloat a2 = pow2( alpha );\n\tfloat denom = pow2( dotNH ) * ( a2 - 1.0 ) + 1.0;\n\treturn RECIPROCAL_PI * a2 / pow2( denom );\n}\n#ifdef USE_ANISOTROPY\n\tfloat V_GGX_SmithCorrelated_Anisotropic( const in float alphaT, const in float alphaB, const in float dotTV, const in float dotBV, const in float dotTL, const in float dotBL, const in float dotNV, const in float dotNL ) {\n\t\tfloat gv = dotNL * length( vec3( alphaT * dotTV, alphaB * dotBV, dotNV ) );\n\t\tfloat gl = dotNV * length( vec3( alphaT * dotTL, alphaB * dotBL, dotNL ) );\n\t\treturn 0.5 / max( gv + gl, EPSILON );\n\t}\n\tfloat D_GGX_Anisotropic( const in float alphaT, const in float alphaB, const in float dotNH, const in float dotTH, const in float dotBH ) {\n\t\tfloat a2 = alphaT * alphaB;\n\t\thighp vec3 v = vec3( alphaB * dotTH, alphaT * dotBH, a2 * dotNH );\n\t\thighp float v2 = dot( v, v );\n\t\tfloat w2 = a2 / v2;\n\t\treturn RECIPROCAL_PI * a2 * pow2 ( w2 );\n\t}\n#endif\n#ifdef USE_CLEARCOAT\n\tvec3 BRDF_GGX_Clearcoat( const in vec3 lightDir, const in vec3 viewDir, const in vec3 normal, const in PhysicalMaterial material) {\n\t\tvec3 f0 = material.clearcoatF0;\n\t\tfloat f90 = material.clearcoatF90;\n\t\tfloat roughness = material.clearcoatRoughness;\n\t\tfloat alpha = pow2( roughness );\n\t\tvec3 halfDir = normalize( lightDir + viewDir );\n\t\tfloat dotNL = saturate( dot( normal, lightDir ) );\n\t\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\t\tfloat dotNH = saturate( dot( normal, halfDir ) );\n\t\tfloat dotVH = saturate( dot( viewDir, halfDir ) );\n\t\tvec3 F = F_Schlick( f0, f90, dotVH );\n\t\tfloat V = V_GGX_SmithCorrelated( alpha, dotNL, dotNV );\n\t\tfloat D = D_GGX( alpha, dotNH );\n\t\treturn F * ( V * D );\n\t}\n#endif\nvec3 BRDF_GGX( const in vec3 lightDir, const in vec3 viewDir, const in vec3 normal, const in PhysicalMaterial material ) {\n\tvec3 f0 = material.specularColorBlended;\n\tfloat f90 = material.specularF90;\n\tfloat roughness = material.roughness;\n\tfloat alpha = pow2( roughness );\n\tvec3 halfDir = normalize( lightDir + viewDir );\n\tfloat dotNL = saturate( dot( normal, lightDir ) );\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tfloat dotNH = saturate( dot( normal, halfDir ) );\n\tfloat dotVH = saturate( dot( viewDir, halfDir ) );\n\tvec3 F = F_Schlick( f0, f90, dotVH );\n\t#ifdef USE_IRIDESCENCE\n\t\tF = mix( F, material.iridescenceFresnel, material.iridescence );\n\t#endif\n\t#ifdef USE_ANISOTROPY\n\t\tfloat dotTL = dot( material.anisotropyT, lightDir );\n\t\tfloat dotTV = dot( material.anisotropyT, viewDir );\n\t\tfloat dotTH = dot( material.anisotropyT, halfDir );\n\t\tfloat dotBL = dot( material.anisotropyB, lightDir );\n\t\tfloat dotBV = dot( material.anisotropyB, viewDir );\n\t\tfloat dotBH = dot( material.anisotropyB, halfDir );\n\t\tfloat V = V_GGX_SmithCorrelated_Anisotropic( material.alphaT, alpha, dotTV, dotBV, dotTL, dotBL, dotNV, dotNL );\n\t\tfloat D = D_GGX_Anisotropic( material.alphaT, alpha, dotNH, dotTH, dotBH );\n\t#else\n\t\tfloat V = V_GGX_SmithCorrelated( alpha, dotNL, dotNV );\n\t\tfloat D = D_GGX( alpha, dotNH );\n\t#endif\n\treturn F * ( V * D );\n}\nvec2 LTC_Uv( const in vec3 N, const in vec3 V, const in float roughness ) {\n\tconst float LUT_SIZE = 64.0;\n\tconst float LUT_SCALE = ( LUT_SIZE - 1.0 ) / LUT_SIZE;\n\tconst float LUT_BIAS = 0.5 / LUT_SIZE;\n\tfloat dotNV = saturate( dot( N, V ) );\n\tvec2 uv = vec2( roughness, sqrt( 1.0 - dotNV ) );\n\tuv = uv * LUT_SCALE + LUT_BIAS;\n\treturn uv;\n}\nfloat LTC_ClippedSphereFormFactor( const in vec3 f ) {\n\tfloat l = length( f );\n\treturn max( ( l * l + f.z ) / ( l + 1.0 ), 0.0 );\n}\nvec3 LTC_EdgeVectorFormFactor( const in vec3 v1, const in vec3 v2 ) {\n\tfloat x = dot( v1, v2 );\n\tfloat y = abs( x );\n\tfloat a = 0.8543985 + ( 0.4965155 + 0.0145206 * y ) * y;\n\tfloat b = 3.4175940 + ( 4.1616724 + y ) * y;\n\tfloat v = a / b;\n\tfloat theta_sintheta = ( x > 0.0 ) ? v : 0.5 * inversesqrt( max( 1.0 - x * x, 1e-7 ) ) - v;\n\treturn cross( v1, v2 ) * theta_sintheta;\n}\nvec3 LTC_Evaluate( const in vec3 N, const in vec3 V, const in vec3 P, const in mat3 mInv, const in vec3 rectCoords[ 4 ] ) {\n\tvec3 v1 = rectCoords[ 1 ] - rectCoords[ 0 ];\n\tvec3 v2 = rectCoords[ 3 ] - rectCoords[ 0 ];\n\tvec3 lightNormal = cross( v1, v2 );\n\tif( dot( lightNormal, P - rectCoords[ 0 ] ) < 0.0 ) return vec3( 0.0 );\n\tvec3 T1, T2;\n\tT1 = normalize( V - N * dot( V, N ) );\n\tT2 = - cross( N, T1 );\n\tmat3 mat = mInv * transpose( mat3( T1, T2, N ) );\n\tvec3 coords[ 4 ];\n\tcoords[ 0 ] = mat * ( rectCoords[ 0 ] - P );\n\tcoords[ 1 ] = mat * ( rectCoords[ 1 ] - P );\n\tcoords[ 2 ] = mat * ( rectCoords[ 2 ] - P );\n\tcoords[ 3 ] = mat * ( rectCoords[ 3 ] - P );\n\tcoords[ 0 ] = normalize( coords[ 0 ] );\n\tcoords[ 1 ] = normalize( coords[ 1 ] );\n\tcoords[ 2 ] = normalize( coords[ 2 ] );\n\tcoords[ 3 ] = normalize( coords[ 3 ] );\n\tvec3 vectorFormFactor = vec3( 0.0 );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 0 ], coords[ 1 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 1 ], coords[ 2 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 2 ], coords[ 3 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 3 ], coords[ 0 ] );\n\tfloat result = LTC_ClippedSphereFormFactor( vectorFormFactor );\n\treturn vec3( result );\n}\n#if defined( USE_SHEEN )\nfloat D_Charlie( float roughness, float dotNH ) {\n\tfloat alpha = pow2( roughness );\n\tfloat invAlpha = 1.0 / alpha;\n\tfloat cos2h = dotNH * dotNH;\n\tfloat sin2h = max( 1.0 - cos2h, 0.0078125 );\n\treturn ( 2.0 + invAlpha ) * pow( sin2h, invAlpha * 0.5 ) / ( 2.0 * PI );\n}\nfloat V_Neubelt( float dotNV, float dotNL ) {\n\treturn saturate( 1.0 / ( 4.0 * ( dotNL + dotNV - dotNL * dotNV ) ) );\n}\nvec3 BRDF_Sheen( const in vec3 lightDir, const in vec3 viewDir, const in vec3 normal, vec3 sheenColor, const in float sheenRoughness ) {\n\tvec3 halfDir = normalize( lightDir + viewDir );\n\tfloat dotNL = saturate( dot( normal, lightDir ) );\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tfloat dotNH = saturate( dot( normal, halfDir ) );\n\tfloat D = D_Charlie( sheenRoughness, dotNH );\n\tfloat V = V_Neubelt( dotNV, dotNL );\n\treturn sheenColor * ( D * V );\n}\n#endif\nfloat IBLSheenBRDF( const in vec3 normal, const in vec3 viewDir, const in float roughness ) {\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tfloat r2 = roughness * roughness;\n\tfloat rInv = 1.0 / ( roughness + 0.1 );\n\tfloat a = -1.9362 + 1.0678 * roughness + 0.4573 * r2 - 0.8469 * rInv;\n\tfloat b = -0.6014 + 0.5538 * roughness - 0.4670 * r2 - 0.1255 * rInv;\n\tfloat DG = exp( a * dotNV + b );\n\treturn saturate( DG );\n}\nvec3 EnvironmentBRDF( const in vec3 normal, const in vec3 viewDir, const in vec3 specularColor, const in float specularF90, const in float roughness ) {\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tvec2 fab = texture2D( dfgLUT, vec2( roughness, dotNV ) ).rg;\n\treturn specularColor * fab.x + specularF90 * fab.y;\n}\n#ifdef USE_IRIDESCENCE\nvoid computeMultiscatteringIridescence( const in vec3 normal, const in vec3 viewDir, const in vec3 specularColor, const in float specularF90, const in float iridescence, const in vec3 iridescenceF0, const in float roughness, inout vec3 singleScatter, inout vec3 multiScatter ) {\n#else\nvoid computeMultiscattering( const in vec3 normal, const in vec3 viewDir, const in vec3 specularColor, const in float specularF90, const in float roughness, inout vec3 singleScatter, inout vec3 multiScatter ) {\n#endif\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tvec2 fab = texture2D( dfgLUT, vec2( roughness, dotNV ) ).rg;\n\t#ifdef USE_IRIDESCENCE\n\t\tvec3 Fr = mix( specularColor, iridescenceF0, iridescence );\n\t#else\n\t\tvec3 Fr = specularColor;\n\t#endif\n\tvec3 FssEss = Fr * fab.x + specularF90 * fab.y;\n\tfloat Ess = fab.x + fab.y;\n\tfloat Ems = 1.0 - Ess;\n\tvec3 Favg = Fr + ( 1.0 - Fr ) * 0.047619;\tvec3 Fms = FssEss * Favg / ( 1.0 - Ems * Favg );\n\tsingleScatter += FssEss;\n\tmultiScatter += Fms * Ems;\n}\nvec3 BRDF_GGX_Multiscatter( const in vec3 lightDir, const in vec3 viewDir, const in vec3 normal, const in PhysicalMaterial material ) {\n\tvec3 singleScatter = BRDF_GGX( lightDir, viewDir, normal, material );\n\tfloat dotNL = saturate( dot( normal, lightDir ) );\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tvec2 dfgV = texture2D( dfgLUT, vec2( material.roughness, dotNV ) ).rg;\n\tvec2 dfgL = texture2D( dfgLUT, vec2( material.roughness, dotNL ) ).rg;\n\tvec3 FssEss_V = material.specularColorBlended * dfgV.x + material.specularF90 * dfgV.y;\n\tvec3 FssEss_L = material.specularColorBlended * dfgL.x + material.specularF90 * dfgL.y;\n\tfloat Ess_V = dfgV.x + dfgV.y;\n\tfloat Ess_L = dfgL.x + dfgL.y;\n\tfloat Ems_V = 1.0 - Ess_V;\n\tfloat Ems_L = 1.0 - Ess_L;\n\tvec3 Favg = material.specularColorBlended + ( 1.0 - material.specularColorBlended ) * 0.047619;\n\tvec3 Fms = FssEss_V * FssEss_L * Favg / ( 1.0 - Ems_V * Ems_L * Favg + EPSILON );\n\tfloat compensationFactor = Ems_V * Ems_L;\n\tvec3 multiScatter = Fms * compensationFactor;\n\treturn singleScatter + multiScatter;\n}\n#if NUM_RECT_AREA_LIGHTS > 0\n\tvoid RE_Direct_RectArea_Physical( const in RectAreaLight rectAreaLight, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\t\tvec3 normal = geometryNormal;\n\t\tvec3 viewDir = geometryViewDir;\n\t\tvec3 position = geometryPosition;\n\t\tvec3 lightPos = rectAreaLight.position;\n\t\tvec3 halfWidth = rectAreaLight.halfWidth;\n\t\tvec3 halfHeight = rectAreaLight.halfHeight;\n\t\tvec3 lightColor = rectAreaLight.color;\n\t\tfloat roughness = material.roughness;\n\t\tvec3 rectCoords[ 4 ];\n\t\trectCoords[ 0 ] = lightPos + halfWidth - halfHeight;\t\trectCoords[ 1 ] = lightPos - halfWidth - halfHeight;\n\t\trectCoords[ 2 ] = lightPos - halfWidth + halfHeight;\n\t\trectCoords[ 3 ] = lightPos + halfWidth + halfHeight;\n\t\tvec2 uv = LTC_Uv( normal, viewDir, roughness );\n\t\tvec4 t1 = texture2D( ltc_1, uv );\n\t\tvec4 t2 = texture2D( ltc_2, uv );\n\t\tmat3 mInv = mat3(\n\t\t\tvec3( t1.x, 0, t1.y ),\n\t\t\tvec3( 0, 1, 0 ),\n\t\t\tvec3( t1.z, 0, t1.w )\n\t\t);\n\t\tvec3 fresnel = ( material.specularColorBlended * t2.x + ( material.specularF90 - material.specularColorBlended ) * t2.y );\n\t\treflectedLight.directSpecular += lightColor * fresnel * LTC_Evaluate( normal, viewDir, position, mInv, rectCoords );\n\t\treflectedLight.directDiffuse += lightColor * material.diffuseContribution * LTC_Evaluate( normal, viewDir, position, mat3( 1.0 ), rectCoords );\n\t\t#ifdef USE_CLEARCOAT\n\t\t\tvec3 Ncc = geometryClearcoatNormal;\n\t\t\tvec2 uvClearcoat = LTC_Uv( Ncc, viewDir, material.clearcoatRoughness );\n\t\t\tvec4 t1Clearcoat = texture2D( ltc_1, uvClearcoat );\n\t\t\tvec4 t2Clearcoat = texture2D( ltc_2, uvClearcoat );\n\t\t\tmat3 mInvClearcoat = mat3(\n\t\t\t\tvec3( t1Clearcoat.x, 0, t1Clearcoat.y ),\n\t\t\t\tvec3( 0, 1, 0 ),\n\t\t\t\tvec3( t1Clearcoat.z, 0, t1Clearcoat.w )\n\t\t\t);\n\t\t\tvec3 fresnelClearcoat = material.clearcoatF0 * t2Clearcoat.x + ( material.clearcoatF90 - material.clearcoatF0 ) * t2Clearcoat.y;\n\t\t\tclearcoatSpecularDirect += lightColor * fresnelClearcoat * LTC_Evaluate( Ncc, viewDir, position, mInvClearcoat, rectCoords );\n\t\t#endif\n\t}\n#endif\nvoid RE_Direct_Physical( const in IncidentLight directLight, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\tfloat dotNL = saturate( dot( geometryNormal, directLight.direction ) );\n\tvec3 irradiance = dotNL * directLight.color;\n\t#ifdef USE_CLEARCOAT\n\t\tfloat dotNLcc = saturate( dot( geometryClearcoatNormal, directLight.direction ) );\n\t\tvec3 ccIrradiance = dotNLcc * directLight.color;\n\t\tclearcoatSpecularDirect += ccIrradiance * BRDF_GGX_Clearcoat( directLight.direction, geometryViewDir, geometryClearcoatNormal, material );\n\t#endif\n\t#ifdef USE_SHEEN\n \n \t\tsheenSpecularDirect += irradiance * BRDF_Sheen( directLight.direction, geometryViewDir, geometryNormal, material.sheenColor, material.sheenRoughness );\n \n \t\tfloat sheenAlbedoV = IBLSheenBRDF( geometryNormal, geometryViewDir, material.sheenRoughness );\n \t\tfloat sheenAlbedoL = IBLSheenBRDF( geometryNormal, directLight.direction, material.sheenRoughness );\n \n \t\tfloat sheenEnergyComp = 1.0 - max3( material.sheenColor ) * max( sheenAlbedoV, sheenAlbedoL );\n \n \t\tirradiance *= sheenEnergyComp;\n \n \t#endif\n\treflectedLight.directSpecular += irradiance * BRDF_GGX_Multiscatter( directLight.direction, geometryViewDir, geometryNormal, material );\n\treflectedLight.directDiffuse += irradiance * BRDF_Lambert( material.diffuseContribution );\n}\nvoid RE_IndirectDiffuse_Physical( const in vec3 irradiance, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\tvec3 diffuse = irradiance * BRDF_Lambert( material.diffuseContribution );\n\t#ifdef USE_SHEEN\n\t\tfloat sheenAlbedo = IBLSheenBRDF( geometryNormal, geometryViewDir, material.sheenRoughness );\n\t\tfloat sheenEnergyComp = 1.0 - max3( material.sheenColor ) * sheenAlbedo;\n\t\tdiffuse *= sheenEnergyComp;\n\t#endif\n\treflectedLight.indirectDiffuse += diffuse;\n}\nvoid RE_IndirectSpecular_Physical( const in vec3 radiance, const in vec3 irradiance, const in vec3 clearcoatRadiance, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in PhysicalMaterial material, inout ReflectedLight reflectedLight) {\n\t#ifdef USE_CLEARCOAT\n\t\tclearcoatSpecularIndirect += clearcoatRadiance * EnvironmentBRDF( geometryClearcoatNormal, geometryViewDir, material.clearcoatF0, material.clearcoatF90, material.clearcoatRoughness );\n\t#endif\n\t#ifdef USE_SHEEN\n\t\tsheenSpecularIndirect += irradiance * material.sheenColor * IBLSheenBRDF( geometryNormal, geometryViewDir, material.sheenRoughness ) * RECIPROCAL_PI;\n \t#endif\n\tvec3 singleScatteringDielectric = vec3( 0.0 );\n\tvec3 multiScatteringDielectric = vec3( 0.0 );\n\tvec3 singleScatteringMetallic = vec3( 0.0 );\n\tvec3 multiScatteringMetallic = vec3( 0.0 );\n\t#ifdef USE_IRIDESCENCE\n\t\tcomputeMultiscatteringIridescence( geometryNormal, geometryViewDir, material.specularColor, material.specularF90, material.iridescence, material.iridescenceFresnelDielectric, material.roughness, singleScatteringDielectric, multiScatteringDielectric );\n\t\tcomputeMultiscatteringIridescence( geometryNormal, geometryViewDir, material.diffuseColor, material.specularF90, material.iridescence, material.iridescenceFresnelMetallic, material.roughness, singleScatteringMetallic, multiScatteringMetallic );\n\t#else\n\t\tcomputeMultiscattering( geometryNormal, geometryViewDir, material.specularColor, material.specularF90, material.roughness, singleScatteringDielectric, multiScatteringDielectric );\n\t\tcomputeMultiscattering( geometryNormal, geometryViewDir, material.diffuseColor, material.specularF90, material.roughness, singleScatteringMetallic, multiScatteringMetallic );\n\t#endif\n\tvec3 singleScattering = mix( singleScatteringDielectric, singleScatteringMetallic, material.metalness );\n\tvec3 multiScattering = mix( multiScatteringDielectric, multiScatteringMetallic, material.metalness );\n\tvec3 totalScatteringDielectric = singleScatteringDielectric + multiScatteringDielectric;\n\tvec3 diffuse = material.diffuseContribution * ( 1.0 - totalScatteringDielectric );\n\tvec3 cosineWeightedIrradiance = irradiance * RECIPROCAL_PI;\n\tvec3 indirectSpecular = radiance * singleScattering;\n\tindirectSpecular += multiScattering * cosineWeightedIrradiance;\n\tvec3 indirectDiffuse = diffuse * cosineWeightedIrradiance;\n\t#ifdef USE_SHEEN\n\t\tfloat sheenAlbedo = IBLSheenBRDF( geometryNormal, geometryViewDir, material.sheenRoughness );\n\t\tfloat sheenEnergyComp = 1.0 - max3( material.sheenColor ) * sheenAlbedo;\n\t\tindirectSpecular *= sheenEnergyComp;\n\t\tindirectDiffuse *= sheenEnergyComp;\n\t#endif\n\treflectedLight.indirectSpecular += indirectSpecular;\n\treflectedLight.indirectDiffuse += indirectDiffuse;\n}\n#define RE_Direct\t\t\t\tRE_Direct_Physical\n#define RE_Direct_RectArea\t\tRE_Direct_RectArea_Physical\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_Physical\n#define RE_IndirectSpecular\t\tRE_IndirectSpecular_Physical\nfloat computeSpecularOcclusion( const in float dotNV, const in float ambientOcclusion, const in float roughness ) {\n\treturn saturate( pow( dotNV + ambientOcclusion, exp2( - 16.0 * roughness - 1.0 ) ) - 1.0 + ambientOcclusion );\n}";
59866
60109
 
59867
- var lights_fragment_begin = "\nvec3 geometryPosition = - vViewPosition;\nvec3 geometryNormal = normal;\nvec3 geometryViewDir = ( isOrthographic ) ? vec3( 0, 0, 1 ) : normalize( vViewPosition );\nvec3 geometryClearcoatNormal = vec3( 0.0 );\n#ifdef USE_CLEARCOAT\n\tgeometryClearcoatNormal = clearcoatNormal;\n#endif\n#ifdef USE_IRIDESCENCE\n\tfloat dotNVi = saturate( dot( normal, geometryViewDir ) );\n\tif ( material.iridescenceThickness == 0.0 ) {\n\t\tmaterial.iridescence = 0.0;\n\t} else {\n\t\tmaterial.iridescence = saturate( material.iridescence );\n\t}\n\tif ( material.iridescence > 0.0 ) {\n\t\tmaterial.iridescenceFresnelDielectric = evalIridescence( 1.0, material.iridescenceIOR, dotNVi, material.iridescenceThickness, material.specularColor );\n\t\tmaterial.iridescenceFresnelMetallic = evalIridescence( 1.0, material.iridescenceIOR, dotNVi, material.iridescenceThickness, material.diffuseColor );\n\t\tmaterial.iridescenceFresnel = mix( material.iridescenceFresnelDielectric, material.iridescenceFresnelMetallic, material.metalness );\n\t\tmaterial.iridescenceF0 = Schlick_to_F0( material.iridescenceFresnel, 1.0, dotNVi );\n\t}\n#endif\nIncidentLight directLight;\n#if ( NUM_POINT_LIGHTS > 0 ) && defined( RE_Direct )\n\tPointLight pointLight;\n\t#if defined( USE_SHADOWMAP ) && NUM_POINT_LIGHT_SHADOWS > 0\n\tPointLightShadow pointLightShadow;\n\t#endif\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\n\t\tpointLight = pointLights[ i ];\n\t\tgetPointLightInfo( pointLight, geometryPosition, directLight );\n\t\t#if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_POINT_LIGHT_SHADOWS ) && ( defined( SHADOWMAP_TYPE_PCF ) || defined( SHADOWMAP_TYPE_BASIC ) )\n\t\tpointLightShadow = pointLightShadows[ i ];\n\t\tdirectLight.color *= ( directLight.visible && receiveShadow ) ? getPointShadow( pointShadowMap[ i ], pointLightShadow.shadowMapSize, pointLightShadow.shadowIntensity, pointLightShadow.shadowBias, pointLightShadow.shadowRadius, vPointShadowCoord[ i ], pointLightShadow.shadowCameraNear, pointLightShadow.shadowCameraFar ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, material, reflectedLight );\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if ( NUM_SPOT_LIGHTS > 0 ) && defined( RE_Direct )\n\tSpotLight spotLight;\n\tvec4 spotColor;\n\tvec3 spotLightCoord;\n\tbool inSpotLightMap;\n\t#if defined( USE_SHADOWMAP ) && NUM_SPOT_LIGHT_SHADOWS > 0\n\tSpotLightShadow spotLightShadow;\n\t#endif\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\n\t\tspotLight = spotLights[ i ];\n\t\tgetSpotLightInfo( spotLight, geometryPosition, directLight );\n\t\t#if ( UNROLLED_LOOP_INDEX < NUM_SPOT_LIGHT_SHADOWS_WITH_MAPS )\n\t\t#define SPOT_LIGHT_MAP_INDEX UNROLLED_LOOP_INDEX\n\t\t#elif ( UNROLLED_LOOP_INDEX < NUM_SPOT_LIGHT_SHADOWS )\n\t\t#define SPOT_LIGHT_MAP_INDEX NUM_SPOT_LIGHT_MAPS\n\t\t#else\n\t\t#define SPOT_LIGHT_MAP_INDEX ( UNROLLED_LOOP_INDEX - NUM_SPOT_LIGHT_SHADOWS + NUM_SPOT_LIGHT_SHADOWS_WITH_MAPS )\n\t\t#endif\n\t\t#if ( SPOT_LIGHT_MAP_INDEX < NUM_SPOT_LIGHT_MAPS )\n\t\t\tspotLightCoord = vSpotLightCoord[ i ].xyz / vSpotLightCoord[ i ].w;\n\t\t\tinSpotLightMap = all( lessThan( abs( spotLightCoord * 2. - 1. ), vec3( 1.0 ) ) );\n\t\t\tspotColor = texture2D( spotLightMap[ SPOT_LIGHT_MAP_INDEX ], spotLightCoord.xy );\n\t\t\tdirectLight.color = inSpotLightMap ? directLight.color * spotColor.rgb : directLight.color;\n\t\t#endif\n\t\t#undef SPOT_LIGHT_MAP_INDEX\n\t\t#if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_SPOT_LIGHT_SHADOWS )\n\t\tspotLightShadow = spotLightShadows[ i ];\n\t\tdirectLight.color *= ( directLight.visible && receiveShadow ) ? getShadow( spotShadowMap[ i ], spotLightShadow.shadowMapSize, spotLightShadow.shadowIntensity, spotLightShadow.shadowBias, spotLightShadow.shadowRadius, vSpotLightCoord[ i ] ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, material, reflectedLight );\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if ( NUM_DIR_LIGHTS > 0 ) && defined( RE_Direct )\n\tDirectionalLight directionalLight;\n\t#if defined( USE_SHADOWMAP ) && NUM_DIR_LIGHT_SHADOWS > 0\n\tDirectionalLightShadow directionalLightShadow;\n\t#endif\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\n\t\tdirectionalLight = directionalLights[ i ];\n\t\tgetDirectionalLightInfo( directionalLight, directLight );\n\t\t#if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_DIR_LIGHT_SHADOWS )\n\t\tdirectionalLightShadow = directionalLightShadows[ i ];\n\t\tdirectLight.color *= ( directLight.visible && receiveShadow ) ? getShadow( directionalShadowMap[ i ], directionalLightShadow.shadowMapSize, directionalLightShadow.shadowIntensity, directionalLightShadow.shadowBias, directionalLightShadow.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, material, reflectedLight );\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if ( NUM_RECT_AREA_LIGHTS > 0 ) && defined( RE_Direct_RectArea )\n\tRectAreaLight rectAreaLight;\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_RECT_AREA_LIGHTS; i ++ ) {\n\t\trectAreaLight = rectAreaLights[ i ];\n\t\tRE_Direct_RectArea( rectAreaLight, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, material, reflectedLight );\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if defined( RE_IndirectDiffuse )\n\tvec3 iblIrradiance = vec3( 0.0 );\n\tvec3 irradiance = getAmbientLightIrradiance( ambientLightColor );\n\t#if defined( USE_LIGHT_PROBES )\n\t\tirradiance += getLightProbeIrradiance( lightProbe, geometryNormal );\n\t#endif\n\t#if ( NUM_HEMI_LIGHTS > 0 )\n\t\t#pragma unroll_loop_start\n\t\tfor ( int i = 0; i < NUM_HEMI_LIGHTS; i ++ ) {\n\t\t\tirradiance += getHemisphereLightIrradiance( hemisphereLights[ i ], geometryNormal );\n\t\t}\n\t\t#pragma unroll_loop_end\n\t#endif\n#endif\n#if defined( RE_IndirectSpecular )\n\tvec3 radiance = vec3( 0.0 );\n\tvec3 clearcoatRadiance = vec3( 0.0 );\n#endif";
60110
+ var lights_fragment_begin = "\nvec3 geometryPosition = - vViewPosition;\nvec3 geometryNormal = normal;\nvec3 geometryViewDir = ( isOrthographic ) ? vec3( 0, 0, 1 ) : normalize( vViewPosition );\nvec3 geometryClearcoatNormal = vec3( 0.0 );\n#ifdef USE_CLEARCOAT\n\tgeometryClearcoatNormal = clearcoatNormal;\n#endif\n#ifdef USE_IRIDESCENCE\n\tfloat dotNVi = saturate( dot( normal, geometryViewDir ) );\n\tif ( material.iridescenceThickness == 0.0 ) {\n\t\tmaterial.iridescence = 0.0;\n\t} else {\n\t\tmaterial.iridescence = saturate( material.iridescence );\n\t}\n\tif ( material.iridescence > 0.0 ) {\n\t\tmaterial.iridescenceFresnelDielectric = evalIridescence( 1.0, material.iridescenceIOR, dotNVi, material.iridescenceThickness, material.specularColor );\n\t\tmaterial.iridescenceFresnelMetallic = evalIridescence( 1.0, material.iridescenceIOR, dotNVi, material.iridescenceThickness, material.diffuseColor );\n\t\tmaterial.iridescenceFresnel = mix( material.iridescenceFresnelDielectric, material.iridescenceFresnelMetallic, material.metalness );\n\t\tmaterial.iridescenceF0 = Schlick_to_F0( material.iridescenceFresnel, 1.0, dotNVi );\n\t}\n#endif\nIncidentLight directLight;\n#if ( NUM_POINT_LIGHTS > 0 ) && defined( RE_Direct )\n\tPointLight pointLight;\n\t#if defined( USE_SHADOWMAP ) && NUM_POINT_LIGHT_SHADOWS > 0\n\tPointLightShadow pointLightShadow;\n\t#endif\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\n\t\tpointLight = pointLights[ i ];\n\t\tgetPointLightInfo( pointLight, geometryPosition, directLight );\n\t\t#if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_POINT_LIGHT_SHADOWS ) && ( defined( SHADOWMAP_TYPE_PCF ) || defined( SHADOWMAP_TYPE_BASIC ) )\n\t\tpointLightShadow = pointLightShadows[ i ];\n\t\tdirectLight.color *= ( directLight.visible && receiveShadow ) ? getPointShadow( pointShadowMap[ i ], pointLightShadow.shadowMapSize, pointLightShadow.shadowIntensity, pointLightShadow.shadowBias, pointLightShadow.shadowRadius, vPointShadowCoord[ i ], pointLightShadow.shadowCameraNear, pointLightShadow.shadowCameraFar ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, material, reflectedLight );\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if ( NUM_SPOT_LIGHTS > 0 ) && defined( RE_Direct )\n\tSpotLight spotLight;\n\tvec4 spotColor;\n\tvec3 spotLightCoord;\n\tbool inSpotLightMap;\n\t#if defined( USE_SHADOWMAP ) && NUM_SPOT_LIGHT_SHADOWS > 0\n\tSpotLightShadow spotLightShadow;\n\t#endif\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\n\t\tspotLight = spotLights[ i ];\n\t\tgetSpotLightInfo( spotLight, geometryPosition, directLight );\n\t\t#if ( UNROLLED_LOOP_INDEX < NUM_SPOT_LIGHT_SHADOWS_WITH_MAPS )\n\t\t#define SPOT_LIGHT_MAP_INDEX UNROLLED_LOOP_INDEX\n\t\t#elif ( UNROLLED_LOOP_INDEX < NUM_SPOT_LIGHT_SHADOWS )\n\t\t#define SPOT_LIGHT_MAP_INDEX NUM_SPOT_LIGHT_MAPS\n\t\t#else\n\t\t#define SPOT_LIGHT_MAP_INDEX ( UNROLLED_LOOP_INDEX - NUM_SPOT_LIGHT_SHADOWS + NUM_SPOT_LIGHT_SHADOWS_WITH_MAPS )\n\t\t#endif\n\t\t#if ( SPOT_LIGHT_MAP_INDEX < NUM_SPOT_LIGHT_MAPS )\n\t\t\tspotLightCoord = vSpotLightCoord[ i ].xyz / vSpotLightCoord[ i ].w;\n\t\t\tinSpotLightMap = all( lessThan( abs( spotLightCoord * 2. - 1. ), vec3( 1.0 ) ) );\n\t\t\tspotColor = texture2D( spotLightMap[ SPOT_LIGHT_MAP_INDEX ], spotLightCoord.xy );\n\t\t\tdirectLight.color = inSpotLightMap ? directLight.color * spotColor.rgb : directLight.color;\n\t\t#endif\n\t\t#undef SPOT_LIGHT_MAP_INDEX\n\t\t#if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_SPOT_LIGHT_SHADOWS )\n\t\tspotLightShadow = spotLightShadows[ i ];\n\t\tdirectLight.color *= ( directLight.visible && receiveShadow ) ? getShadow( spotShadowMap[ i ], spotLightShadow.shadowMapSize, spotLightShadow.shadowIntensity, spotLightShadow.shadowBias, spotLightShadow.shadowRadius, vSpotLightCoord[ i ] ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, material, reflectedLight );\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if ( NUM_DIR_LIGHTS > 0 ) && defined( RE_Direct )\n\tDirectionalLight directionalLight;\n\t#if defined( USE_SHADOWMAP ) && NUM_DIR_LIGHT_SHADOWS > 0\n\tDirectionalLightShadow directionalLightShadow;\n\t#endif\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\n\t\tdirectionalLight = directionalLights[ i ];\n\t\tgetDirectionalLightInfo( directionalLight, directLight );\n\t\t#if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_DIR_LIGHT_SHADOWS )\n\t\tdirectionalLightShadow = directionalLightShadows[ i ];\n\t\tdirectLight.color *= ( directLight.visible && receiveShadow ) ? getShadow( directionalShadowMap[ i ], directionalLightShadow.shadowMapSize, directionalLightShadow.shadowIntensity, directionalLightShadow.shadowBias, directionalLightShadow.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, material, reflectedLight );\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if ( NUM_RECT_AREA_LIGHTS > 0 ) && defined( RE_Direct_RectArea )\n\tRectAreaLight rectAreaLight;\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_RECT_AREA_LIGHTS; i ++ ) {\n\t\trectAreaLight = rectAreaLights[ i ];\n\t\tRE_Direct_RectArea( rectAreaLight, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, material, reflectedLight );\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if defined( RE_IndirectDiffuse )\n\tvec3 iblIrradiance = vec3( 0.0 );\n\tvec3 irradiance = getAmbientLightIrradiance( ambientLightColor );\n\t#if defined( USE_LIGHT_PROBES )\n\t\tirradiance += getLightProbeIrradiance( lightProbe, geometryNormal );\n\t#endif\n\t#if ( NUM_HEMI_LIGHTS > 0 )\n\t\t#pragma unroll_loop_start\n\t\tfor ( int i = 0; i < NUM_HEMI_LIGHTS; i ++ ) {\n\t\t\tirradiance += getHemisphereLightIrradiance( hemisphereLights[ i ], geometryNormal );\n\t\t}\n\t\t#pragma unroll_loop_end\n\t#endif\n\t#ifdef USE_LIGHT_PROBES_GRID\n\t\tvec3 probeWorldPos = ( ( vec4( geometryPosition, 1.0 ) - viewMatrix[ 3 ] ) * viewMatrix ).xyz;\n\t\tvec3 probeWorldNormal = inverseTransformDirection( geometryNormal, viewMatrix );\n\t\tirradiance += getLightProbeGridIrradiance( probeWorldPos, probeWorldNormal );\n\t#endif\n#endif\n#if defined( RE_IndirectSpecular )\n\tvec3 radiance = vec3( 0.0 );\n\tvec3 clearcoatRadiance = vec3( 0.0 );\n#endif";
59868
60111
 
59869
60112
  var lights_fragment_maps = "#if defined( RE_IndirectDiffuse )\n\t#ifdef USE_LIGHTMAP\n\t\tvec4 lightMapTexel = texture2D( lightMap, vLightMapUv );\n\t\tvec3 lightMapIrradiance = lightMapTexel.rgb * lightMapIntensity;\n\t\tirradiance += lightMapIrradiance;\n\t#endif\n\t#if defined( USE_ENVMAP ) && defined( ENVMAP_TYPE_CUBE_UV )\n\t\t#if defined( STANDARD ) || defined( LAMBERT ) || defined( PHONG )\n\t\t\tiblIrradiance += getIBLIrradiance( geometryNormal );\n\t\t#endif\n\t#endif\n#endif\n#if defined( USE_ENVMAP ) && defined( RE_IndirectSpecular )\n\t#ifdef USE_ANISOTROPY\n\t\tradiance += getIBLAnisotropyRadiance( geometryViewDir, geometryNormal, material.roughness, material.anisotropyB, material.anisotropy );\n\t#else\n\t\tradiance += getIBLRadiance( geometryViewDir, geometryNormal, material.roughness );\n\t#endif\n\t#ifdef USE_CLEARCOAT\n\t\tclearcoatRadiance += getIBLRadiance( geometryViewDir, geometryClearcoatNormal, material.clearcoatRoughness );\n\t#endif\n#endif";
59870
60113
 
59871
60114
  var lights_fragment_end = "#if defined( RE_IndirectDiffuse )\n\t#if defined( LAMBERT ) || defined( PHONG )\n\t\tirradiance += iblIrradiance;\n\t#endif\n\tRE_IndirectDiffuse( irradiance, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, material, reflectedLight );\n#endif\n#if defined( RE_IndirectSpecular )\n\tRE_IndirectSpecular( radiance, iblIrradiance, clearcoatRadiance, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, material, reflectedLight );\n#endif";
59872
60115
 
60116
+ var lightprobes_pars_fragment = "#ifdef USE_LIGHT_PROBES_GRID\nuniform highp sampler3D probesSH;\nuniform vec3 probesMin;\nuniform vec3 probesMax;\nuniform vec3 probesResolution;\nvec3 getLightProbeGridIrradiance( vec3 worldPos, vec3 worldNormal ) {\n\tvec3 res = probesResolution;\n\tvec3 gridRange = probesMax - probesMin;\n\tvec3 resMinusOne = res - 1.0;\n\tvec3 probeSpacing = gridRange / resMinusOne;\n\tvec3 samplePos = worldPos + worldNormal * probeSpacing * 0.5;\n\tvec3 uvw = clamp( ( samplePos - probesMin ) / gridRange, 0.0, 1.0 );\n\tuvw = uvw * resMinusOne / res + 0.5 / res;\n\tfloat nz = res.z;\n\tfloat paddedSlices = nz + 2.0;\n\tfloat atlasDepth = 7.0 * paddedSlices;\n\tfloat uvZBase = uvw.z * nz + 1.0;\n\tvec4 s0 = texture( probesSH, vec3( uvw.xy, ( uvZBase ) / atlasDepth ) );\n\tvec4 s1 = texture( probesSH, vec3( uvw.xy, ( uvZBase + paddedSlices ) / atlasDepth ) );\n\tvec4 s2 = texture( probesSH, vec3( uvw.xy, ( uvZBase + 2.0 * paddedSlices ) / atlasDepth ) );\n\tvec4 s3 = texture( probesSH, vec3( uvw.xy, ( uvZBase + 3.0 * paddedSlices ) / atlasDepth ) );\n\tvec4 s4 = texture( probesSH, vec3( uvw.xy, ( uvZBase + 4.0 * paddedSlices ) / atlasDepth ) );\n\tvec4 s5 = texture( probesSH, vec3( uvw.xy, ( uvZBase + 5.0 * paddedSlices ) / atlasDepth ) );\n\tvec4 s6 = texture( probesSH, vec3( uvw.xy, ( uvZBase + 6.0 * paddedSlices ) / atlasDepth ) );\n\tvec3 c0 = s0.xyz;\n\tvec3 c1 = vec3( s0.w, s1.xy );\n\tvec3 c2 = vec3( s1.zw, s2.x );\n\tvec3 c3 = s2.yzw;\n\tvec3 c4 = s3.xyz;\n\tvec3 c5 = vec3( s3.w, s4.xy );\n\tvec3 c6 = vec3( s4.zw, s5.x );\n\tvec3 c7 = s5.yzw;\n\tvec3 c8 = s6.xyz;\n\tfloat x = worldNormal.x, y = worldNormal.y, z = worldNormal.z;\n\tvec3 result = c0 * 0.886227;\n\tresult += c1 * 2.0 * 0.511664 * y;\n\tresult += c2 * 2.0 * 0.511664 * z;\n\tresult += c3 * 2.0 * 0.511664 * x;\n\tresult += c4 * 2.0 * 0.429043 * x * y;\n\tresult += c5 * 2.0 * 0.429043 * y * z;\n\tresult += c6 * ( 0.743125 * z * z - 0.247708 );\n\tresult += c7 * 2.0 * 0.429043 * x * z;\n\tresult += c8 * 0.429043 * ( x * x - y * y );\n\treturn max( result, vec3( 0.0 ) );\n}\n#endif";
60117
+
59873
60118
  var logdepthbuf_fragment = "#if defined( USE_LOGARITHMIC_DEPTH_BUFFER )\n\tgl_FragDepth = vIsPerspective == 0.0 ? gl_FragCoord.z : log2( vFragDepth ) * logDepthBufFC * 0.5;\n#endif";
59874
60119
 
59875
60120
  var logdepthbuf_pars_fragment = "#if defined( USE_LOGARITHMIC_DEPTH_BUFFER )\n\tuniform float logDepthBufFC;\n\tvarying float vFragDepth;\n\tvarying float vIsPerspective;\n#endif";
@@ -59902,7 +60147,7 @@ var morphtarget_vertex = "#ifdef USE_MORPHTARGETS\n\ttransformed *= morphTargetB
59902
60147
 
59903
60148
  var normal_fragment_begin = "float faceDirection = gl_FrontFacing ? 1.0 : - 1.0;\n#ifdef FLAT_SHADED\n\tvec3 fdx = dFdx( vViewPosition );\n\tvec3 fdy = dFdy( vViewPosition );\n\tvec3 normal = normalize( cross( fdx, fdy ) );\n#else\n\tvec3 normal = normalize( vNormal );\n\t#ifdef DOUBLE_SIDED\n\t\tnormal *= faceDirection;\n\t#endif\n#endif\n#if defined( USE_NORMALMAP_TANGENTSPACE ) || defined( USE_CLEARCOAT_NORMALMAP ) || defined( USE_ANISOTROPY )\n\t#ifdef USE_TANGENT\n\t\tmat3 tbn = mat3( normalize( vTangent ), normalize( vBitangent ), normal );\n\t#else\n\t\tmat3 tbn = getTangentFrame( - vViewPosition, normal,\n\t\t#if defined( USE_NORMALMAP )\n\t\t\tvNormalMapUv\n\t\t#elif defined( USE_CLEARCOAT_NORMALMAP )\n\t\t\tvClearcoatNormalMapUv\n\t\t#else\n\t\t\tvUv\n\t\t#endif\n\t\t);\n\t#endif\n\t#if defined( DOUBLE_SIDED ) && ! defined( FLAT_SHADED )\n\t\ttbn[0] *= faceDirection;\n\t\ttbn[1] *= faceDirection;\n\t#endif\n#endif\n#ifdef USE_CLEARCOAT_NORMALMAP\n\t#ifdef USE_TANGENT\n\t\tmat3 tbn2 = mat3( normalize( vTangent ), normalize( vBitangent ), normal );\n\t#else\n\t\tmat3 tbn2 = getTangentFrame( - vViewPosition, normal, vClearcoatNormalMapUv );\n\t#endif\n\t#if defined( DOUBLE_SIDED ) && ! defined( FLAT_SHADED )\n\t\ttbn2[0] *= faceDirection;\n\t\ttbn2[1] *= faceDirection;\n\t#endif\n#endif\nvec3 nonPerturbedNormal = normal;";
59904
60149
 
59905
- var normal_fragment_maps = "#ifdef USE_NORMALMAP_OBJECTSPACE\n\tnormal = texture2D( normalMap, vNormalMapUv ).xyz * 2.0 - 1.0;\n\t#ifdef FLIP_SIDED\n\t\tnormal = - normal;\n\t#endif\n\t#ifdef DOUBLE_SIDED\n\t\tnormal = normal * faceDirection;\n\t#endif\n\tnormal = normalize( normalMatrix * normal );\n#elif defined( USE_NORMALMAP_TANGENTSPACE )\n\tvec3 mapN = texture2D( normalMap, vNormalMapUv ).xyz * 2.0 - 1.0;\n\tmapN.xy *= normalScale;\n\tnormal = normalize( tbn * mapN );\n#elif defined( USE_BUMPMAP )\n\tnormal = perturbNormalArb( - vViewPosition, normal, dHdxy_fwd(), faceDirection );\n#endif";
60150
+ var normal_fragment_maps = "#ifdef USE_NORMALMAP_OBJECTSPACE\n\tnormal = texture2D( normalMap, vNormalMapUv ).xyz * 2.0 - 1.0;\n\t#ifdef FLIP_SIDED\n\t\tnormal = - normal;\n\t#endif\n\t#ifdef DOUBLE_SIDED\n\t\tnormal = normal * faceDirection;\n\t#endif\n\tnormal = normalize( normalMatrix * normal );\n#elif defined( USE_NORMALMAP_TANGENTSPACE )\n\tvec3 mapN = texture2D( normalMap, vNormalMapUv ).xyz * 2.0 - 1.0;\n\t#if defined( USE_PACKED_NORMALMAP )\n\t\tmapN = vec3( mapN.xy, sqrt( saturate( 1.0 - dot( mapN.xy, mapN.xy ) ) ) );\n\t#endif\n\tmapN.xy *= normalScale;\n\tnormal = normalize( tbn * mapN );\n#elif defined( USE_BUMPMAP )\n\tnormal = perturbNormalArb( - vViewPosition, normal, dHdxy_fwd(), faceDirection );\n#endif";
59906
60151
 
59907
60152
  var normal_pars_fragment = "#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n\t#ifdef USE_TANGENT\n\t\tvarying vec3 vTangent;\n\t\tvarying vec3 vBitangent;\n\t#endif\n#endif";
59908
60153
 
@@ -59940,7 +60185,7 @@ var shadowmap_pars_fragment = "#if NUM_SPOT_LIGHT_COORDS > 0\n\tvarying vec4 vSp
59940
60185
 
59941
60186
  var shadowmap_pars_vertex = "#if NUM_SPOT_LIGHT_COORDS > 0\n\tuniform mat4 spotLightMatrix[ NUM_SPOT_LIGHT_COORDS ];\n\tvarying vec4 vSpotLightCoord[ NUM_SPOT_LIGHT_COORDS ];\n#endif\n#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHT_SHADOWS > 0\n\t\tuniform mat4 directionalShadowMatrix[ NUM_DIR_LIGHT_SHADOWS ];\n\t\tvarying vec4 vDirectionalShadowCoord[ NUM_DIR_LIGHT_SHADOWS ];\n\t\tstruct DirectionalLightShadow {\n\t\t\tfloat shadowIntensity;\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t};\n\t\tuniform DirectionalLightShadow directionalLightShadows[ NUM_DIR_LIGHT_SHADOWS ];\n\t#endif\n\t#if NUM_SPOT_LIGHT_SHADOWS > 0\n\t\tstruct SpotLightShadow {\n\t\t\tfloat shadowIntensity;\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t};\n\t\tuniform SpotLightShadow spotLightShadows[ NUM_SPOT_LIGHT_SHADOWS ];\n\t#endif\n\t#if NUM_POINT_LIGHT_SHADOWS > 0\n\t\tuniform mat4 pointShadowMatrix[ NUM_POINT_LIGHT_SHADOWS ];\n\t\tvarying vec4 vPointShadowCoord[ NUM_POINT_LIGHT_SHADOWS ];\n\t\tstruct PointLightShadow {\n\t\t\tfloat shadowIntensity;\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t\tfloat shadowCameraNear;\n\t\t\tfloat shadowCameraFar;\n\t\t};\n\t\tuniform PointLightShadow pointLightShadows[ NUM_POINT_LIGHT_SHADOWS ];\n\t#endif\n#endif";
59942
60187
 
59943
- var shadowmap_vertex = "#if ( defined( USE_SHADOWMAP ) && ( NUM_DIR_LIGHT_SHADOWS > 0 || NUM_POINT_LIGHT_SHADOWS > 0 ) ) || ( NUM_SPOT_LIGHT_COORDS > 0 )\n\tvec3 shadowWorldNormal = inverseTransformDirection( transformedNormal, viewMatrix );\n\tvec4 shadowWorldPosition;\n#endif\n#if defined( USE_SHADOWMAP )\n\t#if NUM_DIR_LIGHT_SHADOWS > 0\n\t\t#pragma unroll_loop_start\n\t\tfor ( int i = 0; i < NUM_DIR_LIGHT_SHADOWS; i ++ ) {\n\t\t\tshadowWorldPosition = worldPosition + vec4( shadowWorldNormal * directionalLightShadows[ i ].shadowNormalBias, 0 );\n\t\t\tvDirectionalShadowCoord[ i ] = directionalShadowMatrix[ i ] * shadowWorldPosition;\n\t\t}\n\t\t#pragma unroll_loop_end\n\t#endif\n\t#if NUM_POINT_LIGHT_SHADOWS > 0\n\t\t#pragma unroll_loop_start\n\t\tfor ( int i = 0; i < NUM_POINT_LIGHT_SHADOWS; i ++ ) {\n\t\t\tshadowWorldPosition = worldPosition + vec4( shadowWorldNormal * pointLightShadows[ i ].shadowNormalBias, 0 );\n\t\t\tvPointShadowCoord[ i ] = pointShadowMatrix[ i ] * shadowWorldPosition;\n\t\t}\n\t\t#pragma unroll_loop_end\n\t#endif\n#endif\n#if NUM_SPOT_LIGHT_COORDS > 0\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_SPOT_LIGHT_COORDS; i ++ ) {\n\t\tshadowWorldPosition = worldPosition;\n\t\t#if ( defined( USE_SHADOWMAP ) && UNROLLED_LOOP_INDEX < NUM_SPOT_LIGHT_SHADOWS )\n\t\t\tshadowWorldPosition.xyz += shadowWorldNormal * spotLightShadows[ i ].shadowNormalBias;\n\t\t#endif\n\t\tvSpotLightCoord[ i ] = spotLightMatrix[ i ] * shadowWorldPosition;\n\t}\n\t#pragma unroll_loop_end\n#endif";
60188
+ var shadowmap_vertex = "#if ( defined( USE_SHADOWMAP ) && ( NUM_DIR_LIGHT_SHADOWS > 0 || NUM_POINT_LIGHT_SHADOWS > 0 ) ) || ( NUM_SPOT_LIGHT_COORDS > 0 )\n\t#ifdef HAS_NORMAL\n\t\tvec3 shadowWorldNormal = inverseTransformDirection( transformedNormal, viewMatrix );\n\t#else\n\t\tvec3 shadowWorldNormal = vec3( 0.0 );\n\t#endif\n\tvec4 shadowWorldPosition;\n#endif\n#if defined( USE_SHADOWMAP )\n\t#if NUM_DIR_LIGHT_SHADOWS > 0\n\t\t#pragma unroll_loop_start\n\t\tfor ( int i = 0; i < NUM_DIR_LIGHT_SHADOWS; i ++ ) {\n\t\t\tshadowWorldPosition = worldPosition + vec4( shadowWorldNormal * directionalLightShadows[ i ].shadowNormalBias, 0 );\n\t\t\tvDirectionalShadowCoord[ i ] = directionalShadowMatrix[ i ] * shadowWorldPosition;\n\t\t}\n\t\t#pragma unroll_loop_end\n\t#endif\n\t#if NUM_POINT_LIGHT_SHADOWS > 0\n\t\t#pragma unroll_loop_start\n\t\tfor ( int i = 0; i < NUM_POINT_LIGHT_SHADOWS; i ++ ) {\n\t\t\tshadowWorldPosition = worldPosition + vec4( shadowWorldNormal * pointLightShadows[ i ].shadowNormalBias, 0 );\n\t\t\tvPointShadowCoord[ i ] = pointShadowMatrix[ i ] * shadowWorldPosition;\n\t\t}\n\t\t#pragma unroll_loop_end\n\t#endif\n#endif\n#if NUM_SPOT_LIGHT_COORDS > 0\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_SPOT_LIGHT_COORDS; i ++ ) {\n\t\tshadowWorldPosition = worldPosition;\n\t\t#if ( defined( USE_SHADOWMAP ) && UNROLLED_LOOP_INDEX < NUM_SPOT_LIGHT_SHADOWS )\n\t\t\tshadowWorldPosition.xyz += shadowWorldNormal * spotLightShadows[ i ].shadowNormalBias;\n\t\t#endif\n\t\tvSpotLightCoord[ i ] = spotLightMatrix[ i ] * shadowWorldPosition;\n\t}\n\t#pragma unroll_loop_end\n#endif";
59944
60189
 
59945
60190
  var shadowmask_pars_fragment = "float getShadowMask() {\n\tfloat shadow = 1.0;\n\t#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHT_SHADOWS > 0\n\tDirectionalLightShadow directionalLight;\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_DIR_LIGHT_SHADOWS; i ++ ) {\n\t\tdirectionalLight = directionalLightShadows[ i ];\n\t\tshadow *= receiveShadow ? getShadow( directionalShadowMap[ i ], directionalLight.shadowMapSize, directionalLight.shadowIntensity, directionalLight.shadowBias, directionalLight.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0;\n\t}\n\t#pragma unroll_loop_end\n\t#endif\n\t#if NUM_SPOT_LIGHT_SHADOWS > 0\n\tSpotLightShadow spotLight;\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_SPOT_LIGHT_SHADOWS; i ++ ) {\n\t\tspotLight = spotLightShadows[ i ];\n\t\tshadow *= receiveShadow ? getShadow( spotShadowMap[ i ], spotLight.shadowMapSize, spotLight.shadowIntensity, spotLight.shadowBias, spotLight.shadowRadius, vSpotLightCoord[ i ] ) : 1.0;\n\t}\n\t#pragma unroll_loop_end\n\t#endif\n\t#if NUM_POINT_LIGHT_SHADOWS > 0 && ( defined( SHADOWMAP_TYPE_PCF ) || defined( SHADOWMAP_TYPE_BASIC ) )\n\tPointLightShadow pointLight;\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_POINT_LIGHT_SHADOWS; i ++ ) {\n\t\tpointLight = pointLightShadows[ i ];\n\t\tshadow *= receiveShadow ? getPointShadow( pointShadowMap[ i ], pointLight.shadowMapSize, pointLight.shadowIntensity, pointLight.shadowBias, pointLight.shadowRadius, vPointShadowCoord[ i ], pointLight.shadowCameraNear, pointLight.shadowCameraFar ) : 1.0;\n\t}\n\t#pragma unroll_loop_end\n\t#endif\n\t#endif\n\treturn shadow;\n}";
59946
60191
 
@@ -59978,7 +60223,7 @@ const fragment$h = "uniform sampler2D t2D;\nuniform float backgroundIntensity;\n
59978
60223
 
59979
60224
  const vertex$g = "varying vec3 vWorldDirection;\n#include <common>\nvoid main() {\n\tvWorldDirection = transformDirection( position, modelMatrix );\n\t#include <begin_vertex>\n\t#include <project_vertex>\n\tgl_Position.z = gl_Position.w;\n}";
59980
60225
 
59981
- const fragment$g = "#ifdef ENVMAP_TYPE_CUBE\n\tuniform samplerCube envMap;\n#elif defined( ENVMAP_TYPE_CUBE_UV )\n\tuniform sampler2D envMap;\n#endif\nuniform float flipEnvMap;\nuniform float backgroundBlurriness;\nuniform float backgroundIntensity;\nuniform mat3 backgroundRotation;\nvarying vec3 vWorldDirection;\n#include <cube_uv_reflection_fragment>\nvoid main() {\n\t#ifdef ENVMAP_TYPE_CUBE\n\t\tvec4 texColor = textureCube( envMap, backgroundRotation * vec3( flipEnvMap * vWorldDirection.x, vWorldDirection.yz ) );\n\t#elif defined( ENVMAP_TYPE_CUBE_UV )\n\t\tvec4 texColor = textureCubeUV( envMap, backgroundRotation * vWorldDirection, backgroundBlurriness );\n\t#else\n\t\tvec4 texColor = vec4( 0.0, 0.0, 0.0, 1.0 );\n\t#endif\n\ttexColor.rgb *= backgroundIntensity;\n\tgl_FragColor = texColor;\n\t#include <tonemapping_fragment>\n\t#include <colorspace_fragment>\n}";
60226
+ const fragment$g = "#ifdef ENVMAP_TYPE_CUBE\n\tuniform samplerCube envMap;\n#elif defined( ENVMAP_TYPE_CUBE_UV )\n\tuniform sampler2D envMap;\n#endif\nuniform float backgroundBlurriness;\nuniform float backgroundIntensity;\nuniform mat3 backgroundRotation;\nvarying vec3 vWorldDirection;\n#include <cube_uv_reflection_fragment>\nvoid main() {\n\t#ifdef ENVMAP_TYPE_CUBE\n\t\tvec4 texColor = textureCube( envMap, backgroundRotation * vWorldDirection );\n\t#elif defined( ENVMAP_TYPE_CUBE_UV )\n\t\tvec4 texColor = textureCubeUV( envMap, backgroundRotation * vWorldDirection, backgroundBlurriness );\n\t#else\n\t\tvec4 texColor = vec4( 0.0, 0.0, 0.0, 1.0 );\n\t#endif\n\ttexColor.rgb *= backgroundIntensity;\n\tgl_FragColor = texColor;\n\t#include <tonemapping_fragment>\n\t#include <colorspace_fragment>\n}";
59982
60227
 
59983
60228
  const vertex$f = "varying vec3 vWorldDirection;\n#include <common>\nvoid main() {\n\tvWorldDirection = transformDirection( position, modelMatrix );\n\t#include <begin_vertex>\n\t#include <project_vertex>\n\tgl_Position.z = gl_Position.w;\n}";
59984
60229
 
@@ -60097,6 +60342,7 @@ const ShaderChunk = {
60097
60342
  lights_fragment_begin: lights_fragment_begin,
60098
60343
  lights_fragment_maps: lights_fragment_maps,
60099
60344
  lights_fragment_end: lights_fragment_end,
60345
+ lightprobes_pars_fragment: lightprobes_pars_fragment,
60100
60346
  logdepthbuf_fragment: logdepthbuf_fragment,
60101
60347
  logdepthbuf_pars_fragment: logdepthbuf_pars_fragment,
60102
60348
  logdepthbuf_pars_vertex: logdepthbuf_pars_vertex,
@@ -60214,7 +60460,6 @@ const UniformsLib = {
60214
60460
 
60215
60461
  envMap: { value: null },
60216
60462
  envMapRotation: { value: /*@__PURE__*/ new Matrix3() },
60217
- flipEnvMap: { value: -1 },
60218
60463
  reflectivity: { value: 1.0 }, // basic, lambert, phong
60219
60464
  ior: { value: 1.5 }, // physical
60220
60465
  refractionRatio: { value: 0.98 }, // basic, lambert, phong
@@ -60375,7 +60620,12 @@ const UniformsLib = {
60375
60620
  } },
60376
60621
 
60377
60622
  ltc_1: { value: null },
60378
- ltc_2: { value: null }
60623
+ ltc_2: { value: null },
60624
+
60625
+ probesSH: { value: null },
60626
+ probesMin: { value: /*@__PURE__*/ new Vector3() },
60627
+ probesMax: { value: /*@__PURE__*/ new Vector3() },
60628
+ probesResolution: { value: /*@__PURE__*/ new Vector3() }
60379
60629
 
60380
60630
  },
60381
60631
 
@@ -60635,7 +60885,6 @@ const ShaderLib = {
60635
60885
 
60636
60886
  uniforms: {
60637
60887
  envMap: { value: null },
60638
- flipEnvMap: { value: -1 },
60639
60888
  backgroundBlurriness: { value: 0 },
60640
60889
  backgroundIntensity: { value: 1 },
60641
60890
  backgroundRotation: { value: /*@__PURE__*/ new Matrix3() }
@@ -60763,8 +61012,10 @@ ShaderLib.physical = {
60763
61012
  };
60764
61013
 
60765
61014
  const _rgb = { r: 0, b: 0, g: 0 };
60766
- const _e1$1 = /*@__PURE__*/ new Euler();
60767
61015
  const _m1$1 = /*@__PURE__*/ new Matrix4();
61016
+ const _m$1 = /*@__PURE__*/ new Matrix3();
61017
+
61018
+ _m$1.set( -1, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0 );
60768
61019
 
60769
61020
  function WebGLBackground( renderer, environments, state, objects, alpha, premultipliedAlpha ) {
60770
61021
 
@@ -60882,24 +61133,22 @@ function WebGLBackground( renderer, environments, state, objects, alpha, premult
60882
61133
 
60883
61134
  }
60884
61135
 
60885
- _e1$1.copy( scene.backgroundRotation );
60886
61136
 
60887
- // accommodate left-handed frame
60888
- _e1$1.x *= -1; _e1$1.y *= -1; _e1$1.z *= -1;
61137
+ boxMesh.material.uniforms.envMap.value = background;
61138
+ boxMesh.material.uniforms.backgroundBlurriness.value = scene.backgroundBlurriness;
61139
+ boxMesh.material.uniforms.backgroundIntensity.value = scene.backgroundIntensity;
61140
+
61141
+
61142
+ // note: since the matrix is orthonormal, we can use the more-efficient transpose() in lieu of invert()
61143
+ boxMesh.material.uniforms.backgroundRotation.value.setFromMatrix4( _m1$1.makeRotationFromEuler( scene.backgroundRotation ) ).transpose();
60889
61144
 
60890
61145
  if ( background.isCubeTexture && background.isRenderTargetTexture === false ) {
60891
61146
 
60892
- // environment maps which are not cube render targets or PMREMs follow a different convention
60893
- _e1$1.y *= -1;
60894
- _e1$1.z *= -1;
61147
+ boxMesh.material.uniforms.backgroundRotation.value.premultiply( _m$1 );
60895
61148
 
60896
61149
  }
60897
61150
 
60898
- boxMesh.material.uniforms.envMap.value = background;
60899
- boxMesh.material.uniforms.flipEnvMap.value = ( background.isCubeTexture && background.isRenderTargetTexture === false ) ? -1 : 1;
60900
- boxMesh.material.uniforms.backgroundBlurriness.value = scene.backgroundBlurriness;
60901
- boxMesh.material.uniforms.backgroundIntensity.value = scene.backgroundIntensity;
60902
- boxMesh.material.uniforms.backgroundRotation.value.setFromMatrix4( _m1$1.makeRotationFromEuler( _e1$1 ) );
61151
+
60903
61152
  boxMesh.material.toneMapped = ColorManagement.getTransfer( background.colorSpace ) !== SRGBTransfer;
60904
61153
 
60905
61154
  if ( currentBackground !== background ||
@@ -61759,44 +62008,12 @@ function WebGLBufferRenderer( gl, extensions, info ) {
61759
62008
 
61760
62009
  }
61761
62010
 
61762
- function renderMultiDrawInstances( starts, counts, drawCount, primcount ) {
61763
-
61764
- if ( drawCount === 0 ) return;
61765
-
61766
- const extension = extensions.get( 'WEBGL_multi_draw' );
61767
-
61768
- if ( extension === null ) {
61769
-
61770
- for ( let i = 0; i < starts.length; i ++ ) {
61771
-
61772
- renderInstances( starts[ i ], counts[ i ], primcount[ i ] );
61773
-
61774
- }
61775
-
61776
- } else {
61777
-
61778
- extension.multiDrawArraysInstancedWEBGL( mode, starts, 0, counts, 0, primcount, 0, drawCount );
61779
-
61780
- let elementCount = 0;
61781
- for ( let i = 0; i < drawCount; i ++ ) {
61782
-
61783
- elementCount += counts[ i ] * primcount[ i ];
61784
-
61785
- }
61786
-
61787
- info.update( elementCount, mode, 1 );
61788
-
61789
- }
61790
-
61791
- }
61792
-
61793
62011
  //
61794
62012
 
61795
62013
  this.setMode = setMode;
61796
62014
  this.render = render;
61797
62015
  this.renderInstances = renderInstances;
61798
62016
  this.renderMultiDraw = renderMultiDraw;
61799
- this.renderMultiDrawInstances = renderMultiDrawInstances;
61800
62017
 
61801
62018
  }
61802
62019
 
@@ -61894,6 +62111,12 @@ function WebGLCapabilities( gl, extensions, parameters, utils ) {
61894
62111
  const logarithmicDepthBuffer = parameters.logarithmicDepthBuffer === true;
61895
62112
  const reversedDepthBuffer = parameters.reversedDepthBuffer === true && extensions.has( 'EXT_clip_control' );
61896
62113
 
62114
+ if ( parameters.reversedDepthBuffer === true && reversedDepthBuffer === false ) {
62115
+
62116
+ warn( 'WebGLRenderer: Unable to use reversed depth buffer due to missing EXT_clip_control extension. Fallback to default depth buffer.' );
62117
+
62118
+ }
62119
+
61897
62120
  const maxTextures = gl.getParameter( gl.MAX_TEXTURE_IMAGE_UNITS );
61898
62121
  const maxVertexTextures = gl.getParameter( gl.MAX_VERTEX_TEXTURE_IMAGE_UNITS );
61899
62122
  const maxTextureSize = gl.getParameter( gl.MAX_TEXTURE_SIZE );
@@ -63935,37 +64158,6 @@ function WebGLIndexedBufferRenderer( gl, extensions, info ) {
63935
64158
 
63936
64159
  }
63937
64160
 
63938
- function renderMultiDrawInstances( starts, counts, drawCount, primcount ) {
63939
-
63940
- if ( drawCount === 0 ) return;
63941
-
63942
- const extension = extensions.get( 'WEBGL_multi_draw' );
63943
-
63944
- if ( extension === null ) {
63945
-
63946
- for ( let i = 0; i < starts.length; i ++ ) {
63947
-
63948
- renderInstances( starts[ i ] / bytesPerElement, counts[ i ], primcount[ i ] );
63949
-
63950
- }
63951
-
63952
- } else {
63953
-
63954
- extension.multiDrawElementsInstancedWEBGL( mode, counts, 0, type, starts, 0, primcount, 0, drawCount );
63955
-
63956
- let elementCount = 0;
63957
- for ( let i = 0; i < drawCount; i ++ ) {
63958
-
63959
- elementCount += counts[ i ] * primcount[ i ];
63960
-
63961
- }
63962
-
63963
- info.update( elementCount, mode, 1 );
63964
-
63965
- }
63966
-
63967
- }
63968
-
63969
64161
  //
63970
64162
 
63971
64163
  this.setMode = setMode;
@@ -63973,7 +64165,6 @@ function WebGLIndexedBufferRenderer( gl, extensions, info ) {
63973
64165
  this.render = render;
63974
64166
  this.renderInstances = renderInstances;
63975
64167
  this.renderMultiDraw = renderMultiDraw;
63976
- this.renderMultiDrawInstances = renderMultiDrawInstances;
63977
64168
 
63978
64169
  }
63979
64170
 
@@ -64315,7 +64506,8 @@ function WebGLOutput( type, width, height, depth, stencil ) {
64315
64506
  const targetA = new WebGLRenderTarget( width, height, {
64316
64507
  type: type,
64317
64508
  depthBuffer: depth,
64318
- stencilBuffer: stencil
64509
+ stencilBuffer: stencil,
64510
+ depthTexture: depth ? new DepthTexture( width, height ) : undefined
64319
64511
  } );
64320
64512
 
64321
64513
  const targetB = new WebGLRenderTarget( width, height, {
@@ -64536,6 +64728,7 @@ function WebGLOutput( type, width, height, depth, stencil ) {
64536
64728
 
64537
64729
  this.dispose = function () {
64538
64730
 
64731
+ if ( targetA.depthTexture ) targetA.depthTexture.dispose();
64539
64732
  targetA.dispose();
64540
64733
  targetB.dispose();
64541
64734
  geometry.dispose();
@@ -66308,6 +66501,7 @@ function WebGLProgram( renderer, cacheKey, parameters, bindingStates ) {
66308
66501
  //
66309
66502
 
66310
66503
  parameters.vertexTangents && parameters.flatShading === false ? '#define USE_TANGENT' : '',
66504
+ parameters.vertexNormals ? '#define HAS_NORMAL' : '',
66311
66505
  parameters.vertexColors ? '#define USE_COLOR' : '',
66312
66506
  parameters.vertexAlphas ? '#define USE_COLOR_ALPHA' : '',
66313
66507
  parameters.vertexUv1s ? '#define USE_UV1' : '',
@@ -66441,6 +66635,7 @@ function WebGLProgram( renderer, cacheKey, parameters, bindingStates ) {
66441
66635
  parameters.normalMap ? '#define USE_NORMALMAP' : '',
66442
66636
  parameters.normalMapObjectSpace ? '#define USE_NORMALMAP_OBJECTSPACE' : '',
66443
66637
  parameters.normalMapTangentSpace ? '#define USE_NORMALMAP_TANGENTSPACE' : '',
66638
+ parameters.packedNormalMap ? '#define USE_PACKED_NORMALMAP' : '',
66444
66639
  parameters.emissiveMap ? '#define USE_EMISSIVEMAP' : '',
66445
66640
 
66446
66641
  parameters.anisotropy ? '#define USE_ANISOTROPY' : '',
@@ -66499,6 +66694,8 @@ function WebGLProgram( renderer, cacheKey, parameters, bindingStates ) {
66499
66694
 
66500
66695
  parameters.numLightProbes > 0 ? '#define USE_LIGHT_PROBES' : '',
66501
66696
 
66697
+ parameters.numLightProbeGrids > 0 ? '#define USE_LIGHT_PROBES_GRID' : '',
66698
+
66502
66699
  parameters.decodeVideoTexture ? '#define DECODE_VIDEO_TEXTURE' : '',
66503
66700
  parameters.decodeVideoTextureEmissive ? '#define DECODE_VIDEO_TEXTURE_EMISSIVE' : '',
66504
66701
 
@@ -66892,6 +67089,12 @@ class WebGLShaderStage {
66892
67089
 
66893
67090
  }
66894
67091
 
67092
+ function isPackedRGFormat( format ) {
67093
+
67094
+ return format === RGFormat || format === RG11_EAC_Format || format === RED_GREEN_RGTC2_Format;
67095
+
67096
+ }
67097
+
66895
67098
  function WebGLPrograms( renderer, environments, extensions, capabilities, bindingStates, clipping ) {
66896
67099
 
66897
67100
  const _programLayers = new Layers();
@@ -66932,7 +67135,7 @@ function WebGLPrograms( renderer, environments, extensions, capabilities, bindin
66932
67135
 
66933
67136
  }
66934
67137
 
66935
- function getParameters( material, lights, shadows, scene, object ) {
67138
+ function getParameters( material, lights, shadows, scene, object, lightProbeGrids ) {
66936
67139
 
66937
67140
  const fog = scene.fog;
66938
67141
  const geometry = object.geometry;
@@ -67085,7 +67288,7 @@ function WebGLPrograms( renderer, environments, extensions, capabilities, bindin
67085
67288
  instancingColor: IS_INSTANCEDMESH && object.instanceColor !== null,
67086
67289
  instancingMorph: IS_INSTANCEDMESH && object.morphTexture !== null,
67087
67290
 
67088
- outputColorSpace: ( currentRenderTarget === null ) ? renderer.outputColorSpace : ( currentRenderTarget.isXRRenderTarget === true ? currentRenderTarget.texture.colorSpace : LinearSRGBColorSpace ),
67291
+ outputColorSpace: ( currentRenderTarget === null ) ? renderer.outputColorSpace : ( currentRenderTarget.isXRRenderTarget === true ? currentRenderTarget.texture.colorSpace : ColorManagement.workingColorSpace ),
67089
67292
  alphaToCoverage: !! material.alphaToCoverage,
67090
67293
 
67091
67294
  map: HAS_MAP,
@@ -67102,6 +67305,7 @@ function WebGLPrograms( renderer, environments, extensions, capabilities, bindin
67102
67305
 
67103
67306
  normalMapObjectSpace: HAS_NORMALMAP && material.normalMapType === ObjectSpaceNormalMap,
67104
67307
  normalMapTangentSpace: HAS_NORMALMAP && material.normalMapType === TangentSpaceNormalMap,
67308
+ packedNormalMap: HAS_NORMALMAP && material.normalMapType === TangentSpaceNormalMap && isPackedRGFormat( material.normalMap.format ),
67105
67309
 
67106
67310
  metalnessMap: HAS_METALNESSMAP,
67107
67311
  roughnessMap: HAS_ROUGHNESSMAP,
@@ -67179,6 +67383,7 @@ function WebGLPrograms( renderer, environments, extensions, capabilities, bindin
67179
67383
  //
67180
67384
 
67181
67385
  vertexTangents: !! geometry.attributes.tangent && ( HAS_NORMALMAP || HAS_ANISOTROPY ),
67386
+ vertexNormals: !! geometry.attributes.normal,
67182
67387
  vertexColors: material.vertexColors,
67183
67388
  vertexAlphas: material.vertexColors === true && !! geometry.attributes.color && geometry.attributes.color.itemSize === 4,
67184
67389
 
@@ -67221,6 +67426,8 @@ function WebGLPrograms( renderer, environments, extensions, capabilities, bindin
67221
67426
 
67222
67427
  numLightProbes: lights.numLightProbes,
67223
67428
 
67429
+ numLightProbeGrids: lightProbeGrids.length,
67430
+
67224
67431
  numClippingPlanes: clipping.numPlanes,
67225
67432
  numClipIntersection: clipping.numIntersection,
67226
67433
 
@@ -67406,6 +67613,10 @@ function WebGLPrograms( renderer, environments, extensions, capabilities, bindin
67406
67613
  _programLayers.enable( 20 );
67407
67614
  if ( parameters.gradientMap )
67408
67615
  _programLayers.enable( 21 );
67616
+ if ( parameters.packedNormalMap )
67617
+ _programLayers.enable( 22 );
67618
+ if ( parameters.vertexNormals )
67619
+ _programLayers.enable( 23 );
67409
67620
 
67410
67621
  array.push( _programLayers.mask );
67411
67622
  _programLayers.disableAll();
@@ -67454,6 +67665,8 @@ function WebGLPrograms( renderer, environments, extensions, capabilities, bindin
67454
67665
  _programLayers.enable( 20 );
67455
67666
  if ( parameters.alphaToCoverage )
67456
67667
  _programLayers.enable( 21 );
67668
+ if ( parameters.numLightProbeGrids > 0 )
67669
+ _programLayers.enable( 22 );
67457
67670
 
67458
67671
  array.push( _programLayers.mask );
67459
67672
 
@@ -68430,6 +68643,7 @@ function WebGLRenderState( extensions ) {
68430
68643
 
68431
68644
  const lightsArray = [];
68432
68645
  const shadowsArray = [];
68646
+ const lightProbeGridArray = [];
68433
68647
 
68434
68648
  function init( camera ) {
68435
68649
 
@@ -68437,6 +68651,7 @@ function WebGLRenderState( extensions ) {
68437
68651
 
68438
68652
  lightsArray.length = 0;
68439
68653
  shadowsArray.length = 0;
68654
+ lightProbeGridArray.length = 0;
68440
68655
 
68441
68656
  }
68442
68657
 
@@ -68452,6 +68667,12 @@ function WebGLRenderState( extensions ) {
68452
68667
 
68453
68668
  }
68454
68669
 
68670
+ function pushLightProbeGrid( volume ) {
68671
+
68672
+ lightProbeGridArray.push( volume );
68673
+
68674
+ }
68675
+
68455
68676
  function setupLights() {
68456
68677
 
68457
68678
  lights.setup( lightsArray );
@@ -68467,12 +68688,14 @@ function WebGLRenderState( extensions ) {
68467
68688
  const state = {
68468
68689
  lightsArray: lightsArray,
68469
68690
  shadowsArray: shadowsArray,
68691
+ lightProbeGridArray: lightProbeGridArray,
68470
68692
 
68471
68693
  camera: null,
68472
68694
 
68473
68695
  lights: lights,
68474
68696
 
68475
- transmissionRenderTarget: {}
68697
+ transmissionRenderTarget: {},
68698
+ textureUnits: 0
68476
68699
  };
68477
68700
 
68478
68701
  return {
@@ -68482,7 +68705,8 @@ function WebGLRenderState( extensions ) {
68482
68705
  setupLightsView: setupLightsView,
68483
68706
 
68484
68707
  pushLight: pushLight,
68485
- pushShadow: pushShadow
68708
+ pushShadow: pushShadow,
68709
+ pushLightProbeGrid: pushLightProbeGrid
68486
68710
  };
68487
68711
 
68488
68712
  }
@@ -69465,6 +69689,7 @@ function WebGLState( gl, extensions ) {
69465
69689
  const uboProgramMap = new WeakMap();
69466
69690
 
69467
69691
  let enabledCapabilities = {};
69692
+ let parameters = {};
69468
69693
 
69469
69694
  let currentBoundFramebuffers = {};
69470
69695
  let currentDrawbuffers = new WeakMap();
@@ -70224,6 +70449,31 @@ function WebGLState( gl, extensions ) {
70224
70449
 
70225
70450
  }
70226
70451
 
70452
+ function getParameter( name ) {
70453
+
70454
+ if ( parameters[ name ] !== undefined ) {
70455
+
70456
+ return parameters[ name ];
70457
+
70458
+ } else {
70459
+
70460
+ return gl.getParameter( name );
70461
+
70462
+ }
70463
+
70464
+ }
70465
+
70466
+ function pixelStorei( name, value ) {
70467
+
70468
+ if ( parameters[ name ] !== value ) {
70469
+
70470
+ gl.pixelStorei( name, value );
70471
+ parameters[ name ] = value;
70472
+
70473
+ }
70474
+
70475
+ }
70476
+
70227
70477
  //
70228
70478
 
70229
70479
  function scissor( scissor ) {
@@ -70340,9 +70590,24 @@ function WebGLState( gl, extensions ) {
70340
70590
  gl.scissor( 0, 0, gl.canvas.width, gl.canvas.height );
70341
70591
  gl.viewport( 0, 0, gl.canvas.width, gl.canvas.height );
70342
70592
 
70593
+ gl.pixelStorei( gl.PACK_ALIGNMENT, 4 );
70594
+ gl.pixelStorei( gl.UNPACK_ALIGNMENT, 4 );
70595
+ gl.pixelStorei( gl.UNPACK_FLIP_Y_WEBGL, false );
70596
+ gl.pixelStorei( gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false );
70597
+ gl.pixelStorei( gl.UNPACK_COLORSPACE_CONVERSION_WEBGL, gl.BROWSER_DEFAULT_WEBGL );
70598
+ gl.pixelStorei( gl.PACK_ROW_LENGTH, 0 );
70599
+ gl.pixelStorei( gl.PACK_SKIP_PIXELS, 0 );
70600
+ gl.pixelStorei( gl.PACK_SKIP_ROWS, 0 );
70601
+ gl.pixelStorei( gl.UNPACK_ROW_LENGTH, 0 );
70602
+ gl.pixelStorei( gl.UNPACK_IMAGE_HEIGHT, 0 );
70603
+ gl.pixelStorei( gl.UNPACK_SKIP_PIXELS, 0 );
70604
+ gl.pixelStorei( gl.UNPACK_SKIP_ROWS, 0 );
70605
+ gl.pixelStorei( gl.UNPACK_SKIP_IMAGES, 0 );
70606
+
70343
70607
  // reset internals
70344
70608
 
70345
70609
  enabledCapabilities = {};
70610
+ parameters = {};
70346
70611
 
70347
70612
  currentTextureSlot = null;
70348
70613
  currentBoundTextures = {};
@@ -70416,6 +70681,8 @@ function WebGLState( gl, extensions ) {
70416
70681
  compressedTexImage3D: compressedTexImage3D,
70417
70682
  texImage2D: texImage2D,
70418
70683
  texImage3D: texImage3D,
70684
+ pixelStorei: pixelStorei,
70685
+ getParameter: getParameter,
70419
70686
 
70420
70687
  updateUBOMapping: updateUBOMapping,
70421
70688
  uniformBlockBinding: uniformBlockBinding,
@@ -70443,6 +70710,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils,
70443
70710
 
70444
70711
  const _imageDimensions = new Vector2();
70445
70712
  const _videoTextures = new WeakMap();
70713
+ const _htmlTextures = new Set();
70446
70714
  let _canvas;
70447
70715
 
70448
70716
  const _sources = new WeakMap(); // maps WebglTexture objects to instances of Source
@@ -70557,7 +70825,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils,
70557
70825
 
70558
70826
  }
70559
70827
 
70560
- function getInternalFormat( internalFormatName, glFormat, glType, colorSpace, forceLinearTransfer = false ) {
70828
+ function getInternalFormat( internalFormatName, glFormat, glType, normalized, colorSpace, forceLinearTransfer = false ) {
70561
70829
 
70562
70830
  if ( internalFormatName !== null ) {
70563
70831
 
@@ -70567,6 +70835,20 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils,
70567
70835
 
70568
70836
  }
70569
70837
 
70838
+ let ext_texture_norm16;
70839
+
70840
+ if ( normalized ) {
70841
+
70842
+ ext_texture_norm16 = extensions.get( 'EXT_texture_norm16' );
70843
+
70844
+ if ( ! ext_texture_norm16 ) {
70845
+
70846
+ warn( 'WebGLRenderer: Unable to use normalized textures without EXT_texture_norm16 extension' );
70847
+
70848
+ }
70849
+
70850
+ }
70851
+
70570
70852
  let internalFormat = glFormat;
70571
70853
 
70572
70854
  if ( glFormat === _gl.RED ) {
@@ -70574,6 +70856,8 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils,
70574
70856
  if ( glType === _gl.FLOAT ) internalFormat = _gl.R32F;
70575
70857
  if ( glType === _gl.HALF_FLOAT ) internalFormat = _gl.R16F;
70576
70858
  if ( glType === _gl.UNSIGNED_BYTE ) internalFormat = _gl.R8;
70859
+ if ( glType === _gl.UNSIGNED_SHORT && ext_texture_norm16 ) internalFormat = ext_texture_norm16.R16_EXT;
70860
+ if ( glType === _gl.SHORT && ext_texture_norm16 ) internalFormat = ext_texture_norm16.R16_SNORM_EXT;
70577
70861
 
70578
70862
  }
70579
70863
 
@@ -70593,6 +70877,8 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils,
70593
70877
  if ( glType === _gl.FLOAT ) internalFormat = _gl.RG32F;
70594
70878
  if ( glType === _gl.HALF_FLOAT ) internalFormat = _gl.RG16F;
70595
70879
  if ( glType === _gl.UNSIGNED_BYTE ) internalFormat = _gl.RG8;
70880
+ if ( glType === _gl.UNSIGNED_SHORT && ext_texture_norm16 ) internalFormat = ext_texture_norm16.RG16_EXT;
70881
+ if ( glType === _gl.SHORT && ext_texture_norm16 ) internalFormat = ext_texture_norm16.RG16_SNORM_EXT;
70596
70882
 
70597
70883
  }
70598
70884
 
@@ -70631,6 +70917,8 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils,
70631
70917
 
70632
70918
  if ( glFormat === _gl.RGB ) {
70633
70919
 
70920
+ if ( glType === _gl.UNSIGNED_SHORT && ext_texture_norm16 ) internalFormat = ext_texture_norm16.RGB16_EXT;
70921
+ if ( glType === _gl.SHORT && ext_texture_norm16 ) internalFormat = ext_texture_norm16.RGB16_SNORM_EXT;
70634
70922
  if ( glType === _gl.UNSIGNED_INT_5_9_9_9_REV ) internalFormat = _gl.RGB9_E5;
70635
70923
  if ( glType === _gl.UNSIGNED_INT_10F_11F_11F_REV ) internalFormat = _gl.R11F_G11F_B10F;
70636
70924
 
@@ -70643,6 +70931,8 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils,
70643
70931
  if ( glType === _gl.FLOAT ) internalFormat = _gl.RGBA32F;
70644
70932
  if ( glType === _gl.HALF_FLOAT ) internalFormat = _gl.RGBA16F;
70645
70933
  if ( glType === _gl.UNSIGNED_BYTE ) internalFormat = ( transfer === SRGBTransfer ) ? _gl.SRGB8_ALPHA8 : _gl.RGBA8;
70934
+ if ( glType === _gl.UNSIGNED_SHORT && ext_texture_norm16 ) internalFormat = ext_texture_norm16.RGBA16_EXT;
70935
+ if ( glType === _gl.SHORT && ext_texture_norm16 ) internalFormat = ext_texture_norm16.RGBA16_SNORM_EXT;
70646
70936
  if ( glType === _gl.UNSIGNED_SHORT_4_4_4_4 ) internalFormat = _gl.RGBA4;
70647
70937
  if ( glType === _gl.UNSIGNED_SHORT_5_5_5_1 ) internalFormat = _gl.RGB5_A1;
70648
70938
 
@@ -70744,6 +71034,12 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils,
70744
71034
 
70745
71035
  }
70746
71036
 
71037
+ if ( texture.isHTMLTexture ) {
71038
+
71039
+ _htmlTextures.delete( texture );
71040
+
71041
+ }
71042
+
70747
71043
  }
70748
71044
 
70749
71045
  function onRenderTargetDispose( event ) {
@@ -70900,6 +71196,18 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils,
70900
71196
 
70901
71197
  }
70902
71198
 
71199
+ function getTextureUnits() {
71200
+
71201
+ return textureUnits;
71202
+
71203
+ }
71204
+
71205
+ function setTextureUnits( value ) {
71206
+
71207
+ textureUnits = value;
71208
+
71209
+ }
71210
+
70903
71211
  function allocateTextureUnit() {
70904
71212
 
70905
71213
  const textureUnit = textureUnits;
@@ -71251,11 +71559,11 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils,
71251
71559
  // Trim the array to only contain the merged ranges.
71252
71560
  updateRanges.length = mergeIndex + 1;
71253
71561
 
71254
- const currentUnpackRowLen = _gl.getParameter( _gl.UNPACK_ROW_LENGTH );
71255
- const currentUnpackSkipPixels = _gl.getParameter( _gl.UNPACK_SKIP_PIXELS );
71256
- const currentUnpackSkipRows = _gl.getParameter( _gl.UNPACK_SKIP_ROWS );
71562
+ const currentUnpackRowLen = state.getParameter( _gl.UNPACK_ROW_LENGTH );
71563
+ const currentUnpackSkipPixels = state.getParameter( _gl.UNPACK_SKIP_PIXELS );
71564
+ const currentUnpackSkipRows = state.getParameter( _gl.UNPACK_SKIP_ROWS );
71257
71565
 
71258
- _gl.pixelStorei( _gl.UNPACK_ROW_LENGTH, image.width );
71566
+ state.pixelStorei( _gl.UNPACK_ROW_LENGTH, image.width );
71259
71567
 
71260
71568
  for ( let i = 0, l = updateRanges.length; i < l; i ++ ) {
71261
71569
 
@@ -71271,8 +71579,8 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils,
71271
71579
  const width = pixelCount;
71272
71580
  const height = 1;
71273
71581
 
71274
- _gl.pixelStorei( _gl.UNPACK_SKIP_PIXELS, x );
71275
- _gl.pixelStorei( _gl.UNPACK_SKIP_ROWS, y );
71582
+ state.pixelStorei( _gl.UNPACK_SKIP_PIXELS, x );
71583
+ state.pixelStorei( _gl.UNPACK_SKIP_ROWS, y );
71276
71584
 
71277
71585
  state.texSubImage2D( _gl.TEXTURE_2D, 0, x, y, width, height, glFormat, glType, image.data );
71278
71586
 
@@ -71280,9 +71588,9 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils,
71280
71588
 
71281
71589
  texture.clearUpdateRanges();
71282
71590
 
71283
- _gl.pixelStorei( _gl.UNPACK_ROW_LENGTH, currentUnpackRowLen );
71284
- _gl.pixelStorei( _gl.UNPACK_SKIP_PIXELS, currentUnpackSkipPixels );
71285
- _gl.pixelStorei( _gl.UNPACK_SKIP_ROWS, currentUnpackSkipRows );
71591
+ state.pixelStorei( _gl.UNPACK_ROW_LENGTH, currentUnpackRowLen );
71592
+ state.pixelStorei( _gl.UNPACK_SKIP_PIXELS, currentUnpackSkipPixels );
71593
+ state.pixelStorei( _gl.UNPACK_SKIP_ROWS, currentUnpackSkipRows );
71286
71594
 
71287
71595
  }
71288
71596
 
@@ -71306,14 +71614,21 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils,
71306
71614
 
71307
71615
  state.activeTexture( _gl.TEXTURE0 + slot );
71308
71616
 
71309
- const workingPrimaries = ColorManagement.getPrimaries( ColorManagement.workingColorSpace );
71310
- const texturePrimaries = texture.colorSpace === NoColorSpace ? null : ColorManagement.getPrimaries( texture.colorSpace );
71311
- const unpackConversion = texture.colorSpace === NoColorSpace || workingPrimaries === texturePrimaries ? _gl.NONE : _gl.BROWSER_DEFAULT_WEBGL;
71617
+ const isImageBitmap = ( typeof ImageBitmap !== 'undefined' && texture.image instanceof ImageBitmap );
71618
+
71619
+ if ( isImageBitmap === false ) {
71620
+
71621
+ const workingPrimaries = ColorManagement.getPrimaries( ColorManagement.workingColorSpace );
71622
+ const texturePrimaries = texture.colorSpace === NoColorSpace ? null : ColorManagement.getPrimaries( texture.colorSpace );
71623
+ const unpackConversion = texture.colorSpace === NoColorSpace || workingPrimaries === texturePrimaries ? _gl.NONE : _gl.BROWSER_DEFAULT_WEBGL;
71624
+
71625
+ state.pixelStorei( _gl.UNPACK_FLIP_Y_WEBGL, texture.flipY );
71626
+ state.pixelStorei( _gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, texture.premultiplyAlpha );
71627
+ state.pixelStorei( _gl.UNPACK_COLORSPACE_CONVERSION_WEBGL, unpackConversion );
71312
71628
 
71313
- _gl.pixelStorei( _gl.UNPACK_FLIP_Y_WEBGL, texture.flipY );
71314
- _gl.pixelStorei( _gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, texture.premultiplyAlpha );
71315
- _gl.pixelStorei( _gl.UNPACK_ALIGNMENT, texture.unpackAlignment );
71316
- _gl.pixelStorei( _gl.UNPACK_COLORSPACE_CONVERSION_WEBGL, unpackConversion );
71629
+ }
71630
+
71631
+ state.pixelStorei( _gl.UNPACK_ALIGNMENT, texture.unpackAlignment );
71317
71632
 
71318
71633
  let image = resizeImage( texture.image, false, capabilities.maxTextureSize );
71319
71634
  image = verifyColorSpace( texture, image );
@@ -71321,7 +71636,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils,
71321
71636
  const glFormat = utils.convert( texture.format, texture.colorSpace );
71322
71637
 
71323
71638
  const glType = utils.convert( texture.type );
71324
- let glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType, texture.colorSpace, texture.isVideoTexture );
71639
+ let glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType, texture.normalized, texture.colorSpace, texture.isVideoTexture );
71325
71640
 
71326
71641
  setTextureParameters( textureType, texture );
71327
71642
 
@@ -71638,6 +71953,59 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils,
71638
71953
 
71639
71954
  }
71640
71955
 
71956
+ } else if ( texture.isHTMLTexture ) {
71957
+
71958
+ if ( 'texElementImage2D' in _gl ) {
71959
+
71960
+ const canvas = _gl.canvas;
71961
+
71962
+ // Ensure the canvas supports HTML-in-Canvas and the element is a child.
71963
+ if ( ! canvas.hasAttribute( 'layoutsubtree' ) ) {
71964
+
71965
+ canvas.setAttribute( 'layoutsubtree', 'true' );
71966
+
71967
+ }
71968
+
71969
+ if ( image.parentNode !== canvas ) {
71970
+
71971
+ canvas.appendChild( image );
71972
+
71973
+ // Register and set up a shared paint callback for all HTMLTextures.
71974
+ _htmlTextures.add( texture );
71975
+
71976
+ canvas.onpaint = ( event ) => {
71977
+
71978
+ const changed = event.changedElements;
71979
+
71980
+ for ( const t of _htmlTextures ) {
71981
+
71982
+ if ( changed.includes( t.image ) ) {
71983
+
71984
+ t.needsUpdate = true;
71985
+
71986
+ }
71987
+
71988
+ }
71989
+
71990
+ };
71991
+
71992
+ canvas.requestPaint();
71993
+ return;
71994
+
71995
+ }
71996
+
71997
+ const level = 0;
71998
+ const internalFormat = _gl.RGBA;
71999
+ const srcFormat = _gl.RGBA;
72000
+ const srcType = _gl.UNSIGNED_BYTE;
72001
+
72002
+ _gl.texElementImage2D( _gl.TEXTURE_2D, level, internalFormat, srcFormat, srcType, image );
72003
+ _gl.texParameteri( _gl.TEXTURE_2D, _gl.TEXTURE_MIN_FILTER, _gl.LINEAR );
72004
+ _gl.texParameteri( _gl.TEXTURE_2D, _gl.TEXTURE_WRAP_S, _gl.CLAMP_TO_EDGE );
72005
+ _gl.texParameteri( _gl.TEXTURE_2D, _gl.TEXTURE_WRAP_T, _gl.CLAMP_TO_EDGE );
72006
+
72007
+ }
72008
+
71641
72009
  } else {
71642
72010
 
71643
72011
  // regular Texture (image, video, canvas)
@@ -71741,10 +72109,10 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils,
71741
72109
  const texturePrimaries = texture.colorSpace === NoColorSpace ? null : ColorManagement.getPrimaries( texture.colorSpace );
71742
72110
  const unpackConversion = texture.colorSpace === NoColorSpace || workingPrimaries === texturePrimaries ? _gl.NONE : _gl.BROWSER_DEFAULT_WEBGL;
71743
72111
 
71744
- _gl.pixelStorei( _gl.UNPACK_FLIP_Y_WEBGL, texture.flipY );
71745
- _gl.pixelStorei( _gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, texture.premultiplyAlpha );
71746
- _gl.pixelStorei( _gl.UNPACK_ALIGNMENT, texture.unpackAlignment );
71747
- _gl.pixelStorei( _gl.UNPACK_COLORSPACE_CONVERSION_WEBGL, unpackConversion );
72112
+ state.pixelStorei( _gl.UNPACK_FLIP_Y_WEBGL, texture.flipY );
72113
+ state.pixelStorei( _gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, texture.premultiplyAlpha );
72114
+ state.pixelStorei( _gl.UNPACK_ALIGNMENT, texture.unpackAlignment );
72115
+ state.pixelStorei( _gl.UNPACK_COLORSPACE_CONVERSION_WEBGL, unpackConversion );
71748
72116
 
71749
72117
  const isCompressed = ( texture.isCompressedTexture || texture.image[ 0 ].isCompressedTexture );
71750
72118
  const isDataTexture = ( texture.image[ 0 ] && texture.image[ 0 ].isDataTexture );
@@ -71770,7 +72138,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils,
71770
72138
  const image = cubeImage[ 0 ],
71771
72139
  glFormat = utils.convert( texture.format, texture.colorSpace ),
71772
72140
  glType = utils.convert( texture.type ),
71773
- glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType, texture.colorSpace );
72141
+ glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType, texture.normalized, texture.colorSpace );
71774
72142
 
71775
72143
  const useTexStorage = ( texture.isVideoTexture !== true );
71776
72144
  const allocateMemory = ( sourceProperties.__version === undefined ) || ( forceUpload === true );
@@ -71966,7 +72334,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils,
71966
72334
 
71967
72335
  const glFormat = utils.convert( texture.format, texture.colorSpace );
71968
72336
  const glType = utils.convert( texture.type );
71969
- const glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType, texture.colorSpace );
72337
+ const glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType, texture.normalized, texture.colorSpace );
71970
72338
  const renderTargetProperties = properties.get( renderTarget );
71971
72339
  const textureProperties = properties.get( texture );
71972
72340
 
@@ -72045,7 +72413,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils,
72045
72413
 
72046
72414
  const glFormat = utils.convert( texture.format, texture.colorSpace );
72047
72415
  const glType = utils.convert( texture.type );
72048
- const glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType, texture.colorSpace );
72416
+ const glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType, texture.normalized, texture.colorSpace );
72049
72417
 
72050
72418
  if ( useMultisampledRTT( renderTarget ) ) {
72051
72419
 
@@ -72435,7 +72803,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils,
72435
72803
 
72436
72804
  const glFormat = utils.convert( texture.format, texture.colorSpace );
72437
72805
  const glType = utils.convert( texture.type );
72438
- const glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType, texture.colorSpace, renderTarget.isXRRenderTarget === true );
72806
+ const glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType, texture.normalized, texture.colorSpace, renderTarget.isXRRenderTarget === true );
72439
72807
  const samples = getRenderTargetSamples( renderTarget );
72440
72808
  _gl.renderbufferStorageMultisample( _gl.RENDERBUFFER, samples, glInternalFormat, renderTarget.width, renderTarget.height );
72441
72809
 
@@ -72811,6 +73179,8 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils,
72811
73179
 
72812
73180
  this.allocateTextureUnit = allocateTextureUnit;
72813
73181
  this.resetTextureUnits = resetTextureUnits;
73182
+ this.getTextureUnits = getTextureUnits;
73183
+ this.setTextureUnits = setTextureUnits;
72814
73184
 
72815
73185
  this.setTexture2D = setTexture2D;
72816
73186
  this.setTexture2DArray = setTexture2DArray;
@@ -74279,8 +74649,10 @@ class WebXRManager extends EventDispatcher {
74279
74649
 
74280
74650
  }
74281
74651
 
74282
- const _e1 = /*@__PURE__*/ new Euler();
74283
74652
  const _m1 = /*@__PURE__*/ new Matrix4();
74653
+ const _m = /*@__PURE__*/ new Matrix3();
74654
+
74655
+ _m.set( -1, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0 );
74284
74656
 
74285
74657
  function WebGLMaterials( renderer, properties ) {
74286
74658
 
@@ -74315,7 +74687,11 @@ function WebGLMaterials( renderer, properties ) {
74315
74687
 
74316
74688
  function refreshMaterialUniforms( uniforms, material, pixelRatio, height, transmissionRenderTarget ) {
74317
74689
 
74318
- if ( material.isMeshBasicMaterial ) {
74690
+ if ( material.isNodeMaterial ) {
74691
+
74692
+ material.uniformsNeedUpdate = false;
74693
+
74694
+ } else if ( material.isMeshBasicMaterial ) {
74319
74695
 
74320
74696
  refreshUniformsCommon( uniforms, material );
74321
74697
 
@@ -74511,23 +74887,16 @@ function WebGLMaterials( renderer, properties ) {
74511
74887
 
74512
74888
  uniforms.envMap.value = envMap;
74513
74889
 
74514
- _e1.copy( envMapRotation );
74890
+ // note: since the matrix is orthonormal, we can use the more-efficient transpose() in lieu of invert()
74891
+ uniforms.envMapRotation.value.setFromMatrix4( _m1.makeRotationFromEuler( envMapRotation ) ).transpose();
74515
74892
 
74516
- // accommodate left-handed frame
74517
- _e1.x *= -1; _e1.y *= -1; _e1.z *= -1;
74518
74893
 
74519
74894
  if ( envMap.isCubeTexture && envMap.isRenderTargetTexture === false ) {
74520
74895
 
74521
- // environment maps which are not cube render targets or PMREMs follow a different convention
74522
- _e1.y *= -1;
74523
- _e1.z *= -1;
74896
+ uniforms.envMapRotation.value.premultiply( _m );
74524
74897
 
74525
74898
  }
74526
74899
 
74527
- uniforms.envMapRotation.value.setFromMatrix4( _m1.makeRotationFromEuler( _e1 ) );
74528
-
74529
- uniforms.flipEnvMap.value = ( envMap.isCubeTexture && envMap.isRenderTargetTexture === false ) ? -1 : 1;
74530
-
74531
74900
  uniforms.reflectivity.value = material.reflectivity;
74532
74901
  uniforms.ior.value = material.ior;
74533
74902
  uniforms.refractionRatio.value = material.refractionRatio;
@@ -75017,6 +75386,11 @@ function WebGLUniformsGroups( gl, info, capabilities, state ) {
75017
75386
  uniform.__data[ 10 ] = value.elements[ 8 ];
75018
75387
  uniform.__data[ 11 ] = 0;
75019
75388
 
75389
+ } else if ( ArrayBuffer.isView( value ) ) {
75390
+
75391
+ // copy the buffer data using "set"
75392
+ uniform.__data.set( new value.constructor( value.buffer, value.byteOffset, uniform.__data.length ) );
75393
+
75020
75394
  } else {
75021
75395
 
75022
75396
  value.toArray( uniform.__data, arrayOffset );
@@ -75052,6 +75426,10 @@ function WebGLUniformsGroups( gl, info, capabilities, state ) {
75052
75426
 
75053
75427
  cache[ indexString ] = value;
75054
75428
 
75429
+ } else if ( ArrayBuffer.isView( value ) ) {
75430
+
75431
+ cache[ indexString ] = value.slice();
75432
+
75055
75433
  } else {
75056
75434
 
75057
75435
  cache[ indexString ] = value.clone();
@@ -75075,6 +75453,11 @@ function WebGLUniformsGroups( gl, info, capabilities, state ) {
75075
75453
 
75076
75454
  }
75077
75455
 
75456
+ } else if ( ArrayBuffer.isView( value ) ) {
75457
+
75458
+ // always update the array buffers
75459
+ return true;
75460
+
75078
75461
  } else {
75079
75462
 
75080
75463
  if ( cachedObject.equals( value ) === false ) {
@@ -75215,6 +75598,11 @@ function WebGLUniformsGroups( gl, info, capabilities, state ) {
75215
75598
 
75216
75599
  warn( 'WebGLRenderer: Texture samplers can not be part of an uniforms group.' );
75217
75600
 
75601
+ } else if ( ArrayBuffer.isView( value ) ) {
75602
+
75603
+ info.boundary = 16;
75604
+ info.storage = value.byteLength;
75605
+
75218
75606
  } else {
75219
75607
 
75220
75608
  warn( 'WebGLRenderer: Unsupported uniform value type.', value );
@@ -75389,6 +75777,7 @@ class WebGLRenderer {
75389
75777
 
75390
75778
  const uintClearColor = new Uint32Array( 4 );
75391
75779
  const intClearColor = new Int32Array( 4 );
75780
+ const objectPosition = new Vector3();
75392
75781
 
75393
75782
  let currentRenderList = null;
75394
75783
  let currentRenderState = null;
@@ -75551,6 +75940,7 @@ class WebGLRenderer {
75551
75940
  const _this = this;
75552
75941
 
75553
75942
  let _isContextLost = false;
75943
+ let _nodesHandler = null;
75554
75944
 
75555
75945
  // internal state cache
75556
75946
 
@@ -75985,7 +76375,7 @@ class WebGLRenderer {
75985
76375
 
75986
76376
  if ( _outputBufferType === UnsignedByteType ) {
75987
76377
 
75988
- console.error( 'THREE.WebGLRenderer: setEffects() requires outputBufferType set to HalfFloatType or FloatType.' );
76378
+ error( 'THREE.WebGLRenderer: setEffects() requires outputBufferType set to HalfFloatType or FloatType.' );
75989
76379
  return;
75990
76380
 
75991
76381
  }
@@ -75996,7 +76386,7 @@ class WebGLRenderer {
75996
76386
 
75997
76387
  if ( effects[ i ].isOutputPass === true ) {
75998
76388
 
75999
- console.warn( 'THREE.WebGLRenderer: OutputPass is not needed in setEffects(). Tone mapping and color space conversion are applied automatically.' );
76389
+ warn( 'THREE.WebGLRenderer: OutputPass is not needed in setEffects(). Tone mapping and color space conversion are applied automatically.' );
76000
76390
  break;
76001
76391
 
76002
76392
  }
@@ -76256,6 +76646,7 @@ class WebGLRenderer {
76256
76646
  if ( depth ) {
76257
76647
 
76258
76648
  bits |= _gl.DEPTH_BUFFER_BIT;
76649
+ this.state.buffers.depth.setMask( true );
76259
76650
 
76260
76651
  }
76261
76652
 
@@ -76301,6 +76692,20 @@ class WebGLRenderer {
76301
76692
 
76302
76693
  };
76303
76694
 
76695
+ /**
76696
+ * Sets a compatibility node builder for rendering node materials with WebGLRenderer.
76697
+ * This enables using TSL (Three.js Shading Language) node materials to prepare
76698
+ * for migration to WebGPURenderer.
76699
+ *
76700
+ * @param {WebGLNodesHandler} nodesHandler - The node builder instance.
76701
+ */
76702
+ this.setNodesHandler = function ( nodesHandler ) {
76703
+
76704
+ nodesHandler.setRenderer( this );
76705
+ _nodesHandler = nodesHandler;
76706
+
76707
+ };
76708
+
76304
76709
  /**
76305
76710
  * Frees the GPU-related resources allocated by this instance. Call this
76306
76711
  * method whenever this instance is no longer used in your app.
@@ -76536,33 +76941,23 @@ class WebGLRenderer {
76536
76941
 
76537
76942
  if ( object.isBatchedMesh ) {
76538
76943
 
76539
- if ( object._multiDrawInstances !== null ) {
76540
-
76541
- // @deprecated, r174
76542
- warnOnce( 'WebGLRenderer: renderMultiDrawInstances has been deprecated and will be removed in r184. Append to renderMultiDraw arguments and use indirection.' );
76543
- renderer.renderMultiDrawInstances( object._multiDrawStarts, object._multiDrawCounts, object._multiDrawCount, object._multiDrawInstances );
76544
-
76545
- } else {
76546
-
76547
- if ( ! extensions.get( 'WEBGL_multi_draw' ) ) {
76944
+ if ( ! extensions.get( 'WEBGL_multi_draw' ) ) {
76548
76945
 
76549
- const starts = object._multiDrawStarts;
76550
- const counts = object._multiDrawCounts;
76551
- const drawCount = object._multiDrawCount;
76552
- const bytesPerElement = index ? attributes.get( index ).bytesPerElement : 1;
76553
- const uniforms = properties.get( material ).currentProgram.getUniforms();
76554
- for ( let i = 0; i < drawCount; i ++ ) {
76946
+ const starts = object._multiDrawStarts;
76947
+ const counts = object._multiDrawCounts;
76948
+ const drawCount = object._multiDrawCount;
76949
+ const bytesPerElement = index ? attributes.get( index ).bytesPerElement : 1;
76950
+ const uniforms = properties.get( material ).currentProgram.getUniforms();
76951
+ for ( let i = 0; i < drawCount; i ++ ) {
76555
76952
 
76556
- uniforms.setValue( _gl, '_gl_DrawID', i );
76557
- renderer.render( starts[ i ] / bytesPerElement, counts[ i ] );
76953
+ uniforms.setValue( _gl, '_gl_DrawID', i );
76954
+ renderer.render( starts[ i ] / bytesPerElement, counts[ i ] );
76558
76955
 
76559
- }
76560
-
76561
- } else {
76956
+ }
76562
76957
 
76563
- renderer.renderMultiDraw( object._multiDrawStarts, object._multiDrawCounts, object._multiDrawCount );
76958
+ } else {
76564
76959
 
76565
- }
76960
+ renderer.renderMultiDraw( object._multiDrawStarts, object._multiDrawCounts, object._multiDrawCount );
76566
76961
 
76567
76962
  }
76568
76963
 
@@ -76861,6 +77256,13 @@ class WebGLRenderer {
76861
77256
 
76862
77257
  if ( _isContextLost === true ) return;
76863
77258
 
77259
+ // update node builder if available
77260
+ if ( _nodesHandler !== null ) {
77261
+
77262
+ _nodesHandler.renderStart( scene, camera );
77263
+
77264
+ }
77265
+
76864
77266
  // use internal render target for HalfFloatType color buffer (only when tone mapping is enabled)
76865
77267
 
76866
77268
  const isXRPresenting = xr.enabled === true && xr.isPresenting === true;
@@ -76889,6 +77291,7 @@ class WebGLRenderer {
76889
77291
  currentRenderState = renderStates.get( scene, renderStateStack.length );
76890
77292
  currentRenderState.init( camera );
76891
77293
 
77294
+ currentRenderState.state.textureUnits = textures.getTextureUnits();
76892
77295
  renderStateStack.push( currentRenderState );
76893
77296
 
76894
77297
  _projScreenMatrix.multiplyMatrices( camera.projectionMatrix, camera.matrixWorldInverse );
@@ -77034,6 +77437,8 @@ class WebGLRenderer {
77034
77437
 
77035
77438
  currentRenderState = renderStateStack[ renderStateStack.length - 1 ];
77036
77439
 
77440
+ textures.setTextureUnits( currentRenderState.state.textureUnits );
77441
+
77037
77442
  if ( _clippingEnabled === true ) clipping.setGlobalState( _this.clippingPlanes, currentRenderState.state.camera );
77038
77443
 
77039
77444
  } else {
@@ -77054,6 +77459,12 @@ class WebGLRenderer {
77054
77459
 
77055
77460
  }
77056
77461
 
77462
+ if ( _nodesHandler !== null ) {
77463
+
77464
+ _nodesHandler.renderEnd();
77465
+
77466
+ }
77467
+
77057
77468
  };
77058
77469
 
77059
77470
  function projectObject( object, camera, groupOrder, sortObjects ) {
@@ -77072,6 +77483,10 @@ class WebGLRenderer {
77072
77483
 
77073
77484
  if ( object.autoUpdate === true ) object.update( camera );
77074
77485
 
77486
+ } else if ( object.isLightProbeGrid ) {
77487
+
77488
+ currentRenderState.pushLightProbeGrid( object );
77489
+
77075
77490
  } else if ( object.isLight ) {
77076
77491
 
77077
77492
  currentRenderState.pushLight( object );
@@ -77212,7 +77627,7 @@ class WebGLRenderer {
77212
77627
  generateMipmaps: true,
77213
77628
  type: hasHalfFloatSupport ? HalfFloatType : UnsignedByteType,
77214
77629
  minFilter: LinearMipmapLinearFilter,
77215
- samples: capabilities.samples,
77630
+ samples: Math.max( 4, capabilities.samples ), // to avoid feedback loops, the transmission render target requires a resolve, see #26177
77216
77631
  stencilBuffer: stencil,
77217
77632
  resolveDepthBuffer: false,
77218
77633
  resolveStencilBuffer: false,
@@ -77387,7 +77802,7 @@ class WebGLRenderer {
77387
77802
 
77388
77803
  const lightsStateVersion = lights.state.version;
77389
77804
 
77390
- const parameters = programCache.getParameters( material, lights.state, shadowsArray, scene, object );
77805
+ const parameters = programCache.getParameters( material, lights.state, shadowsArray, scene, object, currentRenderState.state.lightProbeGridArray );
77391
77806
  const programCacheKey = programCache.getProgramCacheKey( parameters );
77392
77807
 
77393
77808
  let programs = materialProperties.programs;
@@ -77430,6 +77845,13 @@ class WebGLRenderer {
77430
77845
 
77431
77846
  parameters.uniforms = programCache.getUniforms( material );
77432
77847
 
77848
+ // Use node builder for node materials if available
77849
+ if ( _nodesHandler !== null && material.isNodeMaterial ) {
77850
+
77851
+ _nodesHandler.build( material, object, parameters );
77852
+
77853
+ }
77854
+
77433
77855
  material.onBeforeCompile( parameters, _this );
77434
77856
 
77435
77857
  program = programCache.acquireProgram( parameters, programCacheKey );
@@ -77479,6 +77901,8 @@ class WebGLRenderer {
77479
77901
 
77480
77902
  }
77481
77903
 
77904
+ materialProperties.lightProbeGrid = currentRenderState.state.lightProbeGridArray.length > 0;
77905
+
77482
77906
  materialProperties.currentProgram = program;
77483
77907
  materialProperties.uniformsList = null;
77484
77908
 
@@ -77522,6 +77946,30 @@ class WebGLRenderer {
77522
77946
 
77523
77947
  }
77524
77948
 
77949
+ function findLightProbeGrid( volumes, object ) {
77950
+
77951
+ if ( volumes.length === 0 ) return null;
77952
+
77953
+ if ( volumes.length === 1 ) {
77954
+
77955
+ return volumes[ 0 ].texture !== null ? volumes[ 0 ] : null;
77956
+
77957
+ }
77958
+
77959
+ objectPosition.setFromMatrixPosition( object.matrixWorld );
77960
+
77961
+ for ( let i = 0, l = volumes.length; i < l; i ++ ) {
77962
+
77963
+ const v = volumes[ i ];
77964
+
77965
+ if ( v.texture !== null && v.boundingBox.containsPoint( objectPosition ) ) return v;
77966
+
77967
+ }
77968
+
77969
+ return null;
77970
+
77971
+ }
77972
+
77525
77973
  function setProgram( camera, scene, geometry, material, object ) {
77526
77974
 
77527
77975
  if ( scene.isScene !== true ) scene = _emptyScene; // scene could be a Mesh, Line, Points, ...
@@ -77530,7 +77978,7 @@ class WebGLRenderer {
77530
77978
 
77531
77979
  const fog = scene.fog;
77532
77980
  const environment = ( material.isMeshStandardMaterial || material.isMeshLambertMaterial || material.isMeshPhongMaterial ) ? scene.environment : null;
77533
- const colorSpace = ( _currentRenderTarget === null ) ? _this.outputColorSpace : ( _currentRenderTarget.isXRRenderTarget === true ? _currentRenderTarget.texture.colorSpace : LinearSRGBColorSpace );
77981
+ const colorSpace = ( _currentRenderTarget === null ) ? _this.outputColorSpace : ( _currentRenderTarget.isXRRenderTarget === true ? _currentRenderTarget.texture.colorSpace : ColorManagement.workingColorSpace );
77534
77982
  const usePMREM = material.isMeshStandardMaterial || ( material.isMeshLambertMaterial && ! material.envMap ) || ( material.isMeshPhongMaterial && ! material.envMap );
77535
77983
  const envMap = environments.get( material.envMap || environment, usePMREM );
77536
77984
  const vertexAlphas = material.vertexColors === true && !! geometry.attributes.color && geometry.attributes.color.itemSize === 4;
@@ -77678,6 +78126,10 @@ class WebGLRenderer {
77678
78126
 
77679
78127
  needsProgramChange = true;
77680
78128
 
78129
+ } else if ( !! materialProperties.lightProbeGrid !== ( currentRenderState.state.lightProbeGridArray.length > 0 ) ) {
78130
+
78131
+ needsProgramChange = true;
78132
+
77681
78133
  }
77682
78134
 
77683
78135
  } else {
@@ -77695,6 +78147,14 @@ class WebGLRenderer {
77695
78147
 
77696
78148
  program = getProgram( material, scene, object );
77697
78149
 
78150
+ // notify the node builder that the program has changed so uniforms and update nodes can
78151
+ // be cached and triggered.
78152
+ if ( _nodesHandler && material.isNodeMaterial ) {
78153
+
78154
+ _nodesHandler.onUpdateProgram( material, program, materialProperties );
78155
+
78156
+ }
78157
+
77698
78158
  }
77699
78159
 
77700
78160
  let refreshProgram = false;
@@ -77720,6 +78180,19 @@ class WebGLRenderer {
77720
78180
 
77721
78181
  }
77722
78182
 
78183
+ if ( materialProperties.needsLights ) {
78184
+
78185
+ const objectVolume = findLightProbeGrid( currentRenderState.state.lightProbeGridArray, object );
78186
+
78187
+ if ( materialProperties.lightProbeGrid !== objectVolume ) {
78188
+
78189
+ materialProperties.lightProbeGrid = objectVolume;
78190
+ refreshMaterial = true;
78191
+
78192
+ }
78193
+
78194
+ }
78195
+
77723
78196
  if ( refreshProgram || _currentCamera !== camera ) {
77724
78197
 
77725
78198
  // common camera uniforms
@@ -77899,6 +78372,19 @@ class WebGLRenderer {
77899
78372
 
77900
78373
  materials.refreshMaterialUniforms( m_uniforms, material, _pixelRatio, _height, currentRenderState.state.transmissionRenderTarget[ camera.id ] );
77901
78374
 
78375
+ // light probe volume
78376
+
78377
+ if ( materialProperties.needsLights && materialProperties.lightProbeGrid ) {
78378
+
78379
+ const volume = materialProperties.lightProbeGrid;
78380
+
78381
+ m_uniforms.probesSH.value = volume.texture;
78382
+ m_uniforms.probesMin.value.copy( volume.boundingBox.min );
78383
+ m_uniforms.probesMax.value.copy( volume.boundingBox.max );
78384
+ m_uniforms.probesResolution.value.copy( volume.resolution );
78385
+
78386
+ }
78387
+
77902
78388
  WebGLUniforms.upload( _gl, getUniformList( materialProperties ), m_uniforms, textures );
77903
78389
 
77904
78390
  }
@@ -77924,7 +78410,7 @@ class WebGLRenderer {
77924
78410
 
77925
78411
  // UBOs
77926
78412
 
77927
- if ( material.isShaderMaterial || material.isRawShaderMaterial ) {
78413
+ if ( material.uniformsGroups !== undefined ) {
77928
78414
 
77929
78415
  const groups = material.uniformsGroups;
77930
78416
 
@@ -78500,22 +78986,24 @@ class WebGLRenderer {
78500
78986
 
78501
78987
  }
78502
78988
 
78503
- _gl.pixelStorei( _gl.UNPACK_FLIP_Y_WEBGL, dstTexture.flipY );
78504
- _gl.pixelStorei( _gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, dstTexture.premultiplyAlpha );
78505
- _gl.pixelStorei( _gl.UNPACK_ALIGNMENT, dstTexture.unpackAlignment );
78989
+ state.activeTexture( _gl.TEXTURE0 ); // see #33153
78990
+
78991
+ state.pixelStorei( _gl.UNPACK_FLIP_Y_WEBGL, dstTexture.flipY );
78992
+ state.pixelStorei( _gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, dstTexture.premultiplyAlpha );
78993
+ state.pixelStorei( _gl.UNPACK_ALIGNMENT, dstTexture.unpackAlignment );
78506
78994
 
78507
78995
  // used for copying data from cpu
78508
- const currentUnpackRowLen = _gl.getParameter( _gl.UNPACK_ROW_LENGTH );
78509
- const currentUnpackImageHeight = _gl.getParameter( _gl.UNPACK_IMAGE_HEIGHT );
78510
- const currentUnpackSkipPixels = _gl.getParameter( _gl.UNPACK_SKIP_PIXELS );
78511
- const currentUnpackSkipRows = _gl.getParameter( _gl.UNPACK_SKIP_ROWS );
78512
- const currentUnpackSkipImages = _gl.getParameter( _gl.UNPACK_SKIP_IMAGES );
78513
-
78514
- _gl.pixelStorei( _gl.UNPACK_ROW_LENGTH, image.width );
78515
- _gl.pixelStorei( _gl.UNPACK_IMAGE_HEIGHT, image.height );
78516
- _gl.pixelStorei( _gl.UNPACK_SKIP_PIXELS, minX );
78517
- _gl.pixelStorei( _gl.UNPACK_SKIP_ROWS, minY );
78518
- _gl.pixelStorei( _gl.UNPACK_SKIP_IMAGES, minZ );
78996
+ const currentUnpackRowLen = state.getParameter( _gl.UNPACK_ROW_LENGTH );
78997
+ const currentUnpackImageHeight = state.getParameter( _gl.UNPACK_IMAGE_HEIGHT );
78998
+ const currentUnpackSkipPixels = state.getParameter( _gl.UNPACK_SKIP_PIXELS );
78999
+ const currentUnpackSkipRows = state.getParameter( _gl.UNPACK_SKIP_ROWS );
79000
+ const currentUnpackSkipImages = state.getParameter( _gl.UNPACK_SKIP_IMAGES );
79001
+
79002
+ state.pixelStorei( _gl.UNPACK_ROW_LENGTH, image.width );
79003
+ state.pixelStorei( _gl.UNPACK_IMAGE_HEIGHT, image.height );
79004
+ state.pixelStorei( _gl.UNPACK_SKIP_PIXELS, minX );
79005
+ state.pixelStorei( _gl.UNPACK_SKIP_ROWS, minY );
79006
+ state.pixelStorei( _gl.UNPACK_SKIP_IMAGES, minZ );
78519
79007
 
78520
79008
  // set up the src texture
78521
79009
  const isSrc3D = srcTexture.isDataArrayTexture || srcTexture.isData3DTexture;
@@ -78641,11 +79129,11 @@ class WebGLRenderer {
78641
79129
  }
78642
79130
 
78643
79131
  // reset values
78644
- _gl.pixelStorei( _gl.UNPACK_ROW_LENGTH, currentUnpackRowLen );
78645
- _gl.pixelStorei( _gl.UNPACK_IMAGE_HEIGHT, currentUnpackImageHeight );
78646
- _gl.pixelStorei( _gl.UNPACK_SKIP_PIXELS, currentUnpackSkipPixels );
78647
- _gl.pixelStorei( _gl.UNPACK_SKIP_ROWS, currentUnpackSkipRows );
78648
- _gl.pixelStorei( _gl.UNPACK_SKIP_IMAGES, currentUnpackSkipImages );
79132
+ state.pixelStorei( _gl.UNPACK_ROW_LENGTH, currentUnpackRowLen );
79133
+ state.pixelStorei( _gl.UNPACK_IMAGE_HEIGHT, currentUnpackImageHeight );
79134
+ state.pixelStorei( _gl.UNPACK_SKIP_PIXELS, currentUnpackSkipPixels );
79135
+ state.pixelStorei( _gl.UNPACK_SKIP_ROWS, currentUnpackSkipRows );
79136
+ state.pixelStorei( _gl.UNPACK_SKIP_IMAGES, currentUnpackSkipImages );
78649
79137
 
78650
79138
  // Generate mipmaps only when copying level 0
78651
79139
  if ( dstLevel === 0 && dstTexture.generateMipmaps ) {
@@ -78909,6 +79397,7 @@ var THREE = /*#__PURE__*/Object.freeze({
78909
79397
  GreaterStencilFunc: GreaterStencilFunc,
78910
79398
  GridHelper: GridHelper$1,
78911
79399
  Group: Group,
79400
+ HTMLTexture: HTMLTexture,
78912
79401
  HalfFloatType: HalfFloatType,
78913
79402
  HemisphereLight: HemisphereLight,
78914
79403
  HemisphereLightHelper: HemisphereLightHelper,
@@ -80139,7 +80628,7 @@ class LineMaterial extends ShaderMaterial {
80139
80628
 
80140
80629
  /**
80141
80630
  * The size of the viewport, in screen pixels. This must be kept updated to make
80142
- * screen-space rendering accurate.The `LineSegments2.onBeforeRender` callback
80631
+ * screen-space rendering accurate. The `LineSegments2.onBeforeRender` callback
80143
80632
  * performs the update for visible objects.
80144
80633
  *
80145
80634
  * @type {Vector2}
@@ -83908,8 +84397,9 @@ function applyTriplanarMapping(material, geometry) {
83908
84397
  // Uniform values (captured by closure, per-object)
83909
84398
  const offset = bb.min.clone();
83910
84399
  const scale = 1.0 / maxDim;
83911
- // Read texture repeat from the material's map (all textures share same repeat)
83912
- const repeat = material.map?.repeat?.clone() ?? new Vector2(1, 1);
84400
+ // Read texture repeat from the first available texture map
84401
+ const repeat = (material.map ?? material.roughnessMap ?? material.normalMap ??
84402
+ material.metalnessMap ?? material.emissiveMap ?? material.aoMap)?.repeat?.clone() ?? new Vector2(1, 1);
83913
84403
  material.onBeforeCompile = (shader) => {
83914
84404
  // Custom uniforms
83915
84405
  shader.uniforms.triplanarOffset = { value: offset };
@@ -89063,7 +89553,7 @@ class OrbitControls extends Controls$1 {
89063
89553
  const document = this.domElement.getRootNode(); // offscreen canvas compatibility
89064
89554
  document.addEventListener( 'keydown', this._interceptControlDown, { passive: true, capture: true } );
89065
89555
 
89066
- this.domElement.style.touchAction = 'none'; // disable touch scroll
89556
+ this.domElement.style.touchAction = 'none'; // Disable touch scroll
89067
89557
 
89068
89558
  }
89069
89559
 
@@ -89082,7 +89572,7 @@ class OrbitControls extends Controls$1 {
89082
89572
  const document = this.domElement.getRootNode(); // offscreen canvas compatibility
89083
89573
  document.removeEventListener( 'keydown', this._interceptControlDown, { capture: true } );
89084
89574
 
89085
- this.domElement.style.touchAction = 'auto';
89575
+ this.domElement.style.touchAction = ''; // Restore touch scroll
89086
89576
 
89087
89577
  }
89088
89578
 
@@ -90590,9 +91080,10 @@ class CADOrbitControls extends OrbitControls {
90590
91080
  */
90591
91081
  dispose() {
90592
91082
  if (this.domElement && this._onCADPointerDown && this._onCADPointerUp) {
90593
- this.domElement.removeEventListener("pointerdown", this._onCADPointerDown);
90594
- this.domElement.removeEventListener("pointerup", this._onCADPointerUp);
90595
- this.domElement.removeEventListener("pointercancel", this._onCADPointerUp);
91083
+ const el = this.domElement;
91084
+ el.removeEventListener("pointerdown", this._onCADPointerDown);
91085
+ el.removeEventListener("pointerup", this._onCADPointerUp);
91086
+ el.removeEventListener("pointercancel", this._onCADPointerUp);
90596
91087
  }
90597
91088
  super.dispose();
90598
91089
  }
@@ -90992,7 +91483,7 @@ class TrackballControls extends Controls$1 {
90992
91483
  this.domElement.addEventListener( 'wheel', this._onMouseWheel, { passive: false } );
90993
91484
  this.domElement.addEventListener( 'contextmenu', this._onContextMenu );
90994
91485
 
90995
- this.domElement.style.touchAction = 'none'; // disable touch scroll
91486
+ this.domElement.style.touchAction = 'none'; // Disable touch scroll
90996
91487
 
90997
91488
  }
90998
91489
 
@@ -91008,7 +91499,7 @@ class TrackballControls extends Controls$1 {
91008
91499
  this.domElement.removeEventListener( 'wheel', this._onMouseWheel );
91009
91500
  this.domElement.removeEventListener( 'contextmenu', this._onContextMenu );
91010
91501
 
91011
- this.domElement.style.touchAction = 'auto'; // disable touch scroll
91502
+ this.domElement.style.touchAction = ''; // Restore touch scroll
91012
91503
 
91013
91504
  }
91014
91505
 
@@ -91932,11 +92423,12 @@ class CADTrackballControls extends TrackballControls {
91932
92423
  this._holroydPointerMove &&
91933
92424
  this._holroydPointerUp &&
91934
92425
  this._holroydWheel) {
91935
- this.domElement.removeEventListener("pointerdown", this._holroydPointerDown);
91936
- this.domElement.removeEventListener("pointermove", this._holroydPointerMove);
91937
- this.domElement.removeEventListener("pointerup", this._holroydPointerUp);
91938
- this.domElement.removeEventListener("pointercancel", this._holroydPointerUp);
91939
- this.domElement.removeEventListener("wheel", this._holroydWheel);
92426
+ const el = this.domElement;
92427
+ el.removeEventListener("pointerdown", this._holroydPointerDown);
92428
+ el.removeEventListener("pointermove", this._holroydPointerMove);
92429
+ el.removeEventListener("pointerup", this._holroydPointerUp);
92430
+ el.removeEventListener("pointercancel", this._holroydPointerUp);
92431
+ el.removeEventListener("wheel", this._holroydWheel);
91940
92432
  }
91941
92433
  super.dispose();
91942
92434
  }
@@ -94303,7 +94795,7 @@ class Tools {
94303
94795
  }
94304
94796
  }
94305
94797
 
94306
- const version = "4.3.6";
94798
+ const version = "4.3.8";
94307
94799
 
94308
94800
  /**
94309
94801
  * Clean room environment for Studio mode PMREM generation.
@@ -94537,7 +95029,7 @@ class HDRLoader extends DataTextureLoader {
94537
95029
 
94538
95030
  s += chunk; len += chunk.length;
94539
95031
  p += chunkSize;
94540
- chunk += String.fromCharCode.apply( null, new Uint16Array( buffer.subarray( p, p + chunkSize ) ) );
95032
+ chunk = String.fromCharCode.apply( null, new Uint16Array( buffer.subarray( p, p + chunkSize ) ) );
94541
95033
 
94542
95034
  }
94543
95035
 
@@ -95286,6 +95778,14 @@ class EnvironmentManager {
95286
95778
  constructor(options = {}) {
95287
95779
  /** Cached PMREM render targets keyed by environment name or URL */
95288
95780
  this._cache = new Map();
95781
+ /**
95782
+ * Cached raw equirectangular HDR textures keyed by the same name/URL.
95783
+ * Preserved (not disposed after PMREM generation) so `scene.background`
95784
+ * can sample the original HDR at full source resolution instead of the
95785
+ * 256² PMREM cubemap. Only populated by `_loadHdr` — procedural
95786
+ * environments have no source HDR.
95787
+ */
95788
+ this._hdrCache = new Map();
95289
95789
  /** Cached light detection results keyed by environment name or URL */
95290
95790
  this._lightDetectionCache = new Map();
95291
95791
  /** In-flight load promises keyed by environment name or URL */
@@ -95300,6 +95800,13 @@ class EnvironmentManager {
95300
95800
  this._hdrLoader = null;
95301
95801
  /** The last loaded PMREM texture (stateful — used by apply() for IBL) */
95302
95802
  this._currentTexture = null;
95803
+ /**
95804
+ * Raw HDR texture corresponding to `_currentTexture`, used for
95805
+ * `scene.background` to keep the backdrop at source resolution. Null when
95806
+ * the current environment is procedural ("studio" RoomEnvironment) — in
95807
+ * that case the background falls back to `_currentTexture` (the PMREM).
95808
+ */
95809
+ this._currentBackgroundTexture = null;
95303
95810
  /** Whether this manager has been disposed */
95304
95811
  this._disposed = false;
95305
95812
  /**
@@ -95353,6 +95860,7 @@ class EnvironmentManager {
95353
95860
  }
95354
95861
  if (name === "none") {
95355
95862
  this._currentTexture = null;
95863
+ this._currentBackgroundTexture = null;
95356
95864
  return null;
95357
95865
  }
95358
95866
  // Check cache first (name is the cache key for presets; URL string for custom)
@@ -95361,6 +95869,7 @@ class EnvironmentManager {
95361
95869
  if (cached) {
95362
95870
  logger.debug(`Environment "${cacheKey}" loaded from cache`);
95363
95871
  this._currentTexture = cached.texture;
95872
+ this._currentBackgroundTexture = this._hdrCache.get(cacheKey) ?? null;
95364
95873
  return cached.texture;
95365
95874
  }
95366
95875
  // Check in-flight promise — await and set _currentTexture
@@ -95369,6 +95878,7 @@ class EnvironmentManager {
95369
95878
  logger.debug(`Environment "${cacheKey}" already loading, reusing promise`);
95370
95879
  const texture = await inflight;
95371
95880
  this._currentTexture = texture;
95881
+ this._currentBackgroundTexture = this._hdrCache.get(cacheKey) ?? null;
95372
95882
  return texture;
95373
95883
  }
95374
95884
  // Start new load
@@ -95377,6 +95887,7 @@ class EnvironmentManager {
95377
95887
  try {
95378
95888
  const texture = await promise;
95379
95889
  this._currentTexture = texture;
95890
+ this._currentBackgroundTexture = this._hdrCache.get(cacheKey) ?? null;
95380
95891
  // Self-healing: if apply() was called with "environment" background
95381
95892
  // while texture was null, re-apply now that the texture is ready.
95382
95893
  if (this._deferredApply) {
@@ -95454,9 +95965,13 @@ class EnvironmentManager {
95454
95965
  break;
95455
95966
  case "environment":
95456
95967
  if (this._currentTexture) {
95968
+ // Prefer the raw HDR for the background so the backdrop samples
95969
+ // at source resolution (2K/4K) rather than the 256² PMREM cubemap.
95970
+ // Falls back to PMREM for procedural "studio" (no source HDR).
95971
+ const bgTex = this._currentBackgroundTexture ?? this._currentTexture;
95457
95972
  // Always use render-to-texture with a fixed-FOV bgCamera so the
95458
95973
  // background zoom level is identical in perspective and ortho modes.
95459
- this._setupEnvBackground(scene, this._currentTexture, upIsZ, rotY);
95974
+ this._setupEnvBackground(scene, bgTex, upIsZ, rotY);
95460
95975
  this._deferredApply = null;
95461
95976
  }
95462
95977
  else {
@@ -95541,6 +96056,12 @@ class EnvironmentManager {
95541
96056
  this._lightDetectionCache.delete(slug);
95542
96057
  logger.debug(`Evicted cached environment "${slug}" for resolution switch`);
95543
96058
  }
96059
+ const cachedHdr = this._hdrCache.get(slug);
96060
+ if (cachedHdr) {
96061
+ gpuTracker.untrack("texture", cachedHdr);
96062
+ cachedHdr.dispose();
96063
+ this._hdrCache.delete(slug);
96064
+ }
95544
96065
  }
95545
96066
  // Reload the current environment at the new resolution
95546
96067
  if (currentEnvName && currentEnvName !== "none" && currentEnvName !== "studio") {
@@ -95639,6 +96160,7 @@ class EnvironmentManager {
95639
96160
  dispose() {
95640
96161
  this._disposed = true;
95641
96162
  this._currentTexture = null;
96163
+ this._currentBackgroundTexture = null;
95642
96164
  this._deferredApply = null;
95643
96165
  this._teardownEnvBackground();
95644
96166
  this._bgScene = null;
@@ -95654,6 +96176,13 @@ class EnvironmentManager {
95654
96176
  logger.debug(`Disposed cached environment render target: ${key}`);
95655
96177
  }
95656
96178
  this._cache.clear();
96179
+ // Dispose all cached raw HDR textures
96180
+ for (const [key, hdrTexture] of this._hdrCache) {
96181
+ gpuTracker.untrack("texture", hdrTexture);
96182
+ hdrTexture.dispose();
96183
+ logger.debug(`Disposed cached HDR background: ${key}`);
96184
+ }
96185
+ this._hdrCache.clear();
95657
96186
  this._lightDetectionCache.clear();
95658
96187
  // Clear in-flight promises (they'll resolve but won't be cached)
95659
96188
  this._inflight.clear();
@@ -95808,9 +96337,10 @@ class EnvironmentManager {
95808
96337
  * Load an HDR file and generate a PMREM texture from it.
95809
96338
  *
95810
96339
  * Uses HDRLoader to fetch the .hdr file, then PMREMGenerator.fromEquirectangular()
95811
- * to create the PMREM cubemap. The source equirectangular texture is disposed
95812
- * after PMREM generation. The PMREM texture itself serves as both the IBL
95813
- * environment and the background (in "environment" mode).
96340
+ * to create the PMREM cubemap for IBL. The source equirectangular HDR is
96341
+ * preserved and cached separately (in `_hdrCache`) so that "environment"
96342
+ * background mode can sample the full-resolution equirectangular texture
96343
+ * instead of the 256² PMREM cubemap.
95814
96344
  *
95815
96345
  * @param url - URL of the .hdr file
95816
96346
  * @param cacheKey - Cache key for the resulting PMREM render target
@@ -95840,11 +96370,15 @@ class EnvironmentManager {
95840
96370
  const result = detectDominantLights(hdrTexture.image.data, hdrTexture.image.width, hdrTexture.image.height);
95841
96371
  this._lightDetectionCache.set(cacheKey, result);
95842
96372
  }
95843
- // Dispose the source equirectangular texture (PMREM is now in GPU memory).
95844
- hdrTexture.dispose();
95845
- // Cache render target and track its texture
96373
+ // Preserve the equirectangular HDR for use as `scene.background` at
96374
+ // source resolution. PMREM's base mip is a 256² cubemap — good for IBL
96375
+ // (roughness-weighted prefilter) but visibly soft as a backdrop.
96376
+ hdrTexture.mapping = EquirectangularReflectionMapping;
96377
+ // Cache render target and HDR; track both.
95846
96378
  this._cache.set(cacheKey, renderTarget);
96379
+ this._hdrCache.set(cacheKey, hdrTexture);
95847
96380
  gpuTracker.trackTexture(renderTarget.texture, `PMREM environment: ${cacheKey}`);
96381
+ gpuTracker.trackTexture(hdrTexture, `HDR background: ${cacheKey}`);
95848
96382
  logger.debug(`Loaded HDR environment from "${url}", cached as "${cacheKey}"`);
95849
96383
  return renderTarget.texture;
95850
96384
  }
@@ -95952,104 +96486,12 @@ class StudioFloor {
95952
96486
  }
95953
96487
 
95954
96488
  /**
95955
- * postprocessing v6.38.3 build Thu Feb 19 2026
96489
+ * postprocessing v6.39.0 build Fri Mar 20 2026
95956
96490
  * https://github.com/pmndrs/postprocessing
95957
96491
  * Copyright 2015-2026 Raoul van Rüschen
95958
96492
  * @license Zlib
95959
96493
  */
95960
96494
 
95961
-
95962
- // src/core/Timer.js
95963
- var MILLISECONDS_TO_SECONDS = 1 / 1e3;
95964
- var SECONDS_TO_MILLISECONDS = 1e3;
95965
- var Timer = class {
95966
- /**
95967
- * Constructs a new timer.
95968
- */
95969
- constructor() {
95970
- this.startTime = performance.now();
95971
- this.previousTime = 0;
95972
- this.currentTime = 0;
95973
- this._delta = 0;
95974
- this._elapsed = 0;
95975
- this._fixedDelta = 1e3 / 60;
95976
- this.timescale = 1;
95977
- this.useFixedDelta = false;
95978
- this._autoReset = false;
95979
- }
95980
- /**
95981
- * Enables or disables auto reset based on page visibility.
95982
- *
95983
- * If enabled, the timer will be reset when the page becomes visible. This effectively pauses the timer when the page
95984
- * is hidden. Has no effect if the API is not supported.
95985
- *
95986
- * @type {Boolean}
95987
- * @see https://developer.mozilla.org/en-US/docs/Web/API/Page_Visibility_API
95988
- */
95989
- get autoReset() {
95990
- return this._autoReset;
95991
- }
95992
- set autoReset(value) {
95993
- if (typeof document !== "undefined" && document.hidden !== void 0) {
95994
- if (value) {
95995
- document.addEventListener("visibilitychange", this);
95996
- } else {
95997
- document.removeEventListener("visibilitychange", this);
95998
- }
95999
- this._autoReset = value;
96000
- }
96001
- }
96002
- get delta() {
96003
- return this._delta * MILLISECONDS_TO_SECONDS;
96004
- }
96005
- get fixedDelta() {
96006
- return this._fixedDelta * MILLISECONDS_TO_SECONDS;
96007
- }
96008
- set fixedDelta(value) {
96009
- this._fixedDelta = value * SECONDS_TO_MILLISECONDS;
96010
- }
96011
- get elapsed() {
96012
- return this._elapsed * MILLISECONDS_TO_SECONDS;
96013
- }
96014
- /**
96015
- * Updates this timer.
96016
- *
96017
- * @param {Boolean} [timestamp] - The current time in milliseconds.
96018
- */
96019
- update(timestamp) {
96020
- if (this.useFixedDelta) {
96021
- this._delta = this.fixedDelta;
96022
- } else {
96023
- this.previousTime = this.currentTime;
96024
- this.currentTime = (timestamp !== void 0 ? timestamp : performance.now()) - this.startTime;
96025
- this._delta = this.currentTime - this.previousTime;
96026
- }
96027
- this._delta *= this.timescale;
96028
- this._elapsed += this._delta;
96029
- }
96030
- /**
96031
- * Resets this timer.
96032
- */
96033
- reset() {
96034
- this._delta = 0;
96035
- this._elapsed = 0;
96036
- this.currentTime = performance.now() - this.startTime;
96037
- }
96038
- getDelta() {
96039
- return this.delta;
96040
- }
96041
- getElapsed() {
96042
- return this.elapsed;
96043
- }
96044
- handleEvent(e) {
96045
- if (!document.hidden) {
96046
- this.currentTime = performance.now() - this.startTime;
96047
- }
96048
- }
96049
- dispose() {
96050
- this.autoReset = false;
96051
- }
96052
- };
96053
96495
  var fullscreenGeometry = /* @__PURE__ */ (() => {
96054
96496
  const vertices = new Float32Array([-1, -1, 0, 3, -1, 0, -1, 3, 0]);
96055
96497
  const uvs = new Float32Array([0, 0, 2, 0, 0, 2]);
@@ -96085,6 +96527,7 @@ var Pass = class _Pass {
96085
96527
  this.screen = null;
96086
96528
  this.rtt = true;
96087
96529
  this.needsSwap = true;
96530
+ this.needsDepthBlit = false;
96088
96531
  this.needsDepthTexture = false;
96089
96532
  this.enabled = true;
96090
96533
  }
@@ -96811,6 +97254,98 @@ var MaskPass = class extends Pass {
96811
97254
  }
96812
97255
  };
96813
97256
 
97257
+ // src/core/Timer.js
97258
+ var MILLISECONDS_TO_SECONDS = 1 / 1e3;
97259
+ var SECONDS_TO_MILLISECONDS = 1e3;
97260
+ var Timer = class {
97261
+ /**
97262
+ * Constructs a new timer.
97263
+ */
97264
+ constructor() {
97265
+ this.startTime = performance.now();
97266
+ this.previousTime = 0;
97267
+ this.currentTime = 0;
97268
+ this._delta = 0;
97269
+ this._elapsed = 0;
97270
+ this._fixedDelta = 1e3 / 60;
97271
+ this.timescale = 1;
97272
+ this.useFixedDelta = false;
97273
+ this._autoReset = false;
97274
+ }
97275
+ /**
97276
+ * Enables or disables auto reset based on page visibility.
97277
+ *
97278
+ * If enabled, the timer will be reset when the page becomes visible. This effectively pauses the timer when the page
97279
+ * is hidden. Has no effect if the API is not supported.
97280
+ *
97281
+ * @type {Boolean}
97282
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/Page_Visibility_API
97283
+ */
97284
+ get autoReset() {
97285
+ return this._autoReset;
97286
+ }
97287
+ set autoReset(value) {
97288
+ if (typeof document !== "undefined" && document.hidden !== void 0) {
97289
+ if (value) {
97290
+ document.addEventListener("visibilitychange", this);
97291
+ } else {
97292
+ document.removeEventListener("visibilitychange", this);
97293
+ }
97294
+ this._autoReset = value;
97295
+ }
97296
+ }
97297
+ get delta() {
97298
+ return this._delta * MILLISECONDS_TO_SECONDS;
97299
+ }
97300
+ get fixedDelta() {
97301
+ return this._fixedDelta * MILLISECONDS_TO_SECONDS;
97302
+ }
97303
+ set fixedDelta(value) {
97304
+ this._fixedDelta = value * SECONDS_TO_MILLISECONDS;
97305
+ }
97306
+ get elapsed() {
97307
+ return this._elapsed * MILLISECONDS_TO_SECONDS;
97308
+ }
97309
+ /**
97310
+ * Updates this timer.
97311
+ *
97312
+ * @param {Boolean} [timestamp] - The current time in milliseconds.
97313
+ */
97314
+ update(timestamp) {
97315
+ if (this.useFixedDelta) {
97316
+ this._delta = this.fixedDelta;
97317
+ } else {
97318
+ this.previousTime = this.currentTime;
97319
+ this.currentTime = (timestamp !== void 0 ? timestamp : performance.now()) - this.startTime;
97320
+ this._delta = this.currentTime - this.previousTime;
97321
+ }
97322
+ this._delta *= this.timescale;
97323
+ this._elapsed += this._delta;
97324
+ }
97325
+ /**
97326
+ * Resets this timer.
97327
+ */
97328
+ reset() {
97329
+ this._delta = 0;
97330
+ this._elapsed = 0;
97331
+ this.currentTime = performance.now() - this.startTime;
97332
+ }
97333
+ getDelta() {
97334
+ return this.delta;
97335
+ }
97336
+ getElapsed() {
97337
+ return this.elapsed;
97338
+ }
97339
+ handleEvent(e) {
97340
+ if (!document.hidden) {
97341
+ this.currentTime = performance.now() - this.startTime;
97342
+ }
97343
+ }
97344
+ dispose() {
97345
+ this.autoReset = false;
97346
+ }
97347
+ };
97348
+
96814
97349
  // src/core/EffectComposer.js
96815
97350
  var EffectComposer = class {
96816
97351
  /**
@@ -96820,7 +97355,6 @@ var EffectComposer = class {
96820
97355
  * @param {Object} [options] - The options.
96821
97356
  * @param {Boolean} [options.depthBuffer=true] - Whether the main render targets should have a depth buffer.
96822
97357
  * @param {Boolean} [options.stencilBuffer=false] - Whether the main render targets should have a stencil buffer.
96823
- * @param {Boolean} [options.alpha] - Deprecated. Buffers are always RGBA since three r137.
96824
97358
  * @param {Number} [options.multisampling=0] - The number of samples used for multisample antialiasing. Requires WebGL 2.
96825
97359
  * @param {Number} [options.frameBufferType] - The type of the internal frame buffers. It's recommended to use HalfFloatType if possible.
96826
97360
  */
@@ -96835,6 +97369,7 @@ var EffectComposer = class {
96835
97369
  this.outputBuffer = this.inputBuffer.clone();
96836
97370
  this.copyPass = new CopyPass();
96837
97371
  this.depthTexture = null;
97372
+ this.depthRenderTarget = null;
96838
97373
  this.passes = [];
96839
97374
  this.timer = new Timer();
96840
97375
  this.autoRenderToScreen = true;
@@ -96846,7 +97381,7 @@ var EffectComposer = class {
96846
97381
  * @type {Number}
96847
97382
  */
96848
97383
  get multisampling() {
96849
- return this.inputBuffer.samples || 0;
97384
+ return this.inputBuffer.samples;
96850
97385
  }
96851
97386
  /**
96852
97387
  * Sets the amount of MSAA samples.
@@ -96872,7 +97407,6 @@ var EffectComposer = class {
96872
97407
  buffer.texture.type,
96873
97408
  value
96874
97409
  );
96875
- this.inputBuffer.depthTexture = this.depthTexture;
96876
97410
  this.outputBuffer = this.inputBuffer.clone();
96877
97411
  }
96878
97412
  }
@@ -96943,23 +97477,65 @@ var EffectComposer = class {
96943
97477
  /**
96944
97478
  * Creates a depth texture attachment that will be provided to all passes.
96945
97479
  *
96946
- * Note: When a shader reads from a depth texture and writes to a render target that uses the same depth texture
96947
- * attachment, the depth information will be lost. This happens even if `depthWrite` is disabled.
97480
+ * To prevent errors or incorrect behavior when the same depth buffer is attached to the input and output buffers,
97481
+ * a separate stable depth target is created alongside the ping-pong buffers. All passes receive the stable target's
97482
+ * depth texture, which is never used as a render output and therefore cannot create a feedback loop. The stable
97483
+ * texture is populated each frame via blitFramebuffer immediately before the first buffer swap.
96948
97484
  *
96949
97485
  * @private
96950
- * @return {DepthTexture} The depth texture.
97486
+ * @return {DepthTexture} The stable depth texture distributed to passes.
96951
97487
  */
96952
97488
  createDepthTexture() {
96953
- const depthTexture = this.depthTexture = new DepthTexture();
96954
- this.inputBuffer.depthTexture = depthTexture;
96955
- this.inputBuffer.dispose();
96956
- if (this.inputBuffer.stencilBuffer) {
97489
+ const inputBuffer = this.inputBuffer;
97490
+ const depthTexture = new DepthTexture();
97491
+ this.depthTexture = depthTexture;
97492
+ if (inputBuffer.stencilBuffer) {
96957
97493
  depthTexture.format = DepthStencilFormat;
96958
97494
  depthTexture.type = UnsignedInt248Type;
96959
97495
  } else {
96960
- depthTexture.type = UnsignedIntType;
96961
- }
96962
- return depthTexture;
97496
+ depthTexture.type = FloatType;
97497
+ }
97498
+ const stableDepthTexture = depthTexture.clone();
97499
+ stableDepthTexture.name = "EffectComposer.StableDepth";
97500
+ this.depthRenderTarget = new WebGLRenderTarget(inputBuffer.width, inputBuffer.height, {
97501
+ depthBuffer: true,
97502
+ stencilBuffer: inputBuffer.stencilBuffer,
97503
+ depthTexture: stableDepthTexture
97504
+ });
97505
+ return stableDepthTexture;
97506
+ }
97507
+ /**
97508
+ * Copies the depth buffer from the src render target into the stable depth target.
97509
+ *
97510
+ * @private
97511
+ * @param {WebGLRenderTarget} renderTarget - The render target whose depth buffer should be copied.
97512
+ */
97513
+ blitDepthBuffer(renderTarget) {
97514
+ const renderer = this.renderer;
97515
+ const depthRenderTarget = this.depthRenderTarget;
97516
+ const props = renderer.properties;
97517
+ const gl = renderer.getContext();
97518
+ renderer.setRenderTarget(depthRenderTarget);
97519
+ const srcFBO = props.get(renderTarget).__webglFramebuffer;
97520
+ const dstFBO = props.get(depthRenderTarget).__webglFramebuffer;
97521
+ const blitMask = renderTarget.stencilBuffer ? gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT : gl.DEPTH_BUFFER_BIT;
97522
+ gl.bindFramebuffer(gl.READ_FRAMEBUFFER, srcFBO);
97523
+ gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, dstFBO);
97524
+ gl.blitFramebuffer(
97525
+ 0,
97526
+ 0,
97527
+ renderTarget.width,
97528
+ renderTarget.height,
97529
+ 0,
97530
+ 0,
97531
+ depthRenderTarget.width,
97532
+ depthRenderTarget.height,
97533
+ blitMask,
97534
+ gl.NEAREST
97535
+ );
97536
+ gl.bindFramebuffer(gl.READ_FRAMEBUFFER, null);
97537
+ gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, null);
97538
+ renderer.setRenderTarget(null);
96963
97539
  }
96964
97540
  /**
96965
97541
  * Deletes the current depth texture.
@@ -96970,8 +97546,10 @@ var EffectComposer = class {
96970
97546
  if (this.depthTexture !== null) {
96971
97547
  this.depthTexture.dispose();
96972
97548
  this.depthTexture = null;
97549
+ this.depthRenderTarget.dispose();
97550
+ this.depthRenderTarget = null;
96973
97551
  this.inputBuffer.depthTexture = null;
96974
- this.inputBuffer.dispose();
97552
+ this.outputBuffer.depthTexture = null;
96975
97553
  for (const pass of this.passes) {
96976
97554
  pass.setDepthTexture(null);
96977
97555
  }
@@ -96980,7 +97558,7 @@ var EffectComposer = class {
96980
97558
  /**
96981
97559
  * Creates a new render target.
96982
97560
  *
96983
- * @deprecated Create buffers manually via WebGLRenderTarget instead.
97561
+ * @private
96984
97562
  * @param {Boolean} depthBuffer - Whether the render target should have a depth buffer.
96985
97563
  * @param {Boolean} stencilBuffer - Whether the render target should have a stencil buffer.
96986
97564
  * @param {Number} type - The frame buffer type.
@@ -97040,7 +97618,7 @@ var EffectComposer = class {
97040
97618
  const drawingBufferSize = renderer.getDrawingBufferSize(new Vector2());
97041
97619
  const alpha = renderer.getContext().getContextAttributes().alpha;
97042
97620
  const frameBufferType = this.inputBuffer.texture.type;
97043
- pass.setRenderer(renderer);
97621
+ pass.renderer = renderer;
97044
97622
  pass.setSize(drawingBufferSize.width, drawingBufferSize.height);
97045
97623
  pass.initialize(renderer, alpha, frameBufferType);
97046
97624
  if (this.autoRenderToScreen) {
@@ -97061,12 +97639,13 @@ var EffectComposer = class {
97061
97639
  }
97062
97640
  if (pass.needsDepthTexture || this.depthTexture !== null) {
97063
97641
  if (this.depthTexture === null) {
97064
- const depthTexture = this.createDepthTexture();
97642
+ const stableDepthTexture = this.createDepthTexture();
97065
97643
  for (pass of passes) {
97066
- pass.setDepthTexture(depthTexture);
97644
+ pass.setDepthTexture(stableDepthTexture);
97067
97645
  }
97068
97646
  } else {
97069
- pass.setDepthTexture(this.depthTexture);
97647
+ const stableDepthTexture = this.depthRenderTarget.depthTexture;
97648
+ pass.setDepthTexture(stableDepthTexture);
97070
97649
  }
97071
97650
  }
97072
97651
  }
@@ -97085,7 +97664,8 @@ var EffectComposer = class {
97085
97664
  const reducer = (a, b) => a || b.needsDepthTexture;
97086
97665
  const depthTextureRequired = passes.reduce(reducer, false);
97087
97666
  if (!depthTextureRequired) {
97088
- if (pass.getDepthTexture() === this.depthTexture) {
97667
+ const stableDepthTexture = this.depthRenderTarget.depthTexture;
97668
+ if (pass.getDepthTexture() === stableDepthTexture) {
97089
97669
  pass.setDepthTexture(null);
97090
97670
  }
97091
97671
  this.deleteDepthTexture();
@@ -97124,34 +97704,42 @@ var EffectComposer = class {
97124
97704
  const copyPass = this.copyPass;
97125
97705
  let inputBuffer = this.inputBuffer;
97126
97706
  let outputBuffer = this.outputBuffer;
97707
+ let buffer;
97127
97708
  let stencilTest = false;
97128
- let context, stencil, buffer;
97129
97709
  if (deltaTime === void 0) {
97130
97710
  this.timer.update();
97131
97711
  deltaTime = this.timer.getDelta();
97132
97712
  }
97133
97713
  for (const pass of this.passes) {
97134
- if (pass.enabled) {
97135
- pass.render(renderer, inputBuffer, outputBuffer, deltaTime, stencilTest);
97136
- if (pass.needsSwap) {
97137
- if (stencilTest) {
97138
- copyPass.renderToScreen = pass.renderToScreen;
97139
- context = renderer.getContext();
97140
- stencil = renderer.state.buffers.stencil;
97141
- stencil.setFunc(context.NOTEQUAL, 1, 4294967295);
97142
- copyPass.render(renderer, inputBuffer, outputBuffer, deltaTime, stencilTest);
97143
- stencil.setFunc(context.EQUAL, 1, 4294967295);
97144
- }
97145
- buffer = inputBuffer;
97146
- inputBuffer = outputBuffer;
97147
- outputBuffer = buffer;
97148
- }
97149
- if (pass instanceof MaskPass) {
97150
- stencilTest = true;
97151
- } else if (pass instanceof ClearMaskPass) {
97152
- stencilTest = false;
97714
+ if (!pass.enabled) {
97715
+ continue;
97716
+ }
97717
+ inputBuffer.depthTexture = this.depthTexture;
97718
+ outputBuffer.depthTexture = null;
97719
+ pass.render(renderer, inputBuffer, outputBuffer, deltaTime, stencilTest);
97720
+ if (pass.needsDepthBlit) {
97721
+ if (this.depthRenderTarget !== null) {
97722
+ this.blitDepthBuffer(inputBuffer);
97153
97723
  }
97154
97724
  }
97725
+ if (pass.needsSwap) {
97726
+ if (stencilTest) {
97727
+ copyPass.renderToScreen = pass.renderToScreen;
97728
+ const context = renderer.getContext();
97729
+ const stencil = renderer.state.buffers.stencil;
97730
+ stencil.setFunc(context.NOTEQUAL, 1, 4294967295);
97731
+ copyPass.render(renderer, inputBuffer, outputBuffer, deltaTime, stencilTest);
97732
+ stencil.setFunc(context.EQUAL, 1, 4294967295);
97733
+ }
97734
+ buffer = inputBuffer;
97735
+ inputBuffer = outputBuffer;
97736
+ outputBuffer = buffer;
97737
+ }
97738
+ if (pass instanceof MaskPass) {
97739
+ stencilTest = true;
97740
+ } else if (pass instanceof ClearMaskPass) {
97741
+ stencilTest = false;
97742
+ }
97155
97743
  }
97156
97744
  }
97157
97745
  /**
@@ -97174,6 +97762,9 @@ var EffectComposer = class {
97174
97762
  const drawingBufferSize = renderer.getDrawingBufferSize(new Vector2());
97175
97763
  this.inputBuffer.setSize(drawingBufferSize.width, drawingBufferSize.height);
97176
97764
  this.outputBuffer.setSize(drawingBufferSize.width, drawingBufferSize.height);
97765
+ if (this.depthRenderTarget !== null) {
97766
+ this.depthRenderTarget.setSize(drawingBufferSize.width, drawingBufferSize.height);
97767
+ }
97177
97768
  for (const pass of this.passes) {
97178
97769
  pass.setSize(drawingBufferSize.width, drawingBufferSize.height);
97179
97770
  }
@@ -99100,6 +99691,7 @@ var RenderPass = class extends Pass {
99100
99691
  constructor(scene, camera, overrideMaterial = null) {
99101
99692
  super("RenderPass", scene, camera);
99102
99693
  this.needsSwap = false;
99694
+ this.needsDepthBlit = true;
99103
99695
  this.clearPass = new ClearPass();
99104
99696
  this.overrideMaterialManager = overrideMaterial === null ? null : new OverrideMaterialManager(overrideMaterial);
99105
99697
  this.ignoreBackground = false;
@@ -104411,7 +105003,18 @@ class StudioManager {
104411
105003
  }
104412
105004
  // 3. Load environment map
104413
105005
  const envName = state.get("studioEnvironment");
104414
- await this.envManager.loadEnvironment(envName, renderer);
105006
+ // Sync envManager's 4K setting with state. updateStudioState() writes
105007
+ // studio4kEnvMaps silently (notify=false), so the subscription that
105008
+ // normally forwards this to envManager never fires on initial load.
105009
+ // Without this sync, envManager keeps its default (2K) and loads the
105010
+ // wrong URL even though the checkbox reads "checked".
105011
+ const want4k = state.get("studio4kEnvMaps");
105012
+ if (want4k !== this.envManager.use4kEnvMaps) {
105013
+ await this.envManager.setUse4kEnvMaps(want4k, envName, renderer);
105014
+ }
105015
+ else {
105016
+ await this.envManager.loadEnvironment(envName, renderer);
105017
+ }
104415
105018
  if (!this._active)
104416
105019
  return;
104417
105020
  // 4. Apply ALL rendering changes atomically
@@ -104822,8 +105425,13 @@ class StudioManager {
104822
105425
  const nestedGroup = this._ctx.getNestedGroup();
104823
105426
  if (enabled) {
104824
105427
  this._configureShadowLights();
105428
+ // Back-face meshes share geometry with front meshes but use a
105429
+ // MeshBasicMaterial without alphaMap/alphaTest, so letting them cast
105430
+ // shadows overrides the front mesh's alpha-tested silhouette with a
105431
+ // solid one. The front material is DoubleSide when alphaMap is set,
105432
+ // so its shadow pass already covers both sides of the geometry.
104825
105433
  nestedGroup.rootGroup?.traverse((obj) => {
104826
- if (obj instanceof Mesh) {
105434
+ if (obj instanceof Mesh && obj.material.name !== "backMaterial") {
104827
105435
  obj.castShadow = true;
104828
105436
  }
104829
105437
  });
@@ -107048,6 +107656,11 @@ class Viewer {
107048
107656
  // leaveStudioMode() runs here, while _rendered and scene are still valid.
107049
107657
  // Do NOT move this after deepDispose(scene).
107050
107658
  this.state.set("activeTab", "tree");
107659
+ // Outer-cycle boundary: drop Material Editor deltas that were just
107660
+ // saved by the switchToTab("tree", "studio") path above. Those deltas
107661
+ // are meant to survive mid-cycle tab switches within one scene, not a
107662
+ // full scene re-render. See Display.clearMaterialEditorSession.
107663
+ this.display.clearMaterialEditorSession();
107051
107664
  // clear render canvas
107052
107665
  this.renderer.clear();
107053
107666
  // deselect measurement tools
@@ -108586,6 +109199,15 @@ class Viewer {
108586
109199
  if (flag === isExplodeActive)
108587
109200
  return;
108588
109201
  if (flag) {
109202
+ // Mirror the UI button-group exclusivity: activating explode must
109203
+ // deactivate any active measurement/selection tool. activateTool()
109204
+ // already clears animationMode in the reverse direction; this makes
109205
+ // the API path symmetric with a UI click. Goes through display.setTool
109206
+ // so cadTools/raycaster/picker get fully cleaned up.
109207
+ const currentTool = this.state.get("activeTool");
109208
+ if (currentTool) {
109209
+ this.display.setTool(currentTool, false);
109210
+ }
108589
109211
  if (this.hasAnimation()) {
108590
109212
  this.backupAnimation();
108591
109213
  }
@@ -108614,12 +109236,19 @@ class Viewer {
108614
109236
  activateTool(name, flag) {
108615
109237
  const currentTool = this.state.get("activeTool");
108616
109238
  if (flag) {
108617
- // Activating a tool
109239
+ // Activating a tool implicitly turns off explode (animationMode → "none").
109240
+ // Emit the explode=false notification so consumers don't keep a stale
109241
+ // explode=true in their reported state — otherwise the next render that
109242
+ // echoes back combined_config will set explode back on.
109243
+ const wasExplode = this.state.get("animationMode") === "explode";
108618
109244
  this.state.set("animationMode", "none");
108619
109245
  if (this.hasAnimation()) {
108620
109246
  this.backupAnimation();
108621
109247
  }
108622
109248
  this.state.set("activeTool", name);
109249
+ if (wasExplode) {
109250
+ this.checkChanges({ explode: false });
109251
+ }
108623
109252
  }
108624
109253
  else {
108625
109254
  // Deactivating a tool
@@ -111280,6 +111909,17 @@ class Display {
111280
111909
  }
111281
111910
  this._matEditorClones.clear();
111282
111911
  }
111912
+ /**
111913
+ * Outer-cycle boundary: discard saved Material Editor deltas so they don't
111914
+ * replay on the next Studio entry in a new scene. Unlike viewer preferences
111915
+ * (transparent, axes, grid) which persist across render cycles, Material
111916
+ * Editor edits are per-scene PBR authoring and must reset on scene rebuild.
111917
+ * Mid-cycle (Studio tab leave/enter) and inner-cycle (editor close/reopen)
111918
+ * behavior is unaffected — this is only called from viewer.clear().
111919
+ */
111920
+ clearMaterialEditorSession() {
111921
+ this._savedMatEditorChanges.clear();
111922
+ }
111283
111923
  /** Save material editor property deltas so they survive a Studio mode leave/enter cycle. */
111284
111924
  _saveMatEditorChanges() {
111285
111925
  this._savedMatEditorChanges.clear();