瀏覽代碼

1.1.0:
- Shadow Maps and Variance Shadow Maps
- Shadows Maps and animations are now exported from Blender
- Hand.js is no longer required for ArcRotateCamera
- ArcRotateCamera support pinch/zoom gesture on IE

David Catuhe 12 年之前
父節點
當前提交
4ec2377e20
共有 75 個文件被更改,包括 992 次插入184 次删除
  1. 43 8
      Babylon/Cameras/babylon.arcRotateCamera.js
  2. 93 0
      Babylon/Lights/Shadows/babylon.shadowGenerator.js
  3. 1 0
      Babylon/Lights/babylon.directionalLight.js
  4. 4 0
      Babylon/Lights/babylon.hemisphericLight.js
  5. 21 0
      Babylon/Lights/babylon.light.js
  6. 4 0
      Babylon/Lights/babylon.pointLight.js
  7. 45 36
      Babylon/Materials/babylon.effect.js
  8. 35 10
      Babylon/Materials/babylon.standardMaterial.js
  9. 3 0
      Babylon/Materials/textures/babylon.mirrorTexture.js
  10. 10 4
      Babylon/Materials/textures/babylon.renderTargetTexture.js
  11. 3 3
      Babylon/Materials/textures/babylon.videoTexture.js
  12. 23 16
      Babylon/Mesh/babylon.mesh.js
  13. 4 0
      Babylon/Mesh/babylon.subMesh.js
  14. 1 5
      Babylon/Particles/babylon.particleSystem.js
  15. 126 9
      Babylon/Shaders/default.fragment.fx
  16. 40 1
      Babylon/Shaders/default.vertex.fx
  17. 59 2
      Babylon/Shaders/iedefault.fragment.fx
  18. 19 1
      Babylon/Shaders/iedefault.vertex.fx
  19. 5 1
      Babylon/Shaders/layer.vertex.fx
  20. 5 1
      Babylon/Shaders/particles.vertex.fx
  21. 35 0
      Babylon/Shaders/shadowMap.fragment.fx
  22. 14 0
      Babylon/Shaders/shadowMap.vertex.fx
  23. 5 1
      Babylon/Shaders/sprites.vertex.fx
  24. 31 5
      Babylon/Tools/babylon.sceneLoader.js
  25. 12 0
      Babylon/Tools/babylon.tools.js
  26. 31 11
      Babylon/babylon.engine.js
  27. 25 0
      Babylon/babylon.scene.js
  28. 159 17
      Exporters/Blender/io_export_babylon.py
  29. 二進制
      Samples/Assets/grass.jpg
  30. 二進制
      Samples/Scenes/Blender/63_Free_Windows_Xp_Vista_Wallpapers.jpg
  31. 二進制
      Samples/Scenes/Blender/69_Free_Windows_Xp_Vista_Wallpapers.jpg
  32. 二進制
      Samples/Scenes/Blender/Ciel.png
  33. 二進制
      Samples/Scenes/Blender/Finishes.Plaster.Stucco.Fine.Mauve.jpg
  34. 二進制
      Samples/Scenes/Blender/MS-384.jpg
  35. 二進制
      Samples/Scenes/Blender/Metal1.png
  36. 二進制
      Samples/Scenes/Blender/Tree.png
  37. 二進制
      Samples/Scenes/Blender/WP_20121206_003.jpg
  38. 5 7
      Samples/Scenes/Blender/blender.babylon
  39. 二進制
      Samples/Scenes/Blender/blender.blend
  40. 二進制
      Samples/Scenes/Blender/concrete5.png
  41. 二進制
      Samples/Scenes/Blender/new-york1-1600-1200.jpg
  42. 二進制
      Samples/Scenes/Blender/skin.png
  43. 二進制
      Samples/Scenes/Blender/snow.jpg
  44. 二進制
      Samples/Scenes/Blender/test_vase_color.jpg
  45. 二進制
      Samples/Scenes/Blender/tyrol_austria___misty_mountain_village-1600x1200.jpg
  46. 0 11
      Samples/Scenes/Blender/untitled.babylon
  47. 二進制
      Samples/Scenes/Blender/vase_test1.png
  48. 78 0
      Samples/Scenes/Customs/shadows.js
  49. 二進制
      Samples/Scenes/Customs/skybox/night_nx.jpg
  50. 二進制
      Samples/Scenes/Customs/skybox/night_ny.jpg
  51. 二進制
      Samples/Scenes/Customs/skybox/night_nz.jpg
  52. 二進制
      Samples/Scenes/Customs/skybox/night_px.jpg
  53. 二進制
      Samples/Scenes/Customs/skybox/night_py.jpg
  54. 二進制
      Samples/Scenes/Customs/skybox/night_pz.jpg
  55. 1 1
      Samples/Scenes/Espilit/espilit.babylon
  56. 1 1
      Samples/Scenes/Flat2009/Flat2009.babylon
  57. 1 1
      Samples/Scenes/Heart/Heart.babylon
  58. 1 1
      Samples/Scenes/SpaceDek/SpaceDek.babylon
  59. 1 1
      Samples/Scenes/Spaceship/Spaceship.babylon
  60. 1 1
      Samples/Scenes/TestAnim/TestAnim.babylon
  61. 1 1
      Samples/Scenes/TheCar/TheCar.babylon
  62. 1 1
      Samples/Scenes/Viper/Viper.babylon
  63. 1 1
      Samples/Scenes/WCafe/WCafe.babylon
  64. 4 4
      Samples/Scenes/WorldMonger/Shaders/Water/waterMaterial.js
  65. 二進制
      Samples/Screenshots/blender.jpg
  66. 二進制
      Samples/Screenshots/shadows.jpg
  67. 10 8
      Samples/babylon.js
  68. 1 1
      Samples/hand.minified-1.1.0.js
  69. 1 1
      Samples/index.css
  70. 4 1
      Samples/index.html
  71. 5 0
      Samples/index.js
  72. 0 11
      babylon.1.0.10.js
  73. 13 0
      babylon.1.1.0.js
  74. 1 0
      readme.md
  75. 5 0
      what's new.txt

+ 43 - 8
Babylon/Cameras/babylon.arcRotateCamera.js

@@ -1,6 +1,8 @@
 var BABYLON = BABYLON || {};
 
 (function () {
+    var eventPrefix = BABYLON.Tools.GetPointerPrefix();
+
     BABYLON.ArcRotateCamera = function (name, alpha, beta, radius, target, scene) {
         this.name = name;
         this.id = name;
@@ -39,8 +41,16 @@
     BABYLON.ArcRotateCamera.prototype.attachControl = function(canvas) {
         var previousPosition;
         var that = this;
+        var pointerId;
         
         this._onPointerDown = function (evt) {
+            
+            if (pointerId) {
+                return;
+            }
+
+            pointerId = evt.pointerId;
+
             previousPosition = {
                 x: evt.clientX,
                 y: evt.clientY
@@ -51,6 +61,7 @@
 
         this._onPointerUp = function (evt) {
             previousPosition = null;
+            pointerId = null;
             evt.preventDefault();
         };
 
@@ -58,6 +69,10 @@
             if (!previousPosition) {
                 return;
             }
+            
+            if (pointerId !== evt.pointerId) {
+                return;
+            }
 
             var offsetX = evt.clientX - previousPosition.x;
             var offsetY = evt.clientY - previousPosition.y;
@@ -118,12 +133,28 @@
         
         this._onLostFocus = function () {
             that._keys = [];
+            pointerId = null;
         };
 
-        canvas.addEventListener("pointerdown", this._onPointerDown);
-        canvas.addEventListener("pointerup", this._onPointerUp);
-        canvas.addEventListener("pointerout", this._onPointerUp);
-        canvas.addEventListener("pointermove", this._onPointerMove);
+        this._onGestureStart = function (e) {
+            if (!that._MSGestureHandler) {
+                that._MSGestureHandler = new MSGesture();
+                that._MSGestureHandler.target = canvas;
+            }
+
+            that._MSGestureHandler.addPointer(e.pointerId);
+        };
+
+        this._onGesture = function(e) {
+            that.radius *= e.scale;
+        };
+        
+        canvas.addEventListener(eventPrefix + "down", this._onPointerDown);
+        canvas.addEventListener(eventPrefix + "up", this._onPointerUp);
+        canvas.addEventListener(eventPrefix + "out", this._onPointerUp);
+        canvas.addEventListener(eventPrefix + "move", this._onPointerMove);
+        canvas.addEventListener("MSPointerDown", this._onGestureStart);
+        canvas.addEventListener("MSGestureChange", this._onGesture, true);
         window.addEventListener("keydown", this._onKeyDown, true);
         window.addEventListener("keyup", this._onKeyUp, true);
         window.addEventListener('mousewheel', this._wheel);
@@ -131,14 +162,18 @@
     };
     
     BABYLON.ArcRotateCamera.prototype.detachControl = function (canvas) {
-        canvas.removeEventListener("pointerdown", this._onPointerDown);
-        canvas.removeEventListener("pointerup", this._onPointerUp);
-        canvas.removeEventListener("pointerout", this._onPointerUp);
-        canvas.removeEventListener("pointermove", this._onPointerMove);
+        canvas.removeEventListener(eventPrefix + "down", this._onPointerDown);
+        canvas.removeEventListener(eventPrefix + "up", this._onPointerUp);
+        canvas.removeEventListener(eventPrefix + "out", this._onPointerUp);
+        canvas.removeEventListener(eventPrefix + "move", this._onPointerMove);
+        canvas.removeEventListener("MSPointerDown", this._onGestureStart);
+        canvas.removeEventListener("MSGestureChange", this._onGesture);
         window.removeEventListener("keydown", this._onKeyDown);
         window.removeEventListener("keyup", this._onKeyUp);
         window.removeEventListener('mousewheel', this._wheel);
         window.removeEventListener("blur", this._onLostFocus);
+
+        this._MSGestureHandler = null;
     };
 
     BABYLON.ArcRotateCamera.prototype._update = function () {

+ 93 - 0
Babylon/Lights/Shadows/babylon.shadowGenerator.js

@@ -0,0 +1,93 @@
+var BABYLON = BABYLON || {};
+
+(function () {
+    BABYLON.ShadowGenerator = function (mapSize, light) {
+        this._light = light;
+        this._scene = light.getScene();
+
+        light._shadowGenerator = this;
+
+        // Render target
+        this._shadowMap = new BABYLON.RenderTargetTexture(light.name + "_shadowMap", mapSize, this._scene, false);
+        this._shadowMap.wrapU = BABYLON.Texture.CLAMP_ADDRESSMODE;
+        this._shadowMap.wrapV = BABYLON.Texture.CLAMP_ADDRESSMODE;
+        
+        // Effect
+        this._effect = this._scene.getEngine().createEffect("shadowMap",
+                    ["position"],
+                    ["worldViewProjection"],
+                    [], "");
+        
+        this._effectVSM = this._scene.getEngine().createEffect("shadowMap",
+                    ["position"],
+                    ["worldViewProjection"],
+                    [], "#define VSM");
+        
+        // Custom render function
+        var that = this;
+
+        var renderSubMesh = function (subMesh, effect) {
+            var mesh = subMesh.getMesh();
+            var world = mesh.getWorldMatrix();
+            
+            effect.setMatrix("worldViewProjection", world.multiply(that.getTransformMatrix()));
+            
+            // Bind and draw
+            mesh.bindAndDraw(subMesh, effect, false);
+        };
+
+        this._shadowMap.customRenderFunction = function (opaqueSubMeshes, alphaTestSubMeshes, transparentSubMeshes, activeMeshes) {
+            var engine = that._scene.getEngine();
+            var index;
+            var effect = that.useVarianceShadowMap ? that._effectVSM : that._effect;
+
+            engine.enableEffect(effect);
+            
+            for (index = 0; index < opaqueSubMeshes.length; index++) {
+                renderSubMesh(opaqueSubMeshes[index], effect);
+            }
+            
+            for (index = 0; index < alphaTestSubMeshes.length; index++) {
+                renderSubMesh(alphaTestSubMeshes[index], effect);
+            }
+        };
+    };
+    
+    // Members
+    BABYLON.ShadowGenerator.prototype.useVarianceShadowMap = true;
+    
+    // Properties
+    BABYLON.ShadowGenerator.prototype.isReady = function () {
+        return this._effect.isReady() && this._effectVSM.isReady();
+    };
+    
+    BABYLON.ShadowGenerator.prototype.getShadowMap = function () {
+        return this._shadowMap;
+    };
+    
+    BABYLON.ShadowGenerator.prototype.getLight = function () {
+        return this._light;
+    };
+    
+    // Methods
+    BABYLON.ShadowGenerator.prototype.getTransformMatrix = function () {
+        if (!this._cachedPosition || !this._cachedDirection || !this._light.position.equals(this._cachedPosition) || !this._light.direction.equals(this._cachedDirection)) {
+
+            this._cachedPosition = this._light.position.clone();
+            this._cachedDirection = this._light.direction.clone();
+
+            var activeCamera = this._scene.activeCamera;
+
+            var view = new BABYLON.Matrix.LookAtLH(this._light.position, this._light.position.add(this._light.direction), BABYLON.Vector3.Up());
+            var projection = new BABYLON.Matrix.PerspectiveFovLH(Math.PI / 2.0, 1.0, activeCamera.minZ, activeCamera.maxZ);
+
+            this._transformMatrix = view.multiply(projection);
+        }
+
+        return this._transformMatrix;
+    };
+
+    BABYLON.ShadowGenerator.prototype.dispose = function() {
+        this._shadowMap.dispose();
+    };
+})();

+ 1 - 0
Babylon/Lights/babylon.directionalLight.js

@@ -4,6 +4,7 @@
     BABYLON.DirectionalLight = function (name, direction, scene) {
         this.name = name;
         this.id = name;
+        this.position = direction.scale(-1);
         this.direction = direction;
         this.diffuse = new BABYLON.Color3(1.0, 1.0, 1.0);
         this.specular = new BABYLON.Color3(1.0, 1.0, 1.0);

+ 4 - 0
Babylon/Lights/babylon.hemisphericLight.js

@@ -17,4 +17,8 @@
     };
     
     BABYLON.HemisphericLight.prototype = Object.create(BABYLON.Light.prototype);
+    
+    BABYLON.HemisphericLight.prototype.getShadowGenerator = function () {
+        return null;
+    };
 })();

+ 21 - 0
Babylon/Lights/babylon.light.js

@@ -14,4 +14,25 @@
     BABYLON.Light.prototype.intensity = 1.0;
     BABYLON.Light.prototype.isEnabled = true;
     
+    // Properties
+    BABYLON.Light.prototype.getScene = function () {
+        return this._scene;
+    };
+
+    BABYLON.Light.prototype.getShadowGenerator = function() {
+        return this._shadowGenerator;
+    };
+
+    // Methods
+    BABYLON.Light.prototype.dispose = function () {
+        if (this._shadowGenerator) {
+            this._shadowGenerator.dispose();
+            this._shadowGenerator = null;
+        }
+        
+        // Remove from scene
+        var index = this._scene.lights.indexOf(this);
+        this._scene.lights.splice(index, 1);
+    };
+
 })();

+ 4 - 0
Babylon/Lights/babylon.pointLight.js

@@ -16,4 +16,8 @@
     };
     
     BABYLON.PointLight.prototype = Object.create(BABYLON.Light.prototype);
+    
+    BABYLON.PointLight.prototype.getShadowGenerator = function () {
+        return null;
+    };
 })();

