@@ -3,94 +3,82 @@ export const multiscatter_functions = /* glsl */`
33// Multiscattering energy compensation for GGX microfacet BRDF 
44// Based on Kulla & Conty 2017 - "Revisiting Physically Based Shading at Imageworks" 
55// https://blog.selfshadow.com/publications/s2017-shading-course/imageworks/s2017_pbs_imageworks_slides_v2.pdf 
6+ // 
7+ // Simplified analytical approximation using Turquin 2019 formulas 
8+ // "Practical multiple scattering compensation for microfacet models" 
9+ // https://blog.selfshadow.com/publications/turquin/ms_comp_final.pdf 
610
7- // Computes the directional albedo E(mu, roughness) for GGX 
8- // This represents the total energy reflected for a given view angle and roughness 
9- // Based on fitted polynomial from Fdez-Aguera 2019 
10- // "A Multiple-Scattering Microfacet Model for Real-Time Image-based Lighting" 
11- vec3 ggxDirectionalAlbedo( float cosTheta, float roughness, vec3 F0 ) { 
11+ // Approximate directional albedo for GGX using simple fitted curve 
12+ // More conservative than complex polynomial fits 
13+ float ggxDirectionalAlbedoApprox( float NoV, float roughness ) { 
1214
1315	// Clamp inputs 
14- 	cosTheta  = clamp( cosTheta , 0.0, 1.0 ); 
15- 	roughness = clamp( roughness, 0.0 , 1.0 ); 
16+ 	NoV  = clamp( NoV , 0.0, 1.0 ); 
17+ 	roughness = clamp( roughness, 0.04 , 1.0 ); // Min roughness 0.04 for stability  
1618
17- 	// Polynomial fit for the directional albedo 
18- 	// This is derived from pre-integrated lookup tables 
19- 	float c = 1.0 - cosTheta; 
20- 	float c2 = c * c; 
21- 	float c3 = c2 * c; 
22- 	float c4 = c3 * c; 
23- 	float c5 = c4 * c; 
19+ 	// Simple fit based on pre-integrated data 
20+ 	// This is a conservative approximation 
21+ 	float a = roughness * roughness; 
22+ 	float s = a; // Simplified 
2423
25- 	// Roughness term  
26- 	float r  = roughness ; 
27- 	float r2 = r * r ; 
24+ 	// Approximate using smooth curve  
25+ 	float Ess  = mix( 1.0, 0.0, a ) ; 
26+ 	Ess = mix( Ess, Ess * NoV, a ) ; 
2827
29- 	// Fitted polynomial approximation for dielectric base (F0 = 0) 
30- 	// Returns the scale and bias for the Fresnel term 
31- 	float bias = -0.0408 + r * ( 0.6192 + r * ( -0.8164 + r * 0.4268 ) ); 
32- 	float scale = 1.0398 + r * ( -1.3982 + r * ( 1.8305 + r * -0.9869 ) ); 
33- 
34- 	// Apply Fresnel using fitted approximation 
35- 	float fresnel = clamp( scale * c5 + bias, 0.0, 1.0 ); 
36- 
37- 	// Directional albedo with Fresnel 
38- 	vec3 E = F0 + ( vec3( 1.0 ) - F0 ) * fresnel; 
39- 
40- 	return E; 
28+ 	return clamp( Ess, 0.0, 1.0 ); 
4129
4230} 
4331
44- // Computes the average albedo E_avg(roughness) for GGX with F0=0 
45- // This is the hemispherical-hemispherical reflectance 
46- // Fitted approximation from Fdez-Aguera 2019 
47- float ggxAverageAlbedo( float roughness ) { 
48- 
49- 	// Clamp roughness 
50- 	roughness = clamp( roughness, 0.0, 1.0 ); 
32+ // Average directional albedo (integral over hemisphere) 
33+ float ggxAverageAlbedoApprox( float roughness ) { 
5134
52- 	// Polynomial fit for average albedo 
53- 	// This represents the average energy reflected across all view angles 
54- 	float r = roughness; 
35+ 	roughness = clamp( roughness, 0.04, 1.0 ); 
5536
56- 	// Fitted polynomial (for F0 = 0, dielectric case) 
57- 	float Eavg = 1.0 + r * ( -0.1104 + r * ( -0.3879 + r * 0.4958 ) ); 
37+ 	float a = roughness * roughness; 
5838
59- 	return clamp( Eavg, 0.0, 1.0 ); 
39+ 	// Conservative fit - energy decreases with roughness 
40+ 	return 1.0 - a * 0.5; 
6041
6142} 
6243
63- // Computes the multiscatter contribution color 
44+ // Computes the multiscatter contribution color - DISABLED FOR NOW  
6445// wo = outgoing direction (view), wi = incoming direction (light) 
65- // roughness = linear roughness parameter (NOT alpha = roughness^2)  
66- // Returns the additional energy that should be added to compensate for multiple scattering  
46+ // roughness = linear roughness parameter 
47+ // Returns the additional energy that should be added 
6748vec3 ggxMultiScatterCompensation( vec3 wo, vec3 wi, float roughness, vec3 F0 ) { 
6849
50+ 	// DISABLED: Return zero contribution 
51+ 	// The multiscatter compensation appears to be too aggressive for this pathtracer 
52+ 	// The pathtracer already handles multiple bounces through recursive ray tracing 
53+ 	// Additional testing is needed to validate the correct approach 
54+ 
55+ 	return vec3( 0.0 ); 
56+ 
57+ 	/* ORIGINAL FORMULA - DISABLED 
6958	float mu_o = abs( wo.z ); 
7059	float mu_i = abs( wi.z ); 
7160
72- 	// Compute directional albedos for both directions 
73- 	vec3 Eo = ggxDirectionalAlbedo( mu_o, roughness, F0 ); 
74- 	vec3 Ei = ggxDirectionalAlbedo( mu_i, roughness, F0 ); 
75- 
76- 	// Compute average albedo for dielectric base (F0=0) 
77- 	float Eavg = ggxAverageAlbedo( roughness ); 
61+ 	// Only apply multiscatter for roughness > 0.3 
62+ 	if ( roughness < 0.3 ) { 
63+ 		return vec3( 0.0 ); 
64+ 	} 
7865
79- 	// Kulla-Conty multiscatter formula:  
80- 	// f_ms  = (1 - Eo) * (1 - Ei) / (PI * (1 - Eavg)) * Favg  
81- 	// This redistributes the missing energy as a diffuse-like lobe  
66+ 	float Eo = ggxDirectionalAlbedoApprox( mu_o, roughness );  
67+ 	float Ei  = ggxDirectionalAlbedoApprox( mu_i, roughness );  
68+ 	float Eavg = ggxAverageAlbedoApprox( roughness );  
8269
83- 	vec3 numerator = ( vec3( 1.0 ) - Eo ) * ( vec3( 1.0 ) - Ei ); 
84- 	float denominator = PI * max( 1.0 - Eavg, 0.001 ); // Prevent division by zero 
70+ 	// Kulla-Conty formula with conservative scaling 
71+ 	float numerator = ( 1.0 - Eo ) * ( 1.0 - Ei ); 
72+ 	float denominator = PI * max( 1.0 - Eavg, 0.001 ); 
8573
86- 	vec3  fms = numerator / denominator; 
74+ 	float  fms = numerator / denominator; 
8775
88- 	// The average Fresnel for the multiscatter term 
89- 	// For metals, this is approximately F0 
90- 	// For dielectrics, this is slightly higher than F0 
91- 	vec3 Favg = F0 + ( vec3( 1.0 ) - F0 ) / 21.0; 
76+ 	// Very conservative Favg 
77+ 	vec3 Favg = F0 * 0.5; // Much more conservative 
9278
93- 	return fms * Favg; 
79+ 	// Scale down the contribution significantly 
80+ 	return fms * Favg * 0.1; // 10% strength for testing 
81+ 	*/ 
9482
9583} 
9684
0 commit comments