Browse Source

Add support for light probes

WestLangley 6 years ago
parent
commit
ba2ed44da6

+ 2 - 0
src/Three.js

@@ -60,6 +60,7 @@ export { DirectionalLight } from './lights/DirectionalLight.js';
 export { AmbientLight } from './lights/AmbientLight.js';
 export { LightShadow } from './lights/LightShadow.js';
 export { Light } from './lights/Light.js';
+export { LightProbe } from './lights/LightProbe.js';
 export { StereoCamera } from './cameras/StereoCamera.js';
 export { PerspectiveCamera } from './cameras/PerspectiveCamera.js';
 export { OrthographicCamera } from './cameras/OrthographicCamera.js';
@@ -123,6 +124,7 @@ export { Vector3 } from './math/Vector3.js';
 export { Vector2 } from './math/Vector2.js';
 export { Quaternion } from './math/Quaternion.js';
 export { Color } from './math/Color.js';
+export { SphericalHarmonics3 } from './math/SphericalHarmonics3.js';
 export { ImmediateRenderObject } from './extras/objects/ImmediateRenderObject.js';
 export { VertexNormalsHelper } from './helpers/VertexNormalsHelper.js';
 export { SpotLightHelper } from './helpers/SpotLightHelper.js';

+ 2 - 0
src/renderers/WebGLRenderer.js

@@ -1599,6 +1599,7 @@ function WebGLRenderer( parameters ) {
 			// wire up the material to this renderer's lighting state
 
 			uniforms.ambientLightColor.value = lights.state.ambient;
+			uniforms.lightProbe.value = lights.state.probe;
 			uniforms.directionalLights.value = lights.state.directional;
 			uniforms.spotLights.value = lights.state.spot;
 			uniforms.rectAreaLights.value = lights.state.rectArea;
@@ -2402,6 +2403,7 @@ function WebGLRenderer( parameters ) {
 	function markUniformsLightsNeedsUpdate( uniforms, value ) {
 
 		uniforms.ambientLightColor.needsUpdate = value;
+		uniforms.lightProbe.needsUpdate = value;
 
 		uniforms.directionalLights.needsUpdate = value;
 		uniforms.pointLights.needsUpdate = value;

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

@@ -103,6 +103,8 @@ IncidentLight directLight;
 
 	vec3 irradiance = getAmbientLightIrradiance( ambientLightColor );
 
+	irradiance += getLightProbeIrradiance( lightProbe, geometry );
+
 	#if ( NUM_HEMI_LIGHTS > 0 )
 
 		#pragma unroll_loop

+ 38 - 0
src/renderers/shaders/ShaderChunk/lights_pars_begin.glsl.js

@@ -1,5 +1,43 @@
 export default /* glsl */`
 uniform vec3 ambientLightColor;
+uniform vec3 lightProbe[ 9 ];
+
+// get the irradiance (radiance convolved with cosine lobe) at the point 'normal' on the unit sphere
+// source: https://graphics.stanford.edu/papers/envmap/envmap.pdf
+vec3 shGetIrradianceAt( in vec3 normal, in vec3 shCoefficients[ 9 ] ) {
+
+	// normal is assumed to have unit length
+
+	float x = normal.x, y = normal.y, z = normal.z;
+
+	// band 0
+	vec3 result = shCoefficients[ 0 ] * 0.886227;
+
+	// band 1
+	result += shCoefficients[ 1 ] * 2.0 * 0.511664 * y;
+	result += shCoefficients[ 2 ] * 2.0 * 0.511664 * z;
+	result += shCoefficients[ 3 ] * 2.0 * 0.511664 * x;
+
+	// band 2
+	result += shCoefficients[ 4 ] * 2.0 * 0.429043 * x * y;
+	result += shCoefficients[ 5 ] * 2.0 * 0.429043 * y * z;
+	result += shCoefficients[ 6 ] * ( 0.743125 * z * z - 0.247708 );
+	result += shCoefficients[ 7 ] * 2.0 * 0.429043 * x * z;
+	result += shCoefficients[ 8 ] * 0.429043 * ( x * x - y * y );
+
+	return result;
+
+}
+
+vec3 getLightProbeIrradiance( const in vec3 lightProbe[ 9 ], const in GeometricContext geometry ) {
+
+	vec3 worldNormal = inverseTransformDirection( geometry.normal, viewMatrix );
+
+	vec3 irradiance = shGetIrradianceAt( worldNormal, lightProbe );
+
+	return irradiance;
+
+}
 
 vec3 getAmbientLightIrradiance( const in vec3 ambientLightColor ) {
 

+ 2 - 0
src/renderers/shaders/UniformsLib.js

@@ -109,6 +109,8 @@ var UniformsLib = {
 
 		ambientLightColor: { value: [] },
 
+		lightProbe: { value: [] },
+
 		directionalLights: { value: [], properties: {
 			direction: {},
 			color: {},

+ 13 - 0
src/renderers/webgl/WebGLLights.js

@@ -121,6 +121,7 @@ function WebGLLights() {
 		},
 
 		ambient: [ 0, 0, 0 ],
+		probe: [],
 		directional: [],
 		directionalShadowMap: [],
 		directionalShadowMatrix: [],
@@ -135,6 +136,8 @@ function WebGLLights() {
 
 	};
 
+	for ( var i = 0; i < 9; i ++ ) state.probe.push( new Vector3() );
+
 	var vector3 = new Vector3();
 	var matrix4 = new Matrix4();
 	var matrix42 = new Matrix4();
@@ -143,6 +146,8 @@ function WebGLLights() {
 
 		var r = 0, g = 0, b = 0;
 
+		for ( var i = 0; i < 9; i ++ ) state.probe[ i ].set( 0, 0, 0 );
+
 		var directionalLength = 0;
 		var pointLength = 0;
 		var spotLength = 0;
@@ -167,6 +172,14 @@ function WebGLLights() {
 				g += color.g * intensity;
 				b += color.b * intensity;
 
+			} else if ( light.isLightProbe ) {
+
+				for ( var j = 0; j < 9; j ++ ) {
+
+					state.probe[ j ].addScaledVector( light.sh.coefficients[ j ], intensity );
+
+				}
+
 			} else if ( light.isDirectionalLight ) {
 
 				var uniforms = cache.get( light );