Browse Source

various fixes :
webgl texture cleanup when filtering
clearcoat and refraction take into account realtime filter
moved realtimeFiltering property from BaseTexture to PBRBaseMaterial

Benjamin Guignabert 5 năm trước cách đây
mục cha
commit
ed019c06df

+ 34 - 12
src/Materials/PBR/pbrBaseMaterial.ts

@@ -626,6 +626,31 @@ export abstract class PBRBaseMaterial extends PushMaterial {
      */
     protected _forceIrradianceInFragment = false;
 
+    private _realTimeFiltering: boolean = false;
+    /**
+     * Enables realtime filtering on the texture.
+     */
+    public get realTimeFiltering() {
+        return this._realTimeFiltering;
+    }
+    public set realTimeFiltering(b: boolean) {
+        this._realTimeFiltering = b;
+        this.markAsDirty(Constants.MATERIAL_TextureDirtyFlag);
+    }
+
+    private _realTimeFilteringQuality: number = Constants.TEXTURE_FILTERING_QUALITY_LOW;
+    /**
+     * Quality switch for realtime filtering
+     */
+    public get realTimeFilteringQuality() : number {
+        return this._realTimeFilteringQuality;
+    }
+    public set realTimeFilteringQuality(n: number) {
+        this._realTimeFilteringQuality = n;
+        this.markAsDirty(Constants.MATERIAL_TextureDirtyFlag);
+    }
+
+
     /**
      * Force normal to face away from face.
      */
@@ -1164,7 +1189,7 @@ export abstract class PBRBaseMaterial extends PushMaterial {
 
         var uniforms = ["world", "view", "viewProjection", "vEyePosition", "vLightsType", "vAmbientColor", "vAlbedoColor", "vReflectivityColor", "vEmissiveColor", "visibility", "vReflectionColor",
             "vFogInfos", "vFogColor", "pointSize",
-            "vAlbedoInfos", "vAmbientInfos", "vOpacityInfos", "vReflectionInfos", "vReflectionPosition", "vReflectionSize", "vEmissiveInfos", "vReflectivityInfos",
+            "vAlbedoInfos", "vAmbientInfos", "vOpacityInfos", "vReflectionInfos", "vReflectionPosition", "vReflectionSize", "vEmissiveInfos", "vReflectivityInfos", "vReflectionFilteringInfo",
             "vMicroSurfaceSamplerInfos", "vBumpInfos", "vLightmapInfos",
             "mBones",
             "vClipPlane", "vClipPlane2", "vClipPlane3", "vClipPlane4", "vClipPlane5", "vClipPlane6", "albedoMatrix", "ambientMatrix", "opacityMatrix", "reflectionMatrix", "emissiveMatrix", "reflectivityMatrix", "normalMatrix", "microSurfaceSamplerMatrix", "bumpMatrix", "lightmapMatrix",
@@ -1178,8 +1203,7 @@ export abstract class PBRBaseMaterial extends PushMaterial {
             "vSphericalL2_2", "vSphericalL2_1", "vSphericalL20", "vSphericalL21", "vSphericalL22",
             "vReflectionMicrosurfaceInfos",
             "vTangentSpaceParams", "boneTextureWidth",
-            "vDebugMode",
-            "vFilteringInfo", "linearRoughness"
+            "vDebugMode"
         ];
 
         var samplers = ["albedoSampler", "reflectivitySampler", "ambientSampler", "emissiveSampler",
@@ -1282,8 +1306,8 @@ export abstract class PBRBaseMaterial extends PushMaterial {
                     defines.LODINREFLECTIONALPHA = reflectionTexture.lodLevelInAlpha;
                     defines.LINEARSPECULARREFLECTION = reflectionTexture.linearSpecularLOD;
 
-                    if (reflectionTexture.realTimeFiltering && reflectionTexture.realTimeFilteringQuality > 0) {
-                        defines.NUM_SAMPLES = reflectionTexture.realTimeFilteringQuality + "u";
+                    if (this.realTimeFiltering && this.realTimeFilteringQuality > 0) {
+                        defines.NUM_SAMPLES = this.realTimeFilteringQuality + "u";
                         defines.REALTIME_FILTERING = true;
                     } else {
                         defines.REALTIME_FILTERING = false;
@@ -1347,7 +1371,7 @@ export abstract class PBRBaseMaterial extends PushMaterial {
                         else if (reflectionTexture.isCube) {
                             defines.USESPHERICALFROMREFLECTIONMAP = true;
                             defines.USEIRRADIANCEMAP = false;
-                            if (this._forceIrradianceInFragment || reflectionTexture.realTimeFiltering || scene.getEngine().getCaps().maxVaryingVectors <= 8) {
+                            if (this._forceIrradianceInFragment || this.realTimeFiltering || scene.getEngine().getCaps().maxVaryingVectors <= 8) {
                                 defines.USESPHERICALINVERTEX = false;
                             }
                             else {
@@ -1563,6 +1587,7 @@ export abstract class PBRBaseMaterial extends PushMaterial {
         ubo.addUniform("vReflectivityInfos", 3);
         ubo.addUniform("vMicroSurfaceSamplerInfos", 2);
         ubo.addUniform("vReflectionInfos", 2);
+        ubo.addUniform("vReflectionFilteringInfo", 2);
         ubo.addUniform("vReflectionPosition", 3);
         ubo.addUniform("vReflectionSize", 3);
         ubo.addUniform("vBumpInfos", 3);
@@ -1695,12 +1720,9 @@ export abstract class PBRBaseMaterial extends PushMaterial {
                             ubo.updateVector3("vReflectionSize", cubeTexture.boundingBoxSize);
                         }
 
-                        if (reflectionTexture.realTimeFiltering) {
+                        if (this.realTimeFiltering) {
                             const width = reflectionTexture.getSize().width;
-                            const alpha = this._roughness! * this._roughness!;
-
-                            this._activeEffect.setFloat2("vFilteringInfo", width, Scalar.Log2(width));
-                            this._activeEffect.setFloat("linearRoughness", alpha);
+                            ubo.updateFloat2("vReflectionFilteringInfo", width, Scalar.Log2(width));
                         }
 
                         if (!defines.USEIRRADIANCEMAP) {
@@ -1881,7 +1903,7 @@ export abstract class PBRBaseMaterial extends PushMaterial {
                 }
             }
 
-            this.subSurface.bindForSubMesh(ubo, scene, engine, this.isFrozen, defines.LODBASEDMICROSFURACE);
+            this.subSurface.bindForSubMesh(ubo, scene, engine, this.isFrozen, defines.LODBASEDMICROSFURACE, this.realTimeFiltering);
             this.clearCoat.bindForSubMesh(ubo, scene, engine, this._disableBumpMap, this.isFrozen, this._invertNormalMapX, this._invertNormalMapY);
             this.anisotropy.bindForSubMesh(ubo, scene, this.isFrozen);
             this.sheen.bindForSubMesh(ubo, scene, this.isFrozen);

+ 15 - 5
src/Materials/PBR/pbrSubSurfaceConfiguration.ts

@@ -10,6 +10,7 @@ import { MaterialFlags } from "../materialFlags";
 import { UniformBuffer } from "../../Materials/uniformBuffer";
 import { MaterialHelper } from "../../Materials/materialHelper";
 import { EffectFallbacks } from '../effectFallbacks';
+import { Scalar } from "../../Maths/math.scalar";
 
 declare type Engine = import("../../Engines/engine").Engine;
 declare type Scene = import("../../scene").Scene;
@@ -286,10 +287,11 @@ export class PBRSubSurfaceConfiguration {
      * @param uniformBuffer defines the Uniform buffer to fill in.
      * @param scene defines the scene the material belongs to.
      * @param engine defines the engine the material belongs to.
-     * @param isFrozen defines wether the material is frozen or not.
-     * @param lodBasedMicrosurface defines wether the material relies on lod based microsurface or not.
+     * @param isFrozen defines whether the material is frozen or not.
+     * @param lodBasedMicrosurface defines whether the material relies on lod based microsurface or not.
+     * @param realTimeFiltering defines whether the textures should be filtered on the fly.
      */
-    public bindForSubMesh(uniformBuffer: UniformBuffer, scene: Scene, engine: Engine, isFrozen: boolean, lodBasedMicrosurface: boolean): void {
+    public bindForSubMesh(uniformBuffer: UniformBuffer, scene: Scene, engine: Engine, isFrozen: boolean, lodBasedMicrosurface: boolean, realTimeFiltering: boolean): void {
         var refractionTexture = this._getRefractionTexture(scene);
 
         if (!uniformBuffer.useUbo || !isFrozen || !uniformBuffer.isSync) {
@@ -309,11 +311,18 @@ export class PBRSubSurfaceConfiguration {
                         depth = (<any>refractionTexture).depth;
                     }
                 }
+
+                var width = refractionTexture.getSize().width;
+
                 uniformBuffer.updateFloat4("vRefractionInfos", refractionTexture.level, 1 / this._indexOfRefraction, depth, this._invertRefractionY ? -1 : 1);
                 uniformBuffer.updateFloat3("vRefractionMicrosurfaceInfos",
-                    refractionTexture.getSize().width,
+                    width,
                     refractionTexture.lodGenerationScale,
                     refractionTexture.lodGenerationOffset);
+
+                if (realTimeFiltering) {
+                    uniformBuffer.updateFloat2("vRefractionFilteringInfo", width, Scalar.Log2(width))
+                }
             }
 
             uniformBuffer.updateColor3("vDiffusionDistance", this.diffusionDistance);
@@ -499,7 +508,7 @@ export class PBRSubSurfaceConfiguration {
     public static AddUniforms(uniforms: string[]): void {
         uniforms.push(
             "vDiffusionDistance", "vTintColor", "vSubSurfaceIntensity",
-            "vRefractionMicrosurfaceInfos",
+            "vRefractionMicrosurfaceInfos", "vRefractionFilteringInfo",
             "vRefractionInfos", "vThicknessInfos", "vThicknessParam",
             "refractionMatrix", "thicknessMatrix");
     }
@@ -519,6 +528,7 @@ export class PBRSubSurfaceConfiguration {
      */
     public static PrepareUniformBuffer(uniformBuffer: UniformBuffer): void {
         uniformBuffer.addUniform("vRefractionMicrosurfaceInfos", 3);
+        uniformBuffer.addUniform("vRefractionFilteringInfo", 2);
         uniformBuffer.addUniform("vRefractionInfos", 4);
         uniformBuffer.addUniform("refractionMatrix", 16);
         uniformBuffer.addUniform("vThicknessInfos", 2);

+ 8 - 2
src/Materials/Textures/Filtering/hdrFiltering.ts

@@ -126,13 +126,19 @@ export class HDRFiltering {
                     alpha = 0;
                 }
 
-                effect.setFloat("linearRoughness", alpha);
+                effect.setFloat("alphaG", alpha);
 
                 this._effectRenderer.draw();
                 this._effectRenderer.restoreStates();
             }
         }
 
+        const engine = this._engine;
+
+        engine._gl.deleteTexture(texture._texture!._webGLTexture);
+
+        // Unbind channels
+        engine.unbindAllTextures();
         texture._texture!._webGLTexture = outputTexture._webGLTexture;
         return texture;
     }
@@ -151,7 +157,7 @@ export class HDRFiltering {
             vertexShader: "hdrFiltering",
             fragmentShader: "hdrFiltering",
             samplerNames: ["inputTexture"],
-            uniformNames: ["vSampleDirections", "vWeights", "up", "right", "front", "vFilteringInfo", "hdrScale", "linearRoughness"],
+            uniformNames: ["vSampleDirections", "vWeights", "up", "right", "front", "vFilteringInfo", "hdrScale", "alphaG"],
             useShaderStore: true,
             defines,
             onCompiled: onCompiled

+ 0 - 30
src/Materials/Textures/baseTexture.ts

@@ -345,36 +345,6 @@ export class BaseTexture implements IAnimatable {
         return "BaseTexture";
     }
 
-    private _realTimeFiltering: boolean = false;
-    /**
-     * Enables realtime filtering on the texture.
-     */
-    public get realTimeFiltering() {
-        return this._realTimeFiltering;
-    }
-    public set realTimeFiltering(b: boolean) {
-        this._realTimeFiltering = b;
-        let scene = this.getScene();
-        if (scene) {
-            scene.markAllMaterialsAsDirty(Constants.MATERIAL_TextureDirtyFlag);
-        }
-    }
-
-    private _realTimeFilteringQuality: number = Constants.TEXTURE_FILTERING_QUALITY_LOW;
-    /**
-     * Quality switch for realtime filtering
-     */
-    public get realTimeFilteringQuality() : number {
-        return this._realTimeFilteringQuality;
-    }
-    public set realTimeFilteringQuality(n: number) {
-        this._realTimeFilteringQuality = n;
-        let scene = this.getScene();
-        if (scene) {
-            scene.markAllMaterialsAsDirty(Constants.MATERIAL_TextureDirtyFlag);
-        }
-    }
-
     /**
      * Define the list of animation attached to the texture.
      */

+ 0 - 1
src/Probes/reflectionProbe.ts

@@ -92,7 +92,6 @@ export class ReflectionProbe {
         this._scene.reflectionProbes.push(this);
 
         this._renderTargetTexture = new RenderTargetTexture(name, size, scene, generateMipMaps, true, useFloat ? Constants.TEXTURETYPE_FLOAT : Constants.TEXTURETYPE_UNSIGNED_INT, true);
-        this._renderTargetTexture.realTimeFiltering = true;
         
         this._renderTargetTexture.onBeforeRenderObservable.add((faceIndex: number) => {
             switch (faceIndex) {

+ 13 - 12
src/Shaders/ShadersInclude/hdrFilteringFunctions.fx

@@ -1,8 +1,5 @@
 #ifdef NUM_SAMPLES
 	#if NUM_SAMPLES > 0u
-		uniform vec2 vFilteringInfo;
-		uniform float linearRoughness;
-
 		const float NUM_SAMPLES_FLOAT = float(NUM_SAMPLES);
 		const float NUM_SAMPLES_FLOAT_INVERSED = 1. / NUM_SAMPLES_FLOAT;
 
@@ -124,15 +121,17 @@
 		//
 		//
 
-		vec3 irradiance(samplerCube inputTexture, vec3 n) {
+		vec3 irradiance(samplerCube inputTexture, vec3 N, vec2 filteringInfo) {
+			vec3 n = normalize(N);
+
 		    vec3 result = vec3(0.0);
 			vec3 tangent = abs(n.z) < 0.999 ? vec3(0., 0., 1.) : vec3(1., 0., 0.);
 			tangent = normalize(cross(tangent, n));
 			vec3 bitangent = cross(n, tangent);
 			mat3 tbn = mat3(tangent, bitangent, n);
 
-		    float maxLevel = vFilteringInfo.y;
-		    float dim0 = vFilteringInfo.x;
+		    float maxLevel = filteringInfo.y;
+		    float dim0 = filteringInfo.x;
 		    float omegaP = (4. * PI) / (6. * dim0 * dim0);
 
 		    for(uint i = 0u; i < NUM_SAMPLES; ++i)
@@ -166,8 +165,10 @@
 		    return result;
 		}
 
-		vec3 radiance(samplerCube inputTexture, vec3 n) {
-			if (linearRoughness == 0.) {
+		vec3 radiance(float alphaG, samplerCube inputTexture, vec3 N, vec2 filteringInfo) {
+			vec3 n = normalize(N);
+
+			if (alphaG == 0.) {
 				vec3 c = textureCube(inputTexture, n).rgb;
 				#ifdef GAMMA_INPUT
 				    c = toLinearSpace(c);
@@ -181,15 +182,15 @@
 			vec3 bitangent = cross(n, tangent);
 			mat3 tbn = mat3(tangent, bitangent, n);
 
-			float maxLevel = vFilteringInfo.y;
-			float dim0 = vFilteringInfo.x;
+			float maxLevel = filteringInfo.y;
+			float dim0 = filteringInfo.x;
 			float omegaP = (4. * PI) / (6. * dim0 * dim0);
 
 			float weight = 0.;
 			for(uint i = 0u; i < NUM_SAMPLES; ++i)
 			{
 			    vec2 Xi = hammersley(i, NUM_SAMPLES);
-			    vec3 H = hemisphereImportanceSampleDggx(Xi, linearRoughness);
+			    vec3 H = hemisphereImportanceSampleDggx(Xi, alphaG);
 
 			    float NoV = 1.;
 			    float NoH = H.z;
@@ -199,7 +200,7 @@
 			    L = normalize(L);
 
 			    if (NoL > 0.) {
-			        float pdf_inversed = 4. / normalDistributionFunction_TrowbridgeReitzGGX(NoH, linearRoughness);
+			        float pdf_inversed = 4. / normalDistributionFunction_TrowbridgeReitzGGX(NoH, alphaG);
 
 			        float omegaS = NUM_SAMPLES_FLOAT_INVERSED * pdf_inversed;
 			        float l = log4(omegaS) - log4(omegaP) + log4(K);

+ 10 - 3
src/Shaders/ShadersInclude/pbrBlockReflection.fx

@@ -111,8 +111,15 @@
             #else
                 float requestedReflectionLOD = reflectionLOD;
             #endif
-
-            environmentRadiance = sampleReflectionLod(reflectionSampler, reflectionCoords, reflectionLOD);
+            #ifdef REALTIME_FILTERING
+                #ifdef LINEARSPECULARREFLECTION
+                    environmentRadiance = vec4(radiance(roughness, reflectionSampler, reflectionCoords, vReflectionFilteringInfo), 1.0);
+                #else
+                    environmentRadiance = vec4(radiance(alphaG, reflectionSampler, reflectionCoords, vReflectionFilteringInfo), 1.0);
+                #endif
+            #else
+                environmentRadiance = sampleReflectionLod(reflectionSampler, reflectionCoords, reflectionLOD);
+            #endif
         #else
             float lodReflectionNormalized = saturate(reflectionLOD / log2(vReflectionMicrosurfaceInfos.x));
             float lodReflectionNormalizedDoubled = lodReflectionNormalized * 2.0;
@@ -255,7 +262,7 @@
                 #endif
 
                 #ifdef REALTIME_FILTERING
-                    environmentIrradiance = irradiance(reflectionSampler, irradianceVector);
+                    environmentIrradiance = irradiance(reflectionSampler, vec3(irradianceVector.x, -irradianceVector.y, irradianceVector.z), vReflectionFilteringInfo);
                 #else
                     environmentIrradiance = computeEnvironmentIrradiance(irradianceVector);
                 #endif

+ 9 - 1
src/Shaders/ShadersInclude/pbrBlockSubSurface.fx

@@ -202,7 +202,15 @@ struct subSurfaceOutParams
                 float requestedRefractionLOD = refractionLOD;
             #endif
 
-            environmentRefraction = sampleRefractionLod(refractionSampler, refractionCoords, requestedRefractionLOD);
+            #ifdef REALTIME_FILTERING
+                #ifdef SS_LINEARSPECULARREFRACTION
+                    environmentRefraction = vec4(radiance(roughness, refractionSampler, refractionCoords, vRefractionFilteringInfo), 1.0);
+                #else
+                    environmentRefraction = vec4(radiance(alphaG, refractionSampler, refractionCoords, vRefractionFilteringInfo), 1.0);
+                #endif
+            #else
+                environmentRefraction = sampleRefractionLod(refractionSampler, refractionCoords, requestedRefractionLOD);
+            #endif
         #else
             float lodRefractionNormalized = saturate(refractionLOD / log2(vRefractionMicrosurfaceInfos.x));
             float lodRefractionNormalizedDoubled = lodRefractionNormalized * 2.0;

+ 6 - 0
src/Shaders/ShadersInclude/pbrFragmentDeclaration.fx

@@ -51,6 +51,9 @@ uniform mat4 view;
 // Reflection
 #ifdef REFLECTION
     uniform vec2 vReflectionInfos;
+    #ifdef REALTIME_FILTERING
+        uniform vec2 vReflectionFilteringInfo
+    #endif
     uniform mat4 reflectionMatrix;
     uniform vec3 vReflectionMicrosurfaceInfos;
 
@@ -116,6 +119,9 @@ uniform mat4 view;
         uniform vec3 vRefractionMicrosurfaceInfos;
         uniform vec4 vRefractionInfos;
         uniform mat4 refractionMatrix;
+        #ifdef REALTIME_FILTERING
+            uniform vec2 vRefractionFilteringInfo;
+        #endif
     #endif
 
     #ifdef SS_THICKNESSANDMASK_TEXTURE

+ 1 - 5
src/Shaders/ShadersInclude/pbrFragmentSamplersDeclaration.fx

@@ -144,11 +144,7 @@
         uniform samplerCube reflectionSampler;
         
         #ifdef LODBASEDMICROSFURACE
-            #ifdef REALTIME_FILTERING
-                #define sampleReflectionLod(s, c, l) vec4(radiance(s, c), 1.0)
-            #else
-                #define sampleReflectionLod(s, c, l) textureCubeLodEXT(s, c, l)
-            #endif
+            #define sampleReflectionLod(s, c, l) textureCubeLodEXT(s, c, l)
         #else
             uniform samplerCube reflectionSamplerLow;
             uniform samplerCube reflectionSamplerHigh;

+ 2 - 0
src/Shaders/ShadersInclude/pbrUboDeclaration.fx

@@ -10,6 +10,7 @@ uniform Material
     uniform vec3 vReflectivityInfos;
     uniform vec2 vMicroSurfaceSamplerInfos;
     uniform vec2 vReflectionInfos;
+    uniform vec2 vReflectionFilteringInfo;
     uniform vec3 vReflectionPosition;
     uniform vec3 vReflectionSize;
     uniform vec3 vBumpInfos;
@@ -55,6 +56,7 @@ uniform Material
     uniform mat4 sheenMatrix;
 
     uniform vec3 vRefractionMicrosurfaceInfos;
+    uniform vec2 vRefractionFilteringInfo;
     uniform vec4 vRefractionInfos;
     uniform mat4 refractionMatrix;
     uniform vec2 vThicknessInfos;

+ 3 - 1
src/Shaders/hdrFiltering.fragment.fx

@@ -3,13 +3,15 @@
 #include<pbrBRDFFunctions>
 #include<hdrFilteringFunctions>
 
+uniform float alphaG;
 uniform samplerCube inputTexture;
+uniform vec2 vFilteringInfo;
 uniform float hdrScale;
 
 varying vec3 direction;
 
 void main() {
-    vec3 color = radiance(inputTexture, direction);
+    vec3 color = radiance(alphaG, inputTexture, direction, vFilteringInfo);
 
     gl_FragColor = vec4(color * hdrScale, 1.0);
 }