Browse Source

fix reflectivity (it should modulate specularColor globally), fix GGX Render Equation, clean up BRDF_GGX_Environment to have incident and reflected light, pull out SpecularLightProbe.

Ben Houston 9 years ago
parent
commit
b1df023420

+ 25 - 7
src/renderers/shaders/ShaderChunk/bsdfs.glsl

@@ -15,6 +15,20 @@ float calcLightAttenuation( float lightDistance, float cutoffDistance, float dec
 }
 }
 
 
 
 
+ReflectedLight BRDF_Mix( const in ReflectedLight base, const in ReflectedLight over, const in float weight ) {
+	return ReflectedLight(
+		mix( base.diffuse, over.diffuse, weight ),
+		mix( base.specular, over.specular, weight )
+	);
+}
+
+ReflectedLight BRDF_Add( const in ReflectedLight base, const in ReflectedLight over, const in float weight ) {
+	return ReflectedLight(
+		base.diffuse + over.diffuse,
+		base.specular + over.specular 
+	);
+}
+
 void BRDF_Lambert( const in IncidentLight incidentLight, const in GeometricContext geometryContext, const in vec3 diffuseColor, inout ReflectedLight reflectedLight ) {
 void BRDF_Lambert( const in IncidentLight incidentLight, const in GeometricContext geometryContext, const in vec3 diffuseColor, inout ReflectedLight reflectedLight ) {
 
 
 	float lambertianReflectance = saturate( dot( geometryContext.normal, incidentLight.direction ) );
 	float lambertianReflectance = saturate( dot( geometryContext.normal, incidentLight.direction ) );
@@ -105,12 +119,14 @@ void BRDF_GGX( const in IncidentLight incidentLight, const in GeometricContext g
 	float G = G_SmithSchlick( roughness2, dotNL, dotNV );
 	float G = G_SmithSchlick( roughness2, dotNL, dotNV );
 	float D = D_GGX( roughness2, dotNH );
 	float D = D_GGX( roughness2, dotNH );
 
 
-	reflectedLight.specular += incidentLight.color * F * ( G * D );
+	reflectedLight.specular += incidentLight.color * F * ( dotNL * G * D );
 
 
 }
 }
 
 
+#define DIELECTRIC_SPECULAR_F0 0.20
+
 // this blends the existing reflected light with a clear coat.
 // this blends the existing reflected light with a clear coat.
-void BRDF_GGX_ClearCoat_Over( const in IncidentLight incidentLight, const in GeometricContext geometry, const in float clearCoatWeight, const in float clearCoatRoughness, inout ReflectedLight reflectedLight ) {
+void BRDF_GGX_ClearCoat( const in IncidentLight incidentLight, const in GeometricContext geometry, const in float clearCoatWeight, const in float clearCoatRoughness, inout ReflectedLight reflectedLight ) {
 
 
 	vec3 halfDir = normalize( incidentLight.direction + geometry.viewDir );
 	vec3 halfDir = normalize( incidentLight.direction + geometry.viewDir );
 	float dotNH = saturate( dot( geometry.normal, halfDir ) );
 	float dotNH = saturate( dot( geometry.normal, halfDir ) );
@@ -122,15 +138,17 @@ void BRDF_GGX_ClearCoat_Over( const in IncidentLight incidentLight, const in Geo
 	float G = G_Kelemen( dotNV );
 	float G = G_Kelemen( dotNV );
 	float D = D_GGX( clearCoatRoughness, dotNH );
 	float D = D_GGX( clearCoatRoughness, dotNH );
 
 
-	vec3 clearCoatColor = F * ( G * D );
+	
+	ReflectedLight clearCoatReflectedLight;
+	clearCoatReflectedLight.specular = incidentLight.color * F * ( G * D );
+	clearCoatReflectedLight.diffuse = vec3( 0.0 );
 
 
-	reflectedLight.diffuse = mix( reflectedLight.diffuse, vec3( 0.0 ), clearCoatWeight );
-	reflectedLight.specular = mix( reflectedLight.specular, clearCoatColor, clearCoatWeight ); 
+	reflectedLight = BRDF_Mix( reflectedLight, clearCoatReflectedLight, clearCoatWeight ); 
 
 
 }
 }
 
 
 // ref: https://www.unrealengine.com/blog/physically-based-shading-on-mobile - environmentBRDF for GGX on mobile
 // ref: https://www.unrealengine.com/blog/physically-based-shading-on-mobile - environmentBRDF for GGX on mobile
-vec3 BRDF_GGX_Environment( const in GeometricContext geometry, vec3 specularColor, float roughness  ) {
+void BRDF_GGX_Environment( const in IncidentLight incidentLight, const in GeometricContext geometry, vec3 specularColor, float roughness, inout ReflectedLight reflectedLight ) {
 
 
 	float dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );
 	float dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );
 
 
@@ -140,7 +158,7 @@ vec3 BRDF_GGX_Environment( const in GeometricContext geometry, vec3 specularColo
 	float a004 = min( r.x * r.x, exp2( - 9.28 * dotNV ) ) * r.x + r.y;
 	float a004 = min( r.x * r.x, exp2( - 9.28 * dotNV ) ) * r.x + r.y;
 	vec2 AB = vec2( -1.04, 1.04 ) * a004 + r.zw;
 	vec2 AB = vec2( -1.04, 1.04 ) * a004 + r.zw;
 
 
-	return specularColor * AB.x + AB.y;
+	reflectedLight.specular += incidentLight.color * specularColor * AB.x + AB.y;
 
 
 }
 }
 
 

+ 0 - 63
src/renderers/shaders/ShaderChunk/envmap_physical_fragment.glsl

@@ -1,63 +0,0 @@
-#ifdef USE_ENVMAP
-
-	float reflectivityFactor = reflectivity; // fix add map - replace specular strength?
-
-	vec3 cameraToVertex = normalize( vWorldPosition - cameraPosition );
-
-	// Transforming Normal Vectors with the Inverse Transformation
-	vec3 worldNormal = inverseTransformDirection( normal, viewMatrix );
-
-	#ifdef ENVMAP_MODE_REFLECTION
-
-		vec3 reflectVec = reflect( cameraToVertex, worldNormal );
-
-	#else
-
-		vec3 reflectVec = refract( cameraToVertex, worldNormal, refractionRatio );
-
-	#endif
-
-	#ifdef DOUBLE_SIDED
-
-		float flipNormal = ( float( gl_FrontFacing ) * 2.0 - 1.0 );
-
-	#else
-
-		float flipNormal = 1.0;
-
-	#endif
-
-	#ifdef ENVMAP_TYPE_CUBE
-
-		#if defined( TEXTURE_CUBE_LOD_EXT )
-
-			float bias = pow( roughness, 0.5 ) * 7.0; // from bhouston - there are other models for this calculation (roughness; not roughnesFactor)
-
-			vec4 envMapColor = textureCubeLodEXT( envMap, flipNormal * vec3( flipEnvMap * reflectVec.x, reflectVec.yz ), bias );
-
-		#else
-
-			vec4 envMapColor = textureCube( envMap, flipNormal * vec3( flipEnvMap * reflectVec.x, reflectVec.yz ) );
-
-		#endif
-
-	#elif defined( ENVMAP_TYPE_EQUIREC )
-
-		vec2 sampleUV;
-		sampleUV.y = saturate( flipNormal * reflectVec.y * 0.5 + 0.5 );
-		sampleUV.x = atan( flipNormal * reflectVec.z, flipNormal * reflectVec.x ) * RECIPROCAL_PI2 + 0.5;
-		vec4 envMapColor = texture2D( envMap, sampleUV );
-
-	#elif defined( ENVMAP_TYPE_SPHERE )
-
-		vec3 reflectView = flipNormal * normalize((viewMatrix * vec4( reflectVec, 0.0 )).xyz + vec3(0.0,0.0,1.0));
-		vec4 envMapColor = texture2D( envMap, reflectView.xy * 0.5 + 0.5 );
-
-	#endif
-
-	envMapColor.rgb = inputToLinear( envMapColor.rgb );
-
-    indirectReflectedLight.specular += envBRDFApprox( specularColor, roughnessFactor, normal, viewDir  ) * envMapColor.rgb * envMapIntensity * reflectivityFactor;
-
-#endif
-

+ 73 - 0
src/renderers/shaders/ShaderChunk/lights_pars.glsl

@@ -111,3 +111,76 @@ uniform vec3 ambientLightColor;
 	}
 	}
 
 
 #endif
 #endif
