瀏覽代碼

Merge branch 'decayExponent' of https://github.com/bhouston/three.js into dev

Conflicts:
	src/renderers/shaders/ShaderLib.js
Mr.doob 10 年之前
父節點
當前提交
9dbd7669d0

+ 16 - 17
examples/js/ShaderSkin.js

@@ -103,6 +103,7 @@ THREE.ShaderSkin = {
 				"uniform vec3 pointLightColor[ MAX_POINT_LIGHTS ];",
 				"uniform vec3 pointLightPosition[ MAX_POINT_LIGHTS ];",
 				"uniform float pointLightDistance[ MAX_POINT_LIGHTS ];",
+				"uniform float pointLightDecayExponent[ MAX_POINT_LIGHTS ];",
 
 			"#endif",
 
@@ -200,11 +201,8 @@ THREE.ShaderSkin = {
 						"vec4 lPosition = viewMatrix * vec4( pointLightPosition[ i ], 1.0 );",
 
 						"vec3 lVector = lPosition.xyz + vViewPosition.xyz;",
-
-						"float lDistance = 1.0;",
-
-						"if ( pointLightDistance[ i ] > 0.0 )",
-							"lDistance = 1.0 - min( ( length( lVector ) / pointLightDistance[ i ] ), 1.0 );",
+	
+						"float attenuation = calcLightAttenuation( length( lVector ), pointLightDistance[ i ], pointLightDecayExponent[i] );",
 
 						"lVector = normalize( lVector );",
 
@@ -214,8 +212,8 @@ THREE.ShaderSkin = {
 
 						"float pointSpecularWeight = KS_Skin_Specular( normal, lVector, viewPosition, uRoughness, uSpecularBrightness );",
 
-						"pointTotal    += lDistance * diffuse * pointLightColor[ i ] * pointDiffuseWeight;",
-						"specularTotal += lDistance * specular * pointLightColor[ i ] * pointSpecularWeight * specularStrength;",
+						"pointTotal    += attenuation * diffuse * pointLightColor[ i ] * pointDiffuseWeight;",
+						"specularTotal += attenuation * specular * pointLightColor[ i ] * pointSpecularWeight * specularStrength;",
 
 					"}",
 
@@ -310,6 +308,7 @@ THREE.ShaderSkin = {
 
 			"varying vec3 vViewPosition;",
 
+			THREE.ShaderChunk[ "common" ],
 			THREE.ShaderChunk[ "shadowmap_pars_vertex" ],
 
 			"void main() {",
@@ -625,6 +624,7 @@ THREE.ShaderSkin = {
 
 				"uniform vec3 pointLightPosition[ MAX_POINT_LIGHTS ];",
 				"uniform float pointLightDistance[ MAX_POINT_LIGHTS ];",
+				"uniform float pointLightDecayExponent[ MAX_POINT_LIGHTS ];",
 
 				"varying vec4 vPointLight[ MAX_POINT_LIGHTS ];",
 
@@ -632,6 +632,8 @@ THREE.ShaderSkin = {
 
 			"varying vec3 vViewPosition;",
 
+			THREE.ShaderChunk[ "common" ],
+
 			"void main() {",
 
 				"vec4 worldPosition = modelMatrix * vec4( position, 1.0 );",
@@ -661,14 +663,11 @@ THREE.ShaderSkin = {
 
 						"vec3 lVector = lPosition.xyz - mvPosition.xyz;",
 
-						"float lDistance = 1.0;",
-
-						"if ( pointLightDistance[ i ] > 0.0 )",
-							"lDistance = 1.0 - min( ( length( lVector ) / pointLightDistance[ i ] ), 1.0 );",
+						"float attenuation = calcLightAttenuation( length( lVector ), pointLightDistance[ i ], pointLightDecayExponent[i] );",
 
 						"lVector = normalize( lVector );",
 
-						"vPointLight[ i ] = vec4( lVector, lDistance );",
+						"vPointLight[ i ] = vec4( lVector, attenuation );",
 
 					"}",
 
@@ -714,6 +713,7 @@ THREE.ShaderSkin = {
 
 				"uniform vec3 pointLightPosition[ MAX_POINT_LIGHTS ];",
 				"uniform float pointLightDistance[ MAX_POINT_LIGHTS ];",
+				"uniform float pointLightDecayExponent[ MAX_POINT_LIGHTS ];",
 
 				"varying vec4 vPointLight[ MAX_POINT_LIGHTS ];",
 
@@ -721,6 +721,8 @@ THREE.ShaderSkin = {
 
 			"varying vec3 vViewPosition;",
 
+			THREE.ShaderChunk[ "common" ],
+
 			"void main() {",
 
 				"vec4 worldPosition = modelMatrix * vec4( position, 1.0 );",
@@ -750,14 +752,11 @@ THREE.ShaderSkin = {
 
 						"vec3 lVector = lPosition.xyz - mvPosition.xyz;",
 
-						"float lDistance = 1.0;",
-
-						"if ( pointLightDistance[ i ] > 0.0 )",
-							"lDistance = 1.0 - min( ( length( lVector ) / pointLightDistance[ i ] ), 1.0 );",
+						"float attenuation = calcLightAttenuation( length( lVector ), pointLightDistance[ i ], pointLightDecayExponent[i] );",
 
 						"lVector = normalize( lVector );",
 
-						"vPointLight[ i ] = vec4( lVector, lDistance );",
+						"vPointLight[ i ] = vec4( lVector, attenuation );",
 
 					"}",
 

+ 4 - 6
examples/js/ShaderTerrain.js

@@ -106,6 +106,7 @@ THREE.ShaderTerrain = {
 				"uniform vec3 pointLightColor[ MAX_POINT_LIGHTS ];",
 				"uniform vec3 pointLightPosition[ MAX_POINT_LIGHTS ];",
 				"uniform float pointLightDistance[ MAX_POINT_LIGHTS ];",
+				"uniform float pointLightDecayExponent[ MAX_POINT_LIGHTS ];",
 
 			"#endif",
 
@@ -173,22 +174,19 @@ THREE.ShaderTerrain = {
 						"vec4 lPosition = viewMatrix * vec4( pointLightPosition[ i ], 1.0 );",
 						"vec3 lVector = lPosition.xyz + vViewPosition.xyz;",
 
-						"float lDistance = 1.0;",
-						"if ( pointLightDistance[ i ] > 0.0 )",
-							"lDistance = 1.0 - min( ( length( lVector ) / pointLightDistance[ i ] ), 1.0 );",
+						"float attenuation = calcLightAttenuation( length( lVector ), pointLightDistance[ i ], pointLightDecayExponent[i] );"
 
 						"lVector = normalize( lVector );",
 
 						"vec3 pointHalfVector = normalize( lVector + viewPosition );",
-						"float pointDistance = lDistance;",
 
 						"float pointDotNormalHalf = max( dot( normal, pointHalfVector ), 0.0 );",
 						"float pointDiffuseWeight = max( dot( normal, lVector ), 0.0 );",
 
 						"float pointSpecularWeight = specularTex.r * max( pow( pointDotNormalHalf, shininess ), 0.0 );",
 
-						"pointDiffuse += pointDistance * pointLightColor[ i ] * diffuse * pointDiffuseWeight;",
-						"pointSpecular += pointDistance * pointLightColor[ i ] * specular * pointSpecularWeight * pointDiffuseWeight;",
+						"pointDiffuse += attenuation * pointLightColor[ i ] * diffuse * pointDiffuseWeight;",
+						"pointSpecular += attenuation * pointLightColor[ i ] * specular * pointSpecularWeight * pointDiffuseWeight;",
 
 					"}",
 

+ 15 - 13
examples/js/exporters/SceneExporter.js

@@ -238,11 +238,12 @@ THREE.SceneExporter.prototype = {
 				var output = [
 
 				'\t\t' + LabelString( getObjectName( o ) ) + ' : {',
-				'	"type"      : "PointLight",',
-				'	"color"     : ' + o.color.getHex() + ',',
-				'	"intensity" : ' + o.intensity + ',',
-				'	"position"  : ' + Vector3String( o.position ) + ',',
-				'	"distance"  : ' + o.distance + ( o.children.length ? ',' : '' )
+				'	"type"           : "PointLight",',
+				'	"color"          : ' + o.color.getHex() + ',',
+				'	"intensity"      : ' + o.intensity + ',',
+				'	"position"       : ' + Vector3String( o.position ) + ',',
+				'	"decayExponent"  : ' + o.decayExponent + ',',
+				'	"distance"       : ' + o.distance + ( o.children.length ? ',' : '' )
 
 				];
 
@@ -251,14 +252,15 @@ THREE.SceneExporter.prototype = {
 				var output = [
 
 				'\t\t' + LabelString( getObjectName( o ) ) + ' : {',
-				'	"type"      : "SpotLight",',
-				'	"color"     : ' + o.color.getHex() + ',',
-				'	"intensity" : ' + o.intensity + ',',
-				'	"position"  : ' + Vector3String( o.position ) + ',',
-				'	"distance"  : ' + o.distance + ',',
-				'	"angle"     : ' + o.angle + ',',
-				'	"exponent"  : ' + o.exponent + ',',
-				'	"target"    : ' + LabelString( getObjectName( o.target ) ) + ( o.children.length ? ',' : '' )
+				'	"type"           : "SpotLight",',
+				'	"color"          : ' + o.color.getHex() + ',',
+				'	"intensity"      : ' + o.intensity + ',',
+				'	"position"       : ' + Vector3String( o.position ) + ',',
+				'	"distance"       : ' + o.distance + ',',
+				'	"angle"          : ' + o.angle + ',',
+				'	"exponent"       : ' + o.exponent + ',',
+				'	"decayExponent"  : ' + o.decayExponent + ',',
+				'	"target"         : ' + LabelString( getObjectName( o.target ) ) + ( o.children.length ? ',' : '' )
 
 				];
 

+ 2 - 0
src/core/Object3D.js

@@ -677,6 +677,7 @@ THREE.Object3D.prototype = {
 				data.color = object.color.getHex();
 				data.intensity = object.intensity;
 				data.distance = object.distance;
+				data.decayExponent = object.decayExponent || 0;
 
 			} else if ( object instanceof THREE.SpotLight ) {
 
@@ -685,6 +686,7 @@ THREE.Object3D.prototype = {
 				data.distance = object.distance;
 				data.angle = object.angle;
 				data.exponent = object.exponent;
+				data.decayExponent = object.decayExponent || 0;
 
 			} else if ( object instanceof THREE.HemisphereLight ) {
 

+ 4 - 2
src/lights/PointLight.js

@@ -2,7 +2,7 @@
  * @author mrdoob / http://mrdoob.com/
  */
 
-THREE.PointLight = function ( color, intensity, distance ) {
+THREE.PointLight = function ( color, intensity, distance, decayExponent ) {
 
 	THREE.Light.call( this, color );
 
@@ -10,6 +10,7 @@ THREE.PointLight = function ( color, intensity, distance ) {
 
 	this.intensity = ( intensity !== undefined ) ? intensity : 1;
 	this.distance = ( distance !== undefined ) ? distance : 0;
+	this.decayExponent = ( decayExponent !== undefined ) ? decayExponent : 1;	// for physically correct lights, should be 2.
 
 };
 
@@ -24,7 +25,8 @@ THREE.PointLight.prototype.clone = function () {
 
 	light.intensity = this.intensity;
 	light.distance = this.distance;
-
+	light.decayExponent = this.decayExponent;
+	
 	return light;
 
 };

+ 4 - 2
src/lights/SpotLight.js

@@ -2,7 +2,7 @@
  * @author alteredq / http://alteredqualia.com/
  */
 
-THREE.SpotLight = function ( color, intensity, distance, angle, exponent ) {
+THREE.SpotLight = function ( color, intensity, distance, angle, exponent, decayExponent ) {
 
 	THREE.Light.call( this, color );
 
@@ -15,6 +15,7 @@ THREE.SpotLight = function ( color, intensity, distance, angle, exponent ) {
 	this.distance = ( distance !== undefined ) ? distance : 0;
 	this.angle = ( angle !== undefined ) ? angle : Math.PI / 3;
 	this.exponent = ( exponent !== undefined ) ? exponent : 10;
+	this.decayExponent = ( decayExponent !== undefined ) ? decayExponent : 1;	// for physically correct lights, should be 2.
 
 	this.castShadow = false;
 	this.onlyShadow = false;
@@ -57,7 +58,8 @@ THREE.SpotLight.prototype.clone = function () {
 	light.distance = this.distance;
 	light.angle = this.angle;
 	light.exponent = this.exponent;
-
+	light.decayExponent = this.decayExponent;
+	
 	light.castShadow = this.castShadow;
 	light.onlyShadow = this.onlyShadow;
 

+ 11 - 2
src/renderers/WebGLRenderer.js

@@ -171,8 +171,8 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 		ambient: [ 0, 0, 0 ],
 		directional: { length: 0, colors:[], positions: [] },
-		point: { length: 0, colors: [], positions: [], distances: [] },
-		spot: { length: 0, colors: [], positions: [], distances: [], directions: [], anglesCos: [], exponents: [] },
+		point: { length: 0, colors: [], positions: [], distances: [], decayExponents: [] },
+		spot: { length: 0, colors: [], positions: [], distances: [], directions: [], anglesCos: [], exponents: [], decayExponents: [] },
 		hemi: { length: 0, skyColors: [], groundColors: [], positions: [] }
 
 	};
@@ -4776,6 +4776,7 @@ THREE.WebGLRenderer = function ( parameters ) {
 		uniforms.pointLightColor.value = lights.point.colors;
 		uniforms.pointLightPosition.value = lights.point.positions;
 		uniforms.pointLightDistance.value = lights.point.distances;
+		uniforms.pointLightDecayExponent.value = lights.point.decayExponents;
 
 		uniforms.spotLightColor.value = lights.spot.colors;
 		uniforms.spotLightPosition.value = lights.spot.positions;
@@ -4783,6 +4784,7 @@ THREE.WebGLRenderer = function ( parameters ) {
 		uniforms.spotLightDirection.value = lights.spot.directions;
 		uniforms.spotLightAngleCos.value = lights.spot.anglesCos;
 		uniforms.spotLightExponent.value = lights.spot.exponents;
+		uniforms.spotLightDecayExponent.value = lights.spot.decayExponents;
 
 		uniforms.hemisphereLightSkyColor.value = lights.hemi.skyColors;
 		uniforms.hemisphereLightGroundColor.value = lights.hemi.groundColors;
@@ -4802,6 +4804,7 @@ THREE.WebGLRenderer = function ( parameters ) {
 		uniforms.pointLightColor.needsUpdate = boolean;
 		uniforms.pointLightPosition.needsUpdate = boolean;
 		uniforms.pointLightDistance.needsUpdate = boolean;
+		uniforms.pointLightDecayExponent.needsUpdate = boolean;
 
 		uniforms.spotLightColor.needsUpdate = boolean;
 		uniforms.spotLightPosition.needsUpdate = boolean;
@@ -4809,6 +4812,7 @@ THREE.WebGLRenderer = function ( parameters ) {
 		uniforms.spotLightDirection.needsUpdate = boolean;
 		uniforms.spotLightAngleCos.needsUpdate = boolean;
 		uniforms.spotLightExponent.needsUpdate = boolean;
+		uniforms.spotLightDecayExponent.needsUpdate = boolean;
 
 		uniforms.hemisphereLightSkyColor.needsUpdate = boolean;
 		uniforms.hemisphereLightGroundColor.needsUpdate = boolean;
@@ -5256,6 +5260,7 @@ THREE.WebGLRenderer = function ( parameters ) {
 		pointColors = zlights.point.colors,
 		pointPositions = zlights.point.positions,
 		pointDistances = zlights.point.distances,
+		pointDecayExponents = zlights.point.decayExponents,
 
 		spotColors = zlights.spot.colors,
 		spotPositions = zlights.spot.positions,
@@ -5263,6 +5268,7 @@ THREE.WebGLRenderer = function ( parameters ) {
 		spotDirections = zlights.spot.directions,
 		spotAnglesCos = zlights.spot.anglesCos,
 		spotExponents = zlights.spot.exponents,
+		spotDecayExponents = zlights.spot.decayExponents,
 
 		hemiSkyColors = zlights.hemi.skyColors,
 		hemiGroundColors = zlights.hemi.groundColors,
@@ -5364,7 +5370,9 @@ THREE.WebGLRenderer = function ( parameters ) {
 				pointPositions[ pointOffset + 1 ] = _vector3.y;
 				pointPositions[ pointOffset + 2 ] = _vector3.z;
 
+				// distance is 0 if decayExponent is 0, because there is no attenuation at all.
 				pointDistances[ pointLength ] = distance;
+				pointDecayExponents[ pointLength ] = ( light.distance === 0 ) ? 0.0 : light.decayExponent;
 
 				pointLength += 1;
 
@@ -5404,6 +5412,7 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 				spotAnglesCos[ spotLength ] = Math.cos( light.angle );
 				spotExponents[ spotLength ] = light.exponent;
+				spotDecayExponents[ spotLength ] = ( light.distance === 0 ) ? 0.0 : light.decayExponent;
 
 				spotLength += 1;
 

+ 8 - 1
src/renderers/shaders/ShaderChunk/common.glsl

@@ -36,4 +36,11 @@ float sideOfPlane( in vec3 point, in vec3 pointOnPlane, in vec3 planeNormal ) {
 }
 vec3 linePlaneIntersect( in vec3 pointOnLine, in vec3 lineDirection, in vec3 pointOnPlane, in vec3 planeNormal ) {
 	return pointOnLine + lineDirection * ( dot( planeNormal, pointOnPlane - pointOnLine ) / dot( planeNormal, lineDirection ) );
-}
+}
+float calcLightAttenuation( float lightDistance, float cutoffDistance, float decayExponent ) {
+	if ( decayExponent > 0.0 ) {
+	  return pow( saturate( 1.0 - lightDistance / cutoffDistance ), decayExponent );
+	}
+	return 1.0;
+}
+

+ 2 - 0
src/renderers/shaders/ShaderChunk/lights_lambert_pars_vertex.glsl

@@ -23,6 +23,7 @@ uniform vec3 ambientLightColor;
 	uniform vec3 pointLightColor[ MAX_POINT_LIGHTS ];
 	uniform vec3 pointLightPosition[ MAX_POINT_LIGHTS ];
 	uniform float pointLightDistance[ MAX_POINT_LIGHTS ];
+	uniform float pointLightDecayExponent[ MAX_POINT_LIGHTS ];
 
 #endif
 
@@ -34,6 +35,7 @@ uniform vec3 ambientLightColor;
 	uniform float spotLightDistance[ MAX_SPOT_LIGHTS ];
 	uniform float spotLightAngleCos[ MAX_SPOT_LIGHTS ];
 	uniform float spotLightExponent[ MAX_SPOT_LIGHTS ];
+	uniform float spotLightDecayExponent[ MAX_SPOT_LIGHTS ];
 
 #endif
 

+ 6 - 10
src/renderers/shaders/ShaderChunk/lights_lambert_vertex.glsl

@@ -61,9 +61,7 @@ for( int i = 0; i < MAX_DIR_LIGHTS; i ++ ) {
 		vec4 lPosition = viewMatrix * vec4( pointLightPosition[ i ], 1.0 );
 		vec3 lVector = lPosition.xyz - mvPosition.xyz;
 
-		float lDistance = 1.0;
-		if ( pointLightDistance[ i ] > 0.0 )
-			lDistance = 1.0 - min( ( length( lVector ) / pointLightDistance[ i ] ), 1.0 );
+		float attenuation = calcLightAttenuation( length( lVector ), pointLightDistance[ i ], pointLightDecayExponent[i] );
 
 		lVector = normalize( lVector );
 		float dotProduct = dot( transformedNormal, lVector );
@@ -95,11 +93,11 @@ for( int i = 0; i < MAX_DIR_LIGHTS; i ++ ) {
 
 		#endif
 
-		vLightFront += pointLightColor[ i ] * pointLightWeighting * lDistance;
+		vLightFront += pointLightColor[ i ] * pointLightWeighting * attenuation;
 
 		#ifdef DOUBLE_SIDED
 
-			vLightBack += pointLightColor[ i ] * pointLightWeightingBack * lDistance;
+			vLightBack += pointLightColor[ i ] * pointLightWeightingBack * attenuation;
 
 		#endif
 
@@ -120,9 +118,7 @@ for( int i = 0; i < MAX_DIR_LIGHTS; i ++ ) {
 
 			spotEffect = max( pow( max( spotEffect, 0.0 ), spotLightExponent[ i ] ), 0.0 );
 
-			float lDistance = 1.0;
-			if ( spotLightDistance[ i ] > 0.0 )
-				lDistance = 1.0 - min( ( length( lVector ) / spotLightDistance[ i ] ), 1.0 );
+			float attenuation = calcLightAttenuation( length( lVector ), spotLightDistance[ i ], spotLightDecayExponent[i] );
 
 			lVector = normalize( lVector );
 
@@ -154,11 +150,11 @@ for( int i = 0; i < MAX_DIR_LIGHTS; i ++ ) {
 
 			#endif
 
-			vLightFront += spotLightColor[ i ] * spotLightWeighting * lDistance * spotEffect;
+			vLightFront += spotLightColor[ i ] * spotLightWeighting * attenuation * spotEffect;
 
 			#ifdef DOUBLE_SIDED
 
-				vLightBack += spotLightColor[ i ] * spotLightWeightingBack * lDistance * spotEffect;
+				vLightBack += spotLightColor[ i ] * spotLightWeightingBack * attenuation * spotEffect;
 
 			#endif
 

+ 6 - 10
src/renderers/shaders/ShaderChunk/lights_phong_fragment.glsl

@@ -27,9 +27,7 @@ vec3 viewPosition = normalize( vViewPosition );
 		vec4 lPosition = viewMatrix * vec4( pointLightPosition[ i ], 1.0 );
 		vec3 lVector = lPosition.xyz + vViewPosition.xyz;
 
-		float lDistance = 1.0;
-		if ( pointLightDistance[ i ] > 0.0 )
-			lDistance = saturate( 1.0 - ( length( lVector ) / pointLightDistance[ i ] ) );
+		float attenuation = calcLightAttenuation( length( lVector ), pointLightDistance[ i ], pointLightDecayExponent[i] );
 
 		lVector = normalize( lVector );
 
@@ -50,7 +48,7 @@ vec3 viewPosition = normalize( vViewPosition );
 
 		#endif
 
-		pointDiffuse += diffuse * pointLightColor[ i ] * pointDiffuseWeight * lDistance;
+		pointDiffuse += diffuse * pointLightColor[ i ] * pointDiffuseWeight * attenuation;
 
 				// specular
 
@@ -61,7 +59,7 @@ vec3 viewPosition = normalize( vViewPosition );
 		float specularNormalization = ( shininess + 2.0 ) / 8.0;
 
 		vec3 schlick = specular + vec3( 1.0 - specular ) * pow( max( 1.0 - dot( lVector, pointHalfVector ), 0.0 ), 5.0 );
-		pointSpecular += schlick * pointLightColor[ i ] * pointSpecularWeight * pointDiffuseWeight * lDistance * specularNormalization;
+		pointSpecular += schlick * pointLightColor[ i ] * pointSpecularWeight * pointDiffuseWeight * attenuation * specularNormalization;
 
 	}
 
@@ -77,9 +75,7 @@ vec3 viewPosition = normalize( vViewPosition );
 		vec4 lPosition = viewMatrix * vec4( spotLightPosition[ i ], 1.0 );
 		vec3 lVector = lPosition.xyz + vViewPosition.xyz;
 
-		float lDistance = 1.0;
-		if ( spotLightDistance[ i ] > 0.0 )
-			lDistance = saturate( 1.0 - ( length( lVector ) / spotLightDistance[ i ] ) );
+		float attenuation = calcLightAttenuation( length( lVector ), spotLightDistance[ i ], spotLightDecayExponent[i] );
 
 		lVector = normalize( lVector );
 
@@ -106,7 +102,7 @@ vec3 viewPosition = normalize( vViewPosition );
 
 			#endif
 
-			spotDiffuse += diffuse * spotLightColor[ i ] * spotDiffuseWeight * lDistance * spotEffect;
+			spotDiffuse += diffuse * spotLightColor[ i ] * spotDiffuseWeight * attenuation * spotEffect;
 
 					// specular
 
@@ -117,7 +113,7 @@ vec3 viewPosition = normalize( vViewPosition );
 			float specularNormalization = ( shininess + 2.0 ) / 8.0;
 
 			vec3 schlick = specular + vec3( 1.0 - specular ) * pow( max( 1.0 - dot( lVector, spotHalfVector ), 0.0 ), 5.0 );
-			spotSpecular += schlick * spotLightColor[ i ] * spotSpecularWeight * spotDiffuseWeight * lDistance * specularNormalization * spotEffect;
+			spotSpecular += schlick * spotLightColor[ i ] * spotSpecularWeight * spotDiffuseWeight * attenuation * specularNormalization * spotEffect;
 
 		}
 

+ 2 - 1
src/renderers/shaders/ShaderChunk/lights_phong_pars_fragment.glsl

@@ -21,6 +21,7 @@ uniform vec3 ambientLightColor;
 
 	uniform vec3 pointLightPosition[ MAX_POINT_LIGHTS ];
 	uniform float pointLightDistance[ MAX_POINT_LIGHTS ];
+	uniform float pointLightDecayExponent[ MAX_POINT_LIGHTS ];
 
 #endif
 
@@ -31,8 +32,8 @@ uniform vec3 ambientLightColor;
 	uniform vec3 spotLightDirection[ MAX_SPOT_LIGHTS ];
 	uniform float spotLightAngleCos[ MAX_SPOT_LIGHTS ];
 	uniform float spotLightExponent[ MAX_SPOT_LIGHTS ];
-
 	uniform float spotLightDistance[ MAX_SPOT_LIGHTS ];
+	uniform float spotLightDecayExponent[ MAX_SPOT_LIGHTS ];
 
 #endif
 

+ 3 - 1
src/renderers/shaders/UniformsLib.js

@@ -61,13 +61,15 @@ THREE.UniformsLib = {
 		"pointLightColor" : { type: "fv", value: [] },
 		"pointLightPosition" : { type: "fv", value: [] },
 		"pointLightDistance" : { type: "fv1", value: [] },
+		"pointLightDecayExponent" : { type: "fv1", value: [] },
 
 		"spotLightColor" : { type: "fv", value: [] },
 		"spotLightPosition" : { type: "fv", value: [] },
 		"spotLightDirection" : { type: "fv", value: [] },
 		"spotLightDistance" : { type: "fv1", value: [] },
 		"spotLightAngleCos" : { type: "fv1", value: [] },
-		"spotLightExponent" : { type: "fv1", value: [] }
+		"spotLightExponent" : { type: "fv1", value: [] },
+		"spotLightDecayExponent" : { type: "fv1", value: [] }
 
 	},