浏览代码

Merge pull request #13 from mrdoob/dev

Merge from upstream.
gogoend 6 年之前
父节点
当前提交
6cfccee13d
共有 60 个文件被更改,包括 1250 次插入789 次删除
  1. 1 1
      .github/ISSUE_TEMPLATE.md
  2. 14 1
      build/three.js
  3. 449 446
      build/three.min.js
  4. 14 1
      build/three.module.js
  5. 3 1
      docs/api/en/constants/Renderer.html
  6. 10 0
      docs/api/en/core/Layers.html
  7. 8 5
      docs/api/en/lights/shadows/LightShadow.html
  8. 1 1
      docs/api/en/renderers/WebGLRenderer.html
  9. 3 2
      editor/js/Loader.js
  10. 1 1
      editor/sw.js
  11. 5 4
      examples/files.js
  12. 2 2
      examples/js/libs/draco/README.md
  13. 1 6
      examples/jsm/nodes/Nodes.d.ts
  14. 1 6
      examples/jsm/nodes/Nodes.js
  15. 12 1
      examples/jsm/nodes/accessors/ReflectNode.js
  16. 0 13
      examples/jsm/nodes/bsdfs/BlinnExponentToRoughnessNode.d.ts
  17. 0 52
      examples/jsm/nodes/bsdfs/BlinnExponentToRoughnessNode.js
  18. 0 10
      examples/jsm/nodes/bsdfs/BlinnShininessExponentNode.d.ts
  19. 0 31
      examples/jsm/nodes/bsdfs/BlinnShininessExponentNode.js
  20. 0 94
      examples/jsm/nodes/bsdfs/RoughnessToBlinnExponentNode.js
  21. 1 1
      examples/jsm/nodes/inputs/CubeTextureNode.js
  22. 1 1
      examples/jsm/nodes/inputs/TextureNode.js
  23. 9 5
      examples/jsm/nodes/materials/nodes/StandardNode.js
  24. 35 20
      examples/jsm/nodes/misc/NormalMapNode.js
  25. 14 8
      examples/jsm/nodes/misc/TextureCubeNode.js
  26. 5 3
      examples/jsm/nodes/misc/TextureCubeUVNode.js
  27. 2 4
      examples/jsm/nodes/utils/SpecularMIPLevelNode.d..ts
  28. 102 0
      examples/jsm/nodes/utils/SpecularMIPLevelNode.js
  29. 4 1
      examples/main.css
  30. 二进制
      examples/textures/flakes.png
  31. 二进制
      examples/textures/golfball.jpg
  32. 35 13
      examples/webgl_layers.html
  33. 3 4
      examples/webgl_lightningstrike.html
  34. 3 2
      examples/webgl_materials_cars.html
  35. 2 2
      examples/webgl_materials_nodes.html
  36. 31 10
      examples/webgl_materials_physical_clearcoat.html
  37. 0 0
      examples/webgl_materials_physical_sheen.html
  38. 0 0
      examples/webgl_materials_physical_transparency.html
  39. 2 4
      examples/webgl_shaders_sky.html
  40. 222 0
      examples/webgl_shadowmap_vsm.html
  41. 1 0
      files/main.css
  42. 1 1
      package.json
  43. 1 0
      src/constants.d.ts
  44. 2 1
      src/constants.js
  45. 2 0
      src/core/Layers.d.ts
  46. 12 0
      src/core/Layers.js
  47. 1 0
      src/lights/LightShadow.d.ts
  48. 1 0
      src/lights/LightShadow.js
  49. 3 1
      src/renderers/WebGLRenderTarget.d.ts
  50. 11 9
      src/renderers/shaders/ShaderChunk/envmap_physical_pars_fragment.glsl.js
  51. 2 0
      src/renderers/shaders/ShaderChunk/lights_fragment_begin.glsl.js
  52. 1 1
      src/renderers/shaders/ShaderChunk/lights_fragment_end.glsl.js
  53. 3 3
      src/renderers/shaders/ShaderChunk/lights_fragment_maps.glsl.js
  54. 4 6
      src/renderers/shaders/ShaderChunk/lights_physical_pars_fragment.glsl.js
  55. 17 0
      src/renderers/shaders/ShaderChunk/packing.glsl.js
  56. 32 1
      src/renderers/shaders/ShaderChunk/shadowmap_pars_fragment.glsl.js
  57. 42 0
      src/renderers/shaders/ShaderLib/vsm_frag.glsl.js
  58. 9 0
      src/renderers/shaders/ShaderLib/vsm_vert.glsl.js
  59. 5 1
      src/renderers/webgl/WebGLProgram.js
  60. 104 9
      src/renderers/webgl/WebGLShadowMap.js

+ 1 - 1
.github/ISSUE_TEMPLATE.md

@@ -19,7 +19,7 @@ Please also include a live example if possible. You can start from these templat
 ##### Three.js version
 ##### Three.js version
 
 
 - [ ] Dev
 - [ ] Dev
-- [ ] r107
+- [ ] r108
 - [ ] ...
 - [ ] ...
 
 
 ##### Browser
 ##### Browser

文件差异内容过多而无法显示
+ 14 - 1
build/three.js


文件差异内容过多而无法显示
+ 449 - 446
build/three.min.js


文件差异内容过多而无法显示
+ 14 - 1
build/three.module.js


+ 3 - 1
docs/api/en/constants/Renderer.html

@@ -39,13 +39,15 @@
 		THREE.BasicShadowMap
 		THREE.BasicShadowMap
 		THREE.PCFShadowMap
 		THREE.PCFShadowMap
 		THREE.PCFSoftShadowMap
 		THREE.PCFSoftShadowMap
+		THREE.VSMShadowMap
 		</code>
 		</code>
 		<p>
 		<p>
 		These define the WebGLRenderer's [page:WebGLRenderer.shadowMap.type shadowMap.type] property.<br /><br />
 		These define the WebGLRenderer's [page:WebGLRenderer.shadowMap.type shadowMap.type] property.<br /><br />
 
 
 		[page:constant BasicShadowMap] gives unfiltered shadow maps - fastest, but lowest quality.<br />
 		[page:constant BasicShadowMap] gives unfiltered shadow maps - fastest, but lowest quality.<br />
 		[page:constant PCFShadowMap] filters shadow maps using the Percentage-Closer Filtering (PCF) algorithm (default).<br />
 		[page:constant PCFShadowMap] filters shadow maps using the Percentage-Closer Filtering (PCF) algorithm (default).<br />
-		[page:constant PCFSoftShadowMap] filters shadow maps using the Percentage-Closer Soft Shadows (PCSS) algorithm.
+		[page:constant PCFSoftShadowMap] filters shadow maps using the Percentage-Closer Soft Shadows (PCSS) algorithm.<br />
+		[page:constant VSMShadowMap] filters shadow maps using the Variance Shadow Map (VSM) algorithm.
 		</p>
 		</p>
 
 
 		<h2>Tone Mapping</h2>
 		<h2>Tone Mapping</h2>

+ 10 - 0
docs/api/en/core/Layers.html

@@ -80,6 +80,16 @@
 			Toggle membership of *layer*.
 			Toggle membership of *layer*.
 		</p>
 		</p>
 
 
+		<h3>[method:null enableAll]()</h3>
+		<p>
+			Add membership to all layers.
+		</p>
+
+		<h3>[method:null disableAll]()</h3>
+		<p>
+			Remove membership from all layers.
+		</p>
+
 		<h2>Source</h2>
 		<h2>Source</h2>
 
 
 		<p>
 		<p>

+ 8 - 5
docs/api/en/lights/shadows/LightShadow.html

@@ -22,7 +22,7 @@
 		<p>
 		<p>
 		[page:Camera camera] - the light's view of the world.<br /><br />
 		[page:Camera camera] - the light's view of the world.<br /><br />
 
 
-		Create a new [name]. This is not intended to be called directly - it is used as a base class by
+		Create a new [name]. This is not intended to be called directly - it is used as a base class by 
 		other light shadows.
 		other light shadows.
 		</p>
 		</p>
 
 
@@ -46,6 +46,12 @@
 			in shadow. Computed internally during rendering.
 			in shadow. Computed internally during rendering.
 		</p>
 		</p>
 
 
+		<h3>[property:WebGLRenderTarget mapPass]</h3>
+		<p>
+			The distribution map generated using the internal camera; an occlusion is calculated based 
+			on the distribution of depths. Computed internally during rendering.
+		</p>
+
 		<h3>[property:Vector2 mapSize]</h3>
 		<h3>[property:Vector2 mapSize]</h3>
 		<p>
 		<p>
 			A [Page:Vector2] defining the width and height of the shadow map.<br /><br />
 			A [Page:Vector2] defining the width and height of the shadow map.<br /><br />
@@ -56,7 +62,6 @@
 			The default is *( 512, 512 )*.
 			The default is *( 512, 512 )*.
 		</p>
 		</p>
 
 
-
 		<h3>[property:Matrix4 matrix]</h3>
 		<h3>[property:Matrix4 matrix]</h3>
 		<p>
 		<p>
 			Model to shadow camera space, to compute location and depth in shadow map. Stored
 			Model to shadow camera space, to compute location and depth in shadow map. Stored
@@ -118,8 +123,6 @@
 
 
 		<h2>Source</h2>
 		<h2>Source</h2>
 
 
