Browse Source

added code back and alphabetized cases

Lewy Blue 7 years ago
parent
commit
64c63fc27c

+ 0 - 3
docs/api/core/BufferGeometry.html

@@ -176,9 +176,6 @@
 			You should not change this, as it used internally for optimisation.
 		</div>
 
-		<h3>[property:Integer MaxIndex]</h3>
-		<div>Maximum number of vertices allowed, set to *65535*.</div>
-
 		<h3>[property:Object morphAttributes]</h3>
 		<div>
 			Hashmap of [page:BufferAttribute]s holding details of the geometry's [page:Geometry.morphTargets morphTargets].

+ 4 - 4
examples/css3d_periodictable.html

@@ -228,12 +228,12 @@
 				"Ds", "Darmstadium", "(281)", 10, 7,
 				"Rg", "Roentgenium", "(280)", 11, 7,
 				"Cn", "Copernicium", "(285)", 12, 7,
-				"Uut", "Unutrium", "(284)", 13, 7,
+				"Nh", "Nihonium", "(286)", 13, 7,
 				"Fl", "Flerovium", "(289)", 14, 7,
-				"Uup", "Ununpentium", "(288)", 15, 7,
+				"Mc", "Moscovium", "(290)", 15, 7,
 				"Lv", "Livermorium", "(293)", 16, 7,
-				"Uus", "Ununseptium", "(294)", 17, 7,
-				"Uuo", "Ununoctium", "(294)", 18, 7
+				"Ts", "Tennessine", "(294)", 17, 7,
+				"Og", "Oganesson", "(294)", 18, 7
 			];
 
 			var camera, scene, renderer;

+ 0 - 322
examples/js/WaterShader.js

