Bladeren bron

New Fresnel parameters for StandardMaterial

David Catuhe 11 jaren geleden
bovenliggende
commit
cc1d8d90cc

+ 1 - 1
Babylon/LensFlare/babylon.lensFlareSystem.js

@@ -13,7 +13,7 @@
             scene.lensFlareSystems.push(this);
 
             this.meshesSelectionPredicate = function (m) {
-                return m.material && m.isVisible && m.isEnabled() && m.checkCollisions && ((m.layerMask & scene.activeCamera.layerMask) != 0);
+                return m.material && m.isVisible && m.isEnabled() && m.isBlocker && ((m.layerMask & scene.activeCamera.layerMask) != 0);
             };
 
             // VBO

+ 1 - 1
Babylon/LensFlare/babylon.lensFlareSystem.ts

@@ -21,7 +21,7 @@
             this._emitter = emitter;
             scene.lensFlareSystems.push(this);
 
-            this.meshesSelectionPredicate = m => m.material && m.isVisible && m.isEnabled() && m.checkCollisions && ((m.layerMask & scene.activeCamera.layerMask) != 0);
+            this.meshesSelectionPredicate = m => m.material && m.isVisible && m.isEnabled() && m.isBlocker && ((m.layerMask & scene.activeCamera.layerMask) != 0);
 
             // VBO
             var vertices = [];

+ 6 - 0
Babylon/Loading/Plugins/babylon.babylonFileLoader.js

@@ -91,6 +91,8 @@
             fresnelParameters.isEnabled = parsedFresnelParameters.isEnabled;
             fresnelParameters.leftColor = BABYLON.Color3.FromArray(parsedFresnelParameters.leftColor);
             fresnelParameters.rightColor = BABYLON.Color3.FromArray(parsedFresnelParameters.rightColor);
+            fresnelParameters.bias = parsedFresnelParameters.bias;
+            fresnelParameters.power = parsedFresnelParameters.power || 1.0;
 
             return fresnelParameters;
         };
@@ -145,6 +147,10 @@
                 material.emissiveTexture = loadTexture(rootUrl, parsedMaterial.emissiveTexture, scene);
             }
 
+            if (parsedMaterial.emissiveFresnelParameters) {
+                material.emissiveFresnelParameters = parseFresnelParameters(parsedMaterial.emissiveFresnelParameters);
+            }
+
             if (parsedMaterial.specularTexture) {
                 material.specularTexture = loadTexture(rootUrl, parsedMaterial.specularTexture, scene);
             }

+ 6 - 0
Babylon/Loading/Plugins/babylon.babylonFileLoader.ts

@@ -90,6 +90,8 @@
         fresnelParameters.isEnabled = parsedFresnelParameters.isEnabled;
         fresnelParameters.leftColor = BABYLON.Color3.FromArray(parsedFresnelParameters.leftColor);
         fresnelParameters.rightColor = BABYLON.Color3.FromArray(parsedFresnelParameters.rightColor);
+        fresnelParameters.bias = parsedFresnelParameters.bias;
+        fresnelParameters.power = parsedFresnelParameters.power || 1.0;
 
         return fresnelParameters;
     }
@@ -144,6 +146,10 @@
             material.emissiveTexture = loadTexture(rootUrl, parsedMaterial.emissiveTexture, scene);
         }
 
+        if (parsedMaterial.emissiveFresnelParameters) {
+            material.emissiveFresnelParameters = parseFresnelParameters(parsedMaterial.emissiveFresnelParameters);
+        }
+
         if (parsedMaterial.specularTexture) {
             material.specularTexture = loadTexture(rootUrl, parsedMaterial.specularTexture, scene);
         }

+ 51 - 15
Babylon/Materials/babylon.standardMaterial.js

@@ -11,8 +11,10 @@ var BABYLON;
     var FresnelParameters = (function () {
         function FresnelParameters() {
             this.isEnabled = true;
-            this.leftColor = BABYLON.Color3.Black();
-            this.rightColor = BABYLON.Color3.White();
+            this.leftColor = BABYLON.Color3.White();
+            this.rightColor = BABYLON.Color3.Black();
+            this.bias = 0;
+            this.power = 1;
         }
         return FresnelParameters;
     })();
@@ -33,7 +35,6 @@ var BABYLON;
             this._renderTargets = new BABYLON.SmartArray(16);
             this._worldViewProjectionMatrix = BABYLON.Matrix.Zero();
             this._globalAmbientColor = new BABYLON.Color3(0, 0, 0);
-            this._baseColor = new BABYLON.Color3();
             this._scaledDiffuse = new BABYLON.Color3();
             this._scaledSpecular = new BABYLON.Color3();
 
@@ -48,7 +49,7 @@ var BABYLON;
             };
         }
         StandardMaterial.prototype.needAlphaBlending = function () {
-            return (this.alpha < 1.0) || (this.opacityTexture != null) || this._shouldUseAlphaFromDiffuseTexture();
+            return (this.alpha < 1.0) || (this.opacityTexture != null) || this._shouldUseAlphaFromDiffuseTexture() || this.opacityFresnelParameters && this.opacityFresnelParameters.isEnabled;
         };
 
         StandardMaterial.prototype.needAlphaTesting = function () {
@@ -261,11 +262,35 @@ var BABYLON;
             }
 
             // Fresnel
