|
@@ -72,29 +72,33 @@
|
|
|
uniform float refractionRatio;
|
|
|
#endif
|
|
|
|
|
|
- vec3 getLightProbeIndirectIrradiance( const in GeometricContext geometry, const in int maxMIPLevel ) {
|
|
|
+ vec3 getLightProbeIndirectIrradiance( /*const in SpecularLightProbe specularLightProbe,*/ const in GeometricContext geometry, const in int maxMIPLevel ) {
|
|
|
+
|
|
|
vec3 worldNormal = inverseTransformDirection( geometry.normal, viewMatrix );
|
|
|
+
|
|
|
#ifdef ENVMAP_TYPE_CUBE
|
|
|
|
|
|
- vec3 worldNormalFinal = worldNormal;
|
|
|
+ #ifdef BOX_PROJECTED_ENV_MAP
|
|
|
|
|
|
- #ifdef BOX_PROJECTED_ENV_MAP
|
|
|
+ worldNormal = parallaxCorrectNormal( worldNormal, cubeMapSize, cubeMapPos );
|
|
|
|
|
|
- worldNormalFinal = parallaxCorrectNormal( worldNormal, cubeMapSize, cubeMapPos );
|
|
|
+ #endif
|
|
|
|
|
|
- #endif
|
|
|
+ vec3 queryVec = vec3( flipEnvMap * worldNormal.x, worldNormal.yz );
|
|
|
|
|
|
- vec3 queryVec = vec3( flipEnvMap * worldNormalFinal.x, worldNormalFinal.yz );
|
|
|
+ // TODO: replace with properly filtered cubemaps and access the irradiance LOD level, be it the last LOD level
|
|
|
+ // of a specular cubemap, or just the default level of a specially created irradiance cubemap.
|
|
|
|
|
|
- #ifdef TEXTURE_LOD_EXT
|
|
|
+ #ifdef TEXTURE_LOD_EXT
|
|
|
|
|
|
- vec4 envMapColor = textureCubeLodEXT( envMap, queryVec, float( maxMIPLevel ) );
|
|
|
+ vec4 envMapColor = textureCubeLodEXT( envMap, queryVec, float( maxMIPLevel ) );
|
|
|
|
|
|
- #else
|
|
|
+ #else
|
|
|
|
|
|
- vec4 envMapColor = textureCube( envMap, queryVec, float( maxMIPLevel ) );
|
|
|
+ // force the bias high to get the last LOD level as it is the most blurred.
|
|
|
+ vec4 envMapColor = textureCube( envMap, queryVec, float( maxMIPLevel ) );
|
|
|
|
|
|
- #endif
|
|
|
+ #endif
|
|
|
|
|
|
envMapColor.rgb = envMapTexelToLinear( envMapColor ).rgb;
|
|
|
|
|
@@ -110,20 +114,31 @@
|
|
|
#endif
|
|
|
|
|
|
return PI * envMapColor.rgb * envMapIntensity;
|
|
|
+
|
|
|
}
|
|
|
|
|
|
- float getSpecularMIPLevel( const in float blinnShininessExponent, const in int maxMIPLevel ) {
|
|
|
+ // Trowbridge-Reitz distribution to Mip level, following the logic of http://casual-effects.blogspot.ca/2011/08/plausible-environment-lighting-in-two.html
|
|
|
+ float getSpecularMIPLevel( const in float roughness, const in int maxMIPLevel ) {
|
|
|
+
|
|
|
float maxMIPLevelScalar = float( maxMIPLevel );
|
|
|
- float desiredMIPLevel = maxMIPLevelScalar + 0.79248 - 0.5 * log2( pow2( blinnShininessExponent ) + 1.0 );
|
|
|
+
|
|
|
+ float sigma = PI * roughness * roughness / ( 1.0 + roughness );
|
|
|
+ float desiredMIPLevel = maxMIPLevelScalar + log2( sigma );
|
|
|
+
|
|
|
+ // clamp to allowable LOD ranges.
|
|
|
return clamp( desiredMIPLevel, 0.0, maxMIPLevelScalar );
|
|
|
+
|
|
|
}
|
|
|
|
|
|
- vec3 getLightProbeIndirectRadiance( const in vec3 viewDir, const in vec3 normal, const in float blinnShininessExponent, const in int maxMIPLevel ) {
|
|
|
+ vec3 getLightProbeIndirectRadiance( /*const in SpecularLightProbe specularLightProbe,*/ const in vec3 viewDir, const in vec3 normal, const in float roughness, const in int maxMIPLevel ) {
|
|
|
|
|
|
#ifdef ENVMAP_MODE_REFLECTION
|
|
|
|
|
|
vec3 reflectVec = reflect( -viewDir, normal );
|
|
|
|
|
|
+ // Mixing the reflection with the normal is more accurate and keeps rough objects from gathering light from behind their tangent plane.
|
|
|
+ reflectVec = normalize( mix( reflectVec, normal, roughness * roughness) );
|
|
|
+
|
|
|
#else
|
|
|
|
|
|
vec3 reflectVec = refract( -viewDir, normal, refractionRatio );
|
|
@@ -131,36 +146,33 @@
|
|
|
#endif
|
|
|
|
|
|
reflectVec = inverseTransformDirection( reflectVec, viewMatrix );
|
|
|
- float specularMIPLevel = getSpecularMIPLevel( blinnShininessExponent, maxMIPLevel );
|
|
|
-
|
|
|
- #ifdef ENVMAP_TYPE_CUBE
|
|
|
-
|
|
|
- vec3 reflectVecFinal = reflectVec;
|
|
|
|
|
|
- #ifdef BOX_PROJECTED_ENV_MAP
|
|
|
+ float specularMIPLevel = getSpecularMIPLevel( roughness, maxMIPLevel );
|
|
|
|
|
|
- reflectVecFinal = parallaxCorrectNormal( reflectVec, cubeMapSize, cubeMapPos );
|
|
|
+ #ifdef ENVMAP_TYPE_CUBE
|
|
|
|
|
|
- #endif
|
|
|
+ #ifdef BOX_PROJECTED_ENV_MAP
|
|
|
+ reflectVec = parallaxCorrectNormal( reflectVec, cubeMapSize, cubeMapPos );
|
|
|
+ #endif
|
|
|
|
|
|
- vec3 queryReflectVec = vec3( flipEnvMap * reflectVecFinal.x, reflectVecFinal.yz );
|
|
|
+ vec3 queryReflectVec = vec3( flipEnvMap * reflectVec.x, reflectVec.yz );
|
|
|
|
|
|
- #ifdef TEXTURE_LOD_EXT
|
|
|
+ #ifdef TEXTURE_LOD_EXT
|
|
|
|
|
|
- vec4 envMapColor = textureCubeLodEXT( envMap, queryReflectVec, specularMIPLevel );
|
|
|
+ vec4 envMapColor = textureCubeLodEXT( envMap, queryReflectVec, specularMIPLevel );
|
|
|
|
|
|
- #else
|
|
|
+ #else
|
|
|
|
|
|
- vec4 envMapColor = textureCube( envMap, queryReflectVec, specularMIPLevel );
|
|
|
+ vec4 envMapColor = textureCube( envMap, queryReflectVec, specularMIPLevel );
|
|
|
|
|
|
- #endif
|
|
|
+ #endif
|
|
|
|
|
|
- envMapColor.rgb = envMapTexelToLinear( envMapColor ).rgb;
|
|
|
+ envMapColor.rgb = envMapTexelToLinear( envMapColor ).rgb;
|
|
|
|
|
|
#elif defined( ENVMAP_TYPE_CUBE_UV )
|
|
|
|
|
|
vec3 queryReflectVec = vec3( flipEnvMap * reflectVec.x, reflectVec.yz );
|
|
|
- vec4 envMapColor = textureCubeUV( envMap, queryReflectVec, BlinnExponentToGGXRoughness(blinnShininessExponent ));
|
|
|
+ vec4 envMapColor = textureCubeUV( envMap, queryReflectVec, roughness );
|
|
|
|
|
|
#elif defined( ENVMAP_TYPE_EQUIREC )
|
|
|
|
|
@@ -179,6 +191,7 @@
|
|
|
#endif
|
|
|
|
|
|
envMapColor.rgb = envMapTexelToLinear( envMapColor ).rgb;
|
|
|
+
|
|
|
#elif defined( ENVMAP_TYPE_SPHERE )
|
|
|
|
|
|
vec3 reflectView = normalize( ( viewMatrix * vec4( reflectVec, 0.0 ) ).xyz + vec3( 0.0,0.0,1.0 ) );
|