瀏覽代碼

Merge remote-tracking branch 'BabylonJS/master'

MackeyK24 8 年之前
父節點
當前提交
639c94ead0
共有 34 個文件被更改,包括 13602 次插入12503 次删除
  1. 25 6
      canvas2D/src/Engine/babylon.canvas2d.ts
  2. 55 2
      canvas2D/src/Engine/babylon.fontTexture.ts
  3. 4 3
      canvas2D/src/Engine/babylon.group2d.ts
  4. 35 15
      canvas2D/src/Engine/babylon.prim2dBase.ts
  5. 15 21
      canvas2D/src/Engine/babylon.renderablePrim2d.ts
  6. 32 6
      canvas2D/src/Engine/babylon.text2d.ts
  7. 7 0
      canvas2D/src/shaders/text2d.fragment.fx
  8. 33 0
      contributing.md
  9. 26 26
      dist/preview release/babylon.core.js
  10. 5983 5928
      dist/preview release/babylon.d.ts
  11. 38 37
      dist/preview release/babylon.js
  12. 523 199
      dist/preview release/babylon.max.js
  13. 5983 5928
      dist/preview release/babylon.module.d.ts
  14. 38 37
      dist/preview release/babylon.noworker.js
  15. 13 1
      dist/preview release/canvas2D/babylon.canvas2d.d.ts
  16. 141 45
      dist/preview release/canvas2D/babylon.canvas2d.js
  17. 12 12
      dist/preview release/canvas2D/babylon.canvas2d.min.js
  18. 3 2
      dist/preview release/what's new.md
  19. 3 0
      localDev/index.html
  20. 3 9
      readme.md
  21. 40 5
      src/Bones/babylon.bone.ts
  22. 258 30
      src/Bones/babylon.boneLookController.ts
  23. 1 1
      src/Cameras/babylon.freeCamera.ts
  24. 10 0
      src/Cameras/babylon.targetCamera.ts
  25. 13 0
      src/Materials/Textures/babylon.renderTargetTexture.ts
  26. 1 1
      src/Materials/babylon.material.ts
  27. 33 0
      src/Mesh/babylon.groundMesh.ts
  28. 132 1
      src/Mesh/babylon.mesh.ts
  29. 8 0
      src/Probes/babylon.reflectionProbe.ts
  30. 2 2
      src/Tools/babylon.database.ts
  31. 11 127
      src/Tools/babylon.sceneSerializer.ts
  32. 1 1
      src/Tools/babylon.tools.ts
  33. 107 57
      src/babylon.engine.ts
  34. 13 1
      src/babylon.mixins.ts

+ 25 - 6
canvas2D/src/Engine/babylon.canvas2d.ts

@@ -169,6 +169,8 @@
             this._scene = scene;
             this._engine = engine;
             this._renderingSize = new Size(0, 0);
+            this._curHWScale = 0;
+            this._canvasLevelScale = new Vector3(1, 1, 1);
             this._designSize = settings.designSize || null;
             this._designUseHorizAxis = settings.designUseHorizAxis === true;
             if (!this._trackedGroups) {
@@ -1292,7 +1294,9 @@
         private _designUseHorizAxis: boolean;
         public  _primitiveCollisionManager: PrimitiveCollisionManagerBase;
 
-        public _renderingSize: Size;
+        public _canvasLevelScale: Vector3;
+        public  _renderingSize: Size;
+        private _curHWScale;
 
         private _drawCallsOpaqueCounter          : PerfCounter;
         private _drawCallsAlphaTestCounter       : PerfCounter;
@@ -1458,15 +1462,26 @@
                 return;
             }
 
+            // Detect a change of HWRendering scale
+            let hwsl = this.engine.getHardwareScalingLevel();
+            let hwslChanged = this._curHWScale !== hwsl;
+            if (hwslChanged) {
+                this._curHWScale = hwsl;
+                for (let child of this.children) {
+                    child._setFlags(SmartPropertyPrim.flagLocalTransformDirty|SmartPropertyPrim.flagGlobalTransformDirty);
+                }
+                this._setLayoutDirty();
+            }
+
             // Detect a change of rendering size
             let renderingSizeChanged = false;
-            let newWidth = this.engine.getRenderWidth();
+            let newWidth = this.engine.getRenderWidth() * hwsl;
             if (newWidth !== this._renderingSize.width) {
                 renderingSizeChanged = true;
             }
             this._renderingSize.width = newWidth;
 
-            let newHeight = this.engine.getRenderHeight();
+            let newHeight = this.engine.getRenderHeight() * hwsl;
             if (newHeight !== this._renderingSize.height) {
                 renderingSizeChanged = true;
             }
@@ -1487,17 +1502,21 @@
             if (this._designSize) {
                 let scale: number;
                 if (this._designUseHorizAxis) {
-                    scale = this._renderingSize.width / this._designSize.width;
+                    scale = this._renderingSize.width / (this._designSize.width * hwsl);
                 } else {
-                    scale = this._renderingSize.height / this._designSize.height;
+                    scale = this._renderingSize.height / (this._designSize.height * hwsl);
                 }
                 this.size = this._designSize.clone();
-                this.scale = scale;
+                this._canvasLevelScale.copyFromFloats(scale, scale, 1);
+            } else if (this._curHWScale !== 1) {
+                let ratio = 1 / this._curHWScale;
+                this._canvasLevelScale.copyFromFloats(ratio, ratio, 1);
             }
 
             var context = new PrepareRender2DContext();
 
             ++this._globalTransformProcessStep;
+            this._setFlags(SmartPropertyPrim.flagLocalTransformDirty|SmartPropertyPrim.flagGlobalTransformDirty);
             this.updateCachedStates(false);
 
             this._prepareGroupRender(context);

+ 55 - 2
canvas2D/src/Engine/babylon.fontTexture.ts

@@ -478,13 +478,50 @@
 
             this._currentFreePosition = Vector2.Zero();
 
-            // Add the basic ASCII based characters
+            // Add the basic ASCII based characters                                                               
             for (let i = 0x20; i < 0x7F; i++) {
                 var c = String.fromCharCode(i);
                 this.getChar(c);
             }
 
             this.update();
