Sfoglia il codice sorgente

Merge pull request #965 from sebavan/PBRLodFiltering

Pbr lod filtering
David Catuhe 9 anni fa
parent
commit
591387f60d

File diff suppressed because it is too large
+ 32 - 22
dist/preview release/babylon.core.js


File diff suppressed because it is too large
+ 1689 - 1688
dist/preview release/babylon.d.ts


File diff suppressed because it is too large
+ 37 - 25
dist/preview release/babylon.js


File diff suppressed because it is too large
+ 3555 - 3554
dist/preview release/babylon.max.js


File diff suppressed because it is too large
+ 36 - 24
dist/preview release/babylon.noworker.js


File diff suppressed because it is too large
+ 1 - 1
materialsLibrary/dist/babylon.fireMaterial.js


File diff suppressed because it is too large
+ 1 - 1
materialsLibrary/dist/babylon.fireMaterial.min.js


File diff suppressed because it is too large
+ 1 - 1
materialsLibrary/dist/babylon.normalMaterial.js


File diff suppressed because it is too large
+ 1 - 1
materialsLibrary/dist/babylon.normalMaterial.min.js


File diff suppressed because it is too large
+ 13 - 2
materialsLibrary/dist/babylon.pbrMaterial.js


File diff suppressed because it is too large
+ 2 - 2
materialsLibrary/dist/babylon.pbrMaterial.min.js


File diff suppressed because it is too large
+ 1 - 1
materialsLibrary/dist/babylon.terrainMaterial.js


File diff suppressed because it is too large
+ 1 - 1
materialsLibrary/dist/babylon.terrainMaterial.min.js


+ 1 - 0
materialsLibrary/dist/dts/babylon.pbrMaterial.d.ts

