sebastien 7 лет назад
Родитель
Сommit
0e6ce0ec5e

+ 62 - 5
src/Lights/Shadows/babylon.shadowGenerator.ts

@@ -155,18 +155,32 @@
 
         private _bias = 0.00005;
         /**
-         * Gets the bias: offset applied on the depth preventing acnea.
+         * Gets the bias: offset applied on the depth preventing acnea (in light direction).
          */
         public get bias(): number {
             return this._bias;
         }
         /**
-         * Sets the bias: offset applied on the depth preventing acnea.
+         * Sets the bias: offset applied on the depth preventing acnea (in light direction).
          */
         public set bias(bias: number) {
             this._bias = bias;
         }
 
+        private _normalBias = 0;
+        /**
+         * Gets the normalBias: offset applied on the depth preventing acnea (along side the normal direction and proportinal to the light/normal angle).
+         */
+        public get normalBias(): number {
+            return this._normalBias;
+        }
+        /**
+         * Sets the normalBias: offset applied on the depth preventing acnea (along side the normal direction and proportinal to the light/normal angle).
+         */
+        public set normalBias(normalBias: number) {
+            this._normalBias = normalBias;
+        }
+
         private _blurBoxOffset = 1;
         /**
          * Gets the blur box offset: offset applied during the blur pass.
@@ -860,10 +874,15 @@
                 engine.enableEffect(this._effect);
                 mesh._bind(subMesh, this._effect, Material.TriangleFillMode);
 
-                this._effect.setFloat2("biasAndScale", this.bias, this.depthScale);
+                this._effect.setFloat3("biasAndScale", this.bias, this.normalBias, this.depthScale);
 
                 this._effect.setMatrix("viewProjection", this.getTransformMatrix());
-                this._effect.setVector3("lightPosition", this.getLight().position);
+                if (this.getLight().getTypeID() === Light.LIGHTTYPEID_DIRECTIONALLIGHT) {
+                    this._effect.setVector3("lightData", this._cachedDirection);
+                }
+                else {
+                    this._effect.setVector3("lightData", this._cachedPosition);
+                }
 
                 if (scene.activeCamera) {
                     this._effect.setFloat2("depthValues", this.getLight().getDepthMinZ(scene.activeCamera), this.getLight().getDepthMinZ(scene.activeCamera) + this.getLight().getDepthMaxZ(scene.activeCamera));
@@ -1012,6 +1031,18 @@
             var mesh = subMesh.getMesh();
             var material = subMesh.getMaterial();
 
+            // Normal bias.
+            if (this.normalBias && mesh.isVerticesDataPresent(VertexBuffer.NormalKind)) {
+                attribs.push(VertexBuffer.NormalKind);
+                defines.push("#define NORMAL");
+                if (mesh.nonUniformScaling) {
+                    defines.push("#define NONUNIFORMSCALING");
+                }
+                if (this.getLight().getTypeID() === Light.LIGHTTYPEID_DIRECTIONALLIGHT) {
+                    defines.push("#define DIRECTIONINLIGHTDATA");
+                }
+            }
+
             // Alpha test
             if (material && material.needAlphaTesting()) {
                 var alphaTexture = material.getAlphaTestTexture();
@@ -1059,7 +1090,7 @@
                 this._cachedDefines = join;
                 this._effect = this._scene.getEngine().createEffect("shadowMap",
                     attribs,
-                    ["world", "mBones", "viewProjection", "diffuseMatrix", "lightPosition", "depthValues", "biasAndScale"],
+                    ["world", "mBones", "viewProjection", "diffuseMatrix", "lightData", "depthValues", "biasAndScale"],
                     ["diffuseSampler"], join);
             }
 
@@ -1328,6 +1359,14 @@
             serializationObject.useKernelBlur = this.useKernelBlur;
             serializationObject.transparencyShadow = this._transparencyShadow;
 
+            serializationObject.bias = this.bias;
+            serializationObject.normalBias = this.normalBias;
+
+            serializationObject.usePercentageCloserFiltering = this.usePercentageCloserFiltering;
+            serializationObject.useContactHardeningShadow = this.useContactHardeningShadow;
+            serializationObject.filteringQuality = this.filteringQuality;
+            serializationObject.contactHardeningLightSizeUVRatio = this.contactHardeningLightSizeUVRatio;
+
             serializationObject.renderList = [];
             if (shadowMap.renderList) {
                 for (var meshIndex = 0; meshIndex < shadowMap.renderList.length; meshIndex++) {
@@ -1380,6 +1419,20 @@
             else if (parsedShadowGenerator.useBlurCloseExponentialShadowMap) {
                 shadowGenerator.useBlurCloseExponentialShadowMap = true;
             }
+            else if (parsedShadowGenerator.usePercentageCloserFiltering) {
+                shadowGenerator.usePercentageCloserFiltering = true;
+            }
+            else if (parsedShadowGenerator.useContactHardeningShadow) {
+                shadowGenerator.useContactHardeningShadow = true;
+            }
+
+            if (parsedShadowGenerator.filteringQuality) {
+                shadowGenerator.filteringQuality = parsedShadowGenerator.filteringQuality;
+            }
+
+            if (parsedShadowGenerator.contactHardeningLightSizeUVRatio) {
+                shadowGenerator.contactHardeningLightSizeUVRatio = parsedShadowGenerator.contactHardeningLightSizeUVRatio;
+            }
 
             // Backward compat
             else if (parsedShadowGenerator.useVarianceShadowMap) {
@@ -1413,6 +1466,10 @@
                 shadowGenerator.bias = parsedShadowGenerator.bias;
             }
 
+            if (parsedShadowGenerator.normalBias !== undefined) {
+                shadowGenerator.normalBias = parsedShadowGenerator.normalBias;
+            }
+
             if (parsedShadowGenerator.darkness) {
                 shadowGenerator.setDarkness(parsedShadowGenerator.darkness);
             }

+ 2 - 2
src/Shaders/shadowMap.fragment.fx

@@ -18,7 +18,7 @@ varying vec2 vUV;
 uniform sampler2D diffuseSampler;
 #endif
 
-uniform vec2 biasAndScale;
+uniform vec3 biasAndScale;
 uniform vec2 depthValues;
 
 void main(void)
@@ -31,7 +31,7 @@ void main(void)
 	float depth = vDepthMetric;
 
 #ifdef ESM
-	depth = clamp(exp(-min(87., biasAndScale.y * depth)), 0., 1.);
+	depth = clamp(exp(-min(87., biasAndScale.z * depth)), 0., 1.);
 #endif
 
 #ifdef FLOAT

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

@@ -1,13 +1,19 @@
 // Attribute
 attribute vec3 position;
 
+#ifdef NORMAL
+	attribute vec3 normal;
+	uniform vec3 lightData;
+#endif
+
 #include<bonesDeclaration>
 
 // Uniforms
 #include<instancesDeclaration>
+#include<helperFunctions>
 
 uniform mat4 viewProjection;
-uniform vec2 biasAndScale;
+uniform vec3 biasAndScale;
 uniform vec2 depthValues;
 
 varying float vDepthMetric;
@@ -29,15 +35,42 @@ void main(void)
 #include<bonesVertex>
 
 vec4 worldPos = finalWorld * vec4(position, 1.0);
+
+// Normal inset Bias.
+#ifdef NORMAL
+	mat3 normalWorld = mat3(finalWorld);
+
+	#ifdef NONUNIFORMSCALING
+		normalWorld = transposeMat3(inverseMat3(normalWorld));
+	#endif
+
+	vec3 worldNor = normalize(normalWorld * normal);
+
+	#ifdef DIRECTIONINLIGHTDATA
+		vec3 worldLightDir = normalize(-lightData.xyz);
+	#else
+		vec3 directionToLight = lightData.xyz - worldPos.xyz;
+		vec3 worldLightDir = normalize(directionToLight);
+	#endif
+
+	float ndl = dot(worldNor, worldLightDir);
+	float sinNL = sqrt(1.0 - ndl * ndl);
+	float normalBias = biasAndScale.y * sinNL;
+
+	worldPos.xyz -= worldNor * normalBias;
+#endif
+
+// Projection.
 gl_Position = viewProjection * worldPos;
 
 #ifdef DEPTHTEXTURE
-	gl_Position.z += biasAndScale.x;
-	vDepthMetric = ((gl_Position.z + depthValues.x) / (depthValues.y)) + biasAndScale.x;
-#else
-	vDepthMetric = ((gl_Position.z + depthValues.x) / (depthValues.y)) + biasAndScale.x;
+	// Depth texture Linear bias.
+	gl_Position.z += biasAndScale.x * gl_Position.w;
 #endif
 
+	// Color Texture Linear bias.
+	vDepthMetric = ((gl_Position.z + depthValues.x) / (depthValues.y)) + biasAndScale.x;
+
 #ifdef ALPHATEST
 	#ifdef UV1
 		vUV = vec2(diffuseMatrix * vec4(uv, 1.0, 0.0));