+
+
+#ifdef USE_ENVMAP
+
+	struct SpecularLightProbe {
+		samplerCube	map;
+		float intensity;
+	};
+
+	IncidentLight getSpecularLightProbeIndirectLight( const in SpecularLightProbe specularLightProbe, const in GeometricContext geometry, const in float lodLevel ) { 
+	
+		#ifdef ENVMAP_MODE_REFLECTION
+
+			vec3 reflectVec = reflect( -geometry.viewDir, geometry.normal );
+
+		#else
+
+			vec3 reflectVec = refract( -geometry.viewDir, geometry.normal, refractionRatio );
+
+		#endif
+
+		#ifdef DOUBLE_SIDED
+
+			float flipNormal = ( float( gl_FrontFacing ) * 2.0 - 1.0 );
+
+		#else
+
+			float flipNormal = 1.0;
+
+		#endif
+
+		reflectVec = normalize( transformDirection( reflectVec, viewMatrix ) );
+
+		#ifdef ENVMAP_TYPE_CUBE
+
+			#if defined( TEXTURE_CUBE_LOD_EXT )
+
+				float bias = pow( lodLevel, 0.5 ) * 7.0; // from bhouston - there are other models for this calculation (roughness; not roughnesFactor)
+
+				vec4 envMapColor = textureCubeLodEXT( specularLightProbe.map, flipNormal * vec3( flipEnvMap * reflectVec.x, reflectVec.yz ), bias );
+
+			#else
+
+				vec4 envMapColor = textureCube( specularLightProbe.map, flipNormal * vec3( flipEnvMap * reflectVec.x, reflectVec.yz ) );
+
+			#endif
+
+		#elif defined( ENVMAP_TYPE_EQUIREC )
+
+			vec2 sampleUV;
+			sampleUV.y = saturate( flipNormal * reflectVec.y * 0.5 + 0.5 );
+			sampleUV.x = atan( flipNormal * reflectVec.z, flipNormal * reflectVec.x ) * RECIPROCAL_PI2 + 0.5;
+			vec4 envMapColor = texture2D( specularLightProbe.map, sampleUV );
+
+		#elif defined( ENVMAP_TYPE_SPHERE )
+
+			vec3 reflectView = flipNormal * normalize((viewMatrix * vec4( reflectVec, 0.0 )).xyz + vec3(0.0,0.0,1.0));
+			vec4 envMapColor = texture2D( specularLightProbe.map, reflectView.xy * 0.5 + 0.5 );
+
+		#endif
+
+		envMapColor.rgb = inputToLinear( envMapColor.rgb );
+
+		IncidentLight indirectLight;
+		indirectLight.color = envMapColor.rgb * specularLightProbe.intensity;
+		indirectLight.direction = geometry.normal;
+
+		return indirectLight;
+
+	}
+
+#endif
+