@@ -1,322 +0,0 @@
-/**
- * @author jbouny / https://github.com/jbouny
- *
- * Work based on :
- * @author Slayvin / http://slayvin.net : Flat mirror for three.js
- * @author Stemkoski / http://www.adelphi.edu/~stemkoski : An implementation of water shader based on the flat mirror
- * @author Jonas Wagner / http://29a.ch/ && http://29a.ch/slides/2012/webglwater/ : Water shader explanations in WebGL
- */
-
-THREE.Water = function ( renderer, camera, scene, options ) {
-
-	THREE.Object3D.call( this );
-	this.name = 'water_' + this.id;
-
-	function optionalParameter( value, defaultValue ) {
-
-		return value !== undefined ? value : defaultValue;
-
-	}
-
-	options = options || {};
-
-	this.matrixNeedsUpdate = true;
-
-	var width = optionalParameter( options.textureWidth, 512 );
-	var height = optionalParameter( options.textureHeight, 512 );
-	this.clipBias = optionalParameter( options.clipBias, 0.0 );
-	this.alpha = optionalParameter( options.alpha, 1.0 );
-	this.time = optionalParameter( options.time, 0.0 );
-	this.normalSampler = optionalParameter( options.waterNormals, null );
-	this.sunDirection = optionalParameter( options.sunDirection, new THREE.Vector3( 0.70707, 0.70707, 0.0 ) );
-	this.sunColor = new THREE.Color( optionalParameter( options.sunColor, 0xffffff ) );
-	this.waterColor = new THREE.Color( optionalParameter( options.waterColor, 0x7F7F7F ) );
-	this.eye = optionalParameter( options.eye, new THREE.Vector3( 0, 0, 0 ) );
-	this.distortionScale = optionalParameter( options.distortionScale, 20.0 );
-	this.side = optionalParameter( options.side, THREE.FrontSide );
-	this.fog = optionalParameter( options.fog, false );
-
-	this.renderer = renderer;
-	this.scene = scene;
-	this.mirrorPlane = new THREE.Plane();
-	this.normal = new THREE.Vector3( 0, 0, 1 );
-	this.mirrorWorldPosition = new THREE.Vector3();
-	this.cameraWorldPosition = new THREE.Vector3();
-	this.rotationMatrix = new THREE.Matrix4();
-	this.lookAtPosition = new THREE.Vector3( 0, 0, - 1 );
-	this.clipPlane = new THREE.Vector4();
-
-	if ( camera instanceof THREE.PerspectiveCamera ) {
-
-		this.camera = camera;
-
-	} else {
-
-		this.camera = new THREE.PerspectiveCamera();
-		console.log( this.name + ': camera is not a Perspective Camera!' );
-
-	}
-
-	this.textureMatrix = new THREE.Matrix4();
-
-	this.mirrorCamera = this.camera.clone();
-
-	this.renderTarget = new THREE.WebGLRenderTarget( width, height );
-	this.renderTarget2 = new THREE.WebGLRenderTarget( width, height );
-
-	var mirrorShader = {
-
-		uniforms: THREE.UniformsUtils.merge( [
-			THREE.UniformsLib[ 'fog' ],
-			{
-				normalSampler: { value: null },
-				mirrorSampler: { value: null },
-				alpha: { value: 1.0 },
-				time: { value: 0.0 },
-				distortionScale: { value: 20.0 },
-				noiseScale: { value: 1.0 },
-				textureMatrix: { value: new THREE.Matrix4() },
-				sunColor: { value: new THREE.Color( 0x7F7F7F ) },
-				sunDirection: { value: new THREE.Vector3( 0.70707, 0.70707, 0 ) },
-				eye: { value: new THREE.Vector3() },
-				waterColor: { value: new THREE.Color( 0x555555 ) }
-			}
-		] ),
-
-		vertexShader: [
-			'uniform mat4 textureMatrix;',
-			'uniform float time;',
-
-			'varying vec4 mirrorCoord;',
-			'varying vec3 worldPosition;',
-
-			THREE.ShaderChunk[ 'fog_pars_vertex' ],
-
-			'void main() {',
-			'	mirrorCoord = modelMatrix * vec4( position, 1.0 );',
-			'	worldPosition = mirrorCoord.xyz;',
-			'	mirrorCoord = textureMatrix * mirrorCoord;',
-			'	vec4 mvPosition =  modelViewMatrix * vec4( position, 1.0 );',
-			'	gl_Position = projectionMatrix * mvPosition;',
-
-			THREE.ShaderChunk[ 'fog_vertex' ],
-
-			'}'
-		].join( '\n' ),
-
-		fragmentShader: [
-			'precision highp float;',
-
-			'uniform sampler2D mirrorSampler;',
-			'uniform float alpha;',
-			'uniform float time;',
-			'uniform float distortionScale;',
-			'uniform sampler2D normalSampler;',
-			'uniform vec3 sunColor;',
-			'uniform vec3 sunDirection;',
-			'uniform vec3 eye;',
-			'uniform vec3 waterColor;',
-
-			'varying vec4 mirrorCoord;',
-			'varying vec3 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;',
-			'}',
-
-			THREE.ShaderChunk[ 'common' ],
-			THREE.ShaderChunk[ 'fog_pars_fragment' ],
-
-			'void main() {',
-			'	vec4 noise = getNoise( worldPosition.xz );',
-			'	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;',
-			'	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.z + 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, ( vec3( 0.1 ) + reflectionSample * 0.9 + reflectionSample * specularLight ), reflectance );',
-			'	vec3 outgoingLight = albedo;',
-			'	gl_FragColor = vec4( outgoingLight, alpha );',
-
-			THREE.ShaderChunk[ 'fog_fragment' ],
-
-			'}'
-		].join( '\n' )
-
-	};
-
-	var mirrorUniforms = THREE.UniformsUtils.clone( mirrorShader.uniforms );
-
-	this.material = new THREE.ShaderMaterial( {
-		fragmentShader: mirrorShader.fragmentShader,
-		vertexShader: mirrorShader.vertexShader,
-		uniforms: mirrorUniforms,
-		transparent: true,
-		side: this.side,
-		fog: this.fog
-	} );
-
-	this.material.uniforms.mirrorSampler.value = this.renderTarget.texture;
-	this.material.uniforms.textureMatrix.value = this.textureMatrix;
-	this.material.uniforms.alpha.value = this.alpha;
-	this.material.uniforms.time.value = this.time;
-	this.material.uniforms.normalSampler.value = this.normalSampler;
-	this.material.uniforms.sunColor.value = this.sunColor;
-	this.material.uniforms.waterColor.value = this.waterColor;
-	this.material.uniforms.sunDirection.value = this.sunDirection;
-	this.material.uniforms.distortionScale.value = this.distortionScale;
-
-	this.material.uniforms.eye.value = this.eye;
-
-	if ( ! THREE.Math.isPowerOfTwo( width ) || ! THREE.Math.isPowerOfTwo( height ) ) {
-
-		this.renderTarget.texture.generateMipmaps = false;
-		this.renderTarget.texture.minFilter = THREE.LinearFilter;
-		this.renderTarget2.texture.generateMipmaps = false;
-		this.renderTarget2.texture.minFilter = THREE.LinearFilter;
-
-	}
-
-	this.updateTextureMatrix();
-	this.render();
-
-};
-
-THREE.Water.prototype = Object.create( THREE.Object3D.prototype );
-THREE.Water.prototype.constructor = THREE.Water;
-
-THREE.Water.prototype.render = function () {
-
-	if ( this.matrixNeedsUpdate ) this.updateTextureMatrix();
-
-	this.matrixNeedsUpdate = true;
-
-	// Render the mirrored view of the current scene into the target texture
-	var scene = this;
-
-	while ( scene.parent !== null ) {
-
-		scene = scene.parent;
-
-	}
-
-	if ( scene !== undefined && scene instanceof THREE.Scene ) {
-
-		this.material.visible = false;
-
-		this.renderer.render( scene, this.mirrorCamera, this.renderTarget, true );
-
-		this.material.visible = true;
-
-	}
-
-};
-
-
-THREE.Water.prototype.updateTextureMatrix = function () {
-
-	this.updateMatrixWorld();
-	this.camera.updateMatrixWorld();
-
-	this.mirrorWorldPosition.setFromMatrixPosition( this.matrixWorld );
-	this.cameraWorldPosition.setFromMatrixPosition( this.camera.matrixWorld );
-
-	this.rotationMatrix.extractRotation( this.matrixWorld );
-
-	this.normal.set( 0, 0, 1 );
-	this.normal.applyMatrix4( this.rotationMatrix );
-
-	var view = this.mirrorWorldPosition.clone().sub( this.cameraWorldPosition );
-	view.reflect( this.normal ).negate();
-	view.add( this.mirrorWorldPosition );
-
-	this.rotationMatrix.extractRotation( this.camera.matrixWorld );
-
-	this.lookAtPosition.set( 0, 0, - 1 );
-	this.lookAtPosition.applyMatrix4( this.rotationMatrix );
-	this.lookAtPosition.add( this.cameraWorldPosition );
-
-	var target = this.mirrorWorldPosition.clone().sub( this.lookAtPosition );
-	target.reflect( this.normal ).negate();
-	target.add( this.mirrorWorldPosition );
-
-	this.up.set( 0, - 1, 0 );
-	this.up.applyMatrix4( this.rotationMatrix );
-	this.up.reflect( this.normal ).negate();
-
-	this.mirrorCamera.position.copy( view );
-	this.mirrorCamera.up = this.up;
-	this.mirrorCamera.lookAt( target );
-	this.mirrorCamera.aspect = this.camera.aspect;
-
-	this.mirrorCamera.updateProjectionMatrix();
-	this.mirrorCamera.updateMatrixWorld();
-
-	// Update the texture matrix
-	this.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
-	);
-	this.textureMatrix.multiply( this.mirrorCamera.projectionMatrix );
-	this.textureMatrix.multiply( this.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
-	this.mirrorPlane.setFromNormalAndCoplanarPoint( this.normal, this.mirrorWorldPosition );
-	this.mirrorPlane.applyMatrix4( this.mirrorCamera.matrixWorldInverse );
-
-	this.clipPlane.set( this.mirrorPlane.normal.x, this.mirrorPlane.normal.y, this.mirrorPlane.normal.z, this.mirrorPlane.constant );
-
-	var q = new THREE.Vector4();
-	var projectionMatrix = this.mirrorCamera.projectionMatrix;
-
-	q.x = ( Math.sign( this.clipPlane.x ) + projectionMatrix.elements[ 8 ] ) / projectionMatrix.elements[ 0 ];
-	q.y = ( Math.sign( this.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
-	var c = this.clipPlane.multiplyScalar( 2.0 / this.clipPlane.dot( q ) );
-
-	// Replacing the third row of the projection matrix
-	projectionMatrix.elements[ 2 ] = c.x;
-	projectionMatrix.elements[ 6 ] = c.y;
-	projectionMatrix.elements[ 10 ] = c.z + 1.0 - this.clipBias;
-	projectionMatrix.elements[ 14 ] = c.w;
-
-	var worldCoordinates = new THREE.Vector3();
-	worldCoordinates.setFromMatrixPosition( this.camera.matrixWorld );
-	this.eye = worldCoordinates;
-	this.material.uniforms.eye.value = this.eye;
-
-};

+ 143 - 0
examples/js/loaders/FBXLoader.js

@@ -1449,6 +1449,149 @@
 						}
 						break;
 
+<<<<<<< HEAD
+=======
+					case 'Light':
+						/* ***********
+						* Supported light types:
+						* DirectionalLight
+						* PointLight
+						* SpotLight
+						*
+						* TODO: Support DirectionalLight and SpotLight targets
+						************** */
+
+						var lightAttribute;
+
+						for ( var childrenIndex = 0, childrenLength = conns.children.length; childrenIndex < childrenLength; ++ childrenIndex ) {
+
+							var childID = conns.children[ childrenIndex ].ID;
+
+							var attr = FBXTree.Objects.subNodes.NodeAttribute[ childID ];
+
+							if ( attr !== undefined && attr.properties !== undefined ) {
+
+								lightAttribute = attr.properties;
+
+							}
+
+						}
+
+						if ( lightAttribute === undefined ) {
+
+							model = new THREE.Object3D();
+
+						} else {
+
+							var type;
+
+							// LightType can be undefined for Point lights
+							if ( lightAttribute.LightType === undefined ) {
+
+								type = 0;
+
+							} else {
+
+								type = lightAttribute.LightType.value;
+
+							}
+
+							var color = 0xffffff;
+
+							if ( lightAttribute.Color !== undefined ) {
+
+								var temp = lightAttribute.Color.value.split( ',' );
+
+								var r = parseFloat( temp[ 0 ] );
+								var g = parseFloat( temp[ 1 ] );
+								var b = parseFloat( temp[ 1 ] );
+
+								color = new THREE.Color( r, g, b );
+
+							}
+
+							var intensity = ( lightAttribute.Intensity === undefined ) ? 1 : lightAttribute.Intensity.value / 100;
+
+							// light disabled
+							if ( lightAttribute.CastLightOnObject !== undefined && ( lightAttribute.CastLightOnObject.value === '0' || lightAttribute.CastLightOnObject.value === 0 ) ) {
+
+								intensity = 0;
+
+							}
+
+							var distance = 0;
+							if ( lightAttribute.FarAttenuationEnd !== undefined ) {
+
+								if ( lightAttribute.EnableFarAttenuation !== undefined && ( lightAttribute.EnableFarAttenuation.value === '0' || lightAttribute.EnableFarAttenuation.value === 0 ) ) {
+
+									distance = 0;
+
+								}	else {
+
+									distance = lightAttribute.FarAttenuationEnd.value / 1000;
+
+								}
+
+							}
+
+							// TODO
+							// could be calculated linearly from FarAttenuationStart to FarAttenuationEnd?
+							var decay = 1;
+
+							switch ( type ) {
+
+								case '0': // Point
+								case 0:
+									model = new THREE.PointLight( color, intensity, distance, decay );
+									break;
+
+								case '1': // Directional
+								case 1:
+									model = new THREE.DirectionalLight( color, intensity );
+									break;
+
+								case '2': // Spot
+								case 2:
+									var angle = Math.PI / 3;
+
+									if ( lightAttribute.InnerAngle !== undefined ) {
+
+										angle = THREE.Math.degToRad( lightAttribute.InnerAngle.value );
+
+									}
+
+									var penumbra = 0;
+									if ( lightAttribute.OuterAngle !== undefined ) {
+
+										// TODO: this is not correct - FBX calculates outer and inner angle in degrees
+										// with OuterAngle > InnerAngle && OuterAngle <= Math.PI
+										// while three.js uses a penumbra between (0, 1) to attenuate the inner angle
+										penumbra = THREE.Math.degToRad( lightAttribute.OuterAngle.value );
+										penumbra = Math.max( penumbra, 1 );
+
+									}
+
+									model = new THREE.SpotLight( color, intensity, distance, angle, penumbra, decay );
+									break;
+
+								default:
+									console.warn( 'THREE.FBXLoader: Unknown light type ' + lightAttribute.LightType.value + ', defaulting to a THREE.PointLight.' );
+									model = new THREE.PointLight( color, intensity );
+									break;
+
+							}
+
+							if ( lightAttribute.CastShadows !== undefined && ( lightAttribute.CastShadows.value === '1' || lightAttribute.CastShadows.value === 1 ) ) {
+
+								model.castShadow = true;
+
+							}
+
+						}
+
+						break;
+
+>>>>>>> 697505d2cf8c66a9efcfcae066bd63aa66ef6d9c
 					case 'NurbsCurve':
 						var geometry = null;
 

+ 1 - 0
examples/js/Mirror.js → examples/js/objects/Mirror.js

@@ -239,3 +239,4 @@ THREE.Mirror = function ( width, height, options ) {
 };
 
 THREE.Mirror.prototype = Object.create( THREE.Mesh.prototype );
+THREE.Mirror.prototype.constructor = THREE.Mirror;

+ 0 - 0
examples/js/MirrorRTT.js → examples/js/objects/MirrorRTT.js


+ 8 - 13
examples/js/SkyShader.js → examples/js/objects/Sky.js

@@ -16,26 +16,21 @@
 
 THREE.Sky = function () {
 
-	var skyShader = THREE.Sky.SkyShader;
+	var shader = THREE.Sky.SkyShader;
 
-	var skyUniforms = THREE.UniformsUtils.clone( skyShader.uniforms );
-
-	var skyMat = new THREE.ShaderMaterial( {
-		fragmentShader: skyShader.fragmentShader,
-		vertexShader: skyShader.vertexShader,
-		uniforms: skyUniforms,
+	var material = new THREE.ShaderMaterial( {
+		fragmentShader: shader.fragmentShader,
+		vertexShader: shader.vertexShader,
+		uniforms: THREE.UniformsUtils.clone( shader.uniforms ),
 		side: THREE.BackSide
 	} );
 
-	var skyGeo = new THREE.SphereBufferGeometry( 450000, 32, 15 );
-	var skyMesh = new THREE.Mesh( skyGeo, skyMat );
-
-	// Expose variables
-	this.mesh = skyMesh;
-	this.uniforms = skyUniforms;
+	THREE.Mesh.call( this, new THREE.SphereBufferGeometry( 1, 32, 15 ), material );
 
 };
 
+THREE.Sky.prototype = Object.create( THREE.Mesh.prototype );
+
 THREE.Sky.SkyShader = {
 
 	uniforms: {

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

@@ -0,0 +1,309 @@
+/**
+ * @author jbouny / https://github.com/jbouny
+ *
+ * Work based on :
+ * @author Slayvin / http://slayvin.net : Flat mirror for three.js
+ * @author Stemkoski / http://www.adelphi.edu/~stemkoski : An implementation of water shader based on the flat mirror
+ * @author Jonas Wagner / http://29a.ch/ && http://29a.ch/slides/2012/webglwater/ : Water shader explanations in WebGL
+ */
+
+THREE.Water = function ( width, height, options ) {
+
+	THREE.Mesh.call( this, new THREE.PlaneBufferGeometry( width, height ) );
+
+	var scope = this;
+
+	options = options || {};
+
+	var textureWidth = options.textureWidth !== undefined ? options.textureWidth : 512;
+	var 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 THREE.Vector3( 0.70707, 0.70707, 0.0 );
+	var sunColor = new THREE.Color( options.sunColor !== undefined ? options.sunColor : 0xffffff );
+	var waterColor = new THREE.Color( options.waterColor !== undefined ? options.waterColor : 0x7F7F7F );
+	var eye = options.eye !== undefined ? options.eye : new THREE.Vector3( 0, 0, 0 );
+	var distortionScale = options.distortionScale !== undefined ? options.distortionScale : 20.0;
+	var side = options.side !== undefined ? options.side : THREE.FrontSide;
+	var fog = options.fog !== undefined ? options.fog : false;
+
+	//
+
+	var mirrorPlane = new THREE.Plane();
+	var normal = new THREE.Vector3();
+	var mirrorWorldPosition = 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 mirrorCamera = new THREE.PerspectiveCamera();
+
+	var parameters = {
+		minFilter: THREE.LinearFilter,
+		magFilter: THREE.LinearFilter,
+		format: THREE.RGBFormat,
+		stencilBuffer: false
+	};
+
+	var renderTarget = new THREE.WebGLRenderTarget( textureWidth, textureHeight, parameters );
+
+	if ( ! THREE.Math.isPowerOfTwo( textureWidth ) || ! THREE.Math.isPowerOfTwo( textureHeight ) ) {
+
+		renderTarget.texture.generateMipmaps = false;
+
+	}
+
+	var mirrorShader = {
+
+		uniforms: THREE.UniformsUtils.merge( [
+			THREE.UniformsLib[ 'fog' ],
+			THREE.UniformsLib[ 'lights' ],
+			{
+				normalSampler: { value: null },
+				mirrorSampler: { value: null },
+				alpha: { value: 1.0 },
+				time: { value: 0.0 },
+				size: { value: 1.0 },
+				distortionScale: { value: 20.0 },
+				noiseScale: { value: 1.0 },
+				textureMatrix: { value: new THREE.Matrix4() },
+				sunColor: { value: new THREE.Color( 0x7F7F7F ) },
+				sunDirection: { value: new THREE.Vector3( 0.70707, 0.70707, 0 ) },
+				eye: { value: new THREE.Vector3() },
+				waterColor: { value: new THREE.Color( 0x555555 ) }
+			}
+		] ),
+
+		vertexShader: [
+			'uniform mat4 textureMatrix;',
+			'uniform float time;',
+
+			'varying vec4 mirrorCoord;',
+			'varying vec4 worldPosition;',
+
+			THREE.ShaderChunk[ 'fog_pars_vertex' ],
+			THREE.ShaderChunk[ 'shadowmap_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;',
+
+			THREE.ShaderChunk[ 'fog_vertex' ],
+			THREE.ShaderChunk[ '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;',
+			'}',
+
+			THREE.ShaderChunk[ 'common' ],
+			THREE.ShaderChunk[ 'packing' ],
+			THREE.ShaderChunk[ 'bsdfs' ],
+			THREE.ShaderChunk[ 'fog_pars_fragment' ],
+			THREE.ShaderChunk[ 'lights_pars' ],
+			THREE.ShaderChunk[ 'shadowmap_pars_fragment' ],
+			THREE.ShaderChunk[ 'shadowmask_pars_fragment' ],
+
+			'void main() {',
+			'	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.z + 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 );',
+
+			THREE.ShaderChunk[ 'tonemapping_fragment' ],
+			THREE.ShaderChunk[ 'fog_fragment' ],
+
+			'}'
+		].join( '\n' )
+
+	};
+
+	var material = new THREE.ShaderMaterial( {
+		fragmentShader: mirrorShader.fragmentShader,
+		vertexShader: mirrorShader.vertexShader,
+		uniforms: THREE.UniformsUtils.clone( mirrorShader.uniforms ),
+		transparent: true,
+		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;
+
+	scope.material = material;
+
+	scope.onBeforeRender = function ( renderer, scene, camera ) {
+
+		mirrorWorldPosition.setFromMatrixPosition( scope.matrixWorld );
+		cameraWorldPosition.setFromMatrixPosition( camera.matrixWorld );
+
+		rotationMatrix.extractRotation( scope.matrixWorld );
+
+		normal.set( 0, 0, 1 );
+		normal.applyMatrix4( rotationMatrix );
+
+		view.subVectors( mirrorWorldPosition, cameraWorldPosition );
+
+		// Avoid rendering when mirror is facing away
+
+		if ( view.dot( normal ) > 0 ) return;
+
+		view.reflect( normal ).negate();
+		view.add( mirrorWorldPosition );
+
+		rotationMatrix.extractRotation( camera.matrixWorld );
+
+		lookAtPosition.set( 0, 0, - 1 );
+		lookAtPosition.applyMatrix4( rotationMatrix );
+		lookAtPosition.add( cameraWorldPosition );
+
+		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.far = camera.far; // Used in WebGLBackground
+
+		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 );
+
+		// 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 );
+
+		var 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 ];
+
+		// 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;
+
+		eye.setFromMatrixPosition( camera.matrixWorld );
+
+		//
+
+		var currentRenderTarget = renderer.getRenderTarget();
+
+		var currentVrEnabled = renderer.vr.enabled;
+		var currentShadowAutoUpdate = renderer.shadowMap.autoUpdate;
+
+		scope.visible = false;
+
+		renderer.vr.enabled = false; // Avoid camera modification and recursion
+		renderer.shadowMap.autoUpdate = false; // Avoid re-computing shadows
+
+		renderer.render( scene, mirrorCamera, renderTarget, true );
+
+		scope.visible = true;
+
+		renderer.vr.enabled = currentVrEnabled;
+		renderer.shadowMap.autoUpdate = currentShadowAutoUpdate;
+
+		renderer.setRenderTarget( currentRenderTarget );
+
+	};
+
+};
+
+THREE.Water.prototype = Object.create( THREE.Mesh.prototype );
+THREE.Water.prototype.constructor = THREE.Water;

+ 3 - 3
examples/js/postprocessing/EffectComposer.js

@@ -15,7 +15,7 @@ THREE.EffectComposer = function ( renderer, renderTarget ) {
 			stencilBuffer: false
 		};
 
-		var size = renderer.getSize();
+		var size = renderer.getDrawingBufferSize();
 		renderTarget = new THREE.WebGLRenderTarget( size.width, size.height, parameters );
 		renderTarget.texture.name = 'EffectComposer.rt1';
 
@@ -62,7 +62,7 @@ Object.assign( THREE.EffectComposer.prototype, {
 
 		this.passes.push( pass );
 
-		var size = this.renderer.getSize();
+		var size = this.renderer.getDrawingBufferSize();
 		pass.setSize( size.width, size.height );
 
 	},
@@ -127,7 +127,7 @@ Object.assign( THREE.EffectComposer.prototype, {
 
 		if ( renderTarget === undefined ) {
 
-			var size = this.renderer.getSize();
+			var size = this.renderer.getDrawingBufferSize();
 
 			renderTarget = this.renderTarget1.clone();
 			renderTarget.setSize( size.width, size.height );

+ 16 - 7
examples/js/postprocessing/OutlinePass.js

@@ -15,6 +15,7 @@ THREE.OutlinePass = function ( resolution, scene, camera, selectedObjects ) {
 	this.edgeStrength = 3.0;
 	this.downSampleRatio = 2;
 	this.pulsePeriod = 0;
+	this.renderToScreen = false;
 
 	THREE.Pass.call( this );
 
@@ -321,6 +322,8 @@ THREE.OutlinePass.prototype = Object.assign( Object.create( THREE.Pass.prototype
 		this.overlayMaterial.uniforms[ "edgeStrength" ].value = this.edgeStrength;
 		this.overlayMaterial.uniforms[ "edgeGlow" ].value = this.edgeGlow;
 		this.overlayMaterial.uniforms[ "usePatternTexture" ].value = this.usePatternTexture;
+		this.overlayMaterial.uniforms[ "visibleEdgeColor" ].value = this.tempPulseColor1;
+		this.overlayMaterial.uniforms[ "hiddenEdgeColor" ].value = this.tempPulseColor2;
 
 
 		if ( maskActive ) renderer.context.enable( renderer.context.STENCIL_TEST );
@@ -367,7 +370,7 @@ THREE.OutlinePass.prototype = Object.assign( Object.create( THREE.Pass.prototype
 					float depth = unpackRGBAToDepth(texture2DProj( depthTexture, projTexCoord ));\
 					float viewZ = -perspectiveDepthToViewZ( depth, cameraNearFar.x, cameraNearFar.y );\
 					float depthTest = (-vPosition.z > viewZ) ? 1.0 : 0.0;\
-					gl_FragColor = vec4(0.0, depthTest, 1.0, 1.0);\
+					gl_FragColor = vec4(0.0, depthTest, 1.0, 0.0);\
 				}"
 		} );
 
@@ -411,7 +414,7 @@ THREE.OutlinePass.prototype = Object.assign( Object.create( THREE.Pass.prototype
 					float a1 = min(c1.g, c2.g);\
 					float a2 = min(c3.g, c4.g);\
 					float visibilityFactor = min(a1, a2);\
-					vec3 edgeColor = 1.0 - visibilityFactor > 0.001 ? visibleEdgeColor : hiddenEdgeColor;\
+					vec3 edgeColor = 1.0 - visibilityFactor > 0.001 ? vec3(1,0,0) : vec3(0,1,0);\
 					gl_FragColor = vec4(edgeColor, 1.0) * vec4(d);\
 				}"
 		} );
@@ -482,7 +485,9 @@ THREE.OutlinePass.prototype = Object.assign( Object.create( THREE.Pass.prototype
 				"patternTexture": { value: null },
 				"edgeStrength": { value: 1.0 },
 				"edgeGlow": { value: 1.0 },
-				"usePatternTexture": { value: 0.0 }
+				"usePatternTexture": { value: 0.0 },
+				"visibleEdgeColor": { value: new THREE.Vector3( 1.0, 1.0, 1.0 ) },
+				"hiddenEdgeColor": { value: new THREE.Vector3( 1.0, 1.0, 1.0 ) },
 			},
 
 			vertexShader:
@@ -501,6 +506,8 @@ THREE.OutlinePass.prototype = Object.assign( Object.create( THREE.Pass.prototype
 				uniform float edgeStrength;\
 				uniform float edgeGlow;\
 				uniform bool usePatternTexture;\
+				uniform vec3 visibleEdgeColor;\
+				uniform vec3 hiddenEdgeColor;\
 				\
 				void main() {\
 					vec4 edgeValue1 = texture2D(edgeTexture1, vUv);\
@@ -508,16 +515,18 @@ THREE.OutlinePass.prototype = Object.assign( Object.create( THREE.Pass.prototype
 					vec4 maskColor = texture2D(maskTexture, vUv);\
 					vec4 patternColor = texture2D(patternTexture, 6.0 * vUv);\
 					float visibilityFactor = 1.0 - maskColor.g > 0.0 ? 1.0 : 0.5;\
-					vec4 edgeValue = edgeValue1 + edgeValue2 * edgeGlow;\
-					vec4 finalColor = edgeStrength * maskColor.r * edgeValue;\
+					vec4 edgeValue = edgeStrength * (edgeValue1 + edgeValue2 * edgeGlow);\
+					edgeValue.a = max(edgeValue.r, edgeValue.g);\
+					vec3 edgeColor = edgeValue.r * visibleEdgeColor + edgeValue.g * hiddenEdgeColor;\
+					vec4 finalColor = vec4(edgeColor, edgeValue.a*1.0);\
 					if(usePatternTexture)\
 						finalColor += + visibilityFactor * (1.0 - maskColor.r) * (1.0 - patternColor.r);\
 					gl_FragColor = finalColor;\
 				}",
-			blending: THREE.AdditiveBlending,
+			blending: THREE.NormalBlending,
 			depthTest: false,
 			depthWrite: false,
-			transparent: true
+			transparent: true,
 		} );
 
 	}

+ 1 - 1
examples/webgl_mirror.html

@@ -35,7 +35,7 @@
 		</div>
 
 		<script src="../build/three.js"></script>
-		<script src="js/Mirror.js"></script>
+		<script src="js/objects/Mirror.js"></script>
 		<script src="js/controls/OrbitControls.js"></script>
 
 		<script>

+ 2 - 2
examples/webgl_mirror_nodes.html

@@ -36,8 +36,8 @@
 
 		<script src="../build/three.js"></script>
 		<script src="js/libs/dat.gui.min.js"></script>
-		<script src="js/Mirror.js"></script>
-		<script src="js/MirrorRTT.js"></script>
+		<script src="js/objects/Mirror.js"></script>
+		<script src="js/objects/MirrorRTT.js"></script>
 		<script src="js/controls/OrbitControls.js"></script>
 
 		<!-- NodeLibrary -->

+ 2 - 2
examples/webgl_postprocessing_nodes.html

@@ -465,12 +465,12 @@
 						} );
 
 						break;
-						
+
 					case 'blur':
 
 						// PASS
 
-						var size = renderer.getSize();
+						var size = renderer.getDrawingBufferSize();
 
 						var blurScreen = new THREE.BlurNode( new THREE.ScreenNode() );
 						blurScreen.size = new THREE.Vector2( size.width, size.height );

+ 101 - 72
examples/webgl_shaders_ocean.html

@@ -33,10 +33,11 @@
 		<script src="../build/three.js"></script>
 
 		<script src="js/controls/OrbitControls.js"></script>
-		<script src="js/WaterShader.js"></script>
+		<script src="js/objects/Water.js"></script>
 
 		<script src="js/Detector.js"></script>
 		<script src="js/libs/stats.min.js"></script>
+		<script src="js/libs/dat.gui.min.js"></script>
 
 		<script>
 
@@ -48,17 +49,14 @@
 			}
 
 			var container, stats;
-			var camera, scene, renderer;
-			var controls, water, sphere;
+			var camera, scene, renderer, light;
+			var controls, water, sphere, cubeMap;
 
 			var parameters = {
-				width: 2000,
-				height: 2000,
-				widthSegments: 250,
-				heightSegments: 250,
-				depth: 1500,
-				param: 4,
-				filterparam: 1
+				oceanSide: 2000,
+				size: 1.0,
+				distortionScale: 3.7,
+				alpha: 1.0
 			};
 
 			var waterNormals;
@@ -80,61 +78,103 @@
 				//
 
 				scene = new THREE.Scene();
-				scene.fog = new THREE.FogExp2( 0xaabbbb, 0.0001 );
+				scene.fog = new THREE.FogExp2( 0xaabbbb, 0.001 );
 
 				//
 
-				camera = new THREE.PerspectiveCamera( 55, window.innerWidth / window.innerHeight, 0.5, 3000000 );
-				camera.position.set( 2000, 750, 2000 );
+				camera = new THREE.PerspectiveCamera( 55, window.innerWidth / window.innerHeight, 1, 20000 );
+				camera.position.set( 30, 30, 100 );
 
 				//
 
 				controls = new THREE.OrbitControls( camera, renderer.domElement );
-				controls.enablePan = false;
-				controls.minDistance = 1000.0;
-				controls.maxDistance = 5000.0;
 				controls.maxPolarAngle = Math.PI * 0.495;
-				controls.target.set( 0, 500, 0 );
-				controls.update();
+				controls.target.set( 0, 10, 0 );
+				controls.enablePan = false;
+				controls.minDistance = 40.0;
+				controls.maxDistance = 200.0;
+				camera.lookAt( controls.target );
+
+				setLighting();
+
+				//
 
-				scene.add( new THREE.AmbientLight( 0x444444 ) );
+				setWater();
 
 				//
 
-				var light = new THREE.DirectionalLight( 0xffffbb, 1 );
-				light.position.set( - 1, 1, - 1 );
-				scene.add( light );
+				setSkybox();
 
 				//
 
-				waterNormals = new THREE.TextureLoader().load( 'textures/waternormals.jpg' );
-				waterNormals.wrapS = waterNormals.wrapT = THREE.RepeatWrapping;
-
-				water = new THREE.Water( renderer, camera, scene, {
-					textureWidth: 512,
-					textureHeight: 512,
-					waterNormals: waterNormals,
-					alpha: 	1.0,
-					sunDirection: light.position.clone().normalize(),
-					sunColor: 0xffffff,
-					waterColor: 0x001e0f,
-					distortionScale: 50.0,
-					fog: scene.fog != undefined
+				var geometry = new THREE.IcosahedronGeometry( 20, 2 );
+
+				for ( var i = 0, j = geometry.faces.length; i < j; i ++ ) {
+
+					geometry.faces[ i ].color.setHex( Math.random() * 0xffffff );
+
+				}
+
+				var material = new THREE.MeshPhongMaterial( {
+					vertexColors: THREE.FaceColors,
+					shininess: 10,
+					envMap: cubeMap,
+					side: THREE.DoubleSide
 				} );
 
+				sphere = new THREE.Mesh( geometry, material );
+				sphere.castShadow = true;
+				scene.add( sphere );
+
+				//
+
+				stats = new Stats();
+				container.appendChild( stats.dom );
+
+				//
+
+				gui = new dat.GUI();
+
+				gui.add( parameters, 'distortionScale', 0, 8, 0.1 );
+				gui.add( parameters, 'size', 0.1, 10, 0.1 );
+				gui.add( parameters, 'alpha', 0.9, 1, .001 );
+
+				//
+
+				window.addEventListener( 'resize', onWindowResize, false );
 
-				var mirrorMesh = new THREE.Mesh(
-					new THREE.PlaneBufferGeometry( parameters.width * 500, parameters.height * 500 ),
-					water.material
+			}
+
+			function setWater() {
+
+				water = new THREE.Water(
+					parameters.oceanSide * 5,
+					parameters.oceanSide * 5,
+					{
+						textureWidth: 512,
+						textureHeight: 512,
+						waterNormals: new THREE.TextureLoader().load( 'textures/waternormals.jpg', function ( texture ) {
+							texture.wrapS = texture.wrapT = THREE.RepeatWrapping;
+						}),
+						alpha: 	parameters.alpha,
+						sunDirection: light.position.clone().normalize(),
+						sunColor: 0xffffff,
+						waterColor: 0x001e0f,
+						distortionScale: parameters.distortionScale,
+						fog: scene.fog != undefined
+					}
 				);
 
-				mirrorMesh.add( water );
-				mirrorMesh.rotation.x = - Math.PI * 0.5;
-				scene.add( mirrorMesh );
+				water.rotation.x = - Math.PI / 2;
+				water.receiveShadow = true;
 
-				// skybox
+				scene.add( water );
+
+			}
 
-				var cubeMap = new THREE.CubeTexture( [] );
+			function setSkybox() {
+
+				cubeMap = new THREE.CubeTexture( [] );
 				cubeMap.format = THREE.RGBFormat;
 
 				var loader = new THREE.ImageLoader();
@@ -172,44 +212,32 @@
 					fragmentShader: cubeShader.fragmentShader,
 					vertexShader: cubeShader.vertexShader,
 					uniforms: cubeShader.uniforms,
-					depthWrite: false,
 					side: THREE.BackSide
 				} );
 
 				var skyBox = new THREE.Mesh(
-					new THREE.BoxGeometry( 1000000, 1000000, 1000000 ),
+					new THREE.BoxGeometry( parameters.oceanSide * 5 + 100, parameters.oceanSide * 5 + 100, parameters.oceanSide * 5 + 100 ),
 					skyBoxMaterial
 				);
 
 				scene.add( skyBox );
 
-				//
-
-				var geometry = new THREE.IcosahedronGeometry( 400, 4 );
-
-				for ( var i = 0, j = geometry.faces.length; i < j; i ++ ) {
-
-					geometry.faces[ i ].color.setHex( Math.random() * 0xffffff );
-
-				}
-
-				var material = new THREE.MeshPhongMaterial( {
-					vertexColors: THREE.FaceColors,
-					shininess: 100,
-					envMap: cubeMap
-				} );
-
-				sphere = new THREE.Mesh( geometry, material );
-				scene.add( sphere );
+			}
 
-				//
+			function setLighting() {
 
-				stats = new Stats();
-				container.appendChild( stats.dom );
+				renderer.shadowMap.enabled = true;
 
-				//
+				light = new THREE.DirectionalLight( 0xffffbb, 1 );
+				light.position.set( - 30, 30, - 30 );
+				light.castShadow = true;
+				light.shadow.camera.top = 45;
+				light.shadow.camera.right = 40;
+				light.shadow.camera.left = light.shadow.camera.bottom = -40;
+				light.shadow.camera.near = 1;
+				light.shadow.camera.far = 200;
 
-				window.addEventListener( 'resize', onWindowResize, false );
+				scene.add( light, new THREE.AmbientLight( 0x888888 ) );
 
 			}
 
@@ -222,8 +250,6 @@
 
 			}
 
-			//
-
 			function animate() {
 
 				requestAnimationFrame( animate );
@@ -236,12 +262,15 @@
 
 				var time = performance.now() * 0.001;
 
-				sphere.position.y = Math.sin( time ) * 500 + 250;
+				sphere.position.y = Math.sin( time ) * 20 + 5;
 				sphere.rotation.x = time * 0.5;
 				sphere.rotation.z = time * 0.51;
 
 				water.material.uniforms.time.value += 1.0 / 60.0;
-				water.render();
+				water.material.uniforms.size.value = parameters.size;
+				water.material.uniforms.distortionScale.value = parameters.distortionScale;
+				water.material.uniforms.alpha.value = parameters.alpha;
+
 				renderer.render( scene, camera );
 
 			}

+ 6 - 5
examples/webgl_shaders_sky.html

@@ -44,7 +44,7 @@
 		<script src="../build/three.js"></script>
 
 		<script src="js/controls/OrbitControls.js"></script>
-		<script src="js/SkyShader.js"></script>
+		<script src="js/objects/Sky.js"></script>
 
 		<script src="js/Detector.js"></script>
 		<script src="js/libs/dat.gui.min.js"></script>
@@ -65,9 +65,10 @@
 
 			function initSky() {
 
-				// Add Sky Mesh
+				// Add Sky
 				sky = new THREE.Sky();
-				scene.add( sky.mesh );
+				sky.scale.setScalar( 450000 );
+				scene.add( sky );
 
 				// Add Sun Helper
 				sunSphere = new THREE.Mesh(
@@ -95,7 +96,7 @@
 
 				function guiChanged() {
 
-					var uniforms = sky.uniforms;
+					var uniforms = sky.material.uniforms;
 					uniforms.turbidity.value = effectController.turbidity;
 					uniforms.rayleigh.value = effectController.rayleigh;
 					uniforms.luminance.value = effectController.luminance;
@@ -111,7 +112,7 @@
 
 					sunSphere.visible = effectController.sun;
 
-					sky.uniforms.sunPosition.value.copy( sunSphere.position );
+					uniforms.sunPosition.value.copy( sunSphere.position );
 
 					renderer.render( scene, camera );
 

+ 1 - 1
examples/webvr_sandbox.html

@@ -19,7 +19,7 @@
 
 		<script src="js/vr/WebVR.js"></script>
 
-		<script src="js/Mirror.js"></script>
+		<script src="js/objects/Mirror.js"></script>
 
 		<script>
 

+ 0 - 2
src/core/BufferGeometry.js

@@ -39,8 +39,6 @@ function BufferGeometry() {
 
 }
 
-BufferGeometry.MaxIndex = 65535;
-
 Object.assign( BufferGeometry.prototype, EventDispatcher.prototype, {
 
 	isBufferGeometry: true,

+ 2 - 2
src/core/Object3D.js

@@ -591,8 +591,8 @@ Object.assign( Object3D.prototype, EventDispatcher.prototype, {
 
 	toJSON: function ( meta ) {
 
-		// meta is '' when called from JSON.stringify
-		var isRootObject = ( meta === undefined || meta === '' );
+		// meta is a string when called from JSON.stringify
+		var isRootObject = ( meta === undefined || typeof meta === 'string' );
 
 		var output = {};
 

+ 7 - 0
src/loaders/MaterialLoader.js

@@ -82,6 +82,13 @@ Object.assign( MaterialLoader.prototype, {
 		if ( json.wireframeLinecap !== undefined ) material.wireframeLinecap = json.wireframeLinecap;
 		if ( json.wireframeLinejoin !== undefined ) material.wireframeLinejoin = json.wireframeLinejoin;
 
+		if ( json.rotation !== undefined ) material.rotation = json.rotation;
+
+		if ( json.linewidth !== 1 ) material.linewidth = json.linewidth;
+		if ( json.dashSize !== undefined ) material.dashSize = json.dashSize;
+		if ( json.gapSize !== undefined ) material.gapSize = json.gapSize;
+		if ( json.scale !== undefined ) material.scale = json.scale;
+
 		if ( json.skinning !== undefined ) material.skinning = json.skinning;
 		if ( json.morphTargets !== undefined ) material.morphTargets = json.morphTargets;
 		if ( json.dithering !== undefined ) material.dithering = json.dithering;

+ 11 - 1
src/materials/Material.js

@@ -131,7 +131,7 @@ Object.assign( Material.prototype, EventDispatcher.prototype, {
 
 	toJSON: function ( meta ) {
 
-		var isRoot = meta === undefined;
+		var isRoot = ( meta === undefined || typeof meta === 'string' );
 
 		if ( isRoot ) {
 
@@ -162,6 +162,8 @@ Object.assign( Material.prototype, EventDispatcher.prototype, {
 		if ( this.metalness !== undefined ) data.metalness = this.metalness;
 
 		if ( this.emissive && this.emissive.isColor ) data.emissive = this.emissive.getHex();
+		if ( this.emissiveIntensity !== 1) data.emissiveIntensity = this.emissiveIntensity;
+
 		if ( this.specular && this.specular.isColor ) data.specular = this.specular.getHex();
 		if ( this.shininess !== undefined ) data.shininess = this.shininess;
 		if ( this.clearCoat !== undefined ) data.clearCoat = this.clearCoat;
@@ -223,6 +225,14 @@ Object.assign( Material.prototype, EventDispatcher.prototype, {
 		data.depthTest = this.depthTest;
 		data.depthWrite = this.depthWrite;
 
+		// rotation (SpriteMaterial)
+		if ( this.rotation !== 0 ) data.rotation = this.rotation;
+
+		if ( this.linewidth !== 1 ) data.linewidth = this.linewidth;
+		if ( this.dashSize !== undefined ) data.dashSize = this.dashSize;
+		if ( this.gapSize !== undefined ) data.gapSize = this.gapSize;
+		if ( this.scale !== undefined ) data.scale = this.scale;
+
 		if ( this.dithering === true ) data.dithering = true;
 
 		if ( this.alphaTest > 0 ) data.alphaTest = this.alphaTest;

+ 1 - 7
src/renderers/WebGLRenderer.js

@@ -24,7 +24,6 @@ import { WebGLProperties } from './webgl/WebGLProperties.js';
 import { WebGLState } from './webgl/WebGLState.js';
 import { WebGLCapabilities } from './webgl/WebGLCapabilities.js';
 import { WebVRManager } from './webvr/WebVRManager.js';
-import { BufferGeometry } from '../core/BufferGeometry.js';
 import { WebGLExtensions } from './webgl/WebGLExtensions.js';
 import { Vector3 } from '../math/Vector3.js';
 import { WebGLClipping } from './webgl/WebGLClipping.js';
@@ -258,14 +257,9 @@ function WebGLRenderer( parameters ) {
 		extensions.get( 'OES_texture_half_float' );
 		extensions.get( 'OES_texture_half_float_linear' );
 		extensions.get( 'OES_standard_derivatives' );
+		extensions.get( 'OES_element_index_uint' );
 		extensions.get( 'ANGLE_instanced_arrays' );
 
-		if ( extensions.get( 'OES_element_index_uint' ) ) {
-
-			BufferGeometry.MaxIndex = 4294967296;
-
-		}
-
 		utils = new WebGLUtils( _gl, extensions );
 
 		capabilities = new WebGLCapabilities( _gl, extensions, parameters );

+ 1 - 1
src/renderers/shaders/ShaderChunk/bsdfs.glsl

@@ -191,7 +191,7 @@ vec3 LTC_Evaluate( const in vec3 N, const in vec3 V, const in vec3 P, const in m
 	T2 = - cross( N, T1 ); // negated from paper; possibly due to a different assumed handedness of world coordinate system
 
 	// compute transform
-	mat3 mat = mInv * transpose( mat3( T1, T2, N ) );
+	mat3 mat = mInv * transposeMat3( mat3( T1, T2, N ) );
 
 	// transform rect
 	vec3 coords[ 4 ];

+ 5 - 4
src/renderers/shaders/ShaderChunk/common.glsl

@@ -73,12 +73,13 @@ vec3 linePlaneIntersect( in vec3 pointOnLine, in vec3 lineDirection, in vec3 poi
 
 }
 
-mat3 transpose( const in mat3 v ) {
+mat3 transposeMat3( const in mat3 m ) {
 
 	mat3 tmp;
-	tmp[0] = vec3(v[0].x, v[1].x, v[2].x);
-	tmp[1] = vec3(v[0].y, v[1].y, v[2].y);
-	tmp[2] = vec3(v[0].z, v[1].z, v[2].z);
+
+	tmp[ 0 ] = vec3( m[ 0 ].x, m[ 1 ].x, m[ 2 ].x );
+	tmp[ 1 ] = vec3( m[ 0 ].y, m[ 1 ].y, m[ 2 ].y );
+	tmp[ 2 ] = vec3( m[ 0 ].z, m[ 1 ].z, m[ 2 ].z );
 
 	return tmp;
 

+ 9 - 3
src/textures/Texture.js

@@ -126,7 +126,9 @@ Object.assign( Texture.prototype, EventDispatcher.prototype, {
 
 	toJSON: function ( meta ) {
 
-		if ( meta.textures[ this.uuid ] !== undefined ) {
+		var isRootObject = ( meta === undefined || typeof meta === 'string' );
+
+		if ( ! isRootObject && meta.textures[ this.uuid ] !== undefined ) {
 
 			return meta.textures[ this.uuid ];
 
@@ -210,7 +212,7 @@ Object.assign( Texture.prototype, EventDispatcher.prototype, {
 
 			}
 
-			if ( meta.images[ image.uuid ] === undefined ) {
+			if ( ! isRootObject && meta.images[ image.uuid ] === undefined ) {
 
 				meta.images[ image.uuid ] = {
 					uuid: image.uuid,
@@ -223,7 +225,11 @@ Object.assign( Texture.prototype, EventDispatcher.prototype, {
 
 		}
 
-		meta.textures[ this.uuid ] = output;
+		if ( ! isRootObject ) {
+
+			meta.textures[ this.uuid ] = output;
+
+		}
 
 		return output;