Explorar o código

PCF Moved as a dedicated mode

sebastien %!s(int64=7) %!d(string=hai) anos
pai
achega
1f2ccc82d7

+ 4 - 0
materialsLibrary/src/gradient/babylon.gradientMaterial.ts

@@ -37,6 +37,10 @@ module BABYLON {
         public SHADOWESM1 = false;
         public SHADOWESM2 = false;
         public SHADOWESM3 = false;
+        public SHADOWPOISSON0 = false;
+        public SHADOWPOISSON1 = false;
+        public SHADOWPOISSON2 = false;
+        public SHADOWPOISSON3 = false;
         public SHADOWPCF0 = false;
         public SHADOWPCF1 = false;
         public SHADOWPCF2 = false;

+ 4 - 0
materialsLibrary/src/lava/babylon.lavaMaterial.ts

@@ -37,6 +37,10 @@ module BABYLON {
         public SHADOWESM1 = false;
         public SHADOWESM2 = false;
         public SHADOWESM3 = false;
+        public SHADOWPOISSON0 = false;
+        public SHADOWPOISSON1 = false;
+        public SHADOWPOISSON2 = false;
+        public SHADOWPOISSON3 = false;
         public SHADOWPCF0 = false;
         public SHADOWPCF1 = false;
         public SHADOWPCF2 = false;

+ 4 - 0
materialsLibrary/src/normal/babylon.normalMaterial.ts

@@ -37,6 +37,10 @@ module BABYLON {
         public SHADOWESM1 = false;
         public SHADOWESM2 = false;
         public SHADOWESM3 = false;
+        public SHADOWPOISSON0 = false;
+        public SHADOWPOISSON1 = false;
+        public SHADOWPOISSON2 = false;
+        public SHADOWPOISSON3 = false;
         public SHADOWPCF0 = false;
         public SHADOWPCF1 = false;
         public SHADOWPCF2 = false;

+ 1 - 1
src/Engine/babylon.engine.ts

@@ -2751,7 +2751,7 @@
 
             this.onBeforeShaderCompilationObservable.notifyObservers(this);
 
-            var shaderVersion = (this._webGLVersion > 1) ? "#version 300 es\n" : "";
+            var shaderVersion = (this._webGLVersion > 1) ? "#version 300 es\n#define WEBGL2 \n" : "";
             var vertexShader = compileShader(context, vertexCode, "vertex", defines, shaderVersion);
             var fragmentShader = compileShader(context, fragmentCode, "fragment", defines, shaderVersion);
 

+ 52 - 22
src/Lights/Shadows/babylon.shadowGenerator.ts

@@ -87,6 +87,7 @@
         private static _FILTER_BLUREXPONENTIALSHADOWMAP = 3;
         private static _FILTER_CLOSEEXPONENTIALSHADOWMAP = 4;
         private static _FILTER_BLURCLOSEEXPONENTIALSHADOWMAP = 5;
+        private static _FILTER_PCF = 6;
 
         /**
          * Shadow generator mode None: no filtering applied.
@@ -137,6 +138,15 @@
             return ShadowGenerator._FILTER_BLURCLOSEEXPONENTIALSHADOWMAP;
         }
 
+        /**
+         * Shadow generator mode PCF: Percentage Closer Filtering 
+         * benefits from Webgl 2 shadow samplers. Fallback to Poisson Sampling in Webgl 1
+         * (https://developer.nvidia.com/gpugems/GPUGems/gpugems_ch11.html)
+         */
+        public static get FILTER_PCF(): number {
+            return ShadowGenerator._FILTER_PCF;
+        }
+
         private _bias = 0.00005;
         /**
          * Gets the bias: offset applied on the depth preventing acnea.
@@ -275,6 +285,18 @@
                 }
             }
 
+            // Weblg1 fallback for PCF.
+            if (value === ShadowGenerator.FILTER_PCF) {
+                if (this._scene.getEngine().webGLVersion === 1) {
+                    this.usePoissonSampling = true;
+                    return;
+                }
+                this._useDepthStencilTexture = true;
+            }
+            else {
+                this._useDepthStencilTexture = false;
+            }
+
             if (this._filter === value) {
                 return;
             }
@@ -286,13 +308,13 @@
         }
 
         /**
-         * Gets if the current filter is set to Poisson Sampling aka PCF.
+         * Gets if the current filter is set to Poisson Sampling.
          */
         public get usePoissonSampling(): boolean {
             return this.filter === ShadowGenerator.FILTER_POISSONSAMPLING;
         }
         /**
-         * Sets the current filter to Poisson Sampling aka PCF.
+         * Sets the current filter to Poisson Sampling.
          */
         public set usePoissonSampling(value: boolean) {
             if (!value && this.filter !== ShadowGenerator.FILTER_POISSONSAMPLING) {
@@ -394,7 +416,7 @@
             return this.filter === ShadowGenerator.FILTER_BLURCLOSEEXPONENTIALSHADOWMAP;
         }
         /**
-         * Sets the current filter to fileterd "close ESM" (using the inverse of the 
+         * Sets the current filter to filtered "close ESM" (using the inverse of the 
          * exponential to prevent steep falloff artifacts).
          */
         public set useBlurCloseExponentialShadowMap(value: boolean) {
@@ -404,6 +426,22 @@
             this.filter = (value ? ShadowGenerator.FILTER_BLURCLOSEEXPONENTIALSHADOWMAP : ShadowGenerator.FILTER_NONE);
         }
 
+        /**
+         * Gets if the current filter is set to "PCF" (percentage closer filtering).
+         */
+        public get usePercentageCloserFiltering(): boolean {
+            return this.filter === ShadowGenerator.FILTER_PCF;
+        }
+        /**
+         * Sets the current filter to "PCF" (percentage closer filtering).
+         */
+        public set usePercentageCloserFiltering(value: boolean) {
+            if (!value && this.filter !== ShadowGenerator.FILTER_PCF) {
+                return;
+            }
+            this.filter = (value ? ShadowGenerator.FILTER_PCF : ShadowGenerator.FILTER_NONE);
+        }
+
         private _darkness = 0;
         /**
          * Returns the darkness value (float). This can only decrease the actual darkness of a shadow.
@@ -806,22 +844,10 @@
                 return;
             }
 
-            this._useDepthStencilTexture = false;
-            if (this._scene.getEngine().webGLVersion > 1) {
-                if (this.filter === ShadowGenerator.FILTER_NONE) {
-                    this._useDepthStencilTexture = true;
-                }
-                else {
-                    this._useDepthStencilTexture = false;
-                    this._shadowMap.updateSamplingMode(Texture.BILINEAR_SAMPLINGMODE);
-                }
-            }
-            else {
-                if (this.filter === ShadowGenerator.FILTER_NONE) {
-                    this._shadowMap.updateSamplingMode(Texture.NEAREST_SAMPLINGMODE);
-                } else {
-                    this._shadowMap.updateSamplingMode(Texture.BILINEAR_SAMPLINGMODE);
-                }
+            if (this.filter === ShadowGenerator.FILTER_NONE) {
+                this._shadowMap.updateSamplingMode(Texture.NEAREST_SAMPLINGMODE);
+            } else {
+                this._shadowMap.updateSamplingMode(Texture.BILINEAR_SAMPLINGMODE);
             }
         }
 
@@ -914,6 +940,9 @@
             if (this.useExponentialShadowMap || this.useBlurExponentialShadowMap) {
                 defines.push("#define ESM");
             }
+            else if (this.usePercentageCloserFiltering) {
+                defines.push("#define PCF");
+            }
 
             var attribs = [VertexBuffer.PositionKind];
 
@@ -1007,13 +1036,14 @@
                 return;
             }
 
-            defines["USEDEPTHSTENCILTEXTURE"] = defines["USEDEPTHSTENCILTEXTURE"] || this._useDepthStencilTexture;
-            defines["USEDEPTHSTENCILTEXTURE" + lightIndex] = this._useDepthStencilTexture;
             defines["SHADOW" + lightIndex] = true;
 
-            if (this.usePoissonSampling) {
+            if (this.usePercentageCloserFiltering) {
                 defines["SHADOWPCF" + lightIndex] = true;
             }
+            else if (this.usePoissonSampling) {
+                defines["SHADOWPOISSON" + lightIndex] = true;
+            }
             else if (this.useExponentialShadowMap || this.useBlurExponentialShadowMap) {
                 defines["SHADOWESM" + lightIndex] = true;
             }

+ 1 - 1
src/Materials/babylon.effect.ts

@@ -527,7 +527,7 @@
 
         private _dumpShadersSource(vertexCode: string, fragmentCode: string, defines: string): void {
             // Rebuild shaders source code
-            var shaderVersion = (this._engine.webGLVersion > 1) ? "#version 300 es\n" : "";
+            var shaderVersion = (this._engine.webGLVersion > 1) ? "#version 300 es\n#define WEBGL2 \n" : "";
             var prefix = shaderVersion + (defines ? defines + "\n" : "");
             vertexCode = prefix + vertexCode;
             fragmentCode = prefix + fragmentCode;

+ 5 - 0
src/Materials/babylon.materialHelper.ts

@@ -239,6 +239,7 @@ module BABYLON {
                     // Shadows
                     defines["SHADOW" + lightIndex] = false;
                     defines["SHADOWPCF" + lightIndex] = false;
+                    defines["SHADOWPOISSON" + lightIndex] = false;
                     defines["SHADOWESM" + lightIndex] = false;
                     defines["SHADOWCUBE" + lightIndex] = false;
 
@@ -387,6 +388,10 @@ module BABYLON {
                         fallbacks.addFallback(rank, "SHADOWPCF" + lightIndex);
                     }
 
+                    if (defines["SHADOWPOISSON" + lightIndex]) {
+                        fallbacks.addFallback(rank, "SHADOWPOISSON" + lightIndex);
+                    }
+
                     if (defines["SHADOWESM" + lightIndex]) {
                         fallbacks.addFallback(rank, "SHADOWESM" + lightIndex);
                     }

+ 6 - 6
src/Shaders/ShadersInclude/lightFragment.fx

@@ -42,18 +42,18 @@
 					shadow = computeShadowWithESM(vPositionFromLight{X}, vDepthMetric{X}, shadowSampler{X}, light{X}.shadowsInfo.x, light{X}.shadowsInfo.z, light{X}.shadowsInfo.w);
 				#endif
 			#else	
-				#ifdef SHADOWPCF{X}
+				#ifdef SHADOWPOISSON{X}
 					#if defined(SHADOWCUBE{X})
-						shadow = computeShadowWithPCFCube(light{X}.vLightData.xyz, shadowSampler{X}, light{X}.shadowsInfo.y, light{X}.shadowsInfo.x, light{X}.depthValues);
+						shadow = computeShadowWithPoissonSamplingCube(light{X}.vLightData.xyz, shadowSampler{X}, light{X}.shadowsInfo.y, light{X}.shadowsInfo.x, light{X}.depthValues);
 					#else
-						shadow = computeShadowWithPCF(vPositionFromLight{X}, vDepthMetric{X}, shadowSampler{X}, light{X}.shadowsInfo.y, light{X}.shadowsInfo.x, light{X}.shadowsInfo.w);
+						shadow = computeShadowWithPoissonSampling(vPositionFromLight{X}, vDepthMetric{X}, shadowSampler{X}, light{X}.shadowsInfo.y, light{X}.shadowsInfo.x, light{X}.shadowsInfo.w);
 					#endif
 				#else
-					#if defined(USEDEPTHSTENCILTEXTURE{X})
+					#if defined(SHADOWPCF{X})
 						#if defined(SHADOWCUBE{X})
-							shadow = computeShadowFromDepthTextureCube(light{X}.vLightData.xyz, shadowSampler{X}, light{X}.shadowsInfo.x, light{X}.depthValues);
+							shadow = computeShadowWithPCFCube(light{X}.vLightData.xyz, shadowSampler{X}, light{X}.shadowsInfo.x, light{X}.depthValues);
 						#else
-							shadow = computeShadowFromDepthTexture(vPositionFromLight{X}, vDepthMetric{X}, shadowSampler{X}, light{X}.shadowsInfo.x, light{X}.shadowsInfo.w);
+							shadow = computeShadowWithPCF(vPositionFromLight{X}, vDepthMetric{X}, shadowSampler{X}, light{X}.shadowsInfo.x, light{X}.shadowsInfo.w);
 						#endif
 					#else
 						#if defined(SHADOWCUBE{X})

+ 2 - 2
src/Shaders/ShadersInclude/lightFragmentDeclaration.fx

@@ -8,7 +8,7 @@
 	#endif
 	#ifdef SHADOW{X}
 		#if defined(SHADOWCUBE{X})
-			#if defined(USEDEPTHSTENCILTEXTURE{X})
+			#if defined(SHADOWPCF{X})
 				uniform highp samplerCubeShadow shadowSampler{X};
 			#else
 				uniform samplerCube shadowSampler{X};
@@ -17,7 +17,7 @@
 			varying vec4 vPositionFromLight{X};
 			varying float vDepthMetric{X};
 
-			#if defined(USEDEPTHSTENCILTEXTURE{X})
+			#if defined(SHADOWPCF{X})
 				uniform highp sampler2DShadow shadowSampler{X};
 			#else
 				uniform sampler2D shadowSampler{X};

+ 2 - 2
src/Shaders/ShadersInclude/lightUboDeclaration.fx

@@ -19,7 +19,7 @@
 #endif
 #ifdef SHADOW{X}
 	#if defined(SHADOWCUBE{X})
-		#if defined(USEDEPTHSTENCILTEXTURE{X})
+		#if defined(SHADOWPCF{X})
 			uniform highp samplerCubeShadow shadowSampler{X};
 		#else
 			uniform samplerCube shadowSampler{X};
@@ -28,7 +28,7 @@
 		varying vec4 vPositionFromLight{X};
 		varying float vDepthMetric{X};
 
-		#if defined(USEDEPTHSTENCILTEXTURE{X})
+		#if defined(SHADOWPCF{X})
 			uniform highp sampler2DShadow shadowSampler{X};
 		#else
 			uniform sampler2D shadowSampler{X};

+ 44 - 44
src/Shaders/ShadersInclude/shadowsFragmentFunctions.fx

@@ -7,25 +7,6 @@
 		}
 	#endif
 
-#ifdef USEDEPTHSTENCILTEXTURE
-	float computeShadowFromDepthTextureCube(vec3 lightPosition, samplerCubeShadow shadowSampler, float darkness, vec2 depthValues)
-	{
-		vec4 directionToLight = vec4(vPositionW - lightPosition, 1.0);
-		directionToLight.w = length(directionToLight.xyz);
-		directionToLight.w = (directionToLight.w + depthValues.x) / (depthValues.y);
-		directionToLight.w = clamp(directionToLight.w, 0., 1.0);
-
-		directionToLight.xyz = normalize(directionToLight.xyz);
-		directionToLight.y = -directionToLight.y;
-		
-		float shadow = textureCube(shadowSampler, directionToLight);
-		if (shadow < 1.0)
-		{
-			return shadow * (1. - darkness) + darkness;
-		}
-		return 1.0;
-	}
-#else
 	float computeShadowCube(vec3 lightPosition, samplerCube shadowSampler, float darkness, vec2 depthValues)
 	{
 		vec3 directionToLight = vPositionW - lightPosition;
@@ -48,9 +29,8 @@
 		}
 		return 1.0;
 	}
-#endif
 
-	float computeShadowWithPCFCube(vec3 lightPosition, samplerCube shadowSampler, float mapSize, float darkness, vec2 depthValues)
+	float computeShadowWithPoissonSamplingCube(vec3 lightPosition, samplerCube shadowSampler, float mapSize, float darkness, vec2 depthValues)
 	{
 		vec3 directionToLight = vPositionW - lightPosition;
 		float depth = length(directionToLight);
@@ -85,6 +65,26 @@
 		return  min(1.0, visibility + darkness);
 	}
 
+#ifdef WEBGL2
+	float computeShadowWithPCFCube(vec3 lightPosition, samplerCubeShadow shadowSampler, float darkness, vec2 depthValues)
+	{
+		vec4 directionToLight = vec4(vPositionW - lightPosition, 1.0);
+		directionToLight.w = length(directionToLight.xyz);
+		directionToLight.w = (directionToLight.w + depthValues.x) / (depthValues.y);
+		directionToLight.w = clamp(directionToLight.w, 0., 1.0);
+
+		directionToLight.xyz = normalize(directionToLight.xyz);
+		directionToLight.y = -directionToLight.y;
+		
+		float shadow = textureCube(shadowSampler, directionToLight);
+		if (shadow < 1.0)
+		{
+			return shadow * (1. - darkness) + darkness;
+		}
+		return 1.0;
+	}
+#endif
+
 	float computeShadowWithESMCube(vec3 lightPosition, samplerCube shadowSampler, float darkness, float depthScale, vec2 depthValues)
 	{
 		vec3 directionToLight = vPositionW - lightPosition;
@@ -126,27 +126,6 @@
 		return esm;
 	}
 
-#ifdef USEDEPTHSTENCILTEXTURE
-	float computeShadowFromDepthTexture(vec4 vPositionFromLight, float depthMetric, sampler2DShadow shadowSampler, float darkness, float frustumEdgeFalloff)
-	{
-		vec3 clipSpace = vPositionFromLight.xyz / vPositionFromLight.w;
-		//vec3 uvDepth = vec3(0.5 * clipSpace.xyz + vec3(0.5));
-		vec3 uvDepth = vec3(0.5 * clipSpace.xy + vec2(0.5), depthMetric);
-
-		if (uvDepth.x < 0. || uvDepth.x > 1.0 || uvDepth.y < 0. || uvDepth.y > 1.0)
-		{
-			return 1.0;
-		}
-
-		float shadow = texture2D(shadowSampler, uvDepth);
-		if (shadow < 1.0)
-		{
-			shadow = shadow * (1. - darkness) + darkness;
-			return computeFallOff(shadow, clipSpace.xy, frustumEdgeFalloff);
-		}
-		return 1.0;
-	}
-#else
 	float computeShadow(vec4 vPositionFromLight, float depthMetric, sampler2D shadowSampler, float darkness, float frustumEdgeFalloff)
 	{
 		vec3 clipSpace = vPositionFromLight.xyz / vPositionFromLight.w;
@@ -171,9 +150,8 @@
 		}
 		return 1.;
 	}
-#endif
 
-	float computeShadowWithPCF(vec4 vPositionFromLight, float depthMetric, sampler2D shadowSampler, float mapSize, float darkness, float frustumEdgeFalloff)
+	float computeShadowWithPoissonSampling(vec4 vPositionFromLight, float depthMetric, sampler2D shadowSampler, float mapSize, float darkness, float frustumEdgeFalloff)
 	{
 		vec3 clipSpace = vPositionFromLight.xyz / vPositionFromLight.w;
 		vec2 uv = 0.5 * clipSpace.xy + vec2(0.5);
@@ -210,6 +188,28 @@
 		return computeFallOff(min(1.0, visibility + darkness), clipSpace.xy, frustumEdgeFalloff);
 	}
 
+#ifdef WEBGL2
+	float computeShadowWithPCF(vec4 vPositionFromLight, float depthMetric, sampler2DShadow shadowSampler, float darkness, float frustumEdgeFalloff)
+	{
+		vec3 clipSpace = vPositionFromLight.xyz / vPositionFromLight.w;
+		//vec3 uvDepth = vec3(0.5 * clipSpace.xyz + vec3(0.5));
+		vec3 uvDepth = vec3(0.5 * clipSpace.xy + vec2(0.5), depthMetric);
+
+		if (uvDepth.x < 0. || uvDepth.x > 1.0 || uvDepth.y < 0. || uvDepth.y > 1.0)
+		{
+			return 1.0;
+		}
+
+		float shadow = texture2D(shadowSampler, uvDepth);
+		if (shadow < 1.0)
+		{
+			shadow = shadow * (1. - darkness) + darkness;
+			return computeFallOff(shadow, clipSpace.xy, frustumEdgeFalloff);
+		}
+		return 1.0;
+	}
+#endif
+
 	float computeShadowWithESM(vec4 vPositionFromLight, float depthMetric, sampler2D shadowSampler, float darkness, float depthScale, float frustumEdgeFalloff)
 	{
 		vec3 clipSpace = vPositionFromLight.xyz / vPositionFromLight.w;

+ 5 - 2
src/Shaders/shadowMap.vertex.fx

@@ -30,9 +30,12 @@ void main(void)
 
 vec4 worldPos = finalWorld * vec4(position, 1.0);
 gl_Position = viewProjection * worldPos;
-gl_Position.z += biasAndScale.x * depthValues.y;
 
-vDepthMetric = ((gl_Position.z + depthValues.x) / (depthValues.y)) + biasAndScale.x;
+#ifdef PCF
+	gl_Position.z += biasAndScale.x * depthValues.y;
+#else
+	vDepthMetric = ((gl_Position.z + depthValues.x) / (depthValues.y)) + biasAndScale.x;
+#endif
 
 #ifdef ALPHATEST
 	#ifdef UV1