Explorar o código

Merge remote-tracking branch 'upstream/dev' into dev51

Mugen87 %!s(int64=5) %!d(string=hai) anos
pai
achega
477c924d7b
Modificáronse 55 ficheiros con 690 adicións e 409 borrados
  1. 48 17
      build/three.js
  2. 176 175
      build/three.min.js
  3. 31 22
      build/three.module.js
  4. 1 1
      docs/api/en/cameras/OrthographicCamera.html
  5. 1 1
      docs/api/en/cameras/PerspectiveCamera.html
  6. 4 4
      docs/api/en/core/Geometry.html
  7. 45 0
      docs/api/en/lights/AmbientLightProbe.html
  8. 4 0
      docs/api/en/lights/shadows/LightShadow.html
  9. 30 0
      docs/api/en/materials/Material.html
  10. 19 19
      docs/api/en/math/Box3.html
  11. 7 1
      docs/api/en/textures/DataTexture2DArray.html
  12. 1 2
      docs/api/en/textures/DataTexture3D.html
  13. 1 1
      docs/api/zh/cameras/OrthographicCamera.html
  14. 1 1
      docs/api/zh/cameras/PerspectiveCamera.html
  15. 45 0
      docs/api/zh/lights/AmbientLightProbe.html
  16. 4 0
      docs/api/zh/lights/shadows/LightShadow.html
  17. 5 1
      docs/api/zh/textures/DataTexture2DArray.html
  18. 1 2
      docs/api/zh/textures/DataTexture3D.html
  19. 2 1
      docs/examples/en/controls/OrbitControls.html
  20. 4 1
      docs/examples/zh/controls/OrbitControls.html
  21. 2 0
      docs/list.js
  22. 35 17
      editor/js/Sidebar.Object.js
  23. 2 0
      editor/js/Sidebar.Scene.js
  24. 13 6
      editor/js/Strings.js
  25. 3 1
      examples/js/controls/OrbitControls.js
  26. 1 8
      examples/js/objects/Reflector.js
  27. 1 8
      examples/js/objects/Refractor.js
  28. 2 0
      examples/js/objects/Water.js
  29. 3 1
      examples/jsm/controls/OrbitControls.js
  30. 1 1
      examples/jsm/math/MeshSurfaceSampler.js
  31. 1 9
      examples/jsm/objects/Reflector.js
  32. 1 9
      examples/jsm/objects/Refractor.js
  33. 2 0
      examples/jsm/objects/Water.js
  34. 2 2
      examples/jsm/webxr/XRControllerModelFactory.js
  35. BIN=BIN
      examples/screenshots/webgl_materials_modified.jpg
  36. 61 32
      examples/webgl_materials_modified.html
  37. 1 0
      src/lights/LightShadow.d.ts
  38. 2 0
      src/lights/LightShadow.js
  39. 1 0
      src/loaders/ObjectLoader.js
  40. 5 0
      src/materials/Material.d.ts
  41. 6 0
      src/materials/Material.js
  42. 5 5
      src/math/Euler.js
  43. 5 5
      src/math/Quaternion.js
  44. 3 3
      src/math/Vector2.js
  45. 4 4
      src/math/Vector3.js
  46. 5 5
      src/math/Vector4.js
  47. 0 39
      src/renderers/shaders/ShaderChunk/lights_pars_begin.glsl.js
  48. 29 0
      src/renderers/shaders/ShaderChunk/shadowmap_pars_fragment.glsl.js
  49. 29 0
      src/renderers/shaders/ShaderChunk/shadowmap_pars_vertex.glsl.js
  50. 14 3
      src/renderers/shaders/ShaderChunk/shadowmap_vertex.glsl.js
  51. 7 0
      src/renderers/shaders/ShaderLib/shadow_vert.glsl.js
  52. 3 0
      src/renderers/shaders/UniformsLib.d.ts
  53. 3 0
      src/renderers/shaders/UniformsLib.js
  54. 6 0
      src/renderers/webgl/WebGLLights.js
  55. 2 2
      src/renderers/webgl/WebGLPrograms.js

A diferenza do arquivo foi suprimida porque é demasiado grande
+ 48 - 17
build/three.js


A diferenza do arquivo foi suprimida porque é demasiado grande
+ 176 - 175
build/three.min.js


A diferenza do arquivo foi suprimida porque é demasiado grande
+ 31 - 22
build/three.module.js


+ 1 - 1
docs/api/en/cameras/OrthographicCamera.html

@@ -72,7 +72,7 @@
 		<p>
 		Camera frustum far plane. Default is *2000*.<br /><br />
 
-		The valid range is between the current value of the [page:.near near] plane and infinity.
+		Must be greater than the current value of [page:.near near] plane.
 		</p>
 
 		<h3>[property:Float left]</h3>

+ 1 - 1
docs/api/en/cameras/PerspectiveCamera.html

@@ -63,7 +63,7 @@
 		<p>
 			Camera frustum far plane. Default is *2000*.<br /><br />
 
-			The valid range is between the current value of the [page:.near near] plane and infinity.
+			Must be greater than the current value of [page:.near near] plane.
 		</p>
 
 		<h3>[property:Float filmGauge]</h3>

+ 4 - 4
docs/api/en/core/Geometry.html

@@ -134,8 +134,8 @@
 		</p>
 		<p>
 		The values of the vector should typically be between 0 and 1. For instance when set to 0 the bone
-		transformation will have no affect. When set to 0.5 it will have 50% affect. When set to 100%, it will
-		have 100% affect. If there is only 1 bone associated with the vertex then you only need to worry about
+		transformation will have no effect. When set to 0.5 it will have 50% effect. When set to 100%, it will
+		have 100% effect. If there is only 1 bone associated with the vertex then you only need to worry about
 		the first component of the vector, the rest can be ignored and set to 0.
 		</p>
 
@@ -146,9 +146,9 @@
 		first skinIndex, this will tell you the bones associated with that vertex. For example the first vertex
 		could have a value of <strong>( 10.05, 30.10, 12.12 )</strong>. Then the first skin index could have the
 		value of <strong>( 10, 2, 0, 0 )</strong>. The first skin weight could have the value of
-		<strong>( 0.8, 0.2, 0, 0 )</strong>. In affect this would take the first vertex, and then the bone
+		<strong>( 0.8, 0.2, 0, 0 )</strong>. In effect this would take the first vertex, and then the bone
 		<strong>mesh.bones[10]</strong> and apply it 80% of the way. Then it would take the bone <strong>skeleton.bones[2]</strong>
-		and apply it 20% of the way. The next two values have a weight of 0, so they would have no affect.
+		and apply it 20% of the way. The next two values have a weight of 0, so they would have no effect.
 		</p>
 		<p>
 		In code another example could look like this:

+ 45 - 0
docs/api/en/lights/AmbientLightProbe.html

@@ -0,0 +1,45 @@
+<!DOCTYPE html>
+<html lang="en">
+	<head>
+		<meta charset="utf-8" />
+		<base href="../../../" />
+		<script src="list.js"></script>
+		<script src="page.js"></script>
+		<link type="text/css" rel="stylesheet" href="page.css" />
+	</head>
+	<body>
+		[page:Object3D] &rarr; [page:Light] &rarr; [page:LightProbe]
+
+		<h1>[name]</h1>
+
+		<p class="desc">
+			Light probes are an alternative way of adding light to a 3D scene. AmbientLightProbe is the light estimation data 
+			of a single ambient light in the scene. For more information about light probes, go to [page:LightProbe].
+		</p>
+
+		<h2>Constructor</h2>
+
+		<h3>[name]( [param:Color color], [param:Float intensity] )</h3>
+		<p>
+		[page:Color color] - (optional) An instance of Color, string representing a color or a number representing a color.<br />
+		[page:Float intensity] - (optional) Numeric value of the light probe's intensity. Default is 1.<br /><br />
+
+		Creates a new [name].
+		</p>
+
+		<h2>Properties</h2>
+		<p>
+				See the base [page:LightProbe LightProbe] class for common properties.
+		</p>
+
+		<h2>Methods</h2>
+		<p>
+				See the base [page:LightProbe LightProbe] class for common methods.
+		</p>
+		<h2>Source</h2>
+
+		<p>
+			[link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js]
+		</p>
+	</body>
+</html>

