Jelajahi Sumber

ESM are now enabled to replace VSM

David Catuhe 8 tahun lalu
induk
melakukan
a00329a708

+ 1 - 1
Playground/scripts/shadows.js

@@ -45,7 +45,7 @@
 	// Shadows
 	var shadowGenerator = new BABYLON.ShadowGenerator(1024, light);
 	shadowGenerator.getShadowMap().renderList.push(torus);
-	shadowGenerator.useVarianceShadowMap = true;
+	shadowGenerator.useExponentialShadowMap = true;
 
 	var shadowGenerator2 = new BABYLON.ShadowGenerator(1024, light2);
 	shadowGenerator2.getShadowMap().renderList.push(torus);

TEMPAT SAMPAH
assets/textures/Ground.jpg


File diff ditekan karena terlalu besar
+ 16 - 16
dist/preview release/babylon.core.js


File diff ditekan karena terlalu besar
+ 3989 - 3990
dist/preview release/babylon.d.ts


File diff ditekan karena terlalu besar
+ 19 - 19
dist/preview release/babylon.js


File diff ditekan karena terlalu besar
+ 55 - 53
dist/preview release/babylon.max.js


File diff ditekan karena terlalu besar
+ 3989 - 3990
dist/preview release/babylon.module.d.ts


File diff ditekan karena terlalu besar
+ 27 - 27
dist/preview release/babylon.noworker.js


+ 1 - 0
dist/preview release/what's new.md

