Procházet zdrojové kódy

Merge branch 'dev' into editor/Tetrahedron

Mr.doob před 6 roky
rodič
revize
27b90b8f93

+ 21 - 2
docs/scenes/js/material.js

@@ -129,6 +129,20 @@ var diffuseMaps = ( function () {
 
 } )();
 
+var roughnessMaps = ( function () {
+
+	var bricks = textureLoader.load( '../../examples/textures/brick_roughness.jpg' );
+	bricks.wrapT = THREE.RepeatWrapping;
+	bricks.wrapS = THREE.RepeatWrapping;
+	bricks.repeat.set( 9, 1 );
+
+	return {
+		none: null,
+		bricks: bricks
+	};
+
+} )();
+
 var matcaps = ( function () {
 
 	return {
@@ -154,6 +168,7 @@ var alphaMaps = ( function () {
 
 var envMapKeys = getObjectsKeys( envMaps );
 var diffuseMapKeys = getObjectsKeys( diffuseMaps );
+var roughnessMapKeys = getObjectsKeys( roughnessMaps );
 var matcapKeys = getObjectsKeys( matcaps );
 var alphaMapKeys = getObjectsKeys( alphaMaps );
 
@@ -444,6 +459,7 @@ function guiMeshStandardMaterial( gui, mesh, material, geometry ) {
 		emissive: material.emissive.getHex(),
 		envMaps: envMapKeys[ 0 ],
 		map: diffuseMapKeys[ 0 ],
+		roughnessMap: roughnessMapKeys[ 0 ],
 		alphaMap: alphaMapKeys[ 0 ]
 	};
 
@@ -461,9 +477,10 @@ function guiMeshStandardMaterial( gui, mesh, material, geometry ) {
 	folder.add( material, 'fog' );
 	folder.add( data, 'envMaps', envMapKeys ).onChange( updateTexture( material, 'envMap', envMaps ) );
 	folder.add( data, 'map', diffuseMapKeys ).onChange( updateTexture( material, 'map', diffuseMaps ) );
+	folder.add( data, 'roughnessMap', roughnessMapKeys ).onChange( updateTexture( material, 'roughnessMap', roughnessMaps ) );
 	folder.add( data, 'alphaMap', alphaMapKeys ).onChange( updateTexture( material, 'alphaMap', alphaMaps ) );
 
-	// TODO roughnessMap and metalnessMap
+	// TODO metalnessMap
 
 }
 
@@ -474,6 +491,7 @@ function guiMeshPhysicalMaterial( gui, mesh, material, geometry ) {
 		emissive: material.emissive.getHex(),
 		envMaps: envMapKeys[ 0 ],
 		map: diffuseMapKeys[ 0 ],
+		roughnessMap: roughnessMapKeys[ 0 ],
 		alphaMap: alphaMapKeys[ 0 ]
 	};
 
@@ -494,9 +512,10 @@ function guiMeshPhysicalMaterial( gui, mesh, material, geometry ) {
 	folder.add( material, 'fog' );
 	folder.add( data, 'envMaps', envMapKeys ).onChange( updateTexture( material, 'envMap', envMaps ) );
 	folder.add( data, 'map', diffuseMapKeys ).onChange( updateTexture( material, 'map', diffuseMaps ) );
+	folder.add( data, 'roughnessMap', roughnessMapKeys ).onChange( updateTexture( material, 'roughnessMap', roughnessMaps ) );
 	folder.add( data, 'alphaMap', alphaMapKeys ).onChange( updateTexture( material, 'alphaMap', alphaMaps ) );
 
-	// TODO roughnessMap and metalnessMap
+	// TODO metalnessMap
 
 }
 

+ 1 - 0
editor/index.html

@@ -126,6 +126,7 @@
 		<script src="js/Sidebar.Geometry.CircleGeometry.js"></script>
 		<script src="js/Sidebar.Geometry.CylinderGeometry.js"></script>
 		<script src="js/Sidebar.Geometry.IcosahedronGeometry.js"></script>
+		<script src="js/Sidebar.Geometry.OctahedronGeometry.js"></script>
 		<script src="js/Sidebar.Geometry.PlaneGeometry.js"></script>
 		<script src="js/Sidebar.Geometry.SphereGeometry.js"></script>
 		<script src="js/Sidebar.Geometry.TetrahedronGeometry.js"></script>

+ 16 - 0
editor/js/Menubar.Add.js

@@ -134,6 +134,22 @@ Menubar.Add = function ( editor ) {
 	} );
 	options.add( option );
 
+	// Octahedron
+
+	var option = new UI.Row();
+	option.setClass( 'option' );
+	option.setTextContent( strings.getKey( 'menubar/add/octahedron' ) );
+	option.onClick( function () {
+
+		var geometry = new THREE.OctahedronBufferGeometry( 1, 0 );
+		var mesh = new THREE.Mesh( geometry, new THREE.MeshStandardMaterial() );
+		mesh.name = 'Octahedron';
+
+		editor.execute( new AddObjectCommand( mesh ) );
+
+	} );
+	options.add( option );
+
 	// Tetrahedron
 
 	var option = new UI.Row();

+ 54 - 0
editor/js/Sidebar.Geometry.OctahedronGeometry.js

@@ -0,0 +1,54 @@
+/**
+ * @author Temdog007 / http://github.com/Temdog007
+ */
+
+Sidebar.Geometry.OctahedronGeometry = function ( editor, object ) {
+
+	var strings = editor.strings;
+
+	var signals = editor.signals;
+
+	var container = new UI.Row();
+
+	var geometry = object.geometry;
+	var parameters = geometry.parameters;
+
+	// radius
+
+	var radiusRow = new UI.Row();
+	var radius = new UI.Number( parameters.radius ).onChange( update );
+
+	radiusRow.add( new UI.Text( strings.getKey( 'sidebar/geometry/octahedron_geometry/radius' ) ).setWidth( '90px' ) );
+	radiusRow.add( radius );
+
+	container.add( radiusRow );
+
+	// detail
+
+	var detailRow = new UI.Row();
+	var detail = new UI.Integer( parameters.detail ).setRange( 0, Infinity ).onChange( update );
+
+	detailRow.add( new UI.Text( strings.getKey( 'sidebar/geometry/octahedron_geometry/detail' ) ).setWidth( '90px' ) );
+	detailRow.add( detail );
+
+	container.add( detailRow );
+
+
+	//
+
+	function update() {
+
+		editor.execute( new SetGeometryCommand( object, new THREE[ geometry.type ](
+			radius.getValue(),
+			detail.getValue()
+		) ) );
+
+		signals.objectChanged.dispatch( object );
+
+	}
+
+	return container;
+
+};
+
+Sidebar.Geometry.OctahedronBufferGeometry = Sidebar.Geometry.OctahedronGeometry;

+ 5 - 1
editor/js/Strings.js

@@ -40,6 +40,7 @@ var Strings = function ( config ) {
 			'menubar/add/cylinder': 'Cylinder',
 			'menubar/add/sphere': 'Sphere',
 			'menubar/add/icosahedron': 'Icosahedron',
+			'menubar/add/octahedron': 'Octahedron',
 			'menubar/add/tetrahedron': 'Tetrahedron',
 			'menubar/add/torus': 'Torus',
 			'menubar/add/tube': 'Tube',
@@ -133,7 +134,10 @@ var Strings = function ( config ) {
 			'sidebar/geometry/icosahedron_geometry/radius': 'Radius',
 			'sidebar/geometry/icosahedron_geometry/detail': 'Detail',
 
-			'sidebar/geometry/tetrahedron_geometry/radius': 'Radius',
+			'sidebar/geometry/octahedron_geometry/radius': 'Radius',
+			'sidebar/geometry/octahedron_geometry/detail': 'Detail',
+
+      'sidebar/geometry/tetrahedron_geometry/radius': 'Radius',
 			'sidebar/geometry/tetrahedron_geometry/detail': 'Detail',
 
 			'sidebar/geometry/lathe_geometry/segments': 'Segments',

+ 21 - 5
examples/js/loaders/VRMLLoader.js

@@ -512,7 +512,9 @@ THREE.VRMLLoader.prototype = {
 
 					}
 
-					node[ fieldName ] = property;
+					// VRMLLoader does not support text so it can't process the "string" property yet
+
+					if ( fieldName !== 'string' ) node[ fieldName ] = property;
 
 				}
 
@@ -825,6 +827,16 @@ THREE.VRMLLoader.prototype = {
 
 						parent.geometry = new THREE.SphereBufferGeometry( data.radius );
 
+					} else if ( data.nodeType === 'IndexedLineSet' ) {
+
+						console.warn( 'THREE.VRMLLoader: IndexedLineSet not supported yet.' );
+						parent.parent.remove( parent ); // since the loader is not able to parse the geometry, remove the respective 3D object
+
+					} else if ( data.nodeType === 'Text' ) {
+
+						console.warn( 'THREE.VRMLLoader: Text not supported yet.' );
+						parent.parent.remove( parent );
+
 					} else if ( data.nodeType === 'IndexedFaceSet' ) {
 
 						var geometry = new THREE.BufferGeometry();
@@ -1244,13 +1256,13 @@ THREE.VRMLLoader.prototype = {
 
 		// some lines do not have breaks
 
-		for ( var i = lines.length - 1; i > - 1; i -- ) {
-
-			var line = lines[ i ];
+		for ( var i = lines.length - 1; i > 0; i -- ) {
 
 			// The # symbol indicates that all subsequent text, until the end of the line is a comment,
 			// and should be ignored. (see http://gun.teipir.gr/VRML-amgem/spec/part1/grammar.html)
-			line = line.replace( /(#.*)/, '' );
+			lines[ i ] = lines[ i ].replace( /(#.*)/, '' );
+
+			var line = lines[ i ];
 
 			// split lines with {..{ or {..[ - some have both
 			if ( /{.*[{\[]/.test( line ) ) {
@@ -1270,6 +1282,8 @@ THREE.VRMLLoader.prototype = {
 
 			}
 
+			line = lines[ i ];
+
 			if ( /}.*}/.test( line ) ) {
 
 				// split lines with }..}
@@ -1280,6 +1294,8 @@ THREE.VRMLLoader.prototype = {
 
 			}
 
+			line = lines[ i ];
+
 			if ( /^\b[^\s]+\b$/.test( line.trim() ) ) {
 
 				// prevent lines with single words like "coord" or "geometry", see #12209

+ 12 - 3
examples/js/nodes/accessors/NormalNode.js

@@ -43,7 +43,8 @@ NormalNode.prototype.generate = function ( builder, output ) {
 
 		case NormalNode.LOCAL:
 
-			builder.requires.normal = true;
+			// to use vObjectNormal as vertex normal
+			//builder.requires.normal = true;
 
 			result = 'normal';
 
@@ -51,9 +52,17 @@ NormalNode.prototype.generate = function ( builder, output ) {
 
 		case NormalNode.WORLD:
 
-			builder.requires.worldNormal = true;
+			if ( builder.isShader( 'vertex' ) ) {
 
-			result = builder.isShader( 'vertex' ) ? '( modelMatrix * vec4( objectNormal, 0.0 ) ).xyz' : 'vWNormal';
+				return '( modelMatrix * vec4( objectNormal, 0.0 ) ).xyz';
+
+			} else {
+
+				builder.requires.worldNormal = true;
+
+				result = 'vWNormal';
+
+			}
 
 			break;
 

+ 20 - 4
examples/js/nodes/accessors/PositionNode.js

@@ -59,17 +59,33 @@ PositionNode.prototype.generate = function ( builder, output ) {
 
 		case PositionNode.LOCAL:
 
-			builder.requires.position = true;
+			if ( builder.isShader( 'vertex' ) ) {
 
-			result = builder.isShader( 'vertex' ) ? 'transformed' : 'vPosition';
+				result = 'transformed';
+
+			} else {
+
+				builder.requires.position = true;
+
+				result = 'vPosition';
+
+			}
 
 			break;
 
 		case PositionNode.WORLD:
 
-			builder.requires.worldPosition = true;
+			if ( builder.isShader( 'vertex' ) ) {
+
+				return '( modelMatrix * vec4( transformed, 1.0 ) ).xyz';
+
+			} else {
+
+				builder.requires.worldPosition = true;
+
+				result = 'vWPosition';
 
-			result = 'vWPosition';
+			}
 
 			break;
 

+ 7 - 4
examples/js/nodes/accessors/ResolutionNode.js

@@ -8,6 +8,8 @@ function ResolutionNode() {
 
 	Vector2Node.call( this );
 
+	this.size = new THREE.Vector2();
+
 }
 
 ResolutionNode.prototype = Object.create( Vector2Node.prototype );
@@ -18,11 +20,12 @@ ResolutionNode.prototype.updateFrame = function ( frame ) {
 
 	if ( frame.renderer ) {
 
-		var size = frame.renderer.getSize(),
-			pixelRatio = frame.renderer.getPixelRatio();
+		frame.renderer.getSize( this.size );
+
+		var pixelRatio = frame.renderer.getPixelRatio();
 
-		this.x = size.width * pixelRatio;
-		this.y = size.height * pixelRatio;
+		this.x = this.size.width * pixelRatio;
+		this.y = this.size.height * pixelRatio;
 
 	} else {
 

binární
examples/models/sea3d/morph.sea


binární
examples/models/sea3d/morph.tjs.sea


+ 5 - 3
examples/webgl_materials_nodes.html

@@ -455,7 +455,7 @@
 
 							// apply material
 
-							mtl.side = THREE.DoubleSide;
+							mtl.side = defaultSide;
 							mtl.needsUpdate = true;
 
 							mesh.material = mtl;
@@ -766,6 +766,8 @@
 
 						mtl = new THREE.PhongNodeMaterial();
 
+						defaultSide = THREE.FrontSide;
+
 						var intensity = 1.3;
 						var power = new THREE.FloatNode( 3 );
 						var color = new THREE.ColorNode( 0xFFFFFF );
@@ -1538,6 +1540,8 @@
 
 						mtl = new THREE.PhongNodeMaterial();
 
+						defaultSide = THREE.FrontSide;
+
 						var time = new THREE.TimerNode();
 						var uv = new THREE.UVNode();
 
@@ -1577,8 +1581,6 @@
 						mtl.environment = new THREE.ColorNode( 0xFFFFFF );
 						mtl.alpha = clouds;
 
-						defaultSide = THREE.FrontSide;
-
 						// GUI
 
 						addGui( 'color', mtl.environment.value.getHex(), function ( val ) {

+ 162 - 0
src/lights/LightProbe.js

@@ -0,0 +1,162 @@
+import { _Math } from '../math/Math.js';
+import { Vector3 } from '../math/Vector3.js';
+import { Color } from '../math/Color.js';
+import { SphericalHarmonics3 } from '../math/SphericalHarmonics3.js';
+import { Light } from './Light.js';
+
+/**
+ * @author WestLangley / http://github.com/WestLangley
+ */
+
+// A LightProbe is a source of indirect-diffuse light
+
+function LightProbe( sh, intensity ) {
+
+	Light.call( this, 0xffffff, intensity );
+
+	this.sh = ( sh !== undefined ) ? sh : new SphericalHarmonics3();
+
+	this.type = 'LightProbe';
+
+}
+
+LightProbe.prototype = Object.assign( Object.create( Light.prototype ), {
+
+	constructor: LightProbe,
+
+	isLightProbe: true,
+
+	// https://www.ppsloan.org/publications/StupidSH36.pdf
+	setFromCubeTexture: function ( cubeTexture ) {
+
+		var norm, lengthSq, weight, totalWeight = 0;
+
+		var coord = new Vector3();
+
+		var dir = new Vector3();
+
+		var color = new Color();
+
+		var shBasis = [ 0, 0, 0, 0, 0, 0, 0, 0, 0 ];
+
+		var shCoefficients = this.sh.coefficients;
+
+		for ( var faceIndex = 0; faceIndex < 6; faceIndex ++ ) {
+
+			var image = cubeTexture.image[ faceIndex ];
+
+			var width = image.width;
+			var height = image.height;
+
+			var canvas = document.createElement( 'canvas' );
+
+			canvas.width = width;
+			canvas.height = height;
+
+			var context = canvas.getContext( '2d' );
+
+			context.drawImage( image, 0, 0, width, height );
+
+			var imageData = context.getImageData( 0, 0, width, height );
+
+			var data = imageData.data;
+
+			var imageWidth = imageData.width; // assumed to be square
+
+			var pixelSize = 2 / imageWidth;
+
+			for ( var i = 0, il = data.length; i < il; i += 4 ) { // RGBA assumed
+
+				// pixel color
+				color.setRGB( data[ i ] / 255, data[ i + 1 ] / 255, data[ i + 2 ] / 255 );
+
+				// convert to linear color space
+				color.copySRGBToLinear( color );
+
+				// pixel coordinate on unit cube
+
+				var pixelIndex = i / 4;
+
+				var col = - 1 + ( pixelIndex % imageWidth + 0.5 ) * pixelSize;
+
+				var row = 1 - ( Math.floor( pixelIndex / imageWidth ) + 0.5 ) * pixelSize;
+
+				switch ( faceIndex ) {
+
+					case 0: coord.set( - 1, row, - col ); break;
+
+					case 1: coord.set( 1, row, col ); break;
+
+					case 2: coord.set( - col, 1, - row ); break;
+
+					case 3: coord.set( - col, - 1, row ); break;
+
+					case 4: coord.set( - col, row, 1 ); break;
+
+					case 5: coord.set( col, row, - 1 ); break;
+
+				}
+
+				// weight assigned to this pixel
+
+				lengthSq = coord.lengthSq();
+
+				weight = 4 / ( Math.sqrt( lengthSq ) * lengthSq );
+
+				totalWeight += weight;
+
+				// direction vector to this pixel
+				dir.copy( coord ).normalize();
+
+				// evaluate SH basis functions in direction dir
+				SphericalHarmonics3.getBasisAt( dir, shBasis );
+
+				// accummuulate
+				for ( var j = 0; j < 9; j ++ ) {
+
+					shCoefficients[ j ].x += shBasis[ j ] * color.r * weight;
+					shCoefficients[ j ].y += shBasis[ j ] * color.g * weight;
+					shCoefficients[ j ].z += shBasis[ j ] * color.b * weight;
+
+				}
+
+			}
+
+		}
+
+		// normalize
+		norm = ( 4 * Math.PI ) / totalWeight;
+
+		for ( var j = 0; j < 9; j ++ ) {
+
+			shCoefficients[ j ].x *= norm;
+			shCoefficients[ j ].y *= norm;
+			shCoefficients[ j ].z *= norm;
+
+		}
+
+	},
+
+	copy: function ( source ) {
+
+		Light.prototype.copy.call( this, source );
+
+		this.sh.copy( source.sh );
+
+		return this;
+
+	},
+
+	toJSON: function ( meta ) {
+
+		var data = Light.prototype.toJSON.call( this, meta );
+
+		//data.sh = this.sh.toArray(); // todo
+
+		return data;
+
+	}
+
+} );
+
+export { LightProbe };

+ 1 - 1
src/materials/ShaderMaterial.d.ts

@@ -17,7 +17,7 @@ export interface ShaderMaterialParameters extends MaterialParameters {
   uniforms?: any;
   vertexShader?: string;
   fragmentShader?: string;
-  lineWidth?: number;
+  linewidth?: number;
   wireframe?: boolean;
   wireframeLinewidth?: number;
   lights?: boolean;

+ 211 - 0
src/math/SphericalHarmonics3.js

@@ -0,0 +1,211 @@
+import { Vector3 } from './Vector3.js';
+
+/**
+ * @author bhouston / http://clara.io
+ * @author WestLangley / http://github.com/WestLangley
+ *
+ * Primary reference:
+ *   https://graphics.stanford.edu/papers/envmap/envmap.pdf
+ *
+ * Secondary reference:
+ *   https://www.ppsloan.org/publications/StupidSH36.pdf
+ */
+
+// 3-band SH defined by 9 coefficients
+
+function SphericalHarmonics3() {
+
+	this.coefficients = [];
+
+	for ( var i = 0; i < 9; i ++ ) {
+
+		this.coefficients.push( new Vector3() );
+
+	}
+
+}
+
+Object.assign( SphericalHarmonics3.prototype, {
+
+	isSphericalHarmonics3: true,
+
+	set: function ( coefficients ) {
+
+		for ( var i = 0; i < 9; i ++ ) {
+
+			this.coefficients[ i ].copy( coefficients[ i ] );
+
+		}
+
+		return this;
+
+	},
+
+	zero: function () {
+
+		for ( var i = 0; i < 9; i ++ ) {
+
+			this.coefficients[ i ].set( 0, 0, 0 );
+
+		}
+
+		return this;
+
+	},
+
+	// get the radiance in the direction of the normal
+	// target is a Vector3
+	getAt: function ( normal, target ) {
+
+		// normal is assumed to be unit length
+
+		var x = normal.x, y = normal.y, z = normal.z;
+
+		var coeff = this.coefficients;
+
+		// band 0
+		target = coeff[ 0 ] * 0.282095;
+
+		// band 1
+		target += coeff[ 1 ] * 0.488603 * y;
+		target += coeff[ 2 ] * 0.488603 * z;
+		target += coeff[ 3 ] * 0.488603 * x;
+
+		// band 2
+		target += coeff[ 4 ] * 1.092548 * ( x * y );
+		target += coeff[ 5 ] * 1.092548 * ( y * z );
+		target += coeff[ 6 ] * 0.315392 * ( 3.0 * z * z - 1.0 );
+		target += coeff[ 7 ] * 1.092548 * ( x * z );
+		target += coeff[ 8 ] * 0.546274 * ( x * x - y * y );
+
+		return target;
+
+	},
+
+	// get the irradiance (radiance convolved with cosine lobe) in the direction of the normal
+	// target is a Vector3
+	// https://graphics.stanford.edu/papers/envmap/envmap.pdf
+	getIrradianceAt: function ( normal, target ) {
+
+		// normal is assumed to be unit length
+
+		var x = normal.x, y = normal.y, z = normal.z;
+
+		var coeff = this.coefficients;
+
+		// band 0
+		target = coeff[ 0 ] * 0.886227; // π * 0.282095
+
+		// band 1
+		target += coeff[ 1 ] * 2.0 * 0.511664 * y; // ( 2 * π / 3 ) * 0.488603
+		target += coeff[ 2 ] * 2.0 * 0.511664 * z;
+		target += coeff[ 3 ] * 2.0 * 0.511664 * x;
+
+		// band 2
+		target += coeff[ 4 ] * 2.0 * 0.429043 * x * y; // ( π / 4 ) * 1.092548
+		target += coeff[ 5 ] * 2.0 * 0.429043 * y * z;
+		target += coeff[ 6 ] * ( 0.743125 * z * z - 0.247708 ); // ( π / 4 ) * 0.315392 * 3
+		target += coeff[ 7 ] * 2.0 * 0.429043 * x * z;
+		target += coeff[ 8 ] * 0.429043 * ( x * x - y * y ); // ( π / 4 ) * 0.546274
+
+		return target;
+
+	},
+
+	add: function ( sh ) {
+
+		for ( var i = 0; i < 9; i ++ ) {
+
+			this.coefficients[ i ].add( sh.coefficients[ i ] );
+
+		}
+
+		return this;
+
+	},
+
+
+	scale: function ( s ) {
+
+		for ( var i = 0; i < 9; i ++ ) {
+
+			this.coefficients[ i ].multiplyScalar( s );
+
+		}
+
+		return this;
+
+	},
+
+	lerp: function ( sh, alpha ) {
+
+		for ( var i = 0; i < 9; i ++ ) {
+
+			this.coefficients[ i ].lerp( sh.coefficients[ i ], alpha );
+
+		}
+
+		return this;
+
+	},
+
+	equals: function ( sh ) {
+
+		for ( var i = 0; i < 9; i ++ ) {
+
+			if ( ! this.coefficients[ i ].equals( sh.coefficients[ i ] ) ) {
+
+				return false;
+
+			}
+
+		}
+
+		return true;
+
+	},
+
+	copy: function ( sh ) {
+
+		return this.set( sh.coefficients );
+
+	},
+
+	clone: function () {
+
+		return new this.constructor().copy( this );
+
+	}
+
+} );
+
+Object.assign( SphericalHarmonics3, {
+
+	// evaluate the basis functions
+	// shBasis is an Array[ 9 ]
+	getBasisAt: function ( normal, shBasis ) {
+
+		// normal is assumed to be unit length
+
+		var x = normal.x, y = normal.y, z = normal.z;
+
+		// band 0
+		shBasis[ 0 ] = 0.282095;
+
+		// band 1
+		shBasis[ 1 ] = 0.488603 * y;
+		shBasis[ 2 ] = 0.488603 * z;
+		shBasis[ 3 ] = 0.488603 * x;
+
+		// band 2
+		shBasis[ 4 ] = 1.092548 * x * y;
+		shBasis[ 5 ] = 1.092548 * y * z;
+		shBasis[ 6 ] = 0.315392 * ( 3 * z * z - 1 );
+		shBasis[ 7 ] = 1.092548 * x * z;
+		shBasis[ 8 ] = 0.546274 * ( x * x - y * y );
+
+	}
+
+} );
+
+export { SphericalHarmonics3 };