+ 3 - 1
src/renderers/shaders/ShaderChunk/lights_phong_pars_fragment.glsl

@@ -30,6 +30,7 @@ void BRDF_BlinnPhongMaterial_DirectLight( const in IncidentLight directLight, co
 	
 	
 }
 }
 
 
+#define BRDF_Material_DirectLight    BRDF_BlinnPhongMaterial_DirectLight
 
 
 void BRDF_BlinnPhongMaterial_IndirectLight( const in IncidentLight indirectLight, const in GeometricContext geometry, const in BlinnPhongMaterial material, inout ReflectedLight indirectReflectedLight ) {
 void BRDF_BlinnPhongMaterial_IndirectLight( const in IncidentLight indirectLight, const in GeometricContext geometry, const in BlinnPhongMaterial material, inout ReflectedLight indirectReflectedLight ) {
 
 
@@ -37,5 +38,6 @@ void BRDF_BlinnPhongMaterial_IndirectLight( const in IncidentLight indirectLight
 
 
 }
 }
 
 
-#define BRDF_Material_DirectLight    BRDF_BlinnPhongMaterial_DirectLight
 #define BRDF_Material_IndirectLight    BRDF_BlinnPhongMaterial_IndirectLight
 #define BRDF_Material_IndirectLight    BRDF_BlinnPhongMaterial_IndirectLight
+
+#define Material_LightProbeLOD( material )   (0)

+ 1 - 1
src/renderers/shaders/ShaderChunk/lights_physical_fragment.glsl

@@ -1,7 +1,7 @@
 PhysicalMaterial material;
 PhysicalMaterial material;
 material.diffuseColor = diffuseColor.rgb * ( 1.0 - metalnessFactor );
 material.diffuseColor = diffuseColor.rgb * ( 1.0 - metalnessFactor );
 material.specularRoughness = roughnessFactor * 0.5 + 0.5; // disney's remapping of [ 0, 1 ] roughness to [ 0.5, 1 ]
 material.specularRoughness = roughnessFactor * 0.5 + 0.5; // disney's remapping of [ 0, 1 ] roughness to [ 0.5, 1 ]
-material.specularColor = mix( vec3( 0.04 ), diffuseColor.rgb, metalnessFactor );
+material.specularColor = mix( vec3( 0.04 ) * reflectivity, diffuseColor.rgb, metalnessFactor );
 
 
 #if defined( ENERGY_PRESERVING_RGB )
 #if defined( ENERGY_PRESERVING_RGB )
 
 

+ 14 - 3
src/renderers/shaders/ShaderChunk/lights_physical_pars_fragment.glsl

@@ -24,13 +24,24 @@ void BRDF_PhysicalMaterial_DirectLight( const in IncidentLight directLight, cons
 	directReflectedLight.specular += reflectedLight.specular;
 	directReflectedLight.specular += reflectedLight.specular;
 	
 	
 }
 }
