Julien MOREAU-MATHIS преди 7 години
родител
ревизия
cd2515a2f7

+ 10 - 0
Tools/Gulp/config.json

@@ -1319,6 +1319,16 @@
             },
             {
                 "files": [
+                    "../../materialsLibrary/src/mix/babylon.mixMaterial.ts"
+                ],
+                "shaderFiles": [
+                    "../../materialsLibrary/src/mix/mix.vertex.fx",
+                    "../../materialsLibrary/src/mix/mix.fragment.fx"
+                ],
+                "output": "babylon.mixMaterial.js"
+            },
+            {
+                "files": [
                     "../../materialsLibrary/src/triPlanar/babylon.triPlanarMaterial.ts"
                 ],
                 "shaderFiles": [

+ 489 - 0
materialsLibrary/src/mix/babylon.mixMaterial.ts

@@ -0,0 +1,489 @@
+/// <reference path="../../../dist/preview release/babylon.d.ts"/>
+
+module BABYLON {
+
+    class MixMaterialDefines extends MaterialDefines {
+        public DIFFUSE = false;
+        public BUMP = false;
+        public CLIPPLANE = false;
+        public ALPHATEST = false;
+        public DEPTHPREPASS = false;
+        public POINTSIZE = false;
+        public FOG = false;
+        public SPECULARTERM = false;
+        public NORMAL = false;
+        public UV1 = false;
+        public UV2 = false;
+        public VERTEXCOLOR = false;
+        public VERTEXALPHA = false;
+        public NUM_BONE_INFLUENCERS = 0;
+        public BonesPerMesh = 0;
+        public INSTANCES = false;
+        public MIXMAP2 = false;
+
+        constructor() {
+            super();
+            this.rebuild();
+        }
+    }
+
+    export class MixMaterial extends PushMaterial {
+        /**
+         * Mix textures
+         */
+
+        @serializeAsTexture("mixTexture")
+        private _mixTexture: BaseTexture;
+        @expandToProperty("_markAllSubMeshesAsTexturesDirty")
+        public mixTexture: BaseTexture;
+
+        @serializeAsTexture("mixTexture")
+        private _mixTexture2: BaseTexture;
+        @expandToProperty("_markAllSubMeshesAsTexturesDirty")
+        public mixTexture2: BaseTexture;
+
+        /**
+         * Diffuse textures
+         */
+
+        @serializeAsTexture("diffuseTexture1")
+        private _diffuseTexture1: Texture;
+        @expandToProperty("_markAllSubMeshesAsTexturesDirty")
+        public diffuseTexture1: Texture;
+
+        @serializeAsTexture("diffuseTexture2")
+        private _diffuseTexture2: Texture;
+        @expandToProperty("_markAllSubMeshesAsTexturesDirty")
+        public diffuseTexture2: Texture;
+
+        @serializeAsTexture("diffuseTexture3")
+        private _diffuseTexture3: Texture;
+        @expandToProperty("_markAllSubMeshesAsTexturesDirty")
+        public diffuseTexture3: Texture;
+
+        @serializeAsTexture("diffuseTexture4")
+        private _diffuseTexture4: Texture;
+        @expandToProperty("_markAllSubMeshesAsTexturesDirty")
+        public diffuseTexture4: Texture;
+
+        /**
+         * Bump textures
+         */
+
+        @serializeAsTexture("bumpTexture1")
+        private _bumpTexture1: Texture;
+        @expandToProperty("_markAllSubMeshesAsTexturesDirty")
+        public bumpTexture1: Texture;
+
+        @serializeAsTexture("bumpTexture2")
+        private _bumpTexture2: Texture;
+        @expandToProperty("_markAllSubMeshesAsTexturesDirty")
+        public bumpTexture2: Texture;
+
+        @serializeAsTexture("bumpTexture3")
+        private _bumpTexture3: Texture;
+        @expandToProperty("_markAllSubMeshesAsTexturesDirty")
+        public bumpTexture3: Texture;
+
+        @serializeAsTexture("bumpTexture4")
+        private _bumpTexture4: Texture;
+        @expandToProperty("_markAllSubMeshesAsTexturesDirty")
+        public bumpTexture4: Texture;
+
+        /**
+         * Uniforms
+         */
+
+        @serializeAsColor3()
+        public diffuseColor = new Color3(1, 1, 1);
+
+        @serializeAsColor3()
+        public specularColor = new Color3(0, 0, 0);
+
+        @serialize()
+        public specularPower = 64;
+
+        @serialize("disableLighting")
+        private _disableLighting = false;
+        @expandToProperty("_markAllSubMeshesAsLightsDirty")
+        public disableLighting: boolean;
+
+        @serialize("maxSimultaneousLights")
+        private _maxSimultaneousLights = 4;
+        @expandToProperty("_markAllSubMeshesAsLightsDirty")
+        public maxSimultaneousLights: number;
+
+        private _renderId: number;
+
+        constructor(name: string, scene: Scene) {
+            super(name, scene);
+        }
+
+        public needAlphaBlending(): boolean {
+            return (this.alpha < 1.0);
+        }
+
+        public needAlphaTesting(): boolean {
+            return false;
+        }
+
+        public getAlphaTestTexture(): Nullable<BaseTexture> {
+            return null;
+        }
+
+        // Methods   
+        public isReadyForSubMesh(mesh: AbstractMesh, subMesh: SubMesh, useInstances?: boolean): boolean {
+            if (this.isFrozen) {
+                if (this._wasPreviouslyReady && subMesh.effect) {
+                    return true;
+                }
+            }
+
+            if (!subMesh._materialDefines) {
+                subMesh._materialDefines = new MixMaterialDefines();
+            }
+
+            var defines = <MixMaterialDefines>subMesh._materialDefines;
+            var scene = this.getScene();
+
+            if (!this.checkReadyOnEveryCall && subMesh.effect) {
+                if (this._renderId === scene.getRenderId()) {
+                    return true;
+                }
+            }
+
+            var engine = scene.getEngine();
+
+            // Textures
+            if (scene.texturesEnabled) {
+                if (StandardMaterial.DiffuseTextureEnabled) {
+                    if (this.mixTexture) {
+                        if (!this.mixTexture.isReady()) {
+                            return false;
+                        } else {
+                            defines._needUVs = true;
+                            defines.DIFFUSE = true;
+                        }
+                    }
+                    if (this.mixTexture2) {
+                        if (!this.mixTexture2.isReady()) {
+                            return false;
+                        } else {
+                            defines.MIXMAP2 = true;
+                        }
+                    }
+                    if ((this.bumpTexture1 || this.bumpTexture2 || this.bumpTexture3 || this.bumpTexture4) && StandardMaterial.BumpTextureEnabled) {
+                        defines._needNormals = true;
+                        defines.BUMP = true;
+                    }
+                }
+            }
+
+            // Misc.
+            MaterialHelper.PrepareDefinesForMisc(mesh, scene, false, this.pointsCloud, this.fogEnabled, this._shouldTurnAlphaTestOn(mesh), defines);
+
+            // Lights
+            defines._needNormals = MaterialHelper.PrepareDefinesForLights(scene, mesh, defines, false, this._maxSimultaneousLights, this._disableLighting);
+
+            // Values that need to be evaluated on every frame
+            MaterialHelper.PrepareDefinesForFrameBoundValues(scene, engine, defines, useInstances ? true : false);
+
+            // Attribs
+            MaterialHelper.PrepareDefinesForAttributes(mesh, defines, true, true);
+
+            // Get correct effect      
+            if (defines.isDirty) {
+                defines.markAsProcessed();
+                scene.resetCachedMaterial();
+
+                // Fallbacks
+                var fallbacks = new EffectFallbacks();
+                if (defines.FOG) {
+                    fallbacks.addFallback(1, "FOG");
+                }
+
+                MaterialHelper.HandleFallbacksForShadows(defines, fallbacks, this.maxSimultaneousLights);
+
+                if (defines.NUM_BONE_INFLUENCERS > 0) {
+                    fallbacks.addCPUSkinningFallback(0, mesh);
+                }
+
+                //Attributes
+                var attribs = [VertexBuffer.PositionKind];
+
+                if (defines.NORMAL) {
+                    attribs.push(VertexBuffer.NormalKind);
+                }
+
+                if (defines.UV1) {
+                    attribs.push(VertexBuffer.UVKind);
+                }
+
+                if (defines.UV2) {
+                    attribs.push(VertexBuffer.UV2Kind);
+                }
+
+                if (defines.VERTEXCOLOR) {
+                    attribs.push(VertexBuffer.ColorKind);
+                }
+
+                MaterialHelper.PrepareAttributesForBones(attribs, mesh, defines, fallbacks);
+                MaterialHelper.PrepareAttributesForInstances(attribs, defines);
+
+                // Legacy browser patch
+                var shaderName = "terrain";
+                var join = defines.toString();
+                var uniforms = ["world", "view", "viewProjection", "vEyePosition", "vLightsType", "vDiffuseColor", "vSpecularColor",
+                    "vFogInfos", "vFogColor", "pointSize",
+                    "vTextureInfos",
+                    "mBones",
+                    "vClipPlane", "textureMatrix",
+                    "diffuse1Infos", "diffuse2Infos", "diffuse3Infos", "diffuse4Infos"
+                ];
+                var samplers = [
+                    "mixMap1Sampler", "mixMap2Sampler",
+                    "diffuse1Sampler", "diffuse2Sampler", "diffuse3Sampler", "diffuse4Sampler",
+                    "bump1Sampler", "bump2Sampler", "bump3Sampler"
+                ];
+
+                var uniformBuffers = new Array<string>()
+
+                MaterialHelper.PrepareUniformsAndSamplersList(<EffectCreationOptions>{
+                    uniformsNames: uniforms,
+                    uniformBuffersNames: uniformBuffers,
+                    samplers: samplers,
+                    defines: defines,
+                    maxSimultaneousLights: this.maxSimultaneousLights
+                });
+
+                subMesh.setEffect(scene.getEngine().createEffect(shaderName,
+                    <EffectCreationOptions>{
+                        attributes: attribs,
+                        uniformsNames: uniforms,
+                        uniformBuffersNames: uniformBuffers,
+                        samplers: samplers,
+                        defines: join,
+                        fallbacks: fallbacks,
+                        onCompiled: this.onCompiled,
+                        onError: this.onError,
+                        indexParameters: { maxSimultaneousLights: this.maxSimultaneousLights }
+                    }, engine), defines);
+            }
+            if (!subMesh.effect || !subMesh.effect.isReady()) {
+                return false;
+            }
+
+            this._renderId = scene.getRenderId();
+            this._wasPreviouslyReady = true;
+
+            return true;
+        }
+
+        public bindForSubMesh(world: Matrix, mesh: Mesh, subMesh: SubMesh): void {
+            var scene = this.getScene();
+
+            var defines = <MixMaterialDefines>subMesh._materialDefines;
+            if (!defines) {
+                return;
+            }
+
+            var effect = subMesh.effect;
+            if (!effect) {
+                return;
+            }
+            this._activeEffect = effect;
+
+            // Matrices        
+            this.bindOnlyWorldMatrix(world);
+            this._activeEffect.setMatrix("viewProjection", scene.getTransformMatrix());
+
+            // Bones
+            MaterialHelper.BindBonesParameters(mesh, this._activeEffect);
+
+            if (this._mustRebind(scene, effect)) {
+                // Textures        
+                if (this.mixTexture) {
+                    this._activeEffect.setTexture("mixMap1Sampler", this._mixTexture);
+                    this._activeEffect.setFloat2("vTextureInfos", this._mixTexture.coordinatesIndex, this._mixTexture.level);
+                    this._activeEffect.setMatrix("textureMatrix", this._mixTexture.getTextureMatrix());
+
+                    if (StandardMaterial.DiffuseTextureEnabled) {
+                        if (this._diffuseTexture1) {
+                            this._activeEffect.setTexture("diffuse1Sampler", this._diffuseTexture1);
+                            this._activeEffect.setFloat2("diffuse1Infos", this._diffuseTexture1.uScale, this._diffuseTexture1.vScale);
+                        }
+                        if (this._diffuseTexture2) {
+                            this._activeEffect.setTexture("diffuse2Sampler", this._diffuseTexture2);
+                            this._activeEffect.setFloat2("diffuse2Infos", this._diffuseTexture2.uScale, this._diffuseTexture2.vScale);
+                        }
+                        if (this._diffuseTexture3) {
+                            this._activeEffect.setTexture("diffuse3Sampler", this._diffuseTexture3);
+                            this._activeEffect.setFloat2("diffuse3Infos", this._diffuseTexture3.uScale, this._diffuseTexture3.vScale);
+                        }
+                        if (this._diffuseTexture4) {
+                            this._activeEffect.setTexture("diffuse4Sampler", this._diffuseTexture4);
+                            this._activeEffect.setFloat2("diffuse4Infos", this._diffuseTexture4.uScale, this._diffuseTexture4.vScale);
+                        }
+                    }
+
+                    if (StandardMaterial.BumpTextureEnabled && scene.getEngine().getCaps().standardDerivatives) {
+                        if (this._bumpTexture1) {
+                            this._activeEffect.setTexture("bump1Sampler", this._bumpTexture1);
+                        }
+                        if (this._bumpTexture2) {
+                            this._activeEffect.setTexture("bump2Sampler", this._bumpTexture2);
+                        }
+                        if (this._bumpTexture3) {
+                            this._activeEffect.setTexture("bump3Sampler", this._bumpTexture3);
+                        }
+                        if (this.bumpTexture4) {
+                            this._activeEffect.setTexture("bump4Sampler", this._bumpTexture4);
+                        }
+                    }
+                }
+
+                if (this.mixTexture2) {
+                    this._activeEffect.setTexture("mixMap2Sampler", this._mixTexture2);
+                }
+
+                // Clip plane
+                MaterialHelper.BindClipPlane(this._activeEffect, scene);
+
+                // Point size
+                if (this.pointsCloud) {
+                    this._activeEffect.setFloat("pointSize", this.pointSize);
+                }
+
+                MaterialHelper.BindEyePosition(effect, scene);
+            }
+
+            this._activeEffect.setColor4("vDiffuseColor", this.diffuseColor, this.alpha * mesh.visibility);
+
+            if (defines.SPECULARTERM) {
+                this._activeEffect.setColor4("vSpecularColor", this.specularColor, this.specularPower);
+            }
+
+            if (scene.lightsEnabled && !this.disableLighting) {
+                MaterialHelper.BindLights(scene, mesh, this._activeEffect, defines, this.maxSimultaneousLights);
+            }
+
+            // View
+            if (scene.fogEnabled && mesh.applyFog && scene.fogMode !== Scene.FOGMODE_NONE) {
+                this._activeEffect.setMatrix("view", scene.getViewMatrix());
+            }
+
+            // Fog
+            MaterialHelper.BindFogParameters(scene, mesh, this._activeEffect);
+
+            this._afterBind(mesh, this._activeEffect);
+        }
+
+        public getAnimatables(): IAnimatable[] {
+            var results = [];
+
+            if (this.mixTexture && this.mixTexture.animations && this.mixTexture.animations.length > 0) {
+                results.push(this.mixTexture);
+            }
+
+            return results;
+        }
+
+        public getActiveTextures(): BaseTexture[] {
+            var activeTextures = super.getActiveTextures();
+
+            if (this._mixTexture) {
+                activeTextures.push(this._mixTexture);
+            }
+
+            if (this._diffuseTexture1) {
+                activeTextures.push(this._diffuseTexture1);
+            }
+
+            if (this._diffuseTexture2) {
+                activeTextures.push(this._diffuseTexture2);
+            }
+
+            if (this._diffuseTexture3) {
+                activeTextures.push(this._diffuseTexture3);
+            }
+
+            if (this._bumpTexture1) {
+                activeTextures.push(this._bumpTexture1);
+            }
+
+            if (this._bumpTexture2) {
+                activeTextures.push(this._bumpTexture2);
+            }
+
+            if (this._bumpTexture3) {
+                activeTextures.push(this._bumpTexture3);
+            }
+
+            return activeTextures;
+        }
+
+        public hasTexture(texture: BaseTexture): boolean {
+            if (super.hasTexture(texture)) {
+                return true;
+            }
+
+            if (this._mixTexture === texture) {
+                return true;
+            }
+
+            if (this._diffuseTexture1 === texture) {
+                return true;
+            }
+
+            if (this._diffuseTexture2 === texture) {
+                return true;
+            }
+
+            if (this._diffuseTexture3 === texture) {
+                return true;
+            }
+
+            if (this._bumpTexture1 === texture) {
+                return true;
+            }
+
+            if (this._bumpTexture2 === texture) {
+                return true;
+            }
+
+            if (this._bumpTexture3 === texture) {
+                return true;
+            }
+
+            return false;
+        }
+
+        public dispose(forceDisposeEffect?: boolean): void {
+            if (this.mixTexture) {
+                this.mixTexture.dispose();
+            }
+
+            super.dispose(forceDisposeEffect);
+        }
+
+        public clone(name: string): MixMaterial {
+            return SerializationHelper.Clone(() => new MixMaterial(name, this.getScene()), this);
+        }
+
+        public serialize(): any {
+            var serializationObject = SerializationHelper.Serialize(this);
+            serializationObject.customType = "BABYLON.MixMaterial";
+            return serializationObject;
+        }
+
+        public getClassName(): string {
+            return "MixMaterial";
+        }
+
+        // Statics
+        public static Parse(source: any, scene: Scene, rootUrl: string): MixMaterial {
+            return SerializationHelper.Parse(() => new MixMaterial(source.name, scene), source, scene, rootUrl);
+        }
+    }
+}
+

+ 225 - 0
materialsLibrary/src/mix/mix.fragment.fx

@@ -0,0 +1,225 @@
+precision highp float;
+
+// Constants
+uniform vec3 vEyePosition;
+uniform vec4 vDiffuseColor;
+
+#ifdef SPECULARTERM
+uniform vec4 vSpecularColor;
+#endif
+
+// Input
+varying vec3 vPositionW;
+
+#ifdef NORMAL
+varying vec3 vNormalW;
+#endif
+
+#ifdef VERTEXCOLOR
+varying vec4 vColor;
+#endif
+
+// Helper functions
+#include<helperFunctions>
+
+// Lights
+#include<__decl__lightFragment>[0..maxSimultaneousLights]
+
+// Samplers
+#ifdef DIFFUSE
+varying vec2 vTextureUV;
+uniform sampler2D mixMap1Sampler;
+uniform vec2 vTextureInfos;
+
+#ifdef MIXMAP2
+uniform sampler2D mixMap2Sampler;
+#endif
+
+uniform sampler2D diffuse1Sampler;
+uniform sampler2D diffuse2Sampler;
+uniform sampler2D diffuse3Sampler;
+uniform sampler2D diffuse4Sampler;
+
+#ifdef MIXMAP2
+uniform sampler2D diffuse5Sampler;
+uniform sampler2D diffuse6Sampler;
+uniform sampler2D diffuse7Sampler;
+uniform sampler2D diffuse8Sampler;
+#endif
+
+uniform vec2 diffuse1Infos;
+uniform vec2 diffuse2Infos;
+uniform vec2 diffuse3Infos;
+uniform vec2 diffuse4Infos;
+
+#ifdef MIXMAP2
+uniform vec2 diffuse5Infos;
+uniform vec2 diffuse6Infos;
+uniform vec2 diffuse7Infos;
+uniform vec2 diffuse8Infos;
+#endif
+
+#endif
+
+#ifdef BUMP
+uniform sampler2D bump1Sampler;
+uniform sampler2D bump2Sampler;
+uniform sampler2D bump3Sampler;
+uniform sampler2D bump4Sampler;
+
+#ifdef MIXMAP2
+uniform sampler2D bump5Sampler;
+uniform sampler2D bump6Sampler;
+uniform sampler2D bump7Sampler;
+uniform sampler2D bump8Sampler;
+#endif
+#endif
+
+// Shadows
+#include<lightsFragmentFunctions>
+#include<shadowsFragmentFunctions>
+#include<clipPlaneFragmentDeclaration>
+
+// Fog
+#include<fogFragmentDeclaration>
+
+// Bump
+#ifdef BUMP
+#extension GL_OES_standard_derivatives : enable
+// Thanks to http://www.thetenthplanet.de/archives/1180
+mat3 cotangent_frame(vec3 normal, vec3 p, vec2 uv)
+{
+	// get edge vectors of the pixel triangle
+	vec3 dp1 = dFdx(p);
+	vec3 dp2 = dFdy(p);
+	vec2 duv1 = dFdx(uv);
+	vec2 duv2 = dFdy(uv);
+
+	// solve the linear system
+	vec3 dp2perp = cross(dp2, normal);
+	vec3 dp1perp = cross(normal, dp1);
+	vec3 tangent = dp2perp * duv1.x + dp1perp * duv2.x;
+	vec3 binormal = dp2perp * duv1.y + dp1perp * duv2.y;
+
+	// construct a scale-invariant frame 
+	float invmax = inversesqrt(max(dot(tangent, tangent), dot(binormal, binormal)));
+	return mat3(tangent * invmax, binormal * invmax, normal);
+}
+
+vec3 perturbNormal(vec3 viewDir, vec4 mixColor)
+{	
+	vec3 bump1Color = texture2D(bump1Sampler, vTextureUV * diffuse1Infos).xyz;
+	vec3 bump2Color = texture2D(bump2Sampler, vTextureUV * diffuse2Infos).xyz;
+	vec3 bump3Color = texture2D(bump3Sampler, vTextureUV * diffuse3Infos).xyz;
+	vec3 bump4Color = texture2D(bump4Sampler, vTextureUV * diffuse4Infos).xyz;
+	
+	bump1Color.rgb *= mixColor.r;
+   	bump2Color.rgb = mix(bump1Color.rgb, bump2Color.rgb, mixColor.g);
+   	bump3Color.rgb = mix(bump2Color.rgb, bump3Color.rgb, mixColor.b);
+	
+	vec3 map = mix(bump3Color.rgb, bump4Color.rgb, mixColor.a);
+
+	map = map * 255. / 127. - 128. / 127.;
+	mat3 TBN = cotangent_frame(vNormalW * vTextureInfos.y, -viewDir, vTextureUV);
+	return normalize(TBN * map);
+}
+#endif
+
+
+void main(void) {
+	// Clip plane
+#ifdef CLIPPLANE
+	if (fClipDistance > 0.0)
+		discard;
+#endif
+
+	vec3 viewDirectionW = normalize(vEyePosition - vPositionW);
+
+	// Base color
+	vec4 mixColor1 = vec4(1., 1., 1., 1.);
+	vec3 diffuseColor = vDiffuseColor.rgb;
+
+#ifdef MIXMAP2
+	vec4 mixColor2 = vec4(1., 1., 1., 1.);
+#endif
+	
+#ifdef SPECULARTERM
+	float glossiness = vSpecularColor.a;
+	vec3 specularColor = vSpecularColor.rgb;
+#else
+	float glossiness = 0.;
+#endif
+
+	// Alpha
+	float alpha = vDiffuseColor.a;
+	
+	// Bump
+#ifdef NORMAL
+	vec3 normalW = normalize(vNormalW);
+#else
+	vec3 normalW = vec3(1.0, 1.0, 1.0);
+#endif
+
+#ifdef DIFFUSE
+	mixColor1 = texture2D(mixMap1Sampler, vTextureUV);
+
+#if defined(BUMP) && defined(DIFFUSE)
+	normalW = perturbNormal(viewDirectionW, mixColor1);
+#endif
+
+#include<depthPrePass>
+
+	mixColor1.rgb *= vTextureInfos.y;
+	
+	vec4 diffuse1Color = texture2D(diffuse1Sampler, vTextureUV * diffuse1Infos);
+	vec4 diffuse2Color = texture2D(diffuse2Sampler, vTextureUV * diffuse2Infos);
+	vec4 diffuse3Color = texture2D(diffuse3Sampler, vTextureUV * diffuse3Infos);
+	vec4 diffuse4Color = texture2D(diffuse4Sampler, vTextureUV * diffuse4Infos);
+	
+	diffuse1Color.rgb *= mixColor1.r;
+   	diffuse2Color.rgb = mix(diffuse1Color.rgb, diffuse2Color.rgb, mixColor1.g);
+   	diffuse3Color.rgb = mix(diffuse2Color.rgb, diffuse3Color.rgb, mixColor1.b);
+	mixColor1.rgb = mix(diffuse3Color.rgb, diffuse4Color.rgb, 1.0 - mixColor1.a);
+
+#ifdef MIXMAP2
+	vec4 diffuse5Color = texture2D(diffuse5Sampler, vTextureUV * diffuse5Infos);
+	vec4 diffuse6Color = texture2D(diffuse6Sampler, vTextureUV * diffuse6Infos);
+	vec4 diffuse7Color = texture2D(diffuse7Sampler, vTextureUV * diffuse7Infos);
+	vec4 diffuse8Color = texture2D(diffuse8Sampler, vTextureUV * diffuse8Infos);
+#endif
+	
+#endif
+
+#ifdef VERTEXCOLOR
+	mixColor1.rgb *= vColor.rgb;
+#endif
+
+	// Lighting
+	vec3 diffuseBase = vec3(0., 0., 0.);
+    lightingInfo info;
+	float shadow = 1.;
+	
+#ifdef SPECULARTERM
+	vec3 specularBase = vec3(0., 0., 0.);
+#endif
+	#include<lightFragment>[0..maxSimultaneousLights]
+
+#ifdef VERTEXALPHA
+	alpha *= vColor.a;
+#endif
+
+#ifdef SPECULARTERM
+	vec3 finalSpecular = specularBase * specularColor;
+#else
+	vec3 finalSpecular = vec3(0.0);
+#endif
+
+    vec3 finalDiffuse = clamp(diffuseBase * diffuseColor * mixColor1.rgb, 0.0, 1.0);
+
+	// Composition
+	vec4 color = vec4(finalDiffuse + finalSpecular, alpha);
+
+#include<fogFragment>
+
+	gl_FragColor = color;
+}

+ 102 - 0
materialsLibrary/src/mix/mix.vertex.fx

@@ -0,0 +1,102 @@
+precision highp float;
+
+// Attributes
+attribute vec3 position;
+#ifdef NORMAL
+attribute vec3 normal;
+#endif
+#ifdef UV1
+attribute vec2 uv;
+#endif
+#ifdef UV2
+attribute vec2 uv2;
+#endif
+#ifdef VERTEXCOLOR
+attribute vec4 color;
+#endif
+
+#include<bonesDeclaration>
+
+// Uniforms
+#include<instancesDeclaration>
+
+uniform mat4 view;
+uniform mat4 viewProjection;
+
+#ifdef DIFFUSE
+varying vec2 vTextureUV;
+uniform mat4 textureMatrix;
+uniform vec2 vTextureInfos;
+#endif
+
+#ifdef POINTSIZE
+uniform float pointSize;
+#endif
+
+// Output
+varying vec3 vPositionW;
+#ifdef NORMAL
+varying vec3 vNormalW;
+#endif
+
+#ifdef VERTEXCOLOR
+varying vec4 vColor;
+#endif
+
+#include<clipPlaneVertexDeclaration>
+#include<fogVertexDeclaration>
+#include<__decl__lightFragment>[0..maxSimultaneousLights]
+
+void main(void) {
+	#include<instancesVertex>
+    #include<bonesVertex>
+	
+	gl_Position = viewProjection * finalWorld * vec4(position, 1.0);
+
+	vec4 worldPos = finalWorld * vec4(position, 1.0);
+	vPositionW = vec3(worldPos);
+
+#ifdef NORMAL
+	vNormalW = normalize(vec3(finalWorld * vec4(normal, 0.0)));
+#endif
+
+	// Texture coordinates
+#ifndef UV1
+	vec2 uv = vec2(0., 0.);
+#endif
+#ifndef UV2
+	vec2 uv2 = vec2(0., 0.);
+#endif
+
+#ifdef DIFFUSE
+	if (vTextureInfos.x == 0.)
+	{
+		vTextureUV = vec2(textureMatrix * vec4(uv, 1.0, 0.0));
+	}
+	else
+	{
+		vTextureUV = vec2(textureMatrix * vec4(uv2, 1.0, 0.0));
+	}
+#endif
+
+	// Clip plane
+#ifdef CLIPPLANE
+	fClipDistance = dot(worldPos, vClipPlane);
+#endif
+
+	// Fog
+	#include<fogVertex>
+	
+	// Shadows
+    #include<shadowsVertex>[0..maxSimultaneousLights]
+
+	// Vertex color
+#ifdef VERTEXCOLOR
+	vColor = color;
+#endif
+
+	// Point size
+#ifdef POINTSIZE
+	gl_PointSize = pointSize;
+#endif
+}

+ 21 - 0
materialsLibrary/test/addMix.js

@@ -0,0 +1,21 @@
+window.prepareTerrain = function() {
+    var terrain = new BABYLON.TerrainMaterial("terrain", scene);
+    terrain.specularColor = new BABYLON.Color3(0.5, 0.5, 0.5);
+    terrain.specularPower = 64;
+    terrain.mixTexture = new BABYLON.Texture("/playground/textures/mixMap.png", scene);
+    terrain.diffuseTexture1 = new BABYLON.Texture("/playground/textures/floor.png", scene);
+    terrain.diffuseTexture2 = new BABYLON.Texture("/playground/textures/rock.png", scene);
+    terrain.diffuseTexture3 = new BABYLON.Texture("/playground/textures/grass.png", scene);
+    terrain.diffuseTexture4 = new BABYLON.Texture("/playground/textures/floor.png", scene);
+    
+    terrain.bumpTexture1 = new BABYLON.Texture("/playground/textures/floor_bump.PNG", scene);
+    terrain.bumpTexture2 = new BABYLON.Texture("/playground/textures/rockn.png", scene);
+    terrain.bumpTexture3 = new BABYLON.Texture("/playground/textures/grassn.png", scene);
+    terrain.bumpTexture4 = new BABYLON.Texture("/playground/textures/floor_bump.PNG", scene);
+    
+    terrain.diffuseTexture1.uScale = terrain.diffuseTexture1.vScale = 10;
+    terrain.diffuseTexture2.uScale = terrain.diffuseTexture2.vScale = 10;
+    terrain.diffuseTexture3.uScale = terrain.diffuseTexture3.vScale = 10;
+    
+    return terrain;
+};