瀏覽代碼

Merge remote-tracking branch 'upstream/master' into PMREMGenerator

Sebastien Vandenberghe 9 年之前
父節點
當前提交
8892c28058

+ 3 - 1
Tools/Gulp/config.json

@@ -21,7 +21,9 @@
       "../../src/Tools/babylon.tools.tga.js",
       "../../src/Tools/babylon.smartArray.js",
       "../../src/Tools/babylon.smartCollection.js",
-      "../../src/Tools/babylon.tools.js",
+      "../../src/Tools/babylon.tools.js",      
+      "../../src/states/babylon.alphaCullingState.js",
+      "../../src/states/babylon.depthCullingState.js",
       "../../src/babylon.engine.js",
       "../../src/babylon.node.js",
       "../../src/Tools/babylon.filesInput.js",

文件差異過大導致無法顯示
+ 17 - 17
dist/preview release/babylon.core.js


文件差異過大導致無法顯示
+ 1264 - 1257
dist/preview release/babylon.d.ts


文件差異過大導致無法顯示
+ 24 - 24
dist/preview release/babylon.js


+ 247 - 231
dist/preview release/babylon.max.js

@@ -5042,247 +5042,261 @@ var BABYLON;
 
 var BABYLON;
 (function (BABYLON) {
-    var _DepthCullingState = (function () {
-        function _DepthCullingState() {
-            this._isDepthTestDirty = false;
-            this._isDepthMaskDirty = false;
-            this._isDepthFuncDirty = false;
-            this._isCullFaceDirty = false;
-            this._isCullDirty = false;
-            this._isZOffsetDirty = false;
-        }
-        Object.defineProperty(_DepthCullingState.prototype, "isDirty", {
-            get: function () {
-                return this._isDepthFuncDirty || this._isDepthTestDirty || this._isDepthMaskDirty || this._isCullFaceDirty || this._isCullDirty || this._isZOffsetDirty;
-            },
-            enumerable: true,
-            configurable: true
-        });
-        Object.defineProperty(_DepthCullingState.prototype, "zOffset", {
-            get: function () {
-                return this._zOffset;
-            },
-            set: function (value) {
-                if (this._zOffset === value) {
-                    return;
-                }
-                this._zOffset = value;
-                this._isZOffsetDirty = true;
-            },
-            enumerable: true,
-            configurable: true
-        });
-        Object.defineProperty(_DepthCullingState.prototype, "cullFace", {
-            get: function () {
-                return this._cullFace;
-            },
-            set: function (value) {
-                if (this._cullFace === value) {
-                    return;
-                }
-                this._cullFace = value;
-                this._isCullFaceDirty = true;
-            },
-            enumerable: true,
-            configurable: true
-        });
-        Object.defineProperty(_DepthCullingState.prototype, "cull", {
-            get: function () {
-                return this._cull;
-            },
-            set: function (value) {
-                if (this._cull === value) {
-                    return;
-                }
-                this._cull = value;
-                this._isCullDirty = true;
-            },
-            enumerable: true,
-            configurable: true
-        });
-        Object.defineProperty(_DepthCullingState.prototype, "depthFunc", {
-            get: function () {
-                return this._depthFunc;
-            },
-            set: function (value) {
-                if (this._depthFunc === value) {
-                    return;
-                }
-                this._depthFunc = value;
-                this._isDepthFuncDirty = true;
-            },
-            enumerable: true,
-            configurable: true
-        });
-        Object.defineProperty(_DepthCullingState.prototype, "depthMask", {
-            get: function () {
-                return this._depthMask;
-            },
-            set: function (value) {
-                if (this._depthMask === value) {
+    var Internals;
+    (function (Internals) {
+        var _AlphaState = (function () {
+            function _AlphaState() {
+                this._isAlphaBlendDirty = false;
+                this._isBlendFunctionParametersDirty = false;
+                this._alphaBlend = false;
+                this._blendFunctionParameters = new Array(4);
+            }
+            Object.defineProperty(_AlphaState.prototype, "isDirty", {
+                get: function () {
+                    return this._isAlphaBlendDirty || this._isBlendFunctionParametersDirty;
+                },
+                enumerable: true,
+                configurable: true
+            });
+            Object.defineProperty(_AlphaState.prototype, "alphaBlend", {
+                get: function () {
+                    return this._alphaBlend;
+                },
+                set: function (value) {
+                    if (this._alphaBlend === value) {
+                        return;
+                    }
+                    this._alphaBlend = value;
+                    this._isAlphaBlendDirty = true;
+                },
+                enumerable: true,
+                configurable: true
+            });
+            _AlphaState.prototype.setAlphaBlendFunctionParameters = function (value0, value1, value2, value3) {
+                if (this._blendFunctionParameters[0] === value0 &&
+                    this._blendFunctionParameters[1] === value1 &&
+                    this._blendFunctionParameters[2] === value2 &&
+                    this._blendFunctionParameters[3] === value3) {
                     return;
                 }
-                this._depthMask = value;
-                this._isDepthMaskDirty = true;
-            },
-            enumerable: true,
-            configurable: true
-        });
-        Object.defineProperty(_DepthCullingState.prototype, "depthTest", {
-            get: function () {
-                return this._depthTest;
-            },
-            set: function (value) {
-                if (this._depthTest === value) {
+                this._blendFunctionParameters[0] = value0;
+                this._blendFunctionParameters[1] = value1;
+                this._blendFunctionParameters[2] = value2;
+                this._blendFunctionParameters[3] = value3;
+                this._isBlendFunctionParametersDirty = true;
+            };
+            _AlphaState.prototype.reset = function () {
+                this._alphaBlend = false;
+                this._blendFunctionParameters[0] = null;
+                this._blendFunctionParameters[1] = null;
+                this._blendFunctionParameters[2] = null;
+                this._blendFunctionParameters[3] = null;
+                this._isAlphaBlendDirty = true;
+                this._isBlendFunctionParametersDirty = false;
+            };
+            _AlphaState.prototype.apply = function (gl) {
+                if (!this.isDirty) {
                     return;
                 }
-                this._depthTest = value;
-                this._isDepthTestDirty = true;
-            },
-            enumerable: true,
-            configurable: true
-        });
-        _DepthCullingState.prototype.reset = function () {
-            this._depthMask = true;
-            this._depthTest = true;
-            this._depthFunc = null;
-            this._cull = null;
-            this._cullFace = null;
-            this._zOffset = 0;
-            this._isDepthTestDirty = true;
-            this._isDepthMaskDirty = true;
-            this._isDepthFuncDirty = false;
-            this._isCullFaceDirty = false;
-            this._isCullDirty = false;
-            this._isZOffsetDirty = false;
-        };
-        _DepthCullingState.prototype.apply = function (gl) {
-            if (!this.isDirty) {
-                return;
-            }
-            // Cull
-            if (this._isCullDirty) {
-                if (this.cull) {
-                    gl.enable(gl.CULL_FACE);
+                // Alpha blend
+                if (this._isAlphaBlendDirty) {
+                    if (this._alphaBlend) {
+                        gl.enable(gl.BLEND);
+                    }
+                    else {
+                        gl.disable(gl.BLEND);
+                    }
+                    this._isAlphaBlendDirty = false;
                 }
-                else {
-                    gl.disable(gl.CULL_FACE);
+                // Alpha function
+                if (this._isBlendFunctionParametersDirty) {
+                    gl.blendFuncSeparate(this._blendFunctionParameters[0], this._blendFunctionParameters[1], this._blendFunctionParameters[2], this._blendFunctionParameters[3]);
+                    this._isBlendFunctionParametersDirty = false;
                 }
+            };
+            return _AlphaState;
+        })();
+        Internals._AlphaState = _AlphaState;
+    })(Internals = BABYLON.Internals || (BABYLON.Internals = {}));
+})(BABYLON || (BABYLON = {}));
+
+var BABYLON;
+(function (BABYLON) {
+    var Internals;
+    (function (Internals) {
+        var _DepthCullingState = (function () {
+            function _DepthCullingState() {
+                this._isDepthTestDirty = false;
+                this._isDepthMaskDirty = false;
+                this._isDepthFuncDirty = false;
+                this._isCullFaceDirty = false;
                 this._isCullDirty = false;
+                this._isZOffsetDirty = false;
             }
-            // Cull face
-            if (this._isCullFaceDirty) {
-                gl.cullFace(this.cullFace);
+            Object.defineProperty(_DepthCullingState.prototype, "isDirty", {
+                get: function () {
+                    return this._isDepthFuncDirty || this._isDepthTestDirty || this._isDepthMaskDirty || this._isCullFaceDirty || this._isCullDirty || this._isZOffsetDirty;
+                },
+                enumerable: true,
+                configurable: true
+            });
+            Object.defineProperty(_DepthCullingState.prototype, "zOffset", {
+                get: function () {
+                    return this._zOffset;
+                },
+                set: function (value) {
+                    if (this._zOffset === value) {
+                        return;
+                    }
+                    this._zOffset = value;
+                    this._isZOffsetDirty = true;
+                },
+                enumerable: true,
+                configurable: true
+            });
+            Object.defineProperty(_DepthCullingState.prototype, "cullFace", {
+                get: function () {
+                    return this._cullFace;
+                },
+                set: function (value) {
+                    if (this._cullFace === value) {
+                        return;
+                    }
+                    this._cullFace = value;
+                    this._isCullFaceDirty = true;
+                },
+                enumerable: true,
+                configurable: true
+            });
+            Object.defineProperty(_DepthCullingState.prototype, "cull", {
+                get: function () {
+                    return this._cull;
+                },
+                set: function (value) {
+                    if (this._cull === value) {
+                        return;
+                    }
+                    this._cull = value;
+                    this._isCullDirty = true;
+                },
+                enumerable: true,
+                configurable: true
+            });
+            Object.defineProperty(_DepthCullingState.prototype, "depthFunc", {
+                get: function () {
+                    return this._depthFunc;
+                },
+                set: function (value) {
+                    if (this._depthFunc === value) {
+                        return;
+                    }
+                    this._depthFunc = value;
+                    this._isDepthFuncDirty = true;
+                },
+                enumerable: true,
+                configurable: true
+            });
+            Object.defineProperty(_DepthCullingState.prototype, "depthMask", {
+                get: function () {
+                    return this._depthMask;
+                },
+                set: function (value) {
+                    if (this._depthMask === value) {
+                        return;
+                    }
+                    this._depthMask = value;
+                    this._isDepthMaskDirty = true;
+                },
+                enumerable: true,
+                configurable: true
+            });
+            Object.defineProperty(_DepthCullingState.prototype, "depthTest", {
+                get: function () {
+                    return this._depthTest;
+                },
+                set: function (value) {
+                    if (this._depthTest === value) {
+                        return;
+                    }
+                    this._depthTest = value;
+                    this._isDepthTestDirty = true;
+                },
+                enumerable: true,
+                configurable: true
+            });
+            _DepthCullingState.prototype.reset = function () {
+                this._depthMask = true;
+                this._depthTest = true;
+                this._depthFunc = null;
+                this._cull = null;
+                this._cullFace = null;
+                this._zOffset = 0;
+                this._isDepthTestDirty = true;
+                this._isDepthMaskDirty = true;
+                this._isDepthFuncDirty = false;
                 this._isCullFaceDirty = false;
-            }
-            // Depth mask
-            if (this._isDepthMaskDirty) {
-                gl.depthMask(this.depthMask);
-                this._isDepthMaskDirty = false;
-            }
-            // Depth test
-            if (this._isDepthTestDirty) {
-                if (this.depthTest) {
-                    gl.enable(gl.DEPTH_TEST);
+                this._isCullDirty = false;
+                this._isZOffsetDirty = false;
+            };
+            _DepthCullingState.prototype.apply = function (gl) {
+                if (!this.isDirty) {
+                    return;
                 }
-                else {
-                    gl.disable(gl.DEPTH_TEST);
+                // Cull
+                if (this._isCullDirty) {
+                    if (this.cull) {
+                        gl.enable(gl.CULL_FACE);
+                    }
+                    else {
+                        gl.disable(gl.CULL_FACE);
+                    }
+                    this._isCullDirty = false;
                 }
-                this._isDepthTestDirty = false;
-            }
-            // Depth func
-            if (this._isDepthFuncDirty) {
-                gl.depthFunc(this.depthFunc);
-                this._isDepthFuncDirty = false;
-            }
-            // zOffset
-            if (this._isZOffsetDirty) {
-                if (this.zOffset) {
-                    gl.enable(gl.POLYGON_OFFSET_FILL);
-                    gl.polygonOffset(this.zOffset, 0);
+                // Cull face
+                if (this._isCullFaceDirty) {
+                    gl.cullFace(this.cullFace);
+                    this._isCullFaceDirty = false;
                 }
-                else {
-                    gl.disable(gl.POLYGON_OFFSET_FILL);
+                // Depth mask
+                if (this._isDepthMaskDirty) {
+                    gl.depthMask(this.depthMask);
+                    this._isDepthMaskDirty = false;
                 }
-                this._isZOffsetDirty = false;
-            }
-        };
-        return _DepthCullingState;
-    })();
-    BABYLON._DepthCullingState = _DepthCullingState;
-    var _AlphaState = (function () {
-        function _AlphaState() {
-            this._isAlphaBlendDirty = false;
-            this._isBlendFunctionParametersDirty = false;
-            this._alphaBlend = false;
-            this._blendFunctionParameters = new Array(4);
-        }
-        Object.defineProperty(_AlphaState.prototype, "isDirty", {
-            get: function () {
-                return this._isAlphaBlendDirty || this._isBlendFunctionParametersDirty;
-            },
-            enumerable: true,
-            configurable: true
-        });
-        Object.defineProperty(_AlphaState.prototype, "alphaBlend", {
-            get: function () {
-                return this._alphaBlend;
-            },
-            set: function (value) {
-                if (this._alphaBlend === value) {
-                    return;
+                // Depth test
+                if (this._isDepthTestDirty) {
+                    if (this.depthTest) {
+                        gl.enable(gl.DEPTH_TEST);
+                    }
+                    else {
+                        gl.disable(gl.DEPTH_TEST);
+                    }
+                    this._isDepthTestDirty = false;
                 }
-                this._alphaBlend = value;
-                this._isAlphaBlendDirty = true;
-            },
-            enumerable: true,
-            configurable: true
-        });
-        _AlphaState.prototype.setAlphaBlendFunctionParameters = function (value0, value1, value2, value3) {
-            if (this._blendFunctionParameters[0] === value0 &&
-                this._blendFunctionParameters[1] === value1 &&
-                this._blendFunctionParameters[2] === value2 &&
-                this._blendFunctionParameters[3] === value3) {
-                return;
-            }
-            this._blendFunctionParameters[0] = value0;
-            this._blendFunctionParameters[1] = value1;
-            this._blendFunctionParameters[2] = value2;
-            this._blendFunctionParameters[3] = value3;
-            this._isBlendFunctionParametersDirty = true;
-        };
-        _AlphaState.prototype.reset = function () {
-            this._alphaBlend = false;
-            this._blendFunctionParameters[0] = null;
-            this._blendFunctionParameters[1] = null;
-            this._blendFunctionParameters[2] = null;
-            this._blendFunctionParameters[3] = null;
-            this._isAlphaBlendDirty = true;
-            this._isBlendFunctionParametersDirty = false;
-        };
-        _AlphaState.prototype.apply = function (gl) {
-            if (!this.isDirty) {
-                return;
-            }
-            // Alpha blend
-            if (this._isAlphaBlendDirty) {
-                if (this._alphaBlend) {
-                    gl.enable(gl.BLEND);
+                // Depth func
+                if (this._isDepthFuncDirty) {
+                    gl.depthFunc(this.depthFunc);
+                    this._isDepthFuncDirty = false;
                 }
-                else {
-                    gl.disable(gl.BLEND);
+                // zOffset
+                if (this._isZOffsetDirty) {
+                    if (this.zOffset) {
+                        gl.enable(gl.POLYGON_OFFSET_FILL);
+                        gl.polygonOffset(this.zOffset, 0);
+                    }
+                    else {
+                        gl.disable(gl.POLYGON_OFFSET_FILL);
+                    }
+                    this._isZOffsetDirty = false;
                 }
-                this._isAlphaBlendDirty = false;
-            }
-            // Alpha function
-            if (this._isBlendFunctionParametersDirty) {
-                gl.blendFuncSeparate(this._blendFunctionParameters[0], this._blendFunctionParameters[1], this._blendFunctionParameters[2], this._blendFunctionParameters[3]);
-                this._isBlendFunctionParametersDirty = false;
-            }
-        };
-        return _AlphaState;
-    })();
-    BABYLON._AlphaState = _AlphaState;
+            };
+            return _DepthCullingState;
+        })();
+        Internals._DepthCullingState = _DepthCullingState;
+    })(Internals = BABYLON.Internals || (BABYLON.Internals = {}));
+})(BABYLON || (BABYLON = {}));
+
+var BABYLON;
+(function (BABYLON) {
     var compileShader = function (gl, source, type, defines) {
         var shader = gl.createShader(type === "vertex" ? gl.VERTEX_SHADER : gl.FRAGMENT_SHADER);
         gl.shaderSource(shader, (defines ? defines + "\n" : "") + source);
@@ -5420,8 +5434,8 @@ var BABYLON;
             this.fps = 60;
             this.deltaTime = 0;
             // States
-            this._depthCullingState = new _DepthCullingState();
-            this._alphaState = new _AlphaState();
+            this._depthCullingState = new BABYLON.Internals._DepthCullingState();
+            this._alphaState = new BABYLON.Internals._AlphaState();
             this._alphaMode = Engine.ALPHA_DISABLE;
             // Cache
             this._loadedTexturesCache = new Array();
@@ -5464,7 +5478,8 @@ var BABYLON;
             window.addEventListener("blur", this._onBlur);
             window.addEventListener("focus", this._onFocus);
             // Viewport
-            this._hardwareScalingLevel = adaptToDeviceRatio ? 1.0 / (window.devicePixelRatio || 1.0) : 1.0;
+            var limitDeviceRatio = options.limitDeviceRatio || window.devicePixelRatio || 1.0;
+            this._hardwareScalingLevel = adaptToDeviceRatio ? 1.0 / Math.min(limitDeviceRatio, window.devicePixelRatio || 1.0) : 1.0;
             this.resize();
             // Caps
             this._caps = new EngineCapabilities();
@@ -23074,9 +23089,9 @@ var BABYLON;
             var index = this._scene._activeAnimatables.indexOf(this);
             if (index > -1) {
                 this._scene._activeAnimatables.splice(index, 1);
-            }
-            if (this.onAnimationEnd) {
-                this.onAnimationEnd();
+                if (this.onAnimationEnd) {
+                    this.onAnimationEnd();
+                }
             }
         };
         Animatable.prototype._animate = function (delay) {
@@ -23111,6 +23126,7 @@ var BABYLON;
             }
             if (!running && this.onAnimationEnd) {
                 this.onAnimationEnd();
+                this.onAnimationEnd = null;
             }
             return running;
         };

文件差異過大導致無法顯示
+ 24 - 24
dist/preview release/babylon.noworker.js


+ 4 - 3
src/Animations/babylon.animatable.js

@@ -68,9 +68,9 @@ var BABYLON;
             var index = this._scene._activeAnimatables.indexOf(this);
             if (index > -1) {
                 this._scene._activeAnimatables.splice(index, 1);
-            }
-            if (this.onAnimationEnd) {
-                this.onAnimationEnd();
+                if (this.onAnimationEnd) {
+                    this.onAnimationEnd();
+                }
             }
         };
         Animatable.prototype._animate = function (delay) {
@@ -105,6 +105,7 @@ var BABYLON;
             }
             if (!running && this.onAnimationEnd) {
                 this.onAnimationEnd();
+                this.onAnimationEnd = null;
             }
             return running;
         };

+ 4 - 3
src/Animations/babylon.animatable.ts

@@ -79,10 +79,10 @@
 
             if (index > -1) {
                 this._scene._activeAnimatables.splice(index, 1);
-            }
 
-            if (this.onAnimationEnd) {
-                this.onAnimationEnd();
+                if (this.onAnimationEnd) {
+                    this.onAnimationEnd();
+                }
             }
         }
 
@@ -123,6 +123,7 @@
 
             if (!running && this.onAnimationEnd) {
                 this.onAnimationEnd();
+                this.onAnimationEnd = null;
             }
 
             return running;

+ 79 - 0
src/States/babylon.alphaCullingState.js

@@ -0,0 +1,79 @@
+var BABYLON;
+(function (BABYLON) {
+    var Internals;
+    (function (Internals) {
+        var _AlphaState = (function () {
+            function _AlphaState() {
+                this._isAlphaBlendDirty = false;
+                this._isBlendFunctionParametersDirty = false;
+                this._alphaBlend = false;
+                this._blendFunctionParameters = new Array(4);
+            }
+            Object.defineProperty(_AlphaState.prototype, "isDirty", {
+                get: function () {
+                    return this._isAlphaBlendDirty || this._isBlendFunctionParametersDirty;
+                },
+                enumerable: true,
+                configurable: true
+            });
+            Object.defineProperty(_AlphaState.prototype, "alphaBlend", {
+                get: function () {
+                    return this._alphaBlend;
+                },
+                set: function (value) {
+                    if (this._alphaBlend === value) {
+                        return;
+                    }
+                    this._alphaBlend = value;
+                    this._isAlphaBlendDirty = true;
+                },
+                enumerable: true,
+                configurable: true
+            });
+            _AlphaState.prototype.setAlphaBlendFunctionParameters = function (value0, value1, value2, value3) {
+                if (this._blendFunctionParameters[0] === value0 &&
+                    this._blendFunctionParameters[1] === value1 &&
+                    this._blendFunctionParameters[2] === value2 &&
+                    this._blendFunctionParameters[3] === value3) {
+                    return;
+                }
+                this._blendFunctionParameters[0] = value0;
+                this._blendFunctionParameters[1] = value1;
+                this._blendFunctionParameters[2] = value2;
+                this._blendFunctionParameters[3] = value3;
+                this._isBlendFunctionParametersDirty = true;
+            };
+            _AlphaState.prototype.reset = function () {
+                this._alphaBlend = false;
+                this._blendFunctionParameters[0] = null;
+                this._blendFunctionParameters[1] = null;
+                this._blendFunctionParameters[2] = null;
+                this._blendFunctionParameters[3] = null;
+                this._isAlphaBlendDirty = true;
+                this._isBlendFunctionParametersDirty = false;
+            };
+            _AlphaState.prototype.apply = function (gl) {
+                if (!this.isDirty) {
+                    return;
+                }
+                // Alpha blend
+                if (this._isAlphaBlendDirty) {
+                    if (this._alphaBlend) {
+                        gl.enable(gl.BLEND);
+                    }
+                    else {
+                        gl.disable(gl.BLEND);
+                    }
+                    this._isAlphaBlendDirty = false;
+                }
+                // Alpha function
+                if (this._isBlendFunctionParametersDirty) {
+                    gl.blendFuncSeparate(this._blendFunctionParameters[0], this._blendFunctionParameters[1], this._blendFunctionParameters[2], this._blendFunctionParameters[3]);
+                    this._isBlendFunctionParametersDirty = false;
+                }
+            };
+            return _AlphaState;
+        })();
+        Internals._AlphaState = _AlphaState;
+    })(Internals = BABYLON.Internals || (BABYLON.Internals = {}));
+})(BABYLON || (BABYLON = {}));

+ 78 - 0
src/States/babylon.alphaCullingState.ts

@@ -0,0 +1,78 @@
+module BABYLON.Internals {
+    export class _AlphaState {
+        private _isAlphaBlendDirty = false;
+        private _isBlendFunctionParametersDirty = false;
+        private _alphaBlend = false;
+        private _blendFunctionParameters = new Array<number>(4);
+
+        public get isDirty(): boolean {
+            return this._isAlphaBlendDirty || this._isBlendFunctionParametersDirty;
+        }
+
+        public get alphaBlend(): boolean {
+            return this._alphaBlend;
+        }
+
+        public set alphaBlend(value: boolean) {
+            if (this._alphaBlend === value) {
+                return;
+            }
+
+            this._alphaBlend = value;
+            this._isAlphaBlendDirty = true;
+        }
+
+        public setAlphaBlendFunctionParameters(value0: number, value1: number, value2: number, value3: number): void {
+            if (
+                this._blendFunctionParameters[0] === value0 &&
+                this._blendFunctionParameters[1] === value1 &&
+                this._blendFunctionParameters[2] === value2 &&
+                this._blendFunctionParameters[3] === value3
+            ) {
+                return;
+            }
+
+            this._blendFunctionParameters[0] = value0;
+            this._blendFunctionParameters[1] = value1;
+            this._blendFunctionParameters[2] = value2;
+            this._blendFunctionParameters[3] = value3;
+
+            this._isBlendFunctionParametersDirty = true;
+        }
+
+        public reset() {
+            this._alphaBlend = false;
+            this._blendFunctionParameters[0] = null;
+            this._blendFunctionParameters[1] = null;
+            this._blendFunctionParameters[2] = null;
+            this._blendFunctionParameters[3] = null;
+
+            this._isAlphaBlendDirty = true;
+            this._isBlendFunctionParametersDirty = false;
+        }
+
+        public apply(gl: WebGLRenderingContext) {
+
+            if (!this.isDirty) {
+                return;
+            }
+
+            // Alpha blend
+            if (this._isAlphaBlendDirty) {
+                if (this._alphaBlend) {
+                    gl.enable(gl.BLEND);
+                } else {
+                    gl.disable(gl.BLEND);
+                }
+
+                this._isAlphaBlendDirty = false;
+            }
+
+            // Alpha function
+            if (this._isBlendFunctionParametersDirty) {
+                gl.blendFuncSeparate(this._blendFunctionParameters[0], this._blendFunctionParameters[1], this._blendFunctionParameters[2], this._blendFunctionParameters[3]);
+                this._isBlendFunctionParametersDirty = false;
+            }
+        }
+    }
+}

+ 174 - 0
src/States/babylon.depthCullingState.js

@@ -0,0 +1,174 @@
+var BABYLON;
+(function (BABYLON) {
+    var Internals;
+    (function (Internals) {
+        var _DepthCullingState = (function () {
+            function _DepthCullingState() {
+                this._isDepthTestDirty = false;
+                this._isDepthMaskDirty = false;
+                this._isDepthFuncDirty = false;
+                this._isCullFaceDirty = false;
+                this._isCullDirty = false;
+                this._isZOffsetDirty = false;
+            }
+            Object.defineProperty(_DepthCullingState.prototype, "isDirty", {
+                get: function () {
+                    return this._isDepthFuncDirty || this._isDepthTestDirty || this._isDepthMaskDirty || this._isCullFaceDirty || this._isCullDirty || this._isZOffsetDirty;
+                },
+                enumerable: true,
+                configurable: true
+            });
+            Object.defineProperty(_DepthCullingState.prototype, "zOffset", {
+                get: function () {
+                    return this._zOffset;
+                },
+                set: function (value) {
+                    if (this._zOffset === value) {
+                        return;
+                    }
+                    this._zOffset = value;
+                    this._isZOffsetDirty = true;
+                },
+                enumerable: true,
+                configurable: true
+            });
+            Object.defineProperty(_DepthCullingState.prototype, "cullFace", {
+                get: function () {
+                    return this._cullFace;
+                },
+                set: function (value) {
+                    if (this._cullFace === value) {
+                        return;
+                    }
+                    this._cullFace = value;
+                    this._isCullFaceDirty = true;
+                },
+                enumerable: true,
+                configurable: true
+            });
+            Object.defineProperty(_DepthCullingState.prototype, "cull", {
+                get: function () {
+                    return this._cull;
+                },
+                set: function (value) {
+                    if (this._cull === value) {
+                        return;
+                    }
+                    this._cull = value;
+                    this._isCullDirty = true;
+                },
+                enumerable: true,
+                configurable: true
+            });
+            Object.defineProperty(_DepthCullingState.prototype, "depthFunc", {
+                get: function () {
+                    return this._depthFunc;
+                },
+                set: function (value) {
+                    if (this._depthFunc === value) {
+                        return;
+                    }
+                    this._depthFunc = value;
+                    this._isDepthFuncDirty = true;
+                },
+                enumerable: true,
+                configurable: true
+            });
+            Object.defineProperty(_DepthCullingState.prototype, "depthMask", {
+                get: function () {
+                    return this._depthMask;
+                },
+                set: function (value) {
+                    if (this._depthMask === value) {
+                        return;
+                    }
+                    this._depthMask = value;
+                    this._isDepthMaskDirty = true;
+                },
+                enumerable: true,
+                configurable: true
+            });
+            Object.defineProperty(_DepthCullingState.prototype, "depthTest", {
+                get: function () {
+                    return this._depthTest;
+                },
+                set: function (value) {
+                    if (this._depthTest === value) {
+                        return;
+                    }
+                    this._depthTest = value;
+                    this._isDepthTestDirty = true;
+                },
+                enumerable: true,
+                configurable: true
+            });
+            _DepthCullingState.prototype.reset = function () {
+                this._depthMask = true;
+                this._depthTest = true;
+                this._depthFunc = null;
+                this._cull = null;
+                this._cullFace = null;
+                this._zOffset = 0;
+                this._isDepthTestDirty = true;
+                this._isDepthMaskDirty = true;
+                this._isDepthFuncDirty = false;
+                this._isCullFaceDirty = false;
+                this._isCullDirty = false;
+                this._isZOffsetDirty = false;
+            };
+            _DepthCullingState.prototype.apply = function (gl) {
+                if (!this.isDirty) {
+                    return;
+                }
+                // Cull
+                if (this._isCullDirty) {
+                    if (this.cull) {
+                        gl.enable(gl.CULL_FACE);
+                    }
+                    else {
+                        gl.disable(gl.CULL_FACE);
+                    }
+                    this._isCullDirty = false;
+                }
+                // Cull face
+                if (this._isCullFaceDirty) {
+                    gl.cullFace(this.cullFace);
+                    this._isCullFaceDirty = false;
+                }
+                // Depth mask
+                if (this._isDepthMaskDirty) {
+                    gl.depthMask(this.depthMask);
+                    this._isDepthMaskDirty = false;
+                }
+                // Depth test
+                if (this._isDepthTestDirty) {
+                    if (this.depthTest) {
+                        gl.enable(gl.DEPTH_TEST);
+                    }
+                    else {
+                        gl.disable(gl.DEPTH_TEST);
+                    }
+                    this._isDepthTestDirty = false;
+                }
+                // Depth func
+                if (this._isDepthFuncDirty) {
+                    gl.depthFunc(this.depthFunc);
+                    this._isDepthFuncDirty = false;
+                }
+                // zOffset
+                if (this._isZOffsetDirty) {
+                    if (this.zOffset) {
+                        gl.enable(gl.POLYGON_OFFSET_FILL);
+                        gl.polygonOffset(this.zOffset, 0);
+                    }
+                    else {
+                        gl.disable(gl.POLYGON_OFFSET_FILL);
+                    }
+                    this._isZOffsetDirty = false;
+                }
+            };
+            return _DepthCullingState;
+        })();
+        Internals._DepthCullingState = _DepthCullingState;
+    })(Internals = BABYLON.Internals || (BABYLON.Internals = {}));
+})(BABYLON || (BABYLON = {}));

+ 173 - 0
src/States/babylon.depthCullingState.ts

@@ -0,0 +1,173 @@
+module BABYLON.Internals {
+    export class _DepthCullingState {
+        private _isDepthTestDirty = false;
+        private _isDepthMaskDirty = false;
+        private _isDepthFuncDirty = false;
+        private _isCullFaceDirty = false;
+        private _isCullDirty = false;
+        private _isZOffsetDirty = false;
+
+        private _depthTest: boolean;
+        private _depthMask: boolean;
+        private _depthFunc: number;
+        private _cull: boolean;
+        private _cullFace: number;
+        private _zOffset: number;
+
+        public get isDirty(): boolean {
+            return this._isDepthFuncDirty || this._isDepthTestDirty || this._isDepthMaskDirty || this._isCullFaceDirty || this._isCullDirty || this._isZOffsetDirty;
+        }
+
+        public get zOffset(): number {
+            return this._zOffset;
+        }
+
+        public set zOffset(value: number) {
+            if (this._zOffset === value) {
+                return;
+            }
+
+            this._zOffset = value;
+            this._isZOffsetDirty = true;
+        }
+
+        public get cullFace(): number {
+            return this._cullFace;
+        }
+
+        public set cullFace(value: number) {
+            if (this._cullFace === value) {
+                return;
+            }
+
+            this._cullFace = value;
+            this._isCullFaceDirty = true;
+        }
+
+        public get cull() {
+            return this._cull;
+        }
+
+        public set cull(value: boolean) {
+            if (this._cull === value) {
+                return;
+            }
+
+            this._cull = value;
+            this._isCullDirty = true;
+        }
+
+        public get depthFunc(): number {
+            return this._depthFunc;
+        }
+
+        public set depthFunc(value: number) {
+            if (this._depthFunc === value) {
+                return;
+            }
+
+            this._depthFunc = value;
+            this._isDepthFuncDirty = true;
+        }
+
+        public get depthMask(): boolean {
+            return this._depthMask;
+        }
+
+        public set depthMask(value: boolean) {
+            if (this._depthMask === value) {
+                return;
+            }
+
+            this._depthMask = value;
+            this._isDepthMaskDirty = true;
+        }
+
+        public get depthTest(): boolean {
+            return this._depthTest;
+        }
+
+        public set depthTest(value: boolean) {
+            if (this._depthTest === value) {
+                return;
+            }
+
+            this._depthTest = value;
+            this._isDepthTestDirty = true;
+        }
+
+        public reset() {
+            this._depthMask = true;
+            this._depthTest = true;
+            this._depthFunc = null;
+            this._cull = null;
+            this._cullFace = null;
+            this._zOffset = 0;
+
+            this._isDepthTestDirty = true;
+            this._isDepthMaskDirty = true;
+            this._isDepthFuncDirty = false;
+            this._isCullFaceDirty = false;
+            this._isCullDirty = false;
+            this._isZOffsetDirty = false;
+        }
+
+        public apply(gl: WebGLRenderingContext) {
+
+            if (!this.isDirty) {
+                return;
+            }
+
+            // Cull
+            if (this._isCullDirty) {
+                if (this.cull) {
+                    gl.enable(gl.CULL_FACE);
+                } else {
+                    gl.disable(gl.CULL_FACE);
+                }
+
+                this._isCullDirty = false;
+            }
+
+            // Cull face
+            if (this._isCullFaceDirty) {
+                gl.cullFace(this.cullFace);
+                this._isCullFaceDirty = false;
+            }
+
+            // Depth mask
+            if (this._isDepthMaskDirty) {
+                gl.depthMask(this.depthMask);
+                this._isDepthMaskDirty = false;
+            }
+
+            // Depth test
+            if (this._isDepthTestDirty) {
+                if (this.depthTest) {
+                    gl.enable(gl.DEPTH_TEST);
+                } else {
+                    gl.disable(gl.DEPTH_TEST);
+                }
+                this._isDepthTestDirty = false;
+            }
+
+            // Depth func
+            if (this._isDepthFuncDirty) {
+                gl.depthFunc(this.depthFunc);
+                this._isDepthFuncDirty = false;
+            }
+
+            // zOffset
+            if (this._isZOffsetDirty) {
+                if (this.zOffset) {
+                    gl.enable(gl.POLYGON_OFFSET_FILL);
+                    gl.polygonOffset(this.zOffset, 0);
+                } else {
+                    gl.disable(gl.POLYGON_OFFSET_FILL);
+                }
+
+                this._isZOffsetDirty = false;
+            }
+        }
+    }
+}

+ 4 - 244
src/babylon.engine.js

@@ -1,246 +1,5 @@
 var BABYLON;
 (function (BABYLON) {
-    var _DepthCullingState = (function () {
-        function _DepthCullingState() {
-            this._isDepthTestDirty = false;
-            this._isDepthMaskDirty = false;
-            this._isDepthFuncDirty = false;
-            this._isCullFaceDirty = false;
-            this._isCullDirty = false;
-            this._isZOffsetDirty = false;
-        }
-        Object.defineProperty(_DepthCullingState.prototype, "isDirty", {
-            get: function () {
-                return this._isDepthFuncDirty || this._isDepthTestDirty || this._isDepthMaskDirty || this._isCullFaceDirty || this._isCullDirty || this._isZOffsetDirty;
-            },
-            enumerable: true,
-            configurable: true
-        });
-        Object.defineProperty(_DepthCullingState.prototype, "zOffset", {
-            get: function () {
-                return this._zOffset;
-            },
-            set: function (value) {
-                if (this._zOffset === value) {
-                    return;
-                }
-                this._zOffset = value;
-                this._isZOffsetDirty = true;
-            },
-            enumerable: true,
-            configurable: true
-        });
-        Object.defineProperty(_DepthCullingState.prototype, "cullFace", {
-            get: function () {
-                return this._cullFace;
-            },
-            set: function (value) {
-                if (this._cullFace === value) {
-                    return;
-                }
-                this._cullFace = value;
-                this._isCullFaceDirty = true;
-            },
-            enumerable: true,
-            configurable: true
-        });
-        Object.defineProperty(_DepthCullingState.prototype, "cull", {
-            get: function () {
-                return this._cull;
-            },
-            set: function (value) {
-                if (this._cull === value) {
-                    return;
-                }
-                this._cull = value;
-                this._isCullDirty = true;
-            },
-            enumerable: true,
-            configurable: true
-        });
-        Object.defineProperty(_DepthCullingState.prototype, "depthFunc", {
-            get: function () {
-                return this._depthFunc;
-            },
-            set: function (value) {
-                if (this._depthFunc === value) {
-                    return;
-                }
-                this._depthFunc = value;
-                this._isDepthFuncDirty = true;
-            },
-            enumerable: true,
-            configurable: true
-        });
-        Object.defineProperty(_DepthCullingState.prototype, "depthMask", {
-            get: function () {
-                return this._depthMask;
-            },
-            set: function (value) {
-                if (this._depthMask === value) {
-                    return;
-                }
-                this._depthMask = value;
-                this._isDepthMaskDirty = true;
-            },
-            enumerable: true,
-            configurable: true
-        });
-        Object.defineProperty(_DepthCullingState.prototype, "depthTest", {
-            get: function () {
-                return this._depthTest;
-            },
-            set: function (value) {
-                if (this._depthTest === value) {
-                    return;
-                }
-                this._depthTest = value;
-                this._isDepthTestDirty = true;
-            },
-            enumerable: true,
-            configurable: true
-        });
-        _DepthCullingState.prototype.reset = function () {
-            this._depthMask = true;
-            this._depthTest = true;
-            this._depthFunc = null;
-            this._cull = null;
-            this._cullFace = null;
-            this._zOffset = 0;
-            this._isDepthTestDirty = true;
-            this._isDepthMaskDirty = true;
-            this._isDepthFuncDirty = false;
-            this._isCullFaceDirty = false;
-            this._isCullDirty = false;
-            this._isZOffsetDirty = false;
-        };
-        _DepthCullingState.prototype.apply = function (gl) {
-            if (!this.isDirty) {
-                return;
-            }
-            // Cull
-            if (this._isCullDirty) {
-                if (this.cull) {
-                    gl.enable(gl.CULL_FACE);
-                }
-                else {
-                    gl.disable(gl.CULL_FACE);
-                }
-                this._isCullDirty = false;
-            }
-            // Cull face
-            if (this._isCullFaceDirty) {
-                gl.cullFace(this.cullFace);
-                this._isCullFaceDirty = false;
-            }
-            // Depth mask
-            if (this._isDepthMaskDirty) {
-                gl.depthMask(this.depthMask);
-                this._isDepthMaskDirty = false;
-            }
-            // Depth test
-            if (this._isDepthTestDirty) {
-                if (this.depthTest) {
-                    gl.enable(gl.DEPTH_TEST);
-                }
-                else {
-                    gl.disable(gl.DEPTH_TEST);
-                }
-                this._isDepthTestDirty = false;
-            }
-            // Depth func
-            if (this._isDepthFuncDirty) {
-                gl.depthFunc(this.depthFunc);
-                this._isDepthFuncDirty = false;
-            }
-            // zOffset
-            if (this._isZOffsetDirty) {
-                if (this.zOffset) {
-                    gl.enable(gl.POLYGON_OFFSET_FILL);
-                    gl.polygonOffset(this.zOffset, 0);
-                }
-                else {
-                    gl.disable(gl.POLYGON_OFFSET_FILL);
-                }
-                this._isZOffsetDirty = false;
-            }
-        };
-        return _DepthCullingState;
-    })();
-    BABYLON._DepthCullingState = _DepthCullingState;
-    var _AlphaState = (function () {
-        function _AlphaState() {
-            this._isAlphaBlendDirty = false;
-            this._isBlendFunctionParametersDirty = false;
-            this._alphaBlend = false;
-            this._blendFunctionParameters = new Array(4);
-        }
-        Object.defineProperty(_AlphaState.prototype, "isDirty", {
-            get: function () {
-                return this._isAlphaBlendDirty || this._isBlendFunctionParametersDirty;
-            },
-            enumerable: true,
-            configurable: true
-        });
-        Object.defineProperty(_AlphaState.prototype, "alphaBlend", {
-            get: function () {
-                return this._alphaBlend;
-            },
-            set: function (value) {
-                if (this._alphaBlend === value) {
-                    return;
-                }
-                this._alphaBlend = value;
-                this._isAlphaBlendDirty = true;
-            },
-            enumerable: true,
-            configurable: true
-        });
-        _AlphaState.prototype.setAlphaBlendFunctionParameters = function (value0, value1, value2, value3) {
-            if (this._blendFunctionParameters[0] === value0 &&
-                this._blendFunctionParameters[1] === value1 &&
-                this._blendFunctionParameters[2] === value2 &&
-                this._blendFunctionParameters[3] === value3) {
-                return;
-            }
-            this._blendFunctionParameters[0] = value0;
-            this._blendFunctionParameters[1] = value1;
-            this._blendFunctionParameters[2] = value2;
-            this._blendFunctionParameters[3] = value3;
-            this._isBlendFunctionParametersDirty = true;
-        };
-        _AlphaState.prototype.reset = function () {
-            this._alphaBlend = false;
-            this._blendFunctionParameters[0] = null;
-            this._blendFunctionParameters[1] = null;
-            this._blendFunctionParameters[2] = null;
-            this._blendFunctionParameters[3] = null;
-            this._isAlphaBlendDirty = true;
-            this._isBlendFunctionParametersDirty = false;
-        };
-        _AlphaState.prototype.apply = function (gl) {
-            if (!this.isDirty) {
-                return;
-            }
-            // Alpha blend
-            if (this._isAlphaBlendDirty) {
-                if (this._alphaBlend) {
-                    gl.enable(gl.BLEND);
-                }
-                else {
-                    gl.disable(gl.BLEND);
-                }
-                this._isAlphaBlendDirty = false;
-            }
-            // Alpha function
-            if (this._isBlendFunctionParametersDirty) {
-                gl.blendFuncSeparate(this._blendFunctionParameters[0], this._blendFunctionParameters[1], this._blendFunctionParameters[2], this._blendFunctionParameters[3]);
-                this._isBlendFunctionParametersDirty = false;
-            }
-        };
-        return _AlphaState;
-    })();
-    BABYLON._AlphaState = _AlphaState;
     var compileShader = function (gl, source, type, defines) {
         var shader = gl.createShader(type === "vertex" ? gl.VERTEX_SHADER : gl.FRAGMENT_SHADER);
         gl.shaderSource(shader, (defines ? defines + "\n" : "") + source);
@@ -378,8 +137,8 @@ var BABYLON;
             this.fps = 60;
             this.deltaTime = 0;
             // States
-            this._depthCullingState = new _DepthCullingState();
-            this._alphaState = new _AlphaState();
+            this._depthCullingState = new BABYLON.Internals._DepthCullingState();
+            this._alphaState = new BABYLON.Internals._AlphaState();
             this._alphaMode = Engine.ALPHA_DISABLE;
             // Cache
             this._loadedTexturesCache = new Array();
@@ -422,7 +181,8 @@ var BABYLON;
             window.addEventListener("blur", this._onBlur);
             window.addEventListener("focus", this._onFocus);
             // Viewport
-            this._hardwareScalingLevel = adaptToDeviceRatio ? 1.0 / (window.devicePixelRatio || 1.0) : 1.0;
+            var limitDeviceRatio = options.limitDeviceRatio || window.devicePixelRatio || 1.0;
+            this._hardwareScalingLevel = adaptToDeviceRatio ? 1.0 / Math.min(limitDeviceRatio, window.devicePixelRatio || 1.0) : 1.0;
             this.resize();
             // Caps
             this._caps = new EngineCapabilities();

+ 5 - 253
src/babylon.engine.ts

@@ -1,253 +1,4 @@
 module BABYLON {
-    export class _DepthCullingState {
-        private _isDepthTestDirty = false;
-        private _isDepthMaskDirty = false;
-        private _isDepthFuncDirty = false;
-        private _isCullFaceDirty = false;
-        private _isCullDirty = false;
-        private _isZOffsetDirty = false;
-
-        private _depthTest: boolean;
-        private _depthMask: boolean;
-        private _depthFunc: number;
-        private _cull: boolean;
-        private _cullFace: number;
-        private _zOffset: number;
-
-        public get isDirty(): boolean {
-            return this._isDepthFuncDirty || this._isDepthTestDirty || this._isDepthMaskDirty || this._isCullFaceDirty || this._isCullDirty || this._isZOffsetDirty;
-        }
-
-        public get zOffset(): number {
-            return this._zOffset;
-        }
-
-        public set zOffset(value: number) {
-            if (this._zOffset === value) {
-                return;
-            }
-
-            this._zOffset = value;
-            this._isZOffsetDirty = true;
-        }
-
-        public get cullFace(): number {
-            return this._cullFace;
-        }
-
-        public set cullFace(value: number) {
-            if (this._cullFace === value) {
-                return;
-            }
-
-            this._cullFace = value;
-            this._isCullFaceDirty = true;
-        }
-
-        public get cull() {
-            return this._cull;
-        }
-
-        public set cull(value: boolean) {
-            if (this._cull === value) {
-                return;
-            }
-
-            this._cull = value;
-            this._isCullDirty = true;
-        }
-
-        public get depthFunc(): number {
-            return this._depthFunc;
-        }
-
-        public set depthFunc(value: number) {
-            if (this._depthFunc === value) {
-                return;
-            }
-
-            this._depthFunc = value;
-            this._isDepthFuncDirty = true;
-        }
-
-        public get depthMask(): boolean {
-            return this._depthMask;
-        }
-
-        public set depthMask(value: boolean) {
-            if (this._depthMask === value) {
-                return;
-            }
-
-            this._depthMask = value;
-            this._isDepthMaskDirty = true;
-        }
-
-        public get depthTest(): boolean {
-            return this._depthTest;
-        }
-
-        public set depthTest(value: boolean) {
-            if (this._depthTest === value) {
-                return;
-            }
-
-            this._depthTest = value;
-            this._isDepthTestDirty = true;
-        }
-
-        public reset() {
-            this._depthMask = true;
-            this._depthTest = true;
-            this._depthFunc = null;
-            this._cull = null;
-            this._cullFace = null;
-            this._zOffset = 0;
-
-            this._isDepthTestDirty = true;
-            this._isDepthMaskDirty = true;
-            this._isDepthFuncDirty = false;
-            this._isCullFaceDirty = false;
-            this._isCullDirty = false;
-            this._isZOffsetDirty = false;
-        }
-
-        public apply(gl: WebGLRenderingContext) {
-
-            if (!this.isDirty) {
-                return;
-            }
-
-            // Cull
-            if (this._isCullDirty) {
-                if (this.cull) {
-                    gl.enable(gl.CULL_FACE);
-                } else {
-                    gl.disable(gl.CULL_FACE);
-                }
-
-                this._isCullDirty = false;
-            }
-
-            // Cull face
-            if (this._isCullFaceDirty) {
-                gl.cullFace(this.cullFace);
-                this._isCullFaceDirty = false;
-            }
-
-            // Depth mask
-            if (this._isDepthMaskDirty) {
-                gl.depthMask(this.depthMask);
-                this._isDepthMaskDirty = false;
-            }
-
-            // Depth test
-            if (this._isDepthTestDirty) {
-                if (this.depthTest) {
-                    gl.enable(gl.DEPTH_TEST);
-                } else {
-                    gl.disable(gl.DEPTH_TEST);
-                }
-                this._isDepthTestDirty = false;
-            }
-
-            // Depth func
-            if (this._isDepthFuncDirty) {
-                gl.depthFunc(this.depthFunc);
-                this._isDepthFuncDirty = false;
-            }
-
-            // zOffset
-            if (this._isZOffsetDirty) {
-                if (this.zOffset) {
-                    gl.enable(gl.POLYGON_OFFSET_FILL);
-                    gl.polygonOffset(this.zOffset, 0);
-                } else {
-                    gl.disable(gl.POLYGON_OFFSET_FILL);
-                }
-
-                this._isZOffsetDirty = false;
-            }
-        }
-    }
-
-    export class _AlphaState {
-        private _isAlphaBlendDirty = false;
-        private _isBlendFunctionParametersDirty = false;
-        private _alphaBlend = false;
-        private _blendFunctionParameters = new Array<number>(4);
-
-        public get isDirty(): boolean {
-            return this._isAlphaBlendDirty || this._isBlendFunctionParametersDirty;
-        }
-
-        public get alphaBlend(): boolean {
-            return this._alphaBlend;
-        }
-
-        public set alphaBlend(value: boolean) {
-            if (this._alphaBlend === value) {
-                return;
-            }
-
-            this._alphaBlend = value;
-            this._isAlphaBlendDirty = true;
-        }
-
-        public setAlphaBlendFunctionParameters(value0: number, value1: number, value2: number, value3: number): void {
-            if (
-                this._blendFunctionParameters[0] === value0 &&
-                this._blendFunctionParameters[1] === value1 &&
-                this._blendFunctionParameters[2] === value2 &&
-                this._blendFunctionParameters[3] === value3
-            ) {
-                return;
-            }
-
-            this._blendFunctionParameters[0] = value0;
-            this._blendFunctionParameters[1] = value1;
-            this._blendFunctionParameters[2] = value2;
-            this._blendFunctionParameters[3] = value3;
-
-            this._isBlendFunctionParametersDirty = true;
-        }
-
-        public reset() {
-            this._alphaBlend = false;
-            this._blendFunctionParameters[0] = null;
-            this._blendFunctionParameters[1] = null;
-            this._blendFunctionParameters[2] = null;
-            this._blendFunctionParameters[3] = null;
-
-            this._isAlphaBlendDirty = true;
-            this._isBlendFunctionParametersDirty = false;
-        }
-
-        public apply(gl: WebGLRenderingContext) {
-
-            if (!this.isDirty) {
-                return;
-            }
-
-            // Alpha blend
-            if (this._isAlphaBlendDirty) {
-                if (this._alphaBlend) {
-                    gl.enable(gl.BLEND);
-                } else {
-                    gl.disable(gl.BLEND);
-                }
-
-                this._isAlphaBlendDirty = false;
-            }
-
-            // Alpha function
-            if (this._isBlendFunctionParametersDirty) {
-                gl.blendFuncSeparate(this._blendFunctionParameters[0], this._blendFunctionParameters[1], this._blendFunctionParameters[2], this._blendFunctionParameters[3]);
-                this._isBlendFunctionParametersDirty = false;
-            }
-        }
-    }
-
     var compileShader = (gl: WebGLRenderingContext, source: string, type: string, defines: string): WebGLShader => {
         var shader = gl.createShader(type === "vertex" ? gl.VERTEX_SHADER : gl.FRAGMENT_SHADER);
 
@@ -547,8 +298,8 @@
         private deltaTime = 0;
 
         // States
-        private _depthCullingState = new _DepthCullingState();
-        private _alphaState = new _AlphaState();
+        private _depthCullingState = new Internals._DepthCullingState();
+        private _alphaState = new Internals._AlphaState();
         private _alphaMode = Engine.ALPHA_DISABLE;
 
         // Cache
@@ -576,7 +327,7 @@
          * @param {boolean} [antialias] - enable antialias
          * @param options - further options to be sent to the getContext function
          */
-        constructor(canvas: HTMLCanvasElement, antialias?: boolean, options?: { antialias?: boolean, preserveDrawingBuffer?: boolean }, adaptToDeviceRatio = true) {
+        constructor(canvas: HTMLCanvasElement, antialias?: boolean, options?: { antialias?: boolean, preserveDrawingBuffer?: boolean, limitDeviceRatio?: number }, adaptToDeviceRatio = true) {
             this._renderingCanvas = canvas;
 
             options = options || {};
@@ -621,7 +372,8 @@
             window.addEventListener("focus", this._onFocus);
 
             // Viewport
-            this._hardwareScalingLevel = adaptToDeviceRatio ? 1.0 / (window.devicePixelRatio || 1.0) : 1.0;
+            var limitDeviceRatio = options.limitDeviceRatio || window.devicePixelRatio || 1.0;
+            this._hardwareScalingLevel = adaptToDeviceRatio ? 1.0 / Math.min(limitDeviceRatio, window.devicePixelRatio || 1.0) : 1.0;
             this.resize();
 
             // Caps