Bläddra i källkod

LightProbe: Moved utility methods to examples.

Mr.doob 6 år sedan
förälder
incheckning
db01cf4b94

+ 160 - 0
examples/js/lights/LightProbeGenerator.js

@@ -0,0 +1,160 @@
+/**
+ * @author WestLangley / http://github.com/WestLangley
+ */
+
+THREE.LightProbeGenerator = {
+
+	fromAmbientLight: function ( light ) {
+
+		var color = light.color;
+		var intensity = light.intensity;
+
+		var sh = new THREE.SphericalHarmonics3();
+
+		// without extra factor of PI in the shader, would be 2 / Math.sqrt( Math.PI );
+		sh.coefficients[ 0 ].set( color.r, color.g, color.b ).multiplyScalar(  2 * Math.sqrt( Math.PI ) );
+
+		return new THREE.LightProbe( sh, intensity );
+
+	},
+
+	fromHemisphereLight: function ( light ) {
+
+		// up-direction hardwired
+
+		// up-direction hardwired
+
+		var color1 = light.color;
+		var color2 = light.groundColor;
+
+		var sky = new THREE.Vector3( color1.r, color1.g, color1.b );
+		var ground = new THREE.Vector3( color2.r, color2.g, color2.b );
+		var intensity = light.intensity;
+
+		// without extra factor of PI in the shader, should = 1 / Math.sqrt( Math.PI );
+		var c0 = Math.sqrt( Math.PI );
+		var c1 = c0 * Math.sqrt( 0.75 );
+
+		var sh = new THREE.SphericalHarmonics3();
+		sh.coefficients[ 0 ].copy( sky ).add( ground ).multiplyScalar( c0 );
+		sh.coefficients[ 1 ].copy( sky ).sub( ground ).multiplyScalar( c1 );
+
+		return new THREE.LightProbe( sh, intensity );
+
+	},
+
+	// https://www.ppsloan.org/publications/StupidSH36.pdf
+	fromCubeTexture: function ( cubeTexture ) {
+
+		var norm, lengthSq, weight, totalWeight = 0;
+
+		var coord = new THREE.Vector3();
+
+		var dir = new THREE.Vector3();
+
+		var color = new THREE.Color();
+
+		var shBasis = [ 0, 0, 0, 0, 0, 0, 0, 0, 0 ];
+
+		var sh = new THREE.SphericalHarmonics3();
+		var shCoefficients = 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
+				THREE.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;
+
+		}
+
+		return new THREE.LightProbe( sh );
+
+	}
+
+};

+ 4 - 3
examples/webgl_lightprobe.html

@@ -40,6 +40,7 @@
 		<script src="js/controls/OrbitControls.js"></script>
 		<script src="js/controls/OrbitControls.js"></script>
 
 
 		<script src="js/libs/dat.gui.min.js"></script>
 		<script src="js/libs/dat.gui.min.js"></script>
+		<script src="js/lights/LightProbeGenerator.js"></script>
 
 
 		<script src="js/WebGL.js"></script>
 		<script src="js/WebGL.js"></script>
 
 
@@ -98,7 +99,7 @@
 				controls.enablePan = false;
 				controls.enablePan = false;
 
 
 				// probe
 				// probe
-				lightProbe = new THREE.LightProbe( 0xffffff, API.lightProbeIntensity );
+				lightProbe = new THREE.LightProbe();
 				scene.add( lightProbe );
 				scene.add( lightProbe );
 
 
 				// light
 				// light
@@ -125,8 +126,8 @@
 
 
 					scene.background = cubeTexture;
 					scene.background = cubeTexture;
 
 
-					lightProbe.setFromCubeTexture( cubeTexture );
-
+					lightProbe.copy( THREE.LightProbeGenerator.fromCubeTexture( cubeTexture ) );
+					console.log(lightProbe );
 					var geometry = new THREE.SphereBufferGeometry( 5, 64, 32 );
 					var geometry = new THREE.SphereBufferGeometry( 5, 64, 32 );
 					//var geometry = new THREE.TorusKnotBufferGeometry( 4, 1.5, 256, 32, 2, 3 );
 					//var geometry = new THREE.TorusKnotBufferGeometry( 4, 1.5, 256, 32, 2, 3 );
 
 

+ 4 - 3
examples/webgl_loader_gltf.html

@@ -79,9 +79,9 @@
 
 
 					// light probe
 					// light probe
 
 
-					var lightProbe = new THREE.LightProbe();
-					// Coefficients computed with setFromCubeTexture( texture ) and sh.toArray()
-					lightProbe.sh.fromArray(
+					var sh = new THREE.SphericalHarmonics3();
+					// Coefficients computed with LightProbeGenerator.fromCubeTexture() and sh.toArray()
+					sh.fromArray(
 						[ 0.30350402186576847, 0.4695020609740584, 0.6617666153025029,
 						[ 0.30350402186576847, 0.4695020609740584, 0.6617666153025029,
 							0.08320329629560637, 0.17400245533281114, 0.3453152275957874,
 							0.08320329629560637, 0.17400245533281114, 0.3453152275957874,
 							0.12158824672933624, 0.10353622444396401, 0.06530153583524678,
 							0.12158824672933624, 0.10353622444396401, 0.06530153583524678,
@@ -93,6 +93,7 @@
 							0.13316051440231733, 0.1964793374921572, 0.2189213184804167
 							0.13316051440231733, 0.1964793374921572, 0.2189213184804167
 						]
 						]
 					);
 					);
