Преглед изворни кода

Renderers: Optimize DFG LUT sampling. (#34055)

Michael Herzog пре 1 недеља
родитељ
комит
7025d4ce1a

+ 15 - 6
src/nodes/functions/PhysicalLightingModel.js

@@ -473,6 +473,14 @@ class PhysicalLightingModel extends LightingModel {
 		 */
 		this.iridescenceF0Metallic = null;
 
+		/**
+		 * The sampled DFG LUT value, shared by the direct and indirect lighting paths.
+		 *
+		 * @type {?Node}
+		 * @default null
+		 */
+		this.dfg = null;
+
 		/**
 		 * The multi-scattering energy compensation for direct lighting.
 		 *
@@ -565,14 +573,17 @@ class PhysicalLightingModel extends LightingModel {
 
 		}
 
+		//
+
+		const dotNV = normalView.dot( positionViewDirection ).clamp();
+		this.dfg = DFGLUT( { roughness, dotNV } ).toConst( 'dfg' );
+
 		// Multi-scattering energy compensation for direct lighting
 		// Based on "Practical Multiple Scattering Compensation for Microfacet Models"
 		// https://blog.selfshadow.com/publications/turquin/ms_comp_final.pdf
-		const dotNV = normalView.dot( positionViewDirection ).clamp();
-		const fab = DFGLUT( { roughness, dotNV } );
 
 		// Energy of the single-scattering lobe in a white furnace ( F0 = F90 = 1 )
-		const Ess = fab.x.add( fab.y );
+		const Ess = this.dfg.x.add( this.dfg.y );
 
 		// Compensate for the energy lost to multiple scattering, tinting the added term by F0 ( equation 16 )
 		this.multiScatteringCompensation = specularColorBlended.mul( Ess.reciprocal().sub( 1.0 ) ).add( 1.0 ).toConst( 'multiScatteringCompensation' );
@@ -587,9 +598,7 @@ class PhysicalLightingModel extends LightingModel {
 
 	computeMultiscattering( singleScatter, multiScatter, specularF90, f0, iridescenceF0 = null ) {
 
-		const dotNV = normalView.dot( positionViewDirection ).clamp(); // @ TODO: Move to core dotNV
-
-		const fab = DFGLUT( { roughness, dotNV } );
+		const fab = this.dfg;
 
 		const Fr = iridescenceF0 ? iridescence.mix( f0, iridescenceF0 ) : f0;
 

+ 14 - 9
src/renderers/shaders/ShaderChunk/lights_fragment_begin.glsl.js

@@ -54,20 +54,25 @@ vec3 geometryClearcoatNormal = vec3( 0.0 );
 
 #endif
 
-#if defined( STANDARD ) && ( NUM_DIR_LIGHTS > 0 || NUM_POINT_LIGHTS > 0 || NUM_SPOT_LIGHTS > 0 )
+#ifdef STANDARD
 
-	// Multi-scattering energy compensation for direct lighting
-	// Based on "Practical Multiple Scattering Compensation for Microfacet Models"
-	// https://blog.selfshadow.com/publications/turquin/ms_comp_final.pdf
 	float dotNVms = saturate( dot( geometryNormal, geometryViewDir ) );
 
-	vec2 fabMs = texture2D( dfgLUT, vec2( material.roughness, dotNVms ) ).rg;
+	material.dfg = texture2D( dfgLUT, vec2( material.roughness, dotNVms ) ).rg;
 
-	// Energy of the single-scattering lobe in a white furnace ( F0 = F90 = 1 )
-	float EssMs = fabMs.x + fabMs.y;
+	#if ( NUM_DIR_LIGHTS > 0 || NUM_POINT_LIGHTS > 0 || NUM_SPOT_LIGHTS > 0 )
 
-	// Compensate for the energy lost to multiple scattering, tinting the added term by F0 ( equation 16 )
-	material.multiScatteringCompensation = 1.0 + material.specularColorBlended * ( 1.0 / EssMs - 1.0 );
+		// Multi-scattering energy compensation for direct lighting
+		// Based on "Practical Multiple Scattering Compensation for Microfacet Models"
+		// https://blog.selfshadow.com/publications/turquin/ms_comp_final.pdf
+
+		// Energy of the single-scattering lobe in a white furnace ( F0 = F90 = 1 )
+		float EssMs = material.dfg.x + material.dfg.y;
+
+		// Compensate for the energy lost to multiple scattering, tinting the added term by F0 ( equation 16 )
+		material.multiScatteringCompensation = 1.0 + material.specularColorBlended * ( 1.0 / EssMs - 1.0 );
+
+	#endif
 
 #endif
 

+ 9 - 11
src/renderers/shaders/ShaderChunk/lights_physical_pars_fragment.glsl.js

@@ -13,6 +13,7 @@ struct PhysicalMaterial {
 	float metalness;
 	float specularF90;
 	float dispersion;
+	vec2 dfg;
 	vec3 multiScatteringCompensation;
 
 	#ifdef USE_RETROREFLECTIVE
@@ -391,14 +392,11 @@ vec3 EnvironmentBRDF( const in vec3 normal, const in vec3 viewDir, const in vec3
 // Approximates multiscattering in order to preserve energy.
 // http://www.jcgt.org/published/0008/01/03/
 #ifdef USE_IRIDESCENCE
-void computeMultiscatteringIridescence( const in vec3 normal, const in vec3 viewDir, const in vec3 specularColor, const in float specularF90, const in float iridescence, const in vec3 iridescenceF0, const in float roughness, inout vec3 singleScatter, inout vec3 multiScatter ) {
+void computeMultiscatteringIridescence( const in vec2 fab, const in vec3 specularColor, const in float specularF90, const in float iridescence, const in vec3 iridescenceF0, inout vec3 singleScatter, inout vec3 multiScatter ) {
 #else
-void computeMultiscattering( const in vec3 normal, const in vec3 viewDir, const in vec3 specularColor, const in float specularF90, const in float roughness, inout vec3 singleScatter, inout vec3 multiScatter ) {
+void computeMultiscattering( const in vec2 fab, const in vec3 specularColor, const in float specularF90, inout vec3 singleScatter, inout vec3 multiScatter ) {
 #endif
 
-	float dotNV = saturate( dot( normal, viewDir ) );
-	vec2 fab = texture2D( dfgLUT, vec2( roughness, dotNV ) ).rg;
-
 	#ifdef USE_IRIDESCENCE
 
 		vec3 Fr = mix( specularColor, iridescenceF0, iridescence );
@@ -546,11 +544,11 @@ void RE_IndirectDiffuse_Physical( const in vec3 irradiance, const in vec3 geomet
 
 	#ifdef USE_IRIDESCENCE
 
-		computeMultiscatteringIridescence( geometryNormal, geometryViewDir, material.specularColor, material.specularF90, material.iridescence, material.iridescenceF0Dielectric, material.roughness, singleScattering, multiScattering );
+		computeMultiscatteringIridescence( material.dfg, material.specularColor, material.specularF90, material.iridescence, material.iridescenceF0Dielectric, singleScattering, multiScattering );
 
 	#else
 
-		computeMultiscattering( geometryNormal, geometryViewDir, material.specularColor, material.specularF90, material.roughness, singleScattering, multiScattering );
+		computeMultiscattering( material.dfg, material.specularColor, material.specularF90, singleScattering, multiScattering );
 
 	#endif
 
@@ -597,13 +595,13 @@ void RE_IndirectSpecular_Physical( const in vec3 radiance, const in vec3 irradia
 
 	#ifdef USE_IRIDESCENCE
 
-		computeMultiscatteringIridescence( geometryNormal, geometryViewDir, material.specularColor, material.specularF90, material.iridescence, material.iridescenceF0Dielectric, material.roughness, singleScatteringDielectric, multiScatteringDielectric );
-		computeMultiscatteringIridescence( geometryNormal, geometryViewDir, material.diffuseColor, material.specularF90, material.iridescence, material.iridescenceF0Metallic, material.roughness, singleScatteringMetallic, multiScatteringMetallic );
+		computeMultiscatteringIridescence( material.dfg, material.specularColor, material.specularF90, material.iridescence, material.iridescenceF0Dielectric, singleScatteringDielectric, multiScatteringDielectric );
+		computeMultiscatteringIridescence( material.dfg, material.diffuseColor, material.specularF90, material.iridescence, material.iridescenceF0Metallic, singleScatteringMetallic, multiScatteringMetallic );
 
 	#else
 
-		computeMultiscattering( geometryNormal, geometryViewDir, material.specularColor, material.specularF90, material.roughness, singleScatteringDielectric, multiScatteringDielectric );
-		computeMultiscattering( geometryNormal, geometryViewDir, material.diffuseColor, material.specularF90, material.roughness, singleScatteringMetallic, multiScatteringMetallic );
+		computeMultiscattering( material.dfg, material.specularColor, material.specularF90, singleScatteringDielectric, multiScatteringDielectric );
+		computeMultiscattering( material.dfg, material.diffuseColor, material.specularF90, singleScatteringMetallic, multiScatteringMetallic );
 
 	#endif
 

粤ICP备19079148号