+ 4 - 0
docs/api/en/lights/shadows/LightShadow.html

@@ -40,6 +40,10 @@
 			The default is 0. Very tiny adjustments here (in the order of 0.0001) may help reduce artefacts in shadows
 		</p>
 
+		<h3>[property:Float normalOffset]</h3>
+		<p>Defines how much the position used to query the shadow map is offset along the object normal.</p>
+		<p>The default is 0. Increasing this value can be used to reduce shadow acne especially in large scenes where light shines onto geometry at a shallow angle. The cost is that shadows may appear distorted.</p>
+
 		<h3>[property:WebGLRenderTarget map]</h3>
 		<p>
 			The depth map generated using the internal camera; a location beyond a pixel's depth is

+ 30 - 0
docs/api/en/materials/Material.html

@@ -334,6 +334,36 @@
 		Unlike properties, the callback is not supported by [page:Material.clone .clone](), [page:Material.copy .copy]() and [page:Material.toJSON .toJSON]().
 		</p>
 
+		<h3>[method:String customProgramCacheKey]()</h3>
+		<p>
+		In case onBeforeCompile is used, this callback can be used to identify values of settings used in onBeforeCompile, so three.js can reuse a cached shader or recompile the shader for this material as needed.
+		</p>
+
+		<p>
+		For example, if onBeforeCompile contains a conditional statement like:<br />
+
+		<code>if ( black ) {
+
+			shader.fragmentShader = shader.fragmentShader.replace('gl_FragColor = vec4(1)', 'gl_FragColor = vec4(0)')
+
+		}
+		</code>
+
+		then customProgramCacheKey should be set like this:<br />
+
+		<code>material.customProgramCacheKey = function() {
+
+			return black ? '1' : '0';
+
+		}
+		</code>
+
+		</p>
+
+		<p>
+		Unlike properties, the callback is not supported by [page:Material.clone .clone](), [page:Material.copy .copy]() and [page:Material.toJSON .toJSON]().
+		</p>
+
 		<h3>[method:null setValues]( [param:object values] )</h3>
 		<p>
 		values -- a container with parameters.<br />

+ 19 - 19
docs/api/en/math/Box3.html

@@ -66,7 +66,7 @@
 
 		<h2>Methods</h2>
 
-		<h3>[method:Box3 applyMatrix4]( [param:Matrix4 matrix] )</h3>
+		<h3>[method:this applyMatrix4]( [param:Matrix4 matrix] )</h3>
 		<p>
 		[page:Matrix4 matrix] - The [page:Matrix4] to apply<br /><br />
 
@@ -99,7 +99,7 @@
 		Returns true if the specified [page:Vector3 point] lies within or on the boundaries of this box.
 		</p>
 
-		<h3>[method:Box3 copy]( [param:Box3 box] )</h3>
+		<h3>[method:this copy]( [param:Box3 box] )</h3>
 		<p>
 		[page:Box3 box]  - [page:Box3] to copy.<br /><br />
 
@@ -122,7 +122,7 @@
 		Returns true if this box and [page:Box3 box] share the same lower and upper bounds.
 		</p>
 
-		<h3>[method:Box3 expandByObject]( [param:Object3D object] )</h3>
+		<h3>[method:this expandByObject]( [param:Object3D object] )</h3>
 		<p>
 		[page:Object3D object] - [page:Object3D] to expand the box by.<br /><br />
 
@@ -132,14 +132,14 @@
 
 		</p>
 
-		<h3>[method:Box3 expandByPoint]( [param:Vector3 point] )</h3>
+		<h3>[method:this expandByPoint]( [param:Vector3 point] )</h3>
 		<p>
 		[page:Vector3 point] - [page:Vector3] that should be included in the box.<br /><br />
 
 		Expands the boundaries of this box to include [page:Vector3 point].
 		</p>
 
-		<h3>[method:Box3 expandByScalar]( [param:float scalar] )</h3>
+		<h3>[method:this expandByScalar]( [param:float scalar] )</h3>
 		<p>
 		[page:float scalar] - Distance to expand the box by.<br /><br />
 
@@ -147,7 +147,7 @@
 		will be contracted.
 		</p>
 
-		<h3>[method:Box3 expandByVector]( [param:Vector3 vector] )</h3>
+		<h3>[method:this expandByVector]( [param:Vector3 vector] )</h3>
 		<p>
 		[page:Vector3 vector] - [page:Vector3] to expand the box by.<br /><br />
 
@@ -186,13 +186,13 @@
 		Returns the width, height and depth of this box.
 		</p>
 
-		<h3>[method:Box3 intersect]( [param:Box3 box] )</h3>
+		<h3>[method:this intersect]( [param:Box3 box] )</h3>
 		<p>
 		[page:Box3 box] - Box to intersect with.<br /><br />
 
-		Returns the intersection of this and [page:Box3 box], setting the upper bound of this box to the lesser
+		Computes the intersection of this and [page:Box3 box], setting the upper bound of this box to the lesser
 		of the two boxes' upper bounds and the lower bound of this box to the greater of the two boxes'
-		lower bounds.
+		lower bounds. If there's no overlap, makes this box empty.
 		</p>
 
 		<h3>[method:Boolean intersectsBox]( [param:Box3 box] )</h3>
@@ -230,10 +230,10 @@
 		the one both bounds share.
 		</p>
 
-		<h3>[method:Box3 makeEmpty]()</h3>
+		<h3>[method:this makeEmpty]()</h3>
 		<p>Makes this box empty.</p>
 
-		<h3>[method:Box3 set]( [param:Vector3 min], [param:Vector3 max] )</h3>
+		<h3>[method:this set]( [param:Vector3 min], [param:Vector3 max] )</h3>
 		<p>
 		[page:Vector3 min] - [page:Vector3] representing the lower (x, y, z) boundary of the box.<br />
 		[page:Vector3 max] - [page:Vector3] representing the lower upper (x, y, z) boundary of the box.<br /><br />
@@ -242,21 +242,21 @@
 		Please note that this method only copies the values from the given objects.
 		</p>
 
-		<h3>[method:Box3 setFromArray]( [param:Array array] ) [param:Box3 this]</h3>
+		<h3>[method:this setFromArray]( [param:Array array] )</h3>
 		<p>
 		array -- An array of position data that the resulting box will envelop.<br /><br />
 
 		Sets the upper and lower bounds of this box to include all of the data in *array*.
 		</p>
 
-		<h3>[method:Box3 setFromBufferAttribute]( [param:BufferAttribute attribute] ) [param:Box3 this]</h3>
+		<h3>[method:this setFromBufferAttribute]( [param:BufferAttribute attribute] )</h3>
 		<p>
 		[page:BufferAttribute attribute] - A buffer attribute of position data that the resulting box will envelop.<br /><br />
 
 		Sets the upper and lower bounds of this box to include all of the data in [page:BufferAttribute attribute].
 		</p>
 
-		<h3>[method:Box3 setFromCenterAndSize]( [param:Vector3 center], [param:Vector3 size] ) [param:Box3 this]</h3>
+		<h3>[method:this setFromCenterAndSize]( [param:Vector3 center], [param:Vector3 size] )</h3>
 		<p>
 		[page:Vector3 center], - Desired center position of the box. <br>
 		[page:Vector3 size] - Desired x, y and z dimensions of the box.<br /><br />
@@ -265,7 +265,7 @@
 		in [page:Vector3 size]
 		</p>
 
-		<h3>[method:Box3 setFromObject]( [param:Object3D object] )</h3>
+		<h3>[method:this setFromObject]( [param:Object3D object] )</h3>
 		<p>
 		[page:Object3D object] - [page:Object3D] to compute the bounding box of.<br /><br />
 
@@ -275,14 +275,14 @@
 
 		</p>
 