-            if (this.diffuseFresnelParameters && this.diffuseFresnelParameters.isEnabled) {
+            if (this.diffuseFresnelParameters && this.diffuseFresnelParameters.isEnabled || this.opacityFresnelParameters && this.opacityFresnelParameters.isEnabled || this.emissiveFresnelParameters && this.emissiveFresnelParameters.isEnabled || this.reflectionFresnelParameters && this.reflectionFresnelParameters.isEnabled) {
+                var fresnelRank = 1;
+
+                if (this.diffuseFresnelParameters && this.diffuseFresnelParameters.isEnabled) {
+                    defines.push("#define DIFFUSEFRESNEL");
+                    fallbacks.addFallback(fresnelRank, "DIFFUSEFRESNEL");
+                    fresnelRank++;
+                }
+
+                if (this.opacityFresnelParameters && this.opacityFresnelParameters.isEnabled) {
+                    defines.push("#define OPACITYFRESNEL");
+                    fallbacks.addFallback(fresnelRank, "OPACITYFRESNEL");
+                    fresnelRank++;
+                }
+
+                if (this.reflectionFresnelParameters && this.reflectionFresnelParameters.isEnabled) {
+                    defines.push("#define REFLECTIONFRESNEL");
+                    fallbacks.addFallback(fresnelRank, "REFLECTIONFRESNEL");
+                    fresnelRank++;
+                }
+
+                if (this.emissiveFresnelParameters && this.emissiveFresnelParameters.isEnabled) {
+                    defines.push("#define EMISSIVEFRESNEL");
+                    fallbacks.addFallback(fresnelRank, "EMISSIVEFRESNEL");
+                    fresnelRank++;
+                }
+
                 defines.push("#define FRESNEL");
-                defines.push("#define DIFFUSEFRESNEL");
-                fallbacks.addFallback(1, "FRESNEL");
-                fallbacks.addFallback(1, "DIFFUSEFRESNEL");
+                fallbacks.addFallback(fresnelRank - 1, "FRESNEL");
             }
 
             // Attribs
@@ -324,7 +349,7 @@ var BABYLON;
                     "mBones",
                     "vClipPlane", "diffuseMatrix", "ambientMatrix", "opacityMatrix", "reflectionMatrix", "emissiveMatrix", "specularMatrix", "bumpMatrix",
                     "darkness0", "darkness1", "darkness2", "darkness3",
-                    "diffuseLeftColor", "diffuseRightColor"
+                    "diffuseLeftColor", "diffuseRightColor", "opacityParts", "reflectionLeftColor", "reflectionRightColor", "emissiveLeftColor", "emissiveRightColor"
                 ], [
                     "diffuseSampler", "ambientSampler", "opacitySampler", "reflectionCubeSampler", "reflection2DSampler", "emissiveSampler", "specularSampler", "bumpSampler",
                     "shadowSampler0", "shadowSampler1", "shadowSampler2", "shadowSampler3"
@@ -351,7 +376,6 @@ var BABYLON;
 
         StandardMaterial.prototype.bind = function (world, mesh) {
             var scene = this.getScene();
-            this._baseColor.copyFrom(this.diffuseColor);
 
             // Matrices
             this.bindOnlyWorldMatrix(world);
@@ -364,8 +388,22 @@ var BABYLON;
 
             // Fresnel
             if (this.diffuseFresnelParameters && this.diffuseFresnelParameters.isEnabled) {
-                this._effect.setColor3("diffuseLeftColor", this.diffuseFresnelParameters.leftColor);
-                this._effect.setColor3("diffuseRightColor", this.diffuseFresnelParameters.rightColor);
+                this._effect.setColor4("diffuseLeftColor", this.diffuseFresnelParameters.leftColor, this.diffuseFresnelParameters.power);
+                this._effect.setColor4("diffuseRightColor", this.diffuseFresnelParameters.rightColor, this.diffuseFresnelParameters.bias);
+            }
+
+            if (this.opacityFresnelParameters && this.opacityFresnelParameters.isEnabled) {
+                this._effect.setColor4("opacityParts", new BABYLON.Color3(this.opacityFresnelParameters.leftColor.toLuminance(), this.opacityFresnelParameters.rightColor.toLuminance(), this.opacityFresnelParameters.bias), this.opacityFresnelParameters.power);
+            }
+
+            if (this.reflectionFresnelParameters && this.reflectionFresnelParameters.isEnabled) {
+                this._effect.setColor4("reflectionLeftColor", this.reflectionFresnelParameters.leftColor, this.reflectionFresnelParameters.power);
+                this._effect.setColor4("reflectionRightColor", this.reflectionFresnelParameters.rightColor, this.reflectionFresnelParameters.bias);
+            }
+
+            if (this.emissiveFresnelParameters && this.emissiveFresnelParameters.isEnabled) {
+                this._effect.setColor4("emissiveLeftColor", this.emissiveFresnelParameters.leftColor, this.emissiveFresnelParameters.power);
+                this._effect.setColor4("emissiveRightColor", this.emissiveFresnelParameters.rightColor, this.emissiveFresnelParameters.bias);
             }
 
             // Textures
@@ -374,8 +412,6 @@ var BABYLON;
 
                 this._effect.setFloat2("vDiffuseInfos", this.diffuseTexture.coordinatesIndex, this.diffuseTexture.level);
                 this._effect.setMatrix("diffuseMatrix", this.diffuseTexture.getTextureMatrix());
-
-                this._baseColor.copyFromFloats(1, 1, 1);
             }
 
             if (this.ambientTexture && BABYLON.StandardMaterial.AmbientTextureEnabled) {
@@ -429,7 +465,7 @@ var BABYLON;
 
             this._effect.setVector3("vEyePosition", scene.activeCamera.position);
             this._effect.setColor3("vAmbientColor", this._globalAmbientColor);
-            this._effect.setColor4("vDiffuseColor", this._baseColor, this.alpha * mesh.visibility);
+            this._effect.setColor4("vDiffuseColor", this.diffuseColor, this.alpha * mesh.visibility);
             this._effect.setColor4("vSpecularColor", this.specularColor, this.specularPower);
             this._effect.setColor3("vEmissiveColor", this.emissiveColor);
 

+ 56 - 15
Babylon/Materials/babylon.standardMaterial.ts

@@ -3,8 +3,10 @@
 
     export class FresnelParameters {
         public isEnabled = true;
-        public leftColor = Color3.Black();
-        public rightColor = Color3.White();
+        public leftColor = Color3.White();
+        public rightColor = Color3.Black();
+        public bias = 0;
+        public power = 1;
     }
 
     export class StandardMaterial extends Material {
@@ -26,12 +28,12 @@
         public diffuseFresnelParameters: FresnelParameters;
         public opacityFresnelParameters: FresnelParameters;
         public reflectionFresnelParameters: FresnelParameters;
+        public emissiveFresnelParameters: FresnelParameters;
 
         private _cachedDefines = null;
         private _renderTargets = new BABYLON.SmartArray<RenderTargetTexture>(16);
         private _worldViewProjectionMatrix = BABYLON.Matrix.Zero();
         private _globalAmbientColor = new BABYLON.Color3(0, 0, 0);
-        private _baseColor = new BABYLON.Color3();
         private _scaledDiffuse = new BABYLON.Color3();
         private _scaledSpecular = new BABYLON.Color3();
         private _renderId: number;
@@ -51,7 +53,7 @@
         }
 
         public needAlphaBlending(): boolean {
-            return (this.alpha < 1.0) || (this.opacityTexture != null) || this._shouldUseAlphaFromDiffuseTexture();
+            return (this.alpha < 1.0) || (this.opacityTexture != null) || this._shouldUseAlphaFromDiffuseTexture() || this.opacityFresnelParameters && this.opacityFresnelParameters.isEnabled;
         }
 
         public needAlphaTesting(): boolean {
@@ -264,11 +266,39 @@
             }
 
             // Fresnel
-            if (this.diffuseFresnelParameters && this.diffuseFresnelParameters.isEnabled) {
+            if (this.diffuseFresnelParameters && this.diffuseFresnelParameters.isEnabled ||
+                this.opacityFresnelParameters && this.opacityFresnelParameters.isEnabled ||
+                this.emissiveFresnelParameters && this.emissiveFresnelParameters.isEnabled ||
+                this.reflectionFresnelParameters && this.reflectionFresnelParameters.isEnabled) {
+
+                var fresnelRank = 1;
+
+                if (this.diffuseFresnelParameters && this.diffuseFresnelParameters.isEnabled) {
+                    defines.push("#define DIFFUSEFRESNEL");
+                    fallbacks.addFallback(fresnelRank, "DIFFUSEFRESNEL");
+                    fresnelRank++;
+                }
+
+                if (this.opacityFresnelParameters && this.opacityFresnelParameters.isEnabled) {
+                    defines.push("#define OPACITYFRESNEL");
+                    fallbacks.addFallback(fresnelRank, "OPACITYFRESNEL");
+                    fresnelRank++;
+                }
+
+                if (this.reflectionFresnelParameters && this.reflectionFresnelParameters.isEnabled) {
+                    defines.push("#define REFLECTIONFRESNEL");
+                    fallbacks.addFallback(fresnelRank, "REFLECTIONFRESNEL");
+                    fresnelRank++;
+                }
+
+                if (this.emissiveFresnelParameters && this.emissiveFresnelParameters.isEnabled) {
+                    defines.push("#define EMISSIVEFRESNEL");
+                    fallbacks.addFallback(fresnelRank, "EMISSIVEFRESNEL");
+                    fresnelRank++;
+                }
+
                 defines.push("#define FRESNEL");
-                defines.push("#define DIFFUSEFRESNEL");
-                fallbacks.addFallback(1, "FRESNEL");
-                fallbacks.addFallback(1, "DIFFUSEFRESNEL");
+                fallbacks.addFallback(fresnelRank - 1, "FRESNEL");
             }
 
 
@@ -329,7 +359,7 @@
                         "mBones",
                         "vClipPlane", "diffuseMatrix", "ambientMatrix", "opacityMatrix", "reflectionMatrix", "emissiveMatrix", "specularMatrix", "bumpMatrix",
                         "darkness0", "darkness1", "darkness2", "darkness3",
-                        "diffuseLeftColor", "diffuseRightColor"
+                        "diffuseLeftColor", "diffuseRightColor", "opacityParts", "reflectionLeftColor", "reflectionRightColor", "emissiveLeftColor", "emissiveRightColor"
                     ],
                     ["diffuseSampler", "ambientSampler", "opacitySampler", "reflectionCubeSampler", "reflection2DSampler", "emissiveSampler", "specularSampler", "bumpSampler",
                         "shadowSampler0", "shadowSampler1", "shadowSampler2", "shadowSampler3"
@@ -358,7 +388,6 @@
 
         public bind(world: Matrix, mesh: Mesh): void {
             var scene = this.getScene();
-            this._baseColor.copyFrom(this.diffuseColor);
 
             // Matrices        
             this.bindOnlyWorldMatrix(world);
@@ -371,8 +400,22 @@
 
             // Fresnel
             if (this.diffuseFresnelParameters && this.diffuseFresnelParameters.isEnabled) {
-                this._effect.setColor3("diffuseLeftColor", this.diffuseFresnelParameters.leftColor);
-                this._effect.setColor3("diffuseRightColor", this.diffuseFresnelParameters.rightColor);
+                this._effect.setColor4("diffuseLeftColor", this.diffuseFresnelParameters.leftColor, this.diffuseFresnelParameters.power);
+                this._effect.setColor4("diffuseRightColor", this.diffuseFresnelParameters.rightColor, this.diffuseFresnelParameters.bias);
+            }
+
+            if (this.opacityFresnelParameters && this.opacityFresnelParameters.isEnabled) {
+                this._effect.setColor4("opacityParts", new BABYLON.Color3(this.opacityFresnelParameters.leftColor.toLuminance(), this.opacityFresnelParameters.rightColor.toLuminance(), this.opacityFresnelParameters.bias), this.opacityFresnelParameters.power);
+            }
+
+            if (this.reflectionFresnelParameters && this.reflectionFresnelParameters.isEnabled) {
+                this._effect.setColor4("reflectionLeftColor", this.reflectionFresnelParameters.leftColor, this.reflectionFresnelParameters.power);
+                this._effect.setColor4("reflectionRightColor", this.reflectionFresnelParameters.rightColor, this.reflectionFresnelParameters.bias);
+            }
+
+            if (this.emissiveFresnelParameters && this.emissiveFresnelParameters.isEnabled) {
+                this._effect.setColor4("emissiveLeftColor", this.emissiveFresnelParameters.leftColor, this.emissiveFresnelParameters.power);
+                this._effect.setColor4("emissiveRightColor", this.emissiveFresnelParameters.rightColor, this.emissiveFresnelParameters.bias);
             }
 
             // Textures        
@@ -381,8 +424,6 @@
 
                 this._effect.setFloat2("vDiffuseInfos", this.diffuseTexture.coordinatesIndex, this.diffuseTexture.level);
                 this._effect.setMatrix("diffuseMatrix", this.diffuseTexture.getTextureMatrix());
-
-                this._baseColor.copyFromFloats(1, 1, 1);
             }
 
             if (this.ambientTexture && BABYLON.StandardMaterial.AmbientTextureEnabled) {
@@ -436,7 +477,7 @@
 
             this._effect.setVector3("vEyePosition", scene.activeCamera.position);
             this._effect.setColor3("vAmbientColor", this._globalAmbientColor);
-            this._effect.setColor4("vDiffuseColor", this._baseColor, this.alpha * mesh.visibility);
+            this._effect.setColor4("vDiffuseColor", this.diffuseColor, this.alpha * mesh.visibility);
             this._effect.setColor4("vSpecularColor", this.specularColor, this.specularPower);
             this._effect.setColor3("vEmissiveColor", this.emissiveColor);
 

+ 31 - 0
Babylon/Math/babylon.math.js

@@ -37,6 +37,10 @@
             return result;
         };
 
+        Color3.prototype.toLuminance = function () {
+            return this.r * 0.3 + this.g * 0.59 + this.b * 0.11;
+        };
+
         Color3.prototype.multiply = function (otherColor) {
             return new Color3(this.r * otherColor.r, this.g * otherColor.g, this.b * otherColor.b);
         };
@@ -289,6 +293,33 @@
             return new Vector2(this.x - otherVector.x, this.y - otherVector.y);
         };
 
+        Vector2.prototype.multiplyInPlace = function (otherVector) {
+            this.x *= otherVector.x;
+            this.y *= otherVector.y;
+        };
+
+        Vector2.prototype.multiply = function (otherVector) {
+            return new Vector2(this.x * otherVector.x, this.y * otherVector.y);
+        };
+
+        Vector2.prototype.multiplyToRef = function (otherVector, result) {
+            result.x = this.x * otherVector.x;
+            result.y = this.y * otherVector.y;
+        };
+
+        Vector2.prototype.multiplyByFloats = function (x, y) {
+            return new Vector2(this.x * x, this.y * y);
+        };
+
+        Vector2.prototype.divide = function (otherVector) {
+            return new Vector2(this.x / otherVector.x, this.y / otherVector.y);
+        };
+
+        Vector2.prototype.divideToRef = function (otherVector, result) {
+            result.x = this.x / otherVector.x;
+            result.y = this.y / otherVector.y;
+        };
+
         Vector2.prototype.negate = function () {
             return new Vector2(-this.x, -this.y);
         };

+ 31 - 0
Babylon/Math/babylon.math.ts

@@ -30,6 +30,10 @@
             return result;
         }
 
+        public toLuminance(): number {
+            return this.r * 0.3 + this.g * 0.59 + this.b * 0.11;
+        }
+
         public multiply(otherColor: Color3): Color3 {
             return new Color3(this.r * otherColor.r, this.g * otherColor.g, this.b * otherColor.b);
         }
@@ -255,6 +259,33 @@
             return new Vector2(this.x - otherVector.x, this.y - otherVector.y);
         }
 
