فهرست منبع

Lights: Use inverse-square attenuation w/ distance=0 in physically-correct mode.

Don McCurdy 6 سال پیش
والد
کامیت
8c93327d91

+ 13 - 4
docs/api/en/lights/PointLight.html

@@ -45,8 +45,7 @@ scene.add( light );
 		<p>
 			[page:Integer color] - (optional) hexadecimal color of the light. Default is 0xffffff (white).<br />
 			[page:Float intensity] - (optional) numeric value of the light's strength/intensity. Default is 1.<br /><br />
-			[page:Number distance] - The distance from the light where the intensity is 0.
-			When set to 0, then the light never stops. Default is 0.<br />
+			[page:Number distance] - Maximum range of the light. Default is 0 (no limit).<br />
 			[page:Float decay] - The amount the light dims along the distance of the light. Default is 1.
 			For [page:WebGLRenderer.physicallyCorrectLights physically correct] lighting, set this to 2.<br /><br />
 
@@ -67,8 +66,18 @@ scene.add( light );
 
 		<h3>[property:Float distance]</h3>
 		<p>
-			If non-zero, light will attenuate linearly from maximum intensity at the light's
-			position down to zero at this distance from the light. Default is *0.0*.
+			<em>Default mode</em> — When distance is zero, light does not attenuate. When distance is
+			non-zero, light will attenuate linearly from maximum intensity at the light's position down to
+			zero at this distance from the light.
+		</p>
+		<p>
+			<em>[page:WebGLRenderer.physicallyCorrectLights Physically correct] mode</em> — When distance
+			is zero, light will attenuate according to inverse-square law to infinite distance. When
+			distance is non-zero, a more sudden cutoff is applied at this distance from the light, in
+			addition to inverse-square attenuation, limiting the light's range.
+		</p>
+		<p>
+			Default is *0.0*.
 		</p>
 
 		<h3>[property:Boolean isPointLight]</h3>

+ 13 - 4
docs/api/en/lights/SpotLight.html

@@ -71,8 +71,7 @@
 		<p>
 			[page:Integer color] - (optional) hexadecimal color of the light. Default is 0xffffff (white).<br />
 			[page:Float intensity] - (optional) numeric value of the light's strength/intensity. Default is 1.<br /><br />
-			[page:Float distance] - Maximum distance from origin where light will shine whose intensity
-			is attenuated linearly based on distance from origin. <br />
+			[page:Float distance] - Maximum range of the light. Default is 0 (no limit).<br />
 			[page:Radians angle] - Maximum angle of light dispersion from its direction whose upper
 			bound is Math.PI/2.<br />
 			[page:Float penumbra] - Percent of the spotlight cone that is attenuated due to penumbra.
@@ -109,8 +108,18 @@
 
 		<h3>[property:Float distance]</h3>
 		<p>
-			If non-zero, light will attenuate linearly from maximum intensity at the light's
-			position down to zero at this distance from the light. Default is *0.0*.
+			<em>Default mode</em> — When distance is zero, light does not attenuate. When distance is
+			non-zero, light will attenuate linearly from maximum intensity at the light's position down to
+			zero at this distance from the light.
+		</p>
+		<p>
+			<em>[page:WebGLRenderer.physicallyCorrectLights Physically correct] mode</em> — When distance
+			is zero, light will attenuate according to inverse-square law to infinite distance. When
+			distance is non-zero, a more sudden cutoff is applied at this distance from the light, in
+			addition to inverse-square attenuation, limiting the light's range.
+		</p>
+		<p>
+			Default is *0.0*.
 		</p>
 
 		<h3>[property:Boolean isSpotLight]</h3>

+ 18 - 12
src/renderers/shaders/ShaderChunk/bsdfs.glsl

@@ -1,28 +1,34 @@
 float punctualLightIntensityToIrradianceFactor( const in float lightDistance, const in float cutoffDistance, const in float decayExponent ) {
 
-	if( decayExponent > 0.0 ) {
-
 #if defined ( PHYSICALLY_CORRECT_LIGHTS )
 
-		// based upon Frostbite 3 Moving to Physically-based Rendering
-		// page 32, equation 26: E[window1]
-		// https://seblagarde.files.wordpress.com/2015/07/course_notes_moving_frostbite_to_pbr_v32.pdf
-		// this is intended to be used on spot and point lights who are represented as luminous intensity
-		// but who must be converted to luminous irradiance for surface lighting calculation
-		float distanceFalloff = 1.0 / max( pow( lightDistance, decayExponent ), 0.01 );
-		float maxDistanceCutoffFactor = pow2( saturate( 1.0 - pow4( lightDistance / cutoffDistance ) ) );
-		return distanceFalloff * maxDistanceCutoffFactor;
+	// based upon Frostbite 3 Moving to Physically-based Rendering
+	// page 32, equation 26: E[window1]
+	// https://seblagarde.files.wordpress.com/2015/07/course_notes_moving_frostbite_to_pbr_v32.pdf
+	// this is intended to be used on spot and point lights who are represented as luminous intensity
+	// but who must be converted to luminous irradiance for surface lighting calculation
+	float distanceFalloff = 1.0 / max( pow( lightDistance, decayExponent ), 0.01 );
+
+	if( cutoffDistance > 0.0 ) {
+
+		distanceFalloff *= pow2( saturate( 1.0 - pow4( lightDistance / cutoffDistance ) ) );
+
+	}
+
+	return distanceFalloff;
 
 #else
 
-		return pow( saturate( -lightDistance / cutoffDistance + 1.0 ), decayExponent );
+	if( cutoffDistance > 0.0 ) {
 
-#endif
+		return pow( saturate( -lightDistance / cutoffDistance + 1.0 ), decayExponent );
 
 	}
 
 	return 1.0;
 
+#endif
+
 }
 
 vec3 BRDF_Diffuse_Lambert( const in vec3 diffuseColor ) {

+ 2 - 2
src/renderers/webgl/WebGLLights.js

@@ -212,7 +212,7 @@ function WebGLLights() {
 
 				uniforms.coneCos = Math.cos( light.angle );
 				uniforms.penumbraCos = Math.cos( light.angle * ( 1 - light.penumbra ) );
-				uniforms.decay = ( light.distance === 0 ) ? 0.0 : light.decay;
+				uniforms.decay = light.decay;
 
 				uniforms.shadow = light.castShadow;
 
@@ -273,7 +273,7 @@ function WebGLLights() {
 
 				uniforms.color.copy( light.color ).multiplyScalar( light.intensity );
 				uniforms.distance = light.distance;
-				uniforms.decay = ( light.distance === 0 ) ? 0.0 : light.decay;
+				uniforms.decay = light.decay;
 
 				uniforms.shadow = light.castShadow;