Browse Source

Merge pull request #7414 from bhouston/cosine_envMap_lod

Cosine-based specular env map LOD selection
Mr.doob 9 years ago
parent
commit
7939105783

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

@@ -1,4 +1,4 @@
-float calcLightAttenuation( float lightDistance, float cutoffDistance, float decayExponent ) {
+float calcLightAttenuation( const in float lightDistance, const in float cutoffDistance, const in float decayExponent ) {
 
 	if ( decayExponent > 0.0 ) {
 
@@ -36,7 +36,7 @@ vec3 F_Schlick( const in vec3 specularColor, const in float dotLH ) {
 // Microfacet Models for Refraction through Rough Surfaces - equation (34)
 // http://graphicrants.blogspot.com/2013/08/specular-brdf-reference.html
 // alpha is "roughness squared" in Disney’s reparameterization
-float G_GGX_Smith( in float alpha, in float dotNL, in float dotNV ) {
+float G_GGX_Smith( const in float alpha, const in float dotNL, const in float dotNV ) {
 
 	// geometry term = G(l)⋅G(v) / 4(n⋅l)(n⋅v)
 
@@ -54,7 +54,7 @@ float G_GGX_Smith( in float alpha, in float dotNL, in float dotNV ) {
 // Microfacet Models for Refraction through Rough Surfaces - equation (33)
 // http://graphicrants.blogspot.com/2013/08/specular-brdf-reference.html
 // alpha is "roughness squared" in Disney’s reparameterization
-float D_GGX( in float alpha, in float dotNH ) {
+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
 
@@ -93,7 +93,7 @@ vec3 BRDF_Specular_GGX( const in IncidentLight incidentLight, const in Geometric
 
 
 // ref: https://www.unrealengine.com/blog/physically-based-shading-on-mobile - environmentBRDF for GGX on mobile
-vec3 BRDF_Specular_GGX_Environment( const in GeometricContext geometry, vec3 specularColor, float roughness ) {
+vec3 BRDF_Specular_GGX_Environment( const in GeometricContext geometry, const in vec3 specularColor, const in float roughness ) {
 
 	float dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );
 
@@ -112,7 +112,7 @@ vec3 BRDF_Specular_GGX_Environment( const in GeometricContext geometry, vec3 spe
 } // validated
 
 
-float G_BlinnPhong_Implicit( /* in float dotNL, in float dotNV */ ) {
+float G_BlinnPhong_Implicit( /* const in float dotNL, const in float dotNV */ ) {
 
 	// geometry term is (n dot l)(n dot v) / 4(n dot l)(n dot v)
 	return 0.25;
@@ -146,4 +146,9 @@ vec3 BRDF_Specular_BlinnPhong( const in IncidentLight incidentLight, const in Ge
 
 	return F * ( G * D );
 
-} // validated
+} // validated
+
+// source: http://simonstechblog.blogspot.ca/2011/12/microfacet-brdf.html
+float GGXRoughnessToBlinnExponent( const in float ggxRoughness ) {
+	return ( 2.0 / square( ggxRoughness + 0.0001 ) - 2.0 );
+}

+ 1 - 0
src/renderers/shaders/ShaderChunk/common.glsl

@@ -8,6 +8,7 @@
 #define saturate(a) clamp( a, 0.0, 1.0 )
 #define whiteCompliment(a) ( 1.0 - saturate( a ) )
 
+float square( const in float x ) { return x*x; }
 float average( const in vec3 color ) { return dot( color, vec3( 0.3333 ) ); }
 
 

+ 21 - 3
src/renderers/shaders/ShaderChunk/lights_pars.glsl

@@ -107,7 +107,21 @@ uniform vec3 ambientLightColor;
 
 #if defined( USE_ENVMAP ) && defined( PHYSICAL )
 
-	vec3 getSpecularLightProbeIndirectLightColor( /*const in SpecularLightProbe specularLightProbe,*/ const in GeometricContext geometry, const in float lodLevel ) { 
+	// taken from here: http://casual-effects.blogspot.ca/2011/08/plausible-environment-lighting-in-two.html
+	float getSpecularMIPLevel( const in float blinnShininessExponent, const in int maxMIPLevel ) {
+
+		//float envMapWidth = pow( 2.0, maxMIPLevelScalar );
+		//float desiredMIPLevel = log2( envMapWidth * sqrt( 3.0 ) ) - 0.5 * log2( square( blinnShininessExponent ) + 1.0 );
+
+		float maxMIPLevelScalar = float( maxMIPLevel );
+		float desiredMIPLevel = maxMIPLevelScalar - 0.79248 - 0.5 * log2( square( blinnShininessExponent ) + 1.0 );
+	
+		// clamp to allowable LOD ranges.
+		return clamp( desiredMIPLevel, 0.0, maxMIPLevelScalar );
+
+	}
+
+	vec3 getSpecularLightProbeIndirectLightColor( /*const in SpecularLightProbe specularLightProbe,*/ const in GeometricContext geometry, const in float blinnShininessExponent, const in int maxMIPLevel ) { 
 	
 		#ifdef ENVMAP_MODE_REFLECTION
 
@@ -133,15 +147,19 @@ uniform vec3 ambientLightColor;
 
 		#ifdef ENVMAP_TYPE_CUBE
 
+			vec3 queryReflectVec = flipNormal * vec3( flipEnvMap * reflectVec.x, reflectVec.yz );
+
 			#if defined( TEXTURE_CUBE_LOD_EXT )				
 
-				vec4 envMapColor = textureCubeLodEXT( envMap, flipNormal * vec3( flipEnvMap * reflectVec.x, reflectVec.yz ), lodLevel );
+				float specularMIPLevel = getSpecularMIPLevel( blinnShininessExponent, maxMIPLevel );
+				vec4 envMapColor = textureCubeLodEXT( envMap, queryReflectVec, specularMIPLevel );
 
 			#else
 
-				vec4 envMapColor = textureCube( envMap, flipNormal * vec3( flipEnvMap * reflectVec.x, reflectVec.yz ) );
+				vec4 envMapColor = textureCube( envMap, queryReflectVec );
 
 			#endif
+ 
 
 		#elif defined( ENVMAP_TYPE_EQUIREC )
 

+ 1 - 2
src/renderers/shaders/ShaderChunk/lights_physical_pars_fragment.glsl

@@ -32,7 +32,6 @@ void PhysicalMaterial_RE_SpecularIndirectLight( const in vec3 indirectSpecularCo
 
 }
 
-// from bhouston - there are other models for this calculation (roughness; not roughnesFactor)
-#define Material_LightProbeLOD( material )   (pow( ( material.specularRoughness - 0.5 ) * 2.0, 0.5 ) * 7.0)
+#define Material_BlinnShininessExponent( material )   GGXRoughnessToBlinnExponent( material.specularRoughness )
 
 #define Material_RE_IndirectSpecularLight    PhysicalMaterial_RE_SpecularIndirectLight

+ 2 - 1
src/renderers/shaders/ShaderChunk/lights_template.glsl

@@ -83,7 +83,8 @@ GeometricContext geometry = GeometricContext( -vViewPosition, normalize( normal
 
 	{
 
-		vec3 indirectSpecularColor = getSpecularLightProbeIndirectLightColor( /*specularLightProbe,*/ geometry, Material_LightProbeLOD( material ) );
+		// TODO, replace 8 with the real maxMIPLevel
+		vec3 indirectSpecularColor = getSpecularLightProbeIndirectLightColor( /*specularLightProbe,*/ geometry, Material_BlinnShininessExponent( material ), 8 );
 
 		Material_RE_IndirectSpecularLight( indirectSpecularColor, geometry, material, reflectedLight );