-		<h3>[method:Box3 setFromPoints]( [param:Array points] )</h3>
+		<h3>[method:this setFromPoints]( [param:Array points] )</h3>
 		<p>
 		[page:Array points] - Array of [page:Vector3 Vector3s] that the resulting box will contain.<br /><br />
 
 		Sets the upper and lower bounds of this box to include all of the points in [page:Array points].
 		</p>
 
-		<h3>[method:Box3 translate]( [param:Vector3 offset] )</h3>
+		<h3>[method:this translate]( [param:Vector3 offset] )</h3>
 		<p>
 		[page:Vector3 offset] - Direction and distance of offset.<br /><br />
 
@@ -290,11 +290,11 @@
 		[page:Vector3 offset] units in 3D space.
 		</p>
 
-		<h3>[method:Box3 union]( [param:Box3 box] )</h3>
+		<h3>[method:this union]( [param:Box3 box] )</h3>
 		<p>
 		[page:Box3 box] - Box that will be unioned with this box.<br /><br />
 
-		Unions this box with [page:Box3 box], setting the upper bound of this box to the greater of the
+		Computes the union of this box and [page:Box3 box], setting the upper bound of this box to the greater of the
 		two boxes' upper bounds and the lower bound of this box to the lesser of the two boxes'
 		lower bounds.
 		</p>

+ 7 - 1
docs/api/en/textures/DataTexture2DArray.html

@@ -12,7 +12,7 @@
 
 		<h1>[name]</h1>
 
-		<p class="desc">Creates an array of textures directly from raw data, width and height and depth.</p>
+		<p class="desc">Creates an array of textures directly from raw data, width and height and depth. This type of texture can only be used with a WebGL 2 rendering context.</p>
 
 
 		<h2>Constructor</h2>
@@ -68,6 +68,12 @@
 		texture.type = THREE.UnsignedByteType;
 		</code>
 
+		<h2>Examples</h2>
+
+		<p>
+			[example:webgl2_materials_texture2darray WebGL2 / materials / texture2darray]
+		</p>
+
 		<h2>Properties</h2>
 
 		<p>

+ 1 - 2
docs/api/en/textures/DataTexture3D.html

@@ -30,8 +30,7 @@
 		<h2>Examples</h2>
 
 		<p>
-			[example:webgl2_materials_texture3d WebGL2 / materials / texture3d]<br />
-			[example:webgl2_materials_texture2darray WebGL2 / materials / texture2darray]
+			[example:webgl2_materials_texture3d WebGL2 / materials / texture3d]
 		</p>
 
 		<h2>Properties</h2>

+ 1 - 1
docs/api/zh/cameras/OrthographicCamera.html

@@ -75,7 +75,7 @@
 		<h3>[property:Float far]</h3>
 		<p>
 			摄像机视锥体远端面,其默认值为*2000*。<br /><br />
-			其值的有效范围介于[page:.near near](摄像机视锥体近端面)和无穷大之间。
+			Must be greater than the current value of [page:.near near] plane.
 
 		</p>
 

+ 1 - 1
docs/api/zh/cameras/PerspectiveCamera.html

@@ -62,7 +62,7 @@
 		<p>
 			摄像机的远端面,默认值是*2000*。
 			<br /><br />
-			其有效值范围是在当前摄像机[page:.near near] plane(近端面)的值到无穷远之间。
+			Must be greater than the current value of [page:.near near] plane.
 		</p>
 
 		<h3>[property:Float filmGauge]</h3>

+ 45 - 0
docs/api/zh/lights/AmbientLightProbe.html

@@ -0,0 +1,45 @@
+<!DOCTYPE html>
+<html lang="zh">
+	<head>
+		<meta charset="utf-8" />
+		<base href="../../../" />
+		<script src="list.js"></script>
+		<script src="page.js"></script>
+		<link type="text/css" rel="stylesheet" href="page.css" />
+	</head>
+	<body>
+		[page:Object3D] &rarr; [page:Light] &rarr; [page:LightProbe]
+
+		<h1>[name]</h1>
+
+		<p class="desc">
+			Light probes are an alternative way of adding light to a 3D scene. AmbientLightProbe is the light estimation data 
+			of a single ambient light in the scene. For more information about light probes, go to [page:LightProbe].
+		</p>
+
+		<h2>Constructor</h2>
+
+		<h3>[name]( [param:Color color], [param:Float intensity] )</h3>
+		<p>
+		[page:Color color] - (optional) An instance of Color, string representing a color or a number representing a color.<br />
+		[page:Float intensity] - (optional) Numeric value of the light probe's intensity. Default is 1.<br /><br />
+
+		Creates a new [name].
+		</p>
+
+		<h2>Properties</h2>
+		<p>
+				See the base [page:LightProbe LightProbe] class for common properties.
+		</p>
+
+		<h2>Methods</h2>
+		<p>
+				See the base [page:LightProbe LightProbe] class for common methods.
+		</p>
+		<h2>Source</h2>
+
+		<p>
+			[link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js]
+		</p>
+	</body>
+</html>

+ 4 - 0
docs/api/zh/lights/shadows/LightShadow.html

@@ -38,6 +38,10 @@
 			默认值为0.此处非常小的调整(大约0.0001)可能有助于减少阴影中的伪影
 		</p>
 
+		<h3>[property:Float normalOffset]</h3>
+		<p>Defines how much the position used to query the shadow map is offset along the object normal.</p>
+		<p>The default is 0. Increasing this value can be used to reduce shadow acne especially in large scenes where light shines onto geometry at a shallow angle. The cost is that shadows may appear distorted.</p>
+
 		<h3>[property:WebGLRenderTarget map]</h3>
 		<p>
 			使用内置摄像头生成的深度图;超出像素深度的位置在阴影中。在渲染期间内部计算。

+ 5 - 1
docs/api/zh/textures/DataTexture2DArray.html

@@ -12,7 +12,7 @@
 
 		<h1>[name]</h1>
 
-		<p class="desc">Creates an array of textures directly from raw data, width and height and depth.</p>
+		<p class="desc">Creates an array of textures directly from raw data, width and height and depth. This type of texture can only be used with a WebGL 2 rendering context.</p>
 
 
 		<h2>Constructor</h2>
@@ -68,6 +68,10 @@
 		texture.type = THREE.UnsignedByteType;
 		</code>
 
+		<p>
+			[example:webgl2_materials_texture3d WebGL2 / materials / texture3d]
+		</p>
+
 		<h2>Properties</h2>
 
 		<p>

+ 1 - 2
docs/api/zh/textures/DataTexture3D.html

@@ -30,8 +30,7 @@
 		<h2>例子</h2>
 
 		<p>
-			[example:webgl2_materials_texture3d WebGL2 / materials / texture3d]<br />
-			[example:webgl2_materials_texture2darray WebGL2 / materials / texture2darray]
+			[example:webgl2_materials_texture3d WebGL2 / materials / texture3d]
 		</p>
 
 		<h2>属性</h2>

+ 2 - 1
docs/examples/en/controls/OrbitControls.html