-		<p>
-			[link:https://github.com/mrdoob/three.js/blob/master/src/lights/[name].js src/lights/[name].js]
-		</p>
+		[link:https://github.com/mrdoob/three.js/blob/master/src/lights/[name].js src/lights/[name].js]
 	</body>
 	</body>
 </html>
 </html>

+ 1 - 1
docs/api/en/renderers/WebGLRenderer.html

@@ -248,7 +248,7 @@
 
 
 		<h3>[property:Integer shadowMap.type]</h3>
 		<h3>[property:Integer shadowMap.type]</h3>
 		<p>Defines shadow map type (unfiltered, percentage close filtering, percentage close filtering with bilinear filtering in shader)</p>
 		<p>Defines shadow map type (unfiltered, percentage close filtering, percentage close filtering with bilinear filtering in shader)</p>
-		<p>Options are THREE.BasicShadowMap, THREE.PCFShadowMap (default) and THREE.PCFSoftShadowMap. See [page:Renderer Renderer constants] for details.</p>
+		<p>Options are THREE.BasicShadowMap, THREE.PCFShadowMap (default), THREE.PCFSoftShadowMap and THREE.VSMShadowMap. See [page:Renderer Renderer constants] for details.</p>
 
 
 		<h3>[property:Boolean sortObjects]</h3>
 		<h3>[property:Boolean sortObjects]</h3>
 		<p>
 		<p>

+ 3 - 2
editor/js/Loader.js

@@ -182,10 +182,11 @@ var Loader = function ( editor ) {
 
 
 					var contents = event.target.result;
 					var contents = event.target.result;
 
 
-					THREE.DRACOLoader.setDecoderPath( '../examples/js/libs/draco/gltf/' );
+					var dracoLoader = new THREE.DRACOLoader();
+					dracoLoader.setDecoderPath( '../examples/js/libs/draco/gltf/' );
 
 
 					var loader = new THREE.GLTFLoader();
 					var loader = new THREE.GLTFLoader();
-					loader.setDRACOLoader( new THREE.DRACOLoader() );
+					loader.setDRACOLoader( dracoLoader );
 					loader.parse( contents, '', function ( result ) {
 					loader.parse( contents, '', function ( result ) {
 
 
 						var scene = result.scene;
 						var scene = result.scene;

+ 1 - 1
editor/sw.js

@@ -1,4 +1,4 @@
-// r107
+// r108
 
 
 const staticAssets = [
 const staticAssets = [
 	'./',
 	'./',

+ 5 - 4
examples/files.js

@@ -144,8 +144,6 @@ var files = {
 		"webgl_materials_bumpmap_skin",
 		"webgl_materials_bumpmap_skin",
 		"webgl_materials_cars",
 		"webgl_materials_cars",
 		"webgl_materials_channels",
 		"webgl_materials_channels",
-		"webgl_materials_clearcoat_normalmap",
-		"webgl_materials_compile",
 		"webgl_materials_cubemap",
 		"webgl_materials_cubemap",
 		"webgl_materials_cubemap_balls_reflection",
 		"webgl_materials_cubemap_balls_reflection",
 		"webgl_materials_cubemap_balls_refraction",
 		"webgl_materials_cubemap_balls_refraction",
@@ -164,9 +162,11 @@ var files = {
 		"webgl_materials_normalmap",
 		"webgl_materials_normalmap",
 		"webgl_materials_normalmap_object_space",
 		"webgl_materials_normalmap_object_space",
 		"webgl_materials_parallaxmap",
 		"webgl_materials_parallaxmap",
+		"webgl_materials_physical_clearcoat",
+		"webgl_materials_physical_sheen",
+		"webgl_materials_physical_transparency",
 		"webgl_materials_reflectivity",
 		"webgl_materials_reflectivity",
 		"webgl_materials_shaders_fresnel",
 		"webgl_materials_shaders_fresnel",
-		"webgl_materials_sheen",
 		"webgl_materials_skin",
 		"webgl_materials_skin",
 		"webgl_materials_standard",
 		"webgl_materials_standard",
 		"webgl_materials_texture_anisotropy",
 		"webgl_materials_texture_anisotropy",
@@ -176,7 +176,6 @@ var files = {
 		"webgl_materials_texture_partialupdate",
 		"webgl_materials_texture_partialupdate",
 		"webgl_materials_texture_rotation",
 		"webgl_materials_texture_rotation",
 		"webgl_materials_translucency",
 		"webgl_materials_translucency",
-		"webgl_materials_transparency",
 		"webgl_materials_variations_basic",
 		"webgl_materials_variations_basic",
 		"webgl_materials_variations_lambert",
 		"webgl_materials_variations_lambert",
 		"webgl_materials_variations_phong",
 		"webgl_materials_variations_phong",
@@ -232,6 +231,7 @@ var files = {
 		"webgl_shadowmap_performance",
 		"webgl_shadowmap_performance",
 		"webgl_shadowmap_pointlight",
 		"webgl_shadowmap_pointlight",
 		"webgl_shadowmap_viewer",
 		"webgl_shadowmap_viewer",
+		"webgl_shadowmap_vsm",
 		"webgl_shadowmesh",
 		"webgl_shadowmesh",
 		"webgl_skinning_simple",
 		"webgl_skinning_simple",
 		"webgl_sprites",
 		"webgl_sprites",
@@ -246,6 +246,7 @@ var files = {
 	],
 	],
 	"webgl / nodes": [
 	"webgl / nodes": [
 		"webgl_loader_nodes",
 		"webgl_loader_nodes",
+		"webgl_materials_compile",
 		"webgl_materials_envmaps_hdr_nodes",
 		"webgl_materials_envmaps_hdr_nodes",
 		"webgl_materials_envmaps_pmrem_nodes",
 		"webgl_materials_envmaps_pmrem_nodes",
 		"webgl_materials_nodes",
 		"webgl_materials_nodes",

+ 2 - 2
examples/js/libs/draco/README.md

@@ -20,9 +20,9 @@ Each file is provided in two variations:
 Either variation may be used with `THREE.DRACOLoader`:
 Either variation may be used with `THREE.DRACOLoader`:
 
 
 ```js
 ```js
-THREE.DRACOLoader.setDecoderPath('path/to/decoders/');
-THREE.DRACOLoader.setDecoderConfig({type: 'js'}); // (Optional) Override detection of WASM support.
 var dracoLoader = new THREE.DRACOLoader();
 var dracoLoader = new THREE.DRACOLoader();
+dracoLoader.setDecoderPath('path/to/decoders/');
+dracoLoader.setDecoderConfig({type: 'js'}); // (Optional) Override detection of WASM support.
 ```
 ```
 
 
 Further [documentation on GitHub](https://github.com/google/draco/tree/master/javascript/example#static-loading-javascript-decoder).
 Further [documentation on GitHub](https://github.com/google/draco/tree/master/javascript/example#static-loading-javascript-decoder).

+ 1 - 6
examples/jsm/nodes/Nodes.d.ts

@@ -57,12 +57,6 @@ export * from './math/CondNode';
 export * from './procedural/NoiseNode';
 export * from './procedural/NoiseNode';
 export * from './procedural/CheckerNode';
 export * from './procedural/CheckerNode';
 
 
-// bsdfs
-
-export * from './bsdfs/BlinnShininessExponentNode';
-export * from './bsdfs/BlinnExponentToRoughnessNode';
-export * from './bsdfs/RoughnessToBlinnExponentNode';
-
 // misc
 // misc
 
 
 export * from './misc/TextureCubeUVNode';
 export * from './misc/TextureCubeUVNode';
@@ -79,6 +73,7 @@ export * from './utils/TimerNode';
 export * from './utils/VelocityNode';
 export * from './utils/VelocityNode';
 export * from './utils/UVTransformNode';
 export * from './utils/UVTransformNode';
 export * from './utils/MaxMIPLevelNode';
 export * from './utils/MaxMIPLevelNode';
+export * from './utils/SpecularMIPLevelNode';
 export * from './utils/ColorSpaceNode';
 export * from './utils/ColorSpaceNode';
 
 
 // effects
 // effects

+ 1 - 6
examples/jsm/nodes/Nodes.js

@@ -59,12 +59,6 @@ export { CondNode } from './math/CondNode.js';
 export { NoiseNode } from './procedural/NoiseNode.js';
 export { NoiseNode } from './procedural/NoiseNode.js';
 export { CheckerNode } from './procedural/CheckerNode.js';
 export { CheckerNode } from './procedural/CheckerNode.js';
 
 
-// bsdfs
-
-export { BlinnShininessExponentNode } from './bsdfs/BlinnShininessExponentNode.js';
-export { BlinnExponentToRoughnessNode } from './bsdfs/BlinnExponentToRoughnessNode.js';
-export { RoughnessToBlinnExponentNode } from './bsdfs/RoughnessToBlinnExponentNode.js';
-
 // misc
 // misc
 
 
 export { TextureCubeUVNode } from './misc/TextureCubeUVNode.js';
 export { TextureCubeUVNode } from './misc/TextureCubeUVNode.js';
@@ -81,6 +75,7 @@ export { TimerNode } from './utils/TimerNode.js';
 export { VelocityNode } from './utils/VelocityNode.js';
 export { VelocityNode } from './utils/VelocityNode.js';
 export { UVTransformNode } from './utils/UVTransformNode.js';
 export { UVTransformNode } from './utils/UVTransformNode.js';
 export { MaxMIPLevelNode } from './utils/MaxMIPLevelNode.js';
 export { MaxMIPLevelNode } from './utils/MaxMIPLevelNode.js';
+export { SpecularMIPLevelNode } from './utils/SpecularMIPLevelNode.js';
 export { ColorSpaceNode } from './utils/ColorSpaceNode.js';
 export { ColorSpaceNode } from './utils/ColorSpaceNode.js';
 export { SubSlotNode } from './utils/SubSlotNode.js';
 export { SubSlotNode } from './utils/SubSlotNode.js';
 
 

+ 12 - 1
examples/jsm/nodes/accessors/ReflectNode.js

@@ -55,11 +55,22 @@ ReflectNode.prototype.generate = function ( builder, output ) {
 			case ReflectNode.VECTOR:
 			case ReflectNode.VECTOR:
 
 
 				var viewNormalNode = builder.context.viewNormal || new NormalNode();
 				var viewNormalNode = builder.context.viewNormal || new NormalNode();
+				var roughnessNode = builder.context.roughness;
 
 
 				var viewNormal = viewNormalNode.build( builder, 'v3' );
 				var viewNormal = viewNormalNode.build( builder, 'v3' );
 				var viewPosition = new PositionNode( PositionNode.VIEW ).build( builder, 'v3' );
 				var viewPosition = new PositionNode( PositionNode.VIEW ).build( builder, 'v3' );
+				var roughness = roughnessNode ? roughnessNode.build( builder, 'f' ) : undefined;
 
 
-				var code = `inverseTransformDirection( reflect( -normalize( ${viewPosition} ), ${viewNormal} ), viewMatrix )`;
+				var method = `reflect( -normalize( ${viewPosition} ), ${viewNormal} )`;
+
+				if ( viewNormalNode && roughness ) {
+
+					// Mixing the reflection with the normal is more accurate and keeps rough objects from gathering light from behind their tangent plane.
+					method = `normalize( mix( ${method}, ${viewNormal}, ${roughness} * ${roughness} ) )`;
+
+				}
+
+				var code = `inverseTransformDirection( ${method}, viewMatrix )`;
 
 
 				if ( isUnique ) {
 				if ( isUnique ) {
 
 

+ 0 - 13
examples/jsm/nodes/bsdfs/BlinnExponentToRoughnessNode.d.ts

@@ -1,13 +0,0 @@
-import { TempNode } from '../core/TempNode';
-import { NodeBuilder } from '../core/NodeBuilder';
-import { BlinnShininessExponentNode } from './BlinnShininessExponentNode';
-
-export class BlinnExponentToRoughnessNode extends TempNode {
-  constructor(blinnExponent?: BlinnShininessExponentNode);
-
-  blinnExponent: BlinnShininessExponentNode;
-  nodeType: string;
-
-  generate(builder: NodeBuilder, output: string): string;
-  copy(source: BlinnExponentToRoughnessNode): this;
-}

+ 0 - 52
examples/jsm/nodes/bsdfs/BlinnExponentToRoughnessNode.js

@@ -1,52 +0,0 @@
-/**
- * @author sunag / http://www.sunag.com.br/
- */
-
-import { TempNode } from '../core/TempNode.js';
-import { BlinnShininessExponentNode } from './BlinnShininessExponentNode.js';
-
-function BlinnExponentToRoughnessNode( blinnExponent ) {
-
-	TempNode.call( this, 'f' );
-
-	this.blinnExponent = blinnExponent || new BlinnShininessExponentNode();
-
-}
-
-BlinnExponentToRoughnessNode.prototype = Object.create( TempNode.prototype );
-BlinnExponentToRoughnessNode.prototype.constructor = BlinnExponentToRoughnessNode;
-BlinnExponentToRoughnessNode.prototype.nodeType = "BlinnExponentToRoughness";
-
-BlinnExponentToRoughnessNode.prototype.generate = function ( builder, output ) {
-
-	return builder.format( 'BlinnExponentToGGXRoughness( ' + this.blinnExponent.build( builder, 'f' ) + ' )', this.type, output );
-
-};
-
-BlinnExponentToRoughnessNode.prototype.copy = function ( source ) {
-
-	TempNode.prototype.copy.call( this, source );
-
-	this.blinnExponent = source.blinnExponent;
-
-	return this;
-
-};
-
-BlinnExponentToRoughnessNode.prototype.toJSON = function ( meta ) {
-
-	var data = this.getJSONNode( meta );
-
-	if ( ! data ) {
-
-		data = this.createJSONNode( meta );
-
-		data.blinnExponent = this.blinnExponent;
-
-	}
-
-	return data;
-
-};
-
-export { BlinnExponentToRoughnessNode };

+ 0 - 10
examples/jsm/nodes/bsdfs/BlinnShininessExponentNode.d.ts

@@ -1,10 +0,0 @@
-import { TempNode } from '../core/TempNode';
-import { NodeBuilder } from '../core/NodeBuilder';
-
-export class BlinnShininessExponentNode extends TempNode {
-  constructor();
-
-  nodeType: string;
-
-  generate(builder: NodeBuilder, output: string): string;
-}

+ 0 - 31
examples/jsm/nodes/bsdfs/BlinnShininessExponentNode.js

@@ -1,31 +0,0 @@
-/**
- * @author sunag / http://www.sunag.com.br/
- */
-
-import { TempNode } from '../core/TempNode.js';
-
-function BlinnShininessExponentNode() {
-
-	TempNode.call( this, 'f' );
-
-}
-
-BlinnShininessExponentNode.prototype = Object.create( TempNode.prototype );
-BlinnShininessExponentNode.prototype.constructor = BlinnShininessExponentNode;
-BlinnShininessExponentNode.prototype.nodeType = "BlinnShininessExponent";
-
-BlinnShininessExponentNode.prototype.generate = function ( builder, output ) {
-
-	if ( builder.isCache( 'clearcoat' ) ) {
-
-		return builder.format( 'Material_Clearcoat_BlinnShininessExponent( material )', this.type, output );
-
-	} else {
-
-		return builder.format( 'Material_BlinnShininessExponent( material )', this.type, output );
-
-	}
-
-};
-
-export { BlinnShininessExponentNode };

+ 0 - 94
examples/jsm/nodes/bsdfs/RoughnessToBlinnExponentNode.js

@@ -1,94 +0,0 @@
-/**
- * @author sunag / http://www.sunag.com.br/
- */
-
-import { TempNode } from '../core/TempNode.js';
-import { FunctionNode } from '../core/FunctionNode.js';
-import { MaxMIPLevelNode } from '../utils/MaxMIPLevelNode.js';
-import { BlinnShininessExponentNode } from './BlinnShininessExponentNode.js';
-
-function RoughnessToBlinnExponentNode( texture ) {
-
-	TempNode.call( this, 'f' );
-
-	this.texture = texture;
-
-	this.maxMIPLevel = new MaxMIPLevelNode( texture );
-	this.blinnShininessExponent = new BlinnShininessExponentNode();
-
-}
-
-RoughnessToBlinnExponentNode.Nodes = ( function () {
-
-	var getSpecularMIPLevel = new FunctionNode( [
-		// taken from here: http://casual-effects.blogspot.ca/2011/08/plausible-environment-lighting-in-two.html
-		"float getSpecularMIPLevel( const in float blinnShininessExponent, const in float maxMIPLevelScalar ) {",
-
-		//	float envMapWidth = pow( 2.0, maxMIPLevelScalar );
-		//	float desiredMIPLevel = log2( envMapWidth * sqrt( 3.0 ) ) - 0.5 * log2( pow2( blinnShininessExponent ) + 1.0 );
-
-		"	float desiredMIPLevel = maxMIPLevelScalar + 0.79248 - 0.5 * log2( pow2( blinnShininessExponent ) + 1.0 );",
-
-		// clamp to allowable LOD ranges.
-		"	return clamp( desiredMIPLevel, 0.0, maxMIPLevelScalar );",
-
-		"}"
-	].join( "\n" ) );
-
-	return {
-		getSpecularMIPLevel: getSpecularMIPLevel
-	};
-
-} )();
-
-RoughnessToBlinnExponentNode.prototype = Object.create( TempNode.prototype );
-RoughnessToBlinnExponentNode.prototype.constructor = RoughnessToBlinnExponentNode;
-RoughnessToBlinnExponentNode.prototype.nodeType = "RoughnessToBlinnExponent";
-
-RoughnessToBlinnExponentNode.prototype.generate = function ( builder, output ) {
-
-	if ( builder.isShader( 'fragment' ) ) {
-
-		this.maxMIPLevel.texture = this.texture;
-
-		var getSpecularMIPLevel = builder.include( RoughnessToBlinnExponentNode.Nodes.getSpecularMIPLevel );
-
-		return builder.format( getSpecularMIPLevel + '( ' + this.blinnShininessExponent.build( builder, 'f' ) + ', ' + this.maxMIPLevel.build( builder, 'f' ) + ' )', this.type, output );
-
-	} else {
-
-		console.warn( "THREE.RoughnessToBlinnExponentNode is not compatible with " + builder.shader + " shader." );
-
-		return builder.format( '0.0', this.type, output );
-
-	}
-
-};
-
-RoughnessToBlinnExponentNode.prototype.copy = function ( source ) {
-
-	TempNode.prototype.copy.call( this, source );
-
-	this.texture = source.texture;
-
-	return this;
-
-};
-
-RoughnessToBlinnExponentNode.prototype.toJSON = function ( meta ) {
-
-	var data = this.getJSONNode( meta );
-
-	if ( ! data ) {
-
-		data = this.createJSONNode( meta );
-
-		data.texture = this.texture;
-
-	}
-
-	return data;
-
-};
-
-export { RoughnessToBlinnExponentNode };

+ 1 - 1
examples/jsm/nodes/inputs/CubeTextureNode.js

@@ -41,7 +41,7 @@ CubeTextureNode.prototype.generate = function ( builder, output ) {
 
 
 	if ( bias === undefined && builder.context.bias ) {
 	if ( bias === undefined && builder.context.bias ) {
 
 
-		bias = new builder.context.bias( this ).build( builder, 'f' );
+		bias = builder.context.bias.setTexture( this ).build( builder, 'f' );
 
 
 	}
 	}
 
 

+ 1 - 1
examples/jsm/nodes/inputs/TextureNode.js

@@ -42,7 +42,7 @@ TextureNode.prototype.generate = function ( builder, output ) {
 
 
 	if ( bias === undefined && builder.context.bias ) {
 	if ( bias === undefined && builder.context.bias ) {
 
 
-		bias = new builder.context.bias( this ).build( builder, 'f' );
+		bias = builder.context.bias.setTexture( this ).build( builder, 'f' );
 
 
 	}
 	}
 
 

+ 9 - 5
examples/jsm/nodes/materials/nodes/StandardNode.js

@@ -11,7 +11,7 @@ import { Node } from '../../core/Node.js';
 import { ExpressionNode } from '../../core/ExpressionNode.js';
 import { ExpressionNode } from '../../core/ExpressionNode.js';
 import { ColorNode } from '../../inputs/ColorNode.js';
 import { ColorNode } from '../../inputs/ColorNode.js';
 import { FloatNode } from '../../inputs/FloatNode.js';
 import { FloatNode } from '../../inputs/FloatNode.js';
-import { RoughnessToBlinnExponentNode } from '../../bsdfs/RoughnessToBlinnExponentNode.js';
+import { SpecularMIPLevelNode } from '../../utils/SpecularMIPLevelNode.js';
 
 
 function StandardNode() {
 function StandardNode() {
 
 
@@ -129,8 +129,12 @@ StandardNode.prototype.build = function ( builder ) {
 
 
 	} else {
 	} else {
 
 
+		var specularRoughness = new ExpressionNode('material.specularRoughness', 'f' );
+		var clearcoatRoughness = new ExpressionNode('material.clearcoatRoughness', 'f' );
+
 		var contextEnvironment = {
 		var contextEnvironment = {
-			bias: RoughnessToBlinnExponentNode,
+			roughness: specularRoughness,
+			bias: new SpecularMIPLevelNode( specularRoughness ),
 			viewNormal: new ExpressionNode('normal', 'v3'),
 			viewNormal: new ExpressionNode('normal', 'v3'),
 			gamma: true
 			gamma: true
 		};
 		};
@@ -140,7 +144,8 @@ StandardNode.prototype.build = function ( builder ) {
 		};
 		};
 
 
 		var contextClearcoatEnvironment = {
 		var contextClearcoatEnvironment = {
-			bias: RoughnessToBlinnExponentNode,
+			roughness: clearcoatRoughness,
+			bias: new SpecularMIPLevelNode( clearcoatRoughness ),
 			viewNormal: new ExpressionNode('clearcoatNormal', 'v3'),
 			viewNormal: new ExpressionNode('clearcoatNormal', 'v3'),
 			gamma: true
 			gamma: true
 		};
 		};
@@ -235,7 +240,6 @@ StandardNode.prototype.build = function ( builder ) {
 		builder.requires.transparent = alpha !== undefined;
 		builder.requires.transparent = alpha !== undefined;
 
 
 		builder.addParsCode( [
 		builder.addParsCode( [
-
 			"varying vec3 vViewPosition;",
 			"varying vec3 vViewPosition;",
 
 
 			"#ifndef FLAT_SHADED",
 			"#ifndef FLAT_SHADED",
@@ -457,7 +461,7 @@ StandardNode.prototype.build = function ( builder ) {
 
 
 			if ( builder.requires.irradiance ) {
 			if ( builder.requires.irradiance ) {
 
 
-				output.push( "irradiance += PI * " + environment.irradiance.result + ";" );
+				output.push( "iblIrradiance += PI * " + environment.irradiance.result + ";" );
 
 
 			}
 			}
 
 

+ 35 - 20
examples/jsm/nodes/misc/NormalMapNode.js

@@ -20,37 +20,52 @@ function NormalMapNode( value, scale ) {
 
 
 NormalMapNode.Nodes = ( function () {
 NormalMapNode.Nodes = ( function () {
 
 
-	var perturbNormal2Arb = new FunctionNode( [
+	var perturbNormal2Arb = new FunctionNode( 
 
 
-		// Per-Pixel Tangent Space Normal Mapping
-		// http://hacksoflife.blogspot.ch/2009/11/per-pixel-tangent-space-normal-mapping.html
+// Per-Pixel Tangent Space Normal Mapping
+// http://hacksoflife.blogspot.ch/2009/11/per-pixel-tangent-space-normal-mapping.html
+	
+`vec3 perturbNormal2Arb( vec3 eye_pos, vec3 surf_norm, vec3 map, vec2 vUv, vec2 normalScale ) {
 
 
-		"vec3 perturbNormal2Arb( vec3 eye_pos, vec3 surf_norm, vec3 map, vec2 mUv, vec2 normalScale ) {",
+	// Workaround for Adreno 3XX dFd*( vec3 ) bug. See #9988
 
 
-		// Workaround for Adreno 3XX dFd*( vec3 ) bug. See #9988
+	vec3 q0 = vec3( dFdx( eye_pos.x ), dFdx( eye_pos.y ), dFdx( eye_pos.z ) );
+	vec3 q1 = vec3( dFdy( eye_pos.x ), dFdy( eye_pos.y ), dFdy( eye_pos.z ) );
+	vec2 st0 = dFdx( vUv.st );
+	vec2 st1 = dFdy( vUv.st );
 
 
-		"	vec3 q0 = vec3( dFdx( eye_pos.x ), dFdx( eye_pos.y ), dFdx( eye_pos.z ) );",
-		"	vec3 q1 = vec3( dFdy( eye_pos.x ), dFdy( eye_pos.y ), dFdy( eye_pos.z ) );",
-		"	vec2 st0 = dFdx( mUv.st );",
-		"	vec2 st1 = dFdy( mUv.st );",
+	float scale = sign( st1.t * st0.s - st0.t * st1.s ); // we do not care about the magnitude
 
 
-		"	float scale = sign( st1.t * st0.s - st0.t * st1.s );", // we do not care about the magnitude
+	vec3 S = normalize( ( q0 * st1.t - q1 * st0.t ) * scale );
+	vec3 T = normalize( ( - q0 * st1.s + q1 * st0.s ) * scale );
+	vec3 N = normalize( surf_norm );
 
 
-		"	vec3 S = normalize( ( q0 * st1.t - q1 * st0.t ) * scale );",
-		"	vec3 T = normalize( ( - q0 * st1.s + q1 * st0.s ) * scale );",
-		"	vec3 N = normalize( surf_norm );",
-		"	mat3 tsn = mat3( S, T, N );",
+	vec3 mapN = map * 2.0 - 1.0;
 
 
-		"	vec3 mapN = map * 2.0 - 1.0;",
+	mapN.xy *= normalScale;
 
 
-		"	mapN.xy *= normalScale;",
-		"	mapN.xy *= ( float( gl_FrontFacing ) * 2.0 - 1.0 );",
+	#ifdef DOUBLE_SIDED
 
 
-		"	return normalize( tsn * mapN );",
+		// Workaround for Adreno GPUs gl_FrontFacing bug. See #15850 and #10331
+		// http://hacksoflife.blogspot.com/2009/11/per-pixel-tangent-space-normal-mapping.html?showComment=1522254677437#c5087545147696715943
+		vec3 NfromST = cross( S, T );
+		if( dot( NfromST, N ) > 0.0 ) {
 
 
-		"}"
+			S *= -1.0;
+			T *= -1.0;
 
 
-	].join( "\n" ), null, { derivatives: true } );
+		}
+
+	#else
+
+		mapN.xy *= ( float( gl_FrontFacing ) * 2.0 - 1.0 );
+
+	#endif
+
+	mat3 tsn = mat3( S, T, N );
+	return normalize( tsn * mapN );
+
+}`, null, { derivatives: true } );
 
 
 	return {
 	return {
 		perturbNormal2Arb: perturbNormal2Arb
 		perturbNormal2Arb: perturbNormal2Arb

+ 14 - 8
examples/jsm/nodes/misc/TextureCubeNode.js

@@ -9,26 +9,26 @@ import { TextureCubeUVNode } from './TextureCubeUVNode.js';
 import { ReflectNode } from '../accessors/ReflectNode.js';
 import { ReflectNode } from '../accessors/ReflectNode.js';
 import { NormalNode } from '../accessors/NormalNode.js';
 import { NormalNode } from '../accessors/NormalNode.js';
 import { ColorSpaceNode } from '../utils/ColorSpaceNode.js';
 import { ColorSpaceNode } from '../utils/ColorSpaceNode.js';
-import { BlinnExponentToRoughnessNode } from '../bsdfs/BlinnExponentToRoughnessNode.js';
+import { SpecularMIPLevelNode } from '../utils/SpecularMIPLevelNode.js';
 
 
 function TextureCubeNode( value, textureSize, uv, bias ) {
 function TextureCubeNode( value, textureSize, uv, bias ) {
 
 
 	TempNode.call( this, 'v4' );
 	TempNode.call( this, 'v4' );
 
 
 	this.value = value;
 	this.value = value;
-	this.textureSize = textureSize || new FloatNode( 1024 );
-	this.uv = uv || new ReflectNode( ReflectNode.VECTOR );
-	this.bias = bias || new BlinnExponentToRoughnessNode();
+
+	textureSize = textureSize || new FloatNode( 1024 );
 
 
 	this.radianceCache = { uv: new TextureCubeUVNode(
 	this.radianceCache = { uv: new TextureCubeUVNode(
-		this.uv,
-		this.textureSize,
-		this.bias
+		uv || new ReflectNode( ReflectNode.VECTOR ),
+		textureSize,
+		// bias should be replaced in builder.context in build process
+		bias
 	) };
 	) };
 
 
 	this.irradianceCache = { uv: new TextureCubeUVNode(
 	this.irradianceCache = { uv: new TextureCubeUVNode(
 		new NormalNode( NormalNode.WORLD ),
 		new NormalNode( NormalNode.WORLD ),
-		this.textureSize,
+		textureSize,
 		new FloatNode( 1 ).setReadonly( true )
 		new FloatNode( 1 ).setReadonly( true )
 	) };
 	) };
 
 
@@ -83,6 +83,12 @@ TextureCubeNode.prototype.generate = function ( builder, output ) {
 
 
 		builder.require( 'irradiance' );
 		builder.require( 'irradiance' );
 
 
+		if ( builder.context.bias ) {
+
+			builder.context.bias.setTexture( this );
+
+		}
+
 		var cache = builder.slot === 'irradiance' ? this.irradianceCache : this.radianceCache;
 		var cache = builder.slot === 'irradiance' ? this.irradianceCache : this.radianceCache;
 		var result = this.generateTextureCubeUV( builder, cache );
 		var result = this.generateTextureCubeUV( builder, cache );
 
 

+ 5 - 3
examples/jsm/nodes/misc/TextureCubeUVNode.js

@@ -7,13 +7,13 @@ import { ConstNode } from '../core/ConstNode.js';
 import { StructNode } from '../core/StructNode.js';
 import { StructNode } from '../core/StructNode.js';
 import { FunctionNode } from '../core/FunctionNode.js';
 import { FunctionNode } from '../core/FunctionNode.js';
 
 
-function TextureCubeUVNode( uv, textureSize, blinnExponentToRoughness ) {
+function TextureCubeUVNode( uv, textureSize, bias ) {
 
 
 	TempNode.call( this, 'TextureCubeUVData' ); // TextureCubeUVData is type as StructNode
 	TempNode.call( this, 'TextureCubeUVData' ); // TextureCubeUVData is type as StructNode
 
 
 	this.uv = uv;
 	this.uv = uv;
 	this.textureSize = textureSize;
 	this.textureSize = textureSize;
-	this.blinnExponentToRoughness = blinnExponentToRoughness;
+	this.bias = bias;
 
 
 }
 }
 
 
@@ -171,8 +171,10 @@ TextureCubeUVNode.prototype.generate = function ( builder, output ) {
 
 
 		var textureCubeUV = builder.include( TextureCubeUVNode.Nodes.textureCubeUV );
 		var textureCubeUV = builder.include( TextureCubeUVNode.Nodes.textureCubeUV );
 
 
+		var biasNode = this.bias || builder.context.bias;
+
 		return builder.format( textureCubeUV + '( ' + this.uv.build( builder, 'v3' ) + ', ' +
 		return builder.format( textureCubeUV + '( ' + this.uv.build( builder, 'v3' ) + ', ' +
-			this.blinnExponentToRoughness.build( builder, 'f' ) + ', ' +
+			biasNode.build( builder, 'f' ) + ', ' +
 			this.textureSize.build( builder, 'f' ) + ' )', this.getType( builder ), output );
 			this.textureSize.build( builder, 'f' ) + ' )', this.getType( builder ), output );
 
 
 	} else {
 	} else {

+ 2 - 4
examples/jsm/nodes/bsdfs/RoughnessToBlinnExponentNode.d.ts → examples/jsm/nodes/utils/SpecularMIPLevelNode.d..ts

@@ -1,19 +1,17 @@
 import { TempNode } from '../core/TempNode';
 import { TempNode } from '../core/TempNode';
 import { NodeBuilder } from '../core/NodeBuilder';
 import { NodeBuilder } from '../core/NodeBuilder';
 import { MaxMIPLevelNode } from '../utils/MaxMIPLevelNode';
 import { MaxMIPLevelNode } from '../utils/MaxMIPLevelNode';
-import { BlinnShininessExponentNode } from './BlinnShininessExponentNode';
 import { FunctionNode } from '../core/FunctionNode';
 import { FunctionNode } from '../core/FunctionNode';
 
 
-export class RoughnessToBlinnExponentNode extends TempNode {
+export class SpecularMIPLevelNode extends TempNode {
   constructor(texture: Node);
   constructor(texture: Node);
 
 
   texture: Node;
   texture: Node;
   maxMIPLevel: MaxMIPLevelNode;
   maxMIPLevel: MaxMIPLevelNode;
-  blinnShininessExponent: BlinnShininessExponentNode;
   nodeType: string;
   nodeType: string;
 
 
   generate(builder: NodeBuilder, output: string): string;
   generate(builder: NodeBuilder, output: string): string;
-  copy(source: RoughnessToBlinnExponentNode): this;
+  copy(source: SpecularMIPLevelNode): this;
 
 
   static Nodes: {
   static Nodes: {
     getSpecularMIPLevel: FunctionNode;
     getSpecularMIPLevel: FunctionNode;

+ 102 - 0
examples/jsm/nodes/utils/SpecularMIPLevelNode.js

@@ -0,0 +1,102 @@
+/**
+ * @author sunag / http://www.sunag.com.br/
+ */
+
+import { TempNode } from '../core/TempNode.js';
+import { FunctionNode } from '../core/FunctionNode.js';
+import { MaxMIPLevelNode } from './MaxMIPLevelNode.js';
+
+function SpecularMIPLevelNode( roughness, texture ) {
+
+	TempNode.call( this, 'f' );
+
+	this.roughness = roughness;
+	this.texture = texture;
+
+	this.maxMIPLevel = undefined;
+
+}
+
+SpecularMIPLevelNode.Nodes = ( function () {
+
+	var getSpecularMIPLevel = new FunctionNode( [
+		// taken from here: http://casual-effects.blogspot.ca/2011/08/plausible-environment-lighting-in-two.html
+		"float getSpecularMIPLevel( const in float roughness, const in float maxMIPLevelScalar ) {",
+
+		"	float sigma = PI * roughness * roughness / ( 1.0 + roughness );",
+		"	float desiredMIPLevel = maxMIPLevelScalar + log2( sigma );",
+
+		// clamp to allowable LOD ranges.
+		"	return clamp( desiredMIPLevel, 0.0, maxMIPLevelScalar );",
+
+		"}"
+	].join( "\n" ) );
+
+	return {
+		getSpecularMIPLevel: getSpecularMIPLevel
+	};
+
+} )();
+
+SpecularMIPLevelNode.prototype = Object.create( TempNode.prototype );
+SpecularMIPLevelNode.prototype.constructor = SpecularMIPLevelNode;
+SpecularMIPLevelNode.prototype.nodeType = "SpecularMIPLevel";
+
+SpecularMIPLevelNode.prototype.setTexture = function( texture ) {
+
+	this.texture = texture;
+
+	return this;
+
+};
+
+SpecularMIPLevelNode.prototype.generate = function ( builder, output ) {
+
+	if ( builder.isShader( 'fragment' ) ) {
+
+		this.maxMIPLevel = this.maxMIPLevel || new MaxMIPLevelNode();
+		this.maxMIPLevel.texture = this.texture;
+
+		var getSpecularMIPLevel = builder.include( SpecularMIPLevelNode.Nodes.getSpecularMIPLevel );
+
+		return builder.format( getSpecularMIPLevel + '( ' + this.roughness.build( builder, 'f' ) + ', ' + this.maxMIPLevel.build( builder, 'f' ) + ' )', this.type, output );
+
+	} else {
+
+		console.warn( "THREE.SpecularMIPLevelNode is not compatible with " + builder.shader + " shader." );
+
+		return builder.format( '0.0', this.type, output );
+
+	}
+
+};
+
+SpecularMIPLevelNode.prototype.copy = function ( source ) {
+
+	TempNode.prototype.copy.call( this, source );
+
+	this.texture = source.texture;
+	this.roughness = source.roughness;
+
+	return this;
+
+};
+
+SpecularMIPLevelNode.prototype.toJSON = function ( meta ) {
+
+	var data = this.getJSONNode( meta );
+
+	if ( ! data ) {
+
+		data = this.createJSONNode( meta );
+
+		data.texture = this.texture;
+		data.roughness = this.roughness;
+
+	}
+
+	return data;
+
+};
+
+export { SpecularMIPLevelNode };

+ 4 - 1
examples/main.css

@@ -10,7 +10,6 @@ body {
 a {
 a {
 	color: #ff0;
 	color: #ff0;
 	text-decoration: none;
 	text-decoration: none;
-	pointer-events: auto;
 }
 }
 
 
 a:hover {
 a:hover {
@@ -41,6 +40,10 @@ canvas {
 	z-index: 1; /* TODO Solve this in HTML */
 	z-index: 1; /* TODO Solve this in HTML */
 }
 }
 
 
+a, button, input, select {
+	pointer-events: auto;
+}
+
 .dg.ac {
 .dg.ac {
 	-moz-user-select: none;
 	-moz-user-select: none;
 	-webkit-user-select: none;
 	-webkit-user-select: none;

二进制
examples/textures/flakes.png


二进制
examples/textures/golfball.jpg


+ 35 - 13
examples/webgl_layers.html

@@ -93,26 +93,48 @@
 				stats = new Stats();
 				stats = new Stats();
 				container.appendChild( stats.dom );
 				container.appendChild( stats.dom );
 
 
-				var layers = { red: true, green: true, blue: true };
+				var layers = {
 
 
-				//
-				// Init gui
-				var gui = new GUI();
-				gui.add( layers, 'red' ).onChange( function () {
+					'toggle red': function() {
+
+						camera.layers.toggle( 0 );
+
+					},
+
+					'toggle green': function() {
+
+						camera.layers.toggle( 1 );
+
+					},
 
 
-					camera.layers.toggle( 0 );
+					'toggle blue': function() {
 
 
-				} );
-				gui.add( layers, 'green' ).onChange( function () {
+						camera.layers.toggle( 2 );
 
 
-					camera.layers.toggle( 1 );
+					},
 
 
-				} );
-				gui.add( layers, 'blue' ).onChange( function () {
+					'enable all': function() {
 
 
-					camera.layers.toggle( 2 );
+						camera.layers.enableAll();
 
 
-				} );
+					},
+
+					'disable all': function() {
+
+						camera.layers.disableAll();
+
+					}
+
+				};
+
+				//
+				// Init gui
+				var gui = new GUI();
+				gui.add( layers, 'toggle red' );
+				gui.add( layers, 'toggle green' );
+				gui.add( layers, 'toggle blue' );
+				gui.add( layers, 'enable all' );
+				gui.add( layers, 'disable all' );
 
 
 				window.addEventListener( 'resize', onWindowResize, false );
 				window.addEventListener( 'resize', onWindowResize, false );
 
 

+ 3 - 4
examples/webgl_lightningstrike.html

@@ -422,12 +422,11 @@
 
 
 				var sphereMaterial = new THREE.MeshPhysicalMaterial( {
 				var sphereMaterial = new THREE.MeshPhysicalMaterial( {
 					transparent: true,
 					transparent: true,
+					transparency: .96,
 					depthWrite: false,
 					depthWrite: false,
-					opacity: 0.15,
-					color: 0,
-					metalness: 1,
+					color: 'white',
+					metalness: 0,
 					roughness: 0,
 					roughness: 0,
-					reflectivity: 0,
 					envMap: textureCube
 					envMap: textureCube
 				} );
 				} );
 
 

+ 3 - 2
examples/webgl_materials_cars.html

@@ -140,10 +140,11 @@
 
 
 			function initCar() {
 			function initCar() {
 
 
-				DRACOLoader.setDecoderPath( 'js/libs/draco/gltf/' );
+				var dracoLoader = new DRACOLoader();
+				dracoLoader.setDecoderPath( 'js/libs/draco/gltf/' );
 
 
 				var loader = new GLTFLoader();
 				var loader = new GLTFLoader();
-				loader.setDRACOLoader( new DRACOLoader() );
+				loader.setDRACOLoader( dracoLoader );
 
 
 				loader.load( 'models/gltf/ferrari.glb', function ( gltf ) {
 				loader.load( 'models/gltf/ferrari.glb', function ( gltf ) {
 
 

+ 2 - 2
examples/webgl_materials_nodes.html

@@ -582,7 +582,7 @@
 						subSlotNode.slots['radiance'] = new Nodes.OperatorNode( radiance, envNode, Nodes.OperatorNode.MUL );
 						subSlotNode.slots['radiance'] = new Nodes.OperatorNode( radiance, envNode, Nodes.OperatorNode.MUL );
 						subSlotNode.slots['irradiance'] = new Nodes.OperatorNode( irradiance, envNode, Nodes.OperatorNode.MUL );
 						subSlotNode.slots['irradiance'] = new Nodes.OperatorNode( irradiance, envNode, Nodes.OperatorNode.MUL );
 
 
-						mtl.environment = subSlotNode
+						mtl.environment = subSlotNode;
 
 
 						// GUI
 						// GUI
 
 
@@ -2488,7 +2488,7 @@
 						// MATERIAL
 						// MATERIAL
 
 
 						var bias = new Nodes.FloatNode( .5 );
 						var bias = new Nodes.FloatNode( .5 );
-						var maxMIPLevel = new Nodes.MaxMIPLevelNode( new Nodes.TextureCubeNode( cubemap ) );
+						var maxMIPLevel = new Nodes.MaxMIPLevelNode( new Nodes.TextureNode( cubemap ) );
 						var mipsBias = new Nodes.OperatorNode( bias, maxMIPLevel, Nodes.OperatorNode.MUL );
 						var mipsBias = new Nodes.OperatorNode( bias, maxMIPLevel, Nodes.OperatorNode.MUL );
 
 
 						mtl = new Nodes.PhongNodeMaterial();
 						mtl = new Nodes.PhongNodeMaterial();

+ 31 - 10
examples/webgl_materials_clearcoat_normalmap.html → examples/webgl_materials_physical_clearcoat.html

@@ -2,7 +2,7 @@
 <html lang="en">
 <html lang="en">
 
 
 <head>
 <head>
-	<title>three.js webgl - materials - clearcoat normal</title>
+	<title>three.js webgl - materials - clearcoat</title>
 	<meta charset="utf-8">
 	<meta charset="utf-8">
 	<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
 	<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
 	<link type="text/css" rel="stylesheet" href="main.css">
 	<link type="text/css" rel="stylesheet" href="main.css">
@@ -10,7 +10,7 @@
 
 
 <body>
 <body>
 	<div id="info">
 	<div id="info">
-		<a href="https://threejs.org" target="_blank" rel="noopener">three.js</a> - webgl - materials - clearcoat normal map
+		<a href="https://threejs.org" target="_blank" rel="noopener">three.js</a> webgl - materials - clearcoat
 	</div>
 	</div>
 
 
 	<script type="module">
 	<script type="module">
@@ -66,6 +66,7 @@
 						var textureLoader = new THREE.TextureLoader();
 						var textureLoader = new THREE.TextureLoader();
 
 
 						var diffuse = textureLoader.load( "textures/carbon/Carbon.png" );
 						var diffuse = textureLoader.load( "textures/carbon/Carbon.png" );
+						diffuse.encoding = THREE.sRGBEncoding;
 						diffuse.wrapS = THREE.RepeatWrapping;
 						diffuse.wrapS = THREE.RepeatWrapping;
 						diffuse.wrapT = THREE.RepeatWrapping;
 						diffuse.wrapT = THREE.RepeatWrapping;
 						diffuse.repeat.x = 10;
 						diffuse.repeat.x = 10;
@@ -77,14 +78,28 @@
 
 
 						var normalMap2 = textureLoader.load( "textures/water/Water_1_M_Normal.jpg" );
 						var normalMap2 = textureLoader.load( "textures/water/Water_1_M_Normal.jpg" );
 
 
+						var normalMap3 = textureLoader.load( "textures/flakes.png" );
+						normalMap3.wrapS = THREE.RepeatWrapping;
+						normalMap3.wrapT = THREE.RepeatWrapping;
+						normalMap3.repeat.x = 10;
+						normalMap3.repeat.y = 10;
+						normalMap3.anisotropy = 16;
+
+						var normalMap4 = textureLoader.load( "textures/golfball.jpg" );
+
 						var clearcoatNormaMap = textureLoader.load( "textures/pbr/Scratched_gold/Scratched_gold_01_1K_Normal.png" );
 						var clearcoatNormaMap = textureLoader.load( "textures/pbr/Scratched_gold/Scratched_gold_01_1K_Normal.png" );
 
 
-						//
+						// car paint
 
 
 						var material = new THREE.MeshPhysicalMaterial( {
 						var material = new THREE.MeshPhysicalMaterial( {
 							clearcoat: 1.0,
 							clearcoat: 1.0,
+							clearcoatRoughness: 0.1,
+							metalness: 0.9,
+							roughness: 0.5,
+							color: 0x0000ff,
 							envMap: hdrCubeRenderTarget.texture,
 							envMap: hdrCubeRenderTarget.texture,
-							map: diffuse
+							normalMap: normalMap3,
+							normalScale: new THREE.Vector2( 0.1, 0.1 )
 						} );
 						} );
 
 
 						var mesh = new THREE.Mesh( geometry, material );
 						var mesh = new THREE.Mesh( geometry, material );
@@ -92,10 +107,11 @@
 						mesh.position.y = 100;
 						mesh.position.y = 100;
 						group.add( mesh );
 						group.add( mesh );
 
 
-						// normalmap
+						// fibers
 
 
 						var material = new THREE.MeshPhysicalMaterial( {
 						var material = new THREE.MeshPhysicalMaterial( {
 							clearcoat: 1.0,
 							clearcoat: 1.0,
+							clearcoatRoughness: 0.1,
 							envMap: hdrCubeRenderTarget.texture,
 							envMap: hdrCubeRenderTarget.texture,
 							map: diffuse,
 							map: diffuse,
 							normalMap: normalMap
 							normalMap: normalMap
@@ -105,12 +121,13 @@
 						mesh.position.y = 100;
 						mesh.position.y = 100;
 						group.add( mesh );
 						group.add( mesh );
 
 
-						// clearcoat
+						// golf
 
 
 						var material = new THREE.MeshPhysicalMaterial( {
 						var material = new THREE.MeshPhysicalMaterial( {
-							clearcoat: 1.0,
 							metalness: 0.0,
 							metalness: 0.0,
-							color: 0xff0000,
+							roughness: 0.1,
+							clearcoat: 1.0,
+							normalMap: normalMap4,
 							envMap: hdrCubeRenderTarget.texture,
 							envMap: hdrCubeRenderTarget.texture,
 							clearcoatNormalMap: clearcoatNormaMap,
 							clearcoatNormalMap: clearcoatNormaMap,
 							clearcoatNormalScale: new THREE.Vector2( 2.0, 2.0 )
 							clearcoatNormalScale: new THREE.Vector2( 2.0, 2.0 )
@@ -158,7 +175,7 @@
 			);
 			);
 			scene.add( particleLight );
 			scene.add( particleLight );
 
 
-			particleLight.add( new THREE.PointLight( 0xffffff, 1.25 ) );
+			particleLight.add( new THREE.PointLight( 0xffffff, 1 ) );
 
 
 			renderer = new THREE.WebGLRenderer();
 			renderer = new THREE.WebGLRenderer();
 			renderer.setPixelRatio( window.devicePixelRatio );
 			renderer.setPixelRatio( window.devicePixelRatio );
@@ -167,7 +184,11 @@
 
 
 			//
 			//
 
 
-			renderer.gammaInput = true;
+			renderer.toneMapping = THREE.ACESFilmicToneMapping;
+			renderer.toneMappingExposure = 1;
+
+			//
+
 			renderer.gammaOutput = true;
 			renderer.gammaOutput = true;
 
 
 			//
 			//

+ 0 - 0
examples/webgl_materials_sheen.html → examples/webgl_materials_physical_sheen.html


+ 0 - 0
examples/webgl_materials_transparency.html → examples/webgl_materials_physical_transparency.html


+ 2 - 4
examples/webgl_shaders_sky.html

@@ -65,10 +65,10 @@
 					var uniforms = sky.material.uniforms;
 					var uniforms = sky.material.uniforms;
 					uniforms[ "turbidity" ].value = effectController.turbidity;
 					uniforms[ "turbidity" ].value = effectController.turbidity;
 					uniforms[ "rayleigh" ].value = effectController.rayleigh;
 					uniforms[ "rayleigh" ].value = effectController.rayleigh;
-					uniforms[ "luminance" ].value = effectController.luminance;
 					uniforms[ "mieCoefficient" ].value = effectController.mieCoefficient;
 					uniforms[ "mieCoefficient" ].value = effectController.mieCoefficient;
 					uniforms[ "mieDirectionalG" ].value = effectController.mieDirectionalG;
 					uniforms[ "mieDirectionalG" ].value = effectController.mieDirectionalG;
-
+					uniforms[ "luminance" ].value = effectController.luminance;
+					
 					var theta = Math.PI * ( effectController.inclination - 0.5 );
 					var theta = Math.PI * ( effectController.inclination - 0.5 );
 					var phi = 2 * Math.PI * ( effectController.azimuth - 0.5 );
 					var phi = 2 * Math.PI * ( effectController.azimuth - 0.5 );
 
 
@@ -104,8 +104,6 @@
 				camera = new THREE.PerspectiveCamera( 60, window.innerWidth / window.innerHeight, 100, 2000000 );
 				camera = new THREE.PerspectiveCamera( 60, window.innerWidth / window.innerHeight, 100, 2000000 );
 				camera.position.set( 0, 100, 2000 );
 				camera.position.set( 0, 100, 2000 );
 
 
-				//camera.setLens(20);
-
 				scene = new THREE.Scene();
 				scene = new THREE.Scene();
 
 
 				var helper = new THREE.GridHelper( 10000, 2, 0xffffff, 0xffffff );
 				var helper = new THREE.GridHelper( 10000, 2, 0xffffff, 0xffffff );

+ 222 - 0
examples/webgl_shadowmap_vsm.html

@@ -0,0 +1,222 @@
+<!DOCTYPE html>
+<html lang="en">
+	<head>
+		<title>three.js webgl - VSM Shadows example </title>
+		<meta charset="utf-8">
+		<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
+		<link type="text/css" rel="stylesheet" href="main.css">
+	</head>
+	<body>
+		<div id="info">
+		<a href="http://threejs.org" target="_blank" rel="noopener">three.js</a> - VSM Shadows example by <a href="https://github.com/supereggbert">Paul Brunt</a>
+		</div>
+
+		<script type="module">
+
+			import * as THREE from '../build/three.module.js';
+
+			import Stats from './jsm/libs/stats.module.js';
+			import { GUI } from './jsm/libs/dat.gui.module.js';
+
+			import { OrbitControls } from './jsm/controls/OrbitControls.js';
+
+			var camera, scene, renderer, clock, stats;
+			var dirLight, spotLight;
+			var torusKnot, dirGroup;
+
+			init();
+			animate();
+
+			function init() {
+
+				initScene();
+				initMisc();
+				
+				// Init gui
+				var gui = new GUI();
+
+				var config = {
+					'Spotlight Radius': 4,
+					'Directional light Radius': 4,
+				};
+
+				gui.add( config, 'Spotlight Radius' ).min( 2 ).max( 8 ).onChange( function ( value ) {
+
+					spotLight.shadow.radius = value;
+
+				} );
+
+				gui.add( config, 'Directional light Radius' ).min( 2 ).max( 8 ).onChange( function ( value ) {
+
+					dirLight.shadow.radius = value;
+
+				} );
+
+				document.body.appendChild( renderer.domElement );
+				window.addEventListener( 'resize', onWindowResize, false );
+
+			}
+
+			function initScene() {
+
+				camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 1, 1000 );
+				camera.position.set( 0, 10, 30 );
+
+				scene = new THREE.Scene();
+				scene.fog = new THREE.Fog( 0xCCCCCC, 50, 100 );
+
+				// Lights
+
+				scene.add( new THREE.AmbientLight( 0x444444 ) );
+
+				spotLight = new THREE.SpotLight( 0x888888 );
+				spotLight.name = 'Spot Light';
+				spotLight.angle = Math.PI / 5;
+				spotLight.penumbra = 0.3;
+				spotLight.position.set( 8, 10, 5 );
+				spotLight.castShadow = true;
+				spotLight.shadow.camera.near = 8;
+				spotLight.shadow.camera.far = 200;
+				spotLight.shadow.mapSize.width = 256;
+				spotLight.shadow.mapSize.height = 256;
+				spotLight.shadow.bias = -0.002;
+				spotLight.shadow.radius = 4;
+				scene.add( spotLight );
+
+
+				dirLight = new THREE.DirectionalLight( 0xFFFFFF, 1 );
+				dirLight.name = 'Dir. Light';
+				dirLight.position.set( 3, 12, 17 );
+				dirLight.castShadow = true;
+				dirLight.shadow.camera.near = 0.1;
+				dirLight.shadow.camera.far = 500;
+				dirLight.shadow.camera.right = 17;
+				dirLight.shadow.camera.left = - 17;
+				dirLight.shadow.camera.top	= 17;
+				dirLight.shadow.camera.bottom = - 17;
+				dirLight.shadow.mapSize.width = 512;
+				dirLight.shadow.mapSize.height = 512;
+				dirLight.shadow.radius = 4;
+				dirLight.shadow.bias = -0.0005;
+				scene.add( dirLight );
+
+				dirGroup = new THREE.Group();
+				dirGroup.add( dirLight );
+				scene.add( dirGroup );
+
+				// Geometry
+
+				var geometry = new THREE.TorusKnotBufferGeometry( 25, 8, 75, 20 );
+				var material = new THREE.MeshPhongMaterial( {
+					color: 0x999999,
+					shininess: 0,
+					specular: 0x222222
+				} );
+
+				torusKnot = new THREE.Mesh( geometry, material );
+				torusKnot.scale.multiplyScalar( 1 / 18 );
+				torusKnot.position.y = 3;
+				torusKnot.castShadow = true;
+				torusKnot.receiveShadow = true;
+				scene.add( torusKnot );
+
+				var geometry = new THREE.CylinderBufferGeometry( 0.75, 0.75, 7, 32 );
+
+				var pillar1 = new THREE.Mesh( geometry, material );
+				pillar1.position.set( 10, 3.5, 10 );
+				pillar1.castShadow = true;
+				pillar1.receiveShadow = true;
+
+				var pillar2 = pillar1.clone();
+				pillar2.position.set( 10, 3.5, -10 );
+				var pillar3 = pillar1.clone();
+				pillar3.position.set( -10, 3.5, 10 );
+				var pillar4 = pillar1.clone();
+				pillar4.position.set( -10, 3.5, -10 );
+
+				scene.add( pillar1 );
+				scene.add( pillar2 );
+				scene.add( pillar3 );
+				scene.add( pillar4 );
+
+				var geometry = new THREE.PlaneBufferGeometry( 200, 200 );
+				var material = new THREE.MeshPhongMaterial( {
+					color: 0x999999,
+					shininess: 0,
+					specular: 0x111111
+				} );
+
+				var ground = new THREE.Mesh( geometry, material );
+				ground.rotation.x = -Math.PI/2;
+				ground.scale.multiplyScalar( 3 );
+				ground.castShadow = true;
+				ground.receiveShadow = true;
+				scene.add( ground );
+
+			}
+
+			function initMisc() {
+
+				renderer = new THREE.WebGLRenderer( { antialias: true } );
+				renderer.setPixelRatio( window.devicePixelRatio );
+				renderer.setSize( window.innerWidth, window.innerHeight );
+				renderer.shadowMap.enabled = true;
+				renderer.shadowMap.type = THREE.VSMShadowMap;		
+
+				renderer.setClearColor( 0xCCCCCC, 1 );
+
+				// Mouse control
+				var controls = new OrbitControls( camera, renderer.domElement );
+				controls.target.set( 0, 2, 0 );
+				controls.update();
+
+				clock = new THREE.Clock();
+
+				stats = new Stats();
+				document.body.appendChild( stats.dom );
+
+			}
+
+			function onWindowResize() {
+
+				camera.aspect = window.innerWidth / window.innerHeight;
+				camera.updateProjectionMatrix();
+
+				renderer.setSize( window.innerWidth, window.innerHeight );
+
+			}
+
+			function animate() {
+
+				requestAnimationFrame( animate );
+				render();
+
+				stats.update();
+
+			}
+
+			function renderScene() {
+
+				renderer.render( scene, camera );
+
+			}
+
+			function render() {
+
+				var delta = clock.getDelta();
+				var time = clock.elapsedTime;
+
+				renderScene();
+
+				torusKnot.rotation.x += 0.25 * delta;
+				torusKnot.rotation.y += 2 * delta;
+				torusKnot.rotation.z += 1 * delta;
+
+				dirGroup.rotation.y += 0.7 * delta;
+				dirLight.position.z = 17 + Math.sin(time*0.001)*5;
+
+			}
+
+		</script>
+	</body>
+</html>

+ 1 - 0
files/main.css

@@ -254,6 +254,7 @@ h1 a {
 		flex: 1;
 		flex: 1;
 		overflow-y: auto;
 		overflow-y: auto;
 		overflow-x: hidden;
 		overflow-x: hidden;
+		-webkit-overflow-scrolling: touch;
 		padding: 0 var(--panel-padding) var(--panel-padding) var(--panel-padding);
 		padding: 0 var(--panel-padding) var(--panel-padding) var(--panel-padding);
 	}
 	}
 
 

+ 1 - 1
package.json

@@ -1,6 +1,6 @@
 {
 {
   "name": "three",
   "name": "three",
-  "version": "0.107.0",
+  "version": "0.108.0",
   "description": "JavaScript 3D library",
   "description": "JavaScript 3D library",
   "main": "build/three.js",
   "main": "build/three.js",
   "repository": "mrdoob/three.js",
   "repository": "mrdoob/three.js",

+ 1 - 0
src/constants.d.ts

@@ -33,6 +33,7 @@ export enum ShadowMapType {}
 export const BasicShadowMap: ShadowMapType;
 export const BasicShadowMap: ShadowMapType;
 export const PCFShadowMap: ShadowMapType;
 export const PCFShadowMap: ShadowMapType;
 export const PCFSoftShadowMap: ShadowMapType;
 export const PCFSoftShadowMap: ShadowMapType;
+export const VSMShadowMap: ShadowMapType;
 
 
 // MATERIAL CONSTANTS
 // MATERIAL CONSTANTS
 
 

+ 2 - 1
src/constants.js

@@ -1,4 +1,4 @@
-export var REVISION = '108dev';
+export var REVISION = '109dev';
 export var MOUSE = { LEFT: 0, MIDDLE: 1, RIGHT: 2, ROTATE: 0, DOLLY: 1, PAN: 2 };
 export var MOUSE = { LEFT: 0, MIDDLE: 1, RIGHT: 2, ROTATE: 0, DOLLY: 1, PAN: 2 };
 export var TOUCH = { ROTATE: 0, PAN: 1, DOLLY_PAN: 2, DOLLY_ROTATE: 3 };
 export var TOUCH = { ROTATE: 0, PAN: 1, DOLLY_PAN: 2, DOLLY_ROTATE: 3 };
 export var CullFaceNone = 0;
 export var CullFaceNone = 0;
@@ -10,6 +10,7 @@ export var FrontFaceDirectionCCW = 1;
 export var BasicShadowMap = 0;
 export var BasicShadowMap = 0;
 export var PCFShadowMap = 1;
 export var PCFShadowMap = 1;
 export var PCFSoftShadowMap = 2;
 export var PCFSoftShadowMap = 2;
+export var VSMShadowMap = 3;
 export var FrontSide = 0;
 export var FrontSide = 0;
 export var BackSide = 1;
 export var BackSide = 1;
 export var DoubleSide = 2;
 export var DoubleSide = 2;

+ 2 - 0
src/core/Layers.d.ts

@@ -6,8 +6,10 @@ export class Layers {
 
 
 	set( channel: number ): void;
 	set( channel: number ): void;
 	enable( channel: number ): void;
 	enable( channel: number ): void;
+	enableAll(): void;
 	toggle( channel: number ): void;
 	toggle( channel: number ): void;
 	disable( channel: number ): void;
 	disable( channel: number ): void;
+	disableAll(): void;
 	test( layers: Layers ): boolean;
 	test( layers: Layers ): boolean;
 
 
 }
 }

+ 12 - 0
src/core/Layers.js

@@ -22,6 +22,12 @@ Object.assign( Layers.prototype, {
 
 
 	},
 	},
 
 
+	enableAll: function () {
+
+		this.mask = 0xffffffff | 0;
+
+	},
+
 	toggle: function ( channel ) {
 	toggle: function ( channel ) {
 
 
 		this.mask ^= 1 << channel | 0;
 		this.mask ^= 1 << channel | 0;
@@ -34,6 +40,12 @@ Object.assign( Layers.prototype, {
 
 
 	},
 	},
 
 
+	disableAll: function () {
+
+		this.mask = 0;
+
+	},
+
 	test: function ( layers ) {
 	test: function ( layers ) {
 
 
 		return ( this.mask & layers.mask ) !== 0;
 		return ( this.mask & layers.mask ) !== 0;

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

@@ -14,6 +14,7 @@ export class LightShadow {
 	radius: number;
 	radius: number;
 	mapSize: Vector2;
 	mapSize: Vector2;
 	map: RenderTarget;
 	map: RenderTarget;
+	mapPass: RenderTarget;
 	matrix: Matrix4;
 	matrix: Matrix4;
 
 
 	copy( source: LightShadow ): this;
 	copy( source: LightShadow ): this;

+ 1 - 0
src/lights/LightShadow.js

@@ -18,6 +18,7 @@ function LightShadow( camera ) {
 	this.mapSize = new Vector2( 512, 512 );
 	this.mapSize = new Vector2( 512, 512 );
 
 
 	this.map = null;
 	this.map = null;
+	this.mapPass = null;
 	this.matrix = new Matrix4();
 	this.matrix = new Matrix4();
 
 
 	this._frustum = new Frustum();
 	this._frustum = new Frustum();

+ 3 - 1
src/renderers/WebGLRenderTarget.d.ts

@@ -1,5 +1,6 @@
 import { Vector4 } from './../math/Vector4';
 import { Vector4 } from './../math/Vector4';
 import { Texture } from './../textures/Texture';
 import { Texture } from './../textures/Texture';
+import { DepthTexture } from './../textures/DepthTexture';
 import { EventDispatcher } from './../core/EventDispatcher';
 import { EventDispatcher } from './../core/EventDispatcher';
 import { Wrapping, TextureFilter, TextureDataType } from '../constants';
 import { Wrapping, TextureFilter, TextureDataType } from '../constants';
 
 
@@ -14,6 +15,7 @@ export interface WebGLRenderTargetOptions {
 	depthBuffer?: boolean; // true;
 	depthBuffer?: boolean; // true;
 	stencilBuffer?: boolean; // true;
 	stencilBuffer?: boolean; // true;
 	generateMipmaps?: boolean; // true;
 	generateMipmaps?: boolean; // true;
+	depthTexture?: DepthTexture;
 }
 }
 
 
 export class WebGLRenderTarget extends EventDispatcher {
 export class WebGLRenderTarget extends EventDispatcher {
@@ -33,7 +35,7 @@ export class WebGLRenderTarget extends EventDispatcher {
 	texture: Texture;
 	texture: Texture;
 	depthBuffer: boolean;
 	depthBuffer: boolean;
 	stencilBuffer: boolean;
 	stencilBuffer: boolean;
-	depthTexture: Texture;
+	depthTexture: DepthTexture;
 	/**
 	/**
 	 * @deprecated Use {@link Texture#wrapS texture.wrapS} instead.
 	 * @deprecated Use {@link Texture#wrapS texture.wrapS} instead.
 	 */
 	 */

+ 11 - 9
src/renderers/shaders/ShaderChunk/envmap_physical_pars_fragment.glsl.js

@@ -44,26 +44,28 @@ export default /* glsl */`
 
 
 	}
 	}
 
 
-	// taken from here: http://casual-effects.blogspot.ca/2011/08/plausible-environment-lighting-in-two.html
-	float getSpecularMIPLevel( const in float blinnShininessExponent, const in int maxMIPLevel ) {
-
-		//float envMapWidth = pow( 2.0, maxMIPLevelScalar );
-		//float desiredMIPLevel = log2( envMapWidth * sqrt( 3.0 ) ) - 0.5 * log2( pow2( blinnShininessExponent ) + 1.0 );
+	// Trowbridge-Reitz distribution to Mip level, following the logic of http://casual-effects.blogspot.ca/2011/08/plausible-environment-lighting-in-two.html
+	float getSpecularMIPLevel( const in float roughness, const in int maxMIPLevel ) {
 
 
 		float maxMIPLevelScalar = float( maxMIPLevel );
 		float maxMIPLevelScalar = float( maxMIPLevel );
-		float desiredMIPLevel = maxMIPLevelScalar + 0.79248 - 0.5 * log2( pow2( blinnShininessExponent ) + 1.0 );
+
+		float sigma = PI * roughness * roughness / ( 1.0 + roughness );
+		float desiredMIPLevel = maxMIPLevelScalar + log2( sigma );
 
 
 		// clamp to allowable LOD ranges.
 		// clamp to allowable LOD ranges.
 		return clamp( desiredMIPLevel, 0.0, maxMIPLevelScalar );
 		return clamp( desiredMIPLevel, 0.0, maxMIPLevelScalar );
 
 
 	}
 	}
 
 
-	vec3 getLightProbeIndirectRadiance( /*const in SpecularLightProbe specularLightProbe,*/ const in vec3 viewDir, const in vec3 normal, const in float blinnShininessExponent, const in int maxMIPLevel ) {
+	vec3 getLightProbeIndirectRadiance( /*const in SpecularLightProbe specularLightProbe,*/ const in vec3 viewDir, const in vec3 normal, const in float roughness, const in int maxMIPLevel ) {
 
 
 		#ifdef ENVMAP_MODE_REFLECTION
 		#ifdef ENVMAP_MODE_REFLECTION
 
 
 		  vec3 reflectVec = reflect( -viewDir, normal );
 		  vec3 reflectVec = reflect( -viewDir, normal );
 
 
+		  // Mixing the reflection with the normal is more accurate and keeps rough objects from gathering light from behind their tangent plane.
+		  reflectVec = normalize( mix( reflectVec, normal, roughness * roughness) );
+
 		#else
 		#else
 
 
 		  vec3 reflectVec = refract( -viewDir, normal, refractionRatio );
 		  vec3 reflectVec = refract( -viewDir, normal, refractionRatio );
@@ -72,7 +74,7 @@ export default /* glsl */`
 
 
 		reflectVec = inverseTransformDirection( reflectVec, viewMatrix );
 		reflectVec = inverseTransformDirection( reflectVec, viewMatrix );
 
 
-		float specularMIPLevel = getSpecularMIPLevel( blinnShininessExponent, maxMIPLevel );
+		float specularMIPLevel = getSpecularMIPLevel( roughness, maxMIPLevel );
 
 
 		#ifdef ENVMAP_TYPE_CUBE
 		#ifdef ENVMAP_TYPE_CUBE
 
 
@@ -93,7 +95,7 @@ export default /* glsl */`
 		#elif defined( ENVMAP_TYPE_CUBE_UV )
 		#elif defined( ENVMAP_TYPE_CUBE_UV )
 
 
 			vec3 queryReflectVec = vec3( flipEnvMap * reflectVec.x, reflectVec.yz );
 			vec3 queryReflectVec = vec3( flipEnvMap * reflectVec.x, reflectVec.yz );
-			vec4 envMapColor = textureCubeUV( envMap, queryReflectVec, BlinnExponentToGGXRoughness(blinnShininessExponent ));
+			vec4 envMapColor = textureCubeUV( envMap, queryReflectVec, roughness );
 
 
 		#elif defined( ENVMAP_TYPE_EQUIREC )
 		#elif defined( ENVMAP_TYPE_EQUIREC )
 
 

+ 2 - 0
src/renderers/shaders/ShaderChunk/lights_fragment_begin.glsl.js

@@ -107,6 +107,8 @@ IncidentLight directLight;
 
 
 #if defined( RE_IndirectDiffuse )
 #if defined( RE_IndirectDiffuse )
 
 
+	vec3 iblIrradiance = vec3( 0.0 );
+
 	vec3 irradiance = getAmbientLightIrradiance( ambientLightColor );
 	vec3 irradiance = getAmbientLightIrradiance( ambientLightColor );
 
 
 	irradiance += getLightProbeIrradiance( lightProbe, geometry );
 	irradiance += getLightProbeIrradiance( lightProbe, geometry );

+ 1 - 1
src/renderers/shaders/ShaderChunk/lights_fragment_end.glsl.js

@@ -7,7 +7,7 @@ export default /* glsl */`
 
 
 #if defined( RE_IndirectSpecular )
 #if defined( RE_IndirectSpecular )
 
 
-	RE_IndirectSpecular( radiance, irradiance, clearcoatRadiance, geometry, material, reflectedLight );
+	RE_IndirectSpecular( radiance, iblIrradiance, clearcoatRadiance, geometry, material, reflectedLight );
 
 
 #endif
 #endif
 `;
 `;

+ 3 - 3
src/renderers/shaders/ShaderChunk/lights_fragment_maps.glsl.js

@@ -17,7 +17,7 @@ export default /* glsl */`
 
 
 	#if defined( USE_ENVMAP ) && defined( STANDARD ) && defined( ENVMAP_TYPE_CUBE_UV )
 	#if defined( USE_ENVMAP ) && defined( STANDARD ) && defined( ENVMAP_TYPE_CUBE_UV )
 
 
-		irradiance += getLightProbeIndirectIrradiance( /*lightProbe,*/ geometry, maxMipLevel );
+		iblIrradiance += getLightProbeIndirectIrradiance( /*lightProbe,*/ geometry, maxMipLevel );
 
 
 	#endif
 	#endif
 
 
@@ -25,11 +25,11 @@ export default /* glsl */`
 
 
 #if defined( USE_ENVMAP ) && defined( RE_IndirectSpecular )
 #if defined( USE_ENVMAP ) && defined( RE_IndirectSpecular )
 
 
-	radiance += getLightProbeIndirectRadiance( /*specularLightProbe,*/ geometry.viewDir, geometry.normal, Material_BlinnShininessExponent( material ), maxMipLevel );
+	radiance += getLightProbeIndirectRadiance( /*specularLightProbe,*/ geometry.viewDir, geometry.normal, material.specularRoughness, maxMipLevel );
 
 
 	#ifdef CLEARCOAT
 	#ifdef CLEARCOAT
 
 
-		clearcoatRadiance += getLightProbeIndirectRadiance( /*specularLightProbe,*/ geometry.viewDir, geometry.clearcoatNormal, Material_Clearcoat_BlinnShininessExponent( material ), maxMipLevel );
+		clearcoatRadiance += getLightProbeIndirectRadiance( /*specularLightProbe,*/ geometry.viewDir, geometry.clearcoatNormal, material.clearcoatRoughness, maxMipLevel );
 
 
 	#endif
 	#endif
 
 

+ 4 - 6
src/renderers/shaders/ShaderChunk/lights_physical_pars_fragment.glsl.js

@@ -117,6 +117,7 @@ void RE_Direct_Physical( const in IncidentLight directLight, const in GeometricC
 
 
 void RE_IndirectDiffuse_Physical( const in vec3 irradiance, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {
 void RE_IndirectDiffuse_Physical( const in vec3 irradiance, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {
 
 
+	reflectedLight.indirectDiffuse += irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );
 
 
 }
 }
 
 
@@ -139,8 +140,7 @@ void RE_IndirectSpecular_Physical( const in vec3 radiance, const in vec3 irradia
 
 
 	float clearcoatInv = 1.0 - clearcoatDHR;
 	float clearcoatInv = 1.0 - clearcoatDHR;
 
 
-	// Both indirect specular and diffuse light accumulate here
-	// if energy preservation enabled, and PMREM provided.
+	// Both indirect specular and indirect diffuse light accumulate here
 
 
 	vec3 singleScattering = vec3( 0.0 );
 	vec3 singleScattering = vec3( 0.0 );
 	vec3 multiScattering = vec3( 0.0 );
 	vec3 multiScattering = vec3( 0.0 );
@@ -151,7 +151,8 @@ void RE_IndirectSpecular_Physical( const in vec3 radiance, const in vec3 irradia
 	vec3 diffuse = material.diffuseColor * ( 1.0 - ( singleScattering + multiScattering ) );
 	vec3 diffuse = material.diffuseColor * ( 1.0 - ( singleScattering + multiScattering ) );
 
 
 	reflectedLight.indirectSpecular += clearcoatInv * radiance * singleScattering;
 	reflectedLight.indirectSpecular += clearcoatInv * radiance * singleScattering;
-	reflectedLight.indirectDiffuse += multiScattering * cosineWeightedIrradiance;
+	reflectedLight.indirectSpecular += multiScattering * cosineWeightedIrradiance;
+
 	reflectedLight.indirectDiffuse += diffuse * cosineWeightedIrradiance;
 	reflectedLight.indirectDiffuse += diffuse * cosineWeightedIrradiance;
 
 
 }
 }
@@ -161,9 +162,6 @@ void RE_IndirectSpecular_Physical( const in vec3 radiance, const in vec3 irradia
 #define RE_IndirectDiffuse		RE_IndirectDiffuse_Physical
 #define RE_IndirectDiffuse		RE_IndirectDiffuse_Physical
 #define RE_IndirectSpecular		RE_IndirectSpecular_Physical
 #define RE_IndirectSpecular		RE_IndirectSpecular_Physical
 
 
-#define Material_BlinnShininessExponent( material )   GGXRoughnessToBlinnExponent( material.specularRoughness )
-#define Material_Clearcoat_BlinnShininessExponent( material )   GGXRoughnessToBlinnExponent( material.clearcoatRoughness )
-
 // ref: https://seblagarde.files.wordpress.com/2015/07/course_notes_moving_frostbite_to_pbr_v32.pdf
 // ref: https://seblagarde.files.wordpress.com/2015/07/course_notes_moving_frostbite_to_pbr_v32.pdf
 float computeSpecularOcclusion( const in float dotNV, const in float ambientOcclusion, const in float roughness ) {
 float computeSpecularOcclusion( const in float dotNV, const in float ambientOcclusion, const in float roughness ) {
 
 

+ 17 - 0
src/renderers/shaders/ShaderChunk/packing.glsl.js

@@ -25,6 +25,23 @@ float unpackRGBAToDepth( const in vec4 v ) {
 	return dot( v, UnpackFactors );
 	return dot( v, UnpackFactors );
 }
 }
 
 
+vec4 encodeHalfRGBA ( vec2 v ) {
+	vec4 encoded = vec4( 0.0 );
+	const vec2 offset = vec2( 1.0 / 255.0, 0.0 );
+
+	encoded.xy = vec2( v.x, fract( v.x * 255.0 ) );
+	encoded.xy = encoded.xy - ( encoded.yy * offset );
+
+	encoded.zw = vec2( v.y, fract( v.y * 255.0 ) );
+	encoded.zw = encoded.zw - ( encoded.ww * offset );
+
+	return encoded;
+}
+
+vec2 decodeHalfRGBA( vec4 v ) {
+	return vec2( v.x + ( v.y / 255.0 ), v.z + ( v.w / 255.0 ) );
+}
+
 // NOTE: viewZ/eyeZ is < 0 when in front of the camera per OpenGL conventions
 // NOTE: viewZ/eyeZ is < 0 when in front of the camera per OpenGL conventions
 
 
 float viewZToOrthographicDepth( const in float viewZ, const in float near, const in float far ) {
 float viewZToOrthographicDepth( const in float viewZ, const in float near, const in float far ) {

+ 32 - 1
src/renderers/shaders/ShaderChunk/shadowmap_pars_fragment.glsl.js

@@ -36,6 +36,33 @@ export default /* glsl */`
 
 
 	}
 	}
 
 
+	vec2 texture2DDistribution( sampler2D shadow, vec2 uv ) {
+
+		return decodeHalfRGBA( texture2D( shadow, uv ) );
+
+	}
+
+	float VSMShadow (sampler2D shadow, vec2 uv, float compare ){
+
+		float occlusion = 1.0;
+
+		vec2 distribution = texture2DDistribution( shadow, uv );
+
+		float hard_shadow = step( compare , distribution.x ); // Hard Shadow
+
+		if (hard_shadow != 1.0 ) {
+
+			float distance = compare - distribution.x ;
+			float variance = max( 0.00000, distribution.y * distribution.y );
+			float softness_probability = variance / (variance + distance * distance ); // Chebeyshevs inequality
+			softness_probability = clamp( ( softness_probability - 0.3 ) / ( 0.95 - 0.3 ), 0.0, 1.0 ); // 0.3 reduces light bleed
+			occlusion = clamp( max( hard_shadow, softness_probability ), 0.0, 1.0 );
+
+		}
+		return occlusion;
+
+	}
+
 	float texture2DShadowLerp( sampler2D depths, vec2 size, vec2 uv, float compare ) {
 	float texture2DShadowLerp( sampler2D depths, vec2 size, vec2 uv, float compare ) {
 
 
 		const vec2 offset = vec2( 0.0, 1.0 );
 		const vec2 offset = vec2( 0.0, 1.0 );
@@ -131,6 +158,10 @@ export default /* glsl */`
 				texture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx1, dy1 ), shadowCoord.z )
 				texture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx1, dy1 ), shadowCoord.z )
 			) * ( 1.0 / 9.0 );
 			) * ( 1.0 / 9.0 );
 
 
+		#elif defined( SHADOWMAP_TYPE_VSM )
+
+			shadow = VSMShadow( shadowMap, shadowCoord.xy, shadowCoord.z );
+
 		#else // no percentage-closer filtering:
 		#else // no percentage-closer filtering:
 
 
 			shadow = texture2DCompare( shadowMap, shadowCoord.xy, shadowCoord.z );
 			shadow = texture2DCompare( shadowMap, shadowCoord.xy, shadowCoord.z );
@@ -229,7 +260,7 @@ export default /* glsl */`
 		// bd3D = base direction 3D
 		// bd3D = base direction 3D
 		vec3 bd3D = normalize( lightToPosition );
 		vec3 bd3D = normalize( lightToPosition );
 
 
-		#if defined( SHADOWMAP_TYPE_PCF ) || defined( SHADOWMAP_TYPE_PCF_SOFT )
+		#if defined( SHADOWMAP_TYPE_PCF ) || defined( SHADOWMAP_TYPE_PCF_SOFT ) || defined( SHADOWMAP_TYPE_VSM )
 
 
 			vec2 offset = vec2( - 1, 1 ) * shadowRadius * texelSize.y;
 			vec2 offset = vec2( - 1, 1 ) * shadowRadius * texelSize.y;
 
 

+ 42 - 0
src/renderers/shaders/ShaderLib/vsm_frag.glsl.js

@@ -0,0 +1,42 @@
+export default /* glsl */`
+uniform sampler2D shadow_pass;
+uniform vec2 resolution;
+uniform float radius;
+
+#include <packing>
+
+void main() {
+
+  float mean = 0.0;
+  float squared_mean = 0.0;
+  
+	// This seems totally useless but it's a crazy work around for a Adreno compiler bug
+	float depth = unpackRGBAToDepth( texture2D( shadow_pass, ( gl_FragCoord.xy  ) / resolution ) );
+
+  for ( float i = -1.0; i < 1.0 ; i += SAMPLE_RATE) {
+
+    #ifdef HORIZONAL_PASS
+
+      vec2 distribution = decodeHalfRGBA ( texture2D( shadow_pass, ( gl_FragCoord.xy + vec2( i, 0.0 ) * radius ) / resolution ) );
+      mean += distribution.x;
+      squared_mean += distribution.y * distribution.y + distribution.x * distribution.x;
+
+    #else
+
+      float depth = unpackRGBAToDepth( texture2D( shadow_pass, ( gl_FragCoord.xy + vec2( 0.0,  i )  * radius ) / resolution ) );
+      mean += depth;
+      squared_mean += depth * depth;
+
+    #endif
+
+  }
+
+  mean = mean * HALF_SAMPLE_RATE;
+  squared_mean = squared_mean * HALF_SAMPLE_RATE;
+
+  float std_dev = pow( squared_mean - mean * mean, 0.5 );
+
+  gl_FragColor = encodeHalfRGBA( vec2( mean, std_dev ) );
+
+}
+`;

+ 9 - 0
src/renderers/shaders/ShaderLib/vsm_vert.glsl.js

@@ -0,0 +1,9 @@
+export default /* glsl */`
+
+void main() {
+
+	gl_Position = vec4( position, 1.0 );
+
+}
+
+`;

+ 5 - 1
src/renderers/webgl/WebGLProgram.js

@@ -5,7 +5,7 @@
 import { WebGLUniforms } from './WebGLUniforms.js';
 import { WebGLUniforms } from './WebGLUniforms.js';
 import { WebGLShader } from './WebGLShader.js';
 import { WebGLShader } from './WebGLShader.js';
 import { ShaderChunk } from '../shaders/ShaderChunk.js';
 import { ShaderChunk } from '../shaders/ShaderChunk.js';
-import { NoToneMapping, AddOperation, MixOperation, MultiplyOperation, EquirectangularRefractionMapping, CubeRefractionMapping, SphericalReflectionMapping, EquirectangularReflectionMapping, CubeUVRefractionMapping, CubeUVReflectionMapping, CubeReflectionMapping, PCFSoftShadowMap, PCFShadowMap, ACESFilmicToneMapping, CineonToneMapping, Uncharted2ToneMapping, ReinhardToneMapping, LinearToneMapping, GammaEncoding, RGBDEncoding, RGBM16Encoding, RGBM7Encoding, RGBEEncoding, sRGBEncoding, LinearEncoding, LogLuvEncoding } from '../../constants.js';
+import { NoToneMapping, AddOperation, MixOperation, MultiplyOperation, EquirectangularRefractionMapping, CubeRefractionMapping, SphericalReflectionMapping, EquirectangularReflectionMapping, CubeUVRefractionMapping, CubeUVReflectionMapping, CubeReflectionMapping, PCFSoftShadowMap, PCFShadowMap, VSMShadowMap, ACESFilmicToneMapping, CineonToneMapping, Uncharted2ToneMapping, ReinhardToneMapping, LinearToneMapping, GammaEncoding, RGBDEncoding, RGBM16Encoding, RGBM7Encoding, RGBEEncoding, sRGBEncoding, LinearEncoding, LogLuvEncoding } from '../../constants.js';
 
 
 var programIdCount = 0;
 var programIdCount = 0;
 
 
@@ -262,6 +262,10 @@ function WebGLProgram( renderer, extensions, code, material, shader, parameters,
 
 
 		shadowMapTypeDefine = 'SHADOWMAP_TYPE_PCF_SOFT';
 		shadowMapTypeDefine = 'SHADOWMAP_TYPE_PCF_SOFT';
 
 
+	} else if ( parameters.shadowMapType === VSMShadowMap ) {
+
+		shadowMapTypeDefine = 'SHADOWMAP_TYPE_VSM';
+
 	}
 	}
 
 
 	var envMapTypeDefine = 'ENVMAP_TYPE_CUBE';
 	var envMapTypeDefine = 'ENVMAP_TYPE_CUBE';

+ 104 - 9
src/renderers/webgl/WebGLShadowMap.js

@@ -3,14 +3,21 @@
  * @author mrdoob / http://mrdoob.com/
  * @author mrdoob / http://mrdoob.com/
  */
  */
 
 
-import { FrontSide, BackSide, DoubleSide, RGBAFormat, NearestFilter, PCFShadowMap, RGBADepthPacking, NoBlending } from '../../constants.js';
+import { FrontSide, BackSide, DoubleSide, RGBAFormat, NearestFilter, LinearFilter, PCFShadowMap, VSMShadowMap, RGBADepthPacking, NoBlending } from '../../constants.js';
 import { WebGLRenderTarget } from '../WebGLRenderTarget.js';
 import { WebGLRenderTarget } from '../WebGLRenderTarget.js';
 import { MeshDepthMaterial } from '../../materials/MeshDepthMaterial.js';
 import { MeshDepthMaterial } from '../../materials/MeshDepthMaterial.js';
 import { MeshDistanceMaterial } from '../../materials/MeshDistanceMaterial.js';
 import { MeshDistanceMaterial } from '../../materials/MeshDistanceMaterial.js';
+import { ShaderMaterial } from '../../materials/ShaderMaterial.js';
+import { BufferAttribute } from '../../core/BufferAttribute.js';
+import { BufferGeometry } from '../../core/BufferGeometry.js';
+import { Mesh } from '../../objects/Mesh.js';
 import { Vector4 } from '../../math/Vector4.js';
 import { Vector4 } from '../../math/Vector4.js';
 import { Vector2 } from '../../math/Vector2.js';
 import { Vector2 } from '../../math/Vector2.js';
 import { Frustum } from '../../math/Frustum.js';
 import { Frustum } from '../../math/Frustum.js';
 
 
+import vsm_frag from '../shaders/ShaderLib/vsm_frag.glsl.js';
+import vsm_vert from '../shaders/ShaderLib/vsm_vert.glsl.js';
+
 function WebGLShadowMap( _renderer, _objects, maxTextureSize ) {
 function WebGLShadowMap( _renderer, _objects, maxTextureSize ) {
 
 
 	var _frustum = new Frustum(),
 	var _frustum = new Frustum(),
@@ -32,6 +39,39 @@ function WebGLShadowMap( _renderer, _objects, maxTextureSize ) {
 
 
 	var shadowSide = { 0: BackSide, 1: FrontSide, 2: DoubleSide };
 	var shadowSide = { 0: BackSide, 1: FrontSide, 2: DoubleSide };
 
 
+	var shadowMaterialVertical = new ShaderMaterial( {
+
+		defines: {
+			SAMPLE_RATE: 2.0 / 8.0,
+			HALF_SAMPLE_RATE: 1.0 / 8.0
+		},
+
+		uniforms: {
+			shadow_pass: { value: null },
+			resolution: { value: new Vector2() },
+			radius: { value: 4.0 }
+		},
+
+		vertexShader: vsm_vert,
+
+		fragmentShader: vsm_frag
+
+	} );
+
+	var shadowMaterialHorizonal = shadowMaterialVertical.clone();
+	shadowMaterialHorizonal.defines.HORIZONAL_PASS = 1;
+
+	var fullScreenTri = new BufferGeometry();
+	fullScreenTri.addAttribute(
+		"position",
+		new BufferAttribute(
+			new Float32Array( [ - 1, - 1, 0.5, 3, - 1, 0.5, - 1, 3, 0.5 ] ),
+			3
+		)
+	);
+
+	var fullScreenMesh = new Mesh( fullScreenTri, shadowMaterialVertical );
+
 	// init
 	// init
 
 
 	for ( var i = 0; i !== _NumberOfMaterialVariants; ++ i ) {
 	for ( var i = 0; i !== _NumberOfMaterialVariants; ++ i ) {
@@ -133,6 +173,19 @@ function WebGLShadowMap( _renderer, _objects, maxTextureSize ) {
 
 
 			}
 			}
 
 
+			if ( shadow.map === null && ! shadow.isPointLightShadow && this.type === VSMShadowMap ) {
+
+				var pars = { minFilter: LinearFilter, magFilter: LinearFilter, format: RGBAFormat };
+
+				shadow.map = new WebGLRenderTarget( _shadowMapSize.x, _shadowMapSize.y, pars );
+				shadow.map.texture.name = light.name + ".shadowMap";
+
+				shadow.mapPass = new WebGLRenderTarget( _shadowMapSize.x, _shadowMapSize.y, pars );
+
+				shadow.camera.updateProjectionMatrix();
+
+			}
+
 			if ( shadow.map === null ) {
 			if ( shadow.map === null ) {
 
 
 				var pars = { minFilter: NearestFilter, magFilter: NearestFilter, format: RGBAFormat };
 				var pars = { minFilter: NearestFilter, magFilter: NearestFilter, format: RGBAFormat };
@@ -166,7 +219,15 @@ function WebGLShadowMap( _renderer, _objects, maxTextureSize ) {
 
 
 				_frustum = shadow.getFrustum();
 				_frustum = shadow.getFrustum();
 
 
-				renderObject( scene, camera, shadow.camera, light );
+				renderObject( scene, camera, shadow.camera, light, this.type );
+
+			}
+
+			// do blur pass for VSM
+
+			if ( ! shadow.isPointLightShadow && this.type === VSMShadowMap ) {
+
+				VSMPass( shadow, camera );
 
 
 			}
 			}
 
 
@@ -178,7 +239,31 @@ function WebGLShadowMap( _renderer, _objects, maxTextureSize ) {
 
 
 	};
 	};
 
 
-	function getDepthMaterial( object, material, light, shadowCameraNear, shadowCameraFar ) {
+	function VSMPass( shadow, camera ) {
+
+		var geometry = _objects.update( fullScreenMesh );
+
+		// vertical pass
+
+		shadowMaterialVertical.uniforms.shadow_pass.value = shadow.map.texture;
+		shadowMaterialVertical.uniforms.resolution.value = shadow.mapSize;
+		shadowMaterialVertical.uniforms.radius.value = shadow.radius;
+		_renderer.setRenderTarget( shadow.mapPass );
+		_renderer.clear();
+		_renderer.renderBufferDirect( camera, null, geometry, shadowMaterialVertical, fullScreenMesh, null );
+
+		// horizonal pass
+
+		shadowMaterialHorizonal.uniforms.shadow_pass.value = shadow.mapPass.texture;
+		shadowMaterialHorizonal.uniforms.resolution.value = shadow.mapSize;
+		shadowMaterialHorizonal.uniforms.radius.value = shadow.radius;
+		_renderer.setRenderTarget( shadow.map );
+		_renderer.clear();
+		_renderer.renderBufferDirect( camera, null, geometry, shadowMaterialHorizonal, fullScreenMesh, null );
+
+	}
+
+	function getDepthMaterial( object, material, light, shadowCameraNear, shadowCameraFar, type ) {
 
 
 		var geometry = object.geometry;
 		var geometry = object.geometry;
 
 
@@ -267,7 +352,15 @@ function WebGLShadowMap( _renderer, _objects, maxTextureSize ) {
 		result.visible = material.visible;
 		result.visible = material.visible;
 		result.wireframe = material.wireframe;
 		result.wireframe = material.wireframe;
 
 
-		result.side = ( material.shadowSide != null ) ? material.shadowSide : shadowSide[ material.side ];
+		if ( type === VSMShadowMap ) {
+
+			result.side = ( material.shadowSide != null ) ? material.shadowSide : material.side;
+
+		} else {
+
+			result.side = ( material.shadowSide != null ) ? material.shadowSide : shadowSide[ material.side ];
+
+		}
 
 
 		result.clipShadows = material.clipShadows;
 		result.clipShadows = material.clipShadows;
 		result.clippingPlanes = material.clippingPlanes;
 		result.clippingPlanes = material.clippingPlanes;
@@ -288,7 +381,7 @@ function WebGLShadowMap( _renderer, _objects, maxTextureSize ) {
 
 
 	}
 	}
 
 
-	function renderObject( object, camera, shadowCamera, light ) {
+	function renderObject( object, camera, shadowCamera, light, type ) {
 
 
 		if ( object.visible === false ) return;
 		if ( object.visible === false ) return;
 
 
@@ -296,7 +389,7 @@ function WebGLShadowMap( _renderer, _objects, maxTextureSize ) {
 
 
 		if ( visible && ( object.isMesh || object.isLine || object.isPoints ) ) {
 		if ( visible && ( object.isMesh || object.isLine || object.isPoints ) ) {
 
 
-			if ( object.castShadow && ( ! object.frustumCulled || _frustum.intersectsObject( object ) ) ) {
+			if ( ( object.castShadow || ( object.receiveShadow && type === VSMShadowMap ) ) && ( ! object.frustumCulled || _frustum.intersectsObject( object ) ) ) {
 
 
 				object.modelViewMatrix.multiplyMatrices( shadowCamera.matrixWorldInverse, object.matrixWorld );
 				object.modelViewMatrix.multiplyMatrices( shadowCamera.matrixWorldInverse, object.matrixWorld );
 
 
@@ -314,7 +407,8 @@ function WebGLShadowMap( _renderer, _objects, maxTextureSize ) {
 
 
 						if ( groupMaterial && groupMaterial.visible ) {
 						if ( groupMaterial && groupMaterial.visible ) {
 
 
-							var depthMaterial = getDepthMaterial( object, groupMaterial, light, shadowCamera.near, shadowCamera.far );
+							var depthMaterial = getDepthMaterial( object, groupMaterial, light, shadowCamera.near, shadowCamera.far, type );
+
 							_renderer.renderBufferDirect( shadowCamera, null, geometry, depthMaterial, object, group );
 							_renderer.renderBufferDirect( shadowCamera, null, geometry, depthMaterial, object, group );
 
 
 						}
 						}
@@ -323,7 +417,8 @@ function WebGLShadowMap( _renderer, _objects, maxTextureSize ) {
 
 
 				} else if ( material.visible ) {
 				} else if ( material.visible ) {
 
 
-					var depthMaterial = getDepthMaterial( object, material, light, shadowCamera.near, shadowCamera.far );
+					var depthMaterial = getDepthMaterial( object, material, light, shadowCamera.near, shadowCamera.far, type );
+
 					_renderer.renderBufferDirect( shadowCamera, null, geometry, depthMaterial, object, null );
 					_renderer.renderBufferDirect( shadowCamera, null, geometry, depthMaterial, object, null );
 
 
 				}
 				}
@@ -336,7 +431,7 @@ function WebGLShadowMap( _renderer, _objects, maxTextureSize ) {
 
 
 		for ( var i = 0, l = children.length; i < l; i ++ ) {
 		for ( var i = 0, l = children.length; i < l; i ++ ) {
 
 
-			renderObject( children[ i ], camera, shadowCamera, light );
+			renderObject( children[ i ], camera, shadowCamera, light, type );
 
 
 		}
 		}
 
 

部分文件因为文件数量过多而无法显示