@@ -5,6 +5,7 @@
 ### Major updates
  - WebGL2 context support. WebGL2 is now used instead of WebGL 1 when available. [More info here](http://doc.babylonjs.com/overviews/webgl2) ([deltakosh](https://github.com/deltakosh))
  - Complete WebVR 1.1 support including controllers for HTC Vive and Occulus. [More info here](http://doc.babylonjs.com/overviews/webvr_camera) ([raanan](https://github.com/raananw))
+ - Added support for Exponential Shadow maps to replace Variance Shadow maps. [Demo](http://www.babylonjs.com/Demos/AdvancedShadows/) ([deltakosh](https://github.com/deltakosh))
  - Support for [Vertex Array Objects](https://www.opengl.org/registry/specs/ARB/vertex_array_object.txt) ([deltakosh](https://github.com/deltakosh))
  - Support for multisample render targets. [Demo](http://www.babylonjs-playground.com/#12MKMN) ([deltakosh](https://github.com/deltakosh))
  - New Unity 5 Editor Toolkit. Complete pipeline integration [Doc](TODO) - ([MackeyK24](https://github.com/MackeyK24))

+ 47 - 37
src/Lights/Shadows/babylon.shadowGenerator.ts

@@ -7,32 +7,27 @@
  
     export class ShadowGenerator implements IShadowGenerator {
         private static _FILTER_NONE = 0;
-        private static _FILTER_VARIANCESHADOWMAP = 1;
+        private static _FILTER_EXPONENTIALSHADOWMAP = 1;
         private static _FILTER_POISSONSAMPLING = 2;
-        private static _FILTER_BLURVARIANCESHADOWMAP = 3;
-        private static _FILTER_EXPONENTIALSHADOWMAP = 4;
+        private static _FILTER_BLUREXPONENTIALSHADOWMAP = 3;
 
         // Static
         public static get FILTER_NONE(): number {
             return ShadowGenerator._FILTER_NONE;
         }
 
-        public static get FILTER_VARIANCESHADOWMAP(): number {
-            return ShadowGenerator._FILTER_VARIANCESHADOWMAP;
-        }
-
         public static get FILTER_POISSONSAMPLING(): number {
             return ShadowGenerator._FILTER_POISSONSAMPLING;
         }
 
-        public static get FILTER_BLURVARIANCESHADOWMAP(): number {
-            return ShadowGenerator._FILTER_BLURVARIANCESHADOWMAP;
-        }
-
         public static get FILTER_EXPONENTIALSHADOWMAP(): number {
             return ShadowGenerator._FILTER_EXPONENTIALSHADOWMAP;
         }
 
+        public static get FILTER_BLUREXPONENTIALSHADOWMAP(): number {
+            return ShadowGenerator._FILTER_BLUREXPONENTIALSHADOWMAP;
+        }
+
         // Members
         private _filter = ShadowGenerator.FILTER_NONE;
         public blurScale = 2;
@@ -64,7 +59,16 @@
                 this._boxBlurPostprocess.dispose();
             }
 
-            this._boxBlurPostprocess = new PostProcess("DepthBoxBlur", "depthBoxBlur", ["screenSize", "boxOffset"], [], 1.0 / this.blurScale, null, Texture.BILINEAR_SAMPLINGMODE, this._scene.getEngine(), false, "#define OFFSET " + value);
+            var textureType: number;
+            var caps = this._scene.getEngine().getCaps();
+            if (this._useFullFloat) {
+                textureType = Engine.TEXTURETYPE_FLOAT;
+            }
+            else {
+                textureType = Engine.TEXTURETYPE_UNSIGNED_INT;
+            }
+
+            this._boxBlurPostprocess = new PostProcess("DepthBoxBlur", "depthBoxBlur", ["screenSize", "boxOffset"], [], 1.0 / this.blurScale, null, Texture.BILINEAR_SAMPLINGMODE, this._scene.getEngine(), false, "#define OFFSET " + value, textureType);
             this._boxBlurPostprocess.onApplyObservable.add(effect => {
                 effect.setFloat2("screenSize", this._mapSize / this.blurScale, this._mapSize / this.blurScale);
             });
@@ -81,7 +85,7 @@
 
             this._filter = value;
 
-            if (this.useVarianceShadowMap || this.useBlurVarianceShadowMap || this.usePoissonSampling || this.useExponentialShadowMap) {
+            if (this.usePoissonSampling || this.useExponentialShadowMap || this.useBlurExponentialShadowMap) {
                 this._shadowMap.anisotropicFilteringLevel = 16;
                 this._shadowMap.updateSamplingMode(Texture.BILINEAR_SAMPLINGMODE);
             } else {
@@ -91,35 +95,43 @@
         }
 
         public get useVarianceShadowMap(): boolean {
-            return this.filter === ShadowGenerator.FILTER_VARIANCESHADOWMAP && this._light.supportsVSM();
+            Tools.Warn("VSM are now replaced by ESM. Please use useExponentialShadowMap instead.");
+            return this.useExponentialShadowMap;
         }
         public set useVarianceShadowMap(value: boolean) {
-            this.filter = (value ? ShadowGenerator.FILTER_VARIANCESHADOWMAP : ShadowGenerator.FILTER_NONE);
+            Tools.Warn("VSM are now replaced by ESM. Please use useExponentialShadowMap instead.");
+            this.useExponentialShadowMap = value;
+        }
+
+        public get useExponentialShadowMap(): boolean {
+            return this.filter === ShadowGenerator.FILTER_EXPONENTIALSHADOWMAP;
+        }
+        public set useExponentialShadowMap(value: boolean) {
+            this.filter = (value ? ShadowGenerator.FILTER_EXPONENTIALSHADOWMAP : ShadowGenerator.FILTER_NONE);
         }
 
         public get usePoissonSampling(): boolean {
-            return this.filter === ShadowGenerator.FILTER_POISSONSAMPLING ||
-                (!this._light.supportsVSM() && (
-                    this.filter === ShadowGenerator.FILTER_VARIANCESHADOWMAP ||
-                    this.filter === ShadowGenerator.FILTER_BLURVARIANCESHADOWMAP
-                ));
+            return this.filter === ShadowGenerator.FILTER_POISSONSAMPLING;
         }
+
         public set usePoissonSampling(value: boolean) {
             this.filter = (value ? ShadowGenerator.FILTER_POISSONSAMPLING : ShadowGenerator.FILTER_NONE);
         }
 
         public get useBlurVarianceShadowMap(): boolean {
-            return this.filter === ShadowGenerator.FILTER_BLURVARIANCESHADOWMAP && this._light.supportsVSM();
+            Tools.Warn("VSM are now replaced by ESM. Please use useBlurExponentialShadowMap instead.");
+            return this.useBlurExponentialShadowMap;
         }
         public set useBlurVarianceShadowMap(value: boolean) {
-            this.filter = (value ? ShadowGenerator.FILTER_BLURVARIANCESHADOWMAP : ShadowGenerator.FILTER_NONE);
+            Tools.Warn("VSM are now replaced by ESM. Please use useBlurExponentialShadowMap instead.");
+            this.useBlurExponentialShadowMap = value;
         }
 
-        public get useExponentialShadowMap(): boolean {
-            return this.filter === ShadowGenerator.FILTER_EXPONENTIALSHADOWMAP;
+        public get useBlurExponentialShadowMap(): boolean {
+            return this.filter === ShadowGenerator.FILTER_BLUREXPONENTIALSHADOWMAP;
         }
-        public set useExponentialShadowMap(value: boolean) {
-            this.filter = (value ? ShadowGenerator.FILTER_EXPONENTIALSHADOWMAP : ShadowGenerator.FILTER_NONE);
+        public set useBlurExponentialShadowMap(value: boolean) {
+            this.filter = (value ? ShadowGenerator.FILTER_BLUREXPONENTIALSHADOWMAP : ShadowGenerator.FILTER_NONE);
         }
 
         private _light: IShadowLight;
@@ -187,7 +199,7 @@
             });
 
             this._shadowMap.onAfterUnbindObservable.add(() => {
-                if (!this.useBlurVarianceShadowMap && !this.useExponentialShadowMap) {
+                if (!this.useBlurExponentialShadowMap) {
                     return;
                 }
 
@@ -197,7 +209,7 @@
                     this._shadowMap2.wrapV = Texture.CLAMP_ADDRESSMODE;
                     this._shadowMap2.updateSamplingMode(Texture.BILINEAR_SAMPLINGMODE);
 
-                    this._downSamplePostprocess = new PassPostProcess("downScale", 1.0 / this.blurScale, null, Texture.BILINEAR_SAMPLINGMODE, this._scene.getEngine());
+                    this._downSamplePostprocess = new PassPostProcess("downScale", 1.0 / this.blurScale, null, Texture.BILINEAR_SAMPLINGMODE, this._scene.getEngine(), false, textureType);
                     this._downSamplePostprocess.onApplyObservable.add(effect => {
                         effect.setTexture("textureSampler", this._shadowMap);
                     });
@@ -288,7 +300,7 @@
             };
 
             this._shadowMap.onClearObservable.add((engine: Engine) => {
-                if (this.useBlurVarianceShadowMap || this.useVarianceShadowMap) {
+                if (this.useExponentialShadowMap || this.useBlurExponentialShadowMap) {
                     engine.clear(new Color4(0, 0, 0, 0), true, true, true);
                 } else {
                     engine.clear(new Color4(1.0, 1.0, 1.0, 1.0), true, true, true);
@@ -305,9 +317,7 @@
                 defines.push("#define FULLFLOAT");
             }
 
-            if (this.useVarianceShadowMap || this.useBlurVarianceShadowMap) {
-                defines.push("#define VSM");
-            } else if (this.useExponentialShadowMap) {
+            if (this.useExponentialShadowMap || this.useBlurExponentialShadowMap) {
                 defines.push("#define ESM");
             }
 
@@ -497,7 +507,8 @@
 
             serializationObject.lightId = this._light.id;
             serializationObject.mapSize = this.getShadowMap().getRenderSize();
-            serializationObject.useVarianceShadowMap = this.useVarianceShadowMap;
+            serializationObject.useExponentialShadowMap = this.useExponentialShadowMap;
+            serializationObject.useBlurExponentialShadowMap = this.useBlurExponentialShadowMap;
             serializationObject.usePoissonSampling = this.usePoissonSampling;
             serializationObject.forceBackFacesOnly = this.forceBackFacesOnly;
             serializationObject.darkness = this.getDarkness();
@@ -528,14 +539,13 @@
 
             if (parsedShadowGenerator.usePoissonSampling) {
                 shadowGenerator.usePoissonSampling = true;
-            } else if (parsedShadowGenerator.useVarianceShadowMap) {
-                shadowGenerator.useVarianceShadowMap = true;
-            } else if (parsedShadowGenerator.useBlurVarianceShadowMap) {
-                shadowGenerator.useBlurVarianceShadowMap = true;
             }
             else if (parsedShadowGenerator.useExponentialShadowMap) {
                 shadowGenerator.useExponentialShadowMap = true;
             }
+            else if (parsedShadowGenerator.useBlurExponentialShadowMap) {
+                shadowGenerator.useBlurExponentialShadowMap = true;
+            }
 
             if (parsedShadowGenerator.blurScale) {
                 shadowGenerator.blurScale = parsedShadowGenerator.blurScale;

+ 1 - 1
src/Lights/babylon.directionalLight.ts

@@ -112,7 +112,7 @@ module BABYLON {
 
                 Matrix.OrthoOffCenterLHToRef(this._orthoLeft - xOffset * this.shadowOrthoScale, this._orthoRight + xOffset * this.shadowOrthoScale,
                     this._orthoBottom - yOffset * this.shadowOrthoScale, this._orthoTop + yOffset * this.shadowOrthoScale,
-                    -activeCamera.maxZ, activeCamera.maxZ, matrix);
+                    activeCamera.minZ, activeCamera.maxZ, matrix);
             }
             return this;
         }

+ 2 - 9
src/Materials/babylon.materialHelper.ts

@@ -84,21 +84,14 @@
 
                         defines["SHADOWS"] = true;
 
-                        if (shadowGenerator.useVarianceShadowMap || shadowGenerator.useBlurVarianceShadowMap) {
-                            if (defines["SHADOWVSM" + lightIndex] === undefined) {
-                                needRebuild = true;
-                            }
-
-                            defines["SHADOWVSM" + lightIndex] = true;
-                        } 
-                        else if (shadowGenerator.usePoissonSampling) {
+                        if (shadowGenerator.usePoissonSampling) {
                             if (defines["SHADOWPCF" + lightIndex] === undefined) {
                                 needRebuild = true;
                             }
 
                             defines["SHADOWPCF" + lightIndex] = true;
                         } 
-                        else if (shadowGenerator.useExponentialShadowMap) {
+                        else if (shadowGenerator.useExponentialShadowMap || shadowGenerator.useBlurExponentialShadowMap) {
                             if (defines["SHADOWESM" + lightIndex] === undefined) {
                                 needRebuild = true;
                             }

+ 2 - 2
src/PostProcess/babylon.passPostProcess.ts

@@ -1,7 +1,7 @@
 module BABYLON {
     export class PassPostProcess extends PostProcess {
-        constructor(name: string, options: number | PostProcessOptions, camera: Camera, samplingMode?: number, engine?: Engine, reusable?: boolean) {
-            super(name, "pass", null, null, options, camera, samplingMode, engine, reusable);
+        constructor(name: string, options: number | PostProcessOptions, camera: Camera, samplingMode?: number, engine?: Engine, reusable?: boolean, textureType: number = Engine.TEXTURETYPE_UNSIGNED_INT) {
+            super(name, "pass", null, null, options, camera, samplingMode, engine, reusable, null, textureType);
         }
     }
 } 

+ 5 - 39
src/Shaders/ShadersInclude/shadowsFragmentFunctions.fx

@@ -136,48 +136,12 @@
 		}
 	#endif
 
-	float linstep(float low, float high, float v) {
-		return clamp((v - low) / (high - low), 0.0, 1.0);
-	}
-
-	float ChebychevInequality(vec2 moments, float compare)
-	{
-		float p = smoothstep(compare, compare, moments.x);
-		float variance = max(moments.y - moments.x * moments.x, 0.02);
-		float d = compare - moments.x;
-		float p_max = linstep(0.2, 1.0, variance / (variance + d * d));
-
-		return clamp(max(p, p_max), 0.0, 1.0);
-	}
-
-	float computeShadowWithVSM(vec4 vPositionFromLight, sampler2D shadowSampler, float darkness)
-	{
-		vec3 depth = vPositionFromLight.xyz / vPositionFromLight.w;
-		depth = 0.5 * depth + vec3(0.5);
-		vec2 uv = depth.xy;
-
-		if (uv.x < 0. || uv.x > 1.0 || uv.y < 0. || uv.y > 1.0 || depth.z >= 1.0)
-		{
-			return 1.0;
-		}
-
-		vec4 texel = texture2D(shadowSampler, uv);
-
-		#ifndef SHADOWFULLFLOAT
-			vec2 moments = vec2(unpackHalf(texel.xy), unpackHalf(texel.zw));
-		#else
-			vec2 moments = texel.xy;
-		#endif
-
-		return min(1.0, 1.0 - ChebychevInequality(moments, depth.z) + darkness);
-	}
-
 	float computeShadowWithESM(vec4 vPositionFromLight, sampler2D shadowSampler, float darkness)
 	{
 		vec3 clipSpace = vPositionFromLight.xyz / vPositionFromLight.w;
 		vec3 depth = 0.5 * clipSpace + vec3(0.5);
 		vec2 uv = depth.xy;
-		float shadowPixelDepth = clipSpace.z;
+		float shadowPixelDepth = depth.z;
 
 		if (uv.x < 0. || uv.x > 1.0 || uv.y < 0. || uv.y > 1.0)
 		{
@@ -190,8 +154,8 @@
 			float shadowMapSample = texture2D(shadowSampler, uv).x;
 		#endif
 
-		const float shadowStrength = 50.0;
-		float esm = clamp(exp(shadowStrength * shadowPixelDepth) * shadowMapSample + darkness, 0., 1.);
+		const float shadowStrength = 5.;
+		float esm = 1.0 - clamp(exp(-shadowStrength * shadowPixelDepth) * shadowMapSample, 0., 1.);
 
 		// Apply fade out at frustum edge
 		const float fadeDistance = 0.07;
@@ -199,5 +163,7 @@
 		float mask = smoothstep(1.0, 1.0 - fadeDistance, dot(cs2, cs2));
 
 		return mix(1.0, esm, mask);
+
+		return esm;
 	}
 #endif

+ 5 - 16
src/Shaders/shadowMap.fragment.fx

@@ -55,24 +55,13 @@ void main(void)
 	depth += bias;
 
 #ifdef ESM
-	const float shadowStrength = 50.0;
-	depth = exp(-shadowStrength * depth);
+	const float shadowStrength = 5.0;
+	depth = exp(shadowStrength * depth);
 #endif
 
-#ifdef VSM
-	float moment1 = depth;
-	float moment2 = moment1 * moment1;
-
-	#ifndef FULLFLOAT
-		gl_FragColor = vec4(packHalf(moment1), packHalf(moment2));
-	#else
-		gl_FragColor = vec4(moment1, moment2, 1.0, 1.0);
-	#endif
+#ifndef FULLFLOAT
+	gl_FragColor = pack(depth);
 #else
-	#ifndef FULLFLOAT
-		gl_FragColor = pack(depth);
-	#else
-		gl_FragColor = vec4(depth, 1.0, 1.0, 1.0);
-	#endif
+	gl_FragColor = vec4(depth, 1.0, 1.0, 1.0);
 #endif
 }