Browse Source

initial non-compiling attempt to use proper specular LOD selection with polyfill LOD queries.

Ben Houston 9 years ago
parent
commit
0e559a9ba3

+ 10 - 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 ) ); }
 
 
@@ -90,3 +91,12 @@ vec3 linearToOutput( in vec3 a ) {
 	#endif
 
 }
+
+// http://stackoverflow.com/a/24390149 modified to work on a CubeMap.
+float textureQueryLod( const in vec3 sampleDirection, const in float cubeMapWidth )
+{
+    vec3  dx_vtc        = dFdx( sampleDirection * cubeMapWidth );
+    vec3  dy_vtc        = dFdy( sampleDirection * cubeMapWidth );
+    float delta_max_sqr = max(dot(dx_vtc, dx_vtc), dot(dy_vtc, dy_vtc));
+    return 0.5 * log2( delta_max_sqr );
+}

+ 60 - 9
src/renderers/shaders/ShaderChunk/lights_pars.glsl

@@ -107,7 +107,64 @@ uniform vec3 ambientLightColor;
 
 #if defined( USE_ENVMAP ) && defined( PHYSICAL )
 
-	vec3 getSpecularLightProbeIndirectLightColor( /*const in SpecularLightProbe specularLightProbe,*/ const in GeometricContext geometry, const in float lodLevel ) { 
+
+	vec3 getDiffuseLightProbeIndirectLightColor( /*const in SpecularLightProbe specularLightProbe,*/ const in GeometricContext geometry, const in float maxLodLevel ) { 
+
+		#ifdef DOUBLE_SIDED
+
+			float flipNormal = ( float( gl_FrontFacing ) * 2.0 - 1.0 );
+
+		#else
+
+			float flipNormal = 1.0;
+
+		#endif
+
+		vec3 worldNormal = inverseTransformDirection( geometry.normal, viewMatrix );
+
+		#ifdef ENVMAP_TYPE_CUBE
+
+			#if defined( TEXTURE_CUBE_LOD_EXT )				
+
+				vec4 envMapColor = textureCubeLodEXT( envMap, flipNormal * vec3( flipEnvMap * worldNormal.x, worldNormal.yz ), maxLodLevel );
+
+			#else
+
+				vec4 envMapColor = textureCube( envMap, flipNormal * vec3( flipEnvMap * worldNormal.x, worldNormal.yz ), maxLodLevel );
+
+			#endif
+		#else
+
+			vec4 envMapColor = vec3( 0.0 );
+
+		#endif
+
+		envMapColor.rgb = inputToLinear( envMapColor.rgb );
+
+		return envMapColor.rgb;
+
+	}
+
+
+	// taken from here: http://casual-effects.blogspot.ca/2011/08/plausible-environment-lighting-in-two.html
+	float getSpecularMIPBias( const in float blinnShininessExponent, const in int maxMIPLevel, const vec3 sampleDirection ) {
+
+		float envMapWidth = pow( 2.0, float(mapMIPLevel) );
+
+		//float desiredMIPLevel = log2( envMapWidth * sqrt( 3.0 ) ) - 0.5 * log2( square( blinnShininessExponent ) + 1.0 );
+		float desiredMIPLevel = float(maxMIPLevel) - 0.79248 - 0.5 * log2( square( blinnShininessExponent ) + 1.0 );
+		float sampleMIPLevel = textureQueryLod( environmentMap, worldSpaceReflectionVector, envMapWidth );
+	
+		// clamp to allowable LOD ranges.
+		sampleMIPLevel = clamp( sampleMIPLevel, 0.0, maxMIPLevel );
+		desiredMIPLevel = clamp( desiredMIPLevel, 0.0, maxMIPLevel );
+
+		// only go to lower LOD levels
+	  	return max( desiredMIPLevel - sampleMIPLevel, 0.0 );
+
+	}
+
+	vec3 getSpecularLightProbeIndirectLightColor( /*const in SpecularLightProbe specularLightProbe,*/ const in GeometricContext geometry, const in float blinnShininessExponent, const in int maxMIPLevel ) { 
 	
 		#ifdef ENVMAP_MODE_REFLECTION
 
@@ -133,15 +190,9 @@ uniform vec3 ambientLightColor;
 
 		#ifdef ENVMAP_TYPE_CUBE
 
-			#if defined( TEXTURE_CUBE_LOD_EXT )				
+			float mipBias = getSpecularMIPBias( blinnShininessExponent, maxMIPLevel, reflectVec );
 
-				vec4 envMapColor = textureCubeLodEXT( envMap, flipNormal * vec3( flipEnvMap * reflectVec.x, reflectVec.yz ), lodLevel );
-
-			#else
-
-				vec4 envMapColor = textureCube( envMap, flipNormal * vec3( flipEnvMap * reflectVec.x, reflectVec.yz ) );
-
-			#endif
+			vec4 envMapColor = textureCube( envMap, flipNormal * vec3( flipEnvMap * reflectVec.x, reflectVec.yz ), mipBias );
 
 		#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 )   ( 2.0 / square( material.specularRoughness + 0.0001 ) - 2.0 )
 
 #define Material_RE_IndirectSpecularLight    PhysicalMaterial_RE_SpecularIndirectLight

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

@@ -83,7 +83,7 @@ GeometricContext geometry = GeometricContext( -vViewPosition, normalize( normal
 
 	{
 
-		vec3 indirectSpecularColor = getSpecularLightProbeIndirectLightColor( /*specularLightProbe,*/ geometry, Material_LightProbeLOD( material ) );
+		vec3 indirectSpecularColor = getSpecularLightProbeIndirectLightColor( /*specularLightProbe,*/ geometry, Material_BlinnShininessExponent( material ) );
 
 		Material_RE_IndirectSpecularLight( indirectSpecularColor, geometry, material, reflectedLight );