+        public multiplyInPlace(otherVector: Vector2): void {
+            this.x *= otherVector.x;
+            this.y *= otherVector.y;
+        }
+
+        public multiply(otherVector: Vector2): Vector2 {
+            return new Vector2(this.x * otherVector.x, this.y * otherVector.y);
+        }
+
+        public multiplyToRef(otherVector: Vector2, result: Vector2): void {
+            result.x = this.x * otherVector.x;
+            result.y = this.y * otherVector.y;
+        }
+
+        public multiplyByFloats(x: number, y: number): Vector2 {
+            return new Vector2(this.x * x, this.y * y);
+        }
+
+        public divide(otherVector: Vector2): Vector2 {
+            return new Vector2(this.x / otherVector.x, this.y / otherVector.y);
+        }
+
+        public divideToRef(otherVector: Vector2, result: Vector2): void {
+            result.x = this.x / otherVector.x;
+            result.y = this.y / otherVector.y;
+        }
+
         public negate(): Vector2 {
             return new Vector2(-this.x, -this.y);
         }

+ 1 - 0
Babylon/Mesh/babylon.abstractMesh.js

@@ -23,6 +23,7 @@ var BABYLON;
             this.showSubMeshesBoundingBox = false;
             this.onDispose = null;
             this.checkCollisions = false;