+#define BRDF_Material_DirectLight    BRDF_PhysicalMaterial_DirectLight
 
 
 
 
-void BRDF_PhysicalMaterial_IndirectLight( const in IncidentLight indirectLight, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight indirectReflectedLight ) {
+void BRDF_PhysicalMaterial_DiffuseIndirectLight( const in IncidentLight indirectLight, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight indirectReflectedLight ) {
 
 
 	BRDF_Lambert( indirectLight, geometry, material.diffuseColor, indirectReflectedLight );
 	BRDF_Lambert( indirectLight, geometry, material.diffuseColor, indirectReflectedLight );
 
 
 }
 }
 
 
-#define BRDF_Material_DirectLight    BRDF_PhysicalMaterial_DirectLight
-#define BRDF_Material_IndirectLight    BRDF_PhysicalMaterial_IndirectLight
+#define BRDF_Material_DiffuseIndirectLight    BRDF_PhysicalMaterial_DiffuseIndirectLight
+
+
+void BRDF_PhysicalMaterial_SpecularIndirectLight( const in IncidentLight indirectLight, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight indirectReflectedLight ) {
+
+    BRDF_GGX_Environment( lightProbeIncidentLight, geometry, material.specularColor, material.roughness, indirectReflectedLight );
+
+}
+
+#define Material_LightProbeLOD( material )   (material.roughness)
+
+#define BRDF_Material_SpecularIndirectLight    BRDF_PhysicalMaterial_SpecularIndirectLight

+ 17 - 5
src/renderers/shaders/ShaderChunk/lights_template.glsl

@@ -4,7 +4,7 @@
 
 
 GeometricContext geometry = GeometricContext( -vViewPosition, normalize( normal ), normalize(vViewPosition ) );
 GeometricContext geometry = GeometricContext( -vViewPosition, normalize( normal ), normalize(vViewPosition ) );
 
 
-#if MAX_POINT_LIGHTS > 0
+#if ( MAX_POINT_LIGHTS > 0 ) && defined( BRDF_Material_DirectLight )
 
 
 	for ( int i = 0; i < MAX_POINT_LIGHTS; i ++ ) {
 	for ( int i = 0; i < MAX_POINT_LIGHTS; i ++ ) {
 
 
@@ -16,7 +16,7 @@ GeometricContext geometry = GeometricContext( -vViewPosition, normalize( normal
 
 
 #endif
 #endif
 
 
-#if MAX_SPOT_LIGHTS > 0
+#if ( MAX_SPOT_LIGHTS > 0 ) && defined( BRDF_Material_DirectLight )
 
 
 	for ( int i = 0; i < MAX_SPOT_LIGHTS; i ++ ) {
 	for ( int i = 0; i < MAX_SPOT_LIGHTS; i ++ ) {
 
 
@@ -28,7 +28,7 @@ GeometricContext geometry = GeometricContext( -vViewPosition, normalize( normal
 
 
 #endif
 #endif
 
 
-#if MAX_DIR_LIGHTS > 0
+#if ( MAX_DIR_LIGHTS > 0 ) && defined( BRDF_Material_DirectLight )
 
 
 	for ( int i = 0; i < MAX_DIR_LIGHTS; i ++ ) {
 	for ( int i = 0; i < MAX_DIR_LIGHTS; i ++ ) {
 
 
@@ -40,14 +40,26 @@ GeometricContext geometry = GeometricContext( -vViewPosition, normalize( normal
 
 
 #endif
 #endif
 
 
-#if MAX_HEMI_LIGHTS > 0
+#if ( MAX_HEMI_LIGHTS > 0 ) && defined( BRDF_Material_DiffuseIndirectLight )
 
 
 	for ( int i = 0; i < MAX_HEMI_LIGHTS; i ++ ) {
 	for ( int i = 0; i < MAX_HEMI_LIGHTS; i ++ ) {
 
 
 		IncidentLight indirectLight = getHemisphereIndirectLight( hemisphereLights[ i ], geometry );
 		IncidentLight indirectLight = getHemisphereIndirectLight( hemisphereLights[ i ], geometry );
 
 
-		BRDF_Material_IndirectLight( indirectLight, geometry, material, indirectReflectedLight );
+		BRDF_Material_DiffuseIndirectLight( indirectLight, geometry, material, indirectReflectedLight );
 
 
 	}
 	}
 
 
 #endif
 #endif
+
+#if defined( ENV_MAP ) && defined( BRDF_Material_SpecularIndirectLight )
+
+	{
+
+		IncidentLight indirectLight = getSpecularLightProbeIndirectLight( specularLightProbe, geometry, Material_LightProbeLOD( material ) );
+
+    	BRDF_Material_SpecularIndirectLight( lightProbeIncidentLight, geometry, material, indirectReflectedLight );
+
+    }
+
+#endif