Pārlūkot izejas kodu

Examples: Convert objects to ES6. (#21600)

* Examples: Convert objects to ES6.

* Examples: Clean up.
Michael Herzog 4 gadi atpakaļ
vecāks
revīzija
54688c4e4f

+ 163 - 157
examples/js/objects/Lensflare.js

@@ -1,196 +1,202 @@
 ( function () {
 
-	var Lensflare = function () {
-
-		THREE.Mesh.call( this, Lensflare.Geometry, new THREE.MeshBasicMaterial( {
-			opacity: 0,
-			transparent: true
-		} ) );
-		this.type = 'Lensflare';
-		this.frustumCulled = false;
-		this.renderOrder = Infinity; //
-
-		var positionScreen = new THREE.Vector3();
-		var positionView = new THREE.Vector3(); // textures
-
-		var tempMap = new THREE.DataTexture( new Uint8Array( 16 * 16 * 3 ), 16, 16, THREE.RGBFormat );
-		tempMap.minFilter = THREE.NearestFilter;
-		tempMap.magFilter = THREE.NearestFilter;
-		tempMap.wrapS = THREE.ClampToEdgeWrapping;
-		tempMap.wrapT = THREE.ClampToEdgeWrapping;
-		var occlusionMap = new THREE.DataTexture( new Uint8Array( 16 * 16 * 3 ), 16, 16, THREE.RGBFormat );
-		occlusionMap.minFilter = THREE.NearestFilter;
-		occlusionMap.magFilter = THREE.NearestFilter;
-		occlusionMap.wrapS = THREE.ClampToEdgeWrapping;
-		occlusionMap.wrapT = THREE.ClampToEdgeWrapping; // material
-
-		var geometry = Lensflare.Geometry;
-		var material1a = new THREE.RawShaderMaterial( {
-			uniforms: {
-				'scale': {
-					value: null
+	class Lensflare extends THREE.Mesh {
+
+		constructor() {
+
+			super( Lensflare.Geometry, new THREE.MeshBasicMaterial( {
+				opacity: 0,
+				transparent: true
+			} ) );
+			this.type = 'Lensflare';
+			this.frustumCulled = false;
+			this.renderOrder = Infinity; //
+
+			const positionScreen = new THREE.Vector3();
+			const positionView = new THREE.Vector3(); // textures
+
+			const tempMap = new THREE.DataTexture( new Uint8Array( 16 * 16 * 3 ), 16, 16, THREE.RGBFormat );
+			tempMap.minFilter = THREE.NearestFilter;
+			tempMap.magFilter = THREE.NearestFilter;
+			tempMap.wrapS = THREE.ClampToEdgeWrapping;
+			tempMap.wrapT = THREE.ClampToEdgeWrapping;
+			const occlusionMap = new THREE.DataTexture( new Uint8Array( 16 * 16 * 3 ), 16, 16, THREE.RGBFormat );
+			occlusionMap.minFilter = THREE.NearestFilter;
+			occlusionMap.magFilter = THREE.NearestFilter;
+			occlusionMap.wrapS = THREE.ClampToEdgeWrapping;
+			occlusionMap.wrapT = THREE.ClampToEdgeWrapping; // material
+
+			const geometry = Lensflare.Geometry;
+			const material1a = new THREE.RawShaderMaterial( {
+				uniforms: {
+					'scale': {
+						value: null
+					},
+					'screenPosition': {
+						value: null
+					}
 				},
-				'screenPosition': {
-					value: null
-				}
-			},
-			vertexShader: [ 'precision highp float;', 'uniform vec3 screenPosition;', 'uniform vec2 scale;', 'attribute vec3 position;', 'void main() {', '	gl_Position = vec4( position.xy * scale + screenPosition.xy, screenPosition.z, 1.0 );', '}' ].join( '\n' ),
-			fragmentShader: [ 'precision highp float;', 'void main() {', '	gl_FragColor = vec4( 1.0, 0.0, 1.0, 1.0 );', '}' ].join( '\n' ),
-			depthTest: true,
-			depthWrite: false,
-			transparent: false
-		} );
-		var material1b = new THREE.RawShaderMaterial( {
-			uniforms: {
-				'map': {
-					value: tempMap
-				},
-				'scale': {
-					value: null
+				vertexShader: [ 'precision highp float;', 'uniform vec3 screenPosition;', 'uniform vec2 scale;', 'attribute vec3 position;', 'void main() {', '	gl_Position = vec4( position.xy * scale + screenPosition.xy, screenPosition.z, 1.0 );', '}' ].join( '\n' ),
+				fragmentShader: [ 'precision highp float;', 'void main() {', '	gl_FragColor = vec4( 1.0, 0.0, 1.0, 1.0 );', '}' ].join( '\n' ),
+				depthTest: true,
+				depthWrite: false,
+				transparent: false
+			} );
+			const material1b = new THREE.RawShaderMaterial( {
+				uniforms: {
+					'map': {
+						value: tempMap
+					},
+					'scale': {
+						value: null
+					},
+					'screenPosition': {
+						value: null
+					}
 				},
-				'screenPosition': {
-					value: null
-				}
-			},
-			vertexShader: [ 'precision highp float;', 'uniform vec3 screenPosition;', 'uniform vec2 scale;', 'attribute vec3 position;', 'attribute vec2 uv;', 'varying vec2 vUV;', 'void main() {', '	vUV = uv;', '	gl_Position = vec4( position.xy * scale + screenPosition.xy, screenPosition.z, 1.0 );', '}' ].join( '\n' ),
-			fragmentShader: [ 'precision highp float;', 'uniform sampler2D map;', 'varying vec2 vUV;', 'void main() {', '	gl_FragColor = texture2D( map, vUV );', '}' ].join( '\n' ),
-			depthTest: false,
-			depthWrite: false,
-			transparent: false
-		} ); // the following object is used for occlusionMap generation
-
-		var mesh1 = new THREE.Mesh( geometry, material1a ); //
-
-		var elements = [];
-		var shader = LensflareElement.Shader;
-		var material2 = new THREE.RawShaderMaterial( {
-			uniforms: {
-				'map': {
-					value: null
+				vertexShader: [ 'precision highp float;', 'uniform vec3 screenPosition;', 'uniform vec2 scale;', 'attribute vec3 position;', 'attribute vec2 uv;', 'varying vec2 vUV;', 'void main() {', '	vUV = uv;', '	gl_Position = vec4( position.xy * scale + screenPosition.xy, screenPosition.z, 1.0 );', '}' ].join( '\n' ),
+				fragmentShader: [ 'precision highp float;', 'uniform sampler2D map;', 'varying vec2 vUV;', 'void main() {', '	gl_FragColor = texture2D( map, vUV );', '}' ].join( '\n' ),
+				depthTest: false,
+				depthWrite: false,
+				transparent: false
+			} ); // the following object is used for occlusionMap generation
+
+			const mesh1 = new THREE.Mesh( geometry, material1a ); //
+
+			const elements = [];
+			const shader = LensflareElement.Shader;
+			const material2 = new THREE.RawShaderMaterial( {
+				uniforms: {
+					'map': {
+						value: null
+					},
+					'occlusionMap': {
+						value: occlusionMap
+					},
+					'color': {
+						value: new THREE.Color( 0xffffff )
+					},
+					'scale': {
+						value: new THREE.Vector2()
+					},
+					'screenPosition': {
+						value: new THREE.Vector3()
+					}
 				},
-				'occlusionMap': {
-					value: occlusionMap
-				},
-				'color': {
-					value: new THREE.Color( 0xffffff )
-				},
-				'scale': {
-					value: new THREE.Vector2()
-				},
-				'screenPosition': {
-					value: new THREE.Vector3()
-				}
-			},
-			vertexShader: shader.vertexShader,
-			fragmentShader: shader.fragmentShader,
-			blending: THREE.AdditiveBlending,
-			transparent: true,
-			depthWrite: false
-		} );
-		var mesh2 = new THREE.Mesh( geometry, material2 );
+				vertexShader: shader.vertexShader,
+				fragmentShader: shader.fragmentShader,
+				blending: THREE.AdditiveBlending,
+				transparent: true,
+				depthWrite: false
+			} );
+			const mesh2 = new THREE.Mesh( geometry, material2 );
+
+			this.addElement = function ( element ) {
 
-		this.addElement = function ( element ) {
+				elements.push( element );
 
-			elements.push( element );
+			}; //
 
-		}; //
 
+			const scale = new THREE.Vector2();
+			const screenPositionPixels = new THREE.Vector2();
+			const validArea = new THREE.Box2();
+			const viewport = new THREE.Vector4();
 
-		var scale = new THREE.Vector2();
-		var screenPositionPixels = new THREE.Vector2();
-		var validArea = new THREE.Box2();
-		var viewport = new THREE.Vector4();
+			this.onBeforeRender = function ( renderer, scene, camera ) {
 
-		this.onBeforeRender = function ( renderer, scene, camera ) {
+				renderer.getCurrentViewport( viewport );
+				const invAspect = viewport.w / viewport.z;
+				const halfViewportWidth = viewport.z / 2.0;
+				const halfViewportHeight = viewport.w / 2.0;
+				let size = 16 / viewport.w;
+				scale.set( size * invAspect, size );
+				validArea.min.set( viewport.x, viewport.y );
+				validArea.max.set( viewport.x + ( viewport.z - 16 ), viewport.y + ( viewport.w - 16 ) ); // calculate position in screen space
 
-			renderer.getCurrentViewport( viewport );
-			var invAspect = viewport.w / viewport.z;
-			var halfViewportWidth = viewport.z / 2.0;
-			var halfViewportHeight = viewport.w / 2.0;
-			var size = 16 / viewport.w;
-			scale.set( size * invAspect, size );
-			validArea.min.set( viewport.x, viewport.y );
-			validArea.max.set( viewport.x + ( viewport.z - 16 ), viewport.y + ( viewport.w - 16 ) ); // calculate position in screen space
+				positionView.setFromMatrixPosition( this.matrixWorld );
+				positionView.applyMatrix4( camera.matrixWorldInverse );
+				if ( positionView.z > 0 ) return; // lensflare is behind the camera
 
-			positionView.setFromMatrixPosition( this.matrixWorld );
-			positionView.applyMatrix4( camera.matrixWorldInverse );
-			if ( positionView.z > 0 ) return; // lensflare is behind the camera
+				positionScreen.copy( positionView ).applyMatrix4( camera.projectionMatrix ); // horizontal and vertical coordinate of the lower left corner of the pixels to copy
 
-			positionScreen.copy( positionView ).applyMatrix4( camera.projectionMatrix ); // horizontal and vertical coordinate of the lower left corner of the pixels to copy
+				screenPositionPixels.x = viewport.x + positionScreen.x * halfViewportWidth + halfViewportWidth - 8;
+				screenPositionPixels.y = viewport.y + positionScreen.y * halfViewportHeight + halfViewportHeight - 8; // screen cull
 
-			screenPositionPixels.x = viewport.x + positionScreen.x * halfViewportWidth + halfViewportWidth - 8;
-			screenPositionPixels.y = viewport.y + positionScreen.y * halfViewportHeight + halfViewportHeight - 8; // screen cull
+				if ( validArea.containsPoint( screenPositionPixels ) ) {
 
-			if ( validArea.containsPoint( screenPositionPixels ) ) {
+					// save current RGB to temp texture
+					renderer.copyFramebufferToTexture( screenPositionPixels, tempMap ); // render pink quad
 
-				// save current RGB to temp texture
-				renderer.copyFramebufferToTexture( screenPositionPixels, tempMap ); // render pink quad
+					let uniforms = material1a.uniforms;
+					uniforms[ 'scale' ].value = scale;
+					uniforms[ 'screenPosition' ].value = positionScreen;
+					renderer.renderBufferDirect( camera, null, geometry, material1a, mesh1, null ); // copy result to occlusionMap
 
-				var uniforms = material1a.uniforms;
-				uniforms[ 'scale' ].value = scale;
-				uniforms[ 'screenPosition' ].value = positionScreen;
-				renderer.renderBufferDirect( camera, null, geometry, material1a, mesh1, null ); // copy result to occlusionMap
+					renderer.copyFramebufferToTexture( screenPositionPixels, occlusionMap ); // restore graphics
 
-				renderer.copyFramebufferToTexture( screenPositionPixels, occlusionMap ); // restore graphics
+					uniforms = material1b.uniforms;
+					uniforms[ 'scale' ].value = scale;
+					uniforms[ 'screenPosition' ].value = positionScreen;
+					renderer.renderBufferDirect( camera, null, geometry, material1b, mesh1, null ); // render elements
 
-				var uniforms = material1b.uniforms;
-				uniforms[ 'scale' ].value = scale;
-				uniforms[ 'screenPosition' ].value = positionScreen;
-				renderer.renderBufferDirect( camera, null, geometry, material1b, mesh1, null ); // render elements
+					const vecX = - positionScreen.x * 2;
+					const vecY = - positionScreen.y * 2;
 
-				var vecX = - positionScreen.x * 2;
-				var vecY = - positionScreen.y * 2;
+					for ( let i = 0, l = elements.length; i < l; i ++ ) {
 
-				for ( var i = 0, l = elements.length; i < l; i ++ ) {
+						const element = elements[ i ];
+						const uniforms = material2.uniforms;
+						uniforms[ 'color' ].value.copy( element.color );
+						uniforms[ 'map' ].value = element.texture;
+						uniforms[ 'screenPosition' ].value.x = positionScreen.x + vecX * element.distance;
+						uniforms[ 'screenPosition' ].value.y = positionScreen.y + vecY * element.distance;
+						size = element.size / viewport.w;
+						const invAspect = viewport.w / viewport.z;
+						uniforms[ 'scale' ].value.set( size * invAspect, size );
+						material2.uniformsNeedUpdate = true;
+						renderer.renderBufferDirect( camera, null, geometry, material2, mesh2, null );
 
-					var element = elements[ i ];
-					var uniforms = material2.uniforms;
-					uniforms[ 'color' ].value.copy( element.color );
-					uniforms[ 'map' ].value = element.texture;
-					uniforms[ 'screenPosition' ].value.x = positionScreen.x + vecX * element.distance;
-					uniforms[ 'screenPosition' ].value.y = positionScreen.y + vecY * element.distance;
-					var size = element.size / viewport.w;
-					var invAspect = viewport.w / viewport.z;
-					uniforms[ 'scale' ].value.set( size * invAspect, size );
-					material2.uniformsNeedUpdate = true;
-					renderer.renderBufferDirect( camera, null, geometry, material2, mesh2, null );
+					}
 
 				}
 
-			}
+			};
 
-		};
+			this.dispose = function () {
 
-		this.dispose = function () {
+				material1a.dispose();
+				material1b.dispose();
+				material2.dispose();
+				tempMap.dispose();
+				occlusionMap.dispose();
 
-			material1a.dispose();
-			material1b.dispose();
-			material2.dispose();
-			tempMap.dispose();
-			occlusionMap.dispose();
+				for ( let i = 0, l = elements.length; i < l; i ++ ) {
 
-			for ( var i = 0, l = elements.length; i < l; i ++ ) {
+					elements[ i ].texture.dispose();
 
-				elements[ i ].texture.dispose();
+				}
 
-			}
+			};
 
-		};
+		}
 
-	};
+	}
 
-	Lensflare.prototype = Object.create( THREE.Mesh.prototype );
-	Lensflare.prototype.constructor = Lensflare;
 	Lensflare.prototype.isLensflare = true; //
 
-	var LensflareElement = function ( texture, size, distance, color ) {
+	class LensflareElement {
 
-		this.texture = texture;
-		this.size = size || 1;
-		this.distance = distance || 0;
-		this.color = color || new THREE.Color( 0xffffff );
+		constructor( texture, size = 1, distance = 0, color = new THREE.Color( 0xffffff ) ) {
 
-	};
+			this.texture = texture;
+			this.size = size;
+			this.distance = distance;
+			this.color = color;
+
+		}
+
+	}
 
 	LensflareElement.Shader = {
 		uniforms: {
@@ -216,9 +222,9 @@
 
 	Lensflare.Geometry = function () {
 
-		var geometry = new THREE.BufferGeometry();
-		var float32Array = new Float32Array( [ - 1, - 1, 0, 0, 0, 1, - 1, 0, 1, 0, 1, 1, 0, 1, 1, - 1, 1, 0, 0, 1 ] );
-		var interleavedBuffer = new THREE.InterleavedBuffer( float32Array, 5 );
+		const geometry = new THREE.BufferGeometry();
+		const float32Array = new Float32Array( [ - 1, - 1, 0, 0, 0, 1, - 1, 0, 1, 0, 1, 1, 0, 1, 1, - 1, 1, 0, 0, 1 ] );
+		const interleavedBuffer = new THREE.InterleavedBuffer( float32Array, 5 );
 		geometry.setIndex( [ 0, 1, 2, 0, 2, 3 ] );
 		geometry.setAttribute( 'position', new THREE.InterleavedBufferAttribute( interleavedBuffer, 3, 0, false ) );
 		geometry.setAttribute( 'uv', new THREE.InterleavedBufferAttribute( interleavedBuffer, 2, 3, false ) );

+ 104 - 103
examples/js/objects/LightningStorm.js

@@ -6,7 +6,7 @@
  *
  * Usage
  *
- * var myStorm = new LightningStorm( paramsObject );
+ * const myStorm = new LightningStorm( paramsObject );
  * myStorm.position.set( ... );
  * scene.add( myStorm );
  * ...
@@ -46,163 +46,164 @@
  *
 */
 
-	var LightningStorm = function ( stormParams ) {
+	class LightningStorm extends THREE.Object3D {
 
-		THREE.Object3D.call( this ); // Parameters
+		constructor( stormParams = {} ) {
 
-		stormParams = stormParams || {};
-		this.stormParams = stormParams;
-		stormParams.size = stormParams.size !== undefined ? stormParams.size : 1000.0;
-		stormParams.minHeight = stormParams.minHeight !== undefined ? stormParams.minHeight : 80.0;
-		stormParams.maxHeight = stormParams.maxHeight !== undefined ? stormParams.maxHeight : 100.0;
-		stormParams.maxSlope = stormParams.maxSlope !== undefined ? stormParams.maxSlope : 1.1;
-		stormParams.maxLightnings = stormParams.maxLightnings !== undefined ? stormParams.maxLightnings : 3;
-		stormParams.lightningMinPeriod = stormParams.lightningMinPeriod !== undefined ? stormParams.lightningMinPeriod : 3.0;
-		stormParams.lightningMaxPeriod = stormParams.lightningMaxPeriod !== undefined ? stormParams.lightningMaxPeriod : 7.0;
-		stormParams.lightningMinDuration = stormParams.lightningMinDuration !== undefined ? stormParams.lightningMinDuration : 1.0;
-		stormParams.lightningMaxDuration = stormParams.lightningMaxDuration !== undefined ? stormParams.lightningMaxDuration : 2.5;
-		this.lightningParameters = THREE.LightningStrike.copyParameters( stormParams.lightningParameters, stormParams.lightningParameters );
-		this.lightningParameters.isEternal = false;
-		this.lightningMaterial = stormParams.lightningMaterial !== undefined ? stormParams.lightningMaterial : new THREE.MeshBasicMaterial( {
-			color: 0xB0FFFF
-		} );
+			super(); // Parameters
 
-		if ( stormParams.onRayPosition !== undefined ) {
+			this.stormParams = stormParams;
+			stormParams.size = stormParams.size !== undefined ? stormParams.size : 1000.0;
+			stormParams.minHeight = stormParams.minHeight !== undefined ? stormParams.minHeight : 80.0;
+			stormParams.maxHeight = stormParams.maxHeight !== undefined ? stormParams.maxHeight : 100.0;
+			stormParams.maxSlope = stormParams.maxSlope !== undefined ? stormParams.maxSlope : 1.1;
+			stormParams.maxLightnings = stormParams.maxLightnings !== undefined ? stormParams.maxLightnings : 3;
+			stormParams.lightningMinPeriod = stormParams.lightningMinPeriod !== undefined ? stormParams.lightningMinPeriod : 3.0;
+			stormParams.lightningMaxPeriod = stormParams.lightningMaxPeriod !== undefined ? stormParams.lightningMaxPeriod : 7.0;
+			stormParams.lightningMinDuration = stormParams.lightningMinDuration !== undefined ? stormParams.lightningMinDuration : 1.0;
+			stormParams.lightningMaxDuration = stormParams.lightningMaxDuration !== undefined ? stormParams.lightningMaxDuration : 2.5;
+			this.lightningParameters = THREE.LightningStrike.copyParameters( stormParams.lightningParameters, stormParams.lightningParameters );
+			this.lightningParameters.isEternal = false;
+			this.lightningMaterial = stormParams.lightningMaterial !== undefined ? stormParams.lightningMaterial : new THREE.MeshBasicMaterial( {
+				color: 0xB0FFFF
+			} );
 
-			this.onRayPosition = stormParams.onRayPosition;
+			if ( stormParams.onRayPosition !== undefined ) {
 
-		} else {
+				this.onRayPosition = stormParams.onRayPosition;
 
-			this.onRayPosition = function ( source, dest ) {
+			} else {
 
-				dest.set( ( Math.random() - 0.5 ) * stormParams.size, 0, ( Math.random() - 0.5 ) * stormParams.size );
-				var height = THREE.MathUtils.lerp( stormParams.minHeight, stormParams.maxHeight, Math.random() );
-				source.set( stormParams.maxSlope * ( 2 * Math.random() - 1 ), 1, stormParams.maxSlope * ( 2 * Math.random() - 1 ) ).multiplyScalar( height ).add( dest );
+				this.onRayPosition = function ( source, dest ) {
 
-			};
+					dest.set( ( Math.random() - 0.5 ) * stormParams.size, 0, ( Math.random() - 0.5 ) * stormParams.size );
+					const height = THREE.MathUtils.lerp( stormParams.minHeight, stormParams.maxHeight, Math.random() );
+					source.set( stormParams.maxSlope * ( 2 * Math.random() - 1 ), 1, stormParams.maxSlope * ( 2 * Math.random() - 1 ) ).multiplyScalar( height ).add( dest );
 
-		}
+				};
 
-		this.onLightningDown = stormParams.onLightningDown; // Internal state
+			}
 
-		this.inited = false;
-		this.nextLightningTime = 0;
-		this.lightningsMeshes = [];
-		this.deadLightningsMeshes = [];
+			this.onLightningDown = stormParams.onLightningDown; // Internal state
 
-		for ( var i = 0; i < this.stormParams.maxLightnings; i ++ ) {
+			this.inited = false;
+			this.nextLightningTime = 0;
+			this.lightningsMeshes = [];
+			this.deadLightningsMeshes = [];
 
-			var lightning = new THREE.LightningStrike( THREE.LightningStrike.copyParameters( {}, this.lightningParameters ) );
-			var mesh = new THREE.Mesh( lightning, this.lightningMaterial );
-			this.deadLightningsMeshes.push( mesh );
+			for ( let i = 0; i < this.stormParams.maxLightnings; i ++ ) {
 
-		}
+				const lightning = new THREE.LightningStrike( THREE.LightningStrike.copyParameters( {}, this.lightningParameters ) );
+				const mesh = new THREE.Mesh( lightning, this.lightningMaterial );
+				this.deadLightningsMeshes.push( mesh );
 
-	};
+			}
 
-	LightningStorm.prototype = Object.create( THREE.Object3D.prototype );
-	LightningStorm.prototype.constructor = LightningStorm;
-	LightningStorm.prototype.isLightningStorm = true;
+		}
 
-	LightningStorm.prototype.update = function ( time ) {
+		update( time ) {
 
-		if ( ! this.inited ) {
+			if ( ! this.inited ) {
 
-			this.nextLightningTime = this.getNextLightningTime( time ) * Math.random();
-			this.inited = true;
+				this.nextLightningTime = this.getNextLightningTime( time ) * Math.random();
+				this.inited = true;
 
-		}
+			}
 
-		if ( time >= this.nextLightningTime ) {
+			if ( time >= this.nextLightningTime ) {
 
-			// Lightning creation
-			var lightningMesh = this.deadLightningsMeshes.pop();
+				// Lightning creation
+				const lightningMesh = this.deadLightningsMeshes.pop();
 
-			if ( lightningMesh ) {
+				if ( lightningMesh ) {
 
-				var lightningParams1 = THREE.LightningStrike.copyParameters( lightningMesh.geometry.rayParameters, this.lightningParameters );
-				lightningParams1.birthTime = time;
-				lightningParams1.deathTime = time + THREE.MathUtils.lerp( this.stormParams.lightningMinDuration, this.stormParams.lightningMaxDuration, Math.random() );
-				this.onRayPosition( lightningParams1.sourceOffset, lightningParams1.destOffset );
-				lightningParams1.noiseSeed = Math.random();
-				this.add( lightningMesh );
-				this.lightningsMeshes.push( lightningMesh );
+					const lightningParams1 = THREE.LightningStrike.copyParameters( lightningMesh.geometry.rayParameters, this.lightningParameters );
+					lightningParams1.birthTime = time;
+					lightningParams1.deathTime = time + THREE.MathUtils.lerp( this.stormParams.lightningMinDuration, this.stormParams.lightningMaxDuration, Math.random() );
+					this.onRayPosition( lightningParams1.sourceOffset, lightningParams1.destOffset );
+					lightningParams1.noiseSeed = Math.random();
+					this.add( lightningMesh );
+					this.lightningsMeshes.push( lightningMesh );
 
-			} // Schedule next lightning
+				} // Schedule next lightning
 
 
-			this.nextLightningTime = this.getNextLightningTime( time );
+				this.nextLightningTime = this.getNextLightningTime( time );
 
-		}
+			}
+
+			let i = 0,
+				il = this.lightningsMeshes.length;
 
-		var i = 0,
-			il = this.lightningsMeshes.length;
+			while ( i < il ) {
 
-		while ( i < il ) {
+				const mesh = this.lightningsMeshes[ i ];
+				const lightning = mesh.geometry;
+				const prevState = lightning.state;
+				lightning.update( time );
 
-			var mesh = this.lightningsMeshes[ i ];
-			var lightning = mesh.geometry;
-			var prevState = lightning.state;
-			lightning.update( time );
+				if ( prevState === THREE.LightningStrike.RAY_PROPAGATING && lightning.state > prevState ) {
 
-			if ( prevState === THREE.LightningStrike.RAY_PROPAGATING && lightning.state > prevState ) {
+					if ( this.onLightningDown ) {
 
-				if ( this.onLightningDown ) {
+						this.onLightningDown( lightning );
 
-					this.onLightningDown( lightning );
+					}
 
 				}
 
-			}
+				if ( lightning.state === THREE.LightningStrike.RAY_EXTINGUISHED ) {
 
-			if ( lightning.state === THREE.LightningStrike.RAY_EXTINGUISHED ) {
+					// Lightning is to be destroyed
+					this.lightningsMeshes.splice( this.lightningsMeshes.indexOf( mesh ), 1 );
+					this.deadLightningsMeshes.push( mesh );
+					this.remove( mesh );
+					il --;
 
-				// Lightning is to be destroyed
-				this.lightningsMeshes.splice( this.lightningsMeshes.indexOf( mesh ), 1 );
-				this.deadLightningsMeshes.push( mesh );
-				this.remove( mesh );
-				il --;
+				} else {
 
-			} else {
+					i ++;
 
-				i ++;
+				}
 
 			}
 
 		}
 
-	};
+		getNextLightningTime( currentTime ) {
 
-	LightningStorm.prototype.getNextLightningTime = function ( currentTime ) {
+			return currentTime + THREE.MathUtils.lerp( this.stormParams.lightningMinPeriod, this.stormParams.lightningMaxPeriod, Math.random() ) / ( this.stormParams.maxLightnings + 1 );
 
-		return currentTime + THREE.MathUtils.lerp( this.stormParams.lightningMinPeriod, this.stormParams.lightningMaxPeriod, Math.random() ) / ( this.stormParams.maxLightnings + 1 );
+		}
 
-	};
+		copy( source ) {
+
+			super.copy( source );
+			this.stormParams.size = source.stormParams.size;
+			this.stormParams.minHeight = source.stormParams.minHeight;
+			this.stormParams.maxHeight = source.stormParams.maxHeight;
+			this.stormParams.maxSlope = source.stormParams.maxSlope;
+			this.stormParams.maxLightnings = source.stormParams.maxLightnings;
+			this.stormParams.lightningMinPeriod = source.stormParams.lightningMinPeriod;
+			this.stormParams.lightningMaxPeriod = source.stormParams.lightningMaxPeriod;
+			this.stormParams.lightningMinDuration = source.stormParams.lightningMinDuration;
+			this.stormParams.lightningMaxDuration = source.stormParams.lightningMaxDuration;
+			this.lightningParameters = THREE.LightningStrike.copyParameters( {}, source.lightningParameters );
+			this.lightningMaterial = source.stormParams.lightningMaterial;
+			this.onLightningDown = source.onLightningDown;
+			return this;
 
-	LightningStorm.prototype.copy = function ( source ) {
+		}
 
-		THREE.Object3D.prototype.copy.call( this, source );
-		this.stormParams.size = source.stormParams.size;
-		this.stormParams.minHeight = source.stormParams.minHeight;
-		this.stormParams.maxHeight = source.stormParams.maxHeight;
-		this.stormParams.maxSlope = source.stormParams.maxSlope;
-		this.stormParams.maxLightnings = source.stormParams.maxLightnings;
-		this.stormParams.lightningMinPeriod = source.stormParams.lightningMinPeriod;
-		this.stormParams.lightningMaxPeriod = source.stormParams.lightningMaxPeriod;
-		this.stormParams.lightningMinDuration = source.stormParams.lightningMinDuration;
-		this.stormParams.lightningMaxDuration = source.stormParams.lightningMaxDuration;
-		this.lightningParameters = THREE.LightningStrike.copyParameters( {}, source.lightningParameters );
-		this.lightningMaterial = source.stormParams.lightningMaterial;
-		this.onLightningDown = source.onLightningDown;
-		return this;
+		clone() {
 
-	};
+			return new this.constructor( this.stormParams ).copy( this );
 
-	THREE.LightningStrike.prototype.clone = function () {
+		}
 
-		return new this.constructor( this.stormParams ).copy( this );
+	}
 
-	};
+	LightningStorm.prototype.isLightningStorm = true;
 
 	THREE.LightningStorm = LightningStorm;
 

Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 540 - 545
examples/js/objects/MarchingCubes.js


+ 134 - 132
examples/js/objects/Reflector.js

@@ -1,143 +1,145 @@
 ( function () {
 
-	var Reflector = function ( geometry, options ) {
-
-		THREE.Mesh.call( this, geometry );
-		this.type = 'Reflector';
-		var scope = this;
-		options = options || {};
-		var color = options.color !== undefined ? new THREE.Color( options.color ) : new THREE.Color( 0x7F7F7F );
-		var textureWidth = options.textureWidth || 512;
-		var textureHeight = options.textureHeight || 512;
-		var clipBias = options.clipBias || 0;
-		var shader = options.shader || Reflector.ReflectorShader; //
-
-		var reflectorPlane = new THREE.Plane();
-		var normal = new THREE.Vector3();
-		var reflectorWorldPosition = new THREE.Vector3();
-		var cameraWorldPosition = new THREE.Vector3();
-		var rotationMatrix = new THREE.Matrix4();
-		var lookAtPosition = new THREE.Vector3( 0, 0, - 1 );
-		var clipPlane = new THREE.Vector4();
-		var view = new THREE.Vector3();
-		var target = new THREE.Vector3();
-		var q = new THREE.Vector4();
-		var textureMatrix = new THREE.Matrix4();
-		var virtualCamera = new THREE.PerspectiveCamera();
-		var parameters = {
-			minFilter: THREE.LinearFilter,
-			magFilter: THREE.LinearFilter,
-			format: THREE.RGBFormat
-		};
-		var renderTarget = new THREE.WebGLRenderTarget( textureWidth, textureHeight, parameters );
-
-		if ( ! THREE.MathUtils.isPowerOfTwo( textureWidth ) || ! THREE.MathUtils.isPowerOfTwo( textureHeight ) ) {
-
-			renderTarget.texture.generateMipmaps = false;
-
-		}
-
-		var material = new THREE.ShaderMaterial( {
-			uniforms: THREE.UniformsUtils.clone( shader.uniforms ),
-			fragmentShader: shader.fragmentShader,
-			vertexShader: shader.vertexShader
-		} );
-		material.uniforms[ 'tDiffuse' ].value = renderTarget.texture;
-		material.uniforms[ 'color' ].value = color;
-		material.uniforms[ 'textureMatrix' ].value = textureMatrix;
-		this.material = material;
-
-		this.onBeforeRender = function ( renderer, scene, camera ) {
-
-			reflectorWorldPosition.setFromMatrixPosition( scope.matrixWorld );
-			cameraWorldPosition.setFromMatrixPosition( camera.matrixWorld );
-			rotationMatrix.extractRotation( scope.matrixWorld );
-			normal.set( 0, 0, 1 );
-			normal.applyMatrix4( rotationMatrix );
-			view.subVectors( reflectorWorldPosition, cameraWorldPosition ); // Avoid rendering when reflector is facing away
-
-			if ( view.dot( normal ) > 0 ) return;
-			view.reflect( normal ).negate();
-			view.add( reflectorWorldPosition );
-			rotationMatrix.extractRotation( camera.matrixWorld );
-			lookAtPosition.set( 0, 0, - 1 );
-			lookAtPosition.applyMatrix4( rotationMatrix );
-			lookAtPosition.add( cameraWorldPosition );
-			target.subVectors( reflectorWorldPosition, lookAtPosition );
-			target.reflect( normal ).negate();
-			target.add( reflectorWorldPosition );
-			virtualCamera.position.copy( view );
-			virtualCamera.up.set( 0, 1, 0 );
-			virtualCamera.up.applyMatrix4( rotationMatrix );
-			virtualCamera.up.reflect( normal );
-			virtualCamera.lookAt( target );
-			virtualCamera.far = camera.far; // Used in WebGLBackground
-
-			virtualCamera.updateMatrixWorld();
-			virtualCamera.projectionMatrix.copy( camera.projectionMatrix ); // Update the texture matrix
-
-			textureMatrix.set( 0.5, 0.0, 0.0, 0.5, 0.0, 0.5, 0.0, 0.5, 0.0, 0.0, 0.5, 0.5, 0.0, 0.0, 0.0, 1.0 );
-			textureMatrix.multiply( virtualCamera.projectionMatrix );
-			textureMatrix.multiply( virtualCamera.matrixWorldInverse );
-			textureMatrix.multiply( scope.matrixWorld ); // Now update projection matrix with new clip plane, implementing code from: http://www.terathon.com/code/oblique.html
-			// Paper explaining this technique: http://www.terathon.com/lengyel/Lengyel-Oblique.pdf
-
-			reflectorPlane.setFromNormalAndCoplanarPoint( normal, reflectorWorldPosition );
-			reflectorPlane.applyMatrix4( virtualCamera.matrixWorldInverse );
-			clipPlane.set( reflectorPlane.normal.x, reflectorPlane.normal.y, reflectorPlane.normal.z, reflectorPlane.constant );
-			var projectionMatrix = virtualCamera.projectionMatrix;
-			q.x = ( Math.sign( clipPlane.x ) + projectionMatrix.elements[ 8 ] ) / projectionMatrix.elements[ 0 ];
-			q.y = ( Math.sign( clipPlane.y ) + projectionMatrix.elements[ 9 ] ) / projectionMatrix.elements[ 5 ];
-			q.z = - 1.0;
-			q.w = ( 1.0 + projectionMatrix.elements[ 10 ] ) / projectionMatrix.elements[ 14 ]; // Calculate the scaled plane vector
-
-			clipPlane.multiplyScalar( 2.0 / clipPlane.dot( q ) ); // Replacing the third row of the projection matrix
-
-			projectionMatrix.elements[ 2 ] = clipPlane.x;
-			projectionMatrix.elements[ 6 ] = clipPlane.y;
-			projectionMatrix.elements[ 10 ] = clipPlane.z + 1.0 - clipBias;
-			projectionMatrix.elements[ 14 ] = clipPlane.w; // Render
-
-			renderTarget.texture.encoding = renderer.outputEncoding;
-			scope.visible = false;
-			var currentRenderTarget = renderer.getRenderTarget();
-			var currentXrEnabled = renderer.xr.enabled;
-			var currentShadowAutoUpdate = renderer.shadowMap.autoUpdate;
-			renderer.xr.enabled = false; // Avoid camera modification
-
-			renderer.shadowMap.autoUpdate = false; // Avoid re-computing shadows
-
-			renderer.setRenderTarget( renderTarget );
-			renderer.state.buffers.depth.setMask( true ); // make sure the depth buffer is writable so it can be properly cleared, see #18897
-
-			if ( renderer.autoClear === false ) renderer.clear();
-			renderer.render( scene, virtualCamera );
-			renderer.xr.enabled = currentXrEnabled;
-			renderer.shadowMap.autoUpdate = currentShadowAutoUpdate;
-			renderer.setRenderTarget( currentRenderTarget ); // Restore viewport
-
-			var viewport = camera.viewport;
-
-			if ( viewport !== undefined ) {
-
-				renderer.state.viewport( viewport );
+	class Reflector extends THREE.Mesh {
+
+		constructor( geometry, options = {} ) {
+
+			super( geometry );
+			this.type = 'Reflector';
+			const scope = this;
+			const color = options.color !== undefined ? new THREE.Color( options.color ) : new THREE.Color( 0x7F7F7F );
+			const textureWidth = options.textureWidth || 512;
+			const textureHeight = options.textureHeight || 512;
+			const clipBias = options.clipBias || 0;
+			const shader = options.shader || Reflector.ReflectorShader; //
+
+			const reflectorPlane = new THREE.Plane();
+			const normal = new THREE.Vector3();
+			const reflectorWorldPosition = new THREE.Vector3();
+			const cameraWorldPosition = new THREE.Vector3();
+			const rotationMatrix = new THREE.Matrix4();
+			const lookAtPosition = new THREE.Vector3( 0, 0, - 1 );
+			const clipPlane = new THREE.Vector4();
+			const view = new THREE.Vector3();
+			const target = new THREE.Vector3();
+			const q = new THREE.Vector4();
+			const textureMatrix = new THREE.Matrix4();
+			const virtualCamera = new THREE.PerspectiveCamera();
+			const parameters = {
+				minFilter: THREE.LinearFilter,
+				magFilter: THREE.LinearFilter,
+				format: THREE.RGBFormat
+			};
+			const renderTarget = new THREE.WebGLRenderTarget( textureWidth, textureHeight, parameters );
+
+			if ( ! THREE.MathUtils.isPowerOfTwo( textureWidth ) || ! THREE.MathUtils.isPowerOfTwo( textureHeight ) ) {
+
+				renderTarget.texture.generateMipmaps = false;
 
 			}
 
-			scope.visible = true;
-
-		};
+			const material = new THREE.ShaderMaterial( {
+				uniforms: THREE.UniformsUtils.clone( shader.uniforms ),
+				fragmentShader: shader.fragmentShader,
+				vertexShader: shader.vertexShader
+			} );
+			material.uniforms[ 'tDiffuse' ].value = renderTarget.texture;
+			material.uniforms[ 'color' ].value = color;
+			material.uniforms[ 'textureMatrix' ].value = textureMatrix;
+			this.material = material;
+
+			this.onBeforeRender = function ( renderer, scene, camera ) {
+
+				reflectorWorldPosition.setFromMatrixPosition( scope.matrixWorld );
+				cameraWorldPosition.setFromMatrixPosition( camera.matrixWorld );
+				rotationMatrix.extractRotation( scope.matrixWorld );
+				normal.set( 0, 0, 1 );
+				normal.applyMatrix4( rotationMatrix );
+				view.subVectors( reflectorWorldPosition, cameraWorldPosition ); // Avoid rendering when reflector is facing away
+
+				if ( view.dot( normal ) > 0 ) return;
+				view.reflect( normal ).negate();
+				view.add( reflectorWorldPosition );
+				rotationMatrix.extractRotation( camera.matrixWorld );
+				lookAtPosition.set( 0, 0, - 1 );
+				lookAtPosition.applyMatrix4( rotationMatrix );
+				lookAtPosition.add( cameraWorldPosition );
+				target.subVectors( reflectorWorldPosition, lookAtPosition );
+				target.reflect( normal ).negate();
+				target.add( reflectorWorldPosition );
+				virtualCamera.position.copy( view );
+				virtualCamera.up.set( 0, 1, 0 );
+				virtualCamera.up.applyMatrix4( rotationMatrix );
+				virtualCamera.up.reflect( normal );
+				virtualCamera.lookAt( target );
+				virtualCamera.far = camera.far; // Used in WebGLBackground
+
+				virtualCamera.updateMatrixWorld();
+				virtualCamera.projectionMatrix.copy( camera.projectionMatrix ); // Update the texture matrix
+
+				textureMatrix.set( 0.5, 0.0, 0.0, 0.5, 0.0, 0.5, 0.0, 0.5, 0.0, 0.0, 0.5, 0.5, 0.0, 0.0, 0.0, 1.0 );
+				textureMatrix.multiply( virtualCamera.projectionMatrix );
+				textureMatrix.multiply( virtualCamera.matrixWorldInverse );
+				textureMatrix.multiply( scope.matrixWorld ); // Now update projection matrix with new clip plane, implementing code from: http://www.terathon.com/code/oblique.html
+				// Paper explaining this technique: http://www.terathon.com/lengyel/Lengyel-Oblique.pdf
+
+				reflectorPlane.setFromNormalAndCoplanarPoint( normal, reflectorWorldPosition );
+				reflectorPlane.applyMatrix4( virtualCamera.matrixWorldInverse );
+				clipPlane.set( reflectorPlane.normal.x, reflectorPlane.normal.y, reflectorPlane.normal.z, reflectorPlane.constant );
+				const projectionMatrix = virtualCamera.projectionMatrix;
+				q.x = ( Math.sign( clipPlane.x ) + projectionMatrix.elements[ 8 ] ) / projectionMatrix.elements[ 0 ];
+				q.y = ( Math.sign( clipPlane.y ) + projectionMatrix.elements[ 9 ] ) / projectionMatrix.elements[ 5 ];
+				q.z = - 1.0;
+				q.w = ( 1.0 + projectionMatrix.elements[ 10 ] ) / projectionMatrix.elements[ 14 ]; // Calculate the scaled plane vector
+
+				clipPlane.multiplyScalar( 2.0 / clipPlane.dot( q ) ); // Replacing the third row of the projection matrix
+
+				projectionMatrix.elements[ 2 ] = clipPlane.x;
+				projectionMatrix.elements[ 6 ] = clipPlane.y;
+				projectionMatrix.elements[ 10 ] = clipPlane.z + 1.0 - clipBias;
+				projectionMatrix.elements[ 14 ] = clipPlane.w; // Render
+
+				renderTarget.texture.encoding = renderer.outputEncoding;
+				scope.visible = false;
+				const currentRenderTarget = renderer.getRenderTarget();
+				const currentXrEnabled = renderer.xr.enabled;
+				const currentShadowAutoUpdate = renderer.shadowMap.autoUpdate;
+				renderer.xr.enabled = false; // Avoid camera modification
+
+				renderer.shadowMap.autoUpdate = false; // Avoid re-computing shadows
+
+				renderer.setRenderTarget( renderTarget );
+				renderer.state.buffers.depth.setMask( true ); // make sure the depth buffer is writable so it can be properly cleared, see #18897
+
+				if ( renderer.autoClear === false ) renderer.clear();
+				renderer.render( scene, virtualCamera );
+				renderer.xr.enabled = currentXrEnabled;
+				renderer.shadowMap.autoUpdate = currentShadowAutoUpdate;
+				renderer.setRenderTarget( currentRenderTarget ); // Restore viewport
+
+				const viewport = camera.viewport;
+
+				if ( viewport !== undefined ) {
+
+					renderer.state.viewport( viewport );
+
+				}
+
+				scope.visible = true;
+
+			};
+
+			this.getRenderTarget = function () {
+
+				return renderTarget;
+
+			};
 
-		this.getRenderTarget = function () {
-
-			return renderTarget;
-
-		};
+		}
 
-	};
+	}
 
-	Reflector.prototype = Object.create( THREE.Mesh.prototype );
-	Reflector.prototype.constructor = Reflector;
+	Reflector.prototype.isReflector = true;
 	Reflector.ReflectorShader = {
 		uniforms: {
 			'color': {

+ 188 - 185
examples/js/objects/ReflectorForSSRPass.js

@@ -1,206 +1,209 @@
 ( function () {
 
-	var ReflectorForSSRPass = function ( geometry, options ) {
-
-		THREE.Mesh.call( this, geometry );
-		this.type = 'ReflectorForSSRPass';
-		var scope = this;
-		options = options || {};
-		var color = options.color !== undefined ? new THREE.Color( options.color ) : new THREE.Color( 0x7F7F7F );
-		var textureWidth = options.textureWidth || 512;
-		var textureHeight = options.textureHeight || 512;
-		var clipBias = options.clipBias || 0;
-		var shader = options.shader || ReflectorForSSRPass.ReflectorShader;
-		var useDepthTexture = options.useDepthTexture === true;
-		var yAxis = new THREE.Vector3( 0, 1, 0 );
-		var vecTemp0 = new THREE.Vector3();
-		var vecTemp1 = new THREE.Vector3(); //
-
-		scope.needsUpdate = false;
-		scope.maxDistance = ReflectorForSSRPass.ReflectorShader.uniforms.maxDistance.value;
-		scope.opacity = ReflectorForSSRPass.ReflectorShader.uniforms.opacity.value;
-		scope.color = color;
-		scope.resolution = options.resolution || new THREE.Vector2( window.innerWidth, window.innerHeight );
-		scope._distanceAttenuation = ReflectorForSSRPass.ReflectorShader.defines.DISTANCE_ATTENUATION;
-		Object.defineProperty( scope, 'distanceAttenuation', {
-			get() {
-
-				return scope._distanceAttenuation;
-
-			},
-
-			set( val ) {
-
-				if ( scope._distanceAttenuation === val ) return;
-				scope._distanceAttenuation = val;
-				scope.material.defines.DISTANCE_ATTENUATION = val;
-				scope.material.needsUpdate = true;
+	class ReflectorForSSRPass extends THREE.Mesh {
+
+		constructor( geometry, options = {} ) {
+
+			super( geometry );
+			this.type = 'ReflectorForSSRPass';
+			const scope = this;
+			const color = options.color !== undefined ? new THREE.Color( options.color ) : new THREE.Color( 0x7F7F7F );
+			const textureWidth = options.textureWidth || 512;
+			const textureHeight = options.textureHeight || 512;
+			const clipBias = options.clipBias || 0;
+			const shader = options.shader || ReflectorForSSRPass.ReflectorShader;
+			const useDepthTexture = options.useDepthTexture === true;
+			const yAxis = new THREE.Vector3( 0, 1, 0 );
+			const vecTemp0 = new THREE.Vector3();
+			const vecTemp1 = new THREE.Vector3(); //
+
+			scope.needsUpdate = false;
+			scope.maxDistance = ReflectorForSSRPass.ReflectorShader.uniforms.maxDistance.value;
+			scope.opacity = ReflectorForSSRPass.ReflectorShader.uniforms.opacity.value;
+			scope.color = color;
+			scope.resolution = options.resolution || new THREE.Vector2( window.innerWidth, window.innerHeight );
+			scope._distanceAttenuation = ReflectorForSSRPass.ReflectorShader.defines.DISTANCE_ATTENUATION;
+			Object.defineProperty( scope, 'distanceAttenuation', {
+				get() {
+
+					return scope._distanceAttenuation;
+
+				},
+
+				set( val ) {
+
+					if ( scope._distanceAttenuation === val ) return;
+					scope._distanceAttenuation = val;
+					scope.material.defines.DISTANCE_ATTENUATION = val;
+					scope.material.needsUpdate = true;
+
+				}
+
+			} );
+			scope._fresnel = ReflectorForSSRPass.ReflectorShader.defines.FRESNEL;
+			Object.defineProperty( scope, 'fresnel', {
+				get() {
+
+					return scope._fresnel;
+
+				},
+
+				set( val ) {
+
+					if ( scope._fresnel === val ) return;
+					scope._fresnel = val;
+					scope.material.defines.FRESNEL = val;
+					scope.material.needsUpdate = true;
+
+				}
+
+			} );
+			const normal = new THREE.Vector3();
+			const reflectorWorldPosition = new THREE.Vector3();
+			const cameraWorldPosition = new THREE.Vector3();
+			const rotationMatrix = new THREE.Matrix4();
+			const lookAtPosition = new THREE.Vector3( 0, 0, - 1 );
+			const view = new THREE.Vector3();
+			const target = new THREE.Vector3();
+			const textureMatrix = new THREE.Matrix4();
+			const virtualCamera = new THREE.PerspectiveCamera();
+			let depthTexture;
+
+			if ( useDepthTexture ) {
+
+				depthTexture = new THREE.DepthTexture();
+				depthTexture.type = THREE.UnsignedShortType;
+				depthTexture.minFilter = THREE.NearestFilter;
+				depthTexture.magFilter = THREE.NearestFilter;
 
 			}
 
-		} );
-		scope._fresnel = ReflectorForSSRPass.ReflectorShader.defines.FRESNEL;
-		Object.defineProperty( scope, 'fresnel', {
-			get() {
-
-				return scope._fresnel;
+			const parameters = {
+				minFilter: THREE.LinearFilter,
+				magFilter: THREE.LinearFilter,
+				format: THREE.RGBFormat,
+				depthTexture: useDepthTexture ? depthTexture : null
+			};
+			const renderTarget = new THREE.WebGLRenderTarget( textureWidth, textureHeight, parameters );
 
-			},
+			if ( ! THREE.MathUtils.isPowerOfTwo( textureWidth ) || ! THREE.MathUtils.isPowerOfTwo( textureHeight ) ) {
 
-			set( val ) {
-
-				if ( scope._fresnel === val ) return;
-				scope._fresnel = val;
-				scope.material.defines.FRESNEL = val;
-				scope.material.needsUpdate = true;
+				renderTarget.texture.generateMipmaps = false;
 
 			}
 
-		} );
-		var normal = new THREE.Vector3();
-		var reflectorWorldPosition = new THREE.Vector3();
-		var cameraWorldPosition = new THREE.Vector3();
-		var rotationMatrix = new THREE.Matrix4();
-		var lookAtPosition = new THREE.Vector3( 0, 0, - 1 );
-		var view = new THREE.Vector3();
-		var target = new THREE.Vector3();
-		var textureMatrix = new THREE.Matrix4();
-		var virtualCamera = new THREE.PerspectiveCamera();
-
-		if ( useDepthTexture ) {
-
-			var depthTexture = new THREE.DepthTexture();
-			depthTexture.type = THREE.UnsignedShortType;
-			depthTexture.minFilter = THREE.NearestFilter;
-			depthTexture.magFilter = THREE.NearestFilter;
-
-		}
-
-		var parameters = {
-			minFilter: THREE.LinearFilter,
-			magFilter: THREE.LinearFilter,
-			format: THREE.RGBFormat,
-			depthTexture: useDepthTexture ? depthTexture : null
-		};
-		var renderTarget = new THREE.WebGLRenderTarget( textureWidth, textureHeight, parameters );
-
-		if ( ! THREE.MathUtils.isPowerOfTwo( textureWidth ) || ! THREE.MathUtils.isPowerOfTwo( textureHeight ) ) {
-
-			renderTarget.texture.generateMipmaps = false;
+			const material = new THREE.ShaderMaterial( {
+				transparent: useDepthTexture,
+				defines: Object.assign( {}, ReflectorForSSRPass.ReflectorShader.defines, {
+					useDepthTexture
+				} ),
+				uniforms: THREE.UniformsUtils.clone( shader.uniforms ),
+				fragmentShader: shader.fragmentShader,
+				vertexShader: shader.vertexShader
+			} );
+			material.uniforms[ 'tDiffuse' ].value = renderTarget.texture;
+			material.uniforms[ 'color' ].value = scope.color;
+			material.uniforms[ 'textureMatrix' ].value = textureMatrix;
 
-		}
+			if ( useDepthTexture ) {
 
-		var material = new THREE.ShaderMaterial( {
-			transparent: useDepthTexture,
-			defines: Object.assign( {}, ReflectorForSSRPass.ReflectorShader.defines, {
-				useDepthTexture
-			} ),
-			uniforms: THREE.UniformsUtils.clone( shader.uniforms ),
-			fragmentShader: shader.fragmentShader,
-			vertexShader: shader.vertexShader
-		} );
-		material.uniforms[ 'tDiffuse' ].value = renderTarget.texture;
-		material.uniforms[ 'color' ].value = scope.color;
-		material.uniforms[ 'textureMatrix' ].value = textureMatrix;
+				material.uniforms[ 'tDepth' ].value = renderTarget.depthTexture;
 
-		if ( useDepthTexture ) {
+			}
 
-			material.uniforms[ 'tDepth' ].value = renderTarget.depthTexture;
+			this.material = material;
+			const globalPlane = new THREE.Plane( new THREE.Vector3( 0, 1, 0 ), clipBias );
+			const globalPlanes = [ globalPlane ];
+
+			this.doRender = function ( renderer, scene, camera ) {
+
+				material.uniforms[ 'maxDistance' ].value = scope.maxDistance;
+				material.uniforms[ 'color' ].value = scope.color;
+				material.uniforms[ 'opacity' ].value = scope.opacity;
+				vecTemp0.copy( camera.position ).normalize();
+				vecTemp1.copy( vecTemp0 ).reflect( yAxis );
+				material.uniforms[ 'fresnelCoe' ].value = ( vecTemp0.dot( vecTemp1 ) + 1. ) / 2.; // TODO: Also need to use glsl viewPosition and viewNormal per pixel.
+
+				reflectorWorldPosition.setFromMatrixPosition( scope.matrixWorld );
+				cameraWorldPosition.setFromMatrixPosition( camera.matrixWorld );
+				rotationMatrix.extractRotation( scope.matrixWorld );
+				normal.set( 0, 0, 1 );
+				normal.applyMatrix4( rotationMatrix );
+				view.subVectors( reflectorWorldPosition, cameraWorldPosition ); // Avoid rendering when reflector is facing away
+
+				if ( view.dot( normal ) > 0 ) return;
+				view.reflect( normal ).negate();
+				view.add( reflectorWorldPosition );
+				rotationMatrix.extractRotation( camera.matrixWorld );
+				lookAtPosition.set( 0, 0, - 1 );
+				lookAtPosition.applyMatrix4( rotationMatrix );
+				lookAtPosition.add( cameraWorldPosition );
+				target.subVectors( reflectorWorldPosition, lookAtPosition );
+				target.reflect( normal ).negate();
+				target.add( reflectorWorldPosition );
+				virtualCamera.position.copy( view );
+				virtualCamera.up.set( 0, 1, 0 );
+				virtualCamera.up.applyMatrix4( rotationMatrix );
+				virtualCamera.up.reflect( normal );
+				virtualCamera.lookAt( target );
+				virtualCamera.far = camera.far; // Used in WebGLBackground
+
+				virtualCamera.updateMatrixWorld();
+				virtualCamera.projectionMatrix.copy( camera.projectionMatrix );
+				material.uniforms[ 'virtualCameraNear' ].value = camera.near;
+				material.uniforms[ 'virtualCameraFar' ].value = camera.far;
+				material.uniforms[ 'virtualCameraMatrixWorld' ].value = virtualCamera.matrixWorld;
+				material.uniforms[ 'virtualCameraProjectionMatrix' ].value = camera.projectionMatrix;
+				material.uniforms[ 'virtualCameraProjectionMatrixInverse' ].value = camera.projectionMatrixInverse;
+				material.uniforms[ 'resolution' ].value = scope.resolution; // Update the texture matrix
+
+				textureMatrix.set( 0.5, 0.0, 0.0, 0.5, 0.0, 0.5, 0.0, 0.5, 0.0, 0.0, 0.5, 0.5, 0.0, 0.0, 0.0, 1.0 );
+				textureMatrix.multiply( virtualCamera.projectionMatrix );
+				textureMatrix.multiply( virtualCamera.matrixWorldInverse );
+				textureMatrix.multiply( scope.matrixWorld ); // Render
+
+				renderTarget.texture.encoding = renderer.outputEncoding; // scope.visible = false;
+
+				const currentRenderTarget = renderer.getRenderTarget();
+				const currentXrEnabled = renderer.xr.enabled;
+				const currentShadowAutoUpdate = renderer.shadowMap.autoUpdate;
+				const currentClippingPlanes = renderer.clippingPlanes;
+				renderer.xr.enabled = false; // Avoid camera modification
+
+				renderer.shadowMap.autoUpdate = false; // Avoid re-computing shadows
+
+				renderer.clippingPlanes = globalPlanes;
+				renderer.setRenderTarget( renderTarget );
+				renderer.state.buffers.depth.setMask( true ); // make sure the depth buffer is writable so it can be properly cleared, see #18897
+
+				if ( renderer.autoClear === false ) renderer.clear();
+				renderer.render( scene, virtualCamera );
+				renderer.xr.enabled = currentXrEnabled;
+				renderer.shadowMap.autoUpdate = currentShadowAutoUpdate;
+				renderer.clippingPlanes = currentClippingPlanes;
+				renderer.setRenderTarget( currentRenderTarget ); // Restore viewport
+
+				const viewport = camera.viewport;
+
+				if ( viewport !== undefined ) {
+
+					renderer.state.viewport( viewport );
+
+				} // scope.visible = true;
+
+			};
+
+			this.getRenderTarget = function () {
+
+				return renderTarget;
+
+			};
 
 		}
 
-		this.material = material;
-		const globalPlane = new THREE.Plane( new THREE.Vector3( 0, 1, 0 ), clipBias );
-		const globalPlanes = [ globalPlane ];
-
-		this.doRender = function ( renderer, scene, camera ) {
-
-			material.uniforms[ 'maxDistance' ].value = scope.maxDistance;
-			material.uniforms[ 'color' ].value = scope.color;
-			material.uniforms[ 'opacity' ].value = scope.opacity;
-			vecTemp0.copy( camera.position ).normalize();
-			vecTemp1.copy( vecTemp0 ).reflect( yAxis );
-			material.uniforms[ 'fresnelCoe' ].value = ( vecTemp0.dot( vecTemp1 ) + 1. ) / 2.; // TODO: Also need to use glsl viewPosition and viewNormal per pixel.
-
-			reflectorWorldPosition.setFromMatrixPosition( scope.matrixWorld );
-			cameraWorldPosition.setFromMatrixPosition( camera.matrixWorld );
-			rotationMatrix.extractRotation( scope.matrixWorld );
-			normal.set( 0, 0, 1 );
-			normal.applyMatrix4( rotationMatrix );
-			view.subVectors( reflectorWorldPosition, cameraWorldPosition ); // Avoid rendering when reflector is facing away
-
-			if ( view.dot( normal ) > 0 ) return;
-			view.reflect( normal ).negate();
-			view.add( reflectorWorldPosition );
-			rotationMatrix.extractRotation( camera.matrixWorld );
-			lookAtPosition.set( 0, 0, - 1 );
-			lookAtPosition.applyMatrix4( rotationMatrix );
-			lookAtPosition.add( cameraWorldPosition );
-			target.subVectors( reflectorWorldPosition, lookAtPosition );
-			target.reflect( normal ).negate();
-			target.add( reflectorWorldPosition );
-			virtualCamera.position.copy( view );
-			virtualCamera.up.set( 0, 1, 0 );
-			virtualCamera.up.applyMatrix4( rotationMatrix );
-			virtualCamera.up.reflect( normal );
-			virtualCamera.lookAt( target );
-			virtualCamera.far = camera.far; // Used in WebGLBackground
-
-			virtualCamera.updateMatrixWorld();
-			virtualCamera.projectionMatrix.copy( camera.projectionMatrix );
-			material.uniforms[ 'virtualCameraNear' ].value = camera.near;
-			material.uniforms[ 'virtualCameraFar' ].value = camera.far;
-			material.uniforms[ 'virtualCameraMatrixWorld' ].value = virtualCamera.matrixWorld;
-			material.uniforms[ 'virtualCameraProjectionMatrix' ].value = camera.projectionMatrix;
-			material.uniforms[ 'virtualCameraProjectionMatrixInverse' ].value = camera.projectionMatrixInverse;
-			material.uniforms[ 'resolution' ].value = scope.resolution; // Update the texture matrix
-
-			textureMatrix.set( 0.5, 0.0, 0.0, 0.5, 0.0, 0.5, 0.0, 0.5, 0.0, 0.0, 0.5, 0.5, 0.0, 0.0, 0.0, 1.0 );
-			textureMatrix.multiply( virtualCamera.projectionMatrix );
-			textureMatrix.multiply( virtualCamera.matrixWorldInverse );
-			textureMatrix.multiply( scope.matrixWorld ); // Render
-
-			renderTarget.texture.encoding = renderer.outputEncoding; // scope.visible = false;
-
-			var currentRenderTarget = renderer.getRenderTarget();
-			var currentXrEnabled = renderer.xr.enabled;
-			var currentShadowAutoUpdate = renderer.shadowMap.autoUpdate;
-			var currentClippingPlanes = renderer.clippingPlanes;
-			renderer.xr.enabled = false; // Avoid camera modification
-
-			renderer.shadowMap.autoUpdate = false; // Avoid re-computing shadows
-
-			renderer.clippingPlanes = globalPlanes;
-			renderer.setRenderTarget( renderTarget );
-			renderer.state.buffers.depth.setMask( true ); // make sure the depth buffer is writable so it can be properly cleared, see #18897
-
-			if ( renderer.autoClear === false ) renderer.clear();
-			renderer.render( scene, virtualCamera );
-			renderer.xr.enabled = currentXrEnabled;
-			renderer.shadowMap.autoUpdate = currentShadowAutoUpdate;
-			renderer.clippingPlanes = currentClippingPlanes;
-			renderer.setRenderTarget( currentRenderTarget ); // Restore viewport
-
-			var viewport = camera.viewport;
-
-			if ( viewport !== undefined ) {
-
-				renderer.state.viewport( viewport );
-
-			} // scope.visible = true;
-
-		};
-
-		this.getRenderTarget = function () {
-
-			return renderTarget;
-
-		};
-
-	};
+	}
 
-	ReflectorForSSRPass.prototype = Object.create( THREE.Mesh.prototype );
-	ReflectorForSSRPass.prototype.constructor = ReflectorForSSRPass;
+	ReflectorForSSRPass.prototype.isReflectorForSSRPass = true;
 	ReflectorForSSRPass.ReflectorShader = {
 		defines: {
 			DISTANCE_ATTENUATION: true,

+ 7 - 5
examples/js/objects/ReflectorRTT.js

@@ -1,13 +1,15 @@
 ( function () {
 
-	var ReflectorRTT = function ( geometry, options ) {
+	class ReflectorRTT extends THREE.Reflector {
 
-		THREE.Reflector.call( this, geometry, options );
-		this.geometry.setDrawRange( 0, 0 ); // avoid rendering geometry
+		constructor( geometry, options ) {
 
-	};
+			super( geometry, options );
+			this.geometry.setDrawRange( 0, 0 ); // avoid rendering geometry
 
-	ReflectorRTT.prototype = Object.create( THREE.Reflector.prototype );
+		}
+
+	}
 
 	THREE.ReflectorRTT = ReflectorRTT;
 

+ 149 - 147
examples/js/objects/Refractor.js

@@ -1,197 +1,199 @@
 ( function () {
 
-	var Refractor = function ( geometry, options ) {
-
-		THREE.Mesh.call( this, geometry );
-		this.type = 'Refractor';
-		var scope = this;
-		options = options || {};
-		var color = options.color !== undefined ? new THREE.Color( options.color ) : new THREE.Color( 0x7F7F7F );
-		var textureWidth = options.textureWidth || 512;
-		var textureHeight = options.textureHeight || 512;
-		var clipBias = options.clipBias || 0;
-		var shader = options.shader || Refractor.RefractorShader; //
-
-		var virtualCamera = new THREE.PerspectiveCamera();
-		virtualCamera.matrixAutoUpdate = false;
-		virtualCamera.userData.refractor = true; //
-
-		var refractorPlane = new THREE.Plane();
-		var textureMatrix = new THREE.Matrix4(); // render target
-
-		var parameters = {
-			minFilter: THREE.LinearFilter,
-			magFilter: THREE.LinearFilter,
-			format: THREE.RGBFormat
-		};
-		var renderTarget = new THREE.WebGLRenderTarget( textureWidth, textureHeight, parameters );
-
-		if ( ! THREE.MathUtils.isPowerOfTwo( textureWidth ) || ! THREE.MathUtils.isPowerOfTwo( textureHeight ) ) {
-
-			renderTarget.texture.generateMipmaps = false;
-
-		} // material
-
-
-		this.material = new THREE.ShaderMaterial( {
-			uniforms: THREE.UniformsUtils.clone( shader.uniforms ),
-			vertexShader: shader.vertexShader,
-			fragmentShader: shader.fragmentShader,
-			transparent: true // ensures, refractors are drawn from farthest to closest
-
-		} );
-		this.material.uniforms[ 'color' ].value = color;
-		this.material.uniforms[ 'tDiffuse' ].value = renderTarget.texture;
-		this.material.uniforms[ 'textureMatrix' ].value = textureMatrix; // functions
-
-		var visible = function () {
-
-			var refractorWorldPosition = new THREE.Vector3();
-			var cameraWorldPosition = new THREE.Vector3();
-			var rotationMatrix = new THREE.Matrix4();
-			var view = new THREE.Vector3();
-			var normal = new THREE.Vector3();
-			return function visible( camera ) {
-
-				refractorWorldPosition.setFromMatrixPosition( scope.matrixWorld );
-				cameraWorldPosition.setFromMatrixPosition( camera.matrixWorld );
-				view.subVectors( refractorWorldPosition, cameraWorldPosition );
-				rotationMatrix.extractRotation( scope.matrixWorld );
-				normal.set( 0, 0, 1 );
-				normal.applyMatrix4( rotationMatrix );
-				return view.dot( normal ) < 0;
-
+	class Refractor extends THREE.Mesh {
+
+		constructor( geometry, options = {} ) {
+
+			super( geometry );
+			this.type = 'Refractor';
+			const scope = this;
+			const color = options.color !== undefined ? new THREE.Color( options.color ) : new THREE.Color( 0x7F7F7F );
+			const textureWidth = options.textureWidth || 512;
+			const textureHeight = options.textureHeight || 512;
+			const clipBias = options.clipBias || 0;
+			const shader = options.shader || Refractor.RefractorShader; //
+
+			const virtualCamera = new THREE.PerspectiveCamera();
+			virtualCamera.matrixAutoUpdate = false;
+			virtualCamera.userData.refractor = true; //
+
+			const refractorPlane = new THREE.Plane();
+			const textureMatrix = new THREE.Matrix4(); // render target
+
+			const parameters = {
+				minFilter: THREE.LinearFilter,
+				magFilter: THREE.LinearFilter,
+				format: THREE.RGBFormat
 			};
+			const renderTarget = new THREE.WebGLRenderTarget( textureWidth, textureHeight, parameters );
 
-		}();
+			if ( ! THREE.MathUtils.isPowerOfTwo( textureWidth ) || ! THREE.MathUtils.isPowerOfTwo( textureHeight ) ) {
 
-		var updateRefractorPlane = function () {
+				renderTarget.texture.generateMipmaps = false;
 
-			var normal = new THREE.Vector3();
-			var position = new THREE.Vector3();
-			var quaternion = new THREE.Quaternion();
-			var scale = new THREE.Vector3();
-			return function updateRefractorPlane() {
+			} // material
 
-				scope.matrixWorld.decompose( position, quaternion, scale );
-				normal.set( 0, 0, 1 ).applyQuaternion( quaternion ).normalize(); // flip the normal because we want to cull everything above the plane
 
-				normal.negate();
-				refractorPlane.setFromNormalAndCoplanarPoint( normal, position );
+			this.material = new THREE.ShaderMaterial( {
+				uniforms: THREE.UniformsUtils.clone( shader.uniforms ),
+				vertexShader: shader.vertexShader,
+				fragmentShader: shader.fragmentShader,
+				transparent: true // ensures, refractors are drawn from farthest to closest
 
-			};
+			} );
+			this.material.uniforms[ 'color' ].value = color;
+			this.material.uniforms[ 'tDiffuse' ].value = renderTarget.texture;
+			this.material.uniforms[ 'textureMatrix' ].value = textureMatrix; // functions
 
-		}();
+			const visible = function () {
 
-		var updateVirtualCamera = function () {
+				const refractorWorldPosition = new THREE.Vector3();
+				const cameraWorldPosition = new THREE.Vector3();
+				const rotationMatrix = new THREE.Matrix4();
+				const view = new THREE.Vector3();
+				const normal = new THREE.Vector3();
+				return function visible( camera ) {
 
-			var clipPlane = new THREE.Plane();
-			var clipVector = new THREE.Vector4();
-			var q = new THREE.Vector4();
-			return function updateVirtualCamera( camera ) {
+					refractorWorldPosition.setFromMatrixPosition( scope.matrixWorld );
+					cameraWorldPosition.setFromMatrixPosition( camera.matrixWorld );
+					view.subVectors( refractorWorldPosition, cameraWorldPosition );
+					rotationMatrix.extractRotation( scope.matrixWorld );
+					normal.set( 0, 0, 1 );
+					normal.applyMatrix4( rotationMatrix );
+					return view.dot( normal ) < 0;
 
-				virtualCamera.matrixWorld.copy( camera.matrixWorld );
-				virtualCamera.matrixWorldInverse.copy( virtualCamera.matrixWorld ).invert();
-				virtualCamera.projectionMatrix.copy( camera.projectionMatrix );
-				virtualCamera.far = camera.far; // used in WebGLBackground
-				// The following code creates an oblique view frustum for clipping.
-				// see: Lengyel, Eric. “Oblique View Frustum Depth Projection and Clipping”.
-				// Journal of Game Development, Vol. 1, No. 2 (2005), Charles River Media, pp. 5–16
+				};
 
-				clipPlane.copy( refractorPlane );
-				clipPlane.applyMatrix4( virtualCamera.matrixWorldInverse );
-				clipVector.set( clipPlane.normal.x, clipPlane.normal.y, clipPlane.normal.z, clipPlane.constant ); // calculate the clip-space corner point opposite the clipping plane and
-				// transform it into camera space by multiplying it by the inverse of the projection matrix
+			}();
 
-				var projectionMatrix = virtualCamera.projectionMatrix;
-				q.x = ( Math.sign( clipVector.x ) + projectionMatrix.elements[ 8 ] ) / projectionMatrix.elements[ 0 ];
-				q.y = ( Math.sign( clipVector.y ) + projectionMatrix.elements[ 9 ] ) / projectionMatrix.elements[ 5 ];
-				q.z = - 1.0;
-				q.w = ( 1.0 + projectionMatrix.elements[ 10 ] ) / projectionMatrix.elements[ 14 ]; // calculate the scaled plane vector
+			const updateRefractorPlane = function () {
 
-				clipVector.multiplyScalar( 2.0 / clipVector.dot( q ) ); // replacing the third row of the projection matrix
+				const normal = new THREE.Vector3();
+				const position = new THREE.Vector3();
+				const quaternion = new THREE.Quaternion();
+				const scale = new THREE.Vector3();
+				return function updateRefractorPlane() {
 
-				projectionMatrix.elements[ 2 ] = clipVector.x;
-				projectionMatrix.elements[ 6 ] = clipVector.y;
-				projectionMatrix.elements[ 10 ] = clipVector.z + 1.0 - clipBias;
-				projectionMatrix.elements[ 14 ] = clipVector.w;
+					scope.matrixWorld.decompose( position, quaternion, scale );
+					normal.set( 0, 0, 1 ).applyQuaternion( quaternion ).normalize(); // flip the normal because we want to cull everything above the plane
 
-			};
+					normal.negate();
+					refractorPlane.setFromNormalAndCoplanarPoint( normal, position );
 
-		}(); // This will update the texture matrix that is used for projective texture mapping in the shader.
-		// see: http://developer.download.nvidia.com/assets/gamedev/docs/projective_texture_mapping.pdf
+				};
 
+			}();
 
-		function updateTextureMatrix( camera ) {
+			const updateVirtualCamera = function () {
 
-			// this matrix does range mapping to [ 0, 1 ]
-			textureMatrix.set( 0.5, 0.0, 0.0, 0.5, 0.0, 0.5, 0.0, 0.5, 0.0, 0.0, 0.5, 0.5, 0.0, 0.0, 0.0, 1.0 ); // we use "Object Linear Texgen", so we need to multiply the texture matrix T
-			// (matrix above) with the projection and view matrix of the virtual camera
-			// and the model matrix of the refractor
+				const clipPlane = new THREE.Plane();
+				const clipVector = new THREE.Vector4();
+				const q = new THREE.Vector4();
+				return function updateVirtualCamera( camera ) {
 
-			textureMatrix.multiply( camera.projectionMatrix );
-			textureMatrix.multiply( camera.matrixWorldInverse );
-			textureMatrix.multiply( scope.matrixWorld );
+					virtualCamera.matrixWorld.copy( camera.matrixWorld );
+					virtualCamera.matrixWorldInverse.copy( virtualCamera.matrixWorld ).invert();
+					virtualCamera.projectionMatrix.copy( camera.projectionMatrix );
+					virtualCamera.far = camera.far; // used in WebGLBackground
+					// The following code creates an oblique view frustum for clipping.
+					// see: Lengyel, Eric. “Oblique View Frustum Depth Projection and Clipping”.
+					// Journal of Game Development, Vol. 1, No. 2 (2005), Charles River Media, pp. 5–16
 
-		} //
+					clipPlane.copy( refractorPlane );
+					clipPlane.applyMatrix4( virtualCamera.matrixWorldInverse );
+					clipVector.set( clipPlane.normal.x, clipPlane.normal.y, clipPlane.normal.z, clipPlane.constant ); // calculate the clip-space corner point opposite the clipping plane and
+					// transform it into camera space by multiplying it by the inverse of the projection matrix
 
+					const projectionMatrix = virtualCamera.projectionMatrix;
+					q.x = ( Math.sign( clipVector.x ) + projectionMatrix.elements[ 8 ] ) / projectionMatrix.elements[ 0 ];
+					q.y = ( Math.sign( clipVector.y ) + projectionMatrix.elements[ 9 ] ) / projectionMatrix.elements[ 5 ];
+					q.z = - 1.0;
+					q.w = ( 1.0 + projectionMatrix.elements[ 10 ] ) / projectionMatrix.elements[ 14 ]; // calculate the scaled plane vector
 
-		function render( renderer, scene, camera ) {
+					clipVector.multiplyScalar( 2.0 / clipVector.dot( q ) ); // replacing the third row of the projection matrix
 
-			scope.visible = false;
-			var currentRenderTarget = renderer.getRenderTarget();
-			var currentXrEnabled = renderer.xr.enabled;
-			var currentShadowAutoUpdate = renderer.shadowMap.autoUpdate;
-			renderer.xr.enabled = false; // avoid camera modification
+					projectionMatrix.elements[ 2 ] = clipVector.x;
+					projectionMatrix.elements[ 6 ] = clipVector.y;
+					projectionMatrix.elements[ 10 ] = clipVector.z + 1.0 - clipBias;
+					projectionMatrix.elements[ 14 ] = clipVector.w;
 
-			renderer.shadowMap.autoUpdate = false; // avoid re-computing shadows
+				};
 
-			renderer.setRenderTarget( renderTarget );
-			if ( renderer.autoClear === false ) renderer.clear();
-			renderer.render( scene, virtualCamera );
-			renderer.xr.enabled = currentXrEnabled;
-			renderer.shadowMap.autoUpdate = currentShadowAutoUpdate;
-			renderer.setRenderTarget( currentRenderTarget ); // restore viewport
+			}(); // This will update the texture matrix that is used for projective texture mapping in the shader.
+			// see: http://developer.download.nvidia.com/assets/gamedev/docs/projective_texture_mapping.pdf
 
-			var viewport = camera.viewport;
 
-			if ( viewport !== undefined ) {
+			function updateTextureMatrix( camera ) {
 
-				renderer.state.viewport( viewport );
+				// this matrix does range mapping to [ 0, 1 ]
+				textureMatrix.set( 0.5, 0.0, 0.0, 0.5, 0.0, 0.5, 0.0, 0.5, 0.0, 0.0, 0.5, 0.5, 0.0, 0.0, 0.0, 1.0 ); // we use "Object Linear Texgen", so we need to multiply the texture matrix T
+				// (matrix above) with the projection and view matrix of the virtual camera
+				// and the model matrix of the refractor
 
-			}
+				textureMatrix.multiply( camera.projectionMatrix );
+				textureMatrix.multiply( camera.matrixWorldInverse );
+				textureMatrix.multiply( scope.matrixWorld );
 
-			scope.visible = true;
+			} //
 
-		} //
 
+			function render( renderer, scene, camera ) {
 
-		this.onBeforeRender = function ( renderer, scene, camera ) {
+				scope.visible = false;
+				const currentRenderTarget = renderer.getRenderTarget();
+				const currentXrEnabled = renderer.xr.enabled;
+				const currentShadowAutoUpdate = renderer.shadowMap.autoUpdate;
+				renderer.xr.enabled = false; // avoid camera modification
 
-			// Render
-			renderTarget.texture.encoding = renderer.outputEncoding; // ensure refractors are rendered only once per frame
+				renderer.shadowMap.autoUpdate = false; // avoid re-computing shadows
 
-			if ( camera.userData.refractor === true ) return; // avoid rendering when the refractor is viewed from behind
+				renderer.setRenderTarget( renderTarget );
+				if ( renderer.autoClear === false ) renderer.clear();
+				renderer.render( scene, virtualCamera );
+				renderer.xr.enabled = currentXrEnabled;
+				renderer.shadowMap.autoUpdate = currentShadowAutoUpdate;
+				renderer.setRenderTarget( currentRenderTarget ); // restore viewport
 
-			if ( ! visible( camera ) === true ) return; // update
+				const viewport = camera.viewport;
 
-			updateRefractorPlane();
-			updateTextureMatrix( camera );
-			updateVirtualCamera( camera );
-			render( renderer, scene, camera );
+				if ( viewport !== undefined ) {
 
-		};
+					renderer.state.viewport( viewport );
 
-		this.getRenderTarget = function () {
+				}
 
-			return renderTarget;
+				scope.visible = true;
 
-		};
+			} //
 
-	};
 
-	Refractor.prototype = Object.create( THREE.Mesh.prototype );
-	Refractor.prototype.constructor = Refractor;
+			this.onBeforeRender = function ( renderer, scene, camera ) {
+
+				// Render
+				renderTarget.texture.encoding = renderer.outputEncoding; // ensure refractors are rendered only once per frame
+
+				if ( camera.userData.refractor === true ) return; // avoid rendering when the refractor is viewed from behind
+
+				if ( ! visible( camera ) === true ) return; // update
+
+				updateRefractorPlane();
+				updateTextureMatrix( camera );
+				updateVirtualCamera( camera );
+				render( renderer, scene, camera );
+
+			};
+
+			this.getRenderTarget = function () {
+
+				return renderTarget;
+
+			};
+
+		}
+
+	}
+
+	Refractor.prototype.isRefractor = true;
 	Refractor.RefractorShader = {
 		uniforms: {
 			'color': {

+ 22 - 22
examples/js/objects/ShadowMesh.js

@@ -4,32 +4,30 @@
  * A shadow THREE.Mesh that follows a shadow-casting THREE.Mesh in the scene, but is confined to a single plane.
  */
 
-	var ShadowMesh = function ( mesh ) {
+	const _shadowMatrix = new THREE.Matrix4();
 
-		var shadowMaterial = new THREE.MeshBasicMaterial( {
-			color: 0x000000,
-			transparent: true,
-			opacity: 0.6,
-			depthWrite: false
-		} );
-		THREE.Mesh.call( this, mesh.geometry, shadowMaterial );
-		this.meshMatrix = mesh.matrixWorld;
-		this.frustumCulled = false;
-		this.matrixAutoUpdate = false;
+	class ShadowMesh extends THREE.Mesh {
 
-	};
+		constructor( mesh ) {
 
-	ShadowMesh.prototype = Object.create( THREE.Mesh.prototype );
-	ShadowMesh.prototype.constructor = ShadowMesh;
+			const shadowMaterial = new THREE.MeshBasicMaterial( {
+				color: 0x000000,
+				transparent: true,
+				opacity: 0.6,
+				depthWrite: false
+			} );
+			super( mesh.geometry, shadowMaterial );
+			this.meshMatrix = mesh.matrixWorld;
+			this.frustumCulled = false;
+			this.matrixAutoUpdate = false;
 
-	ShadowMesh.prototype.update = function () {
+		}
 
-		var shadowMatrix = new THREE.Matrix4();
-		return function ( plane, lightPosition4D ) {
+		update( plane, lightPosition4D ) {
 
 			// based on https://www.opengl.org/archives/resources/features/StencilTalk/tsld021.htm
-			var dot = plane.normal.x * lightPosition4D.x + plane.normal.y * lightPosition4D.y + plane.normal.z * lightPosition4D.z + - plane.constant * lightPosition4D.w;
-			var sme = shadowMatrix.elements;
+			const dot = plane.normal.x * lightPosition4D.x + plane.normal.y * lightPosition4D.y + plane.normal.z * lightPosition4D.z + - plane.constant * lightPosition4D.w;
+			const sme = _shadowMatrix.elements;
 			sme[ 0 ] = dot - lightPosition4D.x * plane.normal.x;
 			sme[ 4 ] = - lightPosition4D.x * plane.normal.y;
 			sme[ 8 ] = - lightPosition4D.x * plane.normal.z;
@@ -46,11 +44,13 @@
 			sme[ 7 ] = - lightPosition4D.w * plane.normal.y;
 			sme[ 11 ] = - lightPosition4D.w * plane.normal.z;
 			sme[ 15 ] = dot - lightPosition4D.w * - plane.constant;
-			this.matrix.multiplyMatrices( shadowMatrix, this.meshMatrix );
+			this.matrix.multiplyMatrices( _shadowMatrix, this.meshMatrix );
 
-		};
+		}
 
-	}();
+	}
+
+	ShadowMesh.prototype.isShadowMesh = true;
 
 	THREE.ShadowMesh = ShadowMesh;
 

+ 17 - 13
examples/js/objects/Sky.js

@@ -14,22 +14,26 @@
  * Three.js integration by zz85 http://twitter.com/blurspline
 */
 
-	var Sky = function () {
+	class Sky extends THREE.Mesh {
 
-		var shader = Sky.SkyShader;
-		var material = new THREE.ShaderMaterial( {
-			name: 'SkyShader',
-			fragmentShader: shader.fragmentShader,
-			vertexShader: shader.vertexShader,
-			uniforms: THREE.UniformsUtils.clone( shader.uniforms ),
-			side: THREE.BackSide,
-			depthWrite: false
-		} );
-		THREE.Mesh.call( this, new THREE.BoxGeometry( 1, 1, 1 ), material );
+		constructor() {
 
-	};
+			const shader = Sky.SkyShader;
+			const material = new THREE.ShaderMaterial( {
+				name: 'SkyShader',
+				fragmentShader: shader.fragmentShader,
+				vertexShader: shader.vertexShader,
+				uniforms: THREE.UniformsUtils.clone( shader.uniforms ),
+				side: THREE.BackSide,
+				depthWrite: false
+			} );
+			super( new THREE.BoxGeometry( 1, 1, 1 ), material );
+
+		}
+
+	}
 
-	Sky.prototype = Object.create( THREE.Mesh.prototype );
+	Sky.prototype.isSky = true;
 	Sky.SkyShader = {
 		uniforms: {
 			'turbidity': {

Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 81 - 42
examples/js/objects/Water.js


+ 121 - 119
examples/js/objects/Water2.js

@@ -7,158 +7,160 @@
  *
  */
 
-	var Water = function ( geometry, options ) {
-
-		THREE.Mesh.call( this, geometry );
-		this.type = 'Water';
-		var scope = this;
-		options = options || {};
-		var color = options.color !== undefined ? new THREE.Color( options.color ) : new THREE.Color( 0xFFFFFF );
-		var textureWidth = options.textureWidth || 512;
-		var textureHeight = options.textureHeight || 512;
-		var clipBias = options.clipBias || 0;
-		var flowDirection = options.flowDirection || new THREE.Vector2( 1, 0 );
-		var flowSpeed = options.flowSpeed || 0.03;
-		var reflectivity = options.reflectivity || 0.02;
-		var scale = options.scale || 1;
-		var shader = options.shader || Water.WaterShader;
-		var encoding = options.encoding !== undefined ? options.encoding : THREE.LinearEncoding;
-		var textureLoader = new THREE.TextureLoader();
-		var flowMap = options.flowMap || undefined;
-		var normalMap0 = options.normalMap0 || textureLoader.load( 'textures/water/Water_1_M_Normal.jpg' );
-		var normalMap1 = options.normalMap1 || textureLoader.load( 'textures/water/Water_2_M_Normal.jpg' );
-		var cycle = 0.15; // a cycle of a flow map phase
-
-		var halfCycle = cycle * 0.5;
-		var textureMatrix = new THREE.Matrix4();
-		var clock = new THREE.Clock(); // internal components
-
-		if ( THREE.Reflector === undefined ) {
-
-			console.error( 'THREE.Water: Required component THREE.Reflector not found.' );
-			return;
+	class Water extends THREE.Mesh {
+
+		constructor( geometry, options = {} ) {
+
+			super( geometry );
+			this.type = 'Water';
+			const scope = this;
+			const color = options.color !== undefined ? new THREE.Color( options.color ) : new THREE.Color( 0xFFFFFF );
+			const textureWidth = options.textureWidth || 512;
+			const textureHeight = options.textureHeight || 512;
+			const clipBias = options.clipBias || 0;
+			const flowDirection = options.flowDirection || new THREE.Vector2( 1, 0 );
+			const flowSpeed = options.flowSpeed || 0.03;
+			const reflectivity = options.reflectivity || 0.02;
+			const scale = options.scale || 1;
+			const shader = options.shader || Water.WaterShader;
+			const encoding = options.encoding !== undefined ? options.encoding : THREE.LinearEncoding;
+			const textureLoader = new THREE.TextureLoader();
+			const flowMap = options.flowMap || undefined;
+			const normalMap0 = options.normalMap0 || textureLoader.load( 'textures/water/Water_1_M_Normal.jpg' );
+			const normalMap1 = options.normalMap1 || textureLoader.load( 'textures/water/Water_2_M_Normal.jpg' );
+			const cycle = 0.15; // a cycle of a flow map phase
+
+			const halfCycle = cycle * 0.5;
+			const textureMatrix = new THREE.Matrix4();
+			const clock = new THREE.Clock(); // internal components
+
+			if ( THREE.Reflector === undefined ) {
+
+				console.error( 'THREE.Water: Required component THREE.Reflector not found.' );
+				return;
 
-		}
+			}
 
-		if ( THREE.Refractor === undefined ) {
+			if ( THREE.Refractor === undefined ) {
 
-			console.error( 'THREE.Water: Required component THREE.Refractor not found.' );
-			return;
+				console.error( 'THREE.Water: Required component THREE.Refractor not found.' );
+				return;
 
-		}
+			}
 
-		var reflector = new THREE.Reflector( geometry, {
-			textureWidth: textureWidth,
-			textureHeight: textureHeight,
-			clipBias: clipBias,
-			encoding: encoding
-		} );
-		var refractor = new THREE.Refractor( geometry, {
-			textureWidth: textureWidth,
-			textureHeight: textureHeight,
-			clipBias: clipBias,
-			encoding: encoding
-		} );
-		reflector.matrixAutoUpdate = false;
-		refractor.matrixAutoUpdate = false; // material
-
-		this.material = new THREE.ShaderMaterial( {
-			uniforms: THREE.UniformsUtils.merge( [ THREE.UniformsLib[ 'fog' ], shader.uniforms ] ),
-			vertexShader: shader.vertexShader,
-			fragmentShader: shader.fragmentShader,
-			transparent: true,
-			fog: true
-		} );
-
-		if ( flowMap !== undefined ) {
-
-			this.material.defines.USE_FLOWMAP = '';
-			this.material.uniforms[ 'tFlowMap' ] = {
-				type: 't',
-				value: flowMap
-			};
+			const reflector = new THREE.Reflector( geometry, {
+				textureWidth: textureWidth,
+				textureHeight: textureHeight,
+				clipBias: clipBias,
+				encoding: encoding
+			} );
+			const refractor = new THREE.Refractor( geometry, {
+				textureWidth: textureWidth,
+				textureHeight: textureHeight,
+				clipBias: clipBias,
+				encoding: encoding
+			} );
+			reflector.matrixAutoUpdate = false;
+			refractor.matrixAutoUpdate = false; // material
 
-		} else {
+			this.material = new THREE.ShaderMaterial( {
+				uniforms: THREE.UniformsUtils.merge( [ THREE.UniformsLib[ 'fog' ], shader.uniforms ] ),
+				vertexShader: shader.vertexShader,
+				fragmentShader: shader.fragmentShader,
+				transparent: true,
+				fog: true
+			} );
 
-			this.material.uniforms[ 'flowDirection' ] = {
-				type: 'v2',
-				value: flowDirection
-			};
+			if ( flowMap !== undefined ) {
 
-		} // maps
+				this.material.defines.USE_FLOWMAP = '';
+				this.material.uniforms[ 'tFlowMap' ] = {
+					type: 't',
+					value: flowMap
+				};
 
+			} else {
 
-		normalMap0.wrapS = normalMap0.wrapT = THREE.RepeatWrapping;
-		normalMap1.wrapS = normalMap1.wrapT = THREE.RepeatWrapping;
-		this.material.uniforms[ 'tReflectionMap' ].value = reflector.getRenderTarget().texture;
-		this.material.uniforms[ 'tRefractionMap' ].value = refractor.getRenderTarget().texture;
-		this.material.uniforms[ 'tNormalMap0' ].value = normalMap0;
-		this.material.uniforms[ 'tNormalMap1' ].value = normalMap1; // water
+				this.material.uniforms[ 'flowDirection' ] = {
+					type: 'v2',
+					value: flowDirection
+				};
 
-		this.material.uniforms[ 'color' ].value = color;
-		this.material.uniforms[ 'reflectivity' ].value = reflectivity;
-		this.material.uniforms[ 'textureMatrix' ].value = textureMatrix; // inital values
+			} // maps
 
-		this.material.uniforms[ 'config' ].value.x = 0; // flowMapOffset0
 
-		this.material.uniforms[ 'config' ].value.y = halfCycle; // flowMapOffset1
+			normalMap0.wrapS = normalMap0.wrapT = THREE.RepeatWrapping;
+			normalMap1.wrapS = normalMap1.wrapT = THREE.RepeatWrapping;
+			this.material.uniforms[ 'tReflectionMap' ].value = reflector.getRenderTarget().texture;
+			this.material.uniforms[ 'tRefractionMap' ].value = refractor.getRenderTarget().texture;
+			this.material.uniforms[ 'tNormalMap0' ].value = normalMap0;
+			this.material.uniforms[ 'tNormalMap1' ].value = normalMap1; // water
 
-		this.material.uniforms[ 'config' ].value.z = halfCycle; // halfCycle
+			this.material.uniforms[ 'color' ].value = color;
+			this.material.uniforms[ 'reflectivity' ].value = reflectivity;
+			this.material.uniforms[ 'textureMatrix' ].value = textureMatrix; // inital values
 
-		this.material.uniforms[ 'config' ].value.w = scale; // scale
-		// functions
+			this.material.uniforms[ 'config' ].value.x = 0; // flowMapOffset0
 
-		function updateTextureMatrix( camera ) {
+			this.material.uniforms[ 'config' ].value.y = halfCycle; // flowMapOffset1
 
-			textureMatrix.set( 0.5, 0.0, 0.0, 0.5, 0.0, 0.5, 0.0, 0.5, 0.0, 0.0, 0.5, 0.5, 0.0, 0.0, 0.0, 1.0 );
-			textureMatrix.multiply( camera.projectionMatrix );
-			textureMatrix.multiply( camera.matrixWorldInverse );
-			textureMatrix.multiply( scope.matrixWorld );
+			this.material.uniforms[ 'config' ].value.z = halfCycle; // halfCycle
 
-		}
+			this.material.uniforms[ 'config' ].value.w = scale; // scale
+			// functions
 
-		function updateFlow() {
+			function updateTextureMatrix( camera ) {
 
-			var delta = clock.getDelta();
-			var config = scope.material.uniforms[ 'config' ];
-			config.value.x += flowSpeed * delta; // flowMapOffset0
+				textureMatrix.set( 0.5, 0.0, 0.0, 0.5, 0.0, 0.5, 0.0, 0.5, 0.0, 0.0, 0.5, 0.5, 0.0, 0.0, 0.0, 1.0 );
+				textureMatrix.multiply( camera.projectionMatrix );
+				textureMatrix.multiply( camera.matrixWorldInverse );
+				textureMatrix.multiply( scope.matrixWorld );
 
-			config.value.y = config.value.x + halfCycle; // flowMapOffset1
-			// Important: The distance between offsets should be always the value of "halfCycle".
-			// Moreover, both offsets should be in the range of [ 0, cycle ].
-			// This approach ensures a smooth water flow and avoids "reset" effects.
+			}
 
-			if ( config.value.x >= cycle ) {
+			function updateFlow() {
 
-				config.value.x = 0;
-				config.value.y = halfCycle;
+				const delta = clock.getDelta();
+				const config = scope.material.uniforms[ 'config' ];
+				config.value.x += flowSpeed * delta; // flowMapOffset0
 
-			} else if ( config.value.y >= cycle ) {
+				config.value.y = config.value.x + halfCycle; // flowMapOffset1
+				// Important: The distance between offsets should be always the value of "halfCycle".
+				// Moreover, both offsets should be in the range of [ 0, cycle ].
+				// This approach ensures a smooth water flow and avoids "reset" effects.
 
-				config.value.y = config.value.y - cycle;
+				if ( config.value.x >= cycle ) {
 
-			}
+					config.value.x = 0;
+					config.value.y = halfCycle;
 
-		} //
+				} else if ( config.value.y >= cycle ) {
 
+					config.value.y = config.value.y - cycle;
 
-		this.onBeforeRender = function ( renderer, scene, camera ) {
+				}
 
-			updateTextureMatrix( camera );
-			updateFlow();
-			scope.visible = false;
-			reflector.matrixWorld.copy( scope.matrixWorld );
-			refractor.matrixWorld.copy( scope.matrixWorld );
-			reflector.onBeforeRender( renderer, scene, camera );
-			refractor.onBeforeRender( renderer, scene, camera );
-			scope.visible = true;
+			} //
 
-		};
 
-	};
+			this.onBeforeRender = function ( renderer, scene, camera ) {
+
+				updateTextureMatrix( camera );
+				updateFlow();
+				scope.visible = false;
+				reflector.matrixWorld.copy( scope.matrixWorld );
+				refractor.matrixWorld.copy( scope.matrixWorld );
+				reflector.onBeforeRender( renderer, scene, camera );
+				refractor.onBeforeRender( renderer, scene, camera );
+				scope.visible = true;
+
+			};
+
+		}
+
+	}
 
-	Water.prototype = Object.create( THREE.Mesh.prototype );
-	Water.prototype.constructor = Water;
+	Water.prototype.isWater = true;
 	Water.WaterShader = {
 		uniforms: {
 			'color': {

+ 181 - 175
examples/jsm/objects/Lensflare.js

@@ -17,281 +17,287 @@ import {
 	Vector4
 } from '../../../build/three.module.js';
 
-var Lensflare = function () {
+class Lensflare extends Mesh {
 
-	Mesh.call( this, Lensflare.Geometry, new MeshBasicMaterial( { opacity: 0, transparent: true } ) );
+	constructor() {
 
-	this.type = 'Lensflare';
-	this.frustumCulled = false;
-	this.renderOrder = Infinity;
+		super( Lensflare.Geometry, new MeshBasicMaterial( { opacity: 0, transparent: true } ) );
 
-	//
+		this.type = 'Lensflare';
+		this.frustumCulled = false;
+		this.renderOrder = Infinity;
 
-	var positionScreen = new Vector3();
-	var positionView = new Vector3();
+		//
 
-	// textures
+		const positionScreen = new Vector3();
+		const positionView = new Vector3();
 
-	var tempMap = new DataTexture( new Uint8Array( 16 * 16 * 3 ), 16, 16, RGBFormat );
-	tempMap.minFilter = NearestFilter;
-	tempMap.magFilter = NearestFilter;
-	tempMap.wrapS = ClampToEdgeWrapping;
-	tempMap.wrapT = ClampToEdgeWrapping;
+		// textures
 
-	var occlusionMap = new DataTexture( new Uint8Array( 16 * 16 * 3 ), 16, 16, RGBFormat );
-	occlusionMap.minFilter = NearestFilter;
-	occlusionMap.magFilter = NearestFilter;
-	occlusionMap.wrapS = ClampToEdgeWrapping;
-	occlusionMap.wrapT = ClampToEdgeWrapping;
+		const tempMap = new DataTexture( new Uint8Array( 16 * 16 * 3 ), 16, 16, RGBFormat );
+		tempMap.minFilter = NearestFilter;
+		tempMap.magFilter = NearestFilter;
+		tempMap.wrapS = ClampToEdgeWrapping;
+		tempMap.wrapT = ClampToEdgeWrapping;
 
-	// material
+		const occlusionMap = new DataTexture( new Uint8Array( 16 * 16 * 3 ), 16, 16, RGBFormat );
+		occlusionMap.minFilter = NearestFilter;
+		occlusionMap.magFilter = NearestFilter;
+		occlusionMap.wrapS = ClampToEdgeWrapping;
+		occlusionMap.wrapT = ClampToEdgeWrapping;
 
-	var geometry = Lensflare.Geometry;
+		// material
 
-	var material1a = new RawShaderMaterial( {
-		uniforms: {
-			'scale': { value: null },
-			'screenPosition': { value: null }
-		},
-		vertexShader: [
+		const geometry = Lensflare.Geometry;
 
-			'precision highp float;',
+		const material1a = new RawShaderMaterial( {
+			uniforms: {
+				'scale': { value: null },
+				'screenPosition': { value: null }
+			},
+			vertexShader: [
 
-			'uniform vec3 screenPosition;',
-			'uniform vec2 scale;',
+				'precision highp float;',
 
-			'attribute vec3 position;',
+				'uniform vec3 screenPosition;',
+				'uniform vec2 scale;',
 
-			'void main() {',
+				'attribute vec3 position;',
 
-			'	gl_Position = vec4( position.xy * scale + screenPosition.xy, screenPosition.z, 1.0 );',
+				'void main() {',
 
-			'}'
+				'	gl_Position = vec4( position.xy * scale + screenPosition.xy, screenPosition.z, 1.0 );',
 
-		].join( '\n' ),
-		fragmentShader: [
+				'}'
 
-			'precision highp float;',
+			].join( '\n' ),
+			fragmentShader: [
 
-			'void main() {',
+				'precision highp float;',
 
-			'	gl_FragColor = vec4( 1.0, 0.0, 1.0, 1.0 );',
+				'void main() {',
 
-			'}'
+				'	gl_FragColor = vec4( 1.0, 0.0, 1.0, 1.0 );',
 
-		].join( '\n' ),
-		depthTest: true,
-		depthWrite: false,
-		transparent: false
-	} );
+				'}'
 
-	var material1b = new RawShaderMaterial( {
-		uniforms: {
-			'map': { value: tempMap },
-			'scale': { value: null },
-			'screenPosition': { value: null }
-		},
-		vertexShader: [
+			].join( '\n' ),
+			depthTest: true,
+			depthWrite: false,
+			transparent: false
+		} );
 
-			'precision highp float;',
+		const material1b = new RawShaderMaterial( {
+			uniforms: {
+				'map': { value: tempMap },
+				'scale': { value: null },
+				'screenPosition': { value: null }
+			},
+			vertexShader: [
 
-			'uniform vec3 screenPosition;',
-			'uniform vec2 scale;',
+				'precision highp float;',
 
-			'attribute vec3 position;',
-			'attribute vec2 uv;',
+				'uniform vec3 screenPosition;',
+				'uniform vec2 scale;',
 
-			'varying vec2 vUV;',
+				'attribute vec3 position;',
+				'attribute vec2 uv;',
 
-			'void main() {',
+				'varying vec2 vUV;',
 
-			'	vUV = uv;',
+				'void main() {',
 
-			'	gl_Position = vec4( position.xy * scale + screenPosition.xy, screenPosition.z, 1.0 );',
+				'	vUV = uv;',
 
-			'}'
+				'	gl_Position = vec4( position.xy * scale + screenPosition.xy, screenPosition.z, 1.0 );',
 
-		].join( '\n' ),
-		fragmentShader: [
+				'}'
 
-			'precision highp float;',
+			].join( '\n' ),
+			fragmentShader: [
 
-			'uniform sampler2D map;',
+				'precision highp float;',
 
-			'varying vec2 vUV;',
+				'uniform sampler2D map;',
 
-			'void main() {',
+				'varying vec2 vUV;',
 
-			'	gl_FragColor = texture2D( map, vUV );',
+				'void main() {',
 
-			'}'
+				'	gl_FragColor = texture2D( map, vUV );',
 
-		].join( '\n' ),
-		depthTest: false,
-		depthWrite: false,
-		transparent: false
-	} );
+				'}'
 
-	// the following object is used for occlusionMap generation
+			].join( '\n' ),
+			depthTest: false,
+			depthWrite: false,
+			transparent: false
+		} );
 
-	var mesh1 = new Mesh( geometry, material1a );
+		// the following object is used for occlusionMap generation
 
-	//
+		const mesh1 = new Mesh( geometry, material1a );
 
-	var elements = [];
+		//
 
-	var shader = LensflareElement.Shader;
+		const elements = [];
 
-	var material2 = new RawShaderMaterial( {
-		uniforms: {
-			'map': { value: null },
-			'occlusionMap': { value: occlusionMap },
-			'color': { value: new Color( 0xffffff ) },
-			'scale': { value: new Vector2() },
-			'screenPosition': { value: new Vector3() }
-		},
-		vertexShader: shader.vertexShader,
-		fragmentShader: shader.fragmentShader,
-		blending: AdditiveBlending,
-		transparent: true,
-		depthWrite: false
-	} );
+		const shader = LensflareElement.Shader;
 
-	var mesh2 = new Mesh( geometry, material2 );
+		const material2 = new RawShaderMaterial( {
+			uniforms: {
+				'map': { value: null },
+				'occlusionMap': { value: occlusionMap },
+				'color': { value: new Color( 0xffffff ) },
+				'scale': { value: new Vector2() },
+				'screenPosition': { value: new Vector3() }
+			},
+			vertexShader: shader.vertexShader,
+			fragmentShader: shader.fragmentShader,
+			blending: AdditiveBlending,
+			transparent: true,
+			depthWrite: false
+		} );
 
-	this.addElement = function ( element ) {
+		const mesh2 = new Mesh( geometry, material2 );
 
-		elements.push( element );
+		this.addElement = function ( element ) {
 
-	};
+			elements.push( element );
 
-	//
+		};
 
-	var scale = new Vector2();
-	var screenPositionPixels = new Vector2();
-	var validArea = new Box2();
-	var viewport = new Vector4();
+		//
 
-	this.onBeforeRender = function ( renderer, scene, camera ) {
+		const scale = new Vector2();
+		const screenPositionPixels = new Vector2();
+		const validArea = new Box2();
+		const viewport = new Vector4();
 
-		renderer.getCurrentViewport( viewport );
+		this.onBeforeRender = function ( renderer, scene, camera ) {
 
-		var invAspect = viewport.w / viewport.z;
-		var halfViewportWidth = viewport.z / 2.0;
-		var halfViewportHeight = viewport.w / 2.0;
+			renderer.getCurrentViewport( viewport );
 
-		var size = 16 / viewport.w;
-		scale.set( size * invAspect, size );
+			const invAspect = viewport.w / viewport.z;
+			const halfViewportWidth = viewport.z / 2.0;
+			const halfViewportHeight = viewport.w / 2.0;
 
-		validArea.min.set( viewport.x, viewport.y );
-		validArea.max.set( viewport.x + ( viewport.z - 16 ), viewport.y + ( viewport.w - 16 ) );
+			let size = 16 / viewport.w;
+			scale.set( size * invAspect, size );
 
-		// calculate position in screen space
+			validArea.min.set( viewport.x, viewport.y );
+			validArea.max.set( viewport.x + ( viewport.z - 16 ), viewport.y + ( viewport.w - 16 ) );
 
-		positionView.setFromMatrixPosition( this.matrixWorld );
-		positionView.applyMatrix4( camera.matrixWorldInverse );
+			// calculate position in screen space
 
-		if ( positionView.z > 0 ) return; // lensflare is behind the camera
+			positionView.setFromMatrixPosition( this.matrixWorld );
+			positionView.applyMatrix4( camera.matrixWorldInverse );
 
-		positionScreen.copy( positionView ).applyMatrix4( camera.projectionMatrix );
+			if ( positionView.z > 0 ) return; // lensflare is behind the camera
 
-		// horizontal and vertical coordinate of the lower left corner of the pixels to copy
+			positionScreen.copy( positionView ).applyMatrix4( camera.projectionMatrix );
 
-		screenPositionPixels.x = viewport.x + ( positionScreen.x * halfViewportWidth ) + halfViewportWidth - 8;
-		screenPositionPixels.y = viewport.y + ( positionScreen.y * halfViewportHeight ) + halfViewportHeight - 8;
+			// horizontal and vertical coordinate of the lower left corner of the pixels to copy
 
-		// screen cull
+			screenPositionPixels.x = viewport.x + ( positionScreen.x * halfViewportWidth ) + halfViewportWidth - 8;
+			screenPositionPixels.y = viewport.y + ( positionScreen.y * halfViewportHeight ) + halfViewportHeight - 8;
 
-		if ( validArea.containsPoint( screenPositionPixels ) ) {
+			// screen cull
 
-			// save current RGB to temp texture
+			if ( validArea.containsPoint( screenPositionPixels ) ) {
 
-			renderer.copyFramebufferToTexture( screenPositionPixels, tempMap );
+				// save current RGB to temp texture
 
-			// render pink quad
+				renderer.copyFramebufferToTexture( screenPositionPixels, tempMap );
 
-			var uniforms = material1a.uniforms;
-			uniforms[ 'scale' ].value = scale;
-			uniforms[ 'screenPosition' ].value = positionScreen;
+				// render pink quad
 
-			renderer.renderBufferDirect( camera, null, geometry, material1a, mesh1, null );
+				let uniforms = material1a.uniforms;
+				uniforms[ 'scale' ].value = scale;
+				uniforms[ 'screenPosition' ].value = positionScreen;
 
-			// copy result to occlusionMap
+				renderer.renderBufferDirect( camera, null, geometry, material1a, mesh1, null );
 
-			renderer.copyFramebufferToTexture( screenPositionPixels, occlusionMap );
+				// copy result to occlusionMap
 
-			// restore graphics
+				renderer.copyFramebufferToTexture( screenPositionPixels, occlusionMap );
 
-			var uniforms = material1b.uniforms;
-			uniforms[ 'scale' ].value = scale;
-			uniforms[ 'screenPosition' ].value = positionScreen;
+				// restore graphics
 
-			renderer.renderBufferDirect( camera, null, geometry, material1b, mesh1, null );
+				uniforms = material1b.uniforms;
+				uniforms[ 'scale' ].value = scale;
+				uniforms[ 'screenPosition' ].value = positionScreen;
 
-			// render elements
+				renderer.renderBufferDirect( camera, null, geometry, material1b, mesh1, null );
 
-			var vecX = - positionScreen.x * 2;
-			var vecY = - positionScreen.y * 2;
+				// render elements
 
-			for ( var i = 0, l = elements.length; i < l; i ++ ) {
+				const vecX = - positionScreen.x * 2;
+				const vecY = - positionScreen.y * 2;
 
-				var element = elements[ i ];
+				for ( let i = 0, l = elements.length; i < l; i ++ ) {
 
-				var uniforms = material2.uniforms;
+					const element = elements[ i ];
 
-				uniforms[ 'color' ].value.copy( element.color );
-				uniforms[ 'map' ].value = element.texture;
-				uniforms[ 'screenPosition' ].value.x = positionScreen.x + vecX * element.distance;
-				uniforms[ 'screenPosition' ].value.y = positionScreen.y + vecY * element.distance;
+					const uniforms = material2.uniforms;
 
-				var size = element.size / viewport.w;
-				var invAspect = viewport.w / viewport.z;
+					uniforms[ 'color' ].value.copy( element.color );
+					uniforms[ 'map' ].value = element.texture;
+					uniforms[ 'screenPosition' ].value.x = positionScreen.x + vecX * element.distance;
+					uniforms[ 'screenPosition' ].value.y = positionScreen.y + vecY * element.distance;
 
-				uniforms[ 'scale' ].value.set( size * invAspect, size );
+					size = element.size / viewport.w;
+					const invAspect = viewport.w / viewport.z;
 
-				material2.uniformsNeedUpdate = true;
+					uniforms[ 'scale' ].value.set( size * invAspect, size );
 
-				renderer.renderBufferDirect( camera, null, geometry, material2, mesh2, null );
+					material2.uniformsNeedUpdate = true;
+
+					renderer.renderBufferDirect( camera, null, geometry, material2, mesh2, null );
+
+				}
 
 			}
 
-		}
+		};
 
-	};
+		this.dispose = function () {
 
-	this.dispose = function () {
+			material1a.dispose();
+			material1b.dispose();
+			material2.dispose();
 
-		material1a.dispose();
-		material1b.dispose();
-		material2.dispose();
+			tempMap.dispose();
+			occlusionMap.dispose();
 
-		tempMap.dispose();
-		occlusionMap.dispose();
+			for ( let i = 0, l = elements.length; i < l; i ++ ) {
 
-		for ( var i = 0, l = elements.length; i < l; i ++ ) {
+				elements[ i ].texture.dispose();
 
-			elements[ i ].texture.dispose();
+			}
 
-		}
+		};
 
-	};
+	}
 
-};
+}
 
-Lensflare.prototype = Object.create( Mesh.prototype );
-Lensflare.prototype.constructor = Lensflare;
 Lensflare.prototype.isLensflare = true;
 
 //
 
-var LensflareElement = function ( texture, size, distance, color ) {
+class LensflareElement {
 
-	this.texture = texture;
-	this.size = size || 1;
-	this.distance = distance || 0;
-	this.color = color || new Color( 0xffffff );
+	constructor( texture, size = 1, distance = 0, color = new Color( 0xffffff ) ) {
 
-};
+		this.texture = texture;
+		this.size = size;
+		this.distance = distance;
+		this.color = color;
+
+	}
+
+}
 
 LensflareElement.Shader = {
 
@@ -371,16 +377,16 @@ LensflareElement.Shader = {
 
 Lensflare.Geometry = ( function () {
 
-	var geometry = new BufferGeometry();
+	const geometry = new BufferGeometry();
 
-	var float32Array = new Float32Array( [
+	const float32Array = new Float32Array( [
 		- 1, - 1, 0, 0, 0,
 		1, - 1, 0, 1, 0,
 		1, 1, 0, 1, 1,
 		- 1, 1, 0, 0, 1
 	] );
 
-	var interleavedBuffer = new InterleavedBuffer( float32Array, 5 );
+	const interleavedBuffer = new InterleavedBuffer( float32Array, 5 );
 
 	geometry.setIndex( [ 0, 1, 2,	0, 2, 3 ] );
 	geometry.setAttribute( 'position', new InterleavedBufferAttribute( interleavedBuffer, 3, 0, false ) );

+ 102 - 103
examples/jsm/objects/LightningStorm.js

@@ -12,7 +12,7 @@ import { LightningStrike } from '../geometries/LightningStrike.js';
  *
  * Usage
  *
- * var myStorm = new LightningStorm( paramsObject );
+ * const myStorm = new LightningStorm( paramsObject );
  * myStorm.position.set( ... );
  * scene.add( myStorm );
  * ...
@@ -52,195 +52,194 @@ import { LightningStrike } from '../geometries/LightningStrike.js';
  *
 */
 
-var LightningStorm = function ( stormParams ) {
+class LightningStorm extends Object3D {
 
-	Object3D.call( this );
+	constructor( stormParams = {} ) {
 
-	// Parameters
+		super();
 
-	stormParams = stormParams || {};
-	this.stormParams = stormParams;
+		// Parameters
 
-	stormParams.size = stormParams.size !== undefined ? stormParams.size : 1000.0;
-	stormParams.minHeight = stormParams.minHeight !== undefined ? stormParams.minHeight : 80.0;
-	stormParams.maxHeight = stormParams.maxHeight !== undefined ? stormParams.maxHeight : 100.0;
-	stormParams.maxSlope = stormParams.maxSlope !== undefined ? stormParams.maxSlope : 1.1;
+		this.stormParams = stormParams;
 
-	stormParams.maxLightnings = stormParams.maxLightnings !== undefined ? stormParams.maxLightnings : 3;
+		stormParams.size = stormParams.size !== undefined ? stormParams.size : 1000.0;
+		stormParams.minHeight = stormParams.minHeight !== undefined ? stormParams.minHeight : 80.0;
+		stormParams.maxHeight = stormParams.maxHeight !== undefined ? stormParams.maxHeight : 100.0;
+		stormParams.maxSlope = stormParams.maxSlope !== undefined ? stormParams.maxSlope : 1.1;
 
-	stormParams.lightningMinPeriod = stormParams.lightningMinPeriod !== undefined ? stormParams.lightningMinPeriod : 3.0;
-	stormParams.lightningMaxPeriod = stormParams.lightningMaxPeriod !== undefined ? stormParams.lightningMaxPeriod : 7.0;
+		stormParams.maxLightnings = stormParams.maxLightnings !== undefined ? stormParams.maxLightnings : 3;
 
-	stormParams.lightningMinDuration = stormParams.lightningMinDuration !== undefined ? stormParams.lightningMinDuration : 1.0;
-	stormParams.lightningMaxDuration = stormParams.lightningMaxDuration !== undefined ? stormParams.lightningMaxDuration : 2.5;
+		stormParams.lightningMinPeriod = stormParams.lightningMinPeriod !== undefined ? stormParams.lightningMinPeriod : 3.0;
+		stormParams.lightningMaxPeriod = stormParams.lightningMaxPeriod !== undefined ? stormParams.lightningMaxPeriod : 7.0;
 
-	this.lightningParameters = LightningStrike.copyParameters( stormParams.lightningParameters, stormParams.lightningParameters );
+		stormParams.lightningMinDuration = stormParams.lightningMinDuration !== undefined ? stormParams.lightningMinDuration : 1.0;
+		stormParams.lightningMaxDuration = stormParams.lightningMaxDuration !== undefined ? stormParams.lightningMaxDuration : 2.5;
 
-	this.lightningParameters.isEternal = false;
+		this.lightningParameters = LightningStrike.copyParameters( stormParams.lightningParameters, stormParams.lightningParameters );
 
-	this.lightningMaterial = stormParams.lightningMaterial !== undefined ? stormParams.lightningMaterial : new MeshBasicMaterial( { color: 0xB0FFFF } );
+		this.lightningParameters.isEternal = false;
 
-	if ( stormParams.onRayPosition !== undefined ) {
+		this.lightningMaterial = stormParams.lightningMaterial !== undefined ? stormParams.lightningMaterial : new MeshBasicMaterial( { color: 0xB0FFFF } );
 
-		this.onRayPosition = stormParams.onRayPosition;
+		if ( stormParams.onRayPosition !== undefined ) {
 
-	} else {
+			this.onRayPosition = stormParams.onRayPosition;
 
-		this.onRayPosition = function ( source, dest ) {
+		} else {
 
-			dest.set( ( Math.random() - 0.5 ) * stormParams.size, 0, ( Math.random() - 0.5 ) * stormParams.size );
+			this.onRayPosition = function ( source, dest ) {
 
-			var height = MathUtils.lerp( stormParams.minHeight, stormParams.maxHeight, Math.random() );
+				dest.set( ( Math.random() - 0.5 ) * stormParams.size, 0, ( Math.random() - 0.5 ) * stormParams.size );
 
-			source.set( stormParams.maxSlope * ( 2 * Math.random() - 1 ), 1, stormParams.maxSlope * ( 2 * Math.random() - 1 ) ).multiplyScalar( height ).add( dest );
+				const height = MathUtils.lerp( stormParams.minHeight, stormParams.maxHeight, Math.random() );
 
-		};
+				source.set( stormParams.maxSlope * ( 2 * Math.random() - 1 ), 1, stormParams.maxSlope * ( 2 * Math.random() - 1 ) ).multiplyScalar( height ).add( dest );
 
-	}
+			};
 
-	this.onLightningDown = stormParams.onLightningDown;
+		}
 
-	// Internal state
+		this.onLightningDown = stormParams.onLightningDown;
 
-	this.inited = false;
-	this.nextLightningTime = 0;
-	this.lightningsMeshes = [];
-	this.deadLightningsMeshes = [];
+		// Internal state
 
-	for ( var i = 0; i < this.stormParams.maxLightnings; i ++ ) {
+		this.inited = false;
+		this.nextLightningTime = 0;
+		this.lightningsMeshes = [];
+		this.deadLightningsMeshes = [];
 
-		var lightning = new LightningStrike( LightningStrike.copyParameters( {}, this.lightningParameters ) );
-		var mesh = new Mesh( lightning, this.lightningMaterial );
-		this.deadLightningsMeshes.push( mesh );
+		for ( let i = 0; i < this.stormParams.maxLightnings; i ++ ) {
 
-	}
+			const lightning = new LightningStrike( LightningStrike.copyParameters( {}, this.lightningParameters ) );
+			const mesh = new Mesh( lightning, this.lightningMaterial );
+			this.deadLightningsMeshes.push( mesh );
 
-};
+		}
 
-LightningStorm.prototype = Object.create( Object3D.prototype );
+	}
 
-LightningStorm.prototype.constructor = LightningStorm;
+	update( time ) {
 
-LightningStorm.prototype.isLightningStorm = true;
+		if ( ! this.inited ) {
 
-LightningStorm.prototype.update = function ( time ) {
+			this.nextLightningTime = this.getNextLightningTime( time ) * Math.random();
+			this.inited = true;
 
-	if ( ! this.inited ) {
+		}
 
-		this.nextLightningTime = this.getNextLightningTime( time ) * Math.random();
-		this.inited = true;
+		if ( time >= this.nextLightningTime ) {
 
-	}
+			// Lightning creation
 
-	if ( time >= this.nextLightningTime ) {
+			const lightningMesh = this.deadLightningsMeshes.pop();
 
-		// Lightning creation
+			if ( lightningMesh ) {
 
-		var lightningMesh = this.deadLightningsMeshes.pop();
+				const lightningParams1 = LightningStrike.copyParameters( lightningMesh.geometry.rayParameters, this.lightningParameters );
 
-		if ( lightningMesh ) {
+				lightningParams1.birthTime = time;
+				lightningParams1.deathTime = time + MathUtils.lerp( this.stormParams.lightningMinDuration, this.stormParams.lightningMaxDuration, Math.random() );
 
-			var lightningParams1 = LightningStrike.copyParameters( lightningMesh.geometry.rayParameters, this.lightningParameters );
+				this.onRayPosition( lightningParams1.sourceOffset, lightningParams1.destOffset );
 
-			lightningParams1.birthTime = time;
-			lightningParams1.deathTime = time + MathUtils.lerp( this.stormParams.lightningMinDuration, this.stormParams.lightningMaxDuration, Math.random() );
+				lightningParams1.noiseSeed = Math.random();
 
-			this.onRayPosition( lightningParams1.sourceOffset, lightningParams1.destOffset );
+				this.add( lightningMesh );
 
-			lightningParams1.noiseSeed = Math.random();
+				this.lightningsMeshes.push( lightningMesh );
 
-			this.add( lightningMesh );
+			}
 
-			this.lightningsMeshes.push( lightningMesh );
+			// Schedule next lightning
+			this.nextLightningTime = this.getNextLightningTime( time );
 
 		}
 
-		// Schedule next lightning
-		this.nextLightningTime = this.getNextLightningTime( time );
+		let i = 0, il = this.lightningsMeshes.length;
 
-	}
-
-	var i = 0, il = this.lightningsMeshes.length;
+		while ( i < il ) {
 
-	while ( i < il ) {
+			const mesh = this.lightningsMeshes[ i ];
 
-		var mesh = this.lightningsMeshes[ i ];
+			const lightning = mesh.geometry;
 
-		var lightning = mesh.geometry;
+			const prevState = lightning.state;
 
-		var prevState = lightning.state;
+			lightning.update( time );
 
-		lightning.update( time );
+			if ( prevState === LightningStrike.RAY_PROPAGATING && lightning.state > prevState ) {
 
-		if ( prevState === LightningStrike.RAY_PROPAGATING && lightning.state > prevState ) {
+				if ( this.onLightningDown ) {
 
-			if ( this.onLightningDown ) {
+					this.onLightningDown( lightning );
 
-				this.onLightningDown( lightning );
+				}
 
 			}
 
-		}
+			if ( lightning.state === LightningStrike.RAY_EXTINGUISHED ) {
 
-		if ( lightning.state === LightningStrike.RAY_EXTINGUISHED ) {
+				// Lightning is to be destroyed
 
-			// Lightning is to be destroyed
+				this.lightningsMeshes.splice( this.lightningsMeshes.indexOf( mesh ), 1 );
 
-			this.lightningsMeshes.splice( this.lightningsMeshes.indexOf( mesh ), 1 );
+				this.deadLightningsMeshes.push( mesh );
 
-			this.deadLightningsMeshes.push( mesh );
+				this.remove( mesh );
 
-			this.remove( mesh );
+				il --;
 
-			il --;
+			} else {
 
-		} else {
+				i ++;
 
-			i ++;
+			}
 
 		}
 
 	}
 
-};
+	getNextLightningTime( currentTime ) {
 
-LightningStorm.prototype.getNextLightningTime = function ( currentTime ) {
+		return currentTime + MathUtils.lerp( this.stormParams.lightningMinPeriod, this.stormParams.lightningMaxPeriod, Math.random() ) / ( this.stormParams.maxLightnings + 1 );
 
-	return currentTime + MathUtils.lerp( this.stormParams.lightningMinPeriod, this.stormParams.lightningMaxPeriod, Math.random() ) / ( this.stormParams.maxLightnings + 1 );
+	}
 
-};
+	copy( source ) {
 
-LightningStorm.prototype.copy = function ( source ) {
+		super.copy( source );
 
-	Object3D.prototype.copy.call( this, source );
+		this.stormParams.size = source.stormParams.size;
+		this.stormParams.minHeight = source.stormParams.minHeight;
+		this.stormParams.maxHeight = source.stormParams.maxHeight;
+		this.stormParams.maxSlope = source.stormParams.maxSlope;
 
-	this.stormParams.size = source.stormParams.size;
-	this.stormParams.minHeight = source.stormParams.minHeight;
-	this.stormParams.maxHeight = source.stormParams.maxHeight;
-	this.stormParams.maxSlope = source.stormParams.maxSlope;
+		this.stormParams.maxLightnings = source.stormParams.maxLightnings;
 
-	this.stormParams.maxLightnings = source.stormParams.maxLightnings;
+		this.stormParams.lightningMinPeriod = source.stormParams.lightningMinPeriod;
+		this.stormParams.lightningMaxPeriod = source.stormParams.lightningMaxPeriod;
 
-	this.stormParams.lightningMinPeriod = source.stormParams.lightningMinPeriod;
-	this.stormParams.lightningMaxPeriod = source.stormParams.lightningMaxPeriod;
+		this.stormParams.lightningMinDuration = source.stormParams.lightningMinDuration;
+		this.stormParams.lightningMaxDuration = source.stormParams.lightningMaxDuration;
 
-	this.stormParams.lightningMinDuration = source.stormParams.lightningMinDuration;
-	this.stormParams.lightningMaxDuration = source.stormParams.lightningMaxDuration;
+		this.lightningParameters = LightningStrike.copyParameters( {}, source.lightningParameters );
 
-	this.lightningParameters = LightningStrike.copyParameters( {}, source.lightningParameters );
+		this.lightningMaterial = source.stormParams.lightningMaterial;
 
-	this.lightningMaterial = source.stormParams.lightningMaterial;
+		this.onLightningDown = source.onLightningDown;
 
-	this.onLightningDown = source.onLightningDown;
+		return this;
 
-	return this;
+	}
 
-};
+	clone() {
 
-LightningStrike.prototype.clone = function () {
+		return new this.constructor( this.stormParams ).copy( this );
 
-	return new this.constructor( this.stormParams ).copy( this );
+	}
 
-};
+}
+
+LightningStorm.prototype.isLightningStorm = true;
 
 export { LightningStorm };

Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 453 - 447
examples/jsm/objects/MarchingCubes.js


+ 123 - 122
examples/jsm/objects/Reflector.js

@@ -14,189 +14,190 @@ import {
 	WebGLRenderTarget
 } from '../../../build/three.module.js';
 
-var Reflector = function ( geometry, options ) {
+class Reflector extends Mesh {
 
-	Mesh.call( this, geometry );
+	constructor( geometry, options = {} ) {
 
-	this.type = 'Reflector';
+		super( geometry );
 
-	var scope = this;
+		this.type = 'Reflector';
 
-	options = options || {};
+		const scope = this;
 
-	var color = ( options.color !== undefined ) ? new Color( options.color ) : new Color( 0x7F7F7F );
-	var textureWidth = options.textureWidth || 512;
-	var textureHeight = options.textureHeight || 512;
-	var clipBias = options.clipBias || 0;
-	var shader = options.shader || Reflector.ReflectorShader;
+		const color = ( options.color !== undefined ) ? new Color( options.color ) : new Color( 0x7F7F7F );
+		const textureWidth = options.textureWidth || 512;
+		const textureHeight = options.textureHeight || 512;
+		const clipBias = options.clipBias || 0;
+		const shader = options.shader || Reflector.ReflectorShader;
 
-	//
+		//
 
-	var reflectorPlane = new Plane();
-	var normal = new Vector3();
-	var reflectorWorldPosition = new Vector3();
-	var cameraWorldPosition = new Vector3();
-	var rotationMatrix = new Matrix4();
-	var lookAtPosition = new Vector3( 0, 0, - 1 );
-	var clipPlane = new Vector4();
+		const reflectorPlane = new Plane();
+		const normal = new Vector3();
+		const reflectorWorldPosition = new Vector3();
+		const cameraWorldPosition = new Vector3();
+		const rotationMatrix = new Matrix4();
+		const lookAtPosition = new Vector3( 0, 0, - 1 );
+		const clipPlane = new Vector4();
 
-	var view = new Vector3();
-	var target = new Vector3();
-	var q = new Vector4();
+		const view = new Vector3();
+		const target = new Vector3();
+		const q = new Vector4();
 
-	var textureMatrix = new Matrix4();
-	var virtualCamera = new PerspectiveCamera();
+		const textureMatrix = new Matrix4();
+		const virtualCamera = new PerspectiveCamera();
 
-	var parameters = {
-		minFilter: LinearFilter,
-		magFilter: LinearFilter,
-		format: RGBFormat
-	};
+		const parameters = {
+			minFilter: LinearFilter,
+			magFilter: LinearFilter,
+			format: RGBFormat
+		};
 
-	var renderTarget = new WebGLRenderTarget( textureWidth, textureHeight, parameters );
+		const renderTarget = new WebGLRenderTarget( textureWidth, textureHeight, parameters );
 
-	if ( ! MathUtils.isPowerOfTwo( textureWidth ) || ! MathUtils.isPowerOfTwo( textureHeight ) ) {
+		if ( ! MathUtils.isPowerOfTwo( textureWidth ) || ! MathUtils.isPowerOfTwo( textureHeight ) ) {
 
-		renderTarget.texture.generateMipmaps = false;
+			renderTarget.texture.generateMipmaps = false;
 
-	}
+		}
 
-	var material = new ShaderMaterial( {
-		uniforms: UniformsUtils.clone( shader.uniforms ),
-		fragmentShader: shader.fragmentShader,
-		vertexShader: shader.vertexShader
-	} );
+		const material = new ShaderMaterial( {
+			uniforms: UniformsUtils.clone( shader.uniforms ),
+			fragmentShader: shader.fragmentShader,
+			vertexShader: shader.vertexShader
+		} );
 
-	material.uniforms[ 'tDiffuse' ].value = renderTarget.texture;
-	material.uniforms[ 'color' ].value = color;
-	material.uniforms[ 'textureMatrix' ].value = textureMatrix;
+		material.uniforms[ 'tDiffuse' ].value = renderTarget.texture;
+		material.uniforms[ 'color' ].value = color;
+		material.uniforms[ 'textureMatrix' ].value = textureMatrix;
 
-	this.material = material;
+		this.material = material;
 
-	this.onBeforeRender = function ( renderer, scene, camera ) {
+		this.onBeforeRender = function ( renderer, scene, camera ) {
 
-		reflectorWorldPosition.setFromMatrixPosition( scope.matrixWorld );
-		cameraWorldPosition.setFromMatrixPosition( camera.matrixWorld );
+			reflectorWorldPosition.setFromMatrixPosition( scope.matrixWorld );
+			cameraWorldPosition.setFromMatrixPosition( camera.matrixWorld );
 
-		rotationMatrix.extractRotation( scope.matrixWorld );
+			rotationMatrix.extractRotation( scope.matrixWorld );
 
-		normal.set( 0, 0, 1 );
-		normal.applyMatrix4( rotationMatrix );
+			normal.set( 0, 0, 1 );
+			normal.applyMatrix4( rotationMatrix );
 
-		view.subVectors( reflectorWorldPosition, cameraWorldPosition );
+			view.subVectors( reflectorWorldPosition, cameraWorldPosition );
 
-		// Avoid rendering when reflector is facing away
+			// Avoid rendering when reflector is facing away
 
-		if ( view.dot( normal ) > 0 ) return;
+			if ( view.dot( normal ) > 0 ) return;
 
-		view.reflect( normal ).negate();
-		view.add( reflectorWorldPosition );
+			view.reflect( normal ).negate();
+			view.add( reflectorWorldPosition );
 
-		rotationMatrix.extractRotation( camera.matrixWorld );
+			rotationMatrix.extractRotation( camera.matrixWorld );
 
-		lookAtPosition.set( 0, 0, - 1 );
-		lookAtPosition.applyMatrix4( rotationMatrix );
-		lookAtPosition.add( cameraWorldPosition );
+			lookAtPosition.set( 0, 0, - 1 );
+			lookAtPosition.applyMatrix4( rotationMatrix );
+			lookAtPosition.add( cameraWorldPosition );
 
-		target.subVectors( reflectorWorldPosition, lookAtPosition );
-		target.reflect( normal ).negate();
-		target.add( reflectorWorldPosition );
+			target.subVectors( reflectorWorldPosition, lookAtPosition );
+			target.reflect( normal ).negate();
+			target.add( reflectorWorldPosition );
 
-		virtualCamera.position.copy( view );
-		virtualCamera.up.set( 0, 1, 0 );
-		virtualCamera.up.applyMatrix4( rotationMatrix );
-		virtualCamera.up.reflect( normal );
-		virtualCamera.lookAt( target );
+			virtualCamera.position.copy( view );
+			virtualCamera.up.set( 0, 1, 0 );
+			virtualCamera.up.applyMatrix4( rotationMatrix );
+			virtualCamera.up.reflect( normal );
+			virtualCamera.lookAt( target );
 
-		virtualCamera.far = camera.far; // Used in WebGLBackground
+			virtualCamera.far = camera.far; // Used in WebGLBackground
 
-		virtualCamera.updateMatrixWorld();
-		virtualCamera.projectionMatrix.copy( camera.projectionMatrix );
+			virtualCamera.updateMatrixWorld();
+			virtualCamera.projectionMatrix.copy( camera.projectionMatrix );
 
-		// Update the texture matrix
-		textureMatrix.set(
-			0.5, 0.0, 0.0, 0.5,
-			0.0, 0.5, 0.0, 0.5,
-			0.0, 0.0, 0.5, 0.5,
-			0.0, 0.0, 0.0, 1.0
-		);
-		textureMatrix.multiply( virtualCamera.projectionMatrix );
-		textureMatrix.multiply( virtualCamera.matrixWorldInverse );
-		textureMatrix.multiply( scope.matrixWorld );
+			// Update the texture matrix
+			textureMatrix.set(
+				0.5, 0.0, 0.0, 0.5,
+				0.0, 0.5, 0.0, 0.5,
+				0.0, 0.0, 0.5, 0.5,
+				0.0, 0.0, 0.0, 1.0
+			);
+			textureMatrix.multiply( virtualCamera.projectionMatrix );
+			textureMatrix.multiply( virtualCamera.matrixWorldInverse );
+			textureMatrix.multiply( scope.matrixWorld );
 
-		// Now update projection matrix with new clip plane, implementing code from: http://www.terathon.com/code/oblique.html
-		// Paper explaining this technique: http://www.terathon.com/lengyel/Lengyel-Oblique.pdf
-		reflectorPlane.setFromNormalAndCoplanarPoint( normal, reflectorWorldPosition );
-		reflectorPlane.applyMatrix4( virtualCamera.matrixWorldInverse );
+			// Now update projection matrix with new clip plane, implementing code from: http://www.terathon.com/code/oblique.html
+			// Paper explaining this technique: http://www.terathon.com/lengyel/Lengyel-Oblique.pdf
+			reflectorPlane.setFromNormalAndCoplanarPoint( normal, reflectorWorldPosition );
+			reflectorPlane.applyMatrix4( virtualCamera.matrixWorldInverse );
 
-		clipPlane.set( reflectorPlane.normal.x, reflectorPlane.normal.y, reflectorPlane.normal.z, reflectorPlane.constant );
+			clipPlane.set( reflectorPlane.normal.x, reflectorPlane.normal.y, reflectorPlane.normal.z, reflectorPlane.constant );
 
-		var projectionMatrix = virtualCamera.projectionMatrix;
+			const projectionMatrix = virtualCamera.projectionMatrix;
 
-		q.x = ( Math.sign( clipPlane.x ) + projectionMatrix.elements[ 8 ] ) / projectionMatrix.elements[ 0 ];
-		q.y = ( Math.sign( clipPlane.y ) + projectionMatrix.elements[ 9 ] ) / projectionMatrix.elements[ 5 ];
-		q.z = - 1.0;
-		q.w = ( 1.0 + projectionMatrix.elements[ 10 ] ) / projectionMatrix.elements[ 14 ];
+			q.x = ( Math.sign( clipPlane.x ) + projectionMatrix.elements[ 8 ] ) / projectionMatrix.elements[ 0 ];
+			q.y = ( Math.sign( clipPlane.y ) + projectionMatrix.elements[ 9 ] ) / projectionMatrix.elements[ 5 ];
+			q.z = - 1.0;
+			q.w = ( 1.0 + projectionMatrix.elements[ 10 ] ) / projectionMatrix.elements[ 14 ];
 
-		// Calculate the scaled plane vector
-		clipPlane.multiplyScalar( 2.0 / clipPlane.dot( q ) );
+			// Calculate the scaled plane vector
+			clipPlane.multiplyScalar( 2.0 / clipPlane.dot( q ) );
 
-		// Replacing the third row of the projection matrix
-		projectionMatrix.elements[ 2 ] = clipPlane.x;
-		projectionMatrix.elements[ 6 ] = clipPlane.y;
-		projectionMatrix.elements[ 10 ] = clipPlane.z + 1.0 - clipBias;
-		projectionMatrix.elements[ 14 ] = clipPlane.w;
+			// Replacing the third row of the projection matrix
+			projectionMatrix.elements[ 2 ] = clipPlane.x;
+			projectionMatrix.elements[ 6 ] = clipPlane.y;
+			projectionMatrix.elements[ 10 ] = clipPlane.z + 1.0 - clipBias;
+			projectionMatrix.elements[ 14 ] = clipPlane.w;
 
-		// Render
+			// Render
 
-		renderTarget.texture.encoding = renderer.outputEncoding;
+			renderTarget.texture.encoding = renderer.outputEncoding;
 
-		scope.visible = false;
+			scope.visible = false;
 
-		var currentRenderTarget = renderer.getRenderTarget();
+			const currentRenderTarget = renderer.getRenderTarget();
 
-		var currentXrEnabled = renderer.xr.enabled;
-		var currentShadowAutoUpdate = renderer.shadowMap.autoUpdate;
+			const currentXrEnabled = renderer.xr.enabled;
+			const currentShadowAutoUpdate = renderer.shadowMap.autoUpdate;
 
-		renderer.xr.enabled = false; // Avoid camera modification
-		renderer.shadowMap.autoUpdate = false; // Avoid re-computing shadows
+			renderer.xr.enabled = false; // Avoid camera modification
+			renderer.shadowMap.autoUpdate = false; // Avoid re-computing shadows
 
-		renderer.setRenderTarget( renderTarget );
+			renderer.setRenderTarget( renderTarget );
 
-		renderer.state.buffers.depth.setMask( true ); // make sure the depth buffer is writable so it can be properly cleared, see #18897
+			renderer.state.buffers.depth.setMask( true ); // make sure the depth buffer is writable so it can be properly cleared, see #18897
 
-		if ( renderer.autoClear === false ) renderer.clear();
-		renderer.render( scene, virtualCamera );
+			if ( renderer.autoClear === false ) renderer.clear();
+			renderer.render( scene, virtualCamera );
 
-		renderer.xr.enabled = currentXrEnabled;
-		renderer.shadowMap.autoUpdate = currentShadowAutoUpdate;
+			renderer.xr.enabled = currentXrEnabled;
+			renderer.shadowMap.autoUpdate = currentShadowAutoUpdate;
 
-		renderer.setRenderTarget( currentRenderTarget );
+			renderer.setRenderTarget( currentRenderTarget );
 
-		// Restore viewport
+			// Restore viewport
 
-		var viewport = camera.viewport;
+			const viewport = camera.viewport;
 
-		if ( viewport !== undefined ) {
+			if ( viewport !== undefined ) {
 
-			renderer.state.viewport( viewport );
+				renderer.state.viewport( viewport );
 
-		}
+			}
 
-		scope.visible = true;
+			scope.visible = true;
 
-	};
+		};
 
-	this.getRenderTarget = function () {
+		this.getRenderTarget = function () {
 
-		return renderTarget;
+			return renderTarget;
 
-	};
+		};
 
-};
+	}
+
+}
 
-Reflector.prototype = Object.create( Mesh.prototype );
-Reflector.prototype.constructor = Reflector;
+Reflector.prototype.isReflector = true;
 
 Reflector.ReflectorShader = {
 

+ 169 - 166
examples/jsm/objects/ReflectorForSSRPass.js

@@ -17,248 +17,251 @@ import {
 	Plane
 } from '../../../build/three.module.js';
 
-var ReflectorForSSRPass = function ( geometry, options ) {
+class ReflectorForSSRPass extends Mesh {
 
-	Mesh.call( this, geometry );
+	constructor( geometry, options = {} ) {
 
-	this.type = 'ReflectorForSSRPass';
+		super( geometry );
 
-	var scope = this;
+		this.type = 'ReflectorForSSRPass';
 
-	options = options || {};
+		const scope = this;
 
-	var color = ( options.color !== undefined ) ? new Color( options.color ) : new Color( 0x7F7F7F );
-	var textureWidth = options.textureWidth || 512;
-	var textureHeight = options.textureHeight || 512;
-	var clipBias = options.clipBias || 0;
-	var shader = options.shader || ReflectorForSSRPass.ReflectorShader;
-	var useDepthTexture = options.useDepthTexture === true;
-	var yAxis = new Vector3( 0, 1, 0 );
-	var vecTemp0 = new Vector3();
-	var vecTemp1 = new Vector3();
+		const color = ( options.color !== undefined ) ? new Color( options.color ) : new Color( 0x7F7F7F );
+		const textureWidth = options.textureWidth || 512;
+		const textureHeight = options.textureHeight || 512;
+		const clipBias = options.clipBias || 0;
+		const shader = options.shader || ReflectorForSSRPass.ReflectorShader;
+		const useDepthTexture = options.useDepthTexture === true;
+		const yAxis = new Vector3( 0, 1, 0 );
+		const vecTemp0 = new Vector3();
+		const vecTemp1 = new Vector3();
 
-	//
+		//
 
-	scope.needsUpdate = false;
-	scope.maxDistance = ReflectorForSSRPass.ReflectorShader.uniforms.maxDistance.value;
-	scope.opacity = ReflectorForSSRPass.ReflectorShader.uniforms.opacity.value;
-	scope.color = color;
-	scope.resolution = options.resolution || new Vector2( window.innerWidth, window.innerHeight );
+		scope.needsUpdate = false;
+		scope.maxDistance = ReflectorForSSRPass.ReflectorShader.uniforms.maxDistance.value;
+		scope.opacity = ReflectorForSSRPass.ReflectorShader.uniforms.opacity.value;
+		scope.color = color;
+		scope.resolution = options.resolution || new Vector2( window.innerWidth, window.innerHeight );
 
 
-	scope._distanceAttenuation = ReflectorForSSRPass.ReflectorShader.defines.DISTANCE_ATTENUATION;
-	Object.defineProperty( scope, 'distanceAttenuation', {
-		get() {
+		scope._distanceAttenuation = ReflectorForSSRPass.ReflectorShader.defines.DISTANCE_ATTENUATION;
+		Object.defineProperty( scope, 'distanceAttenuation', {
+			get() {
 
-			return scope._distanceAttenuation;
+				return scope._distanceAttenuation;
 
-		},
-		set( val ) {
+			},
+			set( val ) {
 
-			if ( scope._distanceAttenuation === val ) return;
-			scope._distanceAttenuation = val;
-			scope.material.defines.DISTANCE_ATTENUATION = val;
-			scope.material.needsUpdate = true;
+				if ( scope._distanceAttenuation === val ) return;
+				scope._distanceAttenuation = val;
+				scope.material.defines.DISTANCE_ATTENUATION = val;
+				scope.material.needsUpdate = true;
 
-		}
-	} );
+			}
+		} );
 
-	scope._fresnel = ReflectorForSSRPass.ReflectorShader.defines.FRESNEL;
-	Object.defineProperty( scope, 'fresnel', {
-		get() {
+		scope._fresnel = ReflectorForSSRPass.ReflectorShader.defines.FRESNEL;
+		Object.defineProperty( scope, 'fresnel', {
+			get() {
 
-			return scope._fresnel;
+				return scope._fresnel;
 
-		},
-		set( val ) {
+			},
+			set( val ) {
 
-			if ( scope._fresnel === val ) return;
-			scope._fresnel = val;
-			scope.material.defines.FRESNEL = val;
-			scope.material.needsUpdate = true;
+				if ( scope._fresnel === val ) return;
+				scope._fresnel = val;
+				scope.material.defines.FRESNEL = val;
+				scope.material.needsUpdate = true;
 
-		}
-	} );
+			}
+		} );
 
-	var normal = new Vector3();
-	var reflectorWorldPosition = new Vector3();
-	var cameraWorldPosition = new Vector3();
-	var rotationMatrix = new Matrix4();
-	var lookAtPosition = new Vector3( 0, 0, - 1 );
+		const normal = new Vector3();
+		const reflectorWorldPosition = new Vector3();
+		const cameraWorldPosition = new Vector3();
+		const rotationMatrix = new Matrix4();
+		const lookAtPosition = new Vector3( 0, 0, - 1 );
 
-	var view = new Vector3();
-	var target = new Vector3();
+		const view = new Vector3();
+		const target = new Vector3();
 
-	var textureMatrix = new Matrix4();
-	var virtualCamera = new PerspectiveCamera();
+		const textureMatrix = new Matrix4();
+		const virtualCamera = new PerspectiveCamera();
 
-	if ( useDepthTexture ) {
+		let depthTexture;
 
-		var depthTexture = new DepthTexture();
-		depthTexture.type = UnsignedShortType;
-		depthTexture.minFilter = NearestFilter;
-		depthTexture.magFilter = NearestFilter;
+		if ( useDepthTexture ) {
 
-	}
+			depthTexture = new DepthTexture();
+			depthTexture.type = UnsignedShortType;
+			depthTexture.minFilter = NearestFilter;
+			depthTexture.magFilter = NearestFilter;
 
-	var parameters = {
-		minFilter: LinearFilter,
-		magFilter: LinearFilter,
-		format: RGBFormat,
-		depthTexture: useDepthTexture ? depthTexture : null,
-	};
+		}
 
-	var renderTarget = new WebGLRenderTarget( textureWidth, textureHeight, parameters );
+		const parameters = {
+			minFilter: LinearFilter,
+			magFilter: LinearFilter,
+			format: RGBFormat,
+			depthTexture: useDepthTexture ? depthTexture : null,
+		};
 
-	if ( ! MathUtils.isPowerOfTwo( textureWidth ) || ! MathUtils.isPowerOfTwo( textureHeight ) ) {
+		const renderTarget = new WebGLRenderTarget( textureWidth, textureHeight, parameters );
 
-		renderTarget.texture.generateMipmaps = false;
+		if ( ! MathUtils.isPowerOfTwo( textureWidth ) || ! MathUtils.isPowerOfTwo( textureHeight ) ) {
 
-	}
+			renderTarget.texture.generateMipmaps = false;
+
+		}
 
-	var material = new ShaderMaterial( {
-		transparent: useDepthTexture,
-		defines: Object.assign( {}, ReflectorForSSRPass.ReflectorShader.defines, {
-			useDepthTexture
-		} ),
-		uniforms: UniformsUtils.clone( shader.uniforms ),
-		fragmentShader: shader.fragmentShader,
-		vertexShader: shader.vertexShader
-	} );
+		const material = new ShaderMaterial( {
+			transparent: useDepthTexture,
+			defines: Object.assign( {}, ReflectorForSSRPass.ReflectorShader.defines, {
+				useDepthTexture
+			} ),
+			uniforms: UniformsUtils.clone( shader.uniforms ),
+			fragmentShader: shader.fragmentShader,
+			vertexShader: shader.vertexShader
+		} );
+
+		material.uniforms[ 'tDiffuse' ].value = renderTarget.texture;
+		material.uniforms[ 'color' ].value = scope.color;
+		material.uniforms[ 'textureMatrix' ].value = textureMatrix;
+		if ( useDepthTexture ) {
 
-	material.uniforms[ 'tDiffuse' ].value = renderTarget.texture;
-	material.uniforms[ 'color' ].value = scope.color;
-	material.uniforms[ 'textureMatrix' ].value = textureMatrix;
-	if ( useDepthTexture ) {
+			material.uniforms[ 'tDepth' ].value = renderTarget.depthTexture;
 
-		material.uniforms[ 'tDepth' ].value = renderTarget.depthTexture;
+		}
 
-	}
+		this.material = material;
 
-	this.material = material;
+		const globalPlane = new Plane( new Vector3( 0, 1, 0 ), clipBias );
+		const globalPlanes = [ globalPlane ];
 
-	const globalPlane = new Plane( new Vector3( 0, 1, 0 ), clipBias );
-	const globalPlanes = [ globalPlane ];
+		this.doRender = function ( renderer, scene, camera ) {
 
-	this.doRender = function ( renderer, scene, camera ) {
+			material.uniforms[ 'maxDistance' ].value = scope.maxDistance;
+			material.uniforms[ 'color' ].value = scope.color;
+			material.uniforms[ 'opacity' ].value = scope.opacity;
 
-		material.uniforms[ 'maxDistance' ].value = scope.maxDistance;
-		material.uniforms[ 'color' ].value = scope.color;
-		material.uniforms[ 'opacity' ].value = scope.opacity;
+			vecTemp0.copy( camera.position ).normalize();
+			vecTemp1.copy( vecTemp0 ).reflect( yAxis );
+			material.uniforms[ 'fresnelCoe' ].value = ( vecTemp0.dot( vecTemp1 ) + 1. ) / 2.; // TODO: Also need to use glsl viewPosition and viewNormal per pixel.
 
-		vecTemp0.copy( camera.position ).normalize();
-		vecTemp1.copy( vecTemp0 ).reflect( yAxis );
-		material.uniforms[ 'fresnelCoe' ].value = ( vecTemp0.dot( vecTemp1 ) + 1. ) / 2.; // TODO: Also need to use glsl viewPosition and viewNormal per pixel.
+			reflectorWorldPosition.setFromMatrixPosition( scope.matrixWorld );
+			cameraWorldPosition.setFromMatrixPosition( camera.matrixWorld );
 
-		reflectorWorldPosition.setFromMatrixPosition( scope.matrixWorld );
-		cameraWorldPosition.setFromMatrixPosition( camera.matrixWorld );
+			rotationMatrix.extractRotation( scope.matrixWorld );
 
-		rotationMatrix.extractRotation( scope.matrixWorld );
+			normal.set( 0, 0, 1 );
+			normal.applyMatrix4( rotationMatrix );
 
-		normal.set( 0, 0, 1 );
-		normal.applyMatrix4( rotationMatrix );
+			view.subVectors( reflectorWorldPosition, cameraWorldPosition );
 
-		view.subVectors( reflectorWorldPosition, cameraWorldPosition );
+			// Avoid rendering when reflector is facing away
 
-		// Avoid rendering when reflector is facing away
+			if ( view.dot( normal ) > 0 ) return;
 
-		if ( view.dot( normal ) > 0 ) return;
+			view.reflect( normal ).negate();
+			view.add( reflectorWorldPosition );
 
-		view.reflect( normal ).negate();
-		view.add( reflectorWorldPosition );
+			rotationMatrix.extractRotation( camera.matrixWorld );
 
-		rotationMatrix.extractRotation( camera.matrixWorld );
+			lookAtPosition.set( 0, 0, - 1 );
+			lookAtPosition.applyMatrix4( rotationMatrix );
+			lookAtPosition.add( cameraWorldPosition );
 
-		lookAtPosition.set( 0, 0, - 1 );
-		lookAtPosition.applyMatrix4( rotationMatrix );
-		lookAtPosition.add( cameraWorldPosition );
+			target.subVectors( reflectorWorldPosition, lookAtPosition );
+			target.reflect( normal ).negate();
+			target.add( reflectorWorldPosition );
 
-		target.subVectors( reflectorWorldPosition, lookAtPosition );
-		target.reflect( normal ).negate();
-		target.add( reflectorWorldPosition );
+			virtualCamera.position.copy( view );
+			virtualCamera.up.set( 0, 1, 0 );
+			virtualCamera.up.applyMatrix4( rotationMatrix );
+			virtualCamera.up.reflect( normal );
+			virtualCamera.lookAt( target );
 
-		virtualCamera.position.copy( view );
-		virtualCamera.up.set( 0, 1, 0 );
-		virtualCamera.up.applyMatrix4( rotationMatrix );
-		virtualCamera.up.reflect( normal );
-		virtualCamera.lookAt( target );
+			virtualCamera.far = camera.far; // Used in WebGLBackground
 
-		virtualCamera.far = camera.far; // Used in WebGLBackground
+			virtualCamera.updateMatrixWorld();
+			virtualCamera.projectionMatrix.copy( camera.projectionMatrix );
 
-		virtualCamera.updateMatrixWorld();
-		virtualCamera.projectionMatrix.copy( camera.projectionMatrix );
+			material.uniforms[ 'virtualCameraNear' ].value = camera.near;
+			material.uniforms[ 'virtualCameraFar' ].value = camera.far;
+			material.uniforms[ 'virtualCameraMatrixWorld' ].value = virtualCamera.matrixWorld;
+			material.uniforms[ 'virtualCameraProjectionMatrix' ].value = camera.projectionMatrix;
+			material.uniforms[ 'virtualCameraProjectionMatrixInverse' ].value = camera.projectionMatrixInverse;
+			material.uniforms[ 'resolution' ].value = scope.resolution;
 
-		material.uniforms[ 'virtualCameraNear' ].value = camera.near;
-		material.uniforms[ 'virtualCameraFar' ].value = camera.far;
-		material.uniforms[ 'virtualCameraMatrixWorld' ].value = virtualCamera.matrixWorld;
-		material.uniforms[ 'virtualCameraProjectionMatrix' ].value = camera.projectionMatrix;
-		material.uniforms[ 'virtualCameraProjectionMatrixInverse' ].value = camera.projectionMatrixInverse;
-		material.uniforms[ 'resolution' ].value = scope.resolution;
+			// Update the texture matrix
+			textureMatrix.set(
+				0.5, 0.0, 0.0, 0.5,
+				0.0, 0.5, 0.0, 0.5,
+				0.0, 0.0, 0.5, 0.5,
+				0.0, 0.0, 0.0, 1.0
+			);
+			textureMatrix.multiply( virtualCamera.projectionMatrix );
+			textureMatrix.multiply( virtualCamera.matrixWorldInverse );
+			textureMatrix.multiply( scope.matrixWorld );
 
-		// Update the texture matrix
-		textureMatrix.set(
-			0.5, 0.0, 0.0, 0.5,
-			0.0, 0.5, 0.0, 0.5,
-			0.0, 0.0, 0.5, 0.5,
-			0.0, 0.0, 0.0, 1.0
-		);
-		textureMatrix.multiply( virtualCamera.projectionMatrix );
-		textureMatrix.multiply( virtualCamera.matrixWorldInverse );
-		textureMatrix.multiply( scope.matrixWorld );
+			// Render
 
-		// Render
+			renderTarget.texture.encoding = renderer.outputEncoding;
 
-		renderTarget.texture.encoding = renderer.outputEncoding;
+			// scope.visible = false;
 
-		// scope.visible = false;
+			const currentRenderTarget = renderer.getRenderTarget();
 
-		var currentRenderTarget = renderer.getRenderTarget();
+			const currentXrEnabled = renderer.xr.enabled;
+			const currentShadowAutoUpdate = renderer.shadowMap.autoUpdate;
+			const currentClippingPlanes = renderer.clippingPlanes;
 
-		var currentXrEnabled = renderer.xr.enabled;
-		var currentShadowAutoUpdate = renderer.shadowMap.autoUpdate;
-		var currentClippingPlanes = renderer.clippingPlanes;
+			renderer.xr.enabled = false; // Avoid camera modification
+			renderer.shadowMap.autoUpdate = false; // Avoid re-computing shadows
+			renderer.clippingPlanes = globalPlanes;
 
-		renderer.xr.enabled = false; // Avoid camera modification
-		renderer.shadowMap.autoUpdate = false; // Avoid re-computing shadows
-		renderer.clippingPlanes = globalPlanes;
+			renderer.setRenderTarget( renderTarget );
 
-		renderer.setRenderTarget( renderTarget );
+			renderer.state.buffers.depth.setMask( true ); // make sure the depth buffer is writable so it can be properly cleared, see #18897
 
-		renderer.state.buffers.depth.setMask( true ); // make sure the depth buffer is writable so it can be properly cleared, see #18897
+			if ( renderer.autoClear === false ) renderer.clear();
+			renderer.render( scene, virtualCamera );
 
-		if ( renderer.autoClear === false ) renderer.clear();
-		renderer.render( scene, virtualCamera );
+			renderer.xr.enabled = currentXrEnabled;
+			renderer.shadowMap.autoUpdate = currentShadowAutoUpdate;
+			renderer.clippingPlanes = currentClippingPlanes;
 
-		renderer.xr.enabled = currentXrEnabled;
-		renderer.shadowMap.autoUpdate = currentShadowAutoUpdate;
-		renderer.clippingPlanes = currentClippingPlanes;
+			renderer.setRenderTarget( currentRenderTarget );
 
-		renderer.setRenderTarget( currentRenderTarget );
+			// Restore viewport
 
-		// Restore viewport
+			const viewport = camera.viewport;
 
-		var viewport = camera.viewport;
+			if ( viewport !== undefined ) {
 
-		if ( viewport !== undefined ) {
+				renderer.state.viewport( viewport );
 
-			renderer.state.viewport( viewport );
+			}
 
-		}
+			// scope.visible = true;
 
-		// scope.visible = true;
+		};
 
-	};
+		this.getRenderTarget = function () {
 
-	this.getRenderTarget = function () {
+			return renderTarget;
 
-		return renderTarget;
+		};
 
-	};
+	}
 
-};
+}
 
-ReflectorForSSRPass.prototype = Object.create( Mesh.prototype );
-ReflectorForSSRPass.prototype.constructor = ReflectorForSSRPass;
+ReflectorForSSRPass.prototype.isReflectorForSSRPass = true;
 
 ReflectorForSSRPass.ReflectorShader = {
 

+ 7 - 5
examples/jsm/objects/ReflectorRTT.js

@@ -1,13 +1,15 @@
 import { Reflector } from '../objects/Reflector.js';
 
-var ReflectorRTT = function ( geometry, options ) {
+class ReflectorRTT extends Reflector {
 
-	Reflector.call( this, geometry, options );
+	constructor( geometry, options ) {
 
-	this.geometry.setDrawRange( 0, 0 ); // avoid rendering geometry
+		super( geometry, options );
 
-};
+		this.geometry.setDrawRange( 0, 0 ); // avoid rendering geometry
 
-ReflectorRTT.prototype = Object.create( Reflector.prototype );
+	}
+
+}
 
 export { ReflectorRTT };

+ 157 - 156
examples/jsm/objects/Refractor.js

@@ -15,257 +15,258 @@ import {
 	WebGLRenderTarget
 } from '../../../build/three.module.js';
 
-var Refractor = function ( geometry, options ) {
+class Refractor extends Mesh {
 
-	Mesh.call( this, geometry );
+	constructor( geometry, options = {} ) {
 
-	this.type = 'Refractor';
+		super( geometry );
 
-	var scope = this;
+		this.type = 'Refractor';
 
-	options = options || {};
+		const scope = this;
 
-	var color = ( options.color !== undefined ) ? new Color( options.color ) : new Color( 0x7F7F7F );
-	var textureWidth = options.textureWidth || 512;
-	var textureHeight = options.textureHeight || 512;
-	var clipBias = options.clipBias || 0;
-	var shader = options.shader || Refractor.RefractorShader;
+		const color = ( options.color !== undefined ) ? new Color( options.color ) : new Color( 0x7F7F7F );
+		const textureWidth = options.textureWidth || 512;
+		const textureHeight = options.textureHeight || 512;
+		const clipBias = options.clipBias || 0;
+		const shader = options.shader || Refractor.RefractorShader;
 
-	//
+		//
 
-	var virtualCamera = new PerspectiveCamera();
-	virtualCamera.matrixAutoUpdate = false;
-	virtualCamera.userData.refractor = true;
+		const virtualCamera = new PerspectiveCamera();
+		virtualCamera.matrixAutoUpdate = false;
+		virtualCamera.userData.refractor = true;
 
-	//
+		//
 
-	var refractorPlane = new Plane();
-	var textureMatrix = new Matrix4();
+		const refractorPlane = new Plane();
+		const textureMatrix = new Matrix4();
 
-	// render target
+		// render target
 
-	var parameters = {
-		minFilter: LinearFilter,
-		magFilter: LinearFilter,
-		format: RGBFormat
-	};
+		const parameters = {
+			minFilter: LinearFilter,
+			magFilter: LinearFilter,
+			format: RGBFormat
+		};
 
-	var renderTarget = new WebGLRenderTarget( textureWidth, textureHeight, parameters );
+		const renderTarget = new WebGLRenderTarget( textureWidth, textureHeight, parameters );
 
-	if ( ! MathUtils.isPowerOfTwo( textureWidth ) || ! MathUtils.isPowerOfTwo( textureHeight ) ) {
+		if ( ! MathUtils.isPowerOfTwo( textureWidth ) || ! MathUtils.isPowerOfTwo( textureHeight ) ) {
 
-		renderTarget.texture.generateMipmaps = false;
+			renderTarget.texture.generateMipmaps = false;
 
-	}
+		}
 
-	// material
+		// material
 
-	this.material = new ShaderMaterial( {
-		uniforms: UniformsUtils.clone( shader.uniforms ),
-		vertexShader: shader.vertexShader,
-		fragmentShader: shader.fragmentShader,
-		transparent: true // ensures, refractors are drawn from farthest to closest
-	} );
+		this.material = new ShaderMaterial( {
+			uniforms: UniformsUtils.clone( shader.uniforms ),
+			vertexShader: shader.vertexShader,
+			fragmentShader: shader.fragmentShader,
+			transparent: true // ensures, refractors are drawn from farthest to closest
+		} );
 
-	this.material.uniforms[ 'color' ].value = color;
-	this.material.uniforms[ 'tDiffuse' ].value = renderTarget.texture;
-	this.material.uniforms[ 'textureMatrix' ].value = textureMatrix;
+		this.material.uniforms[ 'color' ].value = color;
+		this.material.uniforms[ 'tDiffuse' ].value = renderTarget.texture;
+		this.material.uniforms[ 'textureMatrix' ].value = textureMatrix;
 
-	// functions
+		// functions
 
-	var visible = ( function () {
+		const visible = ( function () {
 
-		var refractorWorldPosition = new Vector3();
-		var cameraWorldPosition = new Vector3();
-		var rotationMatrix = new Matrix4();
+			const refractorWorldPosition = new Vector3();
+			const cameraWorldPosition = new Vector3();
+			const rotationMatrix = new Matrix4();
 
-		var view = new Vector3();
-		var normal = new Vector3();
+			const view = new Vector3();
+			const normal = new Vector3();
 
-		return function visible( camera ) {
+			return function visible( camera ) {
 
-			refractorWorldPosition.setFromMatrixPosition( scope.matrixWorld );
-			cameraWorldPosition.setFromMatrixPosition( camera.matrixWorld );
+				refractorWorldPosition.setFromMatrixPosition( scope.matrixWorld );
+				cameraWorldPosition.setFromMatrixPosition( camera.matrixWorld );
 
-			view.subVectors( refractorWorldPosition, cameraWorldPosition );
+				view.subVectors( refractorWorldPosition, cameraWorldPosition );
 
-			rotationMatrix.extractRotation( scope.matrixWorld );
+				rotationMatrix.extractRotation( scope.matrixWorld );
 
-			normal.set( 0, 0, 1 );
-			normal.applyMatrix4( rotationMatrix );
+				normal.set( 0, 0, 1 );
+				normal.applyMatrix4( rotationMatrix );
 
-			return view.dot( normal ) < 0;
+				return view.dot( normal ) < 0;
 
-		};
+			};
 
-	} )();
+		} )();
 
-	var updateRefractorPlane = ( function () {
+		const updateRefractorPlane = ( function () {
 
-		var normal = new Vector3();
-		var position = new Vector3();
-		var quaternion = new Quaternion();
-		var scale = new Vector3();
+			const normal = new Vector3();
+			const position = new Vector3();
+			const quaternion = new Quaternion();
+			const scale = new Vector3();
 
-		return function updateRefractorPlane() {
+			return function updateRefractorPlane() {
 
-			scope.matrixWorld.decompose( position, quaternion, scale );
-			normal.set( 0, 0, 1 ).applyQuaternion( quaternion ).normalize();
+				scope.matrixWorld.decompose( position, quaternion, scale );
+				normal.set( 0, 0, 1 ).applyQuaternion( quaternion ).normalize();
 
-			// flip the normal because we want to cull everything above the plane
+				// flip the normal because we want to cull everything above the plane
 
-			normal.negate();
+				normal.negate();
 
-			refractorPlane.setFromNormalAndCoplanarPoint( normal, position );
+				refractorPlane.setFromNormalAndCoplanarPoint( normal, position );
 
-		};
+			};
 
-	} )();
+		} )();
 
-	var updateVirtualCamera = ( function () {
+		const updateVirtualCamera = ( function () {
 
-		var clipPlane = new Plane();
-		var clipVector = new Vector4();
-		var q = new Vector4();
+			const clipPlane = new Plane();
+			const clipVector = new Vector4();
+			const q = new Vector4();
 
-		return function updateVirtualCamera( camera ) {
+			return function updateVirtualCamera( camera ) {
 
-			virtualCamera.matrixWorld.copy( camera.matrixWorld );
-			virtualCamera.matrixWorldInverse.copy( virtualCamera.matrixWorld ).invert();
-			virtualCamera.projectionMatrix.copy( camera.projectionMatrix );
-			virtualCamera.far = camera.far; // used in WebGLBackground
+				virtualCamera.matrixWorld.copy( camera.matrixWorld );
+				virtualCamera.matrixWorldInverse.copy( virtualCamera.matrixWorld ).invert();
+				virtualCamera.projectionMatrix.copy( camera.projectionMatrix );
+				virtualCamera.far = camera.far; // used in WebGLBackground
 
-			// The following code creates an oblique view frustum for clipping.
-			// see: Lengyel, Eric. “Oblique View Frustum Depth Projection and Clipping”.
-			// Journal of Game Development, Vol. 1, No. 2 (2005), Charles River Media, pp. 5–16
+				// The following code creates an oblique view frustum for clipping.
+				// see: Lengyel, Eric. “Oblique View Frustum Depth Projection and Clipping”.
+				// Journal of Game Development, Vol. 1, No. 2 (2005), Charles River Media, pp. 5–16
 
-			clipPlane.copy( refractorPlane );
-			clipPlane.applyMatrix4( virtualCamera.matrixWorldInverse );
+				clipPlane.copy( refractorPlane );
+				clipPlane.applyMatrix4( virtualCamera.matrixWorldInverse );
 
-			clipVector.set( clipPlane.normal.x, clipPlane.normal.y, clipPlane.normal.z, clipPlane.constant );
+				clipVector.set( clipPlane.normal.x, clipPlane.normal.y, clipPlane.normal.z, clipPlane.constant );
 
-			// calculate the clip-space corner point opposite the clipping plane and
-			// transform it into camera space by multiplying it by the inverse of the projection matrix
+				// calculate the clip-space corner point opposite the clipping plane and
+				// transform it into camera space by multiplying it by the inverse of the projection matrix
 
-			var projectionMatrix = virtualCamera.projectionMatrix;
+				const projectionMatrix = virtualCamera.projectionMatrix;
 
-			q.x = ( Math.sign( clipVector.x ) + projectionMatrix.elements[ 8 ] ) / projectionMatrix.elements[ 0 ];
-			q.y = ( Math.sign( clipVector.y ) + projectionMatrix.elements[ 9 ] ) / projectionMatrix.elements[ 5 ];
-			q.z = - 1.0;
-			q.w = ( 1.0 + projectionMatrix.elements[ 10 ] ) / projectionMatrix.elements[ 14 ];
+				q.x = ( Math.sign( clipVector.x ) + projectionMatrix.elements[ 8 ] ) / projectionMatrix.elements[ 0 ];
+				q.y = ( Math.sign( clipVector.y ) + projectionMatrix.elements[ 9 ] ) / projectionMatrix.elements[ 5 ];
+				q.z = - 1.0;
+				q.w = ( 1.0 + projectionMatrix.elements[ 10 ] ) / projectionMatrix.elements[ 14 ];
 
-			// calculate the scaled plane vector
+				// calculate the scaled plane vector
 
-			clipVector.multiplyScalar( 2.0 / clipVector.dot( q ) );
+				clipVector.multiplyScalar( 2.0 / clipVector.dot( q ) );
 
-			// replacing the third row of the projection matrix
+				// replacing the third row of the projection matrix
 
-			projectionMatrix.elements[ 2 ] = clipVector.x;
-			projectionMatrix.elements[ 6 ] = clipVector.y;
-			projectionMatrix.elements[ 10 ] = clipVector.z + 1.0 - clipBias;
-			projectionMatrix.elements[ 14 ] = clipVector.w;
+				projectionMatrix.elements[ 2 ] = clipVector.x;
+				projectionMatrix.elements[ 6 ] = clipVector.y;
+				projectionMatrix.elements[ 10 ] = clipVector.z + 1.0 - clipBias;
+				projectionMatrix.elements[ 14 ] = clipVector.w;
 
-		};
+			};
 
-	} )();
+		} )();
 
-	// This will update the texture matrix that is used for projective texture mapping in the shader.
-	// see: http://developer.download.nvidia.com/assets/gamedev/docs/projective_texture_mapping.pdf
+		// This will update the texture matrix that is used for projective texture mapping in the shader.
+		// see: http://developer.download.nvidia.com/assets/gamedev/docs/projective_texture_mapping.pdf
 
-	function updateTextureMatrix( camera ) {
+		function updateTextureMatrix( camera ) {
 
-		// this matrix does range mapping to [ 0, 1 ]
+			// this matrix does range mapping to [ 0, 1 ]
 
-		textureMatrix.set(
-			0.5, 0.0, 0.0, 0.5,
-			0.0, 0.5, 0.0, 0.5,
-			0.0, 0.0, 0.5, 0.5,
-			0.0, 0.0, 0.0, 1.0
-		);
+			textureMatrix.set(
+				0.5, 0.0, 0.0, 0.5,
+				0.0, 0.5, 0.0, 0.5,
+				0.0, 0.0, 0.5, 0.5,
+				0.0, 0.0, 0.0, 1.0
+			);
 
-		// we use "Object Linear Texgen", so we need to multiply the texture matrix T
-		// (matrix above) with the projection and view matrix of the virtual camera
-		// and the model matrix of the refractor
+			// we use "Object Linear Texgen", so we need to multiply the texture matrix T
+			// (matrix above) with the projection and view matrix of the virtual camera
+			// and the model matrix of the refractor
 
-		textureMatrix.multiply( camera.projectionMatrix );
-		textureMatrix.multiply( camera.matrixWorldInverse );
-		textureMatrix.multiply( scope.matrixWorld );
+			textureMatrix.multiply( camera.projectionMatrix );
+			textureMatrix.multiply( camera.matrixWorldInverse );
+			textureMatrix.multiply( scope.matrixWorld );
 
-	}
+		}
 
-	//
+		//
 
-	function render( renderer, scene, camera ) {
+		function render( renderer, scene, camera ) {
 
-		scope.visible = false;
+			scope.visible = false;
 
-		var currentRenderTarget = renderer.getRenderTarget();
-		var currentXrEnabled = renderer.xr.enabled;
-		var currentShadowAutoUpdate = renderer.shadowMap.autoUpdate;
+			const currentRenderTarget = renderer.getRenderTarget();
+			const currentXrEnabled = renderer.xr.enabled;
+			const currentShadowAutoUpdate = renderer.shadowMap.autoUpdate;
 
-		renderer.xr.enabled = false; // avoid camera modification
-		renderer.shadowMap.autoUpdate = false; // avoid re-computing shadows
+			renderer.xr.enabled = false; // avoid camera modification
+			renderer.shadowMap.autoUpdate = false; // avoid re-computing shadows
 
-		renderer.setRenderTarget( renderTarget );
-		if ( renderer.autoClear === false ) renderer.clear();
-		renderer.render( scene, virtualCamera );
+			renderer.setRenderTarget( renderTarget );
+			if ( renderer.autoClear === false ) renderer.clear();
+			renderer.render( scene, virtualCamera );
 
-		renderer.xr.enabled = currentXrEnabled;
-		renderer.shadowMap.autoUpdate = currentShadowAutoUpdate;
-		renderer.setRenderTarget( currentRenderTarget );
+			renderer.xr.enabled = currentXrEnabled;
+			renderer.shadowMap.autoUpdate = currentShadowAutoUpdate;
+			renderer.setRenderTarget( currentRenderTarget );
 
-		// restore viewport
+			// restore viewport
 
-		var viewport = camera.viewport;
+			const viewport = camera.viewport;
 
-		if ( viewport !== undefined ) {
+			if ( viewport !== undefined ) {
 
-			renderer.state.viewport( viewport );
+				renderer.state.viewport( viewport );
 
-		}
+			}
 
-		scope.visible = true;
+			scope.visible = true;
 
-	}
+		}
+
+		//
 
-	//
+		this.onBeforeRender = function ( renderer, scene, camera ) {
 
-	this.onBeforeRender = function ( renderer, scene, camera ) {
+			// Render
 
-		// Render
+			renderTarget.texture.encoding = renderer.outputEncoding;
 
-		renderTarget.texture.encoding = renderer.outputEncoding;
+			// ensure refractors are rendered only once per frame
 
-		// ensure refractors are rendered only once per frame
+			if ( camera.userData.refractor === true ) return;
 
-		if ( camera.userData.refractor === true ) return;
+			// avoid rendering when the refractor is viewed from behind
 
-		// avoid rendering when the refractor is viewed from behind
+			if ( ! visible( camera ) === true ) return;
 
-		if ( ! visible( camera ) === true ) return;
+			// update
 
-		// update
+			updateRefractorPlane();
 
-		updateRefractorPlane();
+			updateTextureMatrix( camera );
 
-		updateTextureMatrix( camera );
+			updateVirtualCamera( camera );
 
-		updateVirtualCamera( camera );
+			render( renderer, scene, camera );
 
-		render( renderer, scene, camera );
+		};
 
-	};
+		this.getRenderTarget = function () {
 
-	this.getRenderTarget = function () {
+			return renderTarget;
 
-		return renderTarget;
+		};
 
-	};
+	}
 
-};
+}
 
-Refractor.prototype = Object.create( Mesh.prototype );
-Refractor.prototype.constructor = Refractor;
+Refractor.prototype.isRefractor = true;
 
 Refractor.RefractorShader = {
 

+ 22 - 23
examples/jsm/objects/ShadowMesh.js

@@ -8,43 +8,40 @@ import {
  * A shadow Mesh that follows a shadow-casting Mesh in the scene, but is confined to a single plane.
  */
 
-var ShadowMesh = function ( mesh ) {
+const _shadowMatrix = new Matrix4();
 
-	var shadowMaterial = new MeshBasicMaterial( {
+class ShadowMesh extends Mesh {
 
-		color: 0x000000,
-		transparent: true,
-		opacity: 0.6,
-		depthWrite: false
+	constructor( mesh ) {
 
-	} );
+		const shadowMaterial = new MeshBasicMaterial( {
 
-	Mesh.call( this, mesh.geometry, shadowMaterial );
+			color: 0x000000,
+			transparent: true,
+			opacity: 0.6,
+			depthWrite: false
 
-	this.meshMatrix = mesh.matrixWorld;
+		} );
 
-	this.frustumCulled = false;
-	this.matrixAutoUpdate = false;
+		super( mesh.geometry, shadowMaterial );
 
-};
+		this.meshMatrix = mesh.matrixWorld;
 
-ShadowMesh.prototype = Object.create( Mesh.prototype );
-ShadowMesh.prototype.constructor = ShadowMesh;
+		this.frustumCulled = false;
+		this.matrixAutoUpdate = false;
 
-ShadowMesh.prototype.update = function () {
+	}
 
-	var shadowMatrix = new Matrix4();
-
-	return function ( plane, lightPosition4D ) {
+	update( plane, lightPosition4D ) {
 
 		// based on https://www.opengl.org/archives/resources/features/StencilTalk/tsld021.htm
 
-		var dot = plane.normal.x * lightPosition4D.x +
+		const dot = plane.normal.x * lightPosition4D.x +
 			  plane.normal.y * lightPosition4D.y +
 			  plane.normal.z * lightPosition4D.z +
 			  - plane.constant * lightPosition4D.w;
 
-		var sme = shadowMatrix.elements;
+		const sme = _shadowMatrix.elements;
 
 		sme[ 0 ] = dot - lightPosition4D.x * plane.normal.x;
 		sme[ 4 ] = - lightPosition4D.x * plane.normal.y;
@@ -66,10 +63,12 @@ ShadowMesh.prototype.update = function () {
 		sme[ 11 ] = - lightPosition4D.w * plane.normal.z;
 		sme[ 15 ] = dot - lightPosition4D.w * - plane.constant;
 
-		this.matrix.multiplyMatrices( shadowMatrix, this.meshMatrix );
+		this.matrix.multiplyMatrices( _shadowMatrix, this.meshMatrix );
+
+	}
 
-	};
+}
 
-}();
+ShadowMesh.prototype.isShadowMesh = true;
 
 export { ShadowMesh };

+ 17 - 13
examples/jsm/objects/Sky.js

@@ -21,24 +21,28 @@ import {
  * Three.js integration by zz85 http://twitter.com/blurspline
 */
 
-var Sky = function () {
+class Sky extends Mesh {
 
-	var shader = Sky.SkyShader;
+	constructor() {
 
-	var material = new ShaderMaterial( {
-		name: 'SkyShader',
-		fragmentShader: shader.fragmentShader,
-		vertexShader: shader.vertexShader,
-		uniforms: UniformsUtils.clone( shader.uniforms ),
-		side: BackSide,
-		depthWrite: false
-	} );
+		const shader = Sky.SkyShader;
 
-	Mesh.call( this, new BoxGeometry( 1, 1, 1 ), material );
+		const material = new ShaderMaterial( {
+			name: 'SkyShader',
+			fragmentShader: shader.fragmentShader,
+			vertexShader: shader.vertexShader,
+			uniforms: UniformsUtils.clone( shader.uniforms ),
+			side: BackSide,
+			depthWrite: false
+		} );
 
-};
+		super( new BoxGeometry( 1, 1, 1 ), material );
+
+	}
+
+}
 
-Sky.prototype = Object.create( Mesh.prototype );
+Sky.prototype.isSky = true;
 
 Sky.SkyShader = {
 

+ 260 - 259
examples/jsm/objects/Water.js

@@ -23,323 +23,324 @@ import {
  * http://29a.ch/ && http://29a.ch/slides/2012/webglwater/ : Water shader explanations in WebGL
  */
 
-var Water = function ( geometry, options ) {
+class Water extends Mesh {
 
-	Mesh.call( this, geometry );
+	constructor( geometry, options = {} ) {
 
-	var scope = this;
+		super( geometry );
 
-	options = options || {};
+		const scope = this;
 
-	var textureWidth = options.textureWidth !== undefined ? options.textureWidth : 512;
-	var textureHeight = options.textureHeight !== undefined ? options.textureHeight : 512;
+		const textureWidth = options.textureWidth !== undefined ? options.textureWidth : 512;
+		const textureHeight = options.textureHeight !== undefined ? options.textureHeight : 512;
 
-	var clipBias = options.clipBias !== undefined ? options.clipBias : 0.0;
-	var alpha = options.alpha !== undefined ? options.alpha : 1.0;
-	var time = options.time !== undefined ? options.time : 0.0;
-	var normalSampler = options.waterNormals !== undefined ? options.waterNormals : null;
-	var sunDirection = options.sunDirection !== undefined ? options.sunDirection : new Vector3( 0.70707, 0.70707, 0.0 );
-	var sunColor = new Color( options.sunColor !== undefined ? options.sunColor : 0xffffff );
-	var waterColor = new Color( options.waterColor !== undefined ? options.waterColor : 0x7F7F7F );
-	var eye = options.eye !== undefined ? options.eye : new Vector3( 0, 0, 0 );
-	var distortionScale = options.distortionScale !== undefined ? options.distortionScale : 20.0;
-	var side = options.side !== undefined ? options.side : FrontSide;
-	var fog = options.fog !== undefined ? options.fog : false;
+		const clipBias = options.clipBias !== undefined ? options.clipBias : 0.0;
+		const alpha = options.alpha !== undefined ? options.alpha : 1.0;
+		const time = options.time !== undefined ? options.time : 0.0;
+		const normalSampler = options.waterNormals !== undefined ? options.waterNormals : null;
+		const sunDirection = options.sunDirection !== undefined ? options.sunDirection : new Vector3( 0.70707, 0.70707, 0.0 );
+		const sunColor = new Color( options.sunColor !== undefined ? options.sunColor : 0xffffff );
+		const waterColor = new Color( options.waterColor !== undefined ? options.waterColor : 0x7F7F7F );
+		const eye = options.eye !== undefined ? options.eye : new Vector3( 0, 0, 0 );
+		const distortionScale = options.distortionScale !== undefined ? options.distortionScale : 20.0;
+		const side = options.side !== undefined ? options.side : FrontSide;
+		const fog = options.fog !== undefined ? options.fog : false;
 
-	//
+		//
 
-	var mirrorPlane = new Plane();
-	var normal = new Vector3();
-	var mirrorWorldPosition = new Vector3();
-	var cameraWorldPosition = new Vector3();
-	var rotationMatrix = new Matrix4();
-	var lookAtPosition = new Vector3( 0, 0, - 1 );
-	var clipPlane = new Vector4();
+		const mirrorPlane = new Plane();
+		const normal = new Vector3();
+		const mirrorWorldPosition = new Vector3();
+		const cameraWorldPosition = new Vector3();
+		const rotationMatrix = new Matrix4();
+		const lookAtPosition = new Vector3( 0, 0, - 1 );
+		const clipPlane = new Vector4();
 
-	var view = new Vector3();
-	var target = new Vector3();
-	var q = new Vector4();
+		const view = new Vector3();
+		const target = new Vector3();
+		const q = new Vector4();
 
-	var textureMatrix = new Matrix4();
+		const textureMatrix = new Matrix4();
 
-	var mirrorCamera = new PerspectiveCamera();
+		const mirrorCamera = new PerspectiveCamera();
 
-	var parameters = {
-		minFilter: LinearFilter,
-		magFilter: LinearFilter,
-		format: RGBFormat
-	};
+		const parameters = {
+			minFilter: LinearFilter,
+			magFilter: LinearFilter,
+			format: RGBFormat
+		};
 
-	var renderTarget = new WebGLRenderTarget( textureWidth, textureHeight, parameters );
+		const renderTarget = new WebGLRenderTarget( textureWidth, textureHeight, parameters );
 
-	if ( ! MathUtils.isPowerOfTwo( textureWidth ) || ! MathUtils.isPowerOfTwo( textureHeight ) ) {
+		if ( ! MathUtils.isPowerOfTwo( textureWidth ) || ! MathUtils.isPowerOfTwo( textureHeight ) ) {
 
-		renderTarget.texture.generateMipmaps = false;
+			renderTarget.texture.generateMipmaps = false;
 
-	}
+		}
 
-	var mirrorShader = {
-
-		uniforms: UniformsUtils.merge( [
-			UniformsLib[ 'fog' ],
-			UniformsLib[ 'lights' ],
-			{
-				'normalSampler': { value: null },
-				'mirrorSampler': { value: null },
-				'alpha': { value: 1.0 },
-				'time': { value: 0.0 },
-				'size': { value: 1.0 },
-				'distortionScale': { value: 20.0 },
-				'textureMatrix': { value: new Matrix4() },
-				'sunColor': { value: new Color( 0x7F7F7F ) },
-				'sunDirection': { value: new Vector3( 0.70707, 0.70707, 0 ) },
-				'eye': { value: new Vector3() },
-				'waterColor': { value: new Color( 0x555555 ) }
-			}
-		] ),
-
-		vertexShader: [
-			'uniform mat4 textureMatrix;',
-			'uniform float time;',
-
-			'varying vec4 mirrorCoord;',
-			'varying vec4 worldPosition;',
-
-		 	'#include <common>',
-		 	'#include <fog_pars_vertex>',
-			'#include <shadowmap_pars_vertex>',
-			'#include <logdepthbuf_pars_vertex>',
-
-			'void main() {',
-			'	mirrorCoord = modelMatrix * vec4( position, 1.0 );',
-			'	worldPosition = mirrorCoord.xyzw;',
-			'	mirrorCoord = textureMatrix * mirrorCoord;',
-			'	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>',
-			'}'
-		].join( '\n' ),
-
-		fragmentShader: [
-			'uniform sampler2D mirrorSampler;',
-			'uniform float alpha;',
-			'uniform float time;',
-			'uniform float size;',
-			'uniform float distortionScale;',
-			'uniform sampler2D normalSampler;',
-			'uniform vec3 sunColor;',
-			'uniform vec3 sunDirection;',
-			'uniform vec3 eye;',
-			'uniform vec3 waterColor;',
-
-			'varying vec4 mirrorCoord;',
-			'varying vec4 worldPosition;',
-
-			'vec4 getNoise( vec2 uv ) {',
-			'	vec2 uv0 = ( uv / 103.0 ) + vec2(time / 17.0, time / 29.0);',
-			'	vec2 uv1 = uv / 107.0-vec2( time / -19.0, time / 31.0 );',
-			'	vec2 uv2 = uv / vec2( 8907.0, 9803.0 ) + vec2( time / 101.0, time / 97.0 );',
-			'	vec2 uv3 = uv / vec2( 1091.0, 1027.0 ) - vec2( time / 109.0, time / -113.0 );',
-			'	vec4 noise = texture2D( normalSampler, uv0 ) +',
-			'		texture2D( normalSampler, uv1 ) +',
-			'		texture2D( normalSampler, uv2 ) +',
-			'		texture2D( normalSampler, uv3 );',
-			'	return noise * 0.5 - 1.0;',
-			'}',
-
-			'void sunLight( const vec3 surfaceNormal, const vec3 eyeDirection, float shiny, float spec, float diffuse, inout vec3 diffuseColor, inout vec3 specularColor ) {',
-			'	vec3 reflection = normalize( reflect( -sunDirection, surfaceNormal ) );',
-			'	float direction = max( 0.0, dot( eyeDirection, reflection ) );',
-			'	specularColor += pow( direction, shiny ) * sunColor * spec;',
-			'	diffuseColor += max( dot( sunDirection, surfaceNormal ), 0.0 ) * sunColor * diffuse;',
-			'}',
-
-			'#include <common>',
-			'#include <packing>',
-			'#include <bsdfs>',
-			'#include <fog_pars_fragment>',
-			'#include <logdepthbuf_pars_fragment>',
-			'#include <lights_pars_begin>',
-			'#include <shadowmap_pars_fragment>',
-			'#include <shadowmask_pars_fragment>',
-
-			'void main() {',
-
-			'#include <logdepthbuf_fragment>',
-			'	vec4 noise = getNoise( worldPosition.xz * size );',
-			'	vec3 surfaceNormal = normalize( noise.xzy * vec3( 1.5, 1.0, 1.5 ) );',
-
-			'	vec3 diffuseLight = vec3(0.0);',
-			'	vec3 specularLight = vec3(0.0);',
-
-			'	vec3 worldToEye = eye-worldPosition.xyz;',
-			'	vec3 eyeDirection = normalize( worldToEye );',
-			'	sunLight( surfaceNormal, eyeDirection, 100.0, 2.0, 0.5, diffuseLight, specularLight );',
-
-			'	float distance = length(worldToEye);',
-
-			'	vec2 distortion = surfaceNormal.xz * ( 0.001 + 1.0 / distance ) * distortionScale;',
-			'	vec3 reflectionSample = vec3( texture2D( mirrorSampler, mirrorCoord.xy / mirrorCoord.w + distortion ) );',
-
-			'	float theta = max( dot( eyeDirection, surfaceNormal ), 0.0 );',
-			'	float rf0 = 0.3;',
-			'	float reflectance = rf0 + ( 1.0 - rf0 ) * pow( ( 1.0 - theta ), 5.0 );',
-			'	vec3 scatter = max( 0.0, dot( surfaceNormal, eyeDirection ) ) * waterColor;',
-			'	vec3 albedo = mix( ( sunColor * diffuseLight * 0.3 + scatter ) * getShadowMask(), ( vec3( 0.1 ) + reflectionSample * 0.9 + reflectionSample * specularLight ), reflectance);',
-			'	vec3 outgoingLight = albedo;',
-			'	gl_FragColor = vec4( outgoingLight, alpha );',
-
-			'#include <tonemapping_fragment>',
-			'#include <fog_fragment>',
-			'}'
-		].join( '\n' )
-
-	};
-
-	var material = new ShaderMaterial( {
-		fragmentShader: mirrorShader.fragmentShader,
-		vertexShader: mirrorShader.vertexShader,
-		uniforms: UniformsUtils.clone( mirrorShader.uniforms ),
-		lights: true,
-		side: side,
-		fog: fog
-	} );
-
-	material.uniforms[ 'mirrorSampler' ].value = renderTarget.texture;
-	material.uniforms[ 'textureMatrix' ].value = textureMatrix;
-	material.uniforms[ 'alpha' ].value = alpha;
-	material.uniforms[ 'time' ].value = time;
-	material.uniforms[ 'normalSampler' ].value = normalSampler;
-	material.uniforms[ 'sunColor' ].value = sunColor;
-	material.uniforms[ 'waterColor' ].value = waterColor;
-	material.uniforms[ 'sunDirection' ].value = sunDirection;
-	material.uniforms[ 'distortionScale' ].value = distortionScale;
+		const mirrorShader = {
+
+			uniforms: UniformsUtils.merge( [
+				UniformsLib[ 'fog' ],
+				UniformsLib[ 'lights' ],
+				{
+					'normalSampler': { value: null },
+					'mirrorSampler': { value: null },
+					'alpha': { value: 1.0 },
+					'time': { value: 0.0 },
+					'size': { value: 1.0 },
+					'distortionScale': { value: 20.0 },
+					'textureMatrix': { value: new Matrix4() },
+					'sunColor': { value: new Color( 0x7F7F7F ) },
+					'sunDirection': { value: new Vector3( 0.70707, 0.70707, 0 ) },
+					'eye': { value: new Vector3() },
+					'waterColor': { value: new Color( 0x555555 ) }
+				}
+			] ),
+
+			vertexShader: [
+				'uniform mat4 textureMatrix;',
+				'uniform float time;',
+
+				'varying vec4 mirrorCoord;',
+				'varying vec4 worldPosition;',
+
+			 	'#include <common>',
+			 	'#include <fog_pars_vertex>',
+				'#include <shadowmap_pars_vertex>',
+				'#include <logdepthbuf_pars_vertex>',
+
+				'void main() {',
+				'	mirrorCoord = modelMatrix * vec4( position, 1.0 );',
+				'	worldPosition = mirrorCoord.xyzw;',
+				'	mirrorCoord = textureMatrix * mirrorCoord;',
+				'	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>',
+				'}'
+			].join( '\n' ),
+
+			fragmentShader: [
+				'uniform sampler2D mirrorSampler;',
+				'uniform float alpha;',
+				'uniform float time;',
+				'uniform float size;',
+				'uniform float distortionScale;',
+				'uniform sampler2D normalSampler;',
+				'uniform vec3 sunColor;',
+				'uniform vec3 sunDirection;',
+				'uniform vec3 eye;',
+				'uniform vec3 waterColor;',
+
+				'varying vec4 mirrorCoord;',
+				'varying vec4 worldPosition;',
+
+				'vec4 getNoise( vec2 uv ) {',
+				'	vec2 uv0 = ( uv / 103.0 ) + vec2(time / 17.0, time / 29.0);',
+				'	vec2 uv1 = uv / 107.0-vec2( time / -19.0, time / 31.0 );',
+				'	vec2 uv2 = uv / vec2( 8907.0, 9803.0 ) + vec2( time / 101.0, time / 97.0 );',
+				'	vec2 uv3 = uv / vec2( 1091.0, 1027.0 ) - vec2( time / 109.0, time / -113.0 );',
+				'	vec4 noise = texture2D( normalSampler, uv0 ) +',
+				'		texture2D( normalSampler, uv1 ) +',
+				'		texture2D( normalSampler, uv2 ) +',
+				'		texture2D( normalSampler, uv3 );',
+				'	return noise * 0.5 - 1.0;',
+				'}',
+
+				'void sunLight( const vec3 surfaceNormal, const vec3 eyeDirection, float shiny, float spec, float diffuse, inout vec3 diffuseColor, inout vec3 specularColor ) {',
+				'	vec3 reflection = normalize( reflect( -sunDirection, surfaceNormal ) );',
+				'	float direction = max( 0.0, dot( eyeDirection, reflection ) );',
+				'	specularColor += pow( direction, shiny ) * sunColor * spec;',
+				'	diffuseColor += max( dot( sunDirection, surfaceNormal ), 0.0 ) * sunColor * diffuse;',
+				'}',
+
+				'#include <common>',
+				'#include <packing>',
+				'#include <bsdfs>',
+				'#include <fog_pars_fragment>',
+				'#include <logdepthbuf_pars_fragment>',
+				'#include <lights_pars_begin>',
+				'#include <shadowmap_pars_fragment>',
+				'#include <shadowmask_pars_fragment>',
+
+				'void main() {',
+
+				'#include <logdepthbuf_fragment>',
+				'	vec4 noise = getNoise( worldPosition.xz * size );',
+				'	vec3 surfaceNormal = normalize( noise.xzy * vec3( 1.5, 1.0, 1.5 ) );',
+
+				'	vec3 diffuseLight = vec3(0.0);',
+				'	vec3 specularLight = vec3(0.0);',
+
+				'	vec3 worldToEye = eye-worldPosition.xyz;',
+				'	vec3 eyeDirection = normalize( worldToEye );',
+				'	sunLight( surfaceNormal, eyeDirection, 100.0, 2.0, 0.5, diffuseLight, specularLight );',
+
+				'	float distance = length(worldToEye);',
+
+				'	vec2 distortion = surfaceNormal.xz * ( 0.001 + 1.0 / distance ) * distortionScale;',
+				'	vec3 reflectionSample = vec3( texture2D( mirrorSampler, mirrorCoord.xy / mirrorCoord.w + distortion ) );',
+
+				'	float theta = max( dot( eyeDirection, surfaceNormal ), 0.0 );',
+				'	float rf0 = 0.3;',
+				'	float reflectance = rf0 + ( 1.0 - rf0 ) * pow( ( 1.0 - theta ), 5.0 );',
+				'	vec3 scatter = max( 0.0, dot( surfaceNormal, eyeDirection ) ) * waterColor;',
+				'	vec3 albedo = mix( ( sunColor * diffuseLight * 0.3 + scatter ) * getShadowMask(), ( vec3( 0.1 ) + reflectionSample * 0.9 + reflectionSample * specularLight ), reflectance);',
+				'	vec3 outgoingLight = albedo;',
+				'	gl_FragColor = vec4( outgoingLight, alpha );',
+
+				'#include <tonemapping_fragment>',
+				'#include <fog_fragment>',
+				'}'
+			].join( '\n' )
+
+		};
+
+		const material = new ShaderMaterial( {
+			fragmentShader: mirrorShader.fragmentShader,
+			vertexShader: mirrorShader.vertexShader,
+			uniforms: UniformsUtils.clone( mirrorShader.uniforms ),
+			lights: true,
+			side: side,
+			fog: fog
+		} );
+
+		material.uniforms[ 'mirrorSampler' ].value = renderTarget.texture;
+		material.uniforms[ 'textureMatrix' ].value = textureMatrix;
+		material.uniforms[ 'alpha' ].value = alpha;
+		material.uniforms[ 'time' ].value = time;
+		material.uniforms[ 'normalSampler' ].value = normalSampler;
+		material.uniforms[ 'sunColor' ].value = sunColor;
+		material.uniforms[ 'waterColor' ].value = waterColor;
+		material.uniforms[ 'sunDirection' ].value = sunDirection;
+		material.uniforms[ 'distortionScale' ].value = distortionScale;
 
-	material.uniforms[ 'eye' ].value = eye;
+		material.uniforms[ 'eye' ].value = eye;
 
-	scope.material = material;
+		scope.material = material;
 
-	scope.onBeforeRender = function ( renderer, scene, camera ) {
+		scope.onBeforeRender = function ( renderer, scene, camera ) {
 
-		mirrorWorldPosition.setFromMatrixPosition( scope.matrixWorld );
-		cameraWorldPosition.setFromMatrixPosition( camera.matrixWorld );
+			mirrorWorldPosition.setFromMatrixPosition( scope.matrixWorld );
+			cameraWorldPosition.setFromMatrixPosition( camera.matrixWorld );
 
-		rotationMatrix.extractRotation( scope.matrixWorld );
+			rotationMatrix.extractRotation( scope.matrixWorld );
 
-		normal.set( 0, 0, 1 );
-		normal.applyMatrix4( rotationMatrix );
+			normal.set( 0, 0, 1 );
+			normal.applyMatrix4( rotationMatrix );
 
-		view.subVectors( mirrorWorldPosition, cameraWorldPosition );
+			view.subVectors( mirrorWorldPosition, cameraWorldPosition );
 
-		// Avoid rendering when mirror is facing away
+			// Avoid rendering when mirror is facing away
 
-		if ( view.dot( normal ) > 0 ) return;
+			if ( view.dot( normal ) > 0 ) return;
 
-		view.reflect( normal ).negate();
-		view.add( mirrorWorldPosition );
+			view.reflect( normal ).negate();
+			view.add( mirrorWorldPosition );
 
-		rotationMatrix.extractRotation( camera.matrixWorld );
+			rotationMatrix.extractRotation( camera.matrixWorld );
 
-		lookAtPosition.set( 0, 0, - 1 );
-		lookAtPosition.applyMatrix4( rotationMatrix );
-		lookAtPosition.add( cameraWorldPosition );
+			lookAtPosition.set( 0, 0, - 1 );
+			lookAtPosition.applyMatrix4( rotationMatrix );
+			lookAtPosition.add( cameraWorldPosition );
 
-		target.subVectors( mirrorWorldPosition, lookAtPosition );
-		target.reflect( normal ).negate();
-		target.add( mirrorWorldPosition );
+			target.subVectors( mirrorWorldPosition, lookAtPosition );
+			target.reflect( normal ).negate();
+			target.add( mirrorWorldPosition );
 
-		mirrorCamera.position.copy( view );
-		mirrorCamera.up.set( 0, 1, 0 );
-		mirrorCamera.up.applyMatrix4( rotationMatrix );
-		mirrorCamera.up.reflect( normal );
-		mirrorCamera.lookAt( target );
+			mirrorCamera.position.copy( view );
+			mirrorCamera.up.set( 0, 1, 0 );
+			mirrorCamera.up.applyMatrix4( rotationMatrix );
+			mirrorCamera.up.reflect( normal );
+			mirrorCamera.lookAt( target );
 
-		mirrorCamera.far = camera.far; // Used in WebGLBackground
+			mirrorCamera.far = camera.far; // Used in WebGLBackground
 
-		mirrorCamera.updateMatrixWorld();
-		mirrorCamera.projectionMatrix.copy( camera.projectionMatrix );
+			mirrorCamera.updateMatrixWorld();
+			mirrorCamera.projectionMatrix.copy( camera.projectionMatrix );
 
-		// Update the texture matrix
-		textureMatrix.set(
-			0.5, 0.0, 0.0, 0.5,
-			0.0, 0.5, 0.0, 0.5,
-			0.0, 0.0, 0.5, 0.5,
-			0.0, 0.0, 0.0, 1.0
-		);
-		textureMatrix.multiply( mirrorCamera.projectionMatrix );
-		textureMatrix.multiply( mirrorCamera.matrixWorldInverse );
+			// Update the texture matrix
+			textureMatrix.set(
+				0.5, 0.0, 0.0, 0.5,
+				0.0, 0.5, 0.0, 0.5,
+				0.0, 0.0, 0.5, 0.5,
+				0.0, 0.0, 0.0, 1.0
+			);
+			textureMatrix.multiply( mirrorCamera.projectionMatrix );
+			textureMatrix.multiply( mirrorCamera.matrixWorldInverse );
 
-		// Now update projection matrix with new clip plane, implementing code from: http://www.terathon.com/code/oblique.html
-		// Paper explaining this technique: http://www.terathon.com/lengyel/Lengyel-Oblique.pdf
-		mirrorPlane.setFromNormalAndCoplanarPoint( normal, mirrorWorldPosition );
-		mirrorPlane.applyMatrix4( mirrorCamera.matrixWorldInverse );
+			// Now update projection matrix with new clip plane, implementing code from: http://www.terathon.com/code/oblique.html
+			// Paper explaining this technique: http://www.terathon.com/lengyel/Lengyel-Oblique.pdf
+			mirrorPlane.setFromNormalAndCoplanarPoint( normal, mirrorWorldPosition );
+			mirrorPlane.applyMatrix4( mirrorCamera.matrixWorldInverse );
 
-		clipPlane.set( mirrorPlane.normal.x, mirrorPlane.normal.y, mirrorPlane.normal.z, mirrorPlane.constant );
+			clipPlane.set( mirrorPlane.normal.x, mirrorPlane.normal.y, mirrorPlane.normal.z, mirrorPlane.constant );
 
-		var projectionMatrix = mirrorCamera.projectionMatrix;
+			const projectionMatrix = mirrorCamera.projectionMatrix;
 
-		q.x = ( Math.sign( clipPlane.x ) + projectionMatrix.elements[ 8 ] ) / projectionMatrix.elements[ 0 ];
-		q.y = ( Math.sign( clipPlane.y ) + projectionMatrix.elements[ 9 ] ) / projectionMatrix.elements[ 5 ];
-		q.z = - 1.0;
-		q.w = ( 1.0 + projectionMatrix.elements[ 10 ] ) / projectionMatrix.elements[ 14 ];
+			q.x = ( Math.sign( clipPlane.x ) + projectionMatrix.elements[ 8 ] ) / projectionMatrix.elements[ 0 ];
+			q.y = ( Math.sign( clipPlane.y ) + projectionMatrix.elements[ 9 ] ) / projectionMatrix.elements[ 5 ];
+			q.z = - 1.0;
+			q.w = ( 1.0 + projectionMatrix.elements[ 10 ] ) / projectionMatrix.elements[ 14 ];
 
-		// Calculate the scaled plane vector
-		clipPlane.multiplyScalar( 2.0 / clipPlane.dot( q ) );
+			// Calculate the scaled plane vector
+			clipPlane.multiplyScalar( 2.0 / clipPlane.dot( q ) );
 
-		// Replacing the third row of the projection matrix
-		projectionMatrix.elements[ 2 ] = clipPlane.x;
-		projectionMatrix.elements[ 6 ] = clipPlane.y;
-		projectionMatrix.elements[ 10 ] = clipPlane.z + 1.0 - clipBias;
-		projectionMatrix.elements[ 14 ] = clipPlane.w;
+			// Replacing the third row of the projection matrix
+			projectionMatrix.elements[ 2 ] = clipPlane.x;
+			projectionMatrix.elements[ 6 ] = clipPlane.y;
+			projectionMatrix.elements[ 10 ] = clipPlane.z + 1.0 - clipBias;
+			projectionMatrix.elements[ 14 ] = clipPlane.w;
 
-		eye.setFromMatrixPosition( camera.matrixWorld );
+			eye.setFromMatrixPosition( camera.matrixWorld );
 
-		// Render
+			// Render
 
-		var currentRenderTarget = renderer.getRenderTarget();
+			const currentRenderTarget = renderer.getRenderTarget();
 
-		var currentXrEnabled = renderer.xr.enabled;
-		var currentShadowAutoUpdate = renderer.shadowMap.autoUpdate;
+			const currentXrEnabled = renderer.xr.enabled;
+			const currentShadowAutoUpdate = renderer.shadowMap.autoUpdate;
 
-		scope.visible = false;
+			scope.visible = false;
 
-		renderer.xr.enabled = false; // Avoid camera modification and recursion
-		renderer.shadowMap.autoUpdate = false; // Avoid re-computing shadows
+			renderer.xr.enabled = false; // Avoid camera modification and recursion
+			renderer.shadowMap.autoUpdate = false; // Avoid re-computing shadows
 
-		renderer.setRenderTarget( renderTarget );
+			renderer.setRenderTarget( renderTarget );
 
-		renderer.state.buffers.depth.setMask( true ); // make sure the depth buffer is writable so it can be properly cleared, see #18897
+			renderer.state.buffers.depth.setMask( true ); // make sure the depth buffer is writable so it can be properly cleared, see #18897
 
-		if ( renderer.autoClear === false ) renderer.clear();
-		renderer.render( scene, mirrorCamera );
+			if ( renderer.autoClear === false ) renderer.clear();
+			renderer.render( scene, mirrorCamera );
 
-		scope.visible = true;
+			scope.visible = true;
 
-		renderer.xr.enabled = currentXrEnabled;
-		renderer.shadowMap.autoUpdate = currentShadowAutoUpdate;
+			renderer.xr.enabled = currentXrEnabled;
+			renderer.shadowMap.autoUpdate = currentShadowAutoUpdate;
 
-		renderer.setRenderTarget( currentRenderTarget );
+			renderer.setRenderTarget( currentRenderTarget );
 
-		// Restore viewport
+			// Restore viewport
 
-		var viewport = camera.viewport;
+			const viewport = camera.viewport;
 
-		if ( viewport !== undefined ) {
+			if ( viewport !== undefined ) {
 
-			renderer.state.viewport( viewport );
+				renderer.state.viewport( viewport );
 
-		}
+			}
+
+		};
 
-	};
+	}
 
-};
+}
 
-Water.prototype = Object.create( Mesh.prototype );
-Water.prototype.constructor = Water;
+Water.prototype.isWater = true;
 
 export { Water };

+ 133 - 132
examples/jsm/objects/Water2.js

@@ -22,189 +22,190 @@ import { Refractor } from '../objects/Refractor.js';
  *
  */
 
-var Water = function ( geometry, options ) {
+class Water extends Mesh {
 
-	Mesh.call( this, geometry );
+	constructor( geometry, options = {} ) {
 
-	this.type = 'Water';
+		super( geometry );
 
-	var scope = this;
+		this.type = 'Water';
 
-	options = options || {};
+		const scope = this;
 
-	var color = ( options.color !== undefined ) ? new Color( options.color ) : new Color( 0xFFFFFF );
-	var textureWidth = options.textureWidth || 512;
-	var textureHeight = options.textureHeight || 512;
-	var clipBias = options.clipBias || 0;
-	var flowDirection = options.flowDirection || new Vector2( 1, 0 );
-	var flowSpeed = options.flowSpeed || 0.03;
-	var reflectivity = options.reflectivity || 0.02;
-	var scale = options.scale || 1;
-	var shader = options.shader || Water.WaterShader;
-	var encoding = options.encoding !== undefined ? options.encoding : LinearEncoding;
+		const color = ( options.color !== undefined ) ? new Color( options.color ) : new Color( 0xFFFFFF );
+		const textureWidth = options.textureWidth || 512;
+		const textureHeight = options.textureHeight || 512;
+		const clipBias = options.clipBias || 0;
+		const flowDirection = options.flowDirection || new Vector2( 1, 0 );
+		const flowSpeed = options.flowSpeed || 0.03;
+		const reflectivity = options.reflectivity || 0.02;
+		const scale = options.scale || 1;
+		const shader = options.shader || Water.WaterShader;
+		const encoding = options.encoding !== undefined ? options.encoding : LinearEncoding;
 
-	var textureLoader = new TextureLoader();
+		const textureLoader = new TextureLoader();
 
-	var flowMap = options.flowMap || undefined;
-	var normalMap0 = options.normalMap0 || textureLoader.load( 'textures/water/Water_1_M_Normal.jpg' );
-	var normalMap1 = options.normalMap1 || textureLoader.load( 'textures/water/Water_2_M_Normal.jpg' );
+		const flowMap = options.flowMap || undefined;
+		const normalMap0 = options.normalMap0 || textureLoader.load( 'textures/water/Water_1_M_Normal.jpg' );
+		const normalMap1 = options.normalMap1 || textureLoader.load( 'textures/water/Water_2_M_Normal.jpg' );
 
-	var cycle = 0.15; // a cycle of a flow map phase
-	var halfCycle = cycle * 0.5;
-	var textureMatrix = new Matrix4();
-	var clock = new Clock();
+		const cycle = 0.15; // a cycle of a flow map phase
+		const halfCycle = cycle * 0.5;
+		const textureMatrix = new Matrix4();
+		const clock = new Clock();
 
-	// internal components
+		// internal components
 
-	if ( Reflector === undefined ) {
+		if ( Reflector === undefined ) {
 
-		console.error( 'THREE.Water: Required component Reflector not found.' );
-		return;
+			console.error( 'THREE.Water: Required component Reflector not found.' );
+			return;
 
-	}
-
-	if ( Refractor === undefined ) {
+		}
 
-		console.error( 'THREE.Water: Required component Refractor not found.' );
-		return;
+		if ( Refractor === undefined ) {
 
-	}
+			console.error( 'THREE.Water: Required component Refractor not found.' );
+			return;
 
-	var reflector = new Reflector( geometry, {
-		textureWidth: textureWidth,
-		textureHeight: textureHeight,
-		clipBias: clipBias,
-		encoding: encoding
-	} );
-
-	var refractor = new Refractor( geometry, {
-		textureWidth: textureWidth,
-		textureHeight: textureHeight,
-		clipBias: clipBias,
-		encoding: encoding
-	} );
-
-	reflector.matrixAutoUpdate = false;
-	refractor.matrixAutoUpdate = false;
-
-	// material
-
-	this.material = new ShaderMaterial( {
-		uniforms: UniformsUtils.merge( [
-			UniformsLib[ 'fog' ],
-			shader.uniforms
-		] ),
-		vertexShader: shader.vertexShader,
-		fragmentShader: shader.fragmentShader,
-		transparent: true,
-		fog: true
-	} );
-
-	if ( flowMap !== undefined ) {
-
-		this.material.defines.USE_FLOWMAP = '';
-		this.material.uniforms[ 'tFlowMap' ] = {
-			type: 't',
-			value: flowMap
-		};
+		}
 
-	} else {
+		const reflector = new Reflector( geometry, {
+			textureWidth: textureWidth,
+			textureHeight: textureHeight,
+			clipBias: clipBias,
+			encoding: encoding
+		} );
+
+		const refractor = new Refractor( geometry, {
+			textureWidth: textureWidth,
+			textureHeight: textureHeight,
+			clipBias: clipBias,
+			encoding: encoding
+		} );
+
+		reflector.matrixAutoUpdate = false;
+		refractor.matrixAutoUpdate = false;
+
+		// material
+
+		this.material = new ShaderMaterial( {
+			uniforms: UniformsUtils.merge( [
+				UniformsLib[ 'fog' ],
+				shader.uniforms
+			] ),
+			vertexShader: shader.vertexShader,
+			fragmentShader: shader.fragmentShader,
+			transparent: true,
+			fog: true
+		} );
+
+		if ( flowMap !== undefined ) {
+
+			this.material.defines.USE_FLOWMAP = '';
+			this.material.uniforms[ 'tFlowMap' ] = {
+				type: 't',
+				value: flowMap
+			};
+
+		} else {
+
+			this.material.uniforms[ 'flowDirection' ] = {
+				type: 'v2',
+				value: flowDirection
+			};
 
-		this.material.uniforms[ 'flowDirection' ] = {
-			type: 'v2',
-			value: flowDirection
-		};
+		}
 
-	}
+		// maps
 
-	// maps
+		normalMap0.wrapS = normalMap0.wrapT = RepeatWrapping;
+		normalMap1.wrapS = normalMap1.wrapT = RepeatWrapping;
 
-	normalMap0.wrapS = normalMap0.wrapT = RepeatWrapping;
-	normalMap1.wrapS = normalMap1.wrapT = RepeatWrapping;
+		this.material.uniforms[ 'tReflectionMap' ].value = reflector.getRenderTarget().texture;
+		this.material.uniforms[ 'tRefractionMap' ].value = refractor.getRenderTarget().texture;
+		this.material.uniforms[ 'tNormalMap0' ].value = normalMap0;
+		this.material.uniforms[ 'tNormalMap1' ].value = normalMap1;
 
-	this.material.uniforms[ 'tReflectionMap' ].value = reflector.getRenderTarget().texture;
-	this.material.uniforms[ 'tRefractionMap' ].value = refractor.getRenderTarget().texture;
-	this.material.uniforms[ 'tNormalMap0' ].value = normalMap0;
-	this.material.uniforms[ 'tNormalMap1' ].value = normalMap1;
+		// water
 
-	// water
+		this.material.uniforms[ 'color' ].value = color;
+		this.material.uniforms[ 'reflectivity' ].value = reflectivity;
+		this.material.uniforms[ 'textureMatrix' ].value = textureMatrix;
 
-	this.material.uniforms[ 'color' ].value = color;
-	this.material.uniforms[ 'reflectivity' ].value = reflectivity;
-	this.material.uniforms[ 'textureMatrix' ].value = textureMatrix;
+		// inital values
 
-	// inital values
+		this.material.uniforms[ 'config' ].value.x = 0; // flowMapOffset0
+		this.material.uniforms[ 'config' ].value.y = halfCycle; // flowMapOffset1
+		this.material.uniforms[ 'config' ].value.z = halfCycle; // halfCycle
+		this.material.uniforms[ 'config' ].value.w = scale; // scale
 
-	this.material.uniforms[ 'config' ].value.x = 0; // flowMapOffset0
-	this.material.uniforms[ 'config' ].value.y = halfCycle; // flowMapOffset1
-	this.material.uniforms[ 'config' ].value.z = halfCycle; // halfCycle
-	this.material.uniforms[ 'config' ].value.w = scale; // scale
+		// functions
 
-	// functions
+		function updateTextureMatrix( camera ) {
 
-	function updateTextureMatrix( camera ) {
+			textureMatrix.set(
+				0.5, 0.0, 0.0, 0.5,
+				0.0, 0.5, 0.0, 0.5,
+				0.0, 0.0, 0.5, 0.5,
+				0.0, 0.0, 0.0, 1.0
+			);
 
-		textureMatrix.set(
-			0.5, 0.0, 0.0, 0.5,
-			0.0, 0.5, 0.0, 0.5,
-			0.0, 0.0, 0.5, 0.5,
-			0.0, 0.0, 0.0, 1.0
-		);
+			textureMatrix.multiply( camera.projectionMatrix );
+			textureMatrix.multiply( camera.matrixWorldInverse );
+			textureMatrix.multiply( scope.matrixWorld );
 
-		textureMatrix.multiply( camera.projectionMatrix );
-		textureMatrix.multiply( camera.matrixWorldInverse );
-		textureMatrix.multiply( scope.matrixWorld );
+		}
 
-	}
+		function updateFlow() {
 
-	function updateFlow() {
+			const delta = clock.getDelta();
+			const config = scope.material.uniforms[ 'config' ];
 
-		var delta = clock.getDelta();
-		var config = scope.material.uniforms[ 'config' ];
+			config.value.x += flowSpeed * delta; // flowMapOffset0
+			config.value.y = config.value.x + halfCycle; // flowMapOffset1
 
-		config.value.x += flowSpeed * delta; // flowMapOffset0
-		config.value.y = config.value.x + halfCycle; // flowMapOffset1
+			// Important: The distance between offsets should be always the value of "halfCycle".
+			// Moreover, both offsets should be in the range of [ 0, cycle ].
+			// This approach ensures a smooth water flow and avoids "reset" effects.
 
-		// Important: The distance between offsets should be always the value of "halfCycle".
-		// Moreover, both offsets should be in the range of [ 0, cycle ].
-		// This approach ensures a smooth water flow and avoids "reset" effects.
+			if ( config.value.x >= cycle ) {
 
-		if ( config.value.x >= cycle ) {
+				config.value.x = 0;
+				config.value.y = halfCycle;
 
-			config.value.x = 0;
-			config.value.y = halfCycle;
+			} else if ( config.value.y >= cycle ) {
 
-		} else if ( config.value.y >= cycle ) {
+				config.value.y = config.value.y - cycle;
 
-			config.value.y = config.value.y - cycle;
+			}
 
 		}
 
-	}
+		//
 
-	//
+		this.onBeforeRender = function ( renderer, scene, camera ) {
 
-	this.onBeforeRender = function ( renderer, scene, camera ) {
+			updateTextureMatrix( camera );
+			updateFlow();
 
-		updateTextureMatrix( camera );
-		updateFlow();
+			scope.visible = false;
 
-		scope.visible = false;
+			reflector.matrixWorld.copy( scope.matrixWorld );
+			refractor.matrixWorld.copy( scope.matrixWorld );
 
-		reflector.matrixWorld.copy( scope.matrixWorld );
-		refractor.matrixWorld.copy( scope.matrixWorld );
+			reflector.onBeforeRender( renderer, scene, camera );
+			refractor.onBeforeRender( renderer, scene, camera );
 
-		reflector.onBeforeRender( renderer, scene, camera );
-		refractor.onBeforeRender( renderer, scene, camera );
+			scope.visible = true;
 
-		scope.visible = true;
+		};
 
-	};
+	}
 
-};
+}
 
-Water.prototype = Object.create( Mesh.prototype );
-Water.prototype.constructor = Water;
+Water.prototype.isWater = true;
 
 Water.WaterShader = {
 

Daži faili netika attēloti, jo izmaiņu fails ir pārāk liels