+
+            //this._saveToImage("");
+            
+        }
+
+        private _saveToImage(url: string) {
+            let base64Image = this._canvas.toDataURL("image/png");
+
+            //Creating a link if the browser have the download attribute on the a tag, to automatically start download generated image.
+            if (("download" in document.createElement("a"))) {
+                var a = window.document.createElement("a");
+                a.href = base64Image;
+                var date = new Date();
+                var stringDate = (date.getFullYear() + "-" + (date.getMonth() + 1)).slice(-2) +
+                    "-" +
+                    date.getDate() +
+                    "_" +
+                    date.getHours() +
+                    "-" +
+                    ('0' + date.getMinutes()).slice(-2);
+                a.setAttribute("download", "screenshot_" + stringDate + ".png");
+
+                window.document.body.appendChild(a);
+
+                a.addEventListener("click",
+                    () => {
+                        a.parentElement.removeChild(a);
+                    });
+                a.click();
+
+                //Or opening a new tab with the image if it is not possible to automatically start download.
+            } else {
+                var newWindow = window.open("");
+                var img = newWindow.document.createElement("img");
+                img.src = base64Image;
+                newWindow.document.body.appendChild(img);
+            }
         }
 
         /**
@@ -561,6 +598,20 @@
 
                 // Draw the character in the HTML canvas
                 this._context.fillText(char, curPosXMargin, curPosYMargin - this._offset);
+
+                // Premul Alpha manually
+                let id = this._context.getImageData(curPosXMargin, curPosYMargin, width, this._lineHeightSuper);
+                for (let i = 0; i < id.data.length; i += 4) {
+                    let v = id.data[i + 3];
+                    if (v > 0 && v < 255) {
+                        id.data[i + 0] = v;
+                        id.data[i + 1] = v;
+                        id.data[i + 2] = v;
+                        id.data[i + 3] = v;
+                    }
+
+                }
+                this._context.putImageData(id, curPosXMargin, curPosYMargin);
             }
 
             // Fill the CharInfo object
@@ -765,12 +816,14 @@
             ctx.font = font;
             ctx.fillText(chars, 0, 0);
             var pixels = ctx.getImageData(0, 0, fontDraw.width, fontDraw.height).data;
+
             var start = -1;
             var end = -1;
             for (var row = 0; row < fontDraw.height; row++) {
                 for (var column = 0; column < fontDraw.width; column++) {
                     var index = (row * fontDraw.width + column) * 4;
-                    if (pixels[index] === 0) {
+                    let pix = pixels[index];
+                    if (pix === 0) {
                         if (column === fontDraw.width - 1 && start !== -1) {
                             end = row;
                             row = fontDraw.height;

+ 4 - 3
canvas2D/src/Engine/babylon.group2d.ts

@@ -355,8 +355,9 @@
 
             let s = this.actualSize;
             let a = this.actualScale;
-            let sw = Math.ceil(s.width * a.x);
-            let sh = Math.ceil(s.height * a.y);
+            let hwsl = 1/this.owner.engine.getHardwareScalingLevel();
+            let sw = Math.ceil(s.width * a.x * hwsl);
+            let sh = Math.ceil(s.height * a.y * hwsl);
 
             // The dimension must be overridden when using the designSize feature, the ratio is maintain to compute a uniform scale, which is mandatory but if the designSize's ratio is different from the rendering surface's ratio, content will be clipped in some cases.
             // So we set the width/height to the rendering's one because that's what we want for the viewport!
@@ -370,7 +371,7 @@
             if (!this._isCachedGroup) {
                 // Compute the WebGL viewport's location/size
                 let t = this._globalTransform.getTranslation();
-                let rs = this.owner._renderingSize;
+                let rs = this.owner._renderingSize.multiplyByFloats(hwsl, hwsl);
                 sh = Math.min(sh, rs.height - t.y);
                 sw = Math.min(sw, rs.width - t.x);
                 let x = t.x;

+ 35 - 15
canvas2D/src/Engine/babylon.prim2dBase.ts

@@ -2228,6 +2228,7 @@
             this._scale.x = this._scale.y = value;
             this._setFlags(SmartPropertyPrim.flagActualScaleDirty);
             this._spreadActualScaleDirty();
+            this._positioningDirty();
         }
 
         public get scale(): number {
@@ -2553,6 +2554,7 @@
             this._scale.x = value;
             this._setFlags(SmartPropertyPrim.flagActualScaleDirty);
             this._spreadActualScaleDirty();
+            this._positioningDirty();
         }
 
         public get scaleX(): number {
@@ -2567,6 +2569,7 @@
             this._scale.y = value;
             this._setFlags(SmartPropertyPrim.flagActualScaleDirty);
             this._spreadActualScaleDirty();
+            this._positioningDirty();
         }
 
         public get scaleY(): number {
@@ -3665,6 +3668,7 @@
         private static _t2: Matrix = new Matrix();
         private static _v0: Vector2 = Vector2.Zero();   // Must stay with the value 0,0
         private static _v30: Vector3 = Vector3.Zero();   // Must stay with the value 0,0,0
+        private static _iv3: Vector3 = new Vector3(1,1,1); // Must stay identity vector
         private static _ts0 = Size.Zero();
 
         private _updateLocalTransform(): boolean {
@@ -3680,12 +3684,19 @@
                     this._updatePositioning();
                 }
 
+
                 var rot = Quaternion.RotationAxis(new Vector3(0, 0, 1), this._rotation);
                 var local: Matrix;
                 let pos = this._position ? this.position : (this.layoutAreaPos || Prim2DBase._v0);
                 let scale = new Vector3(this._scale.x, this._scale.y, 1);
                 let postScale = this._postScale;
-                let globalScale = scale.multiplyByFloats(postScale.x, postScale.y, 1);
+                let canvasScale = Prim2DBase._iv3;
+                let hasCanvasScale = false;
+                if (this._parent instanceof Canvas2D) {
+                    hasCanvasScale = true;
+                    canvasScale = (this._parent as Canvas2D)._canvasLevelScale || Prim2DBase._iv3;
+                }
+                let globalScale = scale.multiplyByFloats(postScale.x*canvasScale.x, postScale.y*canvasScale.y, 1);
 
                 if (this._origin.x === 0 && this._origin.y === 0) {
                     // ###MATRIX PART###
@@ -3698,31 +3709,39 @@
                     // ###MATRIX PART###
                     {
                         // -Origin offset
+                        let t0 = Prim2DBase._t0;
+                        let t1 = Prim2DBase._t1;
+                        let t2 = Prim2DBase._t2;
                         let as = Prim2DBase._ts0;
                         as.copyFrom(this.actualSize);
                         as.width /= postScale.x;
                         as.height /= postScale.y;
-                        Matrix.TranslationToRef((-as.width * this._origin.x), (-as.height * this._origin.y), 0, Prim2DBase._t0);
+                        Matrix.TranslationToRef((-as.width * this._origin.x), (-as.height * this._origin.y), 0, t0);
 
                         // -Origin * rotation
-                        rot.toRotationMatrix(Prim2DBase._t1);
-                        Prim2DBase._t0.multiplyToRef(Prim2DBase._t1, Prim2DBase._t2);
+                        rot.toRotationMatrix(t1);
+                        t0.multiplyToRef(t1, t2);
 
                         // -Origin * rotation * scale
-                        Matrix.ScalingToRef(this._scale.x, this._scale.y, 1, Prim2DBase._t0);
-                        Prim2DBase._t2.multiplyToRef(Prim2DBase._t0, Prim2DBase._t1);
+                        Matrix.ScalingToRef(this._scale.x, this._scale.y, 1, t0);
+                        t2.multiplyToRef(t0, t1);
 
                         // -Origin * rotation * scale * Origin
-                        Matrix.TranslationToRef((as.width * this._origin.x), (as.height * this._origin.y), 0, Prim2DBase._t2);
-                        Prim2DBase._t1.multiplyToRef(Prim2DBase._t2, Prim2DBase._t0);
+                        Matrix.TranslationToRef((as.width * this._origin.x), (as.height * this._origin.y), 0, t2);
+                        t1.multiplyToRef(t2, t0);
 
                         // -Origin * rotation * scale * Origin * postScale
-                        Matrix.ScalingToRef(postScale.x, postScale.y, 1, Prim2DBase._t1);
-                        Prim2DBase._t0.multiplyToRef(Prim2DBase._t1, Prim2DBase._t2);
+                        Matrix.ScalingToRef(postScale.x, postScale.y, 1, t1);
+                        t0.multiplyToRef(t1, t2);
 
                         // -Origin * rotation * scale * Origin * postScale * Position
-                        Matrix.TranslationToRef(pos.x + this._marginOffset.x, pos.y + this._marginOffset.y, 0, Prim2DBase._t0);
-                        Prim2DBase._t2.multiplyToRef(Prim2DBase._t0, this._localTransform);
+                        Matrix.TranslationToRef(pos.x + this._marginOffset.x, pos.y + this._marginOffset.y, 0, t0);
+                        t2.multiplyToRef(t0, this._localTransform);
+
+                        if (hasCanvasScale) {
+                            Matrix.ScalingToRef(canvasScale.x, canvasScale.y, canvasScale.z, Prim2DBase._t1);
+                            this._localTransform.multiplyToRef(Prim2DBase._t1, this._localTransform);
+                        }
 
                         this._localLayoutTransform = Matrix.Compose(globalScale, rot, new Vector3(pos.x, pos.y, 0));
                     }
@@ -3799,7 +3818,7 @@
             }
 
             // Check if we must update this prim
-            if ((this === <any>this.owner) || (this._globalTransformProcessStep !== this.owner._globalTransformProcessStep) || (this._areSomeFlagsSet(SmartPropertyPrim.flagGlobalTransformDirty))) {
+            if ((this._globalTransformProcessStep !== this.owner._globalTransformProcessStep) || (this._areSomeFlagsSet(SmartPropertyPrim.flagGlobalTransformDirty))) {
                 this.owner.addUpdateGlobalTransformCounter(1);
 
                 let curVisibleState = this.isVisible;
@@ -3864,6 +3883,8 @@
 
         private _updatePositioning() {
             if (!this._isFlagSet(SmartPropertyPrim.flagUsePositioning)) {
+                // Just in case, if may happen and if we don't clear some computation will keep going on forever
+                this._clearFlags(SmartPropertyPrim.flagPositioningDirty);
                 return;
             }
 
@@ -3891,7 +3912,6 @@
             // Set the flag to avoid re-entrance
             this._setFlags(SmartPropertyPrim.flagComputingPositioning);
             try {
-
                 let isSizeAuto = this.isSizeAuto;
                 let isVSizeAuto = this.isVerticalSizeAuto;
                 let isHSizeAuto = this.isHorizontalSizeAuto;
@@ -4008,7 +4028,7 @@
                     //  not yet set and computing alignment would result into a bad size.
                     // So we make sure with compute alignment only if the layoutArea is good
                     if (layoutArea && layoutArea.width >= newSize.width && layoutArea.height >= newSize.height) {
-                        margin.computeWithAlignment(layoutArea, newSize, ma, this.actualScale, mo, Prim2DBase._size2);
+                        margin.computeWithAlignment(layoutArea, newSize, ma, new Vector2(1,1)/*this.actualScale*/, mo, Prim2DBase._size2);
                     } else {
                         mo.copyFromFloats(0, 0, 0, 0);
                     }

+ 15 - 21
canvas2D/src/Engine/babylon.renderablePrim2d.ts

@@ -931,7 +931,7 @@
         private static _s = Vector3.Zero();
         private static _r = Quaternion.Identity();
         private static _t = Vector3.Zero();
