2
0
Эх сурвалжийг харах

Merge pull request #22415 from WestLangley/dev_shaders_attenuation

Shaders: refactored light attenuation code
WestLangley 3 жил өмнө
parent
commit
fb43e1fe4f

+ 2 - 4
examples/jsm/renderers/nodes/functions/BSDFs.js

@@ -32,16 +32,14 @@ vec3 BRDF_Lambert( const in vec3 diffuseColor ) {
 
 }` ); // validated
 
-export const punctualLightIntensityToIrradianceFactor = new FunctionNode( `
-float punctualLightIntensityToIrradianceFactor( float lightDistance, float cutoffDistance, float decayExponent ) {
+export const getDistanceAttenuation = new FunctionNode( `
+float getDistanceAttenuation( float lightDistance, float cutoffDistance, float decayExponent ) {
 
 #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 );
 
 	if( cutoffDistance > 0.0 ) {

+ 3 - 3
examples/jsm/renderers/nodes/lights/LightNode.js

@@ -6,7 +6,7 @@ import FloatNode from '../inputs/FloatNode.js';
 import OperatorNode from '../math/OperatorNode.js';
 import MathNode from '../math/MathNode.js';
 import { NodeUpdateType } from '../core/constants.js';
-import { punctualLightIntensityToIrradianceFactor } from '../functions/BSDFs.js';
+import { getDistanceAttenuation } from '../functions/BSDFs.js';
 
 import { Color } from 'three';
 
@@ -34,13 +34,13 @@ class LightNode extends Node {
 
 		this.lightDistance = new MathNode( MathNode.LENGTH, this.lVector );
 
-		this.lightIntensity = punctualLightIntensityToIrradianceFactor.call( {
+		this.lightAttenuation = getDistanceAttenuation.call( {
 			lightDistance: this.lightDistance,
 			cutoffDistance: this.lightCutoffDistance,
 			decayExponent: this.lightDecayExponent
 		} );
 
-		this.lightColor = new OperatorNode( '*', this.color, this.lightIntensity );
+		this.lightColor = new OperatorNode( '*', this.color, this.lightAttenuation );
 
 	}
 

+ 0 - 33
src/renderers/shaders/ShaderChunk/bsdfs.glsl.js

@@ -1,38 +1,5 @@
 export default /* glsl */`
 
-float punctualLightIntensityToIrradianceFactor( const in float lightDistance, const in float cutoffDistance, const in float decayExponent ) {
-
-#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 );
-
-	if( cutoffDistance > 0.0 ) {
-
-		distanceFalloff *= pow2( saturate( 1.0 - pow4( lightDistance / cutoffDistance ) ) );
-
-	}
-
-	return distanceFalloff;
-
-#else
-
-	if( cutoffDistance > 0.0 && decayExponent > 0.0 ) {
-
-		return pow( saturate( - lightDistance / cutoffDistance + 1.0 ), decayExponent );
-
-	}
-
-	return 1.0;
-
-#endif
-
-}
-
 vec3 BRDF_Lambert( const in vec3 diffuseColor ) {
 
 	return RECIPROCAL_PI * diffuseColor;

+ 63 - 22
src/renderers/shaders/ShaderChunk/lights_pars_begin.glsl.js

@@ -48,6 +48,43 @@ vec3 getAmbientLightIrradiance( const in vec3 ambientLightColor ) {
 
 }
 
+float getDistanceAttenuation( const in float lightDistance, const in float cutoffDistance, const in float decayExponent ) {
+
+	#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
+		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
+
+		if ( cutoffDistance > 0.0 && decayExponent > 0.0 ) {
+
+			return pow( saturate( - lightDistance / cutoffDistance + 1.0 ), decayExponent );
+
+		}
+
+		return 1.0;
+
+	#endif
+
+}
+
+float getSpotAttenuation( const in float coneCosine, const in float penumbraCosine, const in float angleCosine ) {
+
+	return smoothstep( coneCosine, penumbraCosine, angleCosine );
+
+}
+
 #if NUM_DIR_LIGHTS > 0
 
 	struct DirectionalLight {
@@ -57,11 +94,11 @@ vec3 getAmbientLightIrradiance( const in vec3 ambientLightColor ) {
 
 	uniform DirectionalLight directionalLights[ NUM_DIR_LIGHTS ];
 
-	void getDirectionalLightInfo( const in DirectionalLight directionalLight, const in GeometricContext geometry, out IncidentLight directLight ) {
+	void getDirectionalLightInfo( const in DirectionalLight directionalLight, const in GeometricContext geometry, out IncidentLight light ) {
 
-		directLight.color = directionalLight.color;
-		directLight.direction = directionalLight.direction;
-		directLight.visible = true;
+		light.color = directionalLight.color;
+		light.direction = directionalLight.direction;
+		light.visible = true;
 
 	}
 
@@ -79,17 +116,18 @@ vec3 getAmbientLightIrradiance( const in vec3 ambientLightColor ) {
 
 	uniform PointLight pointLights[ NUM_POINT_LIGHTS ];
 
-	// directLight is an out parameter as having it as a return value caused compiler errors on some devices
-	void getPointLightInfo( const in PointLight pointLight, const in GeometricContext geometry, out IncidentLight directLight ) {
+	// light is an out parameter as having it as a return value caused compiler errors on some devices
+	void getPointLightInfo( const in PointLight pointLight, const in GeometricContext geometry, out IncidentLight light ) {
 
 		vec3 lVector = pointLight.position - geometry.position;
-		directLight.direction = normalize( lVector );
+
+		light.direction = normalize( lVector );
 
 		float lightDistance = length( lVector );
 
-		directLight.color = pointLight.color;
-		directLight.color *= punctualLightIntensityToIrradianceFactor( lightDistance, pointLight.distance, pointLight.decay );
-		directLight.visible = ( directLight.color != vec3( 0.0 ) );
+		light.color = pointLight.color;
+		light.color *= getDistanceAttenuation( lightDistance, pointLight.distance, pointLight.decay );
+		light.visible = ( light.color != vec3( 0.0 ) );
 
 	}
 
@@ -110,29 +148,32 @@ vec3 getAmbientLightIrradiance( const in vec3 ambientLightColor ) {
 
 	uniform SpotLight spotLights[ NUM_SPOT_LIGHTS ];
 
-	// directLight is an out parameter as having it as a return value caused compiler errors on some devices
-	void getSpotLightInfo( const in SpotLight spotLight, const in GeometricContext geometry, out IncidentLight directLight ) {
+	// light is an out parameter as having it as a return value caused compiler errors on some devices
+	void getSpotLightInfo( const in SpotLight spotLight, const in GeometricContext geometry, out IncidentLight light ) {
 
 		vec3 lVector = spotLight.position - geometry.position;
-		directLight.direction = normalize( lVector );
 
-		float lightDistance = length( lVector );
-		float angleCos = dot( directLight.direction, spotLight.direction );
+		light.direction = normalize( lVector );
 
-		if ( angleCos > spotLight.coneCos ) {
+		float angleCos = dot( light.direction, spotLight.direction );
 
-			float spotEffect = smoothstep( spotLight.coneCos, spotLight.penumbraCos, angleCos );
+		float spotAttenuation = getSpotAttenuation( spotLight.coneCos, spotLight.penumbraCos, angleCos );
 
-			directLight.color = spotLight.color;
-			directLight.color *= spotEffect * punctualLightIntensityToIrradianceFactor( lightDistance, spotLight.distance, spotLight.decay );
-			directLight.visible = true;
+		if ( spotAttenuation > 0.0 ) {
+
+			float lightDistance = length( lVector );
+
+			light.color = spotLight.color * spotAttenuation;
+			light.color *= getDistanceAttenuation( lightDistance, spotLight.distance, spotLight.decay );
+			light.visible = ( light.color != vec3( 0.0 ) );
 
 		} else {
 
-			directLight.color = vec3( 0.0 );
-			directLight.visible = false;
+			light.color = vec3( 0.0 );
+			light.visible = false;
 
 		}
+
 	}
 
 #endif