+            this.isBlocker = false;
             this.renderingGroupId = 0;
             this.receiveShadows = false;
             this.renderOutline = false;

+ 1 - 0
Babylon/Mesh/babylon.abstractMesh.ts

@@ -41,6 +41,7 @@
         public showSubMeshesBoundingBox = false;
         public onDispose = null;
         public checkCollisions = false;
+        public isBlocker = false;
         public skeleton: Skeleton;
         public renderingGroupId = 0;
         public material: Material;

+ 41 - 7
Babylon/Shaders/default.fragment.fx

@@ -126,16 +126,30 @@ uniform sampler2D specularSampler;
 
 // Fresnel
 #ifdef FRESNEL
-float computeFresnelTerm(vec3 viewDirection, vec3 worldNormal)
+float computeFresnelTerm(vec3 viewDirection, vec3 worldNormal, float bias, float power)
 {
-	float fresnelTerm = dot(viewDirection, worldNormal);
-	return clamp(1.0 - fresnelTerm, 0., 1.);
+	float fresnelTerm = pow(bias + dot(viewDirection, worldNormal), power);
+	return clamp(fresnelTerm, 0., 1.);
 }
 #endif
 
 #ifdef DIFFUSEFRESNEL
-uniform vec3 diffuseLeftColor;
-uniform vec3 diffuseRightColor;
+uniform vec4 diffuseLeftColor;
+uniform vec4 diffuseRightColor;
+#endif
+
+#ifdef OPACITYFRESNEL
+uniform vec4 opacityParts;
+#endif
+
+#ifdef REFLECTIONFRESNEL
+uniform vec4 reflectionLeftColor;
+uniform vec4 reflectionRightColor;
+#endif
+
+#ifdef EMISSIVEFRESNEL
+uniform vec4 emissiveLeftColor;
+uniform vec4 emissiveRightColor;
 #endif
 
 // Reflection