@@ -12,6 +12,7 @@ declare module BABYLON {
         cameraExposure: number;
         cameraContrast: number;
         private _cameraInfos;
+        private _microsurfaceTextureLods;
         overloadedAmbientIntensity: number;
         overloadedAlbedoIntensity: number;
         overloadedReflectivityIntensity: number;

+ 27 - 13
materialsLibrary/materials/pbr/babylon.pbrMaterial.ts

@@ -87,7 +87,8 @@ module BABYLON {
         public REFRACTIONMAP_3D = false;
         public LINKREFRACTIONTOTRANSPARENCY = false;
         public REFRACTIONMAPINLINEARSPACE = false;
-        
+        public LODBASEDMICROSFURACE = false;
+
         constructor() {
             super();
             this._keys = Object.keys(this);
@@ -111,6 +112,8 @@ module BABYLON {
         public cameraContrast: number = 1.0;
         private _cameraInfos: Vector4 = new Vector4(1.0, 1.0, 0.0, 0.0);
 
+        private _microsurfaceTextureLods: Vector2 = new Vector2(0.0, 0.0);
+
         public overloadedAmbientIntensity: number = 0.0;
         public overloadedAlbedoIntensity: number = 0.0;
         public overloadedReflectivityIntensity: number = 0.0;
@@ -204,16 +207,14 @@ module BABYLON {
         }
 
         public needAlphaBlending(): boolean {
-            if (this.linkRefractionWithTransparency)
-            {
+            if (this.linkRefractionWithTransparency) {
                 return false;
             }
             return (this.alpha < 1.0) || (this.opacityTexture != null) || this._shouldUseAlphaFromAlbedoTexture() || this.opacityFresnelParameters && this.opacityFresnelParameters.isEnabled;
         }
 
         public needAlphaTesting(): boolean {
-            if (this.linkRefractionWithTransparency)
-            {
+            if (this.linkRefractionWithTransparency) {
                 return false;
             }
             return this.albedoTexture != null && this.albedoTexture.hasAlpha;
@@ -425,6 +426,10 @@ module BABYLON {
             if (scene.texturesEnabled) {
                 // Textures
                 if (scene.texturesEnabled) {
+                    if (scene.getEngine().getCaps().textureLOD) {
+                        this._defines.LODBASEDMICROSFURACE = true;
+                    }
+
                     if (this.albedoTexture && StandardMaterial.DiffuseTextureEnabled) {
                         if (!this.albedoTexture.isReady()) {
                             return false;
@@ -808,7 +813,8 @@ module BABYLON {
                         "logarithmicDepthConstant",
                         "vSphericalX", "vSphericalY", "vSphericalZ",
                         "vSphericalXX", "vSphericalYY", "vSphericalZZ",
-                        "vSphericalXY", "vSphericalYZ", "vSphericalZX"
+                        "vSphericalXY", "vSphericalYZ", "vSphericalZX",
+                        "vMicrosurfaceTextureLods"
                     ],
                     ["albedoSampler", "ambientSampler", "opacitySampler", "reflectionCubeSampler", "reflection2DSampler", "emissiveSampler", "reflectivitySampler", "bumpSampler", "lightmapSampler", "refractionCubeSampler", "refraction2DSampler",
                         "shadowSampler0", "shadowSampler1", "shadowSampler2", "shadowSampler3"
@@ -902,6 +908,8 @@ module BABYLON {
                     }
 
                     if (this.reflectionTexture && StandardMaterial.ReflectionTextureEnabled) {
+                        this._microsurfaceTextureLods.x = Math.log(this.reflectionTexture.getSize().width) * Math.LOG2E;
+                        
                         if (this.reflectionTexture.isCube) {
                             this._effect.setTexture("reflectionCubeSampler", this.reflectionTexture);
                         } else {
@@ -971,6 +979,8 @@ module BABYLON {
                     }
 
                     if (this.refractionTexture && StandardMaterial.RefractionTextureEnabled) {
+                        this._microsurfaceTextureLods.y = Math.log(this.refractionTexture.getSize().width) * Math.LOG2E;
+                        
                         var depth = 1.0;
                         if (this.refractionTexture.isCube) {
                             this._effect.setTexture("refractionCubeSampler", this.refractionTexture);
@@ -984,6 +994,10 @@ module BABYLON {
                         }
                         this._effect.setFloat4("vRefractionInfos", this.refractionTexture.level, this.indexOfRefraction, depth, this.invertRefractionY ? -1 : 1);
                     }
+                    
+                    if ((this.reflectionTexture || this.refractionTexture) && this._myScene.getEngine().getCaps().textureLOD) {
+                        this._effect.setFloat2("vMicrosurfaceTextureLods", this._microsurfaceTextureLods.x, this._microsurfaceTextureLods.y);
+                    }
                 }
 
                 // Clip plane
@@ -1116,7 +1130,7 @@ module BABYLON {
             if (this.bumpTexture && this.bumpTexture.animations && this.bumpTexture.animations.length > 0) {
                 results.push(this.bumpTexture);
             }
-            
+
             if (this.lightmapTexture && this.lightmapTexture.animations && this.lightmapTexture.animations.length > 0) {
                 results.push(this.lightmapTexture);
             }
@@ -1156,7 +1170,7 @@ module BABYLON {
             if (this.bumpTexture) {
                 this.bumpTexture.dispose();
             }
-            
+
             if (this.lightmapTexture) {
                 this.lightmapTexture.dispose();
             }
@@ -1244,7 +1258,7 @@ module BABYLON {
             newPBRMaterial.useSpecularOverAlpha = this.useSpecularOverAlpha;
             newPBRMaterial.indexOfRefraction = this.indexOfRefraction;
             newPBRMaterial.invertRefractionY = this.invertRefractionY;
-            
+
             newPBRMaterial.emissiveFresnelParameters = this.emissiveFresnelParameters.clone();
             newPBRMaterial.opacityFresnelParameters = this.opacityFresnelParameters.clone();
 
@@ -1313,7 +1327,7 @@ module BABYLON {
                 serializationObject.refractionTexture = this.refractionTexture;
                 serializationObject.linkRefractionWithTransparency = this.linkRefractionWithTransparency;
             }
-            
+
             serializationObject.ambientColor = this.ambientColor.asArray();
             serializationObject.albedoColor = this.albedoColor.asArray();
             serializationObject.reflectivityColor = this.reflectivityColor.asArray();
@@ -1326,7 +1340,7 @@ module BABYLON {
             serializationObject.useSpecularOverAlpha = this.useSpecularOverAlpha;
             serializationObject.indexOfRefraction = this.indexOfRefraction;
             serializationObject.invertRefractionY = this.invertRefractionY;
-            
+
             serializationObject.emissiveFresnelParameters = this.emissiveFresnelParameters.serialize();
             serializationObject.opacityFresnelParameters = this.opacityFresnelParameters.serialize();
 
@@ -1420,8 +1434,8 @@ module BABYLON {
             material.useMicroSurfaceFromReflectivityMapAlpha = source.useMicroSurfaceFromReflectivityMapAlpha;
             material.useSpecularOverAlpha = source.useSpecularOverAlpha;
             material.indexOfRefraction = source.indexOfRefraction;
-            material.invertRefractionY = source.invertRefractionY; 
-            
+            material.invertRefractionY = source.invertRefractionY;
+
             material.emissiveFresnelParameters = FresnelParameters.Parse(source.emissiveFresnelParameters);
             material.opacityFresnelParameters = FresnelParameters.Parse(source.opacityFresnelParameters);
 

+ 61 - 7
materialsLibrary/materials/pbr/pbr.fragment.fx

@@ -2,6 +2,10 @@
 #extension GL_OES_standard_derivatives : enable
 #endif
 
+#ifdef LODBASEDMICROSFURACE
+#extension GL_EXT_shader_texture_lod : enable
+#endif
+
 #ifdef LOGARITHMICDEPTH
 #extension GL_EXT_frag_depth : enable
 #endif
@@ -67,8 +71,14 @@ uniform vec4 vCameraInfos;
     }
 #endif
 
+#ifdef LODBASEDMICROSFURACE
+    uniform vec2 vMicrosurfaceTextureLods;
+#endif
+
 // PBR CUSTOM CONSTANTS
 const float kPi = 3.1415926535897932384626433832795;
+const float kRougnhessToAlphaScale = 0.1;
+const float kRougnhessToAlphaOffset = 0.29248125;
 
 #ifdef PoissonSamplingEnvironment
     const int poissonSphereSamplersCount = 32;
@@ -145,6 +155,22 @@ float convertRoughnessToAverageSlope(float roughness)
     return alphaG;
 }
 
+// Based on Beckamm roughness to Blinn exponent + http://casual-effects.blogspot.ca/2011/08/plausible-environment-lighting-in-two.html 
+float getMipMapIndexFromAverageSlope(float maxMipLevel, float alpha)
+{
+    // do not take in account lower mips hence -1... and wait from proper preprocess.
+    // formula comes from approximation of the mathematical solution.
+    //float mip = maxMipLevel + kRougnhessToAlphaOffset + 0.5 * log2(alpha);
+    
+    // In the mean time 
+    // Always [0..1] goes from max mip to min mip in a log2 way.  
+    // Change 5 to nummip below.
+    // http://www.wolframalpha.com/input/?i=x+in+0..1+plot+(+5+%2B+0.3+%2B+0.1+*+5+*+log2(+(1+-+x)+*+(1+-+x)+%2B+0.0005))
+    float mip = kRougnhessToAlphaOffset + maxMipLevel + (maxMipLevel * kRougnhessToAlphaScale * log2(alpha));
+    
+    return clamp(mip, 0., maxMipLevel);
+}
+
 // From Microfacet Models for Refraction through Rough Surfaces, Walter et al. 2007
 float smithVisibilityG1_TrowbridgeReitzGGX(float dot, float alphaG)
 {
@@ -1112,17 +1138,27 @@ void main(void) {
 vec3 surfaceRefractionColor = vec3(0., 0., 0.);
 
 // Go mat -> blurry reflexion according to microSurface
-float bias = 20. * (1.0 - microSurface);
+#ifndef LODBASEDMICROSFURACE
+    float bias = 20. * (1.0 - microSurface);
+#endif
         
 #ifdef REFRACTION
 	vec3 refractionVector = normalize(refract(-viewDirectionW, normalW, vRefractionInfos.y));
     
+    #ifdef LODBASEDMICROSFURACE
+        float lodRefraction = getMipMapIndexFromAverageSlope(vMicrosurfaceTextureLods.y, Square(1.0 - microSurface + 0.0005));
+    #endif
+    
     #ifdef REFRACTIONMAP_3D
         refractionVector.y = refractionVector.y * vRefractionInfos.w;
 
         if (dot(refractionVector, viewDirectionW) < 1.0)
         {
-            surfaceRefractionColor = textureCube(refractionCubeSampler, refractionVector, bias).rgb * vRefractionInfos.x;
+            #ifdef LODBASEDMICROSFURACE
+                surfaceRefractionColor = textureCubeLodEXT(refractionCubeSampler, refractionVector, lodRefraction).rgb * vRefractionInfos.x;
+            #else
+                surfaceRefractionColor = textureCube(refractionCubeSampler, refractionVector, bias).rgb * vRefractionInfos.x;
+            #endif
         }
         
         #ifndef REFRACTIONMAPINLINEARSPACE
@@ -1135,9 +1171,14 @@ float bias = 20. * (1.0 - microSurface);
 
         refractionCoords.y = 1.0 - refractionCoords.y;
 
-        surfaceRefractionColor = texture2D(refraction2DSampler, refractionCoords).rgb * vRefractionInfos.x;
+        #ifdef LODBASEDMICROSFURACE
+            surfaceRefractionColor = texture2DLodEXT(refraction2DSampler, refractionCoords, lodRefraction).rgb * vRefractionInfos.x;
+        #else
+            surfaceRefractionColor = texture2D(refraction2DSampler, refractionCoords).rgb * vRefractionInfos.x;
+        #endif    
+        
         surfaceRefractionColor = toLinearSpace(surfaceRefractionColor.rgb); 
-    #endif    
+    #endif
 #endif
 
 // Reflection
@@ -1147,8 +1188,17 @@ vec3 environmentIrradiance = vReflectionColor.rgb;
 #ifdef REFLECTION
     vec3 vReflectionUVW = computeReflectionCoords(vec4(vPositionW, 1.0), normalW);
 
+    #ifdef LODBASEDMICROSFURACE
+        float lodReflection = getMipMapIndexFromAverageSlope(vMicrosurfaceTextureLods.x, Square(1.0 - microSurface + 0.0005));
+    #endif
+    
     #ifdef REFLECTIONMAP_3D
-        environmentRadiance = textureCube(reflectionCubeSampler, vReflectionUVW, bias).rgb * vReflectionInfos.x;
+        
+        #ifdef LODBASEDMICROSFURACE
+            environmentRadiance = textureCubeLodEXT(reflectionCubeSampler, vReflectionUVW, lodReflection).rgb * vReflectionInfos.x;
+        #else
+            environmentRadiance = textureCube(reflectionCubeSampler, vReflectionUVW, bias).rgb * vReflectionInfos.x;
+        #endif
         
         #ifdef PoissonSamplingEnvironment
             float alphaG = convertRoughnessToAverageSlope(rough);
@@ -1175,8 +1225,12 @@ vec3 environmentIrradiance = vReflectionColor.rgb;
         #endif
 
         coords.y = 1.0 - coords.y;
-
-        environmentRadiance = texture2D(reflection2DSampler, coords).rgb * vReflectionInfos.x;
+        #ifdef LODBASEDMICROSFURACE
+            environmentRadiance = texture2DLodExt(reflection2DSampler, coords, lodReflection).rgb * vReflectionInfos.x;
+        #else
+            environmentRadiance = texture2D(reflection2DSampler, coords).rgb * vReflectionInfos.x;
+        #endif
+    
         environmentRadiance = toLinearSpace(environmentRadiance.rgb);
 
         environmentIrradiance = texture2D(reflection2DSampler, coords, 20.).rgb * vReflectionInfos.x;

File diff suppressed because it is too large
+ 3555 - 3554
materialsLibrary/test/refs/babylon.max.js


+ 1 - 0
src/babylon.engine.js

@@ -455,6 +455,7 @@ var BABYLON;
             this._caps.highPrecisionShaderSupported = true;
             this._caps.drawBuffersExtension = this._gl.getExtension('WEBGL_draw_buffers');
             this._caps.textureFloatLinearFiltering = this._gl.getExtension('OES_texture_float_linear');
+            this._caps.textureLOD = this._gl.getExtension('EXT_shader_texture_lod');
             if (this._gl.getShaderPrecisionFormat) {
                 var highp = this._gl.getShaderPrecisionFormat(this._gl.FRAGMENT_SHADER, this._gl.HIGH_FLOAT);
                 this._caps.highPrecisionShaderSupported = highp.precision !== 0;

+ 2 - 0
src/babylon.engine.ts

@@ -387,6 +387,7 @@
         public highPrecisionShaderSupported: boolean;
         public fragmentDepthSupported: boolean;
         public textureFloatLinearFiltering: boolean;
+        public textureLOD: boolean;
         public drawBuffersExtension;
     }
 
@@ -659,6 +660,7 @@
             this._caps.highPrecisionShaderSupported = true;
             this._caps.drawBuffersExtension = this._gl.getExtension('WEBGL_draw_buffers');
             this._caps.textureFloatLinearFiltering = this._gl.getExtension('OES_texture_float_linear');
+            this._caps.textureLOD = this._gl.getExtension('EXT_shader_texture_lod');
 
             if (this._gl.getShaderPrecisionFormat) {
                 var highp = this._gl.getShaderPrecisionFormat(this._gl.FRAGMENT_SHADER, this._gl.HIGH_FLOAT);