+ 45 - 36
Babylon/Materials/babylon.effect.js

@@ -9,8 +9,9 @@
         this._uniformsNames = uniformsNames.concat(samplers);
         this._samplers = samplers;
         this._isReady = false;
+        this._compilationError = "";
 
-        var that = this;       
+        var that = this;
 
         // Is in local store ?
         if (BABYLON.Effect.ShadersStore[baseName + "VertexShader"]) {
@@ -19,75 +20,83 @@
             var shaderUrl = BABYLON.Engine.ShadersRepository + baseName;
             // Vertex shader
             BABYLON.Tools.LoadFile(shaderUrl + ".vertex.fx",
-                function(vertexSourceCode) {
+                function (vertexSourceCode) {
                     // Fragment shader
                     BABYLON.Tools.LoadFile(shaderUrl + ".fragment.fx",
-                        function(fragmentSourceCode) {
+                        function (fragmentSourceCode) {
                             that._prepareEffect(vertexSourceCode, fragmentSourceCode, attributesNames, defines);
                         });
                 }
             );
         }
-        
+
         // Cache
         this._valueCache = [];
     };
-    
+
     // Properties
     BABYLON.Effect.prototype.isReady = function () {
         return this._isReady;
     };
-    
-    BABYLON.Effect.prototype.getProgram = function() {
+
+    BABYLON.Effect.prototype.getProgram = function () {
         return this._program;
     };
-    
+
     BABYLON.Effect.prototype.getAttribute = function (index) {
         return this._attributes[index];
     };
-    
+
     BABYLON.Effect.prototype.getAttributesCount = function () {
         return this._attributes.length;
     };
-    
+
     BABYLON.Effect.prototype.getUniformIndex = function (uniformName) {
         return this._uniformsNames.indexOf(uniformName);
     };
-    
+
     BABYLON.Effect.prototype.getUniform = function (uniformName) {
         return this._uniforms[this._uniformsNames.indexOf(uniformName)];
     };
-    
+
     BABYLON.Effect.prototype.getSamplers = function () {
         return this._samplers;
     };
     
+    BABYLON.Effect.prototype.getCompilationError = function () {
+        return this._compilationError;
+    };
+
     // Methods
     BABYLON.Effect.prototype._prepareEffect = function (vertexSourceCode, fragmentSourceCode, attributesNames, defines) {
-        var engine = this._engine;
-        this._program = engine.createShaderProgram(vertexSourceCode, fragmentSourceCode, defines);
+        try {
+            var engine = this._engine;
+            this._program = engine.createShaderProgram(vertexSourceCode, fragmentSourceCode, defines);
 
-        this._uniforms = engine.getUniforms(this._program, this._uniformsNames);
-        this._attributes = engine.getAttributes(this._program, attributesNames);
+            this._uniforms = engine.getUniforms(this._program, this._uniformsNames);
+            this._attributes = engine.getAttributes(this._program, attributesNames);
 
-        for (var index = 0; index < this._samplers.length; index++) {
-            var sampler = this.getUniform(this._samplers[index]);
+            for (var index = 0; index < this._samplers.length; index++) {
+                var sampler = this.getUniform(this._samplers[index]);
 
-            if (sampler == null) {
-                this._samplers.splice(index, 1);
-                index--;
+                if (sampler == null) {
+                    this._samplers.splice(index, 1);
+                    index--;
+                }
             }
-        }
 
-        engine.bindSamplers(this);
+            engine.bindSamplers(this);
 
-        this._isReady = true;
+            this._isReady = true;
+        } catch (e) {
+            this._compilationError = e.message;
+        }
     };
 
     BABYLON.Effect.prototype.setTexture = function (channel, texture) {
         this._engine.setTexture(this._samplers.indexOf(channel), texture);
     };
-        
+
     BABYLON.Effect.prototype.setMatrix = function (uniformName, matrix) {
         if (this._valueCache[uniformName] && this._valueCache[uniformName].equals(matrix))
             return;
@@ -95,7 +104,7 @@
         this._valueCache[uniformName] = matrix;
         this._engine.setMatrix(this.getUniform(uniformName), matrix);
     };
-    
+
     BABYLON.Effect.prototype.setBool = function (uniformName, bool) {
         if (this._valueCache[uniformName] && this._valueCache[uniformName] === bool)
             return;
@@ -104,7 +113,7 @@
 
         this._engine.setBool(this.getUniform(uniformName), bool);
     };
-    
+
     BABYLON.Effect.prototype.setVector2 = function (uniformName, x, y) {
         if (this._valueCache[uniformName] && this._valueCache[uniformName][0] == x && this._valueCache[uniformName][1] == y)
             return;
@@ -113,16 +122,16 @@
 
         this._engine.setVector2(this.getUniform(uniformName), x, y);
     };
-    
+
     BABYLON.Effect.prototype.setVector3 = function (uniformName, vector3) {
         if (this._valueCache[uniformName] && this._valueCache[uniformName][0] == vector3.x && this._valueCache[uniformName][1] == vector3.y && this._valueCache[uniformName][2] == vector3.z)
             return;
 
         this._valueCache[uniformName] = [vector3.x, vector3.y, vector3.z];
-        
+
         this._engine.setVector3(this.getUniform(uniformName), vector3);
     };
-    
+
     BABYLON.Effect.prototype.setFloat2 = function (uniformName, x, y) {
         if (this._valueCache[uniformName] && this._valueCache[uniformName][0] == x && this._valueCache[uniformName][1] == y)
             return;
@@ -130,7 +139,7 @@
         this._valueCache[uniformName] = [x, y];
         this._engine.setFloat2(this.getUniform(uniformName), x, y);
     };
-    
+
     BABYLON.Effect.prototype.setFloat3 = function (uniformName, x, y, z) {
         if (this._valueCache[uniformName] && this._valueCache[uniformName][0] == x && this._valueCache[uniformName][1] == y && this._valueCache[uniformName][2] == z)
             return;
@@ -138,7 +147,7 @@
         this._valueCache[uniformName] = [x, y, z];
         this._engine.setFloat3(this.getUniform(uniformName), x, y, z);
     };
-    
+
     BABYLON.Effect.prototype.setFloat4 = function (uniformName, x, y, z, w) {
         if (this._valueCache[uniformName] && this._valueCache[uniformName][0] == x && this._valueCache[uniformName][1] == y && this._valueCache[uniformName][2] == z && this._valueCache[uniformName][3] == w)
             return;
@@ -146,15 +155,15 @@
         this._valueCache[uniformName] = [x, y, z, w];
         this._engine.setFloat4(this.getUniform(uniformName), x, y, z, w);
     };
-    
+
     BABYLON.Effect.prototype.setColor3 = function (uniformName, color3) {
-        if (this._valueCache[uniformName]  && this._valueCache[uniformName][0] == color3.r && this._valueCache[uniformName][1] == color3.g && this._valueCache[uniformName][2] == color3.b)
+        if (this._valueCache[uniformName] && this._valueCache[uniformName][0] == color3.r && this._valueCache[uniformName][1] == color3.g && this._valueCache[uniformName][2] == color3.b)
             return;
 
         this._valueCache[uniformName] = [color3.r, color3.g, color3.b];
         this._engine.setColor3(this.getUniform(uniformName), color3);
     };
-    
+
     BABYLON.Effect.prototype.setColor4 = function (uniformName, color3, alpha) {
         if (this._valueCache[uniformName] && this._valueCache[uniformName][0] == color3.r && this._valueCache[uniformName][1] == color3.g && this._valueCache[uniformName][2] == color3.b && this._valueCache[uniformName][3] == alpha)
             return;
@@ -162,7 +171,7 @@
         this._valueCache[uniformName] = [color3.r, color3.g, color3.b, alpha];
         this._engine.setColor4(this.getUniform(uniformName), color3, alpha);
     };
-    
+
     // Statics
     BABYLON.Effect.ShadersStore = {};
 

+ 35 - 10
Babylon/Materials/babylon.standardMaterial.js

@@ -100,7 +100,7 @@
             defines.push("#define SPECULAR");
         }
         
-        if (this.bumpTexture && this._scene.getEngine().getCaps().standardDerivatives && !isIE()) {
+        if (this.bumpTexture && this._scene.getEngine().getCaps().standardDerivatives) {
             defines.push("#define BUMP");
         }
 
@@ -116,7 +116,8 @@
         if (this._scene.fogMode !== BABYLON.Scene.FOGMODE_NONE) {
             defines.push("#define FOG");
         }
-        
+
+        var shadowsActivated = false;
         var lightIndex = 0;
         for (var index = 0; index < this._scene.lights.length; index++) {
             var light = this._scene.lights[index];
@@ -132,7 +133,22 @@
             } else if (light instanceof BABYLON.HemisphericLight) {
                 defines.push("#define HEMILIGHT" + lightIndex);
             } else {
-                defines.push("#define POINTDIRLIGHT" + lightIndex);
+                defines.push("#define POINTDIRLIGHT" + lightIndex);               
+            }
+            
+            // Shadows
+            var shadowGenerator = light.getShadowGenerator();
+            if (mesh && mesh.receiveShadows && shadowGenerator && shadowGenerator.isReady()) {
+                defines.push("#define SHADOW" + lightIndex);
+
+                if (!shadowsActivated) {
+                    defines.push("#define SHADOWS");
+                    shadowsActivated = true;
+                }
+
+                if (shadowGenerator.useVarianceShadowMap) {
+                    defines.push("#define SHADOWVSM" + lightIndex);
+                }
             }
 
             lightIndex++;
@@ -169,14 +185,16 @@
             this._effect = this._scene.getEngine().createEffect(shaderName,
                 attribs,
             ["world", "view", "worldViewProjection", "vEyePosition", "vLightsType", "vAmbientColor", "vDiffuseColor", "vSpecularColor", "vEmissiveColor",
-                "vLightData0", "vLightDiffuse0", "vLightSpecular0", "vLightDirection0", "vLightGround0",
-                "vLightData1", "vLightDiffuse1", "vLightSpecular1", "vLightDirection1", "vLightGround1",
-                "vLightData2", "vLightDiffuse2", "vLightSpecular2", "vLightDirection2", "vLightGround2",
-                "vLightData3", "vLightDiffuse3", "vLightSpecular3", "vLightDirection3", "vLightGround3",
+                "vLightData0", "vLightDiffuse0", "vLightSpecular0", "vLightDirection0", "vLightGround0", "lightMatrix0",
+                "vLightData1", "vLightDiffuse1", "vLightSpecular1", "vLightDirection1", "vLightGround1", "lightMatrix1",
+                "vLightData2", "vLightDiffuse2", "vLightSpecular2", "vLightDirection2", "vLightGround2", "lightMatrix2",
+                "vLightData3", "vLightDiffuse3", "vLightSpecular3", "vLightDirection3", "vLightGround3", "lightMatrix3",
                 "vFogInfos", "vFogColor",
                  "vDiffuseInfos", "vAmbientInfos", "vOpacityInfos", "vReflectionInfos", "vEmissiveInfos", "vSpecularInfos", "vBumpInfos",
                  "vClipPlane", "diffuseMatrix", "ambientMatrix", "opacityMatrix", "reflectionMatrix", "emissiveMatrix", "specularMatrix", "bumpMatrix"],
-                ["diffuseSampler", "ambientSampler", "opacitySampler", "reflectionCubeSampler", "reflection2DSampler", "emissiveSampler", "specularSampler", "bumpSampler"],
+                ["diffuseSampler", "ambientSampler", "opacitySampler", "reflectionCubeSampler", "reflection2DSampler", "emissiveSampler", "specularSampler", "bumpSampler",
+                 "shadowSampler0", "shadowSampler1", "shadowSampler2", "shadowSampler3"
+                ],
                 join);
         }
         if (!this._effect.isReady()) {
@@ -254,7 +272,7 @@
             this._effect.setMatrix("specularMatrix", this.specularTexture._computeTextureMatrix());
         }
         
-        if (this.bumpTexture && this._scene.getEngine().getCaps().standardDerivatives && !isIE()) {
+        if (this.bumpTexture && this._scene.getEngine().getCaps().standardDerivatives) {
             this._effect.setTexture("bumpSampler", this.bumpTexture);
 
             this._effect.setVector2("vBumpInfos", this.bumpTexture.coordinatesIndex, this.bumpTexture.level);
@@ -282,7 +300,7 @@
                 this._effect.setFloat4("vLightData" + lightIndex, light.position.x, light.position.y, light.position.z, 0);
             } else if (light instanceof BABYLON.DirectionalLight) {
                 // Directional Light
-                this._effect.setFloat4("vLightData" + lightIndex, light.direction.x, light.direction.y, light.direction.z, 1);
+                this._effect.setFloat4("vLightData" + lightIndex, light.direction.x, light.direction.y, light.direction.z, 1);               
             } else if (light instanceof BABYLON.SpotLight) {
                 // Spot Light
                 this._effect.setFloat4("vLightData" + lightIndex, light.position.x, light.position.y, light.position.z, light.exponent);
@@ -296,6 +314,13 @@
             }
             this._effect.setColor3("vLightDiffuse" + lightIndex, light.diffuse.scale(light.intensity));
             this._effect.setColor3("vLightSpecular" + lightIndex, light.specular.scale(light.intensity));
+            
+            // Shadows
+            var shadowGenerator = light.getShadowGenerator();
+            if (mesh.receiveShadows && shadowGenerator && shadowGenerator.isReady()) {
+                this._effect.setMatrix("lightMatrix" + lightIndex, world.multiply(shadowGenerator.getTransformMatrix()));
+                this._effect.setTexture("shadowSampler" + lightIndex, shadowGenerator.getShadowMap());
+            }
 
             lightIndex++;
 

+ 3 - 0
Babylon/Materials/textures/babylon.mirrorTexture.js

@@ -8,6 +8,9 @@
         this.name = name;        
 
         this._texture = scene.getEngine().createRenderTargetTexture(size, generateMipMaps);
+        
+        // Render list
+        this.renderList = [];
     };
 
     BABYLON.MirrorTexture.prototype = Object.create(BABYLON.RenderTargetTexture.prototype);

+ 10 - 4
Babylon/Materials/textures/babylon.renderTargetTexture.js

@@ -8,12 +8,14 @@
         this.name = name;        
 
         this._texture = scene.getEngine().createRenderTargetTexture(size, generateMipMaps);
+        
+        // Render list
+        this.renderList = [];
     };
 
     BABYLON.RenderTargetTexture.prototype = Object.create(BABYLON.Texture.prototype);
 
-    // Members
-    BABYLON.RenderTargetTexture.prototype.renderList = [];
+    // Members    
     BABYLON.RenderTargetTexture.prototype.isRenderTarget = true;
     BABYLON.RenderTargetTexture.prototype.coordinatesMode = BABYLON.Texture.PROJECTION_MODE;
 
@@ -62,7 +64,7 @@
         for (var meshIndex = 0; meshIndex < this.renderList.length; meshIndex++) {
             var mesh = this.renderList[meshIndex];
 
-            if (mesh.material && mesh.isEnabled() && mesh.isVisible) {
+            if (mesh.isEnabled() && mesh.isVisible) {
                 for (var subIndex = 0; subIndex < mesh.subMeshes.length; subIndex++) {
                     var subMesh = mesh.subMeshes[subIndex];
                     var material = subMesh.getMaterial();
@@ -81,7 +83,11 @@
         }
         
         // Render
-        scene._localRender(this._opaqueSubMeshes, this._alphaTestSubMeshes, this._transparentSubMeshes, this.renderList);
+        if (this.customRenderFunction) {
+            this.customRenderFunction(this._opaqueSubMeshes, this._alphaTestSubMeshes, this._transparentSubMeshes, this.renderList);
+        } else {
+            scene._localRender(this._opaqueSubMeshes, this._alphaTestSubMeshes, this._transparentSubMeshes, this.renderList);
+        }
 
         // Unbind
         engine.unBindFramebuffer(this._texture);

+ 3 - 3
Babylon/Materials/textures/babylon.videoTexture.js

@@ -7,8 +7,8 @@
 
         this.name = name;
 
-        this.wrapU = BABYLON.Texture.REPEAT_CLAMPMODE;
-        this.wrapV = BABYLON.Texture.REPEAT_CLAMPMODE;
+        this.wrapU = BABYLON.Texture.WRAP_ADDRESSMODE;
+        this.wrapV = BABYLON.Texture.WRAP_ADDRESSMODE;
 
         this._texture = scene.getEngine().createDynamicTexture(size, generateMipMaps);
         var textureSize = this.getSize();
@@ -18,7 +18,7 @@
         this.video.height = textureSize.height;
         this.video.autoplay = true;
         this.video.loop = true;
-
+        
         var that = this;
         this.video.addEventListener("canplaythrough", function () {
             that._texture.isReady = true;

+ 23 - 16
Babylon/Mesh/babylon.mesh.js

@@ -58,6 +58,7 @@
     BABYLON.Mesh.prototype.visibility = 1.0;
     BABYLON.Mesh.prototype.billboardMode = BABYLON.Mesh.BILLBOARDMODE_NONE;
     BABYLON.Mesh.prototype.checkCollisions = false;
+    BABYLON.Mesh.prototype.receiveShadows = false;
 
     BABYLON.Mesh.prototype.onDispose = false;
 
@@ -294,13 +295,30 @@
         this._createGlobalSubMesh();
     };
 
+    BABYLON.Mesh.prototype.bindAndDraw = function (subMesh, effect, wireframe) {
+        var engine = this._scene.getEngine();
+        
+        // Wireframe
+        var indexToBind = this._indexBuffer;
+        var useTriangles = true;
+
+        if (wireframe) {
+            indexToBind = subMesh.getLinesIndexBuffer(this._indices, engine);
+            useTriangles = false;
+        }
+
+        // VBOs
+        engine.bindBuffers(this._vertexBuffer, indexToBind, this._vertexDeclaration, this._vertexStrideSize, effect);
+
+        // Draw order
+        engine.draw(useTriangles, useTriangles ? subMesh.indexStart : 0, useTriangles ? subMesh.indexCount : subMesh.linesIndexCount);
+    };
+
     BABYLON.Mesh.prototype.render = function (subMesh) {
         if (!this._vertexBuffer || !this._indexBuffer) {
             return;
         }
 
-        var engine = this._scene.getEngine();
-
         // World
         var world = this.getWorldMatrix();
 
@@ -314,20 +332,9 @@
         effectiveMaterial._preBind();
         effectiveMaterial.bind(world, this);
 
-        // Wireframe
-        var indexToBind = this._indexBuffer;
-        var useTriangles = true;
-
-        if (engine.forceWireframe || effectiveMaterial.wireframe) {
-            indexToBind = subMesh.getLinesIndexBuffer(this._indices, engine);
-            useTriangles = false;
-        }
-
-        // VBOs
-        engine.bindBuffers(this._vertexBuffer, indexToBind, this._vertexDeclaration, this._vertexStrideSize, effectiveMaterial.getEffect());
-
-        // Draw order
-        engine.draw(useTriangles, useTriangles ? subMesh.indexStart : 0, useTriangles ? subMesh.indexCount : subMesh.linesIndexCount);
+        // Bind and draw
+        var engine = this._scene.getEngine();
+        this.bindAndDraw(subMesh, effectiveMaterial.getEffect(), engine.forceWireframe || effectiveMaterial.wireframe);
 
         // Unbind
         effectiveMaterial.unbind();

+ 4 - 0
Babylon/Mesh/babylon.subMesh.js

@@ -18,6 +18,10 @@
     BABYLON.SubMesh.prototype.getBoundingInfo = function() {
         return this._boundingInfo;
     };
+    
+    BABYLON.SubMesh.prototype.getMesh = function () {
+        return this._mesh;
+    };
 
     BABYLON.SubMesh.prototype.getMaterial = function () {
         var rootMaterial = this._mesh.material;

+ 1 - 5
Babylon/Particles/babylon.particleSystem.js

@@ -43,7 +43,6 @@
         this.color1 = new BABYLON.Color4(1.0, 1.0, 1.0, 1.0);
         this.color2 = new BABYLON.Color4(1.0, 1.0, 1.0, 1.0);
         this.colorDead = new BABYLON.Color4(0, 0, 0, 1.0);
-        this.deadAlpha = 0;
         this.textureMask = new BABYLON.Color4(1.0, 1.0, 1.0, 1.0);
 
         // Particles
@@ -176,12 +175,9 @@
             var step = randomNumber(0, 1.0);
 
             var startColor = BABYLON.Color4.Lerp(this.color1, this.color2, step);
-            var deadColor = this.colorDead;
-            startColor.a = 1.0;
-            deadColor.a = this.deadAlpha;
 
             particle.color = startColor;
-            var diff = deadColor.subtract(startColor);
+            var diff = this.colorDead.subtract(startColor);
             particle.colorStep = diff.scale(1.0 / particle.lifeTime);
         }
     };

+ 126 - 9
Babylon/Shaders/default.fragment.fx

@@ -11,7 +11,6 @@ uniform vec4 vDiffuseColor;
 uniform vec4 vSpecularColor;
 uniform vec3 vEmissiveColor;
 
-
 // Input
 varying vec3 vPositionW;
 varying vec3 vNormalW;
@@ -21,6 +20,10 @@ varying vec3 vNormalW;
 uniform vec4 vLightData0;
 uniform vec3 vLightDiffuse0;
 uniform vec3 vLightSpecular0;
+#ifdef SHADOW0
+varying vec4 vPositionFromLight0;
+uniform sampler2D shadowSampler0;
+#endif
 #ifdef SPOTLIGHT0
 uniform vec4 vLightDirection0;
 #endif
@@ -33,6 +36,10 @@ uniform vec3 vLightGround0;
 uniform vec4 vLightData1;
 uniform vec3 vLightDiffuse1;
 uniform vec3 vLightSpecular1;
+#ifdef SHADOW1
+varying vec4 vPositionFromLight1;
+uniform sampler2D shadowSampler1;
+#endif
 #ifdef SPOTLIGHT1
 uniform vec4 vLightDirection1;
 #endif
@@ -45,6 +52,10 @@ uniform vec3 vLightGround1;
 uniform vec4 vLightData2;
 uniform vec3 vLightDiffuse2;
 uniform vec3 vLightSpecular2;
+#ifdef SHADOW2
+varying vec4 vPositionFromLight2;
+uniform sampler2D shadowSampler2;
+#endif
 #ifdef SPOTLIGHT2
 uniform vec4 vLightDirection2;
 #endif
@@ -57,6 +68,10 @@ uniform vec3 vLightGround2;
 uniform vec4 vLightData3;
 uniform vec3 vLightDiffuse3;
 uniform vec3 vLightSpecular3;
+#ifdef SHADOW3
+varying vec4 vPositionFromLight3;
+uniform sampler2D shadowSampler3;
+#endif
 #ifdef SPOTLIGHT3
 uniform vec4 vLightDirection3;
 #endif
@@ -103,6 +118,71 @@ uniform vec2 vSpecularInfos;
 uniform sampler2D specularSampler;
 #endif
 
+// Shadows
+#ifdef SHADOWS
+
+float unpack(vec4 color)
+{
+	const vec4 bitShift = vec4(1. / (255. * 255. * 255.), 1. / (255. * 255.), 1. / 255., 1.);
+	return dot(color, bitShift);
+}
+
+float unpackHalf(vec2 color) 
+{ 
+	return color.x + (color.y / 255.0);
+}
+
+float computeShadow(vec4 vPositionFromLight, sampler2D shadowSampler)
+{
+	vec3 depth = vPositionFromLight.xyz / vPositionFromLight.w;
+	vec2 uv = 0.5 * depth.xy + vec2(0.5, 0.5);
+
+	if (uv.x < 0. || uv.x > 1.0 || uv.y < 0. || uv.y > 1.0)
+	{
+		return 1.0;
+	}
+
+	float shadow = unpack(texture2D(shadowSampler, uv));
+
+	if (depth.z > shadow)
+	{
+		return 0.;
+	}
+	return 1.;
+}
+
+// Thanks to http://devmaster.net/
+float ChebychevInequality(vec2 moments, float t) 
+{
+	if (t <= moments.x)
+	{
+		return 1.0;
+	}
+	
+	float variance = moments.y - (moments.x * moments.x); 
+	variance = max(variance, 0.);
+
+	float d = t - moments.x; 	
+	return variance / (variance + d * d); 
+}
+
+float computeShadowWithVSM(vec4 vPositionFromLight, sampler2D shadowSampler)
+{
+	vec3 depth = vPositionFromLight.xyz / vPositionFromLight.w;
+	vec2 uv = 0.5 * depth.xy + vec2(0.5, 0.5);
+
+	if (uv.x < 0. || uv.x > 1.0 || uv.y < 0. || uv.y > 1.0)
+	{
+		return 1.0;
+	}
+
+	vec4 texel = texture2D(shadowSampler, uv);
+
+	vec2 moments = vec2(unpackHalf(texel.xy), unpackHalf(texel.zw));
+	return clamp(1.3 - ChebychevInequality(moments, depth.z), 0., 1.0);
+}
+#endif
+
 // Bump
 #ifdef BUMP
 #extension GL_OES_standard_derivatives : enable
@@ -306,6 +386,7 @@ void main(void) {
 	// Lighting
 	vec3 diffuseBase = vec3(0., 0., 0.);
 	vec3 specularBase = vec3(0., 0., 0.);
+	float shadow = 1.;
 
 #ifdef LIGHT0
 #ifdef SPOTLIGHT0
@@ -317,8 +398,17 @@ void main(void) {
 #ifdef POINTDIRLIGHT0
 	lightingInfo info = computeLighting(viewDirectionW, normalW, vLightData0, vLightDiffuse0, vLightSpecular0);
 #endif
-	diffuseBase += info.diffuse;
-	specularBase += info.specular;
+#ifdef SHADOW0
+	#ifdef SHADOWVSM0
+		shadow = computeShadowWithVSM(vPositionFromLight0, shadowSampler0);
+	#else
+		shadow = computeShadow(vPositionFromLight0, shadowSampler0);
+	#endif
+#else
+	shadow = 1.;
+#endif
+	diffuseBase += info.diffuse * shadow;
+	specularBase += info.specular * shadow;
 #endif
 
 #ifdef LIGHT1
@@ -331,8 +421,17 @@ void main(void) {
 #ifdef POINTDIRLIGHT1
 	info = computeLighting(viewDirectionW, normalW, vLightData1, vLightDiffuse1, vLightSpecular1);
 #endif
-	diffuseBase += info.diffuse;
-	specularBase += info.specular;
+#ifdef SHADOW1
+	#ifdef SHADOWVSM1
+		shadow = computeShadowWithVSM(vPositionFromLight1, shadowSampler1);
+	#else
+		shadow = computeShadow(vPositionFromLight1, shadowSampler1);
+	#endif
+#else
+	shadow = 1.;
+#endif
+	diffuseBase += info.diffuse * shadow;
+	specularBase += info.specular * shadow;
 #endif
 
 #ifdef LIGHT2
@@ -345,8 +444,17 @@ void main(void) {
 #ifdef POINTDIRLIGHT2
 	info = computeLighting(viewDirectionW, normalW, vLightData2, vLightDiffuse2, vLightSpecular2);
 #endif
-	diffuseBase += info.diffuse;
-	specularBase += info.specular;
+#ifdef SHADOW2
+	#ifdef SHADOWVSM2
+		shadow = computeShadowWithVSM(vPositionFromLight2, shadowSampler2);
+	#else
+		shadow = computeShadow(vPositionFromLight2, shadowSampler2);
+	#endif	
+#else
+	shadow = 1.;
+#endif
+	diffuseBase += info.diffuse * shadow;
+	specularBase += info.specular * shadow;
 #endif
 
 #ifdef LIGHT3
@@ -359,8 +467,17 @@ void main(void) {
 #ifdef POINTDIRLIGHT3
 	info = computeLighting(viewDirectionW, normalW, vLightData3, vLightDiffuse3, vLightSpecular3);
 #endif
-	diffuseBase += info.diffuse;
-	specularBase += info.specular;
+#ifdef SHADOW3
+	#ifdef SHADOWVSM3
+		shadow = computeShadowWithVSM(vPositionFromLight3, shadowSampler3);
+	#else
+		shadow = computeShadow(vPositionFromLight3, shadowSampler3);
+	#endif	
+#else
+	shadow = 1.;
+#endif
+	diffuseBase += info.diffuse * shadow;
+	specularBase += info.specular * shadow;
 #endif
 
 	// Reflection

+ 40 - 1
Babylon/Shaders/default.vertex.fx

@@ -1,4 +1,8 @@
-#define MAP_EXPLICIT	0.
+#ifdef GL_ES
+precision mediump float;
+#endif
+
+#define MAP_EXPLICIT	0.
 #define MAP_SPHERICAL	1.
 #define MAP_PLANAR		2.
 #define MAP_CUBIC		3.
@@ -76,6 +80,25 @@ varying float fClipDistance;
 varying float fFogDistance;
 #endif
 
+#ifdef SHADOWS
+#ifdef LIGHT0
+uniform mat4 lightMatrix0;
+varying vec4 vPositionFromLight0;
+#endif
+#ifdef LIGHT1
+uniform mat4 lightMatrix1;
+varying vec4 vPositionFromLight1;
+#endif
+#ifdef LIGHT2
+uniform mat4 lightMatrix2;
+varying vec4 vPositionFromLight2;
+#endif
+#ifdef LIGHT3
+uniform mat4 lightMatrix3;
+varying vec4 vPositionFromLight3;
+#endif
+#endif
+
 #ifdef REFLECTION
 vec3 computeReflectionCoords(float mode, vec4 worldPos, vec3 worldNormal)
 {	
@@ -206,4 +229,20 @@ void main(void) {
 #ifdef FOG
 		fFogDistance = (view * worldPos).z;
 #endif
+
+	// Shadows
+#ifdef SHADOWS
+#ifdef LIGHT0
+		vPositionFromLight0 = lightMatrix0 * vec4(position, 1.0);
+#endif
+#ifdef LIGHT1
+		vPositionFromLight1 = lightMatrix1 * vec4(position, 1.0);
+#endif
+#ifdef LIGHT2
+		vPositionFromLight2 = lightMatrix2 * vec4(position, 1.0);
+#endif
+#ifdef LIGHT3
+		vPositionFromLight3 = lightMatrix3 * vec4(position, 1.0);
+#endif
+#endif
 }

+ 59 - 2
Babylon/Shaders/iedefault.fragment.fx

@@ -16,6 +16,10 @@ uniform vec3 vEmissiveColor;
 uniform vec4 vLightData0;
 uniform vec3 vLightDiffuse0;
 uniform vec3 vLightSpecular0;
+#ifdef SHADOW0
+varying vec4 vPositionFromLight0;
+uniform sampler2D shadowSampler0;
+#endif
 #endif
 
 //#ifdef LIGHT1
@@ -76,6 +80,37 @@ varying vec3 vNormalW;
 varying float fClipDistance;
 #endif
 
+// Shadows
+#ifdef SHADOWS
+
+float unpack(vec4 color)
+{
+	const vec4 bitShift = vec4(1. / (255. * 255. * 255.), 1. / (255. * 255.), 1. / 255., 1.);
+	return dot(color, bitShift);
+}
+
+float unpackHalf(vec2 color)
+{
+	return color.x + (color.y / 255.0);
+}
+
+// Thanks to http://devmaster.net/
+float ChebychevInequality(vec2 moments, float t)
+{
+	if (t <= moments.x)
+	{
+		return 1.0;
+	}
+
+	float variance = moments.y - (moments.x * moments.x);
+	variance = max(variance, 0);
+
+	float d = t - moments.x;
+	return variance / (variance + d * d);
+}
+
+#endif
+
 // Fog
 #ifdef FOG
 
@@ -187,10 +222,32 @@ void main(void) {
 	// Lighting
 	vec3 diffuseBase = vec3(0., 0., 0.);
 	vec3 specularBase = vec3(0., 0., 0.);
+	float shadow = 1.0;
 
 #ifdef LIGHT0
-	diffuseBase += computeDiffuseLighting(normalW, vLightData0, vLightDiffuse0);
-	specularBase += computeSpecularLighting(viewDirectionW, normalW, vLightData0, vLightSpecular0);
+	#ifdef SHADOW0
+		vec3 depth = vPositionFromLight0.xyz / vPositionFromLight0.w;
+		vec2 uv = 0.5 * depth.xy + vec2(0.5, 0.5);
+	
+		if (uv.x >= 0. && uv.x <= 1.0 && uv.y >= 0. && uv.y <= 1.0)
+		{
+		#ifdef SHADOWVSM0
+			vec4 texel = texture2D(shadowSampler0, uv);
+
+			vec2 moments = vec2(unpackHalf(texel.xy), unpackHalf(texel.zw));
+			shadow = clamp(1.3 - ChebychevInequality(moments, depth.z), 0., 1.0);
+		#else
+			float shadowDepth = unpack(texture2D(shadowSampler0, uv));
+
+			if (depth.z > shadowDepth)
+			{
+				shadow = 0.;
+			}
+		#endif
+		}
+	#endif
+	diffuseBase += computeDiffuseLighting(normalW, vLightData0, vLightDiffuse0) * shadow;
+	specularBase += computeSpecularLighting(viewDirectionW, normalW, vLightData0, vLightSpecular0) * shadow;
 #endif
 //#ifdef LIGHT1
 //	diffuseBase += computeDiffuseLighting(normalW, vLightData1, vLightDiffuse1);

+ 19 - 1
Babylon/Shaders/iedefault.vertex.fx

@@ -1,4 +1,8 @@
-#define MAP_EXPLICIT	0.
+#ifdef GL_ES
+precision mediump float;
+#endif
+
+#define MAP_EXPLICIT	0.
 #define MAP_SPHERICAL	1.
 #define MAP_PLANAR		2.
 #define MAP_CUBIC		3.
@@ -71,6 +75,13 @@ varying float fClipDistance;
 varying float fFogDistance;
 #endif
 
+#ifdef SHADOWS
+#ifdef LIGHT0
+uniform mat4 lightMatrix0;
+varying vec4 vPositionFromLight0;
+#endif
+#endif
+
 #ifdef REFLECTION
 vec3 computeReflectionCoords(float mode, vec4 worldPos, vec3 worldNormal)
 {
@@ -190,4 +201,11 @@ void main(void) {
 #ifdef FOG
 	fFogDistance = (view * worldPos).z;
 #endif
+
+	// Shadows
+#ifdef SHADOWS
+#ifdef LIGHT0
+	vPositionFromLight0 = lightMatrix0 * vec4(position, 1.0);
+#endif
+#endif
 }

+ 5 - 1
Babylon/Shaders/layer.vertex.fx

@@ -1,4 +1,8 @@
-// Attributes
+#ifdef GL_ES
+precision mediump float;
+#endif
+
+// Attributes
 attribute vec2 position;
 
 // Uniforms

+ 5 - 1
Babylon/Shaders/particles.vertex.fx

@@ -1,4 +1,8 @@
-// Attributes
+#ifdef GL_ES
+precision mediump float;
+#endif
+
+// Attributes
 attribute vec3 position;
 attribute vec4 color;
 attribute vec4 options;

+ 35 - 0
Babylon/Shaders/shadowMap.fragment.fx

@@ -0,0 +1,35 @@
+#ifdef GL_ES
+precision mediump float;
+#endif
+
+vec4 pack(float depth)
+{
+	const vec4 bitOffset = vec4(255. * 255. * 255., 255. * 255., 255., 1.);
+	const vec4 bitMask = vec4(0., 1. / 255., 1. / 255., 1. / 255.);
+	
+	vec4 comp = fract(depth * bitOffset);
+	comp -= comp.xxyz * bitMask;
+	
+	return comp;
+}
+
+// Thanks to http://devmaster.net/
+vec2 packHalf(float depth) 
+{ 
+	const vec2 bitOffset = vec2(1.0 / 255., 0.);
+	vec2 color = vec2(depth, fract(depth * 255.));
+
+	return color - (color.yy * bitOffset);
+}
+
+
+void main(void)
+{
+#ifdef VSM
+	float moment1 = gl_FragCoord.z / gl_FragCoord.w; 
+	float moment2 = moment1 * moment1;
+	gl_FragColor = vec4(packHalf(moment1), packHalf(moment2));
+#else
+	gl_FragColor = pack(gl_FragCoord.z / gl_FragCoord.w);
+#endif
+}

+ 14 - 0
Babylon/Shaders/shadowMap.vertex.fx

@@ -0,0 +1,14 @@
+#ifdef GL_ES
+precision mediump float;
+#endif
+
+// Attribute
+attribute vec3 position;
+
+// Uniform
+uniform mat4 worldViewProjection;
+
+void main(void)
+{
+	gl_Position = worldViewProjection * vec4(position, 1.0);
+}

+ 5 - 1
Babylon/Shaders/sprites.vertex.fx

@@ -1,4 +1,8 @@
-// Attributes
+#ifdef GL_ES
+precision mediump float;
+#endif
+
+// Attributes
 attribute vec3 position;
 attribute vec4 options;
 attribute vec4 cellInfo;

+ 31 - 5
Babylon/Tools/babylon.sceneLoader.js

@@ -161,7 +161,6 @@
         particleSystem.color1 = BABYLON.Color4.FromArray(parsedParticleSystem.color1);
         particleSystem.color2 = BABYLON.Color4.FromArray(parsedParticleSystem.color2);
         particleSystem.colorDead = BABYLON.Color4.FromArray(parsedParticleSystem.colorDead);
-        particleSystem.deadAlpha = parsedParticleSystem.deadAlpha;
         particleSystem.updateSpeed = parsedParticleSystem.updateSpeed;
         particleSystem.targetStopDuration = parsedParticleSystem.targetStopFrame;
         particleSystem.textureMask = BABYLON.Color4.FromArray(parsedParticleSystem.textureMask);
@@ -170,6 +169,21 @@
 
         return particleSystem;
     };
+    
+    var parseShadowGenerator = function (parsedShadowGenerator, scene) {
+        var light = scene.getLightByID(parsedShadowGenerator.lightId);
+        var shadowGenerator = new BABYLON.ShadowGenerator(parsedShadowGenerator.mapSize, light);
+
+        for (var meshIndex = 0; meshIndex < parsedShadowGenerator.renderList.length; meshIndex++) {
+            var mesh = scene.getMeshByID(parsedShadowGenerator.renderList[meshIndex]);
+
+            shadowGenerator.getShadowMap().renderList.push(mesh);
+        }
+
+        shadowGenerator.useVarianceShadowMap = parsedShadowGenerator.useVarianceShadowMap;
+
+        return shadowGenerator;
+    };
 
     var parseAnimation = function (parsedAnimation) {
         var animation = new BABYLON.Animation(parsedAnimation.name, parsedAnimation.property, parsedAnimation.framePerSecond, parsedAnimation.dataType, parsedAnimation.loopBehavior);
@@ -210,16 +224,17 @@
 
         switch (parsedLight.type) {
             case 0:
-                light = new BABYLON.PointLight(parsedLight.name, BABYLON.Vector3.FromArray(parsedLight.data), scene);
+                light = new BABYLON.PointLight(parsedLight.name, BABYLON.Vector3.FromArray(parsedLight.position), scene);
                 break;
             case 1:
-                light = new BABYLON.DirectionalLight(parsedLight.name, BABYLON.Vector3.FromArray(parsedLight.data), scene);
+                light = new BABYLON.DirectionalLight(parsedLight.name, BABYLON.Vector3.FromArray(parsedLight.direction), scene);
+                light.position = BABYLON.Vector3.FromArray(parsedLight.position);
                 break;
             case 2:
-                light = new BABYLON.SpotLight(parsedLight.name, BABYLON.Vector3.FromArray(parsedLight.data), BABYLON.Vector3.FromArray(parsedLight.direction), parsedLight.angle, parsedLight.exponent, scene);
+                light = new BABYLON.SpotLight(parsedLight.name, BABYLON.Vector3.FromArray(parsedLight.position), BABYLON.Vector3.FromArray(parsedLight.direction), parsedLight.angle, parsedLight.exponent, scene);
                 break;
             case 3:
-                light = new BABYLON.HemisphericLight(parsedLight.name, BABYLON.Vector3.FromArray(parsedLight.data), scene);
+                light = new BABYLON.HemisphericLight(parsedLight.name, BABYLON.Vector3.FromArray(parsedLight.direction), scene);
                 light.groundColor = BABYLON.Color3.FromArray(parsedLight.groundColor);
                 break;
         }
@@ -258,6 +273,8 @@
         mesh.setEnabled(parsedMesh.isEnabled);
         mesh.isVisible = parsedMesh.isVisible;
 
+        mesh.receiveShadows = parsedMesh.receiveShadows;
+
         mesh.billboardMode = parsedMesh.billboardMode;
 
         if (parsedMesh.visibility !== undefined) {
@@ -463,6 +480,15 @@
                         parseParticleSystem(parsedParticleSystem, scene, rootUrl);
                     }
                 }
+                
+                // Shadows
+                if (parsedData.shadowGenerators) {
+                    for (var index = 0; index < parsedData.shadowGenerators.length; index++) {
+                        var parsedShadowGenerator = parsedData.shadowGenerators[index];
+
+                        parseShadowGenerator(parsedShadowGenerator, scene);
+                    }
+                }
 
                 // Finish
                 if (then) {

+ 12 - 0
Babylon/Tools/babylon.tools.js

@@ -2,6 +2,18 @@
 
 (function () {
     BABYLON.Tools = {};
+
+    BABYLON.Tools.GetPointerPrefix = function() {
+        var eventPrefix = "pointer";
+
+        // Check if hand.js is referenced or if the browser natively supports pointer events
+        if (!navigator.pointerEnabled) {
+            eventPrefix = "mouse";
+        }
+
+        return eventPrefix;
+    };
+
     BABYLON.Tools.QueueNewFrame = function (func) {
         if (window.requestAnimationFrame)
             window.requestAnimationFrame(func);

+ 31 - 11
Babylon/babylon.engine.js

@@ -39,7 +39,7 @@
 
         // Extensions
         var derivatives = this._gl.getExtension('OES_standard_derivatives');
-        this._caps.standardDerivatives = (derivatives !== undefined);
+        this._caps.standardDerivatives = (derivatives !== null);
 
         // Cache
         this._loadedTexturesCache = [];
@@ -99,7 +99,7 @@
         this._hardwareScalingLevel = level;
         this.resize();
     };
-    
+
     BABYLON.Engine.prototype.getHardwareScalingLevel = function () {
         return this._hardwareScalingLevel;
     };
@@ -383,14 +383,14 @@
 
         this._gl.uniform3f(uniform, vector3.x, vector3.y, vector3.z);
     };
-    
+
     BABYLON.Engine.prototype.setFloat2 = function (uniform, x, y) {
         if (!uniform)
             return;
 
         this._gl.uniform2f(uniform, x, y);
     };
-    
+
     BABYLON.Engine.prototype.setFloat3 = function (uniform, x, y, z) {
         if (!uniform)
             return;
@@ -559,16 +559,16 @@
         return texture;
     };
 
-    BABYLON.Engine.prototype.createDynamicTexture = function (size, noMipmap) {
+    BABYLON.Engine.prototype.createDynamicTexture = function (size, generateMipMaps) {
         var texture = this._gl.createTexture();
 
         var width = getExponantOfTwo(size, this._caps.maxTextureSize);
-        var height = getExponantOfTwo(size, this._caps.maxTextureSize);
+        var height = width;
 
         this._gl.bindTexture(this._gl.TEXTURE_2D, texture);
         this._gl.texParameteri(this._gl.TEXTURE_2D, this._gl.TEXTURE_MAG_FILTER, this._gl.LINEAR);
 
-        if (noMipmap) {
+        if (!generateMipMaps) {
             this._gl.texParameteri(this._gl.TEXTURE_2D, this._gl.TEXTURE_MIN_FILTER, this._gl.LINEAR);
         } else {
             this._gl.texParameteri(this._gl.TEXTURE_2D, this._gl.TEXTURE_MIN_FILTER, this._gl.LINEAR_MIPMAP_LINEAR);
@@ -581,7 +581,7 @@
         texture._width = width;
         texture._height = height;
         texture.isReady = false;
-        texture.noMipmap = noMipmap;
+        texture.generateMipMaps = generateMipMaps;
         texture.references = 1;
 
         this._loadedTexturesCache.push(texture);
@@ -593,7 +593,7 @@
         this._gl.bindTexture(this._gl.TEXTURE_2D, texture);
         this._gl.pixelStorei(this._gl.UNPACK_FLIP_Y_WEBGL, true);
         this._gl.texImage2D(this._gl.TEXTURE_2D, 0, this._gl.RGBA, this._gl.RGBA, this._gl.UNSIGNED_BYTE, canvas);
-        if (!texture.noMipmap) {
+        if (texture.generateMipMaps) {
             this._gl.generateMipmap(this._gl.TEXTURE_2D);
         }
         this._gl.bindTexture(this._gl.TEXTURE_2D, null);
@@ -604,10 +604,27 @@
     BABYLON.Engine.prototype.updateVideoTexture = function (texture, video) {
         this._gl.bindTexture(this._gl.TEXTURE_2D, texture);
         this._gl.pixelStorei(this._gl.UNPACK_FLIP_Y_WEBGL, false);
-        this._gl.texImage2D(this._gl.TEXTURE_2D, 0, this._gl.RGBA, this._gl.RGBA, this._gl.UNSIGNED_BYTE, video);
-        if (!texture.noMipmap) {
+
+        // Scale the video if it is a NPOT
+        if (video.videoWidth !== texture._width || video.videoHeight !== texture._height) {
+            if (!texture._workingCanvas) {
+                texture._workingCanvas = document.createElement("canvas");
+                texture._workingContext = texture._workingCanvas.getContext("2d");
+                texture._workingCanvas.width = texture._width;
+                texture._workingCanvas.height = texture._height;
+            }
+
+            texture._workingContext.drawImage(video, 0, 0, video.videoWidth, video.videoHeight, 0, 0, texture._width, texture._height);
+
+            this._gl.texImage2D(this._gl.TEXTURE_2D, 0, this._gl.RGBA, this._gl.RGBA, this._gl.UNSIGNED_BYTE, texture._workingCanvas);
+        } else {
+            this._gl.texImage2D(this._gl.TEXTURE_2D, 0, this._gl.RGBA, this._gl.RGBA, this._gl.UNSIGNED_BYTE, video);
+        }
+        
+        if (texture.generateMipMaps) {
             this._gl.generateMipmap(this._gl.TEXTURE_2D);
         }
+        
         this._gl.bindTexture(this._gl.TEXTURE_2D, null);
         this._activeTexturesCache = [];
         texture.isReady = true;
@@ -759,6 +776,9 @@
     };
 
     BABYLON.Engine.prototype.setTexture = function (channel, texture) {
+        if (channel < 0) {
+            return;
+        }
         if (!texture || !texture.isReady()) {
             if (this._activeTexturesCache[channel] != null) {
                 this._gl.activeTexture(this._gl["TEXTURE" + channel]);

+ 25 - 0
Babylon/babylon.scene.js

@@ -255,6 +255,16 @@
 
         return null;
     };
+    
+    BABYLON.Scene.prototype.getLightByID = function (id) {
+        for (var index = 0; index < this.lights.length; index++) {
+            if (this.lights[index].id == id) {
+                return this.lights[index];
+            }
+        }
+
+        return null;
+    };
 
     BABYLON.Scene.prototype.getMeshByID = function (id) {
         for (var index = 0; index < this.meshes.length; index++) {
@@ -454,6 +464,16 @@
         this._evaluateActiveMeshes();
         this._evaluateActiveMeshesDuration = new Date() - beforeEvaluateActiveMeshesDate;
 
+        // Shadows
+        for (var lightIndex = 0; lightIndex < this.lights.length; lightIndex++) {
+            var light = this.lights[lightIndex];
+            var shadowGenerator = light.getShadowGenerator();
+
+            if (light.isEnabled && shadowGenerator && shadowGenerator.isReady()) {
+                this._renderTargets.push(shadowGenerator.getShadowMap());
+            }
+        }
+        
         // Render targets
         var beforeRenderTargetDate = new Date();
         for (var renderIndex = 0; renderIndex < this._renderTargets.length; renderIndex++) {
@@ -530,6 +550,11 @@
         for (index = 0; index < this.cameras.length; index++) {
             this.cameras[index].detachControl(canvas);
         }
+        
+        // Release lights
+        while (this.lights.length) {
+            this.lights[0].dispose(true);
+        }
 
         // Release meshes
         while (this.meshes.length) {

+ 159 - 17
Exporters/Blender/io_export_babylon.py

@@ -78,11 +78,16 @@ class Export_babylon(bpy.types.Operator, ExportHelper):
 			file_handler.write(",")
 		file_handler.write("\""+name+"\":" + str(int))
 		
-	def write_bool(file_handler, name, bool):	
+	def write_bool(file_handler, name, bool, noComma=False):	
+		if noComma == False:
+			file_handler.write(",")	
 		if bool:
-			file_handler.write(",\""+name+"\":" + "true")
+			file_handler.write("\""+name+"\":" + "true")
 		else:
-			file_handler.write(",\""+name+"\":" + "false")
+			file_handler.write("\""+name+"\":" + "false")
+			
+	def getDirection(matrix):
+		return (matrix.to_3x3() * mathutils.Vector((0.0, 0.0, -1.0))).normalized()
 			
 	def export_camera(object, scene, file_handler):		
 		invWorld = object.matrix_world.copy()
@@ -114,17 +119,14 @@ class Export_babylon(bpy.types.Operator, ExportHelper):
 		Export_babylon.write_string(file_handler, "id", object.name)		
 		Export_babylon.write_float(file_handler, "type", light_type)
 		if light_type == 0:
-			Export_babylon.write_vector(file_handler, "data", object.location)
+			Export_babylon.write_vector(file_handler, "position", object.location)
 		elif light_type == 1:
-			matrix_world = object.matrix_world.copy()
-			matrix_world.translation = mathutils.Vector((0, 0, 0))
-			direction = mathutils.Vector((0, 0, -1)) * matrix_world
-			Export_babylon.write_vector(file_handler, "data", direction)
+			direction = Export_babylon.getDirection(object.matrix_world)
+			Export_babylon.write_vector(file_handler, "position", object.location)
+			Export_babylon.write_vector(file_handler, "direction", direction)
 		elif light_type == 2:
-			Export_babylon.write_vector(file_handler, "data", object.location)
-			matrix_world = object.matrix_world.copy()
-			matrix_world.translation = mathutils.Vector((0, 0, 0))
-			direction = mathutils.Vector((0, 0, -1)) * matrix_world
+			Export_babylon.write_vector(file_handler, "position", object.location)
+			direction = Export_babylon.getDirection(object.matrix_world)
 			Export_babylon.write_vector(file_handler, "direction", direction)
 			Export_babylon.write_float(file_handler, "angle", object.data.spot_size)
 			Export_babylon.write_float(file_handler, "exponent", object.data.spot_blend * 2)
@@ -132,7 +134,7 @@ class Export_babylon(bpy.types.Operator, ExportHelper):
 			matrix_world = object.matrix_world.copy()
 			matrix_world.translation = mathutils.Vector((0, 0, 0))
 			direction = mathutils.Vector((0, 0, -1)) * matrix_world
-			Export_babylon.write_vector(file_handler, "data", -direction)
+			Export_babylon.write_vector(file_handler, "direction", -direction)
 			Export_babylon.write_color(file_handler, "groundColor", mathutils.Color((0, 0, 0)))
 			
 		Export_babylon.write_float(file_handler, "intensity", object.data.energy)
@@ -248,7 +250,53 @@ class Export_babylon(bpy.types.Operator, ExportHelper):
 			first = False
 		file_handler.write("]")
 		file_handler.write("}")
-	
+
+	def export_animation(object, scene, file_handler, typeBl, typeBa, coma):
+		if coma == True:
+			file_handler.write(",")
+		
+		file_handler.write("{")
+		Export_babylon.write_int(file_handler, "dataType", 1, True)
+		Export_babylon.write_int(file_handler, "framePerSecond", 30)
+		Export_babylon.write_int(file_handler, "loopBehavior", 1)
+		Export_babylon.write_string(file_handler, "name", typeBa+" animation")
+		Export_babylon.write_string(file_handler, "property", typeBa)
+		
+		file_handler.write(",\"keys\":[")
+			
+		frames = dict() 
+		for fcurve in object.animation_data.action.fcurves:
+			if fcurve.data_path == typeBl:
+				for key in fcurve.keyframe_points: 
+					frame = key.co.x 
+					frames[frame] = 1
+			
+		#for each frame (next step ==> set for key frames)
+		i = 0
+		for Frame in sorted(frames):
+			if i == 0 and Frame != 0.0:
+				file_handler.write("{")
+				Export_babylon.write_int(file_handler, "frame", 0, True)
+				bpy.context.scene.frame_set(int(Frame + bpy.context.scene.frame_start))
+				Export_babylon.write_vector(file_handler, "values", getattr(object,typeBl))
+				file_handler.write("},")
+			i = i + 1
+			file_handler.write("{")
+			Export_babylon.write_int(file_handler, "frame", Frame, True)
+			bpy.context.scene.frame_set(int(Frame + bpy.context.scene.frame_start))
+			Export_babylon.write_vector(file_handler, "values", getattr(object,typeBl))
+			file_handler.write("}")
+			if i != len(frames):
+				file_handler.write(",")
+			else:
+				file_handler.write(",{")
+				Export_babylon.write_int(file_handler, "frame", bpy.context.scene.frame_end - bpy.context.scene.frame_start + 1, True)
+				bpy.context.scene.frame_set(int(Frame + bpy.context.scene.frame_start))
+				Export_babylon.write_vector(file_handler, "values", getattr(object,typeBl))
+				file_handler.write("}")
+		
+		file_handler.write("]}")
+
 	def export_mesh(object, scene, file_handler, multiMaterials):
 		# Get mesh	
 		mesh = object.to_mesh(scene, True, "PREVIEW")
@@ -412,6 +460,7 @@ class Export_babylon(bpy.types.Operator, ExportHelper):
 		Export_babylon.write_bool(file_handler, "isEnabled", True)
 		Export_babylon.write_bool(file_handler, "checkCollisions", object.data.checkCollisions)
 		Export_babylon.write_int(file_handler, "billboardMode", billboardMode)
+		Export_babylon.write_bool(file_handler, "receiveShadows", object.data.receiveShadows)
 		
 		if hasUV and hasUV2:
 			Export_babylon.write_int(file_handler, "uvCount", 2)
@@ -439,9 +488,59 @@ class Export_babylon(bpy.types.Operator, ExportHelper):
 			first = False
 		file_handler.write("]")
 		
+		#Export Animations
+		
+		rotAnim = False
+		locAnim = False
+		scaAnim = False
+		coma = False
+		
+		if object.animation_data:
+			if object.animation_data.action:
+				file_handler.write(",\"animations\":[")
+				for fcurve in object.animation_data.action.fcurves:
+					if fcurve.data_path == "rotation_euler" and rotAnim == False:
+						Export_babylon.export_animation(object, scene, file_handler, "rotation_euler", "rotation", coma)
+						rotAnim = coma = True
+					elif fcurve.data_path == "location" and locAnim == False:
+						Export_babylon.export_animation(object, scene, file_handler, "location", "position", coma)
+						locAnim = coma = True
+					elif fcurve.data_path == "scale" and scaAnim == False:
+						Export_babylon.export_animation(object, scene, file_handler, "scale", "scaling", coma)
+						locAnim = coma = True
+				file_handler.write("]")
+				#Set Animations
+				Export_babylon.write_bool(file_handler, "autoAnimate", True)
+				Export_babylon.write_int(file_handler, "autoAnimateFrom", 0)
+				Export_babylon.write_int(file_handler, "autoAnimateTo", bpy.context.scene.frame_end - bpy.context.scene.frame_start + 1)
+				Export_babylon.write_bool(file_handler, "autoAnimateLoop", True)
+
+
 		# Closing
 		file_handler.write("}")
 		
+	def export_shadowGenerator(lamp, scene, file_handler):		
+		file_handler.write("{")
+		if lamp.data.shadowMap == 'VAR':
+			Export_babylon.write_bool(file_handler, "useVarianceShadowMap", True, True)
+		else:
+			Export_babylon.write_bool(file_handler, "useVarianceShadowMap", False, True)
+			
+		Export_babylon.write_int(file_handler, "mapSize", lamp.data.shadowMapSize)	
+		Export_babylon.write_string(file_handler, "lightId", lamp.name)		
+		
+		file_handler.write(",\"renderList\":[")
+		multiMaterials = []
+		first = True
+		for object in [object for object in scene.objects]:
+			if (object.type == 'MESH' and object.data.castShadows):
+				if first != True:
+					file_handler.write(",")
+
+				first = False
+				file_handler.write("\"" + object.name + "\"")
+		file_handler.write("]")			
+		file_handler.write("}")	
 
 	def save(operator, context, filepath="",
 		use_apply_modifiers=False,
@@ -469,6 +568,13 @@ class Export_babylon(bpy.types.Operator, ExportHelper):
 		Export_babylon.write_color(file_handler, "ambientColor", world_ambient)
 		Export_babylon.write_vector(file_handler, "gravity", scene.gravity)
 		
+		if world and world.mist_settings.use_mist:
+				Export_babylon.write_int(file_handler, "fogMode", 3)
+				Export_babylon.write_color(file_handler, "fogColor", world.horizon_color)
+				Export_babylon.write_float(file_handler, "fogStart", world.mist_settings.start)
+				Export_babylon.write_float(file_handler, "fogEnd", world.mist_settings.depth)
+				Export_babylon.write_float(file_handler, "fogDensity", 0.1)
+		
 		# Cameras
 		file_handler.write(",\"cameras\":[")
 		first = True
@@ -533,6 +639,19 @@ class Export_babylon(bpy.types.Operator, ExportHelper):
 			data_string = Export_babylon.export_multimaterial(multimaterial, scene, file_handler)
 		file_handler.write("]")
 		
+		# Shadow generators
+		file_handler.write(",\"shadowGenerators\":[")
+		first = True
+		for object in [object for object in scene.objects if object.is_visible(scene)]:
+			if (object.type == 'LAMP' and object.data.shadowMap != 'NONE'):
+				if first != True:
+					file_handler.write(",")
+
+				first = False
+				data_string = Export_babylon.export_shadowGenerator(object, scene, file_handler)
+		file_handler.write("]")
+		
+		
 		# Closing
 		file_handler.write("}")
 		file_handler.close()
@@ -541,11 +660,19 @@ class Export_babylon(bpy.types.Operator, ExportHelper):
 
 # UI
 bpy.types.Mesh.checkCollisions = BoolProperty(
-    name="Check collisions", 
+    name="Check Collisions", 
+    default = False)
+	
+bpy.types.Mesh.castShadows = BoolProperty(
+    name="Cast Shadows", 
+    default = False)
+	
+bpy.types.Mesh.receiveShadows = BoolProperty(
+    name="Receive Shadows", 
     default = False)
 	
 bpy.types.Camera.checkCollisions = BoolProperty(
-    name="Check collisions", 
+    name="Check Collisions", 
     default = False)
 	
 bpy.types.Camera.applyGravity = BoolProperty(
@@ -554,7 +681,16 @@ bpy.types.Camera.applyGravity = BoolProperty(
 	
 bpy.types.Camera.ellipsoid = FloatVectorProperty(
     name="Ellipsoid", 
-	default = mathutils.Vector((0.2, 0.9, 0.2)))		
+	default = mathutils.Vector((0.2, 0.9, 0.2)))
+
+bpy.types.Lamp.shadowMap = EnumProperty(
+    name="Shadow Map Type", 
+	items = (('NONE', "None", "No Shadow Maps"), ('STD', "Standard", "Use Standard Shadow Maps"), ('VAR', "Variance", "Use Variance Shadow Maps")),
+	default = 'NONE')
+	
+bpy.types.Lamp.shadowMapSize = IntProperty(
+    name="Shadow Map Size", 
+	default = 512)	
 
 class ObjectPanel(bpy.types.Panel):
 	bl_label = "Babylon.js"
@@ -570,13 +706,19 @@ class ObjectPanel(bpy.types.Panel):
 		layout = self.layout
 		isMesh = isinstance(ob.data, bpy.types.Mesh)
 		isCamera = isinstance(ob.data, bpy.types.Camera)
+		isLight = isinstance(ob.data, bpy.types.Lamp)
 		
 		if isMesh:
 			layout.prop(ob.data, 'checkCollisions')		
+			layout.prop(ob.data, 'castShadows')		
+			layout.prop(ob.data, 'receiveShadows')		
 		elif isCamera:
 			layout.prop(ob.data, 'checkCollisions')
 			layout.prop(ob.data, 'applyGravity')
 			layout.prop(ob.data, 'ellipsoid')
+		elif isLight:
+			layout.prop(ob.data, 'shadowMap')
+			layout.prop(ob.data, 'shadowMapSize')	
 			
 ### REGISTER ###
 

二進制
Samples/Assets/grass.jpg


二進制
Samples/Scenes/Blender/63_Free_Windows_Xp_Vista_Wallpapers.jpg


二進制
Samples/Scenes/Blender/69_Free_Windows_Xp_Vista_Wallpapers.jpg


二進制
Samples/Scenes/Blender/Ciel.png


二進制
Samples/Scenes/Blender/Finishes.Plaster.Stucco.Fine.Mauve.jpg


二進制
Samples/Scenes/Blender/MS-384.jpg


二進制
Samples/Scenes/Blender/Metal1.png


二進制
Samples/Scenes/Blender/Tree.png


二進制
Samples/Scenes/Blender/WP_20121206_003.jpg


文件差異過大導致無法顯示
+ 5 - 7
Samples/Scenes/Blender/blender.babylon


二進制
Samples/Scenes/Blender/blender.blend


二進制
Samples/Scenes/Blender/concrete5.png


二進制
Samples/Scenes/Blender/new-york1-1600-1200.jpg


二進制
Samples/Scenes/Blender/skin.png


二進制
Samples/Scenes/Blender/snow.jpg


二進制
Samples/Scenes/Blender/test_vase_color.jpg


二進制
Samples/Scenes/Blender/tyrol_austria___misty_mountain_village-1600x1200.jpg


文件差異過大導致無法顯示
+ 0 - 11
Samples/Scenes/Blender/untitled.babylon


二進制
Samples/Scenes/Blender/vase_test1.png


+ 78 - 0
Samples/Scenes/Customs/shadows.js

@@ -0,0 +1,78 @@
+var CreateShadowsTestScene = function (engine) {
+    var scene = new BABYLON.Scene(engine);
+    var camera = new BABYLON.ArcRotateCamera("Camera", 0, 0, 10, BABYLON.Vector3.Zero(), scene);
+    var light = new BABYLON.DirectionalLight("dir01", new BABYLON.Vector3(0, -1, -0.2), scene);
+    var light2 = new BABYLON.DirectionalLight("dir02", new BABYLON.Vector3(-1, -2, -1), scene);
+    light.position = new BABYLON.Vector3(0, 30, 0);
+    light2.position = new BABYLON.Vector3(10, 20, 10);
+
+    light.intensity = 0.6;
+    light2.intensity = 0.6;
+
+    camera.setPosition(new BABYLON.Vector3(-20, 20, 0));
+    
+    // Skybox
+    var skybox = BABYLON.Mesh.CreateBox("skyBox", 1000.0, scene);
+    var skyboxMaterial = new BABYLON.StandardMaterial("skyBox", scene);
+    skyboxMaterial.backFaceCulling = false;
+    skyboxMaterial.reflectionTexture = new BABYLON.CubeTexture("Scenes/Customs/skybox/night", scene);
+    skyboxMaterial.reflectionTexture.coordinatesMode = BABYLON.Texture.SKYBOX_MODE;
+    skyboxMaterial.diffuseColor = new BABYLON.Color3(0, 0, 0);
+    skyboxMaterial.specularColor = new BABYLON.Color3(0, 0, 0);
+    skybox.material = skyboxMaterial;
+
+    // Ground
+    var ground = BABYLON.Mesh.CreateGround("ground", 1000, 1000, 1, scene, false);
+    var groundMaterial = new BABYLON.StandardMaterial("ground", scene);
+    groundMaterial.diffuseTexture = new BABYLON.Texture("assets/grass.jpg", scene);
+    groundMaterial.diffuseTexture.uScale = 60;
+    groundMaterial.diffuseTexture.vScale = 60;
+    groundMaterial.diffuseColor = new BABYLON.Color3(0, 0, 0);
+    groundMaterial.specularColor = new BABYLON.Color3(0, 0, 0);
+    ground.position.y = -2.05;
+    ground.material = groundMaterial;
+    
+    // Torus
+    var torus = BABYLON.Mesh.CreateTorus("torus", 8, 2, 32, scene, false);
+    torus.position.y = 6.0;
+    var torus2 = BABYLON.Mesh.CreateTorus("torus2", 4, 1, 32, scene, false);
+    torus2.position.y = 6.0;
+    
+    // Shadows
+    var shadowGenerator = new BABYLON.ShadowGenerator(512, light);
+    shadowGenerator.getShadowMap().renderList.push(torus);
+    shadowGenerator.getShadowMap().renderList.push(torus2);
+    
+    var shadowGenerator2 = new BABYLON.ShadowGenerator(512, light2);
+    shadowGenerator2.getShadowMap().renderList.push(torus);
+    shadowGenerator2.getShadowMap().renderList.push(torus2);
+    shadowGenerator2.useVarianceShadowMap = false;
+
+    ground.receiveShadows = true;
+    
+    var beforeRenderFunction = function () {
+        // Camera
+        if (camera.beta < 0.1)
+            camera.beta = 0.1;
+        else if (camera.beta > (Math.PI / 2) * 0.99)
+            camera.beta = (Math.PI / 2) * 0.99;
+
+        if (camera.radius > 150)
+            camera.radius = 150;
+
+        if (camera.radius < 5)
+            camera.radius = 5;
+    };
+
+    scene.registerBeforeRender(beforeRenderFunction);
+    
+    // Animations
+    scene.registerBeforeRender(function () {
+        torus.rotation.x += 0.01;
+        torus.rotation.z += 0.02;
+        torus2.rotation.x += 0.02;
+        torus2.rotation.y += 0.01;
+    });
+    
+    return scene;
+};

二進制
Samples/Scenes/Customs/skybox/night_nx.jpg


二進制
Samples/Scenes/Customs/skybox/night_ny.jpg


二進制
Samples/Scenes/Customs/skybox/night_nz.jpg


二進制
Samples/Scenes/Customs/skybox/night_px.jpg


二進制
Samples/Scenes/Customs/skybox/night_py.jpg


二進制
Samples/Scenes/Customs/skybox/night_pz.jpg


文件差異過大導致無法顯示
+ 1 - 1
Samples/Scenes/Espilit/espilit.babylon


文件差異過大導致無法顯示
+ 1 - 1
Samples/Scenes/Flat2009/Flat2009.babylon


文件差異過大導致無法顯示
+ 1 - 1
Samples/Scenes/Heart/Heart.babylon


文件差異過大導致無法顯示
+ 1 - 1
Samples/Scenes/SpaceDek/SpaceDek.babylon


文件差異過大導致無法顯示
+ 1 - 1
Samples/Scenes/Spaceship/Spaceship.babylon


文件差異過大導致無法顯示
+ 1 - 1
Samples/Scenes/TestAnim/TestAnim.babylon


文件差異過大導致無法顯示
+ 1 - 1
Samples/Scenes/TheCar/TheCar.babylon


文件差異過大導致無法顯示
+ 1 - 1
Samples/Scenes/Viper/Viper.babylon


文件差異過大導致無法顯示
+ 1 - 1
Samples/Scenes/WCafe/WCafe.babylon


+ 4 - 4
Samples/Scenes/WorldMonger/Shaders/Water/waterMaterial.js

@@ -21,11 +21,11 @@
 
         this.refractionTexture.onBeforeRender = function() {
             BABYLON.clipPlane = new BABYLON.Plane(0, 1, 0, 0);
-        }
-        
-        this.refractionTexture.onAfterRender = function () {
+        };
+
+        this.refractionTexture.onAfterRender = function() {
             BABYLON.clipPlane = null;
-        }
+        };
 
         this.waterColor = new BABYLON.Color3(0.0, 0.3, 0.1);
         this.waterColorLevel = 0.2;

二進制
Samples/Screenshots/blender.jpg


二進制
Samples/Screenshots/shadows.jpg


文件差異過大導致無法顯示
+ 10 - 8
Samples/babylon.js


文件差異過大導致無法顯示
+ 1 - 1
Samples/hand.minified-1.1.0.js


+ 1 - 1
Samples/index.css

@@ -276,7 +276,7 @@ button {
     font-size: 20px;
     color: white;
     font-weight: bold;
-    background-color: #2F2F2F;
+    background-color: rgba(30, 30, 30, 0.9);
     padding: 10px 10px 10px 10px;
     margin-bottom: 4px;
 }

+ 4 - 1
Samples/index.html

@@ -15,7 +15,7 @@
 
     </script>
     <link href="index.css" rel="stylesheet" />
-    <script src="hand.minified-1.1.0.js"></script>
+    <script src="hand.minified-1.1.1.js"></script>
     <!--<script src="Babylon/Tools/babylon.math.js"></script>
     <script src="Babylon/Tools/babylon.tools.js"></script>
     <script src="Babylon/babylon.engine.js"></script>
@@ -27,6 +27,7 @@
     <script src="Babylon/Lights/babylon.spotLight.js"></script>
     <script src="Babylon/Lights/babylon.hemisphericLight.js"></script>
     <script src="Babylon/Lights/babylon.directionalLight.js"></script>
+    <script src="Babylon/Lights/Shadows/babylon.shadowGenerator.js"></script>
     <script src="Babylon/Collisions/babylon.collisionPlane.js"></script>
     <script src="Babylon/Collisions/babylon.collider.js"></script>
     <script src="Babylon/Cameras/babylon.camera.js"></script>
@@ -62,6 +63,7 @@
     <script src="Scenes/Customs/fog_test.js"></script>
     <script src="Scenes/Customs/multimat.js"></script>
     <script src="Scenes/Customs/heightMap_test.js"></script>
+    <script src="Scenes/Customs/shadows.js"></script>
     <script src="index.js"></script>
 </head>
 <body onload="onload();">
@@ -158,6 +160,7 @@
                                     <li>Alpha testing</li>
                                     <li>Billboarding</li>
                                     <li>Fullscreen mode</li>
+                                    <li>Shadow Maps and Variance Shadow Maps</li>
                                 </ul>
                             </li>
                             <li>

+ 5 - 0
Samples/index.js

@@ -27,6 +27,7 @@
         }];
 
     var tests = [
+        { title: "SHADOWS", id: 6, screenshot: "shadows.jpg", size: "1.0 MB" },
         { title: "HEIGHTMAP", id: 5, screenshot: "heightmap.jpg", size: "1.0 MB" },
         { title: "LIGHTS", id: 1, screenshot: "testlight.jpg", size: "0.1 MB" },
         { title: "BUMP", id: 2, screenshot: "bump.jpg", size: "0.1 MB" },
@@ -198,6 +199,9 @@
                     case 5:
                         newScene = CreateHeightMapTestScene(engine);
                         break;
+                    case 6:
+                        newScene = CreateShadowsTestScene(engine);
+                        break;
                 }
 
                 newScene.activeCamera.attachControl(canvas);
@@ -217,6 +221,7 @@
 
             BABYLON.SceneLoader.Load("Scenes/" + name + "/", name + ".babylon", engine, function (newScene) {
                 scene = newScene;
+                scene.fogMode = BABYLON.Scene.FOGMODE_NONE;
                 loadingText.innerHTML = "Streaming textures...";
                 scene.executeWhenReady(function () {
                     if (scene.activeCamera) {

文件差異過大導致無法顯示
+ 0 - 11
babylon.1.0.10.js


文件差異過大導致無法顯示
+ 13 - 0
babylon.1.1.0.js


+ 1 - 0
readme.md

@@ -33,6 +33,7 @@ Official web site: [www.babylonjs.com](http://www.babylonjs.com/)
  - Alpha testing
  - Billboarding
  - Fullscreen mode
+ - Shadow Maps and Variance Shadow Maps
 -  Textures:
  - Render target textures
  - Dynamic textures (canvas)

+ 5 - 0
what's new.txt

@@ -1,3 +1,8 @@
+1.1.0:
+ - Shadow Maps and Variance Shadow Maps
+ - Shadows Maps and animations are now exported from Blender
+ - Hand.js is no longer required for ArcRotateCamera
+ - ArcRotateCamera support pinch/zoom gesture on IE
 1.0.10:
  - Using typed arrays for Matrix
  - Improving IE11 support