@@ -627,6 +641,12 @@ void main(void) {
 
 		reflectionColor = texture2D(reflection2DSampler, coords).rgb * vReflectionInfos.y * shadow;
 	}
+
+#ifdef REFLECTIONFRESNEL
+	float reflectionFresnelTerm = computeFresnelTerm(viewDirectionW, normalW, reflectionRightColor.a, reflectionLeftColor.a);
+
+	reflectionColor *= reflectionLeftColor.rgb * (1.0 - reflectionFresnelTerm) + reflectionFresnelTerm * reflectionRightColor.rgb;
+#endif
 #endif
 
 #ifdef OPACITY
@@ -639,7 +659,12 @@ void main(void) {
 	alpha *= opacityMap.a * vOpacityInfos.y;
 #endif
 
+#endif
+
+#ifdef OPACITYFRESNEL
+	float opacityFresnelTerm = computeFresnelTerm(viewDirectionW, normalW, opacityParts.z, opacityParts.w);
 
+	alpha += opacityParts.x * (1.0 - opacityFresnelTerm) + opacityFresnelTerm * opacityParts.y;
 #endif
 
 	// Emissive
@@ -648,6 +673,12 @@ void main(void) {
 	emissiveColor += texture2D(emissiveSampler, vEmissiveUV).rgb * vEmissiveInfos.y;
 #endif
 
+#ifdef EMISSIVEFRESNEL
+	float emissiveFresnelTerm = computeFresnelTerm(viewDirectionW, normalW, emissiveRightColor.a, emissiveLeftColor.a);
+
+	emissiveColor *= emissiveLeftColor.rgb * (1.0 - emissiveFresnelTerm) + emissiveFresnelTerm * emissiveRightColor.rgb;
+#endif
+
 	// Specular map
 	vec3 specularColor = vSpecularColor.rgb;
 #ifdef SPECULAR
@@ -656,14 +687,17 @@ void main(void) {
 
 	// Fresnel
 #ifdef DIFFUSEFRESNEL
-	float diffuseFresnelTerm = computeFresnelTerm(viewDirectionW, normalW);
-	diffuseBase *= diffuseLeftColor * (1.0 - diffuseFresnelTerm) + diffuseFresnelTerm * diffuseRightColor;
+	float diffuseFresnelTerm = computeFresnelTerm(viewDirectionW, normalW, diffuseRightColor.a, diffuseLeftColor.a);
+
+	diffuseBase *= diffuseLeftColor.rgb * (1.0 - diffuseFresnelTerm) + diffuseFresnelTerm * diffuseRightColor.rgb;
 #endif
 
 	// Composition
 	vec3 finalDiffuse = clamp(diffuseBase * diffuseColor + emissiveColor + vAmbientColor, 0.0, 1.0) * baseColor.rgb;
 	vec3 finalSpecular = specularBase * specularColor;
 
+	alpha = clamp(alpha + dot(finalSpecular, vec3(0.3, 0.59, 0.11)), 0., 1.);
+
 	vec4 color = vec4(finalDiffuse * baseAmbientColor + finalSpecular + reflectionColor, alpha);
 
 #ifdef FOG

+ 53 - 0
Babylon/Shaders/legacydefault.fragment.fx

@@ -122,6 +122,34 @@ uniform vec2 vSpecularInfos;
 uniform sampler2D specularSampler;
 #endif
 
+// Fresnel
+#ifdef FRESNEL
+float computeFresnelTerm(vec3 viewDirection, vec3 worldNormal, float bias, float power)
+{
+	float fresnelTerm = pow(bias + dot(viewDirection, worldNormal), power);
+	return clamp(fresnelTerm, 0., 1.);
+}
+#endif
+
+#ifdef DIFFUSEFRESNEL
+uniform vec4 diffuseLeftColor;
+uniform vec4 diffuseRightColor;
+#endif
+
+#ifdef OPACITYFRESNEL
+uniform vec4 opacityParts;
+#endif
+
+#ifdef REFLECTIONFRESNEL
+uniform vec4 reflectionLeftColor;
+uniform vec4 reflectionRightColor;
+#endif
+
+#ifdef EMISSIVEFRESNEL
+uniform vec4 emissiveLeftColor;
+uniform vec4 emissiveRightColor;
+#endif
+
 // Shadows
 #ifdef SHADOWS
 
@@ -467,6 +495,12 @@ void main(void) {
 
 		reflectionColor = texture2D(reflection2DSampler, coords).rgb * vReflectionInfos.y;
 	}
+
+#ifdef REFLECTIONFRESNEL
+	float reflectionFresnelTerm = computeFresnelTerm(viewDirectionW, normalW, reflectionRightColor.a, reflectionLeftColor.a);
+
+	reflectionColor *= reflectionLeftColor.rgb * (1.0 - reflectionFresnelTerm) + reflectionFresnelTerm * reflectionRightColor.rgb;
+#endif
 #endif
 
 	// Alpha
@@ -482,18 +516,37 @@ void main(void) {
 #endif
 #endif
 
+#ifdef OPACITYFRESNEL
+	float opacityFresnelTerm = computeFresnelTerm(viewDirectionW, normalW, opacityParts.z, opacityParts.w);
+
+	alpha += opacityParts.x * (1.0 - opacityFresnelTerm) + opacityFresnelTerm * opacityParts.y;
+#endif
+
 	// Emissive
 	vec3 emissiveColor = vEmissiveColor;
 #ifdef EMISSIVE
 	emissiveColor += texture2D(emissiveSampler, vEmissiveUV).rgb * vEmissiveInfos.y;
 #endif
 
+#ifdef EMISSIVEFRESNEL
+	float emissiveFresnelTerm = computeFresnelTerm(viewDirectionW, normalW, emissiveRightColor.a, emissiveLeftColor.a);
+
+	emissiveColor *= emissiveLeftColor.rgb * (1.0 - emissiveFresnelTerm) + emissiveFresnelTerm * emissiveRightColor.rgb;
+#endif
+
 	// Specular map
 	vec3 specularColor = vSpecularColor.rgb;
 #ifdef SPECULAR
 	specularColor = texture2D(specularSampler, vSpecularUV).rgb * vSpecularInfos.y;
 #endif
 
+	// Fresnel
+#ifdef DIFFUSEFRESNEL
+	float diffuseFresnelTerm = computeFresnelTerm(viewDirectionW, normalW, diffuseRightColor.a, diffuseLeftColor.a);
+
+	diffuseBase *= diffuseLeftColor.rgb * (1.0 - diffuseFresnelTerm) + diffuseFresnelTerm * diffuseRightColor.rgb;
+#endif
+
 	// Composition
 	vec3 finalDiffuse = clamp(diffuseBase * diffuseColor + emissiveColor + vAmbientColor, 0.0, 1.0) * baseColor.rgb;
 	vec3 finalSpecular = specularBase * specularColor;

+ 1 - 1
Babylon/babylon.engine.js

@@ -10,7 +10,7 @@
         }
         Object.defineProperty(_DepthCullingState.prototype, "isDirty", {
             get: function () {
-                return this._isDepthTestDirty || this._isDepthMaskDirty || this._isCullFaceDirty || this._isCullDirty;
+                return this._isDepthFuncDirty || this._isDepthTestDirty || this._isDepthMaskDirty || this._isCullFaceDirty || this._isCullDirty;
             },
             enumerable: true,
             configurable: true

+ 1 - 1
Babylon/babylon.engine.ts

@@ -14,7 +14,7 @@
         
 
         public get isDirty(): boolean {
-            return this._isDepthTestDirty || this._isDepthMaskDirty || this._isCullFaceDirty || this._isCullDirty;
+            return this._isDepthFuncDirty || this._isDepthTestDirty || this._isDepthMaskDirty || this._isCullFaceDirty || this._isCullDirty;
         }
 
         public get cullFace(): number {

+ 1 - 0
Exporters/3ds Max/BabylonExport.Entities/BabylonExport.Entities.csproj

@@ -52,6 +52,7 @@
     <Compile Include="BabylonAnimationKey.cs" />
     <Compile Include="BabylonBone.cs" />
     <Compile Include="BabylonCamera.cs" />
+    <Compile Include="BabylonFresnelParameters.cs" />
     <Compile Include="BabylonLensFlare.cs" />
     <Compile Include="BabylonLensFlareSystem.cs" />
     <Compile Include="BabylonLight.cs" />

+ 27 - 0
Exporters/3ds Max/BabylonExport.Entities/BabylonFresnelParameters.cs

@@ -0,0 +1,27 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Runtime.Serialization;
+using System.Text;
+
+namespace BabylonExport.Entities
+{
+    [DataContract]
+    public class BabylonFresnelParameters
+    {
+        [DataMember]
+        public float[] leftColor { get; set; }
+
+        [DataMember]
+        public float[] rightColor { get; set; }
+
+        [DataMember]
+        public bool isEnabled { get; set; }
+
+        [DataMember]
+        public float bias { get; set; }
+
+        [DataMember]
+        public float power { get; set; }
+    }
+}

+ 11 - 0
Exporters/3ds Max/BabylonExport.Entities/BabylonMaterial.cs

@@ -38,16 +38,27 @@ namespace BabylonExport.Entities
         public BabylonTexture diffuseTexture { get; set; }
 
         [DataMember]
+        public BabylonFresnelParameters diffuseFresnelParameters { get; set; }
+
+        [DataMember]
         public BabylonTexture ambientTexture { get; set; }
 
         [DataMember]
         public BabylonTexture opacityTexture { get; set; }
 
         [DataMember]
+        public BabylonFresnelParameters opacityFresnelParameters { get; set; }
+
+        [DataMember]
         public BabylonTexture reflectionTexture { get; set; }
 
         [DataMember]
+        public BabylonFresnelParameters reflectionFresnelParameters { get; set; }
+
+        [DataMember]
         public BabylonTexture emissiveTexture { get; set; }
+        [DataMember]
+        public BabylonFresnelParameters emissiveFresnelParameters { get; set; }
 
         [DataMember]
         public BabylonTexture specularTexture { get; set; }

BIN
Exporters/3ds Max/Max2Babylon-0.7.9.zip


BIN
Exporters/3ds Max/Max2Babylon-0.8.0.zip


+ 50 - 22
Exporters/3ds Max/Max2Babylon/Exporter/BabylonExporter.Material.cs

@@ -18,9 +18,7 @@ namespace Max2Babylon
 
             if (materialNode.NumSubMtls > 0)
             {
-                var babylonMultimaterial = new BabylonMultiMaterial();
-                babylonMultimaterial.name = name;
-                babylonMultimaterial.id = id;
+                var babylonMultimaterial = new BabylonMultiMaterial {name = name, id = id};
 
                 var guids = new List<string>();
 
@@ -51,19 +49,21 @@ namespace Max2Babylon
             }
 
 
-            var babylonMaterial = new BabylonMaterial();
-            babylonMaterial.name = name;
-            babylonMaterial.id = id;
-
-            
-
-            babylonMaterial.ambient = materialNode.GetAmbient(0, false).ToArray();
-            babylonMaterial.diffuse = materialNode.GetDiffuse(0, false).ToArray();
-            babylonMaterial.specular = materialNode.GetSpecular(0, false).Scale(materialNode.GetShinStr(0, false));
-            babylonMaterial.specularPower = materialNode.GetShininess(0, false) * 256;
+            var babylonMaterial = new BabylonMaterial
+            {
+                name = name,
+                id = id,
+                ambient = materialNode.GetAmbient(0, false).ToArray(),
+                diffuse = materialNode.GetDiffuse(0, false).ToArray(),
+                specular = materialNode.GetSpecular(0, false).Scale(materialNode.GetShinStr(0, false)),
+                specularPower = materialNode.GetShininess(0, false)*256,
+                emissive =
+                    materialNode.GetSelfIllumColorOn(0, false)
+                        ? materialNode.GetSelfIllumColor(0, false).ToArray()
+                        : materialNode.GetDiffuse(0, false).Scale(materialNode.GetSelfIllum(0, false)),
+                alpha = 1.0f - materialNode.GetXParency(0, false)
+            };
 
-            babylonMaterial.emissive = materialNode.GetSelfIllumColorOn(0, false) ? materialNode.GetSelfIllumColor(0, false).ToArray() : materialNode.GetDiffuse(0, false).Scale(materialNode.GetSelfIllum(0, false));
-            babylonMaterial.alpha = 1.0f - materialNode.GetXParency(0, false);
 
             var stdMat = materialNode.GetParamBlock(0).Owner as IStdMat2;
 
@@ -73,13 +73,41 @@ namespace Max2Babylon
                 babylonMaterial.wireframe = stdMat.Wire;
 
                 // Textures
-                babylonMaterial.ambientTexture = ExportTexture(stdMat, 0, babylonScene);                // Ambient
-                babylonMaterial.diffuseTexture = ExportTexture(stdMat, 1, babylonScene);                // Diffuse
-                babylonMaterial.specularTexture = ExportTexture(stdMat, 2, babylonScene);               // Specular
-                babylonMaterial.emissiveTexture = ExportTexture(stdMat, 5, babylonScene);               // Emissive
-                babylonMaterial.opacityTexture = ExportTexture(stdMat, 6, babylonScene, false, true);   // Opacity
-                babylonMaterial.bumpTexture = ExportTexture(stdMat, 8, babylonScene);                   // Bump
-                babylonMaterial.reflectionTexture = ExportTexture(stdMat, 9, babylonScene, true);       // Reflection
+                BabylonFresnelParameters fresnelParameters;
+
+                babylonMaterial.ambientTexture = ExportTexture(stdMat, 0, out fresnelParameters, babylonScene);                // Ambient
+                babylonMaterial.diffuseTexture = ExportTexture(stdMat, 1, out fresnelParameters, babylonScene);                // Diffuse
+                if (fresnelParameters != null)
+                {
+                    babylonMaterial.diffuseFresnelParameters = fresnelParameters;
+                }
+
+                babylonMaterial.specularTexture = ExportTexture(stdMat, 2, out fresnelParameters, babylonScene);               // Specular
+                babylonMaterial.emissiveTexture = ExportTexture(stdMat, 5, out fresnelParameters, babylonScene);               // Emissive
+                if (fresnelParameters != null)
+                {
+                    babylonMaterial.emissiveFresnelParameters = fresnelParameters;
+                }
+                
+                babylonMaterial.opacityTexture = ExportTexture(stdMat, 6, out fresnelParameters, babylonScene, false, true);   // Opacity
+                if (fresnelParameters != null)
+                {
+                    babylonMaterial.opacityFresnelParameters = fresnelParameters;
+                }
+
+                babylonMaterial.bumpTexture = ExportTexture(stdMat, 8, out fresnelParameters, babylonScene);                   // Bump
+                babylonMaterial.reflectionTexture = ExportTexture(stdMat, 9, out fresnelParameters, babylonScene, true);       // Reflection
+                if (fresnelParameters != null)
+                {
+                    if (babylonMaterial.reflectionTexture == null)
+                    {
+                        RaiseWarning("Fallout cannot be used with reflection channel without a texture", 2);
+                    }
+                    else
+                    {
+                        babylonMaterial.reflectionFresnelParameters = fresnelParameters;                        
+                    }
+                }
 
                 // Constraints
                 if (babylonMaterial.diffuseTexture != null)

+ 55 - 3
Exporters/3ds Max/Max2Babylon/Exporter/BabylonExporter.Texture.cs

@@ -53,8 +53,10 @@ namespace Max2Babylon
             }
         }
 
-        private BabylonTexture ExportTexture(IStdMat2 stdMat, int index, BabylonScene babylonScene, bool allowCube = false, bool forceAlpha = false)
+        private BabylonTexture ExportTexture(IStdMat2 stdMat, int index, out BabylonFresnelParameters fresnelParameters, BabylonScene babylonScene, bool allowCube = false, bool forceAlpha = false)
         {
+            fresnelParameters = null;
+
             if (!stdMat.MapEnabled(index))
             {
                 return null;
@@ -62,6 +64,56 @@ namespace Max2Babylon
             var babylonTexture = new BabylonTexture();
 
             var texMap = stdMat.GetSubTexmap(index);
+
+            // Fallout
+            if (texMap.ClassName == "Falloff") // This is the only way I found to detect it. This is crappy but it works
+            {
+                fresnelParameters = new BabylonFresnelParameters();
+
+                var paramBlock = texMap.GetParamBlock(0);
+                var color1 = paramBlock.GetColor(0, 0, 0);
+                var color2 = paramBlock.GetColor(4, 0, 0);
+
+                fresnelParameters.isEnabled = true;
+                fresnelParameters.leftColor = color2.ToArray();
+                fresnelParameters.rightColor = color1.ToArray();
+
+                if (paramBlock.GetInt(8, 0, 0) == 2)
+                {
+                    fresnelParameters.power = paramBlock.GetFloat(12, 0, 0);
+                }
+                else
+                {
+                    fresnelParameters.power = 1;
+                }
+                var texMap1 = paramBlock.GetTexmap(2, 0, 0);
+                var texMap1On = paramBlock.GetInt(3, 0, 0);
+
+                var texMap2 = paramBlock.GetTexmap(6, 0, 0);
+                var texMap2On = paramBlock.GetInt(7, 0, 0);
+
+                if (texMap1 != null && texMap1On != 0)
+                {
+                    texMap = texMap1;
+                    fresnelParameters.rightColor = new float[] { 1, 1, 1 };
+
+                    if (texMap2 != null && texMap2On != 0)
+                    {
+                        RaiseWarning(string.Format("You cannot specify two textures for falloff. Only one is supported"), 2);
+                    }
+                }
+                else if (texMap2 != null && texMap2On != 0)
+                {
+                    fresnelParameters.leftColor = new float[] { 1, 1, 1 };
+                    texMap = texMap2;
+                }
+                else
+                {
+                    return null;
+                }
+            }
+
+            // Bitmap
             var texture = texMap.GetParamBlock(0).Owner as IBitmapTex;
 
             if (texture == null)
@@ -158,22 +210,22 @@ namespace Max2Babylon
             {
                 if (File.Exists(texture.MapName))
                 {
+                    babylonTexture.isCube = IsTextureCube(texture.MapName);
                     if (CopyTexturesToOutput)
                     {
                         File.Copy(texture.MapName, Path.Combine(babylonScene.OutputPath, babylonTexture.name), true);
                     }
-                    babylonTexture.isCube = IsTextureCube(texture.MapName);
                 }
                 else
                 {
                     var texturepath = Path.Combine(Path.GetDirectoryName(Loader.Core.CurFilePath), babylonTexture.name);
                     if (File.Exists(texturepath))
                     {
+                        babylonTexture.isCube = IsTextureCube(texturepath);
                         if (CopyTexturesToOutput)
                         {
                             File.Copy(texturepath, Path.Combine(babylonScene.OutputPath, babylonTexture.name), true);
                         }
-                        babylonTexture.isCube = IsTextureCube(texturepath);
                     }
                     else
                     {

+ 27 - 12
Exporters/3ds Max/Max2Babylon/Forms/ExporterForm.Designer.cs

@@ -42,10 +42,11 @@
             this.label2 = new System.Windows.Forms.Label();
             this.chkCopyTextures = new System.Windows.Forms.CheckBox();
             this.groupBox1 = new System.Windows.Forms.GroupBox();
+            this.chkOnlySelected = new System.Windows.Forms.CheckBox();
             this.chkAutoSave = new System.Windows.Forms.CheckBox();
             this.chkHidden = new System.Windows.Forms.CheckBox();
             this.butExportAndRun = new System.Windows.Forms.Button();
-            this.chkOnlySelected = new System.Windows.Forms.CheckBox();
+            this.butClose = new System.Windows.Forms.Button();
             ((System.ComponentModel.ISupportInitialize)(this.pictureBox2)).BeginInit();
             this.groupBox1.SuspendLayout();
             this.SuspendLayout();
@@ -106,7 +107,7 @@
             | System.Windows.Forms.AnchorStyles.Right)));
             this.progressBar.Location = new System.Drawing.Point(12, 516);
             this.progressBar.Name = "progressBar";
-            this.progressBar.Size = new System.Drawing.Size(713, 23);
+            this.progressBar.Size = new System.Drawing.Size(627, 23);
             this.progressBar.TabIndex = 5;
             // 
             // treeView
@@ -124,7 +125,7 @@
             this.butCancel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
             this.butCancel.Enabled = false;
             this.butCancel.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
-            this.butCancel.Location = new System.Drawing.Point(731, 516);
+            this.butCancel.Location = new System.Drawing.Point(645, 516);
             this.butCancel.Name = "butCancel";
             this.butCancel.Size = new System.Drawing.Size(80, 23);
             this.butCancel.TabIndex = 7;
@@ -193,6 +194,17 @@
             this.groupBox1.TabIndex = 13;
             this.groupBox1.TabStop = false;
             // 
+            // chkOnlySelected
+            // 
+            this.chkOnlySelected.AutoSize = true;
+            this.chkOnlySelected.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
+            this.chkOnlySelected.Location = new System.Drawing.Point(362, 81);
+            this.chkOnlySelected.Name = "chkOnlySelected";
+            this.chkOnlySelected.Size = new System.Drawing.Size(118, 17);
+            this.chkOnlySelected.TabIndex = 15;
+            this.chkOnlySelected.Text = "Export only selected";
+            this.chkOnlySelected.UseVisualStyleBackColor = true;
+            // 
             // chkAutoSave
             // 
             this.chkAutoSave.AutoSize = true;
@@ -228,16 +240,17 @@
             this.butExportAndRun.UseVisualStyleBackColor = true;
             this.butExportAndRun.Click += new System.EventHandler(this.butExportAndRun_Click);
             // 
-            // chkOnlySelected
+            // butClose
             // 
-            this.chkOnlySelected.AutoSize = true;
-            this.chkOnlySelected.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
-            this.chkOnlySelected.Location = new System.Drawing.Point(362, 81);
-            this.chkOnlySelected.Name = "chkOnlySelected";
-            this.chkOnlySelected.Size = new System.Drawing.Size(118, 17);
-            this.chkOnlySelected.TabIndex = 15;
-            this.chkOnlySelected.Text = "Export only selected";
-            this.chkOnlySelected.UseVisualStyleBackColor = true;
+            this.butClose.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
+            this.butClose.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
+            this.butClose.Location = new System.Drawing.Point(731, 516);
+            this.butClose.Name = "butClose";
+            this.butClose.Size = new System.Drawing.Size(80, 23);
+            this.butClose.TabIndex = 7;
+            this.butClose.Text = "Close";
+            this.butClose.UseVisualStyleBackColor = true;
+            this.butClose.Click += new System.EventHandler(this.butClose_Click);
             // 
             // ExporterForm
             // 
@@ -247,6 +260,7 @@
             this.Controls.Add(this.butExportAndRun);
             this.Controls.Add(this.groupBox1);
             this.Controls.Add(this.pictureBox2);
+            this.Controls.Add(this.butClose);
             this.Controls.Add(this.butCancel);
             this.Controls.Add(this.treeView);
             this.Controls.Add(this.progressBar);
@@ -287,5 +301,6 @@
         private System.Windows.Forms.CheckBox chkAutoSave;
         private System.Windows.Forms.Button butExportAndRun;
         private System.Windows.Forms.CheckBox chkOnlySelected;
+        private System.Windows.Forms.Button butClose;
     }
 }

+ 5 - 0
Exporters/3ds Max/Max2Babylon/Forms/ExporterForm.cs

@@ -218,5 +218,10 @@ namespace Max2Babylon
                 WindowState = FormWindowState.Minimized;
             }
         }
+
+        private void butClose_Click(object sender, EventArgs e)
+        {
+            Close();
+        }
     }
 }

File diff suppressed because it is too large
+ 93 - 19
babylon.1.14-beta-debug.js


File diff suppressed because it is too large
+ 15 - 15
babylon.1.14-beta.js