@@ -236,7 +236,8 @@ controls.mouseButtons = {
 		<h3>[property:Boolean screenSpacePanning]</h3>
 		<p>
 		Defines how the camera's position is translated when panning. If true, the camera pans in screen space.
-		Otherwise, the camera pans in the plane orthogonal to the camera's up direction. Default is false.
+		Otherwise, the camera pans in the plane orthogonal to the camera's up direction.
+		Default is true for OrbitControls; false for MapControls.
 		</p>
 
 		<h3>[property:Vector3 target0]</h3>

+ 4 - 1
docs/examples/zh/controls/OrbitControls.html

@@ -234,7 +234,10 @@ controls.mouseButtons = {
 		<h3>[property:Boolean screenSpacePanning]</h3>
 		<p>
 			定义当平移的时候摄像机的位置将如何移动。如果为true,摄像机将在屏幕空间内平移。
-			否则,摄像机将在与摄像机向上方向垂直的平面中平移。其默认值为false。
+			否则,摄像机将在与摄像机向上方向垂直的平面中平移。
+			Defines how the camera's position is translated when panning. If true, the camera pans in screen space.
+			Otherwise, the camera pans in the plane orthogonal to the camera's up direction.
+			Default is true for OrbitControls; false for MapControls.
 		</p>
 
 		<h3>[property:Vector3 target0]</h3>

+ 2 - 0
docs/list.js

@@ -201,6 +201,7 @@ var list = {
 
 			"Lights": {
 				"AmbientLight": "api/en/lights/AmbientLight",
+				"AmbientLightProbe": "api/en/lights/AmbientLightProbe",
 				"DirectionalLight": "api/en/lights/DirectionalLight",
 				"HemisphereLight": "api/en/lights/HemisphereLight",
 				"Light": "api/en/lights/Light",
@@ -660,6 +661,7 @@ var list = {
 
 			"灯光": {
 				"AmbientLight": "api/zh/lights/AmbientLight",
+				"AmbientLightProbe": "api/zh/lights/AmbientLightProbe",
 				"DirectionalLight": "api/zh/lights/DirectionalLight",
 				"HemisphereLight": "api/zh/lights/HemisphereLight",
 				"Light": "api/zh/lights/Light",

+ 35 - 17
editor/js/Sidebar.Object.js

@@ -302,17 +302,6 @@ function SidebarObject( editor ) {
 
 	container.add( objectShadowRow );
 
-	// shadow radius
-
-	var objectShadowRadiusRow = new UIRow();
-
-	objectShadowRadiusRow.add( new UIText( strings.getKey( 'sidebar/object/shadowRadius' ) ).setWidth( '90px' ) );
-
-	var objectShadowRadius = new UINumber( 1 ).onChange( update );
-	objectShadowRadiusRow.add( objectShadowRadius );
-
-	container.add( objectShadowRadiusRow );
-
 	// shadow bias
 
 	var objectShadowBiasRow = new UIRow();
@@ -324,6 +313,28 @@ function SidebarObject( editor ) {
 
 	container.add( objectShadowBiasRow );
 
+	// shadow normal offset
+
+	var objectShadowNormalOffsetRow = new UIRow();
+
+	objectShadowNormalOffsetRow.add( new UIText( strings.getKey( 'sidebar/object/shadowNormalOffset' ) ).setWidth( '90px' ) );
+
+	var objectShadowNormalOffset = new UINumber( 0 ).onChange( update );
+	objectShadowNormalOffsetRow.add( objectShadowNormalOffset );
+
+	container.add( objectShadowNormalOffsetRow );
+
+	// shadow radius
+
+	var objectShadowRadiusRow = new UIRow();
+
+	objectShadowRadiusRow.add( new UIText( strings.getKey( 'sidebar/object/shadowRadius' ) ).setWidth( '90px' ) );
+
+	var objectShadowRadius = new UINumber( 1 ).onChange( update );
+	objectShadowRadiusRow.add( objectShadowRadius );
+
+	container.add( objectShadowRadiusRow );
+
 	// visible
 
 	var objectVisibleRow = new UIRow();
@@ -594,15 +605,21 @@ function SidebarObject( editor ) {
 
 			if ( object.shadow !== undefined ) {
 
-				if ( object.shadow.radius !== objectShadowRadius.getValue() ) {
+				if ( object.shadow.bias !== objectShadowBias.getValue() ) {
 
-					editor.execute( new SetValueCommand( editor, object.shadow, 'radius', objectShadowRadius.getValue() ) );
+					editor.execute( new SetValueCommand( editor, object.shadow, 'bias', objectShadowBias.getValue() ) );
 
 				}
 
-				if ( object.shadow.bias !== objectShadowBias.getValue() ) {
+				if ( object.shadow.normalOffset !== objectShadowNormalOffset.getValue() ) {
 
-					editor.execute( new SetValueCommand( editor, object.shadow, 'bias', objectShadowBias.getValue() ) );
+					editor.execute( new SetValueCommand( editor, object.shadow, 'normalOffset', objectShadowNormalOffset.getValue() ) );
+
+				}
+
+				if ( object.shadow.radius !== objectShadowRadius.getValue() ) {
+
+					editor.execute( new SetValueCommand( editor, object.shadow, 'radius', objectShadowRadius.getValue() ) );
 
 				}
 
@@ -646,7 +663,7 @@ function SidebarObject( editor ) {
 			'decay': objectDecayRow,
 			'castShadow': objectShadowRow,
 			'receiveShadow': objectReceiveShadow,
-			'shadow': [ objectShadowRadiusRow, objectShadowBiasRow ]
+			'shadow': [ objectShadowBiasRow, objectShadowNormalOffsetRow, objectShadowRadiusRow ]
 		};
 
 		for ( var property in properties ) {
@@ -840,8 +857,9 @@ function SidebarObject( editor ) {
 
 		if ( object.shadow !== undefined ) {
 
-			objectShadowRadius.setValue( object.shadow.radius );
 			objectShadowBias.setValue( object.shadow.bias );
+			objectShadowNormalOffset.setValue( object.shadow.normalOffset );
+			objectShadowRadius.setValue( object.shadow.radius );
 
 		}
 

+ 2 - 0
editor/js/Sidebar.Scene.js

@@ -436,6 +436,7 @@ function SidebarScene( editor ) {
 
 	signals.sceneGraphChanged.add( refreshUI );
 
+	/*
 	signals.objectChanged.add( function ( object ) {
 
 		var options = outliner.options;
@@ -454,6 +455,7 @@ function SidebarScene( editor ) {
 		}
 
 	} );
+	*/
 
 	signals.objectSelected.add( function ( object ) {
 

+ 13 - 6
editor/js/Strings.js

@@ -110,8 +110,9 @@ function Strings( config ) {
 			'sidebar/object/penumbra': 'Penumbra',
 			'sidebar/object/decay': 'Decay',
 			'sidebar/object/shadow': 'Shadow',
-			'sidebar/object/shadowRadius': 'Shadow Radius',
 			'sidebar/object/shadowBias': 'Shadow Bias',
+			'sidebar/object/shadowNormalOffset': 'Shadow Normal Offset',
+			'sidebar/object/shadowRadius': 'Shadow Radius',
 			'sidebar/object/cast': 'cast',
 			'sidebar/object/receive': 'receive',
 			'sidebar/object/visible': 'Visible',
@@ -323,7 +324,9 @@ function Strings( config ) {
 			'viewport/info/frametime': 'Frametime'
 
 		},
+
 		fr: {
+
 			'menubar/file': 'Fichier',
 			'menubar/file/new': 'Nouveau',
 			'menubar/file/import': 'Importer',
@@ -424,8 +427,9 @@ function Strings( config ) {
 			'sidebar/object/penumbra': 'Pénombre',
 			'sidebar/object/decay': 'Affaiblissement',
 			'sidebar/object/shadow': 'Ombre',
-			'sidebar/object/shadowRadius': 'Rayon de l\'ombre',
 			'sidebar/object/shadowBias': 'Biais directionnel des ombres',
+			'sidebar/object/shadowNormalOffset': 'Shadow Normal Offset',
+			'sidebar/object/shadowRadius': 'Rayon de l\'ombre',
 			'sidebar/object/cast': 'Projète',
 			'sidebar/object/receive': 'Reçoit',
 			'sidebar/object/visible': 'Visible',
@@ -635,7 +639,9 @@ function Strings( config ) {
 			'viewport/info/vertices': 'Sommets',
 			'viewport/info/triangles': 'Triangles',
 			'viewport/info/frametime': 'Temps de trame'
+
 		},
+
 		zh: {
 
 			'menubar/file': '文件',
@@ -738,8 +744,9 @@ function Strings( config ) {
 			'sidebar/object/penumbra': '边缘',
 			'sidebar/object/decay': '衰减',
 			'sidebar/object/shadow': '阴影',
-			'sidebar/object/shadowRadius': '阴影半径',
 			'sidebar/object/shadowBias': '阴影偏移',
+			'sidebar/object/shadowNormalOffset': '阴影法线偏移',
+			'sidebar/object/shadowRadius': '阴影半径',
 			'sidebar/object/cast': '产生',
 			'sidebar/object/receive': '接受',
 			'sidebar/object/visible': '可见性',
@@ -878,8 +885,8 @@ function Strings( config ) {
 			'sidebar/material/opacity': '透明度',
 			'sidebar/material/transparent': '透明性',
 			'sidebar/material/alphatest': 'α测试',
-			'sidebar/material/depthtest': 'Depth Test',
-			'sidebar/material/depthwrite': 'Depth Write',
+			'sidebar/material/depthtest': '深度测试',
+			'sidebar/material/depthwrite': '深度缓冲',
 			'sidebar/material/wireframe': '线框',
 
 			'sidebar/script': '脚本',
@@ -894,7 +901,7 @@ function Strings( config ) {
 			'sidebar/project/renderer': '渲染器',
 			'sidebar/project/antialias': '抗锯齿',
 			'sidebar/project/shadows': '阴影',
-			'sidebar/project/physicallyCorrectLights': 'Physical lights',
+			'sidebar/project/physicallyCorrectLights': '物理灯',
 			'sidebar/project/toneMapping': '色调映射',
 			'sidebar/project/materials': '材质',
 			'sidebar/project/Assign': '应用',

+ 3 - 1
examples/js/controls/OrbitControls.js

@@ -64,7 +64,7 @@ THREE.OrbitControls = function ( object, domElement ) {
 	// Set to false to disable panning
 	this.enablePan = true;
 	this.panSpeed = 1.0;
-	this.screenSpacePanning = false; // if true, pan in screen-space
+	this.screenSpacePanning = true; // if false, pan orthogonal to world-space direction camera.up
 	this.keyPanSpeed = 7.0;	// pixels moved per arrow key push
 
 	// Set to true to automatically rotate around the target
@@ -1139,6 +1139,8 @@ THREE.MapControls = function ( object, domElement ) {
 
 	THREE.OrbitControls.call( this, object, domElement );
 
+	this.screenSpacePanning = false; // pan orthogonal to world-space direction camera.up
+
 	this.mouseButtons.LEFT = THREE.MOUSE.PAN;
 	this.mouseButtons.RIGHT = THREE.MOUSE.ROTATE;
 

+ 1 - 8
examples/js/objects/Reflector.js

@@ -139,14 +139,7 @@ THREE.Reflector = function ( geometry, options ) {
 
 		// Render
 
-		if ( renderer.outputEncoding !== THREE.LinearEncoding ) {
-
-			console.warn( 'THREE.Reflector: WebGLRenderer must use LinearEncoding as outputEncoding.' );
-			scope.onBeforeRender = function () {};
-
-			return;
-
-		}
+		renderTarget.texture.encoding = renderer.outputEncoding;
 
 		scope.visible = false;
 

+ 1 - 8
examples/js/objects/Refractor.js

@@ -224,14 +224,7 @@ THREE.Refractor = function ( geometry, options ) {
 
 		// Render
 
-		if ( renderer.outputEncoding !== THREE.LinearEncoding ) {
-
-			console.warn( 'THREE.Refractor: WebGLRenderer must use LinearEncoding as outputEncoding.' );
-			scope.onBeforeRender = function () {};
-
-			return;
-
-		}
+		renderTarget.texture.encoding = renderer.outputEncoding;
 
 		// ensure refractors are rendered only once per frame
 

+ 2 - 0
examples/js/objects/Water.js

@@ -103,6 +103,8 @@ THREE.Water = function ( geometry, options ) {
 			'	vec4 mvPosition =  modelViewMatrix * vec4( position, 1.0 );',
 			'	gl_Position = projectionMatrix * mvPosition;',
 
+			'#include <beginnormal_vertex>',
+			'#include <defaultnormal_vertex>',
 			'#include <logdepthbuf_vertex>',
 			'#include <fog_vertex>',
 			'#include <shadowmap_vertex>',

+ 3 - 1
examples/jsm/controls/OrbitControls.js

@@ -73,7 +73,7 @@ var OrbitControls = function ( object, domElement ) {
 	// Set to false to disable panning
 	this.enablePan = true;
 	this.panSpeed = 1.0;
-	this.screenSpacePanning = false; // if true, pan in screen-space
+	this.screenSpacePanning = true; // if false, pan orthogonal to world-space direction camera.up
 	this.keyPanSpeed = 7.0;	// pixels moved per arrow key push
 
 	// Set to true to automatically rotate around the target
@@ -1148,6 +1148,8 @@ var MapControls = function ( object, domElement ) {
 
 	OrbitControls.call( this, object, domElement );
 
+	this.screenSpacePanning = false; // pan orthogonal to world-space direction camera.up
+
 	this.mouseButtons.LEFT = MOUSE.PAN;
 	this.mouseButtons.RIGHT = MOUSE.ROTATE;
 

+ 1 - 1
examples/jsm/math/MeshSurfaceSampler.js

@@ -128,7 +128,7 @@ var MeshSurfaceSampler = ( function () {
 
 			while ( start <= end ) {
 
-				var mid = Math.floor( ( start + end ) / 2 );
+				var mid = Math.ceil( ( start + end ) / 2 );
 
 				if ( mid === 0 || dist[ mid - 1 ] <= x && dist[ mid ] > x ) {
 

+ 1 - 9
examples/jsm/objects/Reflector.js

@@ -4,7 +4,6 @@
 
 import {
 	Color,
-	LinearEncoding,
 	LinearFilter,
 	MathUtils,
 	Matrix4,
@@ -155,14 +154,7 @@ var Reflector = function ( geometry, options ) {
 
 		// Render
 
-		if ( renderer.outputEncoding !== LinearEncoding ) {
-
-			console.warn( 'THREE.Reflector: WebGLRenderer must use LinearEncoding as outputEncoding.' );
-			scope.onBeforeRender = function () {};
-
-			return;
-
-		}
+		renderTarget.texture.encoding = renderer.outputEncoding;
 
 		scope.visible = false;
 

+ 1 - 9
examples/jsm/objects/Refractor.js

@@ -5,7 +5,6 @@
 
 import {
 	Color,
-	LinearEncoding,
 	LinearFilter,
 	MathUtils,
 	Matrix4,
@@ -241,14 +240,7 @@ var Refractor = function ( geometry, options ) {
 
 		// Render
 
-		if ( renderer.outputEncoding !== LinearEncoding ) {
-
-			console.warn( 'THREE.Refractor: WebGLRenderer must use LinearEncoding as outputEncoding.' );
-			scope.onBeforeRender = function () {};
-
-			return;
-
-		}
+		renderTarget.texture.encoding = renderer.outputEncoding;
 
 		// ensure refractors are rendered only once per frame
 

+ 2 - 0
examples/jsm/objects/Water.js

@@ -122,6 +122,8 @@ var Water = function ( geometry, options ) {
 			'	vec4 mvPosition =  modelViewMatrix * vec4( position, 1.0 );',
 			'	gl_Position = projectionMatrix * mvPosition;',
 
+			'#include <beginnormal_vertex>',
+			'#include <defaultnormal_vertex>',
 			'#include <logdepthbuf_vertex>',
 			'#include <fog_vertex>',
 			'#include <shadowmap_vertex>',

+ 2 - 2
examples/jsm/webxr/XRControllerModelFactory.js

@@ -8,7 +8,7 @@ import {
 	MeshBasicMaterial,
 	Object3D,
 	Quaternion,
-	SphereGeometry,
+	SphereBufferGeometry,
 } from "../../../build/three.module.js";
 
 import { GLTFLoader } from '../loaders/GLTFLoader.js';
@@ -132,7 +132,7 @@ function findNodes( motionController, scene ) {
 			if ( component.touchPointNode ) {
 
 				// Attach a touch dot to the touchpad.
-				const sphereGeometry = new SphereGeometry( 0.001 );
+				const sphereGeometry = new SphereBufferGeometry( 0.001 );
 				const material = new MeshBasicMaterial( { color: 0x0000FF } );
 				const sphere = new Mesh( sphereGeometry, material );
 				component.touchPointNode.add( sphere );

BIN=BIN
examples/screenshots/webgl_materials_modified.jpg


+ 61 - 32
examples/webgl_materials_modified.html

@@ -24,46 +24,29 @@
 
 			var camera, scene, renderer, stats;
 
-			var materialShader;
-
 			init();
 			animate();
 
 			function init() {
 
-				camera = new THREE.PerspectiveCamera( 27, window.innerWidth / window.innerHeight, 1, 10000 );
-				camera.position.z = 1500;
+				camera = new THREE.PerspectiveCamera( 27, window.innerWidth / window.innerHeight, 0.1, 100 );
+				camera.position.z = 20;
 
 				scene = new THREE.Scene();
 
-				var material = new THREE.MeshNormalMaterial();
-				material.onBeforeCompile = function ( shader ) {
-
-					shader.uniforms.time = { value: 0 };
-
-					shader.vertexShader = 'uniform float time;\n' + shader.vertexShader;
-					shader.vertexShader = shader.vertexShader.replace(
-						'#include <begin_vertex>',
-						[
-							'float theta = sin( time + position.y ) / 2.0;',
-							'float c = cos( theta );',
-							'float s = sin( theta );',
-							'mat3 m = mat3( c, 0, s, 0, 1, 0, -s, 0, c );',
-							'vec3 transformed = vec3( position ) * m;',
-							'vNormal = vNormal * m;'
-						].join( '\n' )
-					);
-
-					materialShader = shader;
-
-				};
-
 				var loader = new GLTFLoader();
 				loader.load( 'models/gltf/LeePerrySmith/LeePerrySmith.glb', function ( gltf ) {
 
-					var mesh = new THREE.Mesh( gltf.scene.children[ 0 ].geometry, material );
-					mesh.position.y = - 50;
-					mesh.scale.setScalar( 100 );
+					var geometry = gltf.scene.children[ 0 ].geometry;
+
+					var mesh = new THREE.Mesh( geometry, buildTwistMaterial( 2.0 ) );
+					mesh.position.x = - 3.5;
+					mesh.position.y = - 0.5;
+					scene.add( mesh );
+
+					var mesh = new THREE.Mesh( geometry, buildTwistMaterial( - 2.0 ) );
+					mesh.position.x = 3.5;
+					mesh.position.y = - 0.5;
 					scene.add( mesh );
 
 				} );
@@ -88,6 +71,42 @@
 
 			}
 
+			function buildTwistMaterial( amount ) {
+
+				var material = new THREE.MeshNormalMaterial();
+				material.onBeforeCompile = function ( shader ) {
+
+					shader.uniforms.time = { value: 0 };
+
+					shader.vertexShader = 'uniform float time;\n' + shader.vertexShader;
+					shader.vertexShader = shader.vertexShader.replace(
+						'#include <begin_vertex>',
+						[
+							`float theta = sin( time + position.y ) / ${ amount.toFixed( 1 ) };`,
+							'float c = cos( theta );',
+							'float s = sin( theta );',
+							'mat3 m = mat3( c, 0, s, 0, 1, 0, -s, 0, c );',
+							'vec3 transformed = vec3( position ) * m;',
+							'vNormal = vNormal * m;'
+						].join( '\n' )
+					);
+
+					material.userData.shader = shader;
+
+				};
+
+				// Make sure WebGLRenderer doesnt reuse a single program
+
+				material.customProgramCacheKey = function () {
+
+					return amount;
+
+				};
+
+				return material;
+
+			}
+
 			//
 
 			function onWindowResize() {
@@ -116,11 +135,21 @@
 
 			function render() {
 
-				if ( materialShader ) {
+				scene.traverse( function ( child ) {
+
+					if ( child.isMesh ) {
+
+						const shader = child.material.userData.shader;
+
+						if ( shader ) {
 
-					materialShader.uniforms.time.value = performance.now() / 1000;
+							shader.uniforms.time.value = performance.now() / 1000;
 
-				}
+						}
+
+					}
+
+				} );
 
 				renderer.render( scene, camera );
 

+ 1 - 0
src/lights/LightShadow.d.ts

@@ -11,6 +11,7 @@ export class LightShadow {
 
 	camera: Camera;
 	bias: number;
+	normalOffset: number;
 	radius: number;
 	mapSize: Vector2;
 	map: RenderTarget;

+ 2 - 0
src/lights/LightShadow.js

@@ -13,6 +13,7 @@ function LightShadow( camera ) {
 	this.camera = camera;
 
 	this.bias = 0;
+	this.normalOffset = 0;
 	this.radius = 1;
 
 	this.mapSize = new Vector2( 512, 512 );
@@ -120,6 +121,7 @@ Object.assign( LightShadow.prototype, {
 		const object = {};
 
 		if ( this.bias !== 0 ) object.bias = this.bias;
+		if ( this.normalOffset !== 0 ) object.normalOffset = this.normalOffset;
 		if ( this.radius !== 1 ) object.radius = this.radius;
 		if ( this.mapSize.x !== 512 || this.mapSize.y !== 512 ) object.mapSize = this.mapSize.toArray();
 

+ 1 - 0
src/loaders/ObjectLoader.js

@@ -928,6 +928,7 @@ ObjectLoader.prototype = Object.assign( Object.create( Loader.prototype ), {
 		if ( data.shadow ) {
 
 			if ( data.shadow.bias !== undefined ) object.shadow.bias = data.shadow.bias;
+			if ( data.shadow.normalOffset !== undefined ) object.shadow.normalOffset = data.shadow.normalOffset;
 			if ( data.shadow.radius !== undefined ) object.shadow.radius = data.shadow.radius;
 			if ( data.shadow.mapSize !== undefined ) object.shadow.mapSize.fromArray( data.shadow.mapSize );
 			if ( data.shadow.camera !== undefined ) object.shadow.camera = this.parseObject( data.shadow.camera );

+ 5 - 0
src/materials/Material.d.ts

@@ -326,6 +326,11 @@ export class Material extends EventDispatcher {
 	 */
 	onBeforeCompile ( shaderobject : object, renderer : WebGLRenderer ) : void;
 
+	/**
+	 * In case onBeforeCompile is used, this callback can be used to identify values of settings used in onBeforeCompile, so three.js can reuse a cached shader or recompile the shader as needed.
+	 */
+	customProgramCacheKey(): string;
+
 	/**
 	 * Sets the properties based on the values.
 	 * @param values A container with parameters.

+ 6 - 0
src/materials/Material.js

@@ -85,6 +85,12 @@ Material.prototype = Object.assign( Object.create( EventDispatcher.prototype ),
 
 	onBeforeCompile: function ( /* shaderobject, renderer */ ) {},
 
+	customProgramCacheKey: function () {
+
+		return this.onBeforeCompile.toString();
+
+	},
+
 	setValues: function ( values ) {
 
 		if ( values === undefined ) return;

+ 5 - 5
src/math/Euler.js

@@ -12,12 +12,12 @@ import { MathUtils } from './MathUtils.js';
 const _matrix = new Matrix4();
 const _quaternion = new Quaternion();
 
-function Euler( x, y, z, order ) {
+function Euler( x = 0, y = 0, z = 0, order = Euler.DefaultOrder ) {
 
-	this._x = x || 0;
-	this._y = y || 0;
-	this._z = z || 0;
-	this._order = order || Euler.DefaultOrder;
+	this._x = x;
+	this._y = y;
+	this._z = z;
+	this._order = order;
 
 }
 

+ 5 - 5
src/math/Quaternion.js

@@ -7,12 +7,12 @@
 
 import { MathUtils } from './MathUtils.js';
 
-function Quaternion( x, y, z, w ) {
+function Quaternion( x = 0, y = 0, z = 0, w = 1 ) {
 
-	this._x = x || 0;
-	this._y = y || 0;
-	this._z = z || 0;
-	this._w = ( w !== undefined ) ? w : 1;
+	this._x = x;
+	this._y = y;
+	this._z = z;
+	this._w = w;
 
 }
 

+ 3 - 3
src/math/Vector2.js

@@ -5,10 +5,10 @@
  * @author zz85 / http://www.lab4games.net/zz85/blog
  */
 
-function Vector2( x, y ) {
+function Vector2( x = 0, y = 0 ) {
 
-	this.x = x || 0;
-	this.y = y || 0;
+	this.x = x;
+	this.y = y;
 
 }
 

+ 4 - 4
src/math/Vector3.js

@@ -13,11 +13,11 @@ import { Quaternion } from './Quaternion.js';
 const _vector = new Vector3();
 const _quaternion = new Quaternion();
 
-function Vector3( x, y, z ) {
+function Vector3( x = 0, y = 0, z = 0 ) {
 
-	this.x = x || 0;
-	this.y = y || 0;
-	this.z = z || 0;
+	this.x = x;
+	this.y = y;
+	this.z = z;
 
 }
 

+ 5 - 5
src/math/Vector4.js

@@ -6,12 +6,12 @@
  * @author WestLangley / http://github.com/WestLangley
  */
 
-function Vector4( x, y, z, w ) {
+function Vector4( x = 0, y = 0, z = 0, w = 1 ) {
 
-	this.x = x || 0;
-	this.y = y || 0;
-	this.z = z || 0;
-	this.w = ( w !== undefined ) ? w : 1;
+	this.x = x;
+	this.y = y;
+	this.z = z;
+	this.w = w;
 
 }
 

+ 0 - 39
src/renderers/shaders/ShaderChunk/lights_pars_begin.glsl.js

@@ -63,19 +63,6 @@ vec3 getAmbientLightIrradiance( const in vec3 ambientLightColor ) {
 
 	uniform DirectionalLight directionalLights[ NUM_DIR_LIGHTS ];
 
-	#if defined( USE_SHADOWMAP ) && NUM_DIR_LIGHT_SHADOWS > 0
-
-		struct DirectionalLightShadow {
-			float shadowBias;
-			float shadowRadius;
-			vec2 shadowMapSize;
-		};
-
-		uniform DirectionalLightShadow directionalLightShadows[ NUM_DIR_LIGHT_SHADOWS ];
-
-	#endif
-
-
 	void getDirectionalDirectLightIrradiance( const in DirectionalLight directionalLight, const in GeometricContext geometry, out IncidentLight directLight ) {
 
 		directLight.color = directionalLight.color;
@@ -98,20 +85,6 @@ vec3 getAmbientLightIrradiance( const in vec3 ambientLightColor ) {
 
 	uniform PointLight pointLights[ NUM_POINT_LIGHTS ];
 
-	#if defined( USE_SHADOWMAP ) && NUM_POINT_LIGHT_SHADOWS > 0
-
-		struct PointLightShadow {
-			float shadowBias;
-			float shadowRadius;
-			vec2 shadowMapSize;
-			float shadowCameraNear;
-			float shadowCameraFar;
-		};
-
-		uniform PointLightShadow pointLightShadows[ NUM_POINT_LIGHT_SHADOWS ];
-
-	#endif
-
 	// directLight is an out parameter as having it as a return value caused compiler errors on some devices
 	void getPointDirectLightIrradiance( const in PointLight pointLight, const in GeometricContext geometry, out IncidentLight directLight ) {
 
@@ -143,18 +116,6 @@ vec3 getAmbientLightIrradiance( const in vec3 ambientLightColor ) {
 
 	uniform SpotLight spotLights[ NUM_SPOT_LIGHTS ];
 
-	#if defined( USE_SHADOWMAP ) && NUM_SPOT_LIGHT_SHADOWS > 0
-
-		struct SpotLightShadow {
-			float shadowBias;
-			float shadowRadius;
-			vec2 shadowMapSize;
-		};
-
-		uniform SpotLightShadow spotLightShadows[ NUM_SPOT_LIGHT_SHADOWS ];
-
-	#endif
-
 	// directLight is an out parameter as having it as a return value caused compiler errors on some devices
 	void getSpotDirectLightIrradiance( const in SpotLight spotLight, const in GeometricContext geometry, out IncidentLight directLight  ) {
 

+ 29 - 0
src/renderers/shaders/ShaderChunk/shadowmap_pars_fragment.glsl.js

@@ -6,6 +6,15 @@ export default /* glsl */`
 		uniform sampler2D directionalShadowMap[ NUM_DIR_LIGHT_SHADOWS ];
 		varying vec4 vDirectionalShadowCoord[ NUM_DIR_LIGHT_SHADOWS ];
 
+		struct DirectionalLightShadow {
+			float shadowBias;
+			float shadowNormalOffset;
+			float shadowRadius;
+			vec2 shadowMapSize;
+		};
+
+		uniform DirectionalLightShadow directionalLightShadows[ NUM_DIR_LIGHT_SHADOWS ];
+
 	#endif
 
 	#if NUM_SPOT_LIGHT_SHADOWS > 0
@@ -13,6 +22,15 @@ export default /* glsl */`
 		uniform sampler2D spotShadowMap[ NUM_SPOT_LIGHT_SHADOWS ];
 		varying vec4 vSpotShadowCoord[ NUM_SPOT_LIGHT_SHADOWS ];
 
+		struct SpotLightShadow {
+			float shadowBias;
+			float shadowNormalOffset;
+			float shadowRadius;
+			vec2 shadowMapSize;
+		};
+
+		uniform SpotLightShadow spotLightShadows[ NUM_SPOT_LIGHT_SHADOWS ];
+
 	#endif
 
 	#if NUM_POINT_LIGHT_SHADOWS > 0
@@ -20,6 +38,17 @@ export default /* glsl */`
 		uniform sampler2D pointShadowMap[ NUM_POINT_LIGHT_SHADOWS ];
 		varying vec4 vPointShadowCoord[ NUM_POINT_LIGHT_SHADOWS ];
 
+		struct PointLightShadow {
+			float shadowBias;
+			float shadowNormalOffset;
+			float shadowRadius;
+			vec2 shadowMapSize;
+			float shadowCameraNear;
+			float shadowCameraFar;
+		};
+
+		uniform PointLightShadow pointLightShadows[ NUM_POINT_LIGHT_SHADOWS ];
+
 	#endif
 
 	/*

+ 29 - 0
src/renderers/shaders/ShaderChunk/shadowmap_pars_vertex.glsl.js

@@ -6,6 +6,15 @@ export default /* glsl */`
 		uniform mat4 directionalShadowMatrix[ NUM_DIR_LIGHT_SHADOWS ];
 		varying vec4 vDirectionalShadowCoord[ NUM_DIR_LIGHT_SHADOWS ];
 
+		struct DirectionalLightShadow {
+			float shadowBias;
+			float shadowNormalOffset;
+			float shadowRadius;
+			vec2 shadowMapSize;
+		};
+
+		uniform DirectionalLightShadow directionalLightShadows[ NUM_DIR_LIGHT_SHADOWS ];
+
 	#endif
 
 	#if NUM_SPOT_LIGHT_SHADOWS > 0
@@ -13,6 +22,15 @@ export default /* glsl */`
 		uniform mat4 spotShadowMatrix[ NUM_SPOT_LIGHT_SHADOWS ];
 		varying vec4 vSpotShadowCoord[ NUM_SPOT_LIGHT_SHADOWS ];
 
+		struct SpotLightShadow {
+			float shadowBias;
+			float shadowNormalOffset;
+			float shadowRadius;
+			vec2 shadowMapSize;
+		};
+
+		uniform SpotLightShadow spotLightShadows[ NUM_SPOT_LIGHT_SHADOWS ];
+
 	#endif
 
 	#if NUM_POINT_LIGHT_SHADOWS > 0
@@ -20,6 +38,17 @@ export default /* glsl */`
 		uniform mat4 pointShadowMatrix[ NUM_POINT_LIGHT_SHADOWS ];
 		varying vec4 vPointShadowCoord[ NUM_POINT_LIGHT_SHADOWS ];
 
+		struct PointLightShadow {
+			float shadowBias;
+			float shadowNormalOffset;
+			float shadowRadius;
+			vec2 shadowMapSize;
+			float shadowCameraNear;
+			float shadowCameraFar;
+		};
+
+		uniform PointLightShadow pointLightShadows[ NUM_POINT_LIGHT_SHADOWS ];
+
 	#endif
 
 	/*

+ 14 - 3
src/renderers/shaders/ShaderChunk/shadowmap_vertex.glsl.js

@@ -1,12 +1,21 @@
 export default /* glsl */`
 #ifdef USE_SHADOWMAP
 
+	#if NUM_DIR_LIGHT_SHADOWS > 0 || NUM_SPOT_LIGHT_SHADOWS > 0 || NUM_POINT_LIGHT_SHADOWS > 0
+
+		// Offsetting the position used for querying occlusion along the world normal can be used to reduce shadow acne.
+		vec3 shadowWorldNormal = inverseTransformDirection( transformedNormal, viewMatrix );
+		vec4 shadowWorldPosition;
+
+	#endif
+
 	#if NUM_DIR_LIGHT_SHADOWS > 0
 
 	#pragma unroll_loop_start
 	for ( int i = 0; i < NUM_DIR_LIGHT_SHADOWS; i ++ ) {
 
-		vDirectionalShadowCoord[ i ] = directionalShadowMatrix[ i ] * worldPosition;
+		shadowWorldPosition = worldPosition + vec4( shadowWorldNormal * directionalLightShadows[ i ].shadowNormalOffset, 0 );
+		vDirectionalShadowCoord[ i ] = directionalShadowMatrix[ i ] * shadowWorldPosition;
 
 	}
 	#pragma unroll_loop_end
@@ -18,7 +27,8 @@ export default /* glsl */`
 	#pragma unroll_loop_start
 	for ( int i = 0; i < NUM_SPOT_LIGHT_SHADOWS; i ++ ) {
 
-		vSpotShadowCoord[ i ] = spotShadowMatrix[ i ] * worldPosition;
+		shadowWorldPosition = worldPosition + vec4( shadowWorldNormal * spotLightShadows[ i ].shadowNormalOffset, 0 );
+		vSpotShadowCoord[ i ] = spotShadowMatrix[ i ] * shadowWorldPosition;
 
 	}
 	#pragma unroll_loop_end
@@ -30,7 +40,8 @@ export default /* glsl */`
 	#pragma unroll_loop_start
 	for ( int i = 0; i < NUM_POINT_LIGHT_SHADOWS; i ++ ) {
 
-		vPointShadowCoord[ i ] = pointShadowMatrix[ i ] * worldPosition;
+		shadowWorldPosition = worldPosition + vec4( shadowWorldNormal * pointLightShadows[ i ].shadowNormalOffset, 0 );
+		vPointShadowCoord[ i ] = pointShadowMatrix[ i ] * shadowWorldPosition;
 
 	}
 	#pragma unroll_loop_end

+ 7 - 0
src/renderers/shaders/ShaderLib/shadow_vert.glsl.js

@@ -7,6 +7,13 @@ void main() {
 	#include <begin_vertex>
 	#include <project_vertex>
 	#include <worldpos_vertex>
+
+	#include <beginnormal_vertex>
+	#include <morphnormal_vertex>
+	#include <skinbase_vertex>
+	#include <skinnormal_vertex>
+	#include <defaultnormal_vertex>
+
 	#include <shadowmap_vertex>
 	#include <fog_vertex>
 

+ 3 - 0
src/renderers/shaders/UniformsLib.d.ts

@@ -73,6 +73,7 @@ export let UniformsLib: {
 			value: any[];
 			properties: {
 				shadowBias: {};
+				shadowNormalOffset: {};
 				shadowRadius: {};
 				shadowMapSize: {};
 			};
@@ -95,6 +96,7 @@ export let UniformsLib: {
 			value: any[];
 			properties: {
 				shadowBias: {};
+				shadowNormalOffset: {};
 				shadowRadius: {};
 				shadowMapSize: {};
 			};
@@ -114,6 +116,7 @@ export let UniformsLib: {
 			value: any[];
 			properties: {
 				shadowBias: {};
+				shadowNormalOffset: {};
 				shadowRadius: {};
 				shadowMapSize: {};
 			};

+ 3 - 0
src/renderers/shaders/UniformsLib.js

@@ -119,6 +119,7 @@ const UniformsLib = {
 
 		directionalLightShadows: { value: [], properties: {
 			shadowBias: {},
+			shadowNormalOffset: {},
 			shadowRadius: {},
 			shadowMapSize: {}
 		} },
@@ -138,6 +139,7 @@ const UniformsLib = {
 
 		spotLightShadows: { value: [], properties: {
 			shadowBias: {},
+			shadowNormalOffset: {},
 			shadowRadius: {},
 			shadowMapSize: {}
 		} },
@@ -154,6 +156,7 @@ const UniformsLib = {
 
 		pointLightShadows: { value: [], properties: {
 			shadowBias: {},
+			shadowNormalOffset: {},
 			shadowRadius: {},
 			shadowMapSize: {},
 			shadowCameraNear: {},

+ 6 - 0
src/renderers/webgl/WebGLLights.js

@@ -103,6 +103,7 @@ function ShadowUniformsCache() {
 				case 'DirectionalLight':
 					uniforms = {
 						shadowBias: 0,
+						shadowNormalOffset: 0,
 						shadowRadius: 1,
 						shadowMapSize: new Vector2()
 					};
@@ -111,6 +112,7 @@ function ShadowUniformsCache() {
 				case 'SpotLight':
 					uniforms = {
 						shadowBias: 0,
+						shadowNormalOffset: 0,
 						shadowRadius: 1,
 						shadowMapSize: new Vector2()
 					};
@@ -119,6 +121,7 @@ function ShadowUniformsCache() {
 				case 'PointLight':
 					uniforms = {
 						shadowBias: 0,
+						shadowNormalOffset: 0,
 						shadowRadius: 1,
 						shadowMapSize: new Vector2(),
 						shadowCameraNear: 1,
@@ -258,6 +261,7 @@ function WebGLLights() {
 					const shadowUniforms = shadowCache.get( light );
 
 					shadowUniforms.shadowBias = shadow.bias;
+					shadowUniforms.shadowNormalOffset = shadow.normalOffset;
 					shadowUniforms.shadowRadius = shadow.radius;
 					shadowUniforms.shadowMapSize = shadow.mapSize;
 
@@ -299,6 +303,7 @@ function WebGLLights() {
 					const shadowUniforms = shadowCache.get( light );
 
 					shadowUniforms.shadowBias = shadow.bias;
+					shadowUniforms.shadowNormalOffset = shadow.normalOffset;
 					shadowUniforms.shadowRadius = shadow.radius;
 					shadowUniforms.shadowMapSize = shadow.mapSize;
 
@@ -364,6 +369,7 @@ function WebGLLights() {
 					const shadowUniforms = shadowCache.get( light );
 
 					shadowUniforms.shadowBias = shadow.bias;
+					shadowUniforms.shadowNormalOffset = shadow.normalOffset;
 					shadowUniforms.shadowRadius = shadow.radius;
 					shadowUniforms.shadowMapSize = shadow.mapSize;
 					shadowUniforms.shadowCameraNear = shadow.camera.near;

+ 2 - 2
src/renderers/webgl/WebGLPrograms.js

@@ -271,7 +271,7 @@ function WebGLPrograms( renderer, extensions, capabilities ) {
 			rendererExtensionDrawBuffers: isWebGL2 || extensions.get( 'WEBGL_draw_buffers' ) !== null,
 			rendererExtensionShaderTextureLod: isWebGL2 || extensions.get( 'EXT_shader_texture_lod' ) !== null,
 
-			onBeforeCompile: material.onBeforeCompile
+			customProgramCacheKey: material.customProgramCacheKey()
 
 		};
 
@@ -318,7 +318,7 @@ function WebGLPrograms( renderer, extensions, capabilities ) {
 
 		}
 
-		array.push( parameters.onBeforeCompile.toString() );
+		array.push( parameters.customProgramCacheKey );
 
 		return array.join();
 

Algúns arquivos non se mostraron porque demasiados arquivos cambiaron neste cambio