WestLangley 3 gadi atpakaļ
vecāks
revīzija
180b4b6dcc

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

@@ -90,26 +90,26 @@ vec3 BRDF_GGX( const in vec3 lightDir, const in vec3 viewDir, const in vec3 norm
 
 #ifdef USE_IRIDESCENCE
 
-vec3 BRDF_GGX_Iridescence( const in vec3 lightDir, const in vec3 viewDir, const in vec3 normal, const in vec3 f0, const in float f90, const in float iridescence, const in vec3 iridescenceFresnel, const in float roughness ) {
+	vec3 BRDF_GGX_Iridescence( const in vec3 lightDir, const in vec3 viewDir, const in vec3 normal, const in vec3 f0, const in float f90, const in float iridescence, const in vec3 iridescenceFresnel, const in float roughness ) {
 
-	float alpha = pow2( roughness ); // UE4's roughness
+		float alpha = pow2( roughness ); // UE4's roughness
 
-	vec3 halfDir = normalize( lightDir + viewDir );
+		vec3 halfDir = normalize( lightDir + viewDir );
 
-	float dotNL = saturate( dot( normal, lightDir ) );
-	float dotNV = saturate( dot( normal, viewDir ) );
-	float dotNH = saturate( dot( normal, halfDir ) );
-	float dotVH = saturate( dot( viewDir, halfDir ) );
+		float dotNL = saturate( dot( normal, lightDir ) );
+		float dotNV = saturate( dot( normal, viewDir ) );
+		float dotNH = saturate( dot( normal, halfDir ) );
+		float dotVH = saturate( dot( viewDir, halfDir ) );
 
-	vec3 F = mix(F_Schlick( f0, f90, dotVH ), iridescenceFresnel, iridescence);
+		vec3 F = mix( F_Schlick( f0, f90, dotVH ), iridescenceFresnel, iridescence );
 
-	float V = V_GGX_SmithCorrelated( alpha, dotNL, dotNV );
+		float V = V_GGX_SmithCorrelated( alpha, dotNL, dotNV );
 
-	float D = D_GGX( alpha, dotNH );
+		float D = D_GGX( alpha, dotNH );
 
-	return F * ( V * D );
+		return F * ( V * D );
 
-}
+	}
 
 #endif
 

+ 113 - 99
src/renderers/shaders/ShaderChunk/iridescence_fragment.glsl.js

@@ -2,105 +2,119 @@ export default /* glsl */`
 
 #ifdef USE_IRIDESCENCE
 
-// XYZ to sRGB color space
-const mat3 XYZ_TO_REC709 = mat3(
-    3.2404542, -0.9692660,  0.0556434,
-   -1.5371385,  1.8760108, -0.2040259,
-   -0.4985314,  0.0415560,  1.0572252
-);
-
-// Assume air interface for top
-// Note: We don't handle the case fresnel0 == 1
-vec3 Fresnel0ToIor( vec3 fresnel0 ) {
-   vec3 sqrtF0 = sqrt( fresnel0 );
-   return ( vec3( 1.0 ) + sqrtF0 ) / ( vec3( 1.0 ) - sqrtF0 );
-}
-
-// Conversion FO/IOR
-vec3 IorToFresnel0( vec3 transmittedIor, float incidentIor ) {
-   return pow2( ( transmittedIor - vec3( incidentIor ) ) / ( transmittedIor + vec3( incidentIor ) ) );
-}
-
-// ior is a value between 1.0 and 3.0. 1.0 is air interface
-float IorToFresnel0( float transmittedIor, float incidentIor ) {
-   return pow2( ( transmittedIor - incidentIor ) / ( transmittedIor + incidentIor ));
-}
-
-// Fresnel equations for dielectric/dielectric interfaces.
-// Ref: https://belcour.github.io/blog/research/2017/05/01/brdf-thin-film.html
-// Evaluation XYZ sensitivity curves in Fourier space
-vec3 evalSensitivity( float OPD, vec3 shift ) {
-   float phase = 2.0 * PI * OPD * 1.0e-9;
-   vec3 val = vec3( 5.4856e-13, 4.4201e-13, 5.2481e-13 );
-   vec3 pos = vec3( 1.6810e+06, 1.7953e+06, 2.2084e+06 );
-   vec3 var = vec3( 4.3278e+09, 9.3046e+09, 6.6121e+09 );
-
-   vec3 xyz = val * sqrt( 2.0 * PI * var ) * cos( pos * phase + shift ) * exp( -pow2( phase ) * var );
-   xyz.x += 9.7470e-14 * sqrt( 2.0 * PI * 4.5282e+09 ) * cos( 2.2399e+06 * phase + shift[0] ) * exp( -4.5282e+09 * pow2( phase ) );
-   xyz /= 1.0685e-7;
-
-   vec3 srgb = XYZ_TO_REC709 * xyz;
-   return srgb;
-}
-
-vec3 evalIridescence( float outsideIOR, float eta2, float cosTheta1, float thinFilmThickness, vec3 baseF0 ) {
-   vec3 I;
-
-   // Force iridescenceIOR -> outsideIOR when thinFilmThickness -> 0.0
-   float iridescenceIOR = mix( outsideIOR, eta2, smoothstep( 0.0, 0.03, thinFilmThickness ) );
-   // Evaluate the cosTheta on the base layer (Snell law)
-   float sinTheta2Sq = pow2( outsideIOR / iridescenceIOR ) * ( 1.0 - pow2( cosTheta1 ) );
-
-   // Handle TIR:
-   float cosTheta2Sq = 1.0 - sinTheta2Sq;
-   if ( cosTheta2Sq < 0.0 ) {
-       return vec3( 1.0 );
-   }
-
-   float cosTheta2 = sqrt( cosTheta2Sq );
-
-   // First interface
-   float R0 = IorToFresnel0( iridescenceIOR, outsideIOR );
-   float R12 = F_Schlick( R0, 1.0, cosTheta1 );
-   float R21 = R12;
-   float T121 = 1.0 - R12;
-   float phi12 = 0.0;
-   if ( iridescenceIOR < outsideIOR ) phi12 = PI;
-   float phi21 = PI - phi12;
-
-   // Second interface
-   vec3 baseIOR = Fresnel0ToIor( clamp( baseF0, 0.0, 0.9999 ) ); // guard against 1.0
-   vec3 R1 = IorToFresnel0( baseIOR, iridescenceIOR );
-   vec3 R23 = F_Schlick( R1, 1.0, cosTheta2 );
-   vec3 phi23 = vec3( 0.0 );
-   if ( baseIOR[0] < iridescenceIOR ) phi23[0] = PI;
-   if ( baseIOR[1] < iridescenceIOR ) phi23[1] = PI;
-   if ( baseIOR[2] < iridescenceIOR ) phi23[2] = PI;
-
-   // Phase shift
-   float OPD = 2.0 * iridescenceIOR * thinFilmThickness * cosTheta2;
-   vec3 phi = vec3( phi21 ) + phi23;
-
-   // Compound terms
-   vec3 R123 = clamp( R12 * R23, 1e-5, 0.9999 );
-   vec3 r123 = sqrt( R123 );
-   vec3 Rs = pow2( T121 ) * R23 / ( vec3( 1.0 ) - R123 );
-
-   // Reflectance term for m = 0 (DC term amplitude)
-   vec3 C0 = R12 + Rs;
-   I = C0;
-
-   // Reflectance term for m > 0 (pairs of diracs)
-   vec3 Cm = Rs - T121;
-   for ( int m = 1; m <= 2; ++m ) {
-       Cm *= r123;
-       vec3 Sm = 2.0 * evalSensitivity( float( m ) * OPD, float( m ) * phi );
-       I += Cm * Sm;
-   }
-
-   // Since out of gamut colors might be produced, negative color values are clamped to 0.
-   return max( I, vec3( 0.0 ) );
-}
+	// XYZ to linear-sRGB color space
+	const mat3 XYZ_TO_REC709 = mat3(
+		 3.2404542, -0.9692660,  0.0556434,
+		-1.5371385,  1.8760108, -0.2040259,
+		-0.4985314,  0.0415560,  1.0572252
+	);
+
+	// Assume air interface for top
+	// Note: We don't handle the case fresnel0 == 1
+	vec3 Fresnel0ToIor( vec3 fresnel0 ) {
+
+		vec3 sqrtF0 = sqrt( fresnel0 );
+		return ( vec3( 1.0 ) + sqrtF0 ) / ( vec3( 1.0 ) - sqrtF0 );
+
+	}
+
+	// Conversion FO/IOR
+	vec3 IorToFresnel0( vec3 transmittedIor, float incidentIor ) {
+
+		return pow2( ( transmittedIor - vec3( incidentIor ) ) / ( transmittedIor + vec3( incidentIor ) ) );
+
+	}
+
+	// ior is a value between 1.0 and 3.0. 1.0 is air interface
+	float IorToFresnel0( float transmittedIor, float incidentIor ) {
+
+		return pow2( ( transmittedIor - incidentIor ) / ( transmittedIor + incidentIor ));
+
+	}
+
+	// Fresnel equations for dielectric/dielectric interfaces.
+	// Ref: https://belcour.github.io/blog/research/2017/05/01/brdf-thin-film.html
+	// Evaluation XYZ sensitivity curves in Fourier space
+	vec3 evalSensitivity( float OPD, vec3 shift ) {
+
+		float phase = 2.0 * PI * OPD * 1.0e-9;
+		vec3 val = vec3( 5.4856e-13, 4.4201e-13, 5.2481e-13 );
+		vec3 pos = vec3( 1.6810e+06, 1.7953e+06, 2.2084e+06 );
+		vec3 var = vec3( 4.3278e+09, 9.3046e+09, 6.6121e+09 );
+
+		vec3 xyz = val * sqrt( 2.0 * PI * var ) * cos( pos * phase + shift ) * exp( - pow2( phase ) * var );
+		xyz.x += 9.7470e-14 * sqrt( 2.0 * PI * 4.5282e+09 ) * cos( 2.2399e+06 * phase + shift[ 0 ] ) * exp( - 4.5282e+09 * pow2( phase ) );
+		xyz /= 1.0685e-7;
+
+		vec3 rgb = XYZ_TO_REC709 * xyz;
+		return rgb;
+
+	}
+
+	vec3 evalIridescence( float outsideIOR, float eta2, float cosTheta1, float thinFilmThickness, vec3 baseF0 ) {
+
+		vec3 I;
+
+		// Force iridescenceIOR -> outsideIOR when thinFilmThickness -> 0.0
+		float iridescenceIOR = mix( outsideIOR, eta2, smoothstep( 0.0, 0.03, thinFilmThickness ) );
+		// Evaluate the cosTheta on the base layer (Snell law)
+		float sinTheta2Sq = pow2( outsideIOR / iridescenceIOR ) * ( 1.0 - pow2( cosTheta1 ) );
+
+		// Handle TIR:
+		float cosTheta2Sq = 1.0 - sinTheta2Sq;
+		if ( cosTheta2Sq < 0.0 ) {
+
+			 return vec3( 1.0 );
+
+		}
+
+		float cosTheta2 = sqrt( cosTheta2Sq );
+
+		// First interface
+		float R0 = IorToFresnel0( iridescenceIOR, outsideIOR );
+		float R12 = F_Schlick( R0, 1.0, cosTheta1 );
+		float R21 = R12;
+		float T121 = 1.0 - R12;
+		float phi12 = 0.0;
+		if ( iridescenceIOR < outsideIOR ) phi12 = PI;
+		float phi21 = PI - phi12;
+
+		// Second interface
+		vec3 baseIOR = Fresnel0ToIor( clamp( baseF0, 0.0, 0.9999 ) ); // guard against 1.0
+		vec3 R1 = IorToFresnel0( baseIOR, iridescenceIOR );
+		vec3 R23 = F_Schlick( R1, 1.0, cosTheta2 );
+		vec3 phi23 = vec3( 0.0 );
+		if ( baseIOR[ 0 ] < iridescenceIOR ) phi23[ 0 ] = PI;
+		if ( baseIOR[ 1 ] < iridescenceIOR ) phi23[ 1 ] = PI;
+		if ( baseIOR[ 2 ] < iridescenceIOR ) phi23[ 2 ] = PI;
+
+		// Phase shift
+		float OPD = 2.0 * iridescenceIOR * thinFilmThickness * cosTheta2;
+		vec3 phi = vec3( phi21 ) + phi23;
+
+		// Compound terms
+		vec3 R123 = clamp( R12 * R23, 1e-5, 0.9999 );
+		vec3 r123 = sqrt( R123 );
+		vec3 Rs = pow2( T121 ) * R23 / ( vec3( 1.0 ) - R123 );
+
+		// Reflectance term for m = 0 (DC term amplitude)
+		vec3 C0 = R12 + Rs;
+		I = C0;
+
+		// Reflectance term for m > 0 (pairs of diracs)
+		vec3 Cm = Rs - T121;
+		for ( int m = 1; m <= 2; ++ m ) {
+
+			Cm *= r123;
+			vec3 Sm = 2.0 * evalSensitivity( float( m ) * OPD, float( m ) * phi );
+			I += Cm * Sm;
+
+		}
+
+		// Since out of gamut colors might be produced, negative color values are clamped to 0.
+		return max( I, vec3( 0.0 ) );
+
+	}
 
 #endif
 

+ 11 - 11
src/renderers/shaders/ShaderChunk/lights_fragment_begin.glsl.js

@@ -28,26 +28,26 @@ geometry.viewDir = ( isOrthographic ) ? vec3( 0, 0, 1 ) : normalize( vViewPositi
 
 #ifdef USE_IRIDESCENCE
 
-float dotNVi = saturate( dot( normal, geometry.viewDir ) );
+	float dotNVi = saturate( dot( normal, geometry.viewDir ) );
 
-if ( material.iridescenceThickness == 0.0 ) {
+	if ( material.iridescenceThickness == 0.0 ) {
 
-	material.iridescence = 0.0;
+		material.iridescence = 0.0;
 
-} else {
+	} else {
 
-	material.iridescence = saturate( material.iridescence );
+		material.iridescence = saturate( material.iridescence );
 
-}
+	}
 
-if ( material.iridescence > 0.0 ) {
+	if ( material.iridescence > 0.0 ) {
 
-	material.iridescenceFresnel = evalIridescence( 1.0, material.iridescenceIOR, dotNVi, material.iridescenceThickness, material.specularColor );
+		material.iridescenceFresnel = evalIridescence( 1.0, material.iridescenceIOR, dotNVi, material.iridescenceThickness, material.specularColor );
 
-	// Iridescence F0 approximation
-	material.iridescenceF0 = Schlick_to_F0( material.iridescenceFresnel, 1.0, dotNVi );
+		// Iridescence F0 approximation
+		material.iridescenceF0 = Schlick_to_F0( material.iridescenceFresnel, 1.0, dotNVi );
 
-}
+	}
 
 #endif