+					var lightProbe = new THREE.LightProbe( sh );
 					scene.add( lightProbe );
 					scene.add( lightProbe );
 
 
 					// model
 					// model

+ 11 - 164
src/lights/LightProbe.js

@@ -1,24 +1,20 @@
+/**
+ * @author WestLangley / http://github.com/WestLangley
+ *
+ * A LightProbe is a source of indirect-diffuse light
+ */
+
 import { _Math } from '../math/Math.js';
 import { _Math } from '../math/Math.js';
 import { Vector3 } from '../math/Vector3.js';
 import { Vector3 } from '../math/Vector3.js';
 import { Color } from '../math/Color.js';
 import { Color } from '../math/Color.js';
 import { SphericalHarmonics3 } from '../math/SphericalHarmonics3.js';
 import { SphericalHarmonics3 } from '../math/SphericalHarmonics3.js';
 import { Light } from './Light.js';
 import { Light } from './Light.js';
 
 
-/**
- * @author WestLangley / http://github.com/WestLangley
- */
-
-// A LightProbe is a source of indirect-diffuse light
-
-function LightProbe( color, intensity ) {
-
-	Light.call( this, color, intensity );
+function LightProbe( sh, intensity ) {
 
 
-	this.sh = new SphericalHarmonics3();
+	Light.call( this, undefined, intensity );
 
 
-	this.sh.coefficients[ 0 ].set( 1, 1, 1 );
-
-	this.type = 'LightProbe';
+	this.sh = ( sh !== undefined ) ? sh : new SphericalHarmonics3();
 
 
 }
 }
 
 
@@ -28,161 +24,12 @@ LightProbe.prototype = Object.assign( Object.create( Light.prototype ), {
 
 
 	isLightProbe: true,
 	isLightProbe: true,
 
 
-	setAmbientProbe: function ( color, intensity ) {
-
-		this.color.set( color );
-
-		this.intensity = intensity !== undefined ? intensity : 1;
-
-		this.sh.zero();
-
-		// without extra factor of PI in the shader, would be 2 / Math.sqrt( Math.PI );
-		this.sh.coefficients[ 0 ].set( 1, 1, 1 ).multiplyScalar( 2 * Math.sqrt( Math.PI ) );
-
-	},
-
-	setHemisphereProbe: function ( skyColor, groundColor, intensity ) {
-
-		// up-direction hardwired
-
-		this.color.setHex( 0xffffff );
-
-		this.intensity = intensity !== undefined ? intensity : 1;
-
-		var sky = new Color( skyColor );
-		var ground = new Color( groundColor );
-
-		/* cough */
-		sky = new Vector3( sky.r, sky.g, sky.b );
-		ground = new Vector3( ground.r, ground.g, ground.b );
-
-		// without extra factor of PI in the shader, should = 1 / Math.sqrt( Math.PI );
-		var c0 = Math.sqrt( Math.PI );
-		var c1 = c0 * Math.sqrt( 0.75 );
-
-		this.sh.zero();
-
-		this.sh.coefficients[ 0 ].copy( sky ).add( ground ).multiplyScalar( c0 );
-		this.sh.coefficients[ 1 ].copy( sky ).sub( ground ).multiplyScalar( c1 );
-
-	},
-
-	// 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 ) {
 	copy: function ( source ) {
 
 
 		Light.prototype.copy.call( this, source );
 		Light.prototype.copy.call( this, source );
 
 
 		this.sh.copy( source.sh );
 		this.sh.copy( source.sh );
+		this.intensity = source.intensity;
 
 
 		return this;
 		return this;
 
 
@@ -192,7 +39,7 @@ LightProbe.prototype = Object.assign( Object.create( Light.prototype ), {
 
 
 		var data = Light.prototype.toJSON.call( this, meta );
 		var data = Light.prototype.toJSON.call( this, meta );
 
 
-		//data.sh = this.sh.toArray(); // todo
+		// data.sh = this.sh.toArray(); // todo
 
 
 		return data;
 		return data;
 
 

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

@@ -176,12 +176,7 @@ function WebGLLights() {
 
 
 				for ( var j = 0; j < 9; j ++ ) {
 				for ( var j = 0; j < 9; j ++ ) {
 
 
-					var probe = state.probe[ j ];
-					var coeff = light.sh.coefficients[ j ];
-
-					probe.x += coeff.x * color.r * intensity;
-					probe.y += coeff.y * color.g * intensity;
-					probe.z += coeff.z * color.b * intensity;
+					state.probe[ j ].addScaledVector( light.sh.coefficients[ j ], intensity );
 
 
 				}
 				}