-        private static _uV3 = new Vector3(1, 1, 1);
+        private static _iV3 = new Vector3(1, 1, 1); // Must stay identity vector3
         /**
          * Update the instanceDataBase level properties of a part
          * @param part the part to update
@@ -939,12 +939,22 @@
          */
         protected updateInstanceDataPart(part: InstanceDataBase, positionOffset: Vector2 = null) {
             let t = this._globalTransform.multiply(this.renderGroup.invGlobalTransform);    // Compute the transformation into the renderGroup's space
-            let rgScale = this._areSomeFlagsSet(SmartPropertyPrim.flagDontInheritParentScale) ? RenderablePrim2D._uV : this.renderGroup.actualScale;         // We still need to apply the scale of the renderGroup to our rendering, so get it.
+            let scl = RenderablePrim2D._s;
+            let rot = RenderablePrim2D._r;
+            let trn = RenderablePrim2D._t;
+            t.decompose(scl, rot, trn);
+            let pas = this.actualScale;
+            scl.x = pas.x;
+            scl.y = pas.y;
+            scl.z = 1;
+            t = Matrix.Compose(this.applyActualScaleOnTransform() ? scl : RenderablePrim2D._iV3, rot, trn);
+
             let size = (<Size>this.renderGroup.viewportSize);
             let zBias = this.actualZOffset;
 
             let offX = 0;
             let offY = 0;
+
             // If there's an offset, apply the global transformation matrix on it to get a global offset
             if (positionOffset) {
                 offX = positionOffset.x * t.m[0] + positionOffset.y * t.m[4];
@@ -960,25 +970,9 @@
             let w = size.width;
             let h = size.height;
             let invZBias = 1 / zBias;
-            let tx = new Vector4(t.m[0] * rgScale.x * 2 / w, t.m[4] * rgScale.x * 2 / w, 0/*t.m[8]*/, ((t.m[12] + offX) * rgScale.x * 2 / w) - 1);
-            let ty = new Vector4(t.m[1] * rgScale.y * 2 / h, t.m[5] * rgScale.y * 2 / h, 0/*t.m[9]*/, ((t.m[13] + offY) * rgScale.y * 2 / h) - 1);
-
-            //if (!this.applyActualScaleOnTransform()) {
-            //    t.m[0] = tx.x, t.m[4] = tx.y, t.m[12] = tx.w;
-            //    t.m[1] = ty.x, t.m[5] = ty.y, t.m[13] = ty.w;
-            //    let las = this.actualScale;
-            //    t.decompose(RenderablePrim2D._s, RenderablePrim2D._r, RenderablePrim2D._t);
-            //    let scale = new Vector3(RenderablePrim2D._s.x / las.x, RenderablePrim2D._s.y / las.y, 1);
-            //    t = Matrix.Compose(scale, RenderablePrim2D._r, RenderablePrim2D._t);
-            //    tx = new Vector4(t.m[0], t.m[4], 0, t.m[12]);
-            //    ty = new Vector4(t.m[1], t.m[5], 0, t.m[13]);
-            //}
-
-            //tx.x /= w;
-            //tx.y /= w;
-
-            //ty.x /= h;
-            //ty.y /= h;
+            let tx = new Vector4(t.m[0] * 2 / w, t.m[4] * 2 / w, 0, ((t.m[12] + offX) * 2 / w) - 1);
+            let ty = new Vector4(t.m[1] * 2 / h, t.m[5] * 2 / h, 0, ((t.m[13] + offY) * 2 / h) - 1);
+
 
             part.transformX = tx;
             part.transformY = ty;

File diff suppressed because it is too large
+ 32 - 6
canvas2D/src/Engine/babylon.text2d.ts


+ 7 - 0
canvas2D/src/shaders/text2d.fragment.fx

@@ -22,7 +22,14 @@ void main(void) {
 	gl_FragColor = vec4(vColor.xyz*dist, vColor.a);
 #else
 	vec4 color = texture2D(diffuseSampler, vUV);
+	if (color.a == 0.0) {
+		discard;
+	}
+#ifdef FontTexture
+	gl_FragColor = vec4(color.xxxx)*vColor;
+#else
 	gl_FragColor = color*vColor;
 #endif
+#endif
 
 }

+ 33 - 0
contributing.md

@@ -0,0 +1,33 @@
+# Contributing to Babylon.js
+
+The foundation of **Babylon.js** is simplicity. 
+
+A developer should be able to quickly and easily learn to use the API. 
+
+Simplicity and a low barrier to entry are must-have features of every API. If you have any second thoughts about the complexity of a design, it is almost always much better to cut the feature from the current release and spend more time to get the design right for the next release. 
+
+You can always add to an API, you cannot ever remove anything from one. If the design does not feel right, and you ship it anyway, you are likely to regret having done so.
+
+That's why many of the guidelines of this document are obvious and serve only one purpose: Simplicity.
+
+## Forum and Github issues
+
+Since the very beginning, Babylon.js relies on a great forum and a tremendous community: http://www.html5gamedevs.com/forum/16-babylonjs/.
+Please use the forum for **ANY questions you may have**.
+
+Please use the Github issues **only** for:
+- Bugs
+- Feature requests
+
+We will try to enforce these rules as we consider the forum is a better place for discussions and learnings.
+
+## Pull requests
+
+We are not complicated people, but we still have some [coding guidelines](http://doc.babylonjs.com/generals/Approved_Naming_Conventions)
+Before submitting your PR, just check that everything goes well by [creating the minified version](http://doc.babylonjs.com/generals/Creating_the_Mini-fied_Version)
+
+Need help contributing, here are some links:
+  - [Gulp](https://github.com/BabylonJS/Babylon.js/tree/master/Tools/Gulp) to build from command line.
+  - [VSCode Editor](https://code.visualstudio.com/), Microsoft Code editor, see [Julian Chenard's post](http://pixelcodr.com/tutos/contribute/contribute.html) a Microsoft code editor.
+  - [Visual Studio](http://doc.babylonjs.com/generals/setup_visualStudio), Microsoft's IDE.
+  - [Forum thread](http://www.html5gamedevs.com/topic/20456-contributing-on-babylonjs/) for assistance from our very helpful family.

File diff suppressed because it is too large
+ 26 - 26
dist/preview release/babylon.core.js


File diff suppressed because it is too large
+ 5983 - 5928
dist/preview release/babylon.d.ts


File diff suppressed because it is too large
+ 38 - 37
dist/preview release/babylon.js


File diff suppressed because it is too large
+ 523 - 199
dist/preview release/babylon.max.js


File diff suppressed because it is too large
+ 5983 - 5928
dist/preview release/babylon.module.d.ts


File diff suppressed because it is too large
+ 38 - 37
dist/preview release/babylon.noworker.js


File diff suppressed because it is too large
+ 13 - 1
dist/preview release/canvas2D/babylon.canvas2d.d.ts


File diff suppressed because it is too large
+ 141 - 45
dist/preview release/canvas2D/babylon.canvas2d.js


File diff suppressed because it is too large
+ 12 - 12
dist/preview release/canvas2D/babylon.canvas2d.min.js


+ 3 - 2
dist/preview release/what's new.md

@@ -1,10 +1,11 @@
-# 2.6.0:
+# 3.0.0:
 
 ## Core engine
 
 ### Major updates
- - WebGL2 context support.WebGL2 is initialized instead of WebGL 1 when available ([deltakosh](https://github.com/deltakosh))
+ - WebGL2 context support. WebGL2 is now used instead of WebGL 1 when available. [More info here](http://doc.babylonjs.com/overviews/webgl2) ([deltakosh](https://github.com/deltakosh))
  - Support for [Vertex Array Objects](https://www.opengl.org/registry/specs/ARB/vertex_array_object.txt) ([deltakosh](https://github.com/deltakosh))
+ - Support for multisample render targets. [Demo](http://www.babylonjs-playground.com/#12MKMN) ([deltakosh](https://github.com/deltakosh))
  - New Unity 5 Editor Toolkit. Complete pipeline integration [Doc](TODO) - ([MackeyK24](https://github.com/MackeyK24))
  - New DebugLayer. [Doc](TODO) - ([temechon](https://github.com/temechon))
  - New `VideoTexture.CreateFromWebCam` to generate video texture using WebRTC. [Demo](https://www.babylonjs-playground.com#1R77YT#2) - (Sebastien Vandenberghe)(https://github.com/sebavanmicrosoft) / ([deltakosh](https://github.com/deltakosh))

+ 3 - 0
localDev/index.html

@@ -2,6 +2,9 @@
 <html xmlns="http://www.w3.org/1999/xhtml">
 <head>
 	<title>Local Development</title>
+	
+    <script src="https://babylonjs.azurewebsites.net/cannon.js"></script>
+    <script src="https://babylonjs.azurewebsites.net/Oimo.js"></script>
 	<script src="../assets/refs/dat.gui.min.js"></script>
 	<script src="../tools/DevLoader/BabylonLoader.js"></script>
 

+ 3 - 9
readme.md

@@ -14,15 +14,9 @@ Getting started? Play directly with the Babylon.js API via our [playground](http
 - http://cdn.babylonjs.com/2-5/babylon.core.js 
 
 ## Preview release
-You can help by testing or contributing to the next version.
-- **2.6-alpha** can be found [here](https://github.com/BabylonJS/Babylon.js/tree/master/dist/preview%20release)
-- We are not complicated people, but we still have some [coding guidelines](http://doc.babylonjs.com/generals/Approved_Naming_Conventions)
-- Before submitting your PR, just check that everything goes well by [creating the minified version](http://doc.babylonjs.com/generals/Creating_the_Mini-fied_Version)
-- Need help contributing, here are some links:
-  - [Gulp](https://github.com/BabylonJS/Babylon.js/tree/master/Tools/Gulp) to build from command line.
-  - [VSCode Editor](https://code.visualstudio.com/), Microsoft Code editor, see [Julian Chenard's post](http://pixelcodr.com/tutos/contribute/contribute.html) a Microsoft code editor.
-  - [Visual Studio](http://doc.babylonjs.com/generals/setup_visualStudio), Microsoft's IDE.
-  - [Forum thread](http://www.html5gamedevs.com/topic/20456-contributing-on-babylonjs/) for assistance from our very helpful family.
+
+**3.0-alpha** can be found [here](https://github.com/BabylonJS/Babylon.js/tree/master/dist/preview%20release)
+If you want to contribute, please read our [contribution guidelines](https://github.com/BabylonJS/Babylon.js/blob/master/contributing.md) first.
 
 ## Documentation
 - [Documentation](http://doc.babylonjs.com)

+ 40 - 5
src/Bones/babylon.bone.ts

@@ -203,13 +203,20 @@ module BABYLON {
 
             }else{
 
+                var wm:Matrix;
+
+                //mesh.getWorldMatrix() needs to be called before skeleton.computeAbsoluteTransforms()
+                if(mesh){
+                    wm = mesh.getWorldMatrix();
+                }
+
                 this._skeleton.computeAbsoluteTransforms();
                 var tmat = Tmp.Matrix[0];
                 var tvec = Tmp.Vector3[0];
 
                 if (mesh) {
                     tmat.copyFrom(this._parent.getAbsoluteTransform());
-                    tmat.multiplyToRef(mesh.getWorldMatrix(), tmat);
+                    tmat.multiplyToRef(wm, tmat);
                 }else {
                     tmat.copyFrom(this._parent.getAbsoluteTransform());
                 }
@@ -249,6 +256,13 @@ module BABYLON {
 
             }else{
 
+                var wm:Matrix;
+
+                //mesh.getWorldMatrix() needs to be called before skeleton.computeAbsoluteTransforms()
+                if(mesh){
+                    wm = mesh.getWorldMatrix();
+                }
+
                 this._skeleton.computeAbsoluteTransforms();
 
                 var tmat = Tmp.Matrix[0];
@@ -256,7 +270,7 @@ module BABYLON {
 
                 if (mesh) {
                     tmat.copyFrom(this._parent.getAbsoluteTransform());
-                    tmat.multiplyToRef(mesh.getWorldMatrix(), tmat);
+                    tmat.multiplyToRef(wm, tmat);
                 }else {
                     tmat.copyFrom(this._parent.getAbsoluteTransform());
                 }
@@ -754,6 +768,13 @@ module BABYLON {
          */
         public getDirectionToRef (localAxis: Vector3, mesh: AbstractMesh, result: Vector3): void {
 
+            var wm:Matrix;
+
+            //mesh.getWorldMatrix() needs to be called before skeleton.computeAbsoluteTransforms()
+            if(mesh){
+                wm = mesh.getWorldMatrix();
+            }
+
             this._skeleton.computeAbsoluteTransforms();
             
             var mat = Tmp.Matrix[0];
@@ -761,7 +782,7 @@ module BABYLON {
             mat.copyFrom(this.getAbsoluteTransform());
 
             if(mesh){
-                mat.multiplyToRef(mesh.getWorldMatrix(), mat);
+                mat.multiplyToRef(wm, mat);
             }
 
             Vector3.TransformNormalToRef(localAxis, mat, result);
@@ -923,13 +944,20 @@ module BABYLON {
          */
         public getAbsolutePositionFromLocalToRef(position:Vector3, mesh:AbstractMesh, result:Vector3): void{
 
+            var wm:Matrix;
+
+            //mesh.getWorldMatrix() needs to be called before skeleton.computeAbsoluteTransforms()
+            if(mesh){
+                wm = mesh.getWorldMatrix();
+            }
+
             this._skeleton.computeAbsoluteTransforms();
 
             var tmat = Tmp.Matrix[0];
             
             if (mesh) {
                 tmat.copyFrom(this.getAbsoluteTransform());
-                tmat.multiplyToRef(mesh.getWorldMatrix(), tmat);
+                tmat.multiplyToRef(wm, tmat);
             }else{
                 tmat = this.getAbsoluteTransform();
             }
@@ -962,6 +990,13 @@ module BABYLON {
          */
         public getLocalPositionFromAbsoluteToRef(position:Vector3, mesh:AbstractMesh, result:Vector3): void{
 
+            var wm:Matrix;
+
+            //mesh.getWorldMatrix() needs to be called before skeleton.computeAbsoluteTransforms()
+            if(mesh){
+                wm = mesh.getWorldMatrix();
+            }
+
             this._skeleton.computeAbsoluteTransforms();
 
             var tmat = Tmp.Matrix[0];
@@ -969,7 +1004,7 @@ module BABYLON {
             tmat.copyFrom(this.getAbsoluteTransform());
             
             if (mesh) {
-                tmat.multiplyToRef(mesh.getWorldMatrix(), tmat);
+                tmat.multiplyToRef(wm, tmat);
             }
 
             tmat.invert();

+ 258 - 30
src/Bones/babylon.boneLookController.ts

@@ -1,24 +1,116 @@
 module BABYLON {
     export class BoneLookController {
 
+        private static _tmpVecs: Vector3[] = [Vector3.Zero(), Vector3.Zero(), Vector3.Zero(),Vector3.Zero(), Vector3.Zero(), Vector3.Zero(), Vector3.Zero(), Vector3.Zero(), Vector3.Zero(), Vector3.Zero()];
+        private static _tmpQuat = Quaternion.Identity();
+        private static _tmpMat1 = Matrix.Identity();
+        private static _tmpMat2 = Matrix.Identity();
+
         public target: Vector3;
         public mesh: AbstractMesh;
         public bone: Bone;
         public upAxis: Vector3 = Vector3.Up();
+        public slerpAmount = 1;
 
-        public adjustYaw = 0;
-        public adjustPitch = 0;
-        public adjustRoll = 0;
-        
-        private _tmpVec1 = Vector3.Zero();
-        private _tmpVec2 = Vector3.Zero();
-        private _tmpVec3 = Vector3.Zero();
-        private _tmpVec4 = Vector3.Zero();
-        
-        private _tmpMat1 = Matrix.Identity();
-        private _tmpMat2 = Matrix.Identity();
+        private _adjustRotY = 0;
+        private _adjustRotX = 0;
+        private _adjustRotZ = 0;
+        private _minRotY:number;
+        private _maxRotY:number;
+        private _minRotX:number;
+        private _maxRotX:number;
+        private _minRotYSin:number;
+        private _minRotYCos:number;
+        private _maxRotYSin:number;
+        private _maxRotYCos:number;
+        private _minRotXTan:number;
+        private _maxRotXTan:number;
+        private _minRotZ:number;
+        private _maxRotZ:number;
+        private _minRotZSin:number;
+        private _minRotZCos:number;
+        private _maxRotZSin:number;
+        private _maxRotZCos:number;
+        private _boneQuat:Quaternion = Quaternion.Identity();
+        private _slerping = false;
 
-        constructor(mesh: AbstractMesh, bone: Bone, target: Vector3, options?: {adjustYaw?: number, adjustPitch?: number, adjustRoll?: number} ){
+        get minRotationY():number{
+            return this._minRotY - this._adjustRotY;
+        }
+
+        set minRotationY(value:number){
+            this._minRotY = value + this._adjustRotY;
+            this._minRotYSin = Math.sin(this._minRotY);
+            this._minRotYCos = Math.cos(this._minRotY);
+        }
+
+        get maxRoationY():number{
+            return this._maxRotY - this._adjustRotY;
+        }
+
+        set maxRotationY(value:number){
+            this._maxRotY = value + this._adjustRotY;
+            this._maxRotYSin = Math.sin(this._maxRotY);
+            this._maxRotYCos = Math.cos(this._maxRotY);
+        }
+
+        get minRotationX():number{
+            return this._minRotX - this._adjustRotX;
+        }
+
+        set minRotationX(value:number){
+            this._minRotX = value + this._adjustRotX;
+            this._minRotXTan = Math.tan(this._minRotX);
+        }
+
+        get maxRotationX():number{
+            return this._maxRotX - this._adjustRotX;
+        }
+
+        set maxRotationX(value:number){
+            this._maxRotX = value + this._adjustRotX;
+            this._maxRotXTan = Math.tan(this._maxRotX);
+        }
+
+        get minRotationZ():number{
+            return this._minRotZ - this._adjustRotZ;
+        }
+
+        set minRotationZ(value:number){
+            this._minRotZ = value + this._adjustRotZ;
+            this._minRotZSin = Math.sin(this._minRotZ);
+            this._minRotZCos = Math.cos(this._minRotZ);
+        }
+
+        get maxRotationZ():number{
+            return this._maxRotZ - this._adjustRotZ;
+        }
+
+        set maxRotationZ(value:number){
+            this._maxRotZ = value + this._adjustRotZ;
+            this._maxRotZSin = Math.sin(this._maxRotZ);
+            this._maxRotZCos = Math.cos(this._maxRotZ);
+        }
+
+        constructor(mesh: AbstractMesh, 
+                    bone: Bone, 
+                    target: Vector3, 
+                    options?: { 
+                        adjustRotationX?: number, 
+                        adjustRotationY?: number, 
+                        adjustRotationZ?: number, 
+                        slerpAmount?: number, 
+                        maxRotationY?:number, 
+                        minRotationY?:number,
+                        maxRotationX?:number, 
+                        minRotationX?:number,
+                        maxRotationZ?:number, 
+                        minRotationZ?:number,
+                        adjustYaw?: number, 
+                        adjustPitch?: number, 
+                        adjustRoll?: number 
+                    } 
+                    ){
 
             this.mesh = mesh;
             this.bone = bone;
@@ -27,15 +119,55 @@ module BABYLON {
             if(options){
 
                 if(options.adjustYaw){
-                    this.adjustYaw = options.adjustYaw;
+                    this._adjustRotY = options.adjustYaw;
                 }
 
                 if(options.adjustPitch){
-                    this.adjustPitch = options.adjustPitch;
+                    this._adjustRotX = options.adjustPitch;
                 }
 
                 if(options.adjustRoll){
-                    this.adjustRoll = options.adjustRoll;
+                    this._adjustRotZ = options.adjustRoll;
+                }
+
+                if(options.adjustRotationY){
+                    this._adjustRotY = options.adjustRotationY;
+                }
+
+                if(options.adjustRotationX){
+                    this._adjustRotX = options.adjustRotationX;
+                }
+
+                if(options.adjustRotationZ){
+                    this._adjustRotZ = options.adjustRotationZ;
+                }
+
+                if(options.maxRotationY != undefined){
+                    this.maxRotationY = options.maxRotationY;
+                }
+
+                if(options.minRotationY != undefined){
+                    this.minRotationY = options.minRotationY;
+                }
+
+                if(options.maxRotationX != undefined){
+                    this.maxRotationX = options.maxRotationX;
+                }
+
+                if(options.minRotationX != undefined){
+                    this.minRotationX = options.minRotationX;
+                }
+
+                if(options.maxRotationZ != undefined){
+                    this.maxRotationZ = options.maxRotationZ;
+                }
+
+                if(options.minRotationZ != undefined){
+                    this.minRotationZ = options.minRotationZ;
+                }
+
+                if(options.slerpAmount != undefined){
+                    this.slerpAmount = options.slerpAmount;
                 }
 
             }
@@ -46,33 +178,129 @@ module BABYLON {
                 
             var bone = this.bone;
             var target = this.target;
+            var mat1 = BoneLookController._tmpMat1;
+            var mat2 = BoneLookController._tmpMat2;
 
-            var bonePos = this._tmpVec1;
-            var zaxis = this._tmpVec2;
-            var xaxis = this._tmpVec3;
-            var yaxis = this._tmpVec4;
-            var mat1 = this._tmpMat1;
-            var mat2 = this._tmpMat2;
+            var parentBone = bone.getParent();
 
-            bone.getAbsolutePositionToRef(this.mesh, bonePos);
+            if(parentBone){
+                if(this._maxRotX != undefined || this._minRotX != undefined){
+                    var localTarget = BoneLookController._tmpVecs[4];
+                    var _tmpVec5 = BoneLookController._tmpVecs[5];
+                    parentBone.getLocalPositionFromAbsoluteToRef(target, this.mesh, localTarget);
+                    bone.getPositionToRef(Space.LOCAL, null, _tmpVec5);
+                    localTarget.x -= _tmpVec5.x;
+                    localTarget.y -= _tmpVec5.y;
+                    localTarget.z -= _tmpVec5.z;
+                    var xzlen = Math.sqrt(localTarget.x*localTarget.x + localTarget.z*localTarget.z);
+                    var rotX = Math.atan2(localTarget.y, xzlen);
+
+                    if(rotX > this._maxRotX){
+                        localTarget.y = this._maxRotXTan*xzlen + _tmpVec5.y;
+                        parentBone.getAbsolutePositionFromLocalToRef(localTarget, this.mesh, localTarget);
+                        target = localTarget;
+                    }else if(rotX < this._minRotX){
+                        localTarget.y = this._minRotXTan*xzlen + _tmpVec5.y;
+                        parentBone.getAbsolutePositionFromLocalToRef(localTarget, this.mesh, localTarget);
+                        target = localTarget;
+                    }
+                }
+
+                if(this._maxRotY != undefined || this._minRotY != undefined){
+                    var localTarget = BoneLookController._tmpVecs[6];
+                    var _tmpVec7 = BoneLookController._tmpVecs[7];
+                    parentBone.getLocalPositionFromAbsoluteToRef(target, this.mesh, localTarget);
+                    bone.getPositionToRef(Space.LOCAL, null, _tmpVec7);
+                    localTarget.x -= _tmpVec7.x;
+                    localTarget.z -= _tmpVec7.z;
+                    var rotY = Math.atan2(localTarget.x, localTarget.z);
+                    
+                    if(rotY > this._maxRotY){
+                        var xzlen = Math.sqrt(localTarget.x*localTarget.x + localTarget.z*localTarget.z);
+                        localTarget.z = this._maxRotYCos*xzlen;
+                        localTarget.x = this._maxRotYSin*xzlen;
+                        parentBone.getAbsolutePositionFromLocalToRef(localTarget, this.mesh, localTarget);
+                        target = localTarget;
+                    }else if(rotY < this._minRotY){
+                        var xzlen = Math.sqrt(localTarget.x*localTarget.x + localTarget.z*localTarget.z);
+                        localTarget.z = this._minRotYCos*xzlen;
+                        localTarget.x = this._minRotYSin*xzlen;
+                        parentBone.getAbsolutePositionFromLocalToRef(localTarget, this.mesh, localTarget);
+                        target = localTarget;
+                    }
+                }
 
+                if(this._maxRotZ != undefined || this._minRotZ != undefined){
+                    var localTarget = BoneLookController._tmpVecs[8];
+                    var _tmpVec9 = BoneLookController._tmpVecs[9];
+                    parentBone.getLocalPositionFromAbsoluteToRef(target, this.mesh, localTarget);
+                    bone.getPositionToRef(Space.LOCAL, null, _tmpVec9);
+                    localTarget.x -= _tmpVec9.x;
+                    localTarget.y -= _tmpVec9.y;
+                    var rotZ = Math.atan2(localTarget.y, localTarget.x);
+                    
+                    if(rotZ > this._maxRotZ){
+                        var xylen = Math.sqrt(localTarget.x*localTarget.x + localTarget.y*localTarget.y);
+                        localTarget.x = this._maxRotZCos*xylen;
+                        localTarget.y = this._maxRotZSin*xylen;
+                        parentBone.getAbsolutePositionFromLocalToRef(localTarget, this.mesh, localTarget);
+                        target = localTarget;
+                    }else if(rotZ < this._minRotZ){
+                        var xylen = Math.sqrt(localTarget.x*localTarget.x + localTarget.y*localTarget.y);
+                        localTarget.x = this._minRotZCos*xylen;
+                        localTarget.y = this._minRotZSin*xylen;
+                        parentBone.getAbsolutePositionFromLocalToRef(localTarget, this.mesh, localTarget);
+                        target = localTarget;
+                    }
+                }
+
+
+            }
+
+            var bonePos = BoneLookController._tmpVecs[0];
+            var zaxis = BoneLookController._tmpVecs[1];
+            var xaxis = BoneLookController._tmpVecs[2];
+            var yaxis = BoneLookController._tmpVecs[3];
+            var _tmpQuat = BoneLookController._tmpQuat;
+
+            bone.getAbsolutePositionToRef(this.mesh, bonePos);
             target.subtractToRef(bonePos, zaxis);
             zaxis.normalize();
-
-            BABYLON.Vector3.CrossToRef(this.upAxis, zaxis, xaxis);
+            Vector3.CrossToRef(this.upAxis, zaxis, xaxis);
             xaxis.normalize();
-
-            BABYLON.Vector3.CrossToRef(zaxis, xaxis, yaxis);
+            Vector3.CrossToRef(zaxis, xaxis, yaxis);
             yaxis.normalize();
+            Matrix.FromXYZAxesToRef(xaxis, yaxis, zaxis, mat1);
+
+            if(xaxis.x === 0 && xaxis.y === 0 && xaxis.z === 0){
+                return;
+            }
+
+            if(yaxis.x === 0 && yaxis.y === 0 && yaxis.z === 0){
+                return;
+            }
 
-            BABYLON.Matrix.FromXYZAxesToRef(xaxis, yaxis, zaxis, mat1);
+            if(zaxis.x === 0 && zaxis.y === 0 && zaxis.z === 0){
+                return;
+            }
 
-            if (this.adjustYaw || this.adjustPitch || this.adjustRoll) {
-                BABYLON.Matrix.RotationYawPitchRollToRef(this.adjustYaw, this.adjustPitch, this.adjustRoll, mat2);
+            if (this._adjustRotY || this._adjustRotX || this._adjustRotZ) {
+                Matrix.RotationYawPitchRollToRef(this._adjustRotY, this._adjustRotX, this._adjustRotZ, mat2);
                 mat2.multiplyToRef(mat1, mat1);
             }
 
-            this.bone.setRotationMatrix(mat1, BABYLON.Space.WORLD, this.mesh);
+            if (this.slerpAmount < 1) {
+                if (!this._slerping) {
+                    this.bone.getRotationQuaternionToRef(Space.WORLD, this.mesh, this._boneQuat);
+                }
+                Quaternion.FromRotationMatrixToRef(mat1, _tmpQuat);
+                Quaternion.SlerpToRef(this._boneQuat, _tmpQuat, this.slerpAmount, this._boneQuat);
+                this.bone.setRotationQuaternion(this._boneQuat, Space.WORLD, this.mesh);
+                this._slerping = true;
+            } else {
+                this.bone.setRotationMatrix(mat1, Space.WORLD, this.mesh);
+                this._slerping = false;
+            }
 
         }
 

+ 1 - 1
src/Cameras/babylon.freeCamera.ts

@@ -181,7 +181,7 @@
             if (this.checkCollisions && this.getScene().collisionsEnabled) {
                 this._collideWithWorld(this.cameraDirection);
             } else {
-                this.position.addInPlace(this.cameraDirection);
+                super._updatePosition();
             }
         }
 

+ 10 - 0
src/Cameras/babylon.targetCamera.ts

@@ -142,6 +142,10 @@ module BABYLON {
             }
         }
 
+
+        /**
+         * Return the current target position of the camera. This value is expressed in local space.
+         */
         public getTarget(): Vector3 {
             return this._currentTarget;
         }
@@ -151,6 +155,12 @@ module BABYLON {
         }
 
         public _updatePosition(): void {
+            if (this.parent) {
+                this.parent.getWorldMatrix().invertToRef(Tmp.Matrix[0]);
+                Vector3.TransformNormalToRef(this.cameraDirection, Tmp.Matrix[0], Tmp.Vector3[0]);
+                this.position.addInPlace(Tmp.Vector3[0]);
+                return;
+            }
             this.position.addInPlace(this.cameraDirection);
         }
         public _checkInputs(): void {

+ 13 - 0
src/Materials/Textures/babylon.renderTargetTexture.ts

@@ -99,6 +99,7 @@
         private _currentRefreshId = -1;
         private _refreshRate = 1;
         private _textureMatrix: Matrix;
+        private _samples = 1;
         protected _renderTargetOptions: {
             generateMipMaps: boolean,
             type: number,
@@ -141,6 +142,18 @@
             this._renderingManager = new RenderingManager(scene);
         }
 
+        public get samples(): number {
+            return this._samples;
+        }
+
+        public set samples(value: number) {
+            if (this._samples === value) {
+                return;
+            }
+            
+            this._samples = this.getScene().getEngine().updateRenderTargetTextureSampleCount(this._texture, value);
+        }
+
         public resetRefreshCounter(): void {
             this._currentRefreshId = -1;
         }

+ 1 - 1
src/Materials/babylon.material.ts

@@ -215,7 +215,7 @@
 
             this._scene = scene || Engine.LastCreatedScene;
 
-            if (scene.useRightHandedSystem) {
+            if (this._scene.useRightHandedSystem) {
                 this.sideOrientation = Material.ClockWiseSideOrientation;
             } else {
                 this.sideOrientation = Material.CounterClockWiseSideOrientation;

+ 33 - 0
src/Mesh/babylon.groundMesh.ts

@@ -229,5 +229,38 @@ module BABYLON {
             }
             return this;
         }
+
+        public serialize(serializationObject: any): void {
+            super.serialize(serializationObject);
+            serializationObject.subdivisionsX = this._subdivisionsX;
+            serializationObject.subdivisionsY = this._subdivisionsY;
+
+            serializationObject.minX = this._minX;
+            serializationObject.maxX = this._maxX;
+
+            serializationObject.minZ = this._minZ;
+            serializationObject.maxZ = this._maxZ;
+
+            serializationObject.width = this._width;
+            serializationObject.height = this._height;
+        }
+
+        public static Parse(parsedMesh: any, scene: Scene): GroundMesh {
+            var result = new GroundMesh(parsedMesh.name, scene);
+
+            result._subdivisionsX = parsedMesh.subdivisionsX || 1;
+            result._subdivisionsY = parsedMesh.subdivisionsY || 1;
+
+            result._minX = parsedMesh.minX;
+            result._maxX = parsedMesh.maxX;
+
+            result._minZ = parsedMesh.minZ;
+            result._maxZ = parsedMesh.maxZ;
+
+            result._width = parsedMesh.width;
+            result._height = parsedMesh.height;
+
+            return result;
+        }
     }
 }

+ 132 - 1
src/Mesh/babylon.mesh.ts

@@ -1845,6 +1845,137 @@
             return this;
         }
 
+        public serialize(serializationObject: any): void {
+            serializationObject.name = this.name;
+            serializationObject.id = this.id;
+            serializationObject.type = this.getClassName();
+
+            if (Tags.HasTags(this)) {
+                serializationObject.tags = Tags.GetTags(this);
+            }
+
+            serializationObject.position = this.position.asArray();
+
+            if (this.rotationQuaternion) {
+                serializationObject.rotationQuaternion = this.rotationQuaternion.asArray();
+            } else if (this.rotation) {
+                serializationObject.rotation = this.rotation.asArray();
+            }
+
+            serializationObject.scaling = this.scaling.asArray();
+            serializationObject.localMatrix = this.getPivotMatrix().asArray();
+
+            serializationObject.isEnabled = this.isEnabled();
+            serializationObject.isVisible = this.isVisible;
+            serializationObject.infiniteDistance = this.infiniteDistance;
+            serializationObject.pickable = this.isPickable;
+
+            serializationObject.receiveShadows = this.receiveShadows;
+
+            serializationObject.billboardMode = this.billboardMode;
+            serializationObject.visibility = this.visibility;
+
+            serializationObject.checkCollisions = this.checkCollisions;
+            serializationObject.isBlocker = this.isBlocker;
+
+            // Parent
+            if (this.parent) {
+                serializationObject.parentId = this.parent.id;
+            }
+
+            // Geometry
+            var geometry = this._geometry;
+            if (geometry) {
+                var geometryId = geometry.id;
+                serializationObject.geometryId = geometryId;
+
+                // SubMeshes
+                serializationObject.subMeshes = [];
+                for (var subIndex = 0; subIndex < this.subMeshes.length; subIndex++) {
+                    var subMesh = this.subMeshes[subIndex];
+
+                    serializationObject.subMeshes.push({
+                        materialIndex: subMesh.materialIndex,
+                        verticesStart: subMesh.verticesStart,
+                        verticesCount: subMesh.verticesCount,
+                        indexStart: subMesh.indexStart,
+                        indexCount: subMesh.indexCount
+                    });
+                }
+            }
+
+            // Material
+            if (this.material) {
+                serializationObject.materialId = this.material.id;
+            } else {
+                this.material = null;
+            }
+
+            // Skeleton
+            if (this.skeleton) {
+                serializationObject.skeletonId = this.skeleton.id;
+            }
+
+            // Physics
+            //TODO implement correct serialization for physics impostors.
+            if (this.getPhysicsImpostor()) {
+                serializationObject.physicsMass = this.getPhysicsMass();
+                serializationObject.physicsFriction = this.getPhysicsFriction();
+                serializationObject.physicsRestitution = this.getPhysicsRestitution();
+                serializationObject.physicsImpostor = this.getPhysicsImpostor().type;
+            }
+
+            // Metadata
+            if (this.metadata) {
+                serializationObject.metadata = this.metadata;
+            }
+
+            // Instances
+            serializationObject.instances = [];
+            for (var index = 0; index < this.instances.length; index++) {
+                var instance = this.instances[index];
+                var serializationInstance: any = {
+                    name: instance.name,
+                    position: instance.position.asArray(),
+                    scaling: instance.scaling.asArray()
+                };
+                if (instance.rotationQuaternion) {
+                    serializationInstance.rotationQuaternion = instance.rotationQuaternion.asArray();
+                } else if (instance.rotation) {
+                    serializationInstance.rotation = instance.rotation.asArray();
+                }
+                serializationObject.instances.push(serializationInstance);
+
+                // Animations
+                Animation.AppendSerializedAnimations(instance, serializationInstance);
+                serializationInstance.ranges = instance.serializeAnimationRanges();
+            }
+
+            // Animations
+            Animation.AppendSerializedAnimations(this, serializationObject);
+            serializationObject.ranges = this.serializeAnimationRanges();
+
+            // Layer mask
+            serializationObject.layerMask = this.layerMask;
+
+            // Alpha
+            serializationObject.alphaIndex = this.alphaIndex;
+            serializationObject.hasVertexAlpha = this.hasVertexAlpha;
+            
+            // Overlay
+            serializationObject.overlayAlpha = this.overlayAlpha;
+            serializationObject.overlayColor = this.overlayColor.asArray();
+            serializationObject.renderOverlay = this.renderOverlay;
+
+            // Fog
+            serializationObject.applyFog = this.applyFog;
+
+            // Action Manager
+            if (this.actionManager) {
+                serializationObject.actions = this.actionManager.serialize(this.name);
+            }
+        }
+
         // Statics
         /**
          * Returns a new Mesh object what is a deep copy of the passed mesh.   
@@ -1855,7 +1986,7 @@
             var mesh : Mesh;
 
             if (parsedMesh.type && parsedMesh.type === "GroundMesh") {
-                mesh = new GroundMesh(parsedMesh.name, scene);
+                mesh = GroundMesh.Parse(parsedMesh, scene);
             } else {
                 mesh = new Mesh(parsedMesh.name, scene);
             }

+ 8 - 0
src/Probes/babylon.reflectionProbe.ts

@@ -59,6 +59,14 @@
             this._projectionMatrix = Matrix.PerspectiveFovLH(Math.PI / 2, 1, scene.activeCamera.minZ, scene.activeCamera.maxZ);
         }
 
+        public get samples(): number {
+            return this._renderTargetTexture.samples;
+        }
+
+        public set samples(value: number) {
+            this._renderTargetTexture.samples = value;
+        }
+
         public get refreshRate(): number {
             return this._renderTargetTexture.refreshRate;
         }

+ 2 - 2
src/Tools/babylon.database.ts

@@ -43,7 +43,7 @@ module BABYLON {
         }
 
         static ReturnFullUrlLocation = (url: string): string => {
-            if (url.indexOf("http:/") === -1) {
+            if (url.indexOf("http:/") === -1 && url.indexOf("https:/") === -1) {
                 return (Database.parseURL(window.location.href) + url);
             }
             else {
@@ -584,4 +584,4 @@ module BABYLON {
             }
         }
     }
-}
+}

+ 11 - 127
src/Tools/babylon.sceneSerializer.ts

@@ -43,138 +43,18 @@
     var serializeMesh = (mesh: Mesh, serializationScene: any): any => {
         var serializationObject: any = {};
 
-        serializationObject.name = mesh.name;
-        serializationObject.id = mesh.id;
-        serializationObject.type = mesh.getClassName();
-
-        if (Tags.HasTags(mesh)) {
-            serializationObject.tags = Tags.GetTags(mesh);
-        }
-
-        serializationObject.position = mesh.position.asArray();
-
-        if (mesh.rotationQuaternion) {
-            serializationObject.rotationQuaternion = mesh.rotationQuaternion.asArray();
-        } else if (mesh.rotation) {
-            serializationObject.rotation = mesh.rotation.asArray();
-        }
-
-        serializationObject.scaling = mesh.scaling.asArray();
-        serializationObject.localMatrix = mesh.getPivotMatrix().asArray();
-
-        serializationObject.isEnabled = mesh.isEnabled();
-        serializationObject.isVisible = mesh.isVisible;
-        serializationObject.infiniteDistance = mesh.infiniteDistance;
-        serializationObject.pickable = mesh.isPickable;
-
-        serializationObject.receiveShadows = mesh.receiveShadows;
-
-        serializationObject.billboardMode = mesh.billboardMode;
-        serializationObject.visibility = mesh.visibility;
-
-        serializationObject.checkCollisions = mesh.checkCollisions;
-        serializationObject.isBlocker = mesh.isBlocker;
-
-        // Parent
-        if (mesh.parent) {
-            serializationObject.parentId = mesh.parent.id;
-        }
-
-        // Geometry
-        var geometry = mesh._geometry;
+        // Geometry      
+        var geometry = mesh._geometry;      
         if (geometry) {
-            var geometryId = geometry.id;
-            serializationObject.geometryId = geometryId;
-
-            if (!mesh.getScene().getGeometryByID(geometryId)) {
-                // geometry was in the memory but not added to the scene, nevertheless it's better to serialize to be able to reload the mesh with its geometry
+            if (!mesh.getScene().getGeometryByID(geometry.id)) {
+                // Geometry was in the memory but not added to the scene, nevertheless it's better to serialize to be able to reload the mesh with its geometry
                 serializeGeometry(geometry, serializationScene.geometries);
             }
-
-            // SubMeshes
-            serializationObject.subMeshes = [];
-            for (var subIndex = 0; subIndex < mesh.subMeshes.length; subIndex++) {
-                var subMesh = mesh.subMeshes[subIndex];
-
-                serializationObject.subMeshes.push({
-                    materialIndex: subMesh.materialIndex,
-                    verticesStart: subMesh.verticesStart,
-                    verticesCount: subMesh.verticesCount,
-                    indexStart: subMesh.indexStart,
-                    indexCount: subMesh.indexCount
-                });
-            }
-        }
-
-        // Material
-        if (mesh.material) {
-            serializationObject.materialId = mesh.material.id;
-        } else {
-            mesh.material = null;
         }
 
-        // Skeleton
-        if (mesh.skeleton) {
-            serializationObject.skeletonId = mesh.skeleton.id;
-        }
-
-        // Physics
-        //TODO implement correct serialization for physics impostors.
-        if (mesh.getPhysicsImpostor()) {
-            serializationObject.physicsMass = mesh.getPhysicsMass();
-            serializationObject.physicsFriction = mesh.getPhysicsFriction();
-            serializationObject.physicsRestitution = mesh.getPhysicsRestitution();
-            serializationObject.physicsImpostor = mesh.getPhysicsImpostor().type;
-        }
-
-        // Metadata
-        if (mesh.metadata) {
-            serializationObject.metadata = mesh.metadata;
-        }
-
-        // Instances
-        serializationObject.instances = [];
-        for (var index = 0; index < mesh.instances.length; index++) {
-            var instance = mesh.instances[index];
-            var serializationInstance: any = {
-                name: instance.name,
-                position: instance.position.asArray(),
-                scaling: instance.scaling.asArray()
-            };
-            if (instance.rotationQuaternion) {
-                serializationInstance.rotationQuaternion = instance.rotationQuaternion.asArray();
-            } else if (instance.rotation) {
-                serializationInstance.rotation = instance.rotation.asArray();
-            }
-            serializationObject.instances.push(serializationInstance);
-
-            // Animations
-            Animation.AppendSerializedAnimations(instance, serializationInstance);
-            serializationInstance.ranges = instance.serializeAnimationRanges();
-        }
-
-        // Animations
-        Animation.AppendSerializedAnimations(mesh, serializationObject);
-        serializationObject.ranges = mesh.serializeAnimationRanges();
-
-        // Layer mask
-        serializationObject.layerMask = mesh.layerMask;
-
-        // Alpha
-        serializationObject.alphaIndex = mesh.alphaIndex;
-        serializationObject.hasVertexAlpha = mesh.hasVertexAlpha;
-        
-        // Overlay
-        serializationObject.overlayAlpha = mesh.overlayAlpha;
-        serializationObject.overlayColor = mesh.overlayColor.asArray();
-        serializationObject.renderOverlay = mesh.renderOverlay;
-
-        // Fog
-        serializationObject.applyFog = mesh.applyFog;
-
-        // Action Manager
-        if (mesh.actionManager) {
-            serializationObject.actions = mesh.actionManager.serialize(mesh.name);
+        // Custom
+        if (mesh.serialize) {
+            mesh.serialize(serializationObject);
         }
 
         return serializationObject;
@@ -236,6 +116,8 @@
         public static Serialize(scene: Scene): any {
             var serializationObject: any = {};
 
+            SceneSerializer.ClearCache();
+
             // Scene
             serializationObject.useDelayedTextureLoading = scene.useDelayedTextureLoading;
             serializationObject.autoClear = scene.autoClear;
@@ -402,6 +284,8 @@
         public static SerializeMesh(toSerialize: any /* Mesh || Mesh[] */, withParents: boolean = false, withChildren: boolean = false): any {
             var serializationObject: any = {};
 
+            SceneSerializer.ClearCache();
+
             toSerialize = (toSerialize instanceof Array) ? toSerialize : [toSerialize];
 
             if (withParents || withChildren) {

+ 1 - 1
src/Tools/babylon.tools.ts

@@ -304,7 +304,7 @@
                     case "function":
                         var result = Tools.CorsBehavior(url);
                         if (result) {
-                            return result;
+                            img.crossOrigin = result;
                         }
                         break;
                     case "string":

+ 107 - 57
src/babylon.engine.ts

@@ -408,7 +408,7 @@
         }
 
         public static get Version(): string {
-            return "2.6-alpha";
+            return "3.0-alpha";
         }
 
         // Updatable statics so stick with vars here
@@ -1216,10 +1216,9 @@
 
         public bindFramebuffer(texture: WebGLTexture, faceIndex?: number, requiredWidth?: number, requiredHeight?: number): void {
             this._currentRenderTarget = texture;
-            this.bindUnboundFramebuffer(texture._framebuffer);
+            this.bindUnboundFramebuffer(texture._MSAAFramebuffer ? texture._MSAAFramebuffer : texture._framebuffer);
             var gl = this._gl;
             if (texture.isCube) {
-
                 gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_CUBE_MAP_POSITIVE_X + faceIndex, texture, 0);
             }
 
@@ -1237,8 +1236,19 @@
 
         public unBindFramebuffer(texture: WebGLTexture, disableGenerateMipMaps = false): void {
             this._currentRenderTarget = null;
+
+            // If MSAA, we need to bitblt back to main texture
+            var gl = this._gl;
+
+            if (texture._MSAAFramebuffer) {
+                gl.bindFramebuffer(gl.READ_FRAMEBUFFER, texture._MSAAFramebuffer);
+                gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, texture._framebuffer);
+                gl.blitFramebuffer( 0, 0, texture._width, texture._height, 
+                                    0, 0, texture._width, texture._height,
+                                    gl.COLOR_BUFFER_BIT, gl.NEAREST);
+            }
+
             if (texture.generateMipMaps && !disableGenerateMipMaps) {
-                var gl = this._gl;
                 this._bindTextureDirectly(gl.TEXTURE_2D, texture);
                 gl.generateMipmap(gl.TEXTURE_2D);
                 this._bindTextureDirectly(gl.TEXTURE_2D, null);
@@ -1995,7 +2005,7 @@
                     this._alphaState.alphaBlend = false;
                     break;
                 case Engine.ALPHA_PREMULTIPLIED:
-                    this._alphaState.setAlphaBlendFunctionParameters(this._gl.ONE, this._gl.ONE_MINUS_SRC_ALPHA, this._gl.ONE, this._gl.ONE_MINUS_SRC_ALPHA);
+                    this._alphaState.setAlphaBlendFunctionParameters(this._gl.ONE, this._gl.ONE_MINUS_SRC_ALPHA, this._gl.ONE, this._gl.ONE);
                     this._alphaState.alphaBlend = true;
                     break;
                 case Engine.ALPHA_COMBINE:
@@ -2467,33 +2477,13 @@
 
             gl.texImage2D(gl.TEXTURE_2D, 0, this._getRGBABufferInternalSizedFormat(type), width, height, 0, gl.RGBA, this._getWebGLTextureType(type), null);
 
-            var depthStencilBuffer: WebGLRenderbuffer;
-
-            // Create the depth/stencil buffer
-            if (generateStencilBuffer) {
-                depthStencilBuffer = gl.createRenderbuffer();
-                gl.bindRenderbuffer(gl.RENDERBUFFER, depthStencilBuffer);
-                gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_STENCIL, width, height);
-            }
-            else if (generateDepthBuffer) {
-                depthStencilBuffer = gl.createRenderbuffer();
-                gl.bindRenderbuffer(gl.RENDERBUFFER, depthStencilBuffer);
-                gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_COMPONENT16, width, height);
-            }
-
             // Create the framebuffer
             var framebuffer = gl.createFramebuffer();
             this.bindUnboundFramebuffer(framebuffer);
-
-            // Manage attachments
-            if (generateStencilBuffer) {
-                gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, gl.RENDERBUFFER, depthStencilBuffer);
-            }
-            else if (generateDepthBuffer) {
-                gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, depthStencilBuffer);
-            }
             gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0);
 
+            texture._depthStencilBuffer = this._setupFramebufferDepthAttachments(generateStencilBuffer, generateDepthBuffer, width, height);
+
             if (generateMipMaps) {
                 this._gl.generateMipmap(this._gl.TEXTURE_2D);
             }
@@ -2504,9 +2494,6 @@
             this.bindUnboundFramebuffer(null);
 
             texture._framebuffer = framebuffer;
-            if (generateDepthBuffer) {
-                texture._depthBuffer = depthStencilBuffer;
-            }
             texture._baseWidth = width;
             texture._baseHeight = height;
             texture._width = width;
@@ -2516,6 +2503,8 @@
             texture.references = 1;
             texture.samplingMode = samplingMode;
             texture.type = type;
+            texture._generateDepthBuffer = generateDepthBuffer;
+            texture._generateStencilBuffer = generateStencilBuffer;
 
             this.resetTextureCache();
 
@@ -2524,6 +2513,83 @@
             return texture;
         }
 
+        private _setupFramebufferDepthAttachments(generateStencilBuffer: boolean, generateDepthBuffer: boolean, width: number, height: number, samples = 1): WebGLRenderbuffer {
+            var depthStencilBuffer: WebGLRenderbuffer = null;
+            var gl = this._gl;
+
+            // Create the depth/stencil buffer
+            if (generateStencilBuffer) {
+                depthStencilBuffer = gl.createRenderbuffer();
+                gl.bindRenderbuffer(gl.RENDERBUFFER, depthStencilBuffer);
+
+                if (samples > 1) {
+                    gl.renderbufferStorageMultisample(gl.RENDERBUFFER, samples, gl.DEPTH_STENCIL, width, height);
+                } else {
+                    gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_STENCIL, width, height);
+                }
+
+                gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, gl.RENDERBUFFER, depthStencilBuffer);
+            }
+            else if (generateDepthBuffer) {
+                depthStencilBuffer = gl.createRenderbuffer();
+                gl.bindRenderbuffer(gl.RENDERBUFFER, depthStencilBuffer);
+
+                if (samples > 1) {
+                    gl.renderbufferStorageMultisample(gl.RENDERBUFFER, samples, gl.DEPTH_COMPONENT16, width, height);
+                } else {
+                    gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_COMPONENT16, width, height);
+                }
+
+                gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, depthStencilBuffer);
+            }
+
+            return depthStencilBuffer;
+        }
+
+        public updateRenderTargetTextureSampleCount(texture: WebGLTexture, samples: number) : number {
+            if (this.webGLVersion < 2) {
+                return 1;
+            }
+            var gl = this._gl;
+
+            samples = Math.min(samples, gl.getParameter(gl.MAX_SAMPLES));
+
+            // Dispose previous render buffers
+            if (texture._depthStencilBuffer) {
+                gl.deleteRenderbuffer(texture._depthStencilBuffer);
+            }
+
+            if (texture._MSAAFramebuffer) {
+                gl.deleteFramebuffer(texture._MSAAFramebuffer);
+            }
+
+            if (texture._MSAARenderBuffer) {
+                gl.deleteRenderbuffer(texture._MSAARenderBuffer);
+            }
+
+            if (samples > 1) {
+                texture._MSAAFramebuffer = gl.createFramebuffer();
+                this.bindUnboundFramebuffer(texture._MSAAFramebuffer);
+
+                var colorRenderbuffer = gl.createRenderbuffer();
+                gl.bindRenderbuffer(gl.RENDERBUFFER, colorRenderbuffer);
+                gl.renderbufferStorageMultisample(gl.RENDERBUFFER, samples, gl.RGBA8, texture._width, texture._height);
+
+                gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, colorRenderbuffer);
+
+                texture._MSAARenderBuffer = colorRenderbuffer;
+            } else {
+                this.bindUnboundFramebuffer(texture._framebuffer);
+            }
+
+            texture._depthStencilBuffer = this._setupFramebufferDepthAttachments(texture._generateStencilBuffer, texture._generateDepthBuffer, texture._width, texture._height, samples);
+
+            gl.bindRenderbuffer(gl.RENDERBUFFER, null);
+            this.bindUnboundFramebuffer(null);
+
+            return samples;
+        }
+
         public createRenderTargetCubeTexture(size: number, options?: any): WebGLTexture {
             var gl = this._gl;
 
@@ -2563,32 +2629,11 @@
             gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
             gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
 
-            // Create the depth buffer
-            var depthStencilBuffer: WebGLRenderbuffer;
-
-            // Create the depth/stencil buffer
-            if (generateStencilBuffer) {
-                depthStencilBuffer = gl.createRenderbuffer();
-                gl.bindRenderbuffer(gl.RENDERBUFFER, depthStencilBuffer);
-                gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_STENCIL, size, size);
-            }
-            else if (generateDepthBuffer) {
-                depthStencilBuffer = gl.createRenderbuffer();
-                gl.bindRenderbuffer(gl.RENDERBUFFER, depthStencilBuffer);
-                gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_COMPONENT16, size, size);
-            }
-
             // Create the framebuffer
             var framebuffer = gl.createFramebuffer();
             this.bindUnboundFramebuffer(framebuffer);
 
-            // Manage attachments
-            if (generateStencilBuffer) {
-                gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, gl.RENDERBUFFER, depthStencilBuffer);
-            }
-            else if (generateDepthBuffer) {
-                gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, depthStencilBuffer);
-            }
+            texture._depthStencilBuffer = this._setupFramebufferDepthAttachments(generateStencilBuffer, generateDepthBuffer, size, size);
 
             // Mipmaps
             if (texture.generateMipMaps) {
@@ -2602,9 +2647,6 @@
             this.bindUnboundFramebuffer(null);
 
             texture._framebuffer = framebuffer;
-            if (generateDepthBuffer) {
-                texture._depthBuffer = depthStencilBuffer;
-            }
             texture._width = size;
             texture._height = size;
             texture.isReady = true;
@@ -2918,8 +2960,16 @@
                 gl.deleteFramebuffer(texture._framebuffer);
             }
 
-            if (texture._depthBuffer) {
-                gl.deleteRenderbuffer(texture._depthBuffer);
+            if (texture._depthStencilBuffer) {
+                gl.deleteRenderbuffer(texture._depthStencilBuffer);
+            }
+
+            if (texture._MSAAFramebuffer) {
+                gl.deleteFramebuffer(texture._MSAAFramebuffer);
+            }
+
+            if (texture._MSAARenderBuffer) {
+                gl.deleteRenderbuffer(texture._MSAARenderBuffer);
             }
 
             gl.deleteTexture(texture);

+ 13 - 1
src/babylon.mixins.ts

@@ -39,6 +39,14 @@ interface WebGLRenderingContext {
     createVertexArray(): any;
     bindVertexArray(vao: WebGLVertexArrayObject): void;
     deleteVertexArray(vao: WebGLVertexArrayObject): void;
+
+    blitFramebuffer(srcX0 : number, srcY0 : number, srcX1 : number, srcY1 : number, dstX0 : number, dstY0 : number, dstX1 : number, dstY1 : number, mask : number, filter : number) : void;
+    renderbufferStorageMultisample(target : number, samples : number, internalformat : number, width : number, height : number) : void;
+
+    MAX_SAMPLES: number;
+    RGBA8: number;
+    READ_FRAMEBUFFER : number;
+    DRAW_FRAMEBUFFER : number;
 }
 
 interface HTMLURL {
@@ -91,11 +99,15 @@ interface WebGLTexture {
     _workingCanvas: HTMLCanvasElement;
     _workingContext: CanvasRenderingContext2D;
     _framebuffer: WebGLFramebuffer;
-    _depthBuffer: WebGLRenderbuffer;
+    _depthStencilBuffer: WebGLRenderbuffer;
+    _MSAAFramebuffer: WebGLFramebuffer;
+    _MSAARenderBuffer: WebGLRenderbuffer;
     _cachedCoordinatesMode: number;
     _cachedWrapU: number;
     _cachedWrapV: number;
     _isDisabled: boolean;
+    _generateStencilBuffer: boolean;
+    _generateDepthBuffer: boolean;
 }
 
 interface WebGLBuffer {