Browse Source

Merge pull request #7523 from WestLangley/dev-pi

Restored factor of PI to BRDFs
Mr.doob 9 năm trước cách đây
mục cha
commit
54fa941616

+ 3 - 13
src/renderers/shaders/ShaderChunk/bsdfs.glsl

@@ -13,9 +13,7 @@ float calcLightAttenuation( const in float lightDistance, const in float cutoffD
 
 vec3 BRDF_Diffuse_Lambert( const in vec3 diffuseColor ) {
 
-	// factor of 1/PI in BRDF omitted as incoming light intensity is scaled up by PI because it is considered a punctual light source
-
-	return diffuseColor;
+	return RECIPROCAL_PI * diffuseColor;
 
 } // validated
 
@@ -56,21 +54,17 @@ float G_GGX_Smith( const in float alpha, const in float dotNL, const in float do
 // alpha is "roughness squared" in Disney’s reparameterization
 float D_GGX( const in float alpha, const in float dotNH ) {
 
-	// factor of 1/PI in distribution term omitted as incoming light intensity is scaled up by PI because it is considered a punctual light source
-
 	float a2 = alpha * alpha;
 
 	float denom = dotNH * dotNH * ( a2 - 1.0 ) + 1.0; // avoid alpha = 0 with dotNH = 1
 
-	return a2 / ( denom * denom );
+	return RECIPROCAL_PI * a2 / ( denom * denom );
 
 }
 
 
 // GGX Distribution, Schlick Fresnel, GGX-Smith Visibility
 vec3 BRDF_Specular_GGX( const in IncidentLight incidentLight, const in GeometricContext geometry, const in vec3 specularColor, const in float roughness ) {
-	
-	// factor of 1/PI in BRDF omitted (normally it is in D_GGX) as incoming light intensity is scaled up by PI because it is considered a punctual light source
 
 	float alpha = roughness * roughness; // UE4's roughness
 
@@ -121,16 +115,12 @@ float G_BlinnPhong_Implicit( /* const in float dotNL, const in float dotNV */ )
 
 float D_BlinnPhong( const in float shininess, const in float dotNH ) {
 
-	// factor of 1/PI in distribution term omitted as incoming light intensity is scaled up by PI because it is considered a punctual light source
-
-	return ( shininess * 0.5 + 1.0 ) * pow( dotNH, shininess );
+	return RECIPROCAL_PI * ( shininess * 0.5 + 1.0 ) * pow( dotNH, shininess );
 
 }
 
 vec3 BRDF_Specular_BlinnPhong( const in IncidentLight incidentLight, const in GeometricContext geometry, const in vec3 specularColor, const in float shininess ) {
 
-	// factor of 1/PI in BRDF omitted (normally it is in D_BlinnPhong) as incoming light intensity is scaled up by PI because it is considered a punctual light source
-
 	vec3 halfDir = normalize( incidentLight.direction + geometry.viewDir );
 
 	//float dotNL = saturate( dot( geometry.normal, incidentLight.direction ) );

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

@@ -16,7 +16,7 @@ vLightFront = vec3( 0.0 );
 		IncidentLight directLight = getPointDirectLight( pointLights[ i ], geometry );
 
 		float dotNL = dot( geometry.normal, directLight.direction );
-		vec3 directLightColor_Diffuse = directLight.color * BRDF_Diffuse_Lambert( diffuse );
+		vec3 directLightColor_Diffuse = PI * directLight.color;
 
 		vLightFront += saturate( dotNL ) * directLightColor_Diffuse;
 
@@ -37,7 +37,7 @@ vLightFront = vec3( 0.0 );
 		IncidentLight directLight = getSpotDirectLight( spotLights[ i ], geometry );
 
 		float dotNL = dot( geometry.normal, directLight.direction );
-		vec3 directLightColor_Diffuse = directLight.color * BRDF_Diffuse_Lambert( diffuse );
+		vec3 directLightColor_Diffuse = PI * directLight.color;
 
 		vLightFront += saturate( dotNL ) * directLightColor_Diffuse;
 
@@ -57,7 +57,7 @@ vLightFront = vec3( 0.0 );
 		IncidentLight directLight = getDirectionalDirectLight( directionalLights[ i ], geometry );
 
 		float dotNL = dot( geometry.normal, directLight.direction );
-		vec3 directLightColor_Diffuse = directLight.color * BRDF_Diffuse_Lambert( diffuse );
+		vec3 directLightColor_Diffuse = PI * directLight.color;
 
 		vLightFront += saturate( dotNL ) * directLightColor_Diffuse;
 
@@ -72,15 +72,12 @@ vLightFront = vec3( 0.0 );
 #endif
 
 	{
-		// dotNL is always one, and diffuseColor is vec3(1.0), thus the result is equivalent to summing indirectDiffuse lights
-		//float frontDotNL = saturate( dot( geometry.normal, frontIndirectLight.direction ) );
-		//vLightFront += frontDotNL * frontIndirectLight.color * BRDF_Diffuse_Lambert( diffuse );
 
-		vLightFront += ambientLightColor;
+		vLightFront += PI * ambientLightColor;
 
 		#ifdef DOUBLE_SIDED
 
-			vLightBack += ambientLightColor;
+			vLightBack += PI * ambientLightColor;
 
 		#endif
 
@@ -88,11 +85,11 @@ vLightFront = vec3( 0.0 );
 
 			for ( int i = 0; i < MAX_HEMI_LIGHTS; i ++ ) {
 
-				vLightFront += getHemisphereIndirectLightColor( hemisphereLights[ i ], geometry );
+				vLightFront += getHemisphereLightIrradiance( hemisphereLights[ i ], geometry );
 
 				#ifdef DOUBLE_SIDED
 
-					vLightBack += getHemisphereIndirectLightColor( hemisphereLights[ i ], backGeometry );
+					vLightBack += getHemisphereLightIrradiance( hemisphereLights[ i ], backGeometry );
 
 				#endif
 

+ 11 - 6
src/renderers/shaders/ShaderChunk/lights_pars.glsl

@@ -1,5 +1,11 @@
 uniform vec3 ambientLightColor;
 
+vec3 getAmbientLightIrradiance( const in vec3 ambientLightColor ) {
+
+
+	return PI * ambientLightColor;
+
+}
 
 #if MAX_DIR_LIGHTS > 0
 
@@ -104,12 +110,12 @@ uniform vec3 ambientLightColor;
 
 	uniform HemisphereLight hemisphereLights[ MAX_HEMI_LIGHTS ];
 
-	vec3 getHemisphereIndirectLightColor( const in HemisphereLight hemiLight, const in GeometricContext geometry ) {
+	vec3 getHemisphereLightIrradiance( const in HemisphereLight hemiLight, const in GeometricContext geometry ) {
 
 		float dotNL = dot( geometry.normal, hemiLight.direction );
 		float hemiDiffuseWeight = 0.5 * dotNL + 0.5;
 
-		return mix( hemiLight.groundColor, hemiLight.skyColor, hemiDiffuseWeight );
+		return PI * mix( hemiLight.groundColor, hemiLight.skyColor, hemiDiffuseWeight );
 
 	}
 
@@ -118,8 +124,7 @@ uniform vec3 ambientLightColor;
 
 #if defined( USE_ENVMAP ) && defined( PHYSICAL )
 
-
-	vec3 getDiffuseLightProbeIndirectLightColor( /*const in SpecularLightProbe specularLightProbe,*/ const in GeometricContext geometry, const in int maxMIPLevel ) {
+	vec3 getLightProbeIndirectIrradiance( /*const in SpecularLightProbe specularLightProbe,*/ const in GeometricContext geometry, const in int maxMIPLevel ) {
 
 		#ifdef DOUBLE_SIDED
 
@@ -158,7 +163,7 @@ uniform vec3 ambientLightColor;
 
 		envMapColor.rgb = inputToLinear( envMapColor.rgb );
 
-		return envMapColor.rgb;
+		return PI * envMapColor.rgb;
 
 	}
 
@@ -176,7 +181,7 @@ uniform vec3 ambientLightColor;
 
 	}
 
-	vec3 getSpecularLightProbeIndirectLightColor( /*const in SpecularLightProbe specularLightProbe,*/ const in GeometricContext geometry, const in float blinnShininessExponent, const in int maxMIPLevel ) {
+	vec3 getLightProbeIndirectRadiance( /*const in SpecularLightProbe specularLightProbe,*/ const in GeometricContext geometry, const in float blinnShininessExponent, const in int maxMIPLevel ) {
 
 		#ifdef ENVMAP_MODE_REFLECTION
 

+ 6 - 4
src/renderers/shaders/ShaderChunk/lights_phong_pars_fragment.glsl

@@ -24,17 +24,19 @@ void BlinnPhongMaterial_RE_DirectLight( const in IncidentLight directLight, cons
 
 	float dotNL = saturate( dot( geometry.normal, directLight.direction ) );
 
-	reflectedLight.directDiffuse += dotNL * directLight.color * BRDF_Diffuse_Lambert( material.diffuseColor );
+	vec3 irradiance = dotNL * PI * directLight.color; // punctual light
 
-	reflectedLight.directSpecular += dotNL * directLight.color * BRDF_Specular_BlinnPhong( directLight, geometry, material.specularColor, material.specularShininess ) * material.specularStrength;
+	reflectedLight.directDiffuse += irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );
+
+	reflectedLight.directSpecular += irradiance * BRDF_Specular_BlinnPhong( directLight, geometry, material.specularColor, material.specularShininess ) * material.specularStrength;
 
 }
 
 #define Material_RE_DirectLight    BlinnPhongMaterial_RE_DirectLight
 
-void BlinnPhongMaterial_RE_IndirectDiffuseLight( const in vec3 indirectDiffuseColor, const in GeometricContext geometry, const in BlinnPhongMaterial material, inout ReflectedLight reflectedLight ) {
+void BlinnPhongMaterial_RE_IndirectDiffuseLight( const in vec3 irradiance, const in GeometricContext geometry, const in BlinnPhongMaterial material, inout ReflectedLight reflectedLight ) {
 
-	reflectedLight.indirectDiffuse += indirectDiffuseColor * BRDF_Diffuse_Lambert( material.diffuseColor );
+	reflectedLight.indirectDiffuse += irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );
 
 }
 

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

@@ -10,25 +10,29 @@ void PhysicalMaterial_RE_DirectLight( const in IncidentLight directLight, const
 
 	float dotNL = saturate( dot( geometry.normal, directLight.direction ) );
 
-	reflectedLight.directDiffuse += dotNL * directLight.color * BRDF_Diffuse_Lambert( material.diffuseColor );
-	reflectedLight.directSpecular += dotNL * directLight.color * BRDF_Specular_GGX( directLight, geometry, material.specularColor, material.specularRoughness );
+	vec3 irradiance = dotNL * PI * directLight.color; // punctual light
+
+	reflectedLight.directDiffuse += irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );
+
+	reflectedLight.directSpecular += irradiance * BRDF_Specular_GGX( directLight, geometry, material.specularColor, material.specularRoughness );
 	
 }
+
 #define Material_RE_DirectLight    PhysicalMaterial_RE_DirectLight
 
 
-void PhysicalMaterial_RE_DiffuseIndirectLight( const in vec3 indirectDiffuseColor, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {
+void PhysicalMaterial_RE_DiffuseIndirectLight( const in vec3 irradiance, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {
 
-	reflectedLight.indirectDiffuse += indirectDiffuseColor * BRDF_Diffuse_Lambert( material.diffuseColor );
+	reflectedLight.indirectDiffuse += irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );
 
 }
 
 #define Material_RE_IndirectDiffuseLight    PhysicalMaterial_RE_DiffuseIndirectLight
 
 
-void PhysicalMaterial_RE_SpecularIndirectLight( const in vec3 indirectSpecularColor, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {
+void PhysicalMaterial_RE_SpecularIndirectLight( const in vec3 radiance, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {
 
-    reflectedLight.indirectSpecular += indirectSpecularColor * BRDF_Specular_GGX_Environment( geometry, material.specularColor, material.specularRoughness );
+    reflectedLight.indirectSpecular += radiance * BRDF_Specular_GGX_Environment( geometry, material.specularColor, material.specularRoughness );
 
 }
 

+ 7 - 7
src/renderers/shaders/ShaderChunk/lights_template.glsl

@@ -55,11 +55,11 @@ GeometricContext geometry = GeometricContext( -vViewPosition, normalize( normal
 
 	{
 	
-		vec3 indirectDiffuseColor = ambientLightColor;
+		vec3 indirectDiffuseIrradiance = getAmbientLightIrradiance( ambientLightColor );
 
 #ifdef USE_LIGHTMAP
 
-		indirectDiffuseColor += texture2D( lightMap, vUv2 ).xyz * lightMapIntensity;
+		indirectDiffuseIrradiance += PI * texture2D( lightMap, vUv2 ).xyz * lightMapIntensity; // factor of PI should not be present; included here to prevent breakage
 
 #endif
 
@@ -67,7 +67,7 @@ GeometricContext geometry = GeometricContext( -vViewPosition, normalize( normal
 
 		for ( int i = 0; i < MAX_HEMI_LIGHTS; i ++ ) {
 
-			indirectDiffuseColor += getHemisphereIndirectLightColor( hemisphereLights[ i ], geometry );
+			indirectDiffuseIrradiance += getHemisphereLightIrradiance( hemisphereLights[ i ], geometry );
 
 		}
 
@@ -76,11 +76,11 @@ GeometricContext geometry = GeometricContext( -vViewPosition, normalize( normal
 #if defined( USE_ENVMAP ) && defined( PHYSICAL )
 
 		// TODO, replace 8 with the real maxMIPLevel
-		indirectDiffuseColor += getDiffuseLightProbeIndirectLightColor( /*lightProbe,*/ geometry, 8 );
+		indirectDiffuseIrradiance += getLightProbeIndirectIrradiance( /*lightProbe,*/ geometry, 8 );
 
 #endif
 
-		Material_RE_IndirectDiffuseLight( indirectDiffuseColor, geometry, material, reflectedLight );
+		Material_RE_IndirectDiffuseLight( indirectDiffuseIrradiance, geometry, material, reflectedLight );
 
 	}
 
@@ -91,9 +91,9 @@ GeometricContext geometry = GeometricContext( -vViewPosition, normalize( normal
 	{
 
 		// TODO, replace 8 with the real maxMIPLevel
-		vec3 indirectSpecularColor = getSpecularLightProbeIndirectLightColor( /*specularLightProbe,*/ geometry, Material_BlinnShininessExponent( material ), 8 );
+		vec3 indirectSpecularRadiance = getLightProbeIndirectRadiance( /*specularLightProbe,*/ geometry, Material_BlinnShininessExponent( material ), 8 );
 
-		Material_RE_IndirectSpecularLight( indirectSpecularColor, geometry, material, reflectedLight );
+		Material_RE_IndirectSpecularLight( indirectSpecularRadiance, geometry, material, reflectedLight );
 
     }
 

+ 3 - 4
src/renderers/shaders/ShaderLib.js

@@ -216,7 +216,6 @@ THREE.ShaderLib = {
 
 			"	vec3 outgoingLight = vec3( 0.0 );",	// outgoing light does not have an alpha, the surface does
 			"	vec4 diffuseColor = vec4( diffuse, opacity );",
-			"	vec3 totalAmbientLight = ambientLightColor;",
 			"	vec3 shadowMask = vec3( 1.0 );",
 
 				THREE.ShaderChunk[ "logdepthbuf_fragment" ],
@@ -230,13 +229,13 @@ THREE.ShaderLib = {
 			"	#ifdef DOUBLE_SIDED",
 
 			"		if ( gl_FrontFacing )",
-			"			outgoingLight += diffuseColor.rgb * ( vLightFront * shadowMask ) + emissive;",
+			"			outgoingLight += RECIPROCAL_PI * diffuseColor.rgb * ( vLightFront * shadowMask ) + emissive;",
 			"		else",
-			"			outgoingLight += diffuseColor.rgb * ( vLightBack * shadowMask ) + emissive;",
+			"			outgoingLight += RECIPROCAL_PI * diffuseColor.rgb * ( vLightBack * shadowMask ) + emissive;",
 
 			"	#else",
 
-			"		outgoingLight += diffuseColor.rgb * ( vLightFront * shadowMask ) + emissive;",
+			"		outgoingLight += RECIPROCAL_PI * diffuseColor.rgb * ( vLightFront * shadowMask ) + emissive;",
 
 			"	#endif",