瀏覽代碼

Merge remote-tracking branch 'upstream/master' into prepass-geometry-buffer

Benjamin Guignabert 4 年之前
父節點
當前提交
3411c4f9e4
共有 36 個文件被更改,包括 664 次插入497 次删除
  1. 0 2
      .github/ISSUE_TEMPLATE.md
  2. 0 2
      .github/ISSUE_TEMPLATE/bug_report.md
  3. 6 4
      dist/preview release/babylon.d.ts
  4. 1 1
      dist/preview release/babylon.js
  5. 186 206
      dist/preview release/babylon.max.js
  6. 1 1
      dist/preview release/babylon.max.js.map
  7. 12 8
      dist/preview release/babylon.module.d.ts
  8. 6 4
      dist/preview release/documentation.d.ts
  9. 2 2
      dist/preview release/nodeEditor/babylon.nodeEditor.d.ts
  10. 5 5
      dist/preview release/nodeEditor/babylon.nodeEditor.js
  11. 74 46
      dist/preview release/nodeEditor/babylon.nodeEditor.max.js
  12. 1 1
      dist/preview release/nodeEditor/babylon.nodeEditor.max.js.map
  13. 4 4
      dist/preview release/nodeEditor/babylon.nodeEditor.module.d.ts
  14. 1 1
      dist/preview release/packagesSizeBaseLine.json
  15. 16 1
      dist/preview release/serializers/babylon.glTF2Serializer.js
  16. 1 1
      dist/preview release/serializers/babylon.glTF2Serializer.js.map
  17. 1 1
      dist/preview release/serializers/babylon.glTF2Serializer.min.js
  18. 16 1
      dist/preview release/serializers/babylonjs.serializers.js
  19. 1 1
      dist/preview release/serializers/babylonjs.serializers.js.map
  20. 1 1
      dist/preview release/serializers/babylonjs.serializers.min.js
  21. 12 8
      dist/preview release/viewer/babylon.module.d.ts
  22. 6 6
      dist/preview release/viewer/babylon.viewer.js
  23. 1 1
      dist/preview release/viewer/babylon.viewer.max.js
  24. 4 0
      dist/preview release/what's new.md
  25. 69 40
      nodeEditor/src/diagram/graphFrame.ts
  26. 0 1
      nodeEditor/src/diagram/nodePort.ts
  27. 16 2
      serializers/src/glTF/2.0/glTFExporter.ts
  28. 10 12
      src/Cameras/Inputs/flyCameraMouseInput.ts
  29. 10 6
      src/Cameras/Inputs/freeCameraMouseInput.ts
  30. 157 119
      src/Engines/nativeEngine.ts
  31. 2 2
      src/Materials/Node/nodeMaterialBlockConnectionPoint.ts
  32. 5 3
      src/Materials/Textures/Procedurals/proceduralTexture.ts
  33. 12 1
      src/Materials/Textures/videoTexture.ts
  34. 1 0
      src/Misc/index.ts
  35. 19 2
      src/XR/features/WebXRHandTracking.ts
  36. 5 1
      src/scene.ts

+ 0 - 2
.github/ISSUE_TEMPLATE.md

@@ -2,8 +2,6 @@
 
 We have a really active forum to help answering questions (https://forum.babylonjs.com/)
 
-*If you are convinced that you found a bug, please use the following template for your issue:*
-
 # Bugs
 
 - Bug repro on [playground](https://playground.babylonjs.com):

+ 0 - 2
.github/ISSUE_TEMPLATE/bug_report.md

@@ -11,8 +11,6 @@ assignees: ''
 
 We have a really active forum to help answering questions (https://forum.babylonjs.com/)
 
-*If you are convinced that you found a bug, please use the following template for your issue:*
-
 **Repro**
 - Bug repro on [playground](https://playground.babylonjs.com):
 - Expected result:

+ 6 - 4
dist/preview release/babylon.d.ts

@@ -11796,8 +11796,9 @@ declare module BABYLON {
          * @param fallbackTexture Define a fallback texture in case there were issues to create the custom texture
          * @param generateMipMaps Define if the texture should creates mip maps or not
          * @param isCube Define if the texture is a cube texture or not (this will render each faces of the cube)
+         * @param textureType The FBO internal texture type
          */
-        constructor(name: string, size: RenderTargetTextureSize, fragment: any, scene: Nullable<Scene>, fallbackTexture?: Nullable<Texture>, generateMipMaps?: boolean, isCube?: boolean);
+        constructor(name: string, size: RenderTargetTextureSize, fragment: any, scene: Nullable<Scene>, fallbackTexture?: Nullable<Texture>, generateMipMaps?: boolean, isCube?: boolean, textureType?: number);
         /**
          * The effect that is created when initializing the post process.
          * @returns The created effect corresponding the the postprocess.
@@ -44330,7 +44331,6 @@ declare module BABYLON {
          * Higher values reduce its sensitivity.
          */
         angularSensibility: number;
-        private _mousemoveCallback;
         private _observer;
         private _rollObserver;
         private previousPosition;
@@ -53201,8 +53201,6 @@ declare module BABYLON {
          * @returns the cube texture as an InternalTexture
          */
         createCubeTexture(rootUrl: string, scene: Nullable<Scene>, files: Nullable<string[]>, noMipmap?: boolean, onLoad?: Nullable<(data?: any) => void>, onError?: Nullable<(message?: string, exception?: any) => void>, format?: number, forcedExtension?: any, createPolynomials?: boolean, lodScale?: number, lodOffset?: number, fallback?: Nullable<InternalTexture>): InternalTexture;
-        private _getSamplingFilter;
-        private static _GetNativeTextureFormat;
         createRenderTargetTexture(size: number | {
             width: number;
             height: number;
@@ -53235,6 +53233,10 @@ declare module BABYLON {
         _uploadArrayBufferViewToTexture(texture: InternalTexture, imageData: ArrayBufferView, faceIndex?: number, lod?: number): void;
         /** @hidden */
         _uploadImageToTexture(texture: InternalTexture, image: HTMLImageElement, faceIndex?: number, lod?: number): void;
+        private _getNativeSamplingMode;
+        private _getNativeTextureFormat;
+        private _getNativeAlphaMode;
+        private _getNativeAttribType;
     }
 }
 declare module BABYLON {

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


+ 186 - 206
dist/preview release/babylon.max.js

@@ -15043,11 +15043,6 @@ var FlyCameraMouseInput = /** @class */ (function () {
                 _this.camera.restoreRoll(_this.camera.rollCorrect);
             }
         });
-        // Helper function to keep 'this'.
-        this._mousemoveCallback = function (e) {
-            _this._onMouseMove(e);
-        };
-        element.addEventListener("mousemove", this._mousemoveCallback, false);
     };
     /**
      * Detach the current controls from the specified dom element.
@@ -15057,9 +15052,6 @@ var FlyCameraMouseInput = /** @class */ (function () {
         if (this._observer && element) {
             this.camera.getScene().onPointerObservable.remove(this._observer);
             this.camera.getScene().onBeforeRenderObservable.remove(this._rollObserver);
-            if (this._mousemoveCallback) {
-                element.removeEventListener("mousemove", this._mousemoveCallback);
-            }
             this._observer = null;
             this._rollObserver = null;
             this.previousPosition = null;
@@ -15113,6 +15105,10 @@ var FlyCameraMouseInput = /** @class */ (function () {
                 e.preventDefault();
                 this.element.focus();
             }
+            // This is required to move while pointer button is down
+            if (engine.isPointerLock) {
+                this._onMouseMove(p.event);
+            }
         }
         else 
         // Mouse up.
@@ -15132,7 +15128,10 @@ var FlyCameraMouseInput = /** @class */ (function () {
         else 
         // Mouse move.
         if (p.type === _Events_pointerEvents__WEBPACK_IMPORTED_MODULE_3__["PointerEventTypes"].POINTERMOVE) {
-            if (!this.previousPosition || engine.isPointerLock) {
+            if (!this.previousPosition) {
+                if (engine.isPointerLock) {
+                    this._onMouseMove(p.event);
+                }
                 return;
             }
             var offsetX = e.clientX - this.previousPosition.x;
@@ -16611,7 +16610,10 @@ var FreeCameraMouseInput = /** @class */ (function () {
                     }
                 }
                 else if (p.type === _Events_pointerEvents__WEBPACK_IMPORTED_MODULE_4__["PointerEventTypes"].POINTERMOVE) {
-                    if (!_this.previousPosition || engine.isPointerLock) {
+                    if (!_this.previousPosition) {
+                        if (engine.isPointerLock && _this._onMouseMove) {
+                            _this._onMouseMove(p.event);
+                        }
                         return;
                     }
                     var offsetX = evt.clientX - _this.previousPosition.x;
@@ -16660,7 +16662,6 @@ var FreeCameraMouseInput = /** @class */ (function () {
             }
         };
         this._observer = this.camera.getScene().onPointerObservable.add(this._pointerInput, _Events_pointerEvents__WEBPACK_IMPORTED_MODULE_4__["PointerEventTypes"].POINTERDOWN | _Events_pointerEvents__WEBPACK_IMPORTED_MODULE_4__["PointerEventTypes"].POINTERUP | _Events_pointerEvents__WEBPACK_IMPORTED_MODULE_4__["PointerEventTypes"].POINTERMOVE);
-        element.addEventListener("mousemove", this._onMouseMove, false);
         element.addEventListener("contextmenu", this.onContextMenu.bind(this), false);
     };
     /**
@@ -16677,9 +16678,6 @@ var FreeCameraMouseInput = /** @class */ (function () {
     FreeCameraMouseInput.prototype.detachControl = function (element) {
         if (this._observer && element) {
             this.camera.getScene().onPointerObservable.remove(this._observer);
-            if (this._onMouseMove) {
-                element.removeEventListener("mousemove", this._onMouseMove);
-            }
             if (this.onContextMenu) {
                 element.removeEventListener("contextmenu", this.onContextMenu);
             }
@@ -37310,18 +37308,20 @@ __webpack_require__.r(__webpack_exports__);
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "NativeEngine", function() { return NativeEngine; });
 /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! tslib */ "../node_modules/tslib/tslib.es6.js");
 /* harmony import */ var _Engines_engine__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../Engines/engine */ "./Engines/engine.ts");
-/* harmony import */ var _Materials_Textures_internalTexture__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../Materials/Textures/internalTexture */ "./Materials/Textures/internalTexture.ts");
-/* harmony import */ var _Materials_Textures_texture__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../Materials/Textures/texture */ "./Materials/Textures/texture.ts");
-/* harmony import */ var _Meshes_dataBuffer__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../Meshes/dataBuffer */ "./Meshes/dataBuffer.ts");
-/* harmony import */ var _Misc_tools__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../Misc/tools */ "./Misc/tools.ts");
-/* harmony import */ var _Misc_environmentTextureTools__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../Misc/environmentTextureTools */ "./Misc/environmentTextureTools.ts");
-/* harmony import */ var _Materials_Textures_renderTargetCreationOptions__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../Materials/Textures/renderTargetCreationOptions */ "./Materials/Textures/renderTargetCreationOptions.ts");
-/* harmony import */ var _Misc_logger__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ../Misc/logger */ "./Misc/logger.ts");
-/* harmony import */ var _constants__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ./constants */ "./Engines/constants.ts");
-/* harmony import */ var _thinEngine__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ./thinEngine */ "./Engines/thinEngine.ts");
-/* harmony import */ var _engineStore__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ./engineStore */ "./Engines/engineStore.ts");
-/* harmony import */ var _Processors_shaderCodeInliner__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! ./Processors/shaderCodeInliner */ "./Engines/Processors/shaderCodeInliner.ts");
-/* harmony import */ var _Engines_WebGL_webGL2ShaderProcessors__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! ../Engines/WebGL/webGL2ShaderProcessors */ "./Engines/WebGL/webGL2ShaderProcessors.ts");
+/* harmony import */ var _Meshes_buffer__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../Meshes/buffer */ "./Meshes/buffer.ts");
+/* harmony import */ var _Materials_Textures_internalTexture__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../Materials/Textures/internalTexture */ "./Materials/Textures/internalTexture.ts");
+/* harmony import */ var _Materials_Textures_texture__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../Materials/Textures/texture */ "./Materials/Textures/texture.ts");
+/* harmony import */ var _Meshes_dataBuffer__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../Meshes/dataBuffer */ "./Meshes/dataBuffer.ts");
+/* harmony import */ var _Misc_tools__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../Misc/tools */ "./Misc/tools.ts");
+/* harmony import */ var _Misc_environmentTextureTools__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../Misc/environmentTextureTools */ "./Misc/environmentTextureTools.ts");
+/* harmony import */ var _Materials_Textures_renderTargetCreationOptions__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ../Materials/Textures/renderTargetCreationOptions */ "./Materials/Textures/renderTargetCreationOptions.ts");
+/* harmony import */ var _Misc_logger__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ../Misc/logger */ "./Misc/logger.ts");
+/* harmony import */ var _constants__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ./constants */ "./Engines/constants.ts");
+/* harmony import */ var _thinEngine__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ./thinEngine */ "./Engines/thinEngine.ts");
+/* harmony import */ var _engineStore__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! ./engineStore */ "./Engines/engineStore.ts");
+/* harmony import */ var _Processors_shaderCodeInliner__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! ./Processors/shaderCodeInliner */ "./Engines/Processors/shaderCodeInliner.ts");
+/* harmony import */ var _Engines_WebGL_webGL2ShaderProcessors__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! ../Engines/WebGL/webGL2ShaderProcessors */ "./Engines/WebGL/webGL2ShaderProcessors.ts");
+
 
 
 
@@ -37363,72 +37363,7 @@ var NativeDataBuffer = /** @class */ (function (_super) {
         return _super !== null && _super.apply(this, arguments) || this;
     }
     return NativeDataBuffer;
-}(_Meshes_dataBuffer__WEBPACK_IMPORTED_MODULE_4__["DataBuffer"]));
-// TODO: change this to match bgfx.
-// Must match Filter enum in SpectreEngine.h.
-var NativeFilter = /** @class */ (function () {
-    function NativeFilter() {
-    }
-    NativeFilter.POINT = 0;
-    NativeFilter.MINPOINT_MAGPOINT_MIPPOINT = NativeFilter.POINT;
-    NativeFilter.BILINEAR = 1;
-    NativeFilter.MINLINEAR_MAGLINEAR_MIPPOINT = NativeFilter.BILINEAR;
-    NativeFilter.TRILINEAR = 2;
-    NativeFilter.MINLINEAR_MAGLINEAR_MIPLINEAR = NativeFilter.TRILINEAR;
-    NativeFilter.ANISOTROPIC = 3;
-    NativeFilter.POINT_COMPARE = 4;
-    NativeFilter.TRILINEAR_COMPARE = 5;
-    NativeFilter.MINBILINEAR_MAGPOINT = 6;
-    NativeFilter.MINLINEAR_MAGPOINT_MIPLINEAR = NativeFilter.MINBILINEAR_MAGPOINT;
-    NativeFilter.MINPOINT_MAGPOINT_MIPLINEAR = 7;
-    NativeFilter.MINPOINT_MAGLINEAR_MIPPOINT = 8;
-    NativeFilter.MINPOINT_MAGLINEAR_MIPLINEAR = 9;
-    NativeFilter.MINLINEAR_MAGPOINT_MIPPOINT = 10;
-    return NativeFilter;
-}());
-// depth test values
-// Values match bgfx defines
-var DepthTest = /** @class */ (function () {
-    function DepthTest() {
-    }
-    DepthTest.DEPTH_TEST_LESS = 16;
-    DepthTest.DEPTH_TEST_LEQUAL = 32;
-    DepthTest.DEPTH_TEST_EQUAL = 48;
-    DepthTest.DEPTH_TEST_GEQUAL = 64;
-    DepthTest.DEPTH_TEST_GREATER = 80;
-    DepthTest.DEPTH_TEST_NOTEQUAL = 96;
-    DepthTest.DEPTH_TEST_NEVER = 112;
-    DepthTest.DEPTH_TEST_ALWAYS = 128;
-    return DepthTest;
-}());
-// these flags match bgfx.
-var NativeClearFlags = /** @class */ (function () {
-    function NativeClearFlags() {
-    }
-    NativeClearFlags.CLEAR_COLOR = 1;
-    NativeClearFlags.CLEAR_DEPTH = 2;
-    NativeClearFlags.CLEAR_STENCIL = 4;
-    return NativeClearFlags;
-}());
-// TODO: change this to match bgfx.
-// Must match AddressMode enum in SpectreEngine.h.
-var NativeAddressMode = /** @class */ (function () {
-    function NativeAddressMode() {
-    }
-    NativeAddressMode.WRAP = 0;
-    NativeAddressMode.MIRROR = 1;
-    NativeAddressMode.CLAMP = 2;
-    NativeAddressMode.BORDER = 3;
-    NativeAddressMode.MIRROR_ONCE = 4;
-    return NativeAddressMode;
-}());
-var NativeTextureFormat = /** @class */ (function () {
-    function NativeTextureFormat() {
-    }
-    NativeTextureFormat.RGBA8 = 0;
-    NativeTextureFormat.RGBA32F = 1;
-    return NativeTextureFormat;
-}());
+}(_Meshes_dataBuffer__WEBPACK_IMPORTED_MODULE_5__["DataBuffer"]));
 /** @hidden */
 var NativeTexture = /** @class */ (function (_super) {
     Object(tslib__WEBPACK_IMPORTED_MODULE_0__["__extends"])(NativeTexture, _super);
@@ -37442,7 +37377,7 @@ var NativeTexture = /** @class */ (function (_super) {
         return 1;
     };
     return NativeTexture;
-}(_Materials_Textures_internalTexture__WEBPACK_IMPORTED_MODULE_2__["InternalTexture"]));
+}(_Materials_Textures_internalTexture__WEBPACK_IMPORTED_MODULE_3__["InternalTexture"]));
 /** @hidden */
 var NativeEngine = /** @class */ (function (_super) {
     Object(tslib__WEBPACK_IMPORTED_MODULE_0__["__extends"])(NativeEngine, _super);
@@ -37452,7 +37387,7 @@ var NativeEngine = /** @class */ (function (_super) {
         /** Defines the invalid handle returned by bgfx when resource creation goes wrong */
         _this.INVALID_HANDLE = 65535;
         _this._boundBuffersVertexArray = null;
-        _this._currentDepthTest = DepthTest.DEPTH_TEST_LEQUAL;
+        _this._currentDepthTest = _this._native.DEPTH_TEST_LEQUAL;
         _this._webGLVersion = 2;
         _this.disableUniformBuffers = true;
         // TODO: Initialize this more correctly based on the hardware capabilities.
@@ -37494,9 +37429,9 @@ var NativeEngine = /** @class */ (function (_super) {
             blendMinMax: false,
             maxMSAASamples: 1
         };
-        _Misc_tools__WEBPACK_IMPORTED_MODULE_5__["Tools"].Log("Babylon Native (v" + _Engines_engine__WEBPACK_IMPORTED_MODULE_1__["Engine"].Version + ") launched");
-        _Misc_tools__WEBPACK_IMPORTED_MODULE_5__["Tools"].LoadScript = function (scriptUrl, onSuccess, onError, scriptId) {
-            _Misc_tools__WEBPACK_IMPORTED_MODULE_5__["Tools"].LoadFile(scriptUrl, function (data) {
+        _Misc_tools__WEBPACK_IMPORTED_MODULE_6__["Tools"].Log("Babylon Native (v" + _Engines_engine__WEBPACK_IMPORTED_MODULE_1__["Engine"].Version + ") launched");
+        _Misc_tools__WEBPACK_IMPORTED_MODULE_6__["Tools"].LoadScript = function (scriptUrl, onSuccess, onError, scriptId) {
+            _Misc_tools__WEBPACK_IMPORTED_MODULE_6__["Tools"].LoadFile(scriptUrl, function (data) {
                 Function(data).apply(null);
                 if (onSuccess) {
                     onSuccess();
@@ -37518,7 +37453,7 @@ var NativeEngine = /** @class */ (function (_super) {
             window.Blob = function () { };
         }
         // Shader processor
-        _this._shaderProcessor = new _Engines_WebGL_webGL2ShaderProcessors__WEBPACK_IMPORTED_MODULE_13__["WebGL2ShaderProcessor"]();
+        _this._shaderProcessor = new _Engines_WebGL_webGL2ShaderProcessors__WEBPACK_IMPORTED_MODULE_14__["WebGL2ShaderProcessor"]();
         return _this;
     }
     NativeEngine.prototype.getHardwareScalingLevel = function () {
@@ -37575,15 +37510,15 @@ var NativeEngine = /** @class */ (function (_super) {
         var mode = 0;
         if (backBuffer && color) {
             this._native.clearColor(color.r, color.g, color.b, color.a !== undefined ? color.a : 1.0);
-            mode |= NativeClearFlags.CLEAR_COLOR;
+            mode |= this._native.CLEAR_FLAG_COLOR;
         }
         if (depth) {
             this._native.clearDepth(1.0);
-            mode |= NativeClearFlags.CLEAR_DEPTH;
+            mode |= this._native.CLEAR_FLAG_DEPTH;
         }
         if (stencil) {
             this._native.clearStencil(0);
-            mode |= NativeClearFlags.CLEAR_STENCIL;
+            mode |= this._native.CLEAR_FLAG_STENCIL;
         }
         this._native.clear(mode);
     };
@@ -37625,7 +37560,7 @@ var NativeEngine = /** @class */ (function (_super) {
                 if (vertexBuffer) {
                     var buffer = vertexBuffer.getBuffer();
                     if (buffer) {
-                        this._native.recordVertexBuffer(vertexArray, buffer.nativeVertexBuffer, location_1, vertexBuffer.byteOffset, vertexBuffer.byteStride, vertexBuffer.getSize(), vertexBuffer.type, vertexBuffer.normalized);
+                        this._native.recordVertexBuffer(vertexArray, buffer.nativeVertexBuffer, location_1, vertexBuffer.byteOffset, vertexBuffer.byteStride, vertexBuffer.getSize(), this._getNativeAttribType(vertexBuffer.type), vertexBuffer.normalized);
                     }
                 }
             }
@@ -37720,14 +37655,14 @@ var NativeEngine = /** @class */ (function (_super) {
     NativeEngine.prototype.createShaderProgram = function (pipelineContext, vertexCode, fragmentCode, defines, context, transformFeedbackVaryings) {
         if (transformFeedbackVaryings === void 0) { transformFeedbackVaryings = null; }
         this.onBeforeShaderCompilationObservable.notifyObservers(this);
-        var vertexInliner = new _Processors_shaderCodeInliner__WEBPACK_IMPORTED_MODULE_12__["ShaderCodeInliner"](vertexCode);
+        var vertexInliner = new _Processors_shaderCodeInliner__WEBPACK_IMPORTED_MODULE_13__["ShaderCodeInliner"](vertexCode);
         vertexInliner.processCode();
         vertexCode = vertexInliner.code;
-        var fragmentInliner = new _Processors_shaderCodeInliner__WEBPACK_IMPORTED_MODULE_12__["ShaderCodeInliner"](fragmentCode);
+        var fragmentInliner = new _Processors_shaderCodeInliner__WEBPACK_IMPORTED_MODULE_13__["ShaderCodeInliner"](fragmentCode);
         fragmentInliner.processCode();
         fragmentCode = fragmentInliner.code;
-        vertexCode = _thinEngine__WEBPACK_IMPORTED_MODULE_10__["ThinEngine"]._ConcatenateShader(vertexCode, defines);
-        fragmentCode = _thinEngine__WEBPACK_IMPORTED_MODULE_10__["ThinEngine"]._ConcatenateShader(fragmentCode, defines);
+        vertexCode = _thinEngine__WEBPACK_IMPORTED_MODULE_11__["ThinEngine"]._ConcatenateShader(vertexCode, defines);
+        fragmentCode = _thinEngine__WEBPACK_IMPORTED_MODULE_11__["ThinEngine"]._ConcatenateShader(fragmentCode, defines);
         var program = this._native.createProgram(vertexCode, fragmentCode);
         this.onAfterShaderCompilationObservable.notifyObservers(this);
         return program;
@@ -37813,7 +37748,7 @@ var NativeEngine = /** @class */ (function (_super) {
      * @param enable defines the state to set
      */
     NativeEngine.prototype.setDepthBuffer = function (enable) {
-        this._native.setDepthTest(enable ? this._currentDepthTest : DepthTest.DEPTH_TEST_ALWAYS);
+        this._native.setDepthTest(enable ? this._currentDepthTest : this._native.DEPTH_TEST_ALWAYS);
     };
     /**
      * Gets a boolean indicating if depth writing is enabled
@@ -37823,19 +37758,19 @@ var NativeEngine = /** @class */ (function (_super) {
         return this._native.getDepthWrite();
     };
     NativeEngine.prototype.setDepthFunctionToGreater = function () {
-        this._currentDepthTest = DepthTest.DEPTH_TEST_GREATER;
+        this._currentDepthTest = this._native.DEPTH_TEST_GREATER;
         this._native.setDepthTest(this._currentDepthTest);
     };
     NativeEngine.prototype.setDepthFunctionToGreaterOrEqual = function () {
-        this._currentDepthTest = DepthTest.DEPTH_TEST_GEQUAL;
+        this._currentDepthTest = this._native.DEPTH_TEST_GEQUAL;
         this._native.setDepthTest(this._currentDepthTest);
     };
     NativeEngine.prototype.setDepthFunctionToLess = function () {
-        this._currentDepthTest = DepthTest.DEPTH_TEST_LESS;
+        this._currentDepthTest = this._native.DEPTH_TEST_LESS;
         this._native.setDepthTest(this._currentDepthTest);
     };
     NativeEngine.prototype.setDepthFunctionToLessOrEqual = function () {
-        this._currentDepthTest = DepthTest.DEPTH_TEST_LEQUAL;
+        this._currentDepthTest = this._native.DEPTH_TEST_LEQUAL;
         this._native.setDepthTest(this._currentDepthTest);
     };
     /**
@@ -37881,9 +37816,10 @@ var NativeEngine = /** @class */ (function (_super) {
         if (this._alphaMode === mode) {
             return;
         }
+        mode = this._getNativeAlphaMode(mode);
         this._native.setBlendMode(mode);
         if (!noDepthWriteChange) {
-            this.setDepthWrite(mode === _constants__WEBPACK_IMPORTED_MODULE_9__["Constants"].ALPHA_DISABLE);
+            this.setDepthWrite(mode === _constants__WEBPACK_IMPORTED_MODULE_10__["Constants"].ALPHA_DISABLE);
         }
         this._alphaMode = mode;
     };
@@ -38094,7 +38030,7 @@ var NativeEngine = /** @class */ (function (_super) {
      */
     NativeEngine.prototype.createTexture = function (url, noMipmap, invertY, scene, samplingMode, onLoad, onError, buffer, fallback, format, forcedExtension, mimeType) {
         var _this = this;
-        if (samplingMode === void 0) { samplingMode = _constants__WEBPACK_IMPORTED_MODULE_9__["Constants"].TEXTURE_TRILINEAR_SAMPLINGMODE; }
+        if (samplingMode === void 0) { samplingMode = _constants__WEBPACK_IMPORTED_MODULE_10__["Constants"].TEXTURE_TRILINEAR_SAMPLINGMODE; }
         if (onLoad === void 0) { onLoad = null; }
         if (onError === void 0) { onError = null; }
         if (buffer === void 0) { buffer = null; }
@@ -38105,7 +38041,7 @@ var NativeEngine = /** @class */ (function (_super) {
         var fromData = url.substr(0, 5) === "data:";
         //const fromBlob = url.substr(0, 5) === "blob:";
         var isBase64 = fromData && url.indexOf(";base64,") !== -1;
-        var texture = fallback ? fallback : new _Materials_Textures_internalTexture__WEBPACK_IMPORTED_MODULE_2__["InternalTexture"](this, _Materials_Textures_internalTexture__WEBPACK_IMPORTED_MODULE_2__["InternalTextureSource"].Url);
+        var texture = fallback ? fallback : new _Materials_Textures_internalTexture__WEBPACK_IMPORTED_MODULE_3__["InternalTexture"](this, _Materials_Textures_internalTexture__WEBPACK_IMPORTED_MODULE_3__["InternalTextureSource"].Url);
         var originalUrl = url;
         if (this._transformTextureUrl && !isBase64 && !fallback && !buffer) {
             url = this._transformTextureUrl(url);
@@ -38147,16 +38083,16 @@ var NativeEngine = /** @class */ (function (_super) {
                 if (onLoadObserver) {
                     texture.onLoadedObservable.remove(onLoadObserver);
                 }
-                if (_engineStore__WEBPACK_IMPORTED_MODULE_11__["EngineStore"].UseFallbackTexture) {
-                    _this.createTexture(_engineStore__WEBPACK_IMPORTED_MODULE_11__["EngineStore"].FallbackTexture, noMipmap, texture.invertY, scene, samplingMode, null, onError, buffer, texture);
+                if (_engineStore__WEBPACK_IMPORTED_MODULE_12__["EngineStore"].UseFallbackTexture) {
+                    _this.createTexture(_engineStore__WEBPACK_IMPORTED_MODULE_12__["EngineStore"].FallbackTexture, noMipmap, texture.invertY, scene, samplingMode, null, onError, buffer, texture);
                 }
                 if (onError) {
-                    onError((message || "Unknown error") + (_engineStore__WEBPACK_IMPORTED_MODULE_11__["EngineStore"].UseFallbackTexture ? " - Fallback texture was used" : ""), exception);
+                    onError((message || "Unknown error") + (_engineStore__WEBPACK_IMPORTED_MODULE_12__["EngineStore"].UseFallbackTexture ? " - Fallback texture was used" : ""), exception);
                 }
             }
             else {
                 // fall back to the original url if the transformed url fails to load
-                _Misc_logger__WEBPACK_IMPORTED_MODULE_8__["Logger"].Warn("Failed to load " + url + ", falling back to " + originalUrl);
+                _Misc_logger__WEBPACK_IMPORTED_MODULE_9__["Logger"].Warn("Failed to load " + url + ", falling back to " + originalUrl);
                 _this.createTexture(originalUrl, noMipmap, texture.invertY, scene, samplingMode, onLoad, onError, buffer, texture, format, forcedExtension, mimeType);
             }
         };
@@ -38179,7 +38115,7 @@ var NativeEngine = /** @class */ (function (_super) {
                     texture.width = texture.baseWidth;
                     texture.height = texture.baseHeight;
                     texture.isReady = true;
-                    var filter = _this._getSamplingFilter(samplingMode);
+                    var filter = _this._getNativeSamplingMode(samplingMode);
                     _this._native.setTextureSampling(webGLTexture, filter);
                     if (scene) {
                         scene._removePendingData(texture);
@@ -38198,7 +38134,7 @@ var NativeEngine = /** @class */ (function (_super) {
                     onload_1(buffer);
                 }
                 else if (typeof buffer === "string") {
-                    onload_1(new Uint8Array(_Misc_tools__WEBPACK_IMPORTED_MODULE_5__["Tools"].DecodeBase64(buffer)));
+                    onload_1(new Uint8Array(_Misc_tools__WEBPACK_IMPORTED_MODULE_6__["Tools"].DecodeBase64(buffer)));
                 }
                 else {
                     throw new Error("Unsupported buffer type");
@@ -38206,7 +38142,7 @@ var NativeEngine = /** @class */ (function (_super) {
             }
             else {
                 if (isBase64) {
-                    onload_1(new Uint8Array(_Misc_tools__WEBPACK_IMPORTED_MODULE_5__["Tools"].DecodeBase64(url)));
+                    onload_1(new Uint8Array(_Misc_tools__WEBPACK_IMPORTED_MODULE_6__["Tools"].DecodeBase64(url)));
                 }
                 else {
                     this._loadFile(url, function (data) { return onload_1(new Uint8Array(data)); }, undefined, undefined, true, function (request, exception) {
@@ -38242,7 +38178,7 @@ var NativeEngine = /** @class */ (function (_super) {
         if (lodScale === void 0) { lodScale = 0; }
         if (lodOffset === void 0) { lodOffset = 0; }
         if (fallback === void 0) { fallback = null; }
-        var texture = fallback ? fallback : new _Materials_Textures_internalTexture__WEBPACK_IMPORTED_MODULE_2__["InternalTexture"](this, _Materials_Textures_internalTexture__WEBPACK_IMPORTED_MODULE_2__["InternalTextureSource"].Cube);
+        var texture = fallback ? fallback : new _Materials_Textures_internalTexture__WEBPACK_IMPORTED_MODULE_3__["InternalTexture"](this, _Materials_Textures_internalTexture__WEBPACK_IMPORTED_MODULE_3__["InternalTextureSource"].Cube);
         texture.isCube = true;
         texture.url = rootUrl;
         texture.generateMipMaps = !noMipmap;
@@ -38257,10 +38193,10 @@ var NativeEngine = /** @class */ (function (_super) {
         // TODO: use texture loader to load env files?
         if (extension === ".env") {
             var onloaddata_1 = function (data) {
-                var info = _Misc_environmentTextureTools__WEBPACK_IMPORTED_MODULE_6__["EnvironmentTextureTools"].GetEnvInfo(data);
+                var info = _Misc_environmentTextureTools__WEBPACK_IMPORTED_MODULE_7__["EnvironmentTextureTools"].GetEnvInfo(data);
                 texture.width = info.width;
                 texture.height = info.width;
-                _Misc_environmentTextureTools__WEBPACK_IMPORTED_MODULE_6__["EnvironmentTextureTools"].UploadEnvSpherical(texture, info);
+                _Misc_environmentTextureTools__WEBPACK_IMPORTED_MODULE_7__["EnvironmentTextureTools"].UploadEnvSpherical(texture, info);
                 if (info.version !== 1) {
                     throw new Error("Unsupported babylon environment map version \"" + info.version + "\"");
                 }
@@ -38269,11 +38205,11 @@ var NativeEngine = /** @class */ (function (_super) {
                     throw new Error("Nothing else parsed so far");
                 }
                 texture._lodGenerationScale = specularInfo.lodGenerationScale;
-                var imageData = _Misc_environmentTextureTools__WEBPACK_IMPORTED_MODULE_6__["EnvironmentTextureTools"].CreateImageDataArrayBufferViews(data, info);
-                texture.format = _constants__WEBPACK_IMPORTED_MODULE_9__["Constants"].TEXTUREFORMAT_RGBA;
-                texture.type = _constants__WEBPACK_IMPORTED_MODULE_9__["Constants"].TEXTURETYPE_UNSIGNED_INT;
+                var imageData = _Misc_environmentTextureTools__WEBPACK_IMPORTED_MODULE_7__["EnvironmentTextureTools"].CreateImageDataArrayBufferViews(data, info);
+                texture.format = _constants__WEBPACK_IMPORTED_MODULE_10__["Constants"].TEXTUREFORMAT_RGBA;
+                texture.type = _constants__WEBPACK_IMPORTED_MODULE_10__["Constants"].TEXTURETYPE_UNSIGNED_INT;
                 texture.generateMipMaps = true;
-                texture.getEngine().updateTextureSamplingMode(_Materials_Textures_texture__WEBPACK_IMPORTED_MODULE_3__["Texture"].TRILINEAR_SAMPLINGMODE, texture);
+                texture.getEngine().updateTextureSamplingMode(_Materials_Textures_texture__WEBPACK_IMPORTED_MODULE_4__["Texture"].TRILINEAR_SAMPLINGMODE, texture);
                 texture._isRGBD = true;
                 texture.invertY = true;
                 _this._native.loadCubeTextureWithMips(texture._webGLTexture, imageData, function () {
@@ -38303,7 +38239,7 @@ var NativeEngine = /** @class */ (function (_super) {
             }
             // Reorder from [+X, +Y, +Z, -X, -Y, -Z] to [+X, -X, +Y, -Y, +Z, -Z].
             var reorderedFiles = [files[0], files[3], files[1], files[4], files[2], files[5]];
-            Promise.all(reorderedFiles.map(function (file) { return _Misc_tools__WEBPACK_IMPORTED_MODULE_5__["Tools"].LoadFileAsync(file).then(function (data) { return new Uint8Array(data); }); })).then(function (data) {
+            Promise.all(reorderedFiles.map(function (file) { return _Misc_tools__WEBPACK_IMPORTED_MODULE_6__["Tools"].LoadFileAsync(file).then(function (data) { return new Uint8Array(data); }); })).then(function (data) {
                 return new Promise(function (resolve, reject) {
                     _this._native.loadCubeTexture(texture._webGLTexture, data, !noMipmap, resolve, reject);
                 });
@@ -38321,86 +38257,40 @@ var NativeEngine = /** @class */ (function (_super) {
         this._internalTexturesCache.push(texture);
         return texture;
     };
-    // Returns a NativeFilter.XXXX value.
-    NativeEngine.prototype._getSamplingFilter = function (samplingMode) {
-        switch (samplingMode) {
-            case _constants__WEBPACK_IMPORTED_MODULE_9__["Constants"].TEXTURE_BILINEAR_SAMPLINGMODE:
-                return NativeFilter.MINLINEAR_MAGLINEAR_MIPPOINT;
-            case _constants__WEBPACK_IMPORTED_MODULE_9__["Constants"].TEXTURE_TRILINEAR_SAMPLINGMODE:
-                return NativeFilter.MINLINEAR_MAGLINEAR_MIPLINEAR;
-            case _constants__WEBPACK_IMPORTED_MODULE_9__["Constants"].TEXTURE_NEAREST_SAMPLINGMODE:
-                return NativeFilter.MINPOINT_MAGPOINT_MIPLINEAR;
-            case _constants__WEBPACK_IMPORTED_MODULE_9__["Constants"].TEXTURE_NEAREST_NEAREST_MIPNEAREST:
-                return NativeFilter.MINPOINT_MAGPOINT_MIPPOINT;
-            case _constants__WEBPACK_IMPORTED_MODULE_9__["Constants"].TEXTURE_NEAREST_LINEAR_MIPNEAREST:
-                return NativeFilter.MINLINEAR_MAGPOINT_MIPPOINT;
-            case _constants__WEBPACK_IMPORTED_MODULE_9__["Constants"].TEXTURE_NEAREST_LINEAR_MIPLINEAR:
-                return NativeFilter.MINLINEAR_MAGPOINT_MIPLINEAR;
-            case _constants__WEBPACK_IMPORTED_MODULE_9__["Constants"].TEXTURE_NEAREST_LINEAR:
-                return NativeFilter.MINLINEAR_MAGPOINT_MIPLINEAR;
-            case _constants__WEBPACK_IMPORTED_MODULE_9__["Constants"].TEXTURE_NEAREST_NEAREST:
-                return NativeFilter.MINPOINT_MAGPOINT_MIPPOINT;
-            case _constants__WEBPACK_IMPORTED_MODULE_9__["Constants"].TEXTURE_LINEAR_NEAREST_MIPNEAREST:
-                return NativeFilter.MINPOINT_MAGLINEAR_MIPPOINT;
-            case _constants__WEBPACK_IMPORTED_MODULE_9__["Constants"].TEXTURE_LINEAR_NEAREST_MIPLINEAR:
-                return NativeFilter.MINPOINT_MAGLINEAR_MIPLINEAR;
-            case _constants__WEBPACK_IMPORTED_MODULE_9__["Constants"].TEXTURE_LINEAR_LINEAR:
-                return NativeFilter.MINLINEAR_MAGLINEAR_MIPLINEAR;
-            case _constants__WEBPACK_IMPORTED_MODULE_9__["Constants"].TEXTURE_LINEAR_NEAREST:
-                return NativeFilter.MINPOINT_MAGLINEAR_MIPLINEAR;
-            case _constants__WEBPACK_IMPORTED_MODULE_9__["Constants"].TEXTURE_NEAREST_NEAREST_MIPLINEAR:
-                return NativeFilter.MINPOINT_MAGPOINT_MIPLINEAR;
-            case _constants__WEBPACK_IMPORTED_MODULE_9__["Constants"].TEXTURE_LINEAR_LINEAR_MIPNEAREST:
-                return NativeFilter.MINLINEAR_MAGLINEAR_MIPLINEAR;
-            default:
-                throw new Error("Unexpected sampling mode: " + samplingMode + ".");
-        }
-    };
-    NativeEngine._GetNativeTextureFormat = function (format, type) {
-        if (format == _constants__WEBPACK_IMPORTED_MODULE_9__["Constants"].TEXTUREFORMAT_RGBA && type == _constants__WEBPACK_IMPORTED_MODULE_9__["Constants"].TEXTURETYPE_UNSIGNED_INT) {
-            return NativeTextureFormat.RGBA8;
-        }
-        else if (format == _constants__WEBPACK_IMPORTED_MODULE_9__["Constants"].TEXTUREFORMAT_RGBA && type == _constants__WEBPACK_IMPORTED_MODULE_9__["Constants"].TEXTURETYPE_FLOAT) {
-            return NativeTextureFormat.RGBA32F;
-        }
-        else {
-            throw new Error("Unexpected texture format or type: format " + format + ", type " + type + ".");
-        }
-    };
     NativeEngine.prototype.createRenderTargetTexture = function (size, options) {
-        var fullOptions = new _Materials_Textures_renderTargetCreationOptions__WEBPACK_IMPORTED_MODULE_7__["RenderTargetCreationOptions"]();
+        var fullOptions = new _Materials_Textures_renderTargetCreationOptions__WEBPACK_IMPORTED_MODULE_8__["RenderTargetCreationOptions"]();
         if (options !== undefined && typeof options === "object") {
             fullOptions.generateMipMaps = options.generateMipMaps;
             fullOptions.generateDepthBuffer = options.generateDepthBuffer === undefined ? true : options.generateDepthBuffer;
             fullOptions.generateStencilBuffer = fullOptions.generateDepthBuffer && options.generateStencilBuffer;
-            fullOptions.type = options.type === undefined ? _constants__WEBPACK_IMPORTED_MODULE_9__["Constants"].TEXTURETYPE_UNSIGNED_INT : options.type;
-            fullOptions.samplingMode = options.samplingMode === undefined ? _constants__WEBPACK_IMPORTED_MODULE_9__["Constants"].TEXTURE_TRILINEAR_SAMPLINGMODE : options.samplingMode;
-            fullOptions.format = options.format === undefined ? _constants__WEBPACK_IMPORTED_MODULE_9__["Constants"].TEXTUREFORMAT_RGBA : options.format;
+            fullOptions.type = options.type === undefined ? _constants__WEBPACK_IMPORTED_MODULE_10__["Constants"].TEXTURETYPE_UNSIGNED_INT : options.type;
+            fullOptions.samplingMode = options.samplingMode === undefined ? _constants__WEBPACK_IMPORTED_MODULE_10__["Constants"].TEXTURE_TRILINEAR_SAMPLINGMODE : options.samplingMode;
+            fullOptions.format = options.format === undefined ? _constants__WEBPACK_IMPORTED_MODULE_10__["Constants"].TEXTUREFORMAT_RGBA : options.format;
         }
         else {
             fullOptions.generateMipMaps = options;
             fullOptions.generateDepthBuffer = true;
             fullOptions.generateStencilBuffer = false;
-            fullOptions.type = _constants__WEBPACK_IMPORTED_MODULE_9__["Constants"].TEXTURETYPE_UNSIGNED_INT;
-            fullOptions.samplingMode = _constants__WEBPACK_IMPORTED_MODULE_9__["Constants"].TEXTURE_TRILINEAR_SAMPLINGMODE;
-            fullOptions.format = _constants__WEBPACK_IMPORTED_MODULE_9__["Constants"].TEXTUREFORMAT_RGBA;
+            fullOptions.type = _constants__WEBPACK_IMPORTED_MODULE_10__["Constants"].TEXTURETYPE_UNSIGNED_INT;
+            fullOptions.samplingMode = _constants__WEBPACK_IMPORTED_MODULE_10__["Constants"].TEXTURE_TRILINEAR_SAMPLINGMODE;
+            fullOptions.format = _constants__WEBPACK_IMPORTED_MODULE_10__["Constants"].TEXTUREFORMAT_RGBA;
         }
-        if (fullOptions.type === _constants__WEBPACK_IMPORTED_MODULE_9__["Constants"].TEXTURETYPE_FLOAT && !this._caps.textureFloatLinearFiltering) {
+        if (fullOptions.type === _constants__WEBPACK_IMPORTED_MODULE_10__["Constants"].TEXTURETYPE_FLOAT && !this._caps.textureFloatLinearFiltering) {
             // if floating point linear (gl.FLOAT) then force to NEAREST_SAMPLINGMODE
-            fullOptions.samplingMode = _constants__WEBPACK_IMPORTED_MODULE_9__["Constants"].TEXTURE_NEAREST_SAMPLINGMODE;
+            fullOptions.samplingMode = _constants__WEBPACK_IMPORTED_MODULE_10__["Constants"].TEXTURE_NEAREST_SAMPLINGMODE;
         }
-        else if (fullOptions.type === _constants__WEBPACK_IMPORTED_MODULE_9__["Constants"].TEXTURETYPE_HALF_FLOAT && !this._caps.textureHalfFloatLinearFiltering) {
+        else if (fullOptions.type === _constants__WEBPACK_IMPORTED_MODULE_10__["Constants"].TEXTURETYPE_HALF_FLOAT && !this._caps.textureHalfFloatLinearFiltering) {
             // if floating point linear (HALF_FLOAT) then force to NEAREST_SAMPLINGMODE
-            fullOptions.samplingMode = _constants__WEBPACK_IMPORTED_MODULE_9__["Constants"].TEXTURE_NEAREST_SAMPLINGMODE;
+            fullOptions.samplingMode = _constants__WEBPACK_IMPORTED_MODULE_10__["Constants"].TEXTURE_NEAREST_SAMPLINGMODE;
         }
-        var texture = new NativeTexture(this, _Materials_Textures_internalTexture__WEBPACK_IMPORTED_MODULE_2__["InternalTextureSource"].RenderTarget);
+        var texture = new NativeTexture(this, _Materials_Textures_internalTexture__WEBPACK_IMPORTED_MODULE_3__["InternalTextureSource"].RenderTarget);
         var width = size.width || size;
         var height = size.height || size;
-        if (fullOptions.type === _constants__WEBPACK_IMPORTED_MODULE_9__["Constants"].TEXTURETYPE_FLOAT && !this._caps.textureFloat) {
-            fullOptions.type = _constants__WEBPACK_IMPORTED_MODULE_9__["Constants"].TEXTURETYPE_UNSIGNED_INT;
-            _Misc_logger__WEBPACK_IMPORTED_MODULE_8__["Logger"].Warn("Float textures are not supported. Render target forced to TEXTURETYPE_UNSIGNED_BYTE type");
+        if (fullOptions.type === _constants__WEBPACK_IMPORTED_MODULE_10__["Constants"].TEXTURETYPE_FLOAT && !this._caps.textureFloat) {
+            fullOptions.type = _constants__WEBPACK_IMPORTED_MODULE_10__["Constants"].TEXTURETYPE_UNSIGNED_INT;
+            _Misc_logger__WEBPACK_IMPORTED_MODULE_9__["Logger"].Warn("Float textures are not supported. Render target forced to TEXTURETYPE_UNSIGNED_BYTE type");
         }
-        var framebuffer = this._native.createFramebuffer(texture._webGLTexture, width, height, NativeEngine._GetNativeTextureFormat(fullOptions.format, fullOptions.type), fullOptions.samplingMode, fullOptions.generateStencilBuffer ? true : false, fullOptions.generateDepthBuffer, fullOptions.generateMipMaps ? true : false);
+        var framebuffer = this._native.createFramebuffer(texture._webGLTexture, width, height, this._getNativeTextureFormat(fullOptions.format, fullOptions.type), fullOptions.samplingMode, fullOptions.generateStencilBuffer ? true : false, fullOptions.generateDepthBuffer, fullOptions.generateMipMaps ? true : false);
         texture._framebuffer = framebuffer;
         texture.baseWidth = width;
         texture.baseHeight = height;
@@ -38419,7 +38309,7 @@ var NativeEngine = /** @class */ (function (_super) {
     };
     NativeEngine.prototype.updateTextureSamplingMode = function (samplingMode, texture) {
         if (texture._webGLTexture) {
-            var filter = this._getSamplingFilter(samplingMode);
+            var filter = this._getNativeSamplingMode(samplingMode);
             this._native.setTextureSampling(texture._webGLTexture, filter);
         }
         texture.samplingMode = samplingMode;
@@ -38439,7 +38329,7 @@ var NativeEngine = /** @class */ (function (_super) {
     NativeEngine.prototype.unBindFramebuffer = function (texture, disableGenerateMipMaps, onBeforeUnbind) {
         if (disableGenerateMipMaps === void 0) { disableGenerateMipMaps = false; }
         if (disableGenerateMipMaps) {
-            _Misc_logger__WEBPACK_IMPORTED_MODULE_8__["Logger"].Warn("Disabling mipmap generation not yet supported in NativeEngine. Ignoring.");
+            _Misc_logger__WEBPACK_IMPORTED_MODULE_9__["Logger"].Warn("Disabling mipmap generation not yet supported in NativeEngine. Ignoring.");
         }
         if (onBeforeUnbind) {
             onBeforeUnbind();
@@ -38489,7 +38379,7 @@ var NativeEngine = /** @class */ (function (_super) {
             this._activeChannel = channel;
             texture.update();
         }
-        else if (texture.delayLoadState === _constants__WEBPACK_IMPORTED_MODULE_9__["Constants"].DELAYLOADSTATE_NOTLOADED) { // Delay loading
+        else if (texture.delayLoadState === _constants__WEBPACK_IMPORTED_MODULE_10__["Constants"].DELAYLOADSTATE_NOTLOADED) { // Delay loading
             texture.delayLoad();
             return false;
         }
@@ -38538,12 +38428,12 @@ var NativeEngine = /** @class */ (function (_super) {
     // Returns a NativeAddressMode.XXX value.
     NativeEngine.prototype._getAddressMode = function (wrapMode) {
         switch (wrapMode) {
-            case _constants__WEBPACK_IMPORTED_MODULE_9__["Constants"].TEXTURE_WRAP_ADDRESSMODE:
-                return NativeAddressMode.WRAP;
-            case _constants__WEBPACK_IMPORTED_MODULE_9__["Constants"].TEXTURE_CLAMP_ADDRESSMODE:
-                return NativeAddressMode.CLAMP;
-            case _constants__WEBPACK_IMPORTED_MODULE_9__["Constants"].TEXTURE_MIRROR_ADDRESSMODE:
-                return NativeAddressMode.MIRROR;
+            case _constants__WEBPACK_IMPORTED_MODULE_10__["Constants"].TEXTURE_WRAP_ADDRESSMODE:
+                return this._native.ADDRESS_MODE_WRAP;
+            case _constants__WEBPACK_IMPORTED_MODULE_10__["Constants"].TEXTURE_CLAMP_ADDRESSMODE:
+                return this._native.ADDRESS_MODE_CLAMP;
+            case _constants__WEBPACK_IMPORTED_MODULE_10__["Constants"].TEXTURE_MIRROR_ADDRESSMODE:
+                return this._native.ADDRESS_MODE_MIRROR;
             default:
                 throw new Error("Unexpected wrap mode: " + wrapMode + ".");
         }
@@ -38589,6 +38479,92 @@ var NativeEngine = /** @class */ (function (_super) {
         if (lod === void 0) { lod = 0; }
         throw new Error("_uploadArrayBufferViewToTexture not implemented.");
     };
+    // JavaScript-to-Native conversion helper functions.
+    NativeEngine.prototype._getNativeSamplingMode = function (samplingMode) {
+        switch (samplingMode) {
+            case _constants__WEBPACK_IMPORTED_MODULE_10__["Constants"].TEXTURE_BILINEAR_SAMPLINGMODE:
+                return this._native.SAMPLER_BILINEAR;
+            case _constants__WEBPACK_IMPORTED_MODULE_10__["Constants"].TEXTURE_TRILINEAR_SAMPLINGMODE:
+                return this._native.SAMPLER_TRILINEAR;
+            case _constants__WEBPACK_IMPORTED_MODULE_10__["Constants"].TEXTURE_NEAREST_SAMPLINGMODE:
+                return this._native.SAMPLER_MINPOINT_MAGPOINT_MIPLINEAR;
+            case _constants__WEBPACK_IMPORTED_MODULE_10__["Constants"].TEXTURE_NEAREST_NEAREST_MIPNEAREST:
+                return this._native.SAMPLER_NEAREST;
+            case _constants__WEBPACK_IMPORTED_MODULE_10__["Constants"].TEXTURE_NEAREST_LINEAR_MIPNEAREST:
+                return this._native.SAMPLER_MINLINEAR_MAGPOINT_MIPPOINT;
+            case _constants__WEBPACK_IMPORTED_MODULE_10__["Constants"].TEXTURE_NEAREST_LINEAR_MIPLINEAR:
+                return this._native.SAMPLER_MINBILINEAR_MAGPOINT;
+            case _constants__WEBPACK_IMPORTED_MODULE_10__["Constants"].TEXTURE_NEAREST_LINEAR:
+                return this._native.SAMPLER_MINBILINEAR_MAGPOINT;
+            case _constants__WEBPACK_IMPORTED_MODULE_10__["Constants"].TEXTURE_NEAREST_NEAREST:
+                return this._native.SAMPLER_NEAREST;
+            case _constants__WEBPACK_IMPORTED_MODULE_10__["Constants"].TEXTURE_LINEAR_NEAREST_MIPNEAREST:
+                return this._native.SAMPLER_MINPOINT_MAGLINEAR_MIPPOINT;
+            case _constants__WEBPACK_IMPORTED_MODULE_10__["Constants"].TEXTURE_LINEAR_NEAREST_MIPLINEAR:
+                return this._native.SAMPLER_MINPOINT_MAGLINEAR_MIPLINEAR;
+            case _constants__WEBPACK_IMPORTED_MODULE_10__["Constants"].TEXTURE_LINEAR_LINEAR:
+                return this._native.SAMPLER_TRILINEAR;
+            case _constants__WEBPACK_IMPORTED_MODULE_10__["Constants"].TEXTURE_LINEAR_NEAREST:
+                return this._native.SAMPLER_MINPOINT_MAGLINEAR_MIPLINEAR;
+            case _constants__WEBPACK_IMPORTED_MODULE_10__["Constants"].TEXTURE_NEAREST_NEAREST_MIPLINEAR:
+                return this._native.SAMPLER_MINPOINT_MAGPOINT_MIPLINEAR;
+            case _constants__WEBPACK_IMPORTED_MODULE_10__["Constants"].TEXTURE_LINEAR_LINEAR_MIPNEAREST:
+                return this._native.SAMPLER_TRILINEAR;
+            default:
+                throw new Error("Unsupported sampling mode: " + samplingMode + ".");
+        }
+    };
+    NativeEngine.prototype._getNativeTextureFormat = function (format, type) {
+        if (format == _constants__WEBPACK_IMPORTED_MODULE_10__["Constants"].TEXTUREFORMAT_RGBA && type == _constants__WEBPACK_IMPORTED_MODULE_10__["Constants"].TEXTURETYPE_UNSIGNED_INT) {
+            return this._native.TEXTURE_FORMAT_RGBA8;
+        }
+        else if (format == _constants__WEBPACK_IMPORTED_MODULE_10__["Constants"].TEXTUREFORMAT_RGBA && type == _constants__WEBPACK_IMPORTED_MODULE_10__["Constants"].TEXTURETYPE_FLOAT) {
+            return this._native.TEXTURE_FORMAT_RGBA32F;
+        }
+        else {
+            throw new Error("Unsupported texture format or type: format " + format + ", type " + type + ".");
+        }
+    };
+    NativeEngine.prototype._getNativeAlphaMode = function (mode) {
+        switch (mode) {
+            case _constants__WEBPACK_IMPORTED_MODULE_10__["Constants"].ALPHA_DISABLE:
+                return this._native.ALPHA_DISABLE;
+            case _constants__WEBPACK_IMPORTED_MODULE_10__["Constants"].ALPHA_ADD:
+                return this._native.ALPHA_ADD;
+            case _constants__WEBPACK_IMPORTED_MODULE_10__["Constants"].ALPHA_COMBINE:
+                return this._native.ALPHA_COMBINE;
+            case _constants__WEBPACK_IMPORTED_MODULE_10__["Constants"].ALPHA_SUBTRACT:
+                return this._native.ALPHA_SUBTRACT;
+            case _constants__WEBPACK_IMPORTED_MODULE_10__["Constants"].ALPHA_MULTIPLY:
+                return this._native.ALPHA_MULTIPLY;
+            case _constants__WEBPACK_IMPORTED_MODULE_10__["Constants"].ALPHA_MAXIMIZED:
+                return this._native.ALPHA_MAXIMIZED;
+            case _constants__WEBPACK_IMPORTED_MODULE_10__["Constants"].ALPHA_ONEONE:
+                return this._native.ALPHA_ONEONE;
+            case _constants__WEBPACK_IMPORTED_MODULE_10__["Constants"].ALPHA_PREMULTIPLIED:
+                return this._native.ALPHA_PREMULTIPLIED;
+            case _constants__WEBPACK_IMPORTED_MODULE_10__["Constants"].ALPHA_PREMULTIPLIED_PORTERDUFF:
+                return this._native.ALPHA_PREMULTIPLIED_PORTERDUFF;
+            case _constants__WEBPACK_IMPORTED_MODULE_10__["Constants"].ALPHA_INTERPOLATE:
+                return this._native.ALPHA_INTERPOLATE;
+            case _constants__WEBPACK_IMPORTED_MODULE_10__["Constants"].ALPHA_SCREENMODE:
+                return this._native.ALPHA_SCREENMODE;
+            default:
+                throw new Error("Unsupported alpha mode: " + mode + ".");
+        }
+    };
+    NativeEngine.prototype._getNativeAttribType = function (type) {
+        switch (type) {
+            case _Meshes_buffer__WEBPACK_IMPORTED_MODULE_2__["VertexBuffer"].UNSIGNED_BYTE:
+                return this._native.ATTRIB_TYPE_UINT8;
+            case _Meshes_buffer__WEBPACK_IMPORTED_MODULE_2__["VertexBuffer"].SHORT:
+                return this._native.ATTRIB_TYPE_INT16;
+            case _Meshes_buffer__WEBPACK_IMPORTED_MODULE_2__["VertexBuffer"].FLOAT:
+                return this._native.ATTRIB_TYPE_FLOAT;
+            default:
+                throw new Error("Unsupported attribute type: " + type + ".");
+        }
+    };
     return NativeEngine;
 }(_Engines_engine__WEBPACK_IMPORTED_MODULE_1__["Engine"]));
 
@@ -82771,8 +82747,8 @@ var NodeMaterialConnectionPoint = /** @class */ (function () {
             serializationObject.isExposedOnFrame = true;
             serializationObject.exposedPortPosition = this.exposedPortPosition;
         }
-        if (this.isExposedOnFrame) {
-            serializationObject.isExposedOnFrame = this.isExposedOnFrame;
+        if (this.isExposedOnFrame || this.exposedPortPosition >= 0) {
+            serializationObject.isExposedOnFrame = true;
             serializationObject.exposedPortPosition = this.exposedPortPosition;
         }
         return serializationObject;
@@ -90055,6 +90031,8 @@ __webpack_require__.r(__webpack_exports__);
 /* harmony import */ var _Shaders_procedural_vertex__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ../../../Shaders/procedural.vertex */ "./Shaders/procedural.vertex.ts");
 /* harmony import */ var _Misc_typeStore__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! ../../../Misc/typeStore */ "./Misc/typeStore.ts");
 /* harmony import */ var _Engines_engineStore__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! ../../../Engines/engineStore */ "./Engines/engineStore.ts");
+/* harmony import */ var _Engines_constants__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! ../../../Engines/constants */ "./Engines/constants.ts");
+
 
 
 
@@ -90088,11 +90066,13 @@ var ProceduralTexture = /** @class */ (function (_super) {
      * @param fallbackTexture Define a fallback texture in case there were issues to create the custom texture
      * @param generateMipMaps Define if the texture should creates mip maps or not
      * @param isCube Define if the texture is a cube texture or not (this will render each faces of the cube)
+     * @param textureType The FBO internal texture type
      */
-    function ProceduralTexture(name, size, fragment, scene, fallbackTexture, generateMipMaps, isCube) {
+    function ProceduralTexture(name, size, fragment, scene, fallbackTexture, generateMipMaps, isCube, textureType) {
         if (fallbackTexture === void 0) { fallbackTexture = null; }
         if (generateMipMaps === void 0) { generateMipMaps = true; }
         if (isCube === void 0) { isCube = false; }
+        if (textureType === void 0) { textureType = _Engines_constants__WEBPACK_IMPORTED_MODULE_14__["Constants"].TEXTURETYPE_UNSIGNED_INT; }
         var _this = _super.call(this, null, scene, !generateMipMaps) || this;
         /**
          * Define if the texture is enabled or not (disabled texture will not render)
@@ -90148,11 +90128,11 @@ var ProceduralTexture = /** @class */ (function (_super) {
         _this.setFragment(fragment);
         _this._fallbackTexture = fallbackTexture;
         if (isCube) {
-            _this._texture = _this._fullEngine.createRenderTargetCubeTexture(size, { generateMipMaps: generateMipMaps, generateDepthBuffer: false, generateStencilBuffer: false });
+            _this._texture = _this._fullEngine.createRenderTargetCubeTexture(size, { generateMipMaps: generateMipMaps, generateDepthBuffer: false, generateStencilBuffer: false, type: textureType });
             _this.setFloat("face", 0);
         }
         else {
-            _this._texture = _this._fullEngine.createRenderTargetTexture(size, { generateMipMaps: generateMipMaps, generateDepthBuffer: false, generateStencilBuffer: false });
+            _this._texture = _this._fullEngine.createRenderTargetTexture(size, { generateMipMaps: generateMipMaps, generateDepthBuffer: false, generateStencilBuffer: false, type: textureType });
         }
         // VBO
         var vertices = [];
@@ -195155,7 +195135,7 @@ var WebXRFeaturesManager = /** @class */ (function () {
             };
             if (attachIfPossible) {
                 // if session started already, request and enable
-                if (this._xrSessionManager.session && !feature.featureImplementation.attached) {
+                if (this._xrSessionManager.session && !this._features[name].featureImplementation.attached) {
                     // enable feature
                     this.attachFeature(name);
                 }

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


+ 12 - 8
dist/preview release/babylon.module.d.ts

@@ -12062,8 +12062,9 @@ declare module "babylonjs/Materials/Textures/Procedurals/proceduralTexture" {
          * @param fallbackTexture Define a fallback texture in case there were issues to create the custom texture
          * @param generateMipMaps Define if the texture should creates mip maps or not
          * @param isCube Define if the texture is a cube texture or not (this will render each faces of the cube)
+         * @param textureType The FBO internal texture type
          */
-        constructor(name: string, size: RenderTargetTextureSize, fragment: any, scene: Nullable<Scene>, fallbackTexture?: Nullable<Texture>, generateMipMaps?: boolean, isCube?: boolean);
+        constructor(name: string, size: RenderTargetTextureSize, fragment: any, scene: Nullable<Scene>, fallbackTexture?: Nullable<Texture>, generateMipMaps?: boolean, isCube?: boolean, textureType?: number);
         /**
          * The effect that is created when initializing the post process.
          * @returns The created effect corresponding the the postprocess.
@@ -45904,7 +45905,6 @@ declare module "babylonjs/Cameras/Inputs/flyCameraMouseInput" {
          * Higher values reduce its sensitivity.
          */
         angularSensibility: number;
-        private _mousemoveCallback;
         private _observer;
         private _rollObserver;
         private previousPosition;
@@ -55380,8 +55380,6 @@ declare module "babylonjs/Engines/nativeEngine" {
          * @returns the cube texture as an InternalTexture
          */
         createCubeTexture(rootUrl: string, scene: Nullable<Scene>, files: Nullable<string[]>, noMipmap?: boolean, onLoad?: Nullable<(data?: any) => void>, onError?: Nullable<(message?: string, exception?: any) => void>, format?: number, forcedExtension?: any, createPolynomials?: boolean, lodScale?: number, lodOffset?: number, fallback?: Nullable<InternalTexture>): InternalTexture;
-        private _getSamplingFilter;
-        private static _GetNativeTextureFormat;
         createRenderTargetTexture(size: number | {
             width: number;
             height: number;
@@ -55414,6 +55412,10 @@ declare module "babylonjs/Engines/nativeEngine" {
         _uploadArrayBufferViewToTexture(texture: InternalTexture, imageData: ArrayBufferView, faceIndex?: number, lod?: number): void;
         /** @hidden */
         _uploadImageToTexture(texture: InternalTexture, image: HTMLImageElement, faceIndex?: number, lod?: number): void;
+        private _getNativeSamplingMode;
+        private _getNativeTextureFormat;
+        private _getNativeAlphaMode;
+        private _getNativeAttribType;
     }
 }
 declare module "babylonjs/Engines/index" {
@@ -92280,8 +92282,9 @@ declare module BABYLON {
          * @param fallbackTexture Define a fallback texture in case there were issues to create the custom texture
          * @param generateMipMaps Define if the texture should creates mip maps or not
          * @param isCube Define if the texture is a cube texture or not (this will render each faces of the cube)
+         * @param textureType The FBO internal texture type
          */
-        constructor(name: string, size: RenderTargetTextureSize, fragment: any, scene: Nullable<Scene>, fallbackTexture?: Nullable<Texture>, generateMipMaps?: boolean, isCube?: boolean);
+        constructor(name: string, size: RenderTargetTextureSize, fragment: any, scene: Nullable<Scene>, fallbackTexture?: Nullable<Texture>, generateMipMaps?: boolean, isCube?: boolean, textureType?: number);
         /**
          * The effect that is created when initializing the post process.
          * @returns The created effect corresponding the the postprocess.
@@ -124814,7 +124817,6 @@ declare module BABYLON {
          * Higher values reduce its sensitivity.
          */
         angularSensibility: number;
-        private _mousemoveCallback;
         private _observer;
         private _rollObserver;
         private previousPosition;
@@ -133685,8 +133687,6 @@ declare module BABYLON {
          * @returns the cube texture as an InternalTexture
          */
         createCubeTexture(rootUrl: string, scene: Nullable<Scene>, files: Nullable<string[]>, noMipmap?: boolean, onLoad?: Nullable<(data?: any) => void>, onError?: Nullable<(message?: string, exception?: any) => void>, format?: number, forcedExtension?: any, createPolynomials?: boolean, lodScale?: number, lodOffset?: number, fallback?: Nullable<InternalTexture>): InternalTexture;
-        private _getSamplingFilter;
-        private static _GetNativeTextureFormat;
         createRenderTargetTexture(size: number | {
             width: number;
             height: number;
@@ -133719,6 +133719,10 @@ declare module BABYLON {
         _uploadArrayBufferViewToTexture(texture: InternalTexture, imageData: ArrayBufferView, faceIndex?: number, lod?: number): void;
         /** @hidden */
         _uploadImageToTexture(texture: InternalTexture, image: HTMLImageElement, faceIndex?: number, lod?: number): void;
+        private _getNativeSamplingMode;
+        private _getNativeTextureFormat;
+        private _getNativeAlphaMode;
+        private _getNativeAttribType;
     }
 }
 declare module BABYLON {

+ 6 - 4
dist/preview release/documentation.d.ts

@@ -11796,8 +11796,9 @@ declare module BABYLON {
          * @param fallbackTexture Define a fallback texture in case there were issues to create the custom texture
          * @param generateMipMaps Define if the texture should creates mip maps or not
          * @param isCube Define if the texture is a cube texture or not (this will render each faces of the cube)
+         * @param textureType The FBO internal texture type
          */
-        constructor(name: string, size: RenderTargetTextureSize, fragment: any, scene: Nullable<Scene>, fallbackTexture?: Nullable<Texture>, generateMipMaps?: boolean, isCube?: boolean);
+        constructor(name: string, size: RenderTargetTextureSize, fragment: any, scene: Nullable<Scene>, fallbackTexture?: Nullable<Texture>, generateMipMaps?: boolean, isCube?: boolean, textureType?: number);
         /**
          * The effect that is created when initializing the post process.
          * @returns The created effect corresponding the the postprocess.
@@ -44330,7 +44331,6 @@ declare module BABYLON {
          * Higher values reduce its sensitivity.
          */
         angularSensibility: number;
-        private _mousemoveCallback;
         private _observer;
         private _rollObserver;
         private previousPosition;
@@ -53201,8 +53201,6 @@ declare module BABYLON {
          * @returns the cube texture as an InternalTexture
          */
         createCubeTexture(rootUrl: string, scene: Nullable<Scene>, files: Nullable<string[]>, noMipmap?: boolean, onLoad?: Nullable<(data?: any) => void>, onError?: Nullable<(message?: string, exception?: any) => void>, format?: number, forcedExtension?: any, createPolynomials?: boolean, lodScale?: number, lodOffset?: number, fallback?: Nullable<InternalTexture>): InternalTexture;
-        private _getSamplingFilter;
-        private static _GetNativeTextureFormat;
         createRenderTargetTexture(size: number | {
             width: number;
             height: number;
@@ -53235,6 +53233,10 @@ declare module BABYLON {
         _uploadArrayBufferViewToTexture(texture: InternalTexture, imageData: ArrayBufferView, faceIndex?: number, lod?: number): void;
         /** @hidden */
         _uploadImageToTexture(texture: InternalTexture, image: HTMLImageElement, faceIndex?: number, lod?: number): void;
+        private _getNativeSamplingMode;
+        private _getNativeTextureFormat;
+        private _getNativeAlphaMode;
+        private _getNativeAttribType;
     }
 }
 declare module BABYLON {

+ 2 - 2
dist/preview release/nodeEditor/babylon.nodeEditor.d.ts

@@ -180,7 +180,8 @@ declare module NODEEDITOR {
         private _createInputPort;
         private _markFramePortPositions;
         private _createFramePorts;
-        private removePortFromExposed;
+        private removePortFromExposedWithNode;
+        private removePortFromExposedWithLink;
         private createInputPorts;
         private createOutputPorts;
         private _redrawFramePorts;
@@ -279,7 +280,6 @@ declare module NODEEDITOR {
         protected _onCandidateLinkMovedObserver: BABYLON.Nullable<BABYLON.Observer<BABYLON.Nullable<BABYLON.Vector2>>>;
         protected _onSelectionChangedObserver: BABYLON.Nullable<BABYLON.Observer<BABYLON.Nullable<GraphFrame | GraphNode | NodeLink | NodePort | FramePortData>>>;
         protected _exposedOnFrame: boolean;
-        isExposed: boolean;
         delegatedPort: BABYLON.Nullable<FrameNodePort>;
         get element(): HTMLDivElement;
         get portName(): string;

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


+ 74 - 46
dist/preview release/nodeEditor/babylon.nodeEditor.max.js

@@ -67715,9 +67715,10 @@ var GraphFrame = /** @class */ (function () {
         this._frameInPorts.push(localPort);
         port.delegatedPort = localPort;
         this._controlledPorts.push(port);
-        if (!port.isExposed) {
-            port.isExposed = true;
+        port.exposedPortPosition = this._exposedInPorts.findIndex(function (nodePort) { return nodePort === port; });
+        if (port.exposedPortPosition < 0) {
             this._exposedInPorts.push(port);
+            port.exposedPortPosition = this._exposedInPorts.length - 1;
         }
     };
     // Mark ports with FramePortPosition for re-arrangement support
@@ -67766,79 +67767,107 @@ var GraphFrame = /** @class */ (function () {
             var node = _a[_i];
             node.isVisible = false;
         }
-        for (var _b = 0, _c = this._exposedOutPorts; _b < _c.length; _b++) { // Output
-            var port = _c[_b];
+        for (var i = 0; i < this._exposedOutPorts.length;) { // Output
+            var port = this._exposedOutPorts[i];
             if (port.node === null || port.node.enclosingFrameId != this.id) {
-                var index = this._exposedOutPorts.findIndex(function (nodePort) { return nodePort === port; });
-                this._exposedOutPorts.splice(index, 1);
-                port.isExposed = false;
+                if (this.removePortFromExposedWithNode(port, this._exposedOutPorts))
+                    continue;
             }
             else {
-                this.createOutputPorts(port, port.node);
+                if (!this.createOutputPorts(port, port.node) && this.removePortFromExposedWithNode(port, this._exposedOutPorts)) {
+                    continue;
+                }
             }
+            ++i;
         }
-        for (var _d = 0, _e = this._exposedInPorts; _d < _e.length; _d++) { // Input
-            var port = _e[_d];
+        for (var i = 0; i < this._exposedInPorts.length;) { // Input
+            var port = this._exposedInPorts[i];
             if (port.node === null || port.node.enclosingFrameId != this.id) {
-                var index = this._exposedInPorts.findIndex(function (nodePort) { return nodePort === port; });
-                this._exposedInPorts.splice(index, 1);
-                port.isExposed = false;
+                if (this.removePortFromExposedWithNode(port, this._exposedInPorts)) {
+                    continue;
+                }
             }
             else {
-                this.createInputPorts(port, port.node);
+                if (!this.createInputPorts(port, port.node) && this.removePortFromExposedWithNode(port, this._exposedInPorts)) {
+                    continue;
+                }
             }
+            ++i;
         }
-        for (var _f = 0, _g = this._nodes; _f < _g.length; _f++) {
-            var node = _g[_f];
-            for (var _h = 0, _j = node.outputPorts; _h < _j.length; _h++) { // Output
-                var port = _j[_h];
-                if (!port.isExposed) {
-                    if (this.createOutputPorts(port, node)) {
-                        this._exposedOutPorts.push(port);
-                        port.isExposed = true;
+        for (var _b = 0, _c = this._nodes; _b < _c.length; _b++) {
+            var node = _c[_b];
+            var _loop_1 = function (port_1) {
+                port_1.exposedPortPosition = this_1._exposedOutPorts.findIndex(function (nodePort) { return nodePort === port_1; });
+                if (port_1.exposedPortPosition < 0) {
+                    if (this_1.createOutputPorts(port_1, node)) {
+                        port_1.node.enclosingFrameId = this_1.id;
+                        this_1._exposedOutPorts.push(port_1);
+                        port_1.exposedPortPosition = this_1._exposedOutPorts.length - 1;
                     }
                 }
+            };
+            var this_1 = this;
+            for (var _d = 0, _e = node.outputPorts; _d < _e.length; _d++) {
+                var port_1 = _e[_d];
+                _loop_1(port_1);
             }
-            for (var _k = 0, _l = node.inputPorts; _k < _l.length; _k++) { // Input
-                var port = _l[_k];
-                if (!port.isExposed) {
+            for (var _f = 0, _g = node.inputPorts; _f < _g.length; _f++) { // Input
+                var port = _g[_f];
+                port.exposedPortPosition = this._exposedInPorts.findIndex(function (nodePort) { return nodePort === port; });
+                if (port.exposedPortPosition < 0) {
                     this.createInputPorts(port, node);
                 }
             }
         }
     };
-    GraphFrame.prototype.removePortFromExposed = function (nodeLink, exposedPorts) {
+    GraphFrame.prototype.removePortFromExposedWithNode = function (port, exposedPorts) {
+        var index = exposedPorts.findIndex(function (nodePort) { return nodePort === port; });
+        if (index >= 0) {
+            exposedPorts.splice(index, 1);
+            port.exposedPortPosition = -1;
+            return true;
+        }
+        return false;
+    };
+    GraphFrame.prototype.removePortFromExposedWithLink = function (nodeLink, exposedPorts) {
         var aPort = exposedPorts.findIndex(function (nodePort) { return nodePort === nodeLink.portA; });
         var bPort = exposedPorts.findIndex(function (nodePort) { return nodePort === nodeLink.portB; });
         if (aPort >= 0) {
             exposedPorts.splice(aPort, 1);
-            nodeLink.portA.isExposed = false;
+            nodeLink.portA.exposedPortPosition = -1;
         }
         else if (bPort >= 0) {
             exposedPorts.splice(bPort, 1);
-            if (nodeLink.portB)
-                nodeLink.portB.isExposed = false;
+            if (nodeLink.portB) {
+                nodeLink.portB.exposedPortPosition = -1;
+            }
         }
     };
     GraphFrame.prototype.createInputPorts = function (port, node) {
         var _this_1 = this;
         if (port.connectionPoint.isConnected) {
+            var portAdded = false;
             for (var _i = 0, _a = node.links; _i < _a.length; _i++) {
                 var link = _a[_i];
                 if (link.portB === port && this.nodes.indexOf(link.nodeA) === -1) {
                     this._createInputPort(port, node);
                     link.isVisible = true;
+                    portAdded = true;
                     var onLinkDisposedObserver = link.onDisposedObservable.add(function (nodeLink) {
-                        _this_1.removePortFromExposed(nodeLink, _this_1._exposedInPorts);
+                        _this_1.removePortFromExposedWithLink(nodeLink, _this_1._exposedInPorts);
                         _this_1._redrawFramePorts();
                     });
                     this._onNodeLinkDisposedObservers.push(onLinkDisposedObserver);
                 }
             }
+            if (portAdded)
+                return true;
         }
         else if (port.exposedOnFrame) {
             this._createInputPort(port, node);
+            return true;
         }
+        return false;
     };
     GraphFrame.prototype.createOutputPorts = function (port, node) {
         var _this_1 = this;
@@ -67846,7 +67875,7 @@ var GraphFrame = /** @class */ (function () {
             var portAdded = false;
             for (var _i = 0, _a = node.links; _i < _a.length; _i++) {
                 var link = _a[_i];
-                if (link.portA === port && this.nodes.indexOf(link.nodeB) === -1 || (link.portA === port && port.exposedOnFrame)) {
+                if (link.portA === port && this.nodes.indexOf(link.nodeB) === -1) {
                     var localPort = void 0;
                     if (!portAdded) {
                         portAdded = true;
@@ -67854,7 +67883,7 @@ var GraphFrame = /** @class */ (function () {
                         this._frameOutPorts.push(localPort);
                         link.isVisible = true;
                         var onLinkDisposedObserver = link.onDisposedObservable.add(function (nodeLink) {
-                            _this_1.removePortFromExposed(nodeLink, _this_1._exposedOutPorts);
+                            _this_1.removePortFromExposedWithLink(nodeLink, _this_1._exposedOutPorts);
                             _this_1._redrawFramePorts();
                         });
                         this._onNodeLinkDisposedObservers.push(onLinkDisposedObserver);
@@ -67868,9 +67897,17 @@ var GraphFrame = /** @class */ (function () {
                     }
                     port.delegatedPort = localPort;
                     this._controlledPorts.push(port);
-                    return true;
+                }
+                else if (port.exposedPortPosition >= 0 && !portAdded) {
+                    var localPort = _frameNodePort__WEBPACK_IMPORTED_MODULE_3__["FrameNodePort"].CreateFrameNodePortElement(port.connectionPoint, node, this._outputPortContainer, null, this._ownerCanvas.globalState, false, GraphFrame._FramePortCounter++, this.id);
+                    this._frameOutPorts.push(localPort);
+                    port.delegatedPort = localPort;
+                    this._controlledPorts.push(port);
+                    portAdded = true;
                 }
             }
+            if (portAdded)
+                return true;
         }
         else if (port.exposedOnFrame) {
             var localPort = _frameNodePort__WEBPACK_IMPORTED_MODULE_3__["FrameNodePort"].CreateFrameNodePortElement(port.connectionPoint, node, this._outputPortContainer, null, this._ownerCanvas.globalState, false, GraphFrame._FramePortCounter++, this.id);
@@ -68331,7 +68368,7 @@ var GraphFrame = /** @class */ (function () {
         newFrame.color = babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_0__["Color3"].FromArray(serializationData.color);
         newFrame.comments = serializationData.comments;
         if (serializationData.blocks && map) {
-            var _loop_1 = function () {
+            var _loop_2 = function () {
                 var actualId = map[blockId];
                 var node_1 = canvas.nodes.filter(function (n) { return n.block.uniqueId === actualId; });
                 if (node_1.length) {
@@ -68341,7 +68378,7 @@ var GraphFrame = /** @class */ (function () {
             };
             for (var _i = 0, _a = serializationData.blocks; _i < _a.length; _i++) {
                 var blockId = _a[_i];
-                _loop_1();
+                _loop_2();
             }
         }
         else {
@@ -68352,25 +68389,17 @@ var GraphFrame = /** @class */ (function () {
             for (var _d = 0, _e = node.outputPorts; _d < _e.length; _d++) { // Output
                 var port = _e[_d];
                 if (port.exposedOnFrame) {
-                    port.isExposed = true;
-                    if (port.exposedPortPosition) {
+                    if (port.exposedPortPosition !== -1) {
                         newFrame._exposedOutPorts[port.exposedPortPosition] = port;
                     }
-                    else {
-                        newFrame._exposedOutPorts.push(port);
-                    }
                 }
             }
             for (var _f = 0, _g = node.inputPorts; _f < _g.length; _f++) { // Inports
                 var port = _g[_f];
                 if (port.exposedOnFrame) {
-                    port.isExposed = true;
-                    if (port.exposedPortPosition) {
+                    if (port.exposedPortPosition !== -1) {
                         newFrame._exposedInPorts[port.exposedPortPosition] = port;
                     }
-                    else {
-                        newFrame._exposedInPorts.push(port);
-                    }
                 }
             }
         }
@@ -69033,7 +69062,6 @@ var NodePort = /** @class */ (function () {
         var _this = this;
         this.connectionPoint = connectionPoint;
         this.node = node;
-        this.isExposed = false;
         this.delegatedPort = null;
         this._element = portContainer.ownerDocument.createElement("div");
         this._element.classList.add("port");

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


+ 4 - 4
dist/preview release/nodeEditor/babylon.nodeEditor.module.d.ts

@@ -281,7 +281,8 @@ declare module "babylonjs-node-editor/diagram/graphFrame" {
         private _createInputPort;
         private _markFramePortPositions;
         private _createFramePorts;
-        private removePortFromExposed;
+        private removePortFromExposedWithNode;
+        private removePortFromExposedWithLink;
         private createInputPorts;
         private createOutputPorts;
         private _redrawFramePorts;
@@ -391,7 +392,6 @@ declare module "babylonjs-node-editor/diagram/nodePort" {
         protected _onCandidateLinkMovedObserver: Nullable<Observer<Nullable<Vector2>>>;
         protected _onSelectionChangedObserver: Nullable<Observer<Nullable<GraphFrame | GraphNode | NodeLink | NodePort | FramePortData>>>;
         protected _exposedOnFrame: boolean;
-        isExposed: boolean;
         delegatedPort: Nullable<FrameNodePort>;
         get element(): HTMLDivElement;
         get portName(): string;
@@ -2096,7 +2096,8 @@ declare module NODEEDITOR {
         private _createInputPort;
         private _markFramePortPositions;
         private _createFramePorts;
-        private removePortFromExposed;
+        private removePortFromExposedWithNode;
+        private removePortFromExposedWithLink;
         private createInputPorts;
         private createOutputPorts;
         private _redrawFramePorts;
@@ -2195,7 +2196,6 @@ declare module NODEEDITOR {
         protected _onCandidateLinkMovedObserver: BABYLON.Nullable<BABYLON.Observer<BABYLON.Nullable<BABYLON.Vector2>>>;
         protected _onSelectionChangedObserver: BABYLON.Nullable<BABYLON.Observer<BABYLON.Nullable<GraphFrame | GraphNode | NodeLink | NodePort | FramePortData>>>;
         protected _exposedOnFrame: boolean;
-        isExposed: boolean;
         delegatedPort: BABYLON.Nullable<FrameNodePort>;
         get element(): HTMLDivElement;
         get portName(): string;

+ 1 - 1
dist/preview release/packagesSizeBaseLine.json

@@ -1 +1 @@
-{"thinEngineOnly":118576,"engineOnly":155016,"sceneOnly":521091,"minGridMaterial":661878,"minStandardMaterial":816230}
+{"thinEngineOnly":118576,"engineOnly":155016,"sceneOnly":521091,"minGridMaterial":661799,"minStandardMaterial":816151}

+ 16 - 1
dist/preview release/serializers/babylon.glTF2Serializer.js

@@ -1891,6 +1891,7 @@ __webpack_require__.r(__webpack_exports__);
 
 
 
+
 /**
  * Converts Babylon Scene into glTF 2.0.
  * @hidden
@@ -2426,9 +2427,23 @@ var _Exporter = /** @class */ (function () {
                 break;
             }
             case babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__["VertexBuffer"].ColorKind: {
+                var meshMaterial = babylonTransformNode.material;
+                var convertToLinear = meshMaterial ? (meshMaterial instanceof babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__["StandardMaterial"]) : true;
+                var vertexData = stride === 3 ? new babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__["Color3"]() : new babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__["Color4"]();
                 for (var k = 0, length_5 = meshAttributeArray.length / stride; k < length_5; ++k) {
                     index = k * stride;
-                    var vertexData = stride === 3 ? babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__["Vector3"].FromArray(meshAttributeArray, index) : babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__["Vector4"].FromArray(meshAttributeArray, index);
+                    if (stride === 3) {
+                        babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__["Color3"].FromArrayToRef(meshAttributeArray, index, vertexData);
+                        if (convertToLinear) {
+                            vertexData.toLinearSpaceToRef(vertexData);
+                        }
+                    }
+                    else {
+                        babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__["Color4"].FromArrayToRef(meshAttributeArray, index, vertexData);
+                        if (convertToLinear) {
+                            vertexData.toLinearSpaceToRef(vertexData);
+                        }
+                    }
                     vertexAttributes.push(vertexData.asArray());
                 }
                 break;

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


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


+ 16 - 1
dist/preview release/serializers/babylonjs.serializers.js

@@ -2076,6 +2076,7 @@ __webpack_require__.r(__webpack_exports__);
 
 
 
+
 /**
  * Converts Babylon Scene into glTF 2.0.
  * @hidden
@@ -2611,9 +2612,23 @@ var _Exporter = /** @class */ (function () {
                 break;
             }
             case babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__["VertexBuffer"].ColorKind: {
+                var meshMaterial = babylonTransformNode.material;
+                var convertToLinear = meshMaterial ? (meshMaterial instanceof babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__["StandardMaterial"]) : true;
+                var vertexData = stride === 3 ? new babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__["Color3"]() : new babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__["Color4"]();
                 for (var k = 0, length_5 = meshAttributeArray.length / stride; k < length_5; ++k) {
                     index = k * stride;
-                    var vertexData = stride === 3 ? babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__["Vector3"].FromArray(meshAttributeArray, index) : babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__["Vector4"].FromArray(meshAttributeArray, index);
+                    if (stride === 3) {
+                        babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__["Color3"].FromArrayToRef(meshAttributeArray, index, vertexData);
+                        if (convertToLinear) {
+                            vertexData.toLinearSpaceToRef(vertexData);
+                        }
+                    }
+                    else {
+                        babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__["Color4"].FromArrayToRef(meshAttributeArray, index, vertexData);
+                        if (convertToLinear) {
+                            vertexData.toLinearSpaceToRef(vertexData);
+                        }
+                    }
                     vertexAttributes.push(vertexData.asArray());
                 }
                 break;

文件差異過大導致無法顯示
+ 1 - 1
dist/preview release/serializers/babylonjs.serializers.js.map


文件差異過大導致無法顯示
+ 1 - 1
dist/preview release/serializers/babylonjs.serializers.min.js


+ 12 - 8
dist/preview release/viewer/babylon.module.d.ts

@@ -12062,8 +12062,9 @@ declare module "babylonjs/Materials/Textures/Procedurals/proceduralTexture" {
          * @param fallbackTexture Define a fallback texture in case there were issues to create the custom texture
          * @param generateMipMaps Define if the texture should creates mip maps or not
          * @param isCube Define if the texture is a cube texture or not (this will render each faces of the cube)
+         * @param textureType The FBO internal texture type
          */
-        constructor(name: string, size: RenderTargetTextureSize, fragment: any, scene: Nullable<Scene>, fallbackTexture?: Nullable<Texture>, generateMipMaps?: boolean, isCube?: boolean);
+        constructor(name: string, size: RenderTargetTextureSize, fragment: any, scene: Nullable<Scene>, fallbackTexture?: Nullable<Texture>, generateMipMaps?: boolean, isCube?: boolean, textureType?: number);
         /**
          * The effect that is created when initializing the post process.
          * @returns The created effect corresponding the the postprocess.
@@ -45904,7 +45905,6 @@ declare module "babylonjs/Cameras/Inputs/flyCameraMouseInput" {
          * Higher values reduce its sensitivity.
          */
         angularSensibility: number;
-        private _mousemoveCallback;
         private _observer;
         private _rollObserver;
         private previousPosition;
@@ -55380,8 +55380,6 @@ declare module "babylonjs/Engines/nativeEngine" {
          * @returns the cube texture as an InternalTexture
          */
         createCubeTexture(rootUrl: string, scene: Nullable<Scene>, files: Nullable<string[]>, noMipmap?: boolean, onLoad?: Nullable<(data?: any) => void>, onError?: Nullable<(message?: string, exception?: any) => void>, format?: number, forcedExtension?: any, createPolynomials?: boolean, lodScale?: number, lodOffset?: number, fallback?: Nullable<InternalTexture>): InternalTexture;
-        private _getSamplingFilter;
-        private static _GetNativeTextureFormat;
         createRenderTargetTexture(size: number | {
             width: number;
             height: number;
@@ -55414,6 +55412,10 @@ declare module "babylonjs/Engines/nativeEngine" {
         _uploadArrayBufferViewToTexture(texture: InternalTexture, imageData: ArrayBufferView, faceIndex?: number, lod?: number): void;
         /** @hidden */
         _uploadImageToTexture(texture: InternalTexture, image: HTMLImageElement, faceIndex?: number, lod?: number): void;
+        private _getNativeSamplingMode;
+        private _getNativeTextureFormat;
+        private _getNativeAlphaMode;
+        private _getNativeAttribType;
     }
 }
 declare module "babylonjs/Engines/index" {
@@ -92280,8 +92282,9 @@ declare module BABYLON {
          * @param fallbackTexture Define a fallback texture in case there were issues to create the custom texture
          * @param generateMipMaps Define if the texture should creates mip maps or not
          * @param isCube Define if the texture is a cube texture or not (this will render each faces of the cube)
+         * @param textureType The FBO internal texture type
          */
-        constructor(name: string, size: RenderTargetTextureSize, fragment: any, scene: Nullable<Scene>, fallbackTexture?: Nullable<Texture>, generateMipMaps?: boolean, isCube?: boolean);
+        constructor(name: string, size: RenderTargetTextureSize, fragment: any, scene: Nullable<Scene>, fallbackTexture?: Nullable<Texture>, generateMipMaps?: boolean, isCube?: boolean, textureType?: number);
         /**
          * The effect that is created when initializing the post process.
          * @returns The created effect corresponding the the postprocess.
@@ -124814,7 +124817,6 @@ declare module BABYLON {
          * Higher values reduce its sensitivity.
          */
         angularSensibility: number;
-        private _mousemoveCallback;
         private _observer;
         private _rollObserver;
         private previousPosition;
@@ -133685,8 +133687,6 @@ declare module BABYLON {
          * @returns the cube texture as an InternalTexture
          */
         createCubeTexture(rootUrl: string, scene: Nullable<Scene>, files: Nullable<string[]>, noMipmap?: boolean, onLoad?: Nullable<(data?: any) => void>, onError?: Nullable<(message?: string, exception?: any) => void>, format?: number, forcedExtension?: any, createPolynomials?: boolean, lodScale?: number, lodOffset?: number, fallback?: Nullable<InternalTexture>): InternalTexture;
-        private _getSamplingFilter;
-        private static _GetNativeTextureFormat;
         createRenderTargetTexture(size: number | {
             width: number;
             height: number;
@@ -133719,6 +133719,10 @@ declare module BABYLON {
         _uploadArrayBufferViewToTexture(texture: InternalTexture, imageData: ArrayBufferView, faceIndex?: number, lod?: number): void;
         /** @hidden */
         _uploadImageToTexture(texture: InternalTexture, image: HTMLImageElement, faceIndex?: number, lod?: number): void;
+        private _getNativeSamplingMode;
+        private _getNativeTextureFormat;
+        private _getNativeAlphaMode;
+        private _getNativeAttribType;
     }
 }
 declare module BABYLON {

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


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


+ 4 - 0
dist/preview release/what's new.md

@@ -49,6 +49,7 @@
 - Added support for multi-pointer mesh selection and pointer over/out triggers ([#8820](https://github.com/BabylonJS/Babylon.js/issues/8820)) ([RaananW](https://github.com/RaananW))
 - Changed DeviceSourceManager getInput contract to no longer return nullable values for reals this time. Also added proper cleanup for DeviceSourceManager observables ([Drigax](https://github.com/drigax))
 - Default Loading screen supports any image size and ratio ([#8845](https://github.com/BabylonJS/Babylon.js/issues/8845)) ([RaananW](https://github.com/RaananW))
+- Added optional success and error callbacks for freezeActiveMeshes ([RaananW](https://github.com/RaananW))
 
 ### Engine
 
@@ -166,6 +167,7 @@
 - Added the possibility to update the shader code before being compiled ([Popov72](https://github.com/Popov72))
 - Added the `shadowOnly` property to the `BackgroundMaterial` class ([Popov72](https://github.com/Popov72))
 - Added support for lightmaps in unlit PBR materials ([Popov72](https://github.com/Popov72))
+- Added `muted` setting to `VideoTexture`, fix autoplay in Chrome ([simonihmig](https://github.com/simonihmig))
 
 ### Meshes
 
@@ -322,6 +324,8 @@
 - Fix gltf2 Morph Target export code style, add additional test case for non-animation group created morph targets ([drigax](https://github.com/drigax))
 - Fix "Uncaught ReferenceError: name is not defined" ([outermeasure](https://github.com/outermeasure))
 - Fix wrong winding when applying a transform matrix on VertexData ([Popov72](https://github.com/Popov72))
+- Fix exporting vertex color of mesh with `StandardMaterial` when exporting to glTF ([Drigax](https://github.com/drigax))
+- Changed use of mousemove to pointermove in freeCameraMouseInput and flyCameraMouseInput to fix issue with Firefox ([PolygonalSun](https://github.com/PolygonalSun))
 
 ## Breaking changes
 - `FollowCamera.target` was renamed to `FollowCamera.meshTarget` to not be in conflict with `TargetCamera.target` ([Deltakosh](https://github.com/deltakosh))

+ 69 - 40
nodeEditor/src/diagram/graphFrame.ts

@@ -90,9 +90,10 @@ export class GraphFrame {
         port.delegatedPort = localPort;
         this._controlledPorts.push(port);
 
-        if(!port.isExposed) {
-            port.isExposed = true;
+        port.exposedPortPosition = this._exposedInPorts.findIndex(nodePort => nodePort === port);
+        if(port.exposedPortPosition < 0) {
             this._exposedInPorts.push(port);
+            port.exposedPortPosition = this._exposedInPorts.length -1;
         }
     }
 
@@ -139,82 +140,110 @@ export class GraphFrame {
             node.isVisible = false;
         }
 
-        for (var port of this._exposedOutPorts) { // Output
+        for (var i = 0; i < this._exposedOutPorts.length; ) { // Output
+            var port = this._exposedOutPorts[i];
             if(port.node === null || port.node.enclosingFrameId != this.id) {
-                let index = this._exposedOutPorts.findIndex(nodePort => nodePort === port);
-                this._exposedOutPorts.splice(index,1);
-                port.isExposed = false;
+                if(this.removePortFromExposedWithNode(port, this._exposedOutPorts))
+                    continue;
             }
             else {
-                this.createOutputPorts(port, port.node);
+                if(!this.createOutputPorts(port, port.node) && this.removePortFromExposedWithNode(port, this._exposedOutPorts)) {
+                    continue;
+                }
             }
+            ++i;
         }
 
-        for (var port of this._exposedInPorts) { // Input
+        for (var i = 0; i < this._exposedInPorts.length; ) { // Input
+            var port = this._exposedInPorts[i];
             if(port.node === null || port.node.enclosingFrameId != this.id) {
-                let index = this._exposedInPorts.findIndex(nodePort => nodePort === port);
-                this._exposedInPorts.splice(index,1);
-                port.isExposed = false;
+                if(this.removePortFromExposedWithNode(port, this._exposedInPorts)) {
+                    continue;
+                }
             }
             else {
-                this.createInputPorts(port, port.node);
+                if(!this.createInputPorts(port, port.node) && this.removePortFromExposedWithNode(port, this._exposedInPorts)) {
+                    continue;
+                }
             }
+            ++i;
         }
 
         for (var node of this._nodes) {
-            for (var port of node.outputPorts) { // Output
-                if(!port.isExposed) {
+            for (let port of node.outputPorts) { // Output
+                port.exposedPortPosition = this._exposedOutPorts.findIndex(nodePort => nodePort === port);
+                if(port.exposedPortPosition < 0) {
                     if(this.createOutputPorts(port,node)) {
+                        port.node.enclosingFrameId = this.id;
                         this._exposedOutPorts.push(port);
-                        port.isExposed = true;
+                        port.exposedPortPosition = this._exposedOutPorts.length - 1;
                     }
                 }
             }
             for (var port of node.inputPorts) { // Input
-                if(!port.isExposed){
+                port.exposedPortPosition = this._exposedInPorts.findIndex(nodePort => nodePort === port);
+                if(port.exposedPortPosition < 0){
                     this.createInputPorts(port, node);
                 }
             }
         }
     }
 
-    private removePortFromExposed(nodeLink: NodeLink, exposedPorts: NodePort[])
+    private removePortFromExposedWithNode(port: NodePort,exposedPorts: NodePort[])
+    {
+        let index = exposedPorts.findIndex(nodePort => nodePort === port);
+        if(index >= 0) {
+            exposedPorts.splice(index,1)
+            port.exposedPortPosition = -1;
+            return true;
+        }
+        return false;
+    }
+
+    private removePortFromExposedWithLink(nodeLink: NodeLink, exposedPorts: NodePort[])
     {
         let aPort = exposedPorts.findIndex(nodePort => nodePort === nodeLink.portA);
         let bPort = exposedPorts.findIndex(nodePort => nodePort === nodeLink.portB);
         if(aPort >= 0) {
             exposedPorts.splice(aPort,1);
-            nodeLink.portA.isExposed = false;
+            nodeLink.portA.exposedPortPosition = -1;
         } else if(bPort >= 0) {
             exposedPorts.splice(bPort,1);
-            if(nodeLink.portB) nodeLink.portB.isExposed = false;
+            if(nodeLink.portB){ 
+                nodeLink.portB.exposedPortPosition = -1
+            }
         }
     }
     
     private createInputPorts(port: NodePort, node: GraphNode){
         if (port.connectionPoint.isConnected) {
+            let portAdded = false;
             for (var link of node.links) {
                 if (link.portB === port && this.nodes.indexOf(link.nodeA) === -1) {
                     this._createInputPort(port, node);
                     link.isVisible = true;
+                    portAdded = true;
                     const onLinkDisposedObserver = link.onDisposedObservable.add((nodeLink: NodeLink) => {
-                        this.removePortFromExposed(nodeLink, this._exposedInPorts);
+                        this.removePortFromExposedWithLink(nodeLink, this._exposedInPorts);
                         this._redrawFramePorts();
                     });
                     this._onNodeLinkDisposedObservers.push(onLinkDisposedObserver);
                 }
             }
-        } else if(port.exposedOnFrame) {
+            if(portAdded) return true;
+        } 
+        else if(port.exposedOnFrame) {
             this._createInputPort(port, node);
+            return true;
         }
+        return false;
     }
 
     private createOutputPorts(port: NodePort, node: GraphNode){
         if (port.connectionPoint.hasEndpoints) {
             let portAdded = false;
-
             for (var link of node.links) {
-                if (link.portA === port && this.nodes.indexOf(link.nodeB!) === -1 || (link.portA === port && port.exposedOnFrame)) {
+                if (link.portA === port && this.nodes.indexOf(link.nodeB!) === -1) {
                     let localPort: FrameNodePort;
 
                     if (!portAdded) {
@@ -225,7 +254,7 @@ export class GraphFrame {
                         link.isVisible = true;
 
                         const onLinkDisposedObserver = link.onDisposedObservable.add((nodeLink: NodeLink) => {
-                            this.removePortFromExposed(nodeLink, this._exposedOutPorts);
+                            this.removePortFromExposedWithLink(nodeLink, this._exposedOutPorts);
                             this._redrawFramePorts();
                         });
 
@@ -237,20 +266,29 @@ export class GraphFrame {
                     } else {
                         localPort = this.ports.filter(p => p.connectionPoint === port.connectionPoint)[0];
                     }
-
                     port.delegatedPort = localPort;
                     this._controlledPorts.push(port);
-                    return true;
+                }
+                else if(port.exposedPortPosition >= 0 && !portAdded)
+                {
+                    let localPort = FrameNodePort.CreateFrameNodePortElement(port.connectionPoint, node, this._outputPortContainer, null, this._ownerCanvas.globalState, false, GraphFrame._FramePortCounter++, this.id);
+                    this._frameOutPorts.push(localPort);
+                    port.delegatedPort = localPort;
+                    this._controlledPorts.push(port);
+                    portAdded = true;
                 }
             }
-        } else if(port.exposedOnFrame) {
+            if(portAdded)  return true;
+        } 
+        else if(port.exposedOnFrame) {
             let localPort = FrameNodePort.CreateFrameNodePortElement(port.connectionPoint, node, this._outputPortContainer, null, this._ownerCanvas.globalState, false, GraphFrame._FramePortCounter++, this.id);
             this._frameOutPorts.push(localPort);
             port.delegatedPort = localPort;
             this._controlledPorts.push(port);
             return true;
         }
-        return false
+
+        return false;
     }
 
     private _redrawFramePorts() {
@@ -1427,28 +1465,19 @@ export class GraphFrame {
             newFrame.refresh();
         }
         
-        
         for (var node of newFrame.nodes) {
             for (var port of node.outputPorts) { // Output
                 if(port.exposedOnFrame) {
-                    port.isExposed = true;
-                    if(port.exposedPortPosition) { 
+                    if(port.exposedPortPosition !== -1) {
                         newFrame._exposedOutPorts[port.exposedPortPosition] = port;
                     }
-                    else {
-                        newFrame._exposedOutPorts.push(port);
-                    }
                 }
             }
 
             for (var port of node.inputPorts) { // Inports
                 if(port.exposedOnFrame) {
-                    port.isExposed = true;
-                    if(port.exposedPortPosition) { 
-                        newFrame._exposedInPorts[port.exposedPortPosition] = port;
-                    }
-                    else {
-                        newFrame._exposedInPorts.push(port);
+                    if(port.exposedPortPosition !== -1) {
+                         newFrame._exposedInPorts[port.exposedPortPosition] = port;
                     }
                 }
             }

+ 0 - 1
nodeEditor/src/diagram/nodePort.ts

@@ -20,7 +20,6 @@ export class NodePort {
     protected _onCandidateLinkMovedObserver: Nullable<Observer<Nullable<Vector2>>>;
     protected _onSelectionChangedObserver: Nullable<Observer<Nullable<GraphFrame | GraphNode | NodeLink | NodePort | FramePortData>>>;
     protected _exposedOnFrame: boolean;
-    public isExposed = false;
     public delegatedPort: Nullable<FrameNodePort> = null;
 
     public get element(): HTMLDivElement {

+ 16 - 2
serializers/src/glTF/2.0/glTFExporter.ts

@@ -2,7 +2,7 @@ import { AccessorType, IBufferView, IAccessor, INode, IScene, IMesh, IMaterial,
 
 import { FloatArray, Nullable, IndicesArray } from "babylonjs/types";
 import { Vector2, Vector3, Vector4, Quaternion, Matrix } from "babylonjs/Maths/math.vector";
-import { Color3 } from "babylonjs/Maths/math.color";
+import { Color3, Color4 } from "babylonjs/Maths/math.color";
 import { Tools } from "babylonjs/Misc/tools";
 import { VertexBuffer } from "babylonjs/Meshes/buffer";
 import { Node } from "babylonjs/node";
@@ -18,6 +18,7 @@ import { BaseTexture } from "babylonjs/Materials/Textures/baseTexture";
 import { Texture } from "babylonjs/Materials/Textures/texture";
 import { Material } from "babylonjs/Materials/material";
 import { MultiMaterial } from "babylonjs/Materials/multiMaterial";
+import { StandardMaterial } from 'babylonjs/Materials/standardMaterial';
 import { Engine } from "babylonjs/Engines/engine";
 import { Scene } from "babylonjs/scene";
 
@@ -728,9 +729,22 @@ export class _Exporter {
                 break;
             }
             case VertexBuffer.ColorKind: {
+                const meshMaterial = (babylonTransformNode as Mesh).material;
+                const convertToLinear = meshMaterial ? (meshMaterial instanceof StandardMaterial) : true;
+                const vertexData : Color3 | Color4 = stride === 3 ? new Color3() : new Color4();
                 for (let k = 0, length = meshAttributeArray.length / stride; k < length; ++k) {
                     index = k * stride;
-                    const vertexData = stride === 3 ? Vector3.FromArray(meshAttributeArray, index) : Vector4.FromArray(meshAttributeArray, index);
+                    if (stride === 3) {
+                        Color3.FromArrayToRef(meshAttributeArray, index, (vertexData as Color3));
+                        if (convertToLinear) {
+                            (vertexData as Color3).toLinearSpaceToRef((vertexData as Color3));
+                        }
+                    } else {
+                        Color4.FromArrayToRef(meshAttributeArray, index, (vertexData as Color4));
+                        if (convertToLinear) {
+                            (vertexData as Color4).toLinearSpaceToRef((vertexData as Color4));
+                        }
+                    }
                     vertexAttributes.push(vertexData.asArray());
                 }
                 break;

+ 10 - 12
src/Cameras/Inputs/flyCameraMouseInput.ts

@@ -59,7 +59,6 @@ export class FlyCameraMouseInput implements ICameraInput<FlyCamera> {
     @serialize()
     public angularSensibility = 1000.0;
 
-    private _mousemoveCallback: (e: MouseEvent) => void;
     private _observer: Nullable<Observer<PointerInfo>>;
     private _rollObserver: Nullable<Observer<Scene>>;
     private previousPosition: Nullable<{ x: number, y: number }> = null;
@@ -98,12 +97,6 @@ export class FlyCameraMouseInput implements ICameraInput<FlyCamera> {
                 }
             }
         );
-
-        // Helper function to keep 'this'.
-        this._mousemoveCallback = (e: any) => {
-            this._onMouseMove(e);
-        };
-        element.addEventListener("mousemove", this._mousemoveCallback, false);
     }
 
     /**
@@ -116,10 +109,6 @@ export class FlyCameraMouseInput implements ICameraInput<FlyCamera> {
 
             this.camera.getScene().onBeforeRenderObservable.remove(this._rollObserver);
 
-            if (this._mousemoveCallback) {
-                element.removeEventListener("mousemove", this._mousemoveCallback);
-            }
-
             this._observer = null;
             this._rollObserver = null;
             this.previousPosition = null;
@@ -184,6 +173,11 @@ export class FlyCameraMouseInput implements ICameraInput<FlyCamera> {
                 e.preventDefault();
                 this.element.focus();
             }
+
+            // This is required to move while pointer button is down
+            if (engine.isPointerLock) {
+                this._onMouseMove(p.event);
+            }
         } else
             // Mouse up.
             if (p.type === PointerEventTypes.POINTERUP && srcElement) {
@@ -202,7 +196,11 @@ export class FlyCameraMouseInput implements ICameraInput<FlyCamera> {
             } else
                 // Mouse move.
                 if (p.type === PointerEventTypes.POINTERMOVE) {
-                    if (!this.previousPosition || engine.isPointerLock) {
+                    if (!this.previousPosition) {
+                        if (engine.isPointerLock) {
+                            this._onMouseMove(p.event);
+                        }
+
                         return;
                     }
 

+ 10 - 6
src/Cameras/Inputs/freeCameraMouseInput.ts

@@ -94,6 +94,11 @@ export class FreeCameraMouseInput implements ICameraInput<FreeCamera> {
                         evt.preventDefault();
                         element.focus();
                     }
+
+                    // This is required to move while pointer button is down
+                    if (engine.isPointerLock && this._onMouseMove) {
+                        this._onMouseMove(p.event);
+                    }
                 }
                 else if (p.type === PointerEventTypes.POINTERUP && srcElement) {
                     try {
@@ -109,7 +114,11 @@ export class FreeCameraMouseInput implements ICameraInput<FreeCamera> {
                 }
 
                 else if (p.type === PointerEventTypes.POINTERMOVE) {
-                    if (!this.previousPosition || engine.isPointerLock) {
+                    if (!this.previousPosition) {
+                        if (engine.isPointerLock && this._onMouseMove) {
+                            this._onMouseMove(p.event);
+                        }
+
                         return;
                     }
 
@@ -161,7 +170,6 @@ export class FreeCameraMouseInput implements ICameraInput<FreeCamera> {
         };
 
         this._observer = this.camera.getScene().onPointerObservable.add(this._pointerInput, PointerEventTypes.POINTERDOWN | PointerEventTypes.POINTERUP | PointerEventTypes.POINTERMOVE);
-        element.addEventListener("mousemove", this._onMouseMove, false);
 
         element.addEventListener("contextmenu",
             <EventListener>this.onContextMenu.bind(this), false);
@@ -183,10 +191,6 @@ export class FreeCameraMouseInput implements ICameraInput<FreeCamera> {
         if (this._observer && element) {
             this.camera.getScene().onPointerObservable.remove(this._observer);
 
-            if (this._onMouseMove) {
-                element.removeEventListener("mousemove", this._onMouseMove);
-            }
-
             if (this.onContextMenu) {
                 element.removeEventListener("contextmenu", <EventListener>this.onContextMenu);
             }

+ 157 - 119
src/Engines/nativeEngine.ts

@@ -26,6 +26,58 @@ import { ShaderCodeInliner } from "./Processors/shaderCodeInliner";
 import { WebGL2ShaderProcessor } from '../Engines/WebGL/webGL2ShaderProcessors';
 
 interface INativeEngine {
+
+    readonly TEXTURE_NEAREST_NEAREST: number;
+    readonly TEXTURE_LINEAR_LINEAR: number;
+    readonly TEXTURE_LINEAR_LINEAR_MIPLINEAR: number;
+    readonly TEXTURE_NEAREST_NEAREST_MIPNEAREST: number;
+    readonly TEXTURE_NEAREST_LINEAR_MIPNEAREST: number;
+    readonly TEXTURE_NEAREST_LINEAR_MIPLINEAR: number;
+    readonly TEXTURE_NEAREST_LINEAR: number;
+    readonly TEXTURE_NEAREST_NEAREST_MIPLINEAR: number;
+    readonly TEXTURE_LINEAR_NEAREST_MIPNEAREST: number;
+    readonly TEXTURE_LINEAR_NEAREST_MIPLINEAR: number;
+    readonly TEXTURE_LINEAR_LINEAR_MIPNEAREST: number;
+    readonly TEXTURE_LINEAR_NEAREST: number;
+
+    readonly DEPTH_TEST_LESS: number;
+    readonly DEPTH_TEST_LEQUAL: number;
+    readonly DEPTH_TEST_EQUAL: number;
+    readonly DEPTH_TEST_GEQUAL: number;
+    readonly DEPTH_TEST_GREATER: number;
+    readonly DEPTH_TEST_NOTEQUAL: number;
+    readonly DEPTH_TEST_NEVER: number;
+    readonly DEPTH_TEST_ALWAYS: number;
+
+    readonly CLEAR_FLAG_COLOR: number;
+    readonly CLEAR_FLAG_DEPTH: number;
+    readonly CLEAR_FLAG_STENCIL: number;
+
+    readonly ADDRESS_MODE_WRAP: number;
+    readonly ADDRESS_MODE_MIRROR: number;
+    readonly ADDRESS_MODE_CLAMP: number;
+    readonly ADDRESS_MODE_BORDER: number;
+    readonly ADDRESS_MODE_MIRROR_ONCE: number;
+
+    readonly TEXTURE_FORMAT_RGBA8: number;
+    readonly TEXTURE_FORMAT_RGBA32F: number;
+
+    readonly ATTRIB_TYPE_UINT8: number;
+    readonly ATTRIB_TYPE_INT16: number;
+    readonly ATTRIB_TYPE_FLOAT: number;
+
+    readonly ALPHA_DISABLE: number;
+    readonly ALPHA_ADD: number;
+    readonly ALPHA_COMBINE: number;
+    readonly ALPHA_SUBTRACT: number;
+    readonly ALPHA_MULTIPLY: number;
+    readonly ALPHA_MAXIMIZED: number;
+    readonly ALPHA_ONEONE: number;
+    readonly ALPHA_PREMULTIPLIED: number;
+    readonly ALPHA_PREMULTIPLIED_PORTERDUFF: number;
+    readonly ALPHA_INTERPOLATE: number;
+    readonly ALPHA_SCREENMODE: number;
+
     dispose(): void;
 
     requestAnimationFrame(callback: () => void): void;
@@ -143,61 +195,6 @@ class NativeDataBuffer extends DataBuffer {
     public nativeVertexBuffer?: any;
 }
 
-// TODO: change this to match bgfx.
-// Must match Filter enum in SpectreEngine.h.
-class NativeFilter {
-    public static readonly POINT = 0;
-    public static readonly MINPOINT_MAGPOINT_MIPPOINT = NativeFilter.POINT;
-    public static readonly BILINEAR = 1;
-    public static readonly MINLINEAR_MAGLINEAR_MIPPOINT = NativeFilter.BILINEAR;
-    public static readonly TRILINEAR = 2;
-    public static readonly MINLINEAR_MAGLINEAR_MIPLINEAR = NativeFilter.TRILINEAR;
-    public static readonly ANISOTROPIC = 3;
-    public static readonly POINT_COMPARE = 4;
-    public static readonly TRILINEAR_COMPARE = 5;
-    public static readonly MINBILINEAR_MAGPOINT = 6;
-    public static readonly MINLINEAR_MAGPOINT_MIPLINEAR = NativeFilter.MINBILINEAR_MAGPOINT;
-    public static readonly MINPOINT_MAGPOINT_MIPLINEAR = 7;
-    public static readonly MINPOINT_MAGLINEAR_MIPPOINT = 8;
-    public static readonly MINPOINT_MAGLINEAR_MIPLINEAR = 9;
-    public static readonly MINLINEAR_MAGPOINT_MIPPOINT = 10;
-}
-
-// depth test values
-// Values match bgfx defines
-class DepthTest {
-    public static readonly DEPTH_TEST_LESS = 16;
-    public static readonly DEPTH_TEST_LEQUAL = 32;
-    public static readonly DEPTH_TEST_EQUAL = 48;
-    public static readonly DEPTH_TEST_GEQUAL = 64;
-    public static readonly DEPTH_TEST_GREATER = 80;
-    public static readonly DEPTH_TEST_NOTEQUAL = 96;
-    public static readonly DEPTH_TEST_NEVER = 112;
-    public static readonly DEPTH_TEST_ALWAYS = 128;
-}
-
-// these flags match bgfx.
-class NativeClearFlags
-{
-    public static readonly CLEAR_COLOR = 1;
-    public static readonly CLEAR_DEPTH = 2;
-    public static readonly CLEAR_STENCIL = 4;
-}
-// TODO: change this to match bgfx.
-// Must match AddressMode enum in SpectreEngine.h.
-class NativeAddressMode {
-    public static readonly WRAP = 0;
-    public static readonly MIRROR = 1;
-    public static readonly CLAMP = 2;
-    public static readonly BORDER = 3;
-    public static readonly MIRROR_ONCE = 4;
-}
-
-class NativeTextureFormat {
-    public static readonly RGBA8 = 0;
-    public static readonly RGBA32F = 1;
-}
-
 /** @hidden */
 class NativeTexture extends InternalTexture {
     public getInternalTexture(): InternalTexture {
@@ -218,7 +215,7 @@ export class NativeEngine extends Engine {
     /** Defines the invalid handle returned by bgfx when resource creation goes wrong */
     private readonly INVALID_HANDLE = 65535;
     private _boundBuffersVertexArray: any = null;
-    private _currentDepthTest: number = DepthTest.DEPTH_TEST_LEQUAL;
+    private _currentDepthTest: number = this._native.DEPTH_TEST_LEQUAL;
 
     public getHardwareScalingLevel(): number {
         return 1.0;
@@ -358,15 +355,15 @@ export class NativeEngine extends Engine {
         var mode = 0;
         if (backBuffer && color) {
             this._native.clearColor(color.r, color.g, color.b, color.a !== undefined ? color.a : 1.0);
-            mode |= NativeClearFlags.CLEAR_COLOR;
+            mode |= this._native.CLEAR_FLAG_COLOR;
         }
         if (depth) {
             this._native.clearDepth(1.0);
-            mode |= NativeClearFlags.CLEAR_DEPTH;
+            mode |= this._native.CLEAR_FLAG_DEPTH;
         }
         if (stencil) {
             this._native.clearStencil(0);
-            mode |= NativeClearFlags.CLEAR_STENCIL;
+            mode |= this._native.CLEAR_FLAG_STENCIL;
         }
         this._native.clear(mode);
     }
@@ -418,7 +415,7 @@ export class NativeEngine extends Engine {
                             vertexBuffer.byteOffset,
                             vertexBuffer.byteStride,
                             vertexBuffer.getSize(),
-                            vertexBuffer.type,
+                            this._getNativeAttribType(vertexBuffer.type),
                             vertexBuffer.normalized);
                     }
                 }
@@ -643,7 +640,7 @@ export class NativeEngine extends Engine {
      * @param enable defines the state to set
      */
     public setDepthBuffer(enable: boolean): void {
-        this._native.setDepthTest(enable ? this._currentDepthTest : DepthTest.DEPTH_TEST_ALWAYS);
+        this._native.setDepthTest(enable ? this._currentDepthTest : this._native.DEPTH_TEST_ALWAYS);
     }
 
     /**
@@ -655,22 +652,22 @@ export class NativeEngine extends Engine {
     }
 
     public setDepthFunctionToGreater(): void {
-        this._currentDepthTest = DepthTest.DEPTH_TEST_GREATER;
+        this._currentDepthTest = this._native.DEPTH_TEST_GREATER;
         this._native.setDepthTest(this._currentDepthTest);
     }
 
     public setDepthFunctionToGreaterOrEqual(): void {
-        this._currentDepthTest = DepthTest.DEPTH_TEST_GEQUAL;
+        this._currentDepthTest = this._native.DEPTH_TEST_GEQUAL;
         this._native.setDepthTest(this._currentDepthTest);
     }
 
     public setDepthFunctionToLess(): void {
-        this._currentDepthTest = DepthTest.DEPTH_TEST_LESS;
+        this._currentDepthTest = this._native.DEPTH_TEST_LESS;
         this._native.setDepthTest(this._currentDepthTest);
     }
 
     public setDepthFunctionToLessOrEqual(): void {
-        this._currentDepthTest = DepthTest.DEPTH_TEST_LEQUAL;
+        this._currentDepthTest = this._native.DEPTH_TEST_LEQUAL;
         this._native.setDepthTest(this._currentDepthTest);
     }
 
@@ -721,6 +718,8 @@ export class NativeEngine extends Engine {
             return;
         }
 
+        mode = this._getNativeAlphaMode(mode);
+
         this._native.setBlendMode(mode);
 
         if (!noDepthWriteChange) {
@@ -1080,7 +1079,7 @@ export class NativeEngine extends Engine {
                     texture.height = texture.baseHeight;
                     texture.isReady = true;
 
-                    var filter = this._getSamplingFilter(samplingMode);
+                    var filter = this._getNativeSamplingMode(samplingMode);
                     this._native.setTextureSampling(webGLTexture, filter);
 
                     if (scene) {
@@ -1244,54 +1243,6 @@ export class NativeEngine extends Engine {
         return texture;
     }
 
-    // Returns a NativeFilter.XXXX value.
-    private _getSamplingFilter(samplingMode: number): number {
-        switch (samplingMode) {
-            case Constants.TEXTURE_BILINEAR_SAMPLINGMODE:
-                return NativeFilter.MINLINEAR_MAGLINEAR_MIPPOINT;
-            case Constants.TEXTURE_TRILINEAR_SAMPLINGMODE:
-                return NativeFilter.MINLINEAR_MAGLINEAR_MIPLINEAR;
-            case Constants.TEXTURE_NEAREST_SAMPLINGMODE:
-                return NativeFilter.MINPOINT_MAGPOINT_MIPLINEAR;
-            case Constants.TEXTURE_NEAREST_NEAREST_MIPNEAREST:
-                return NativeFilter.MINPOINT_MAGPOINT_MIPPOINT;
-            case Constants.TEXTURE_NEAREST_LINEAR_MIPNEAREST:
-                return NativeFilter.MINLINEAR_MAGPOINT_MIPPOINT;
-            case Constants.TEXTURE_NEAREST_LINEAR_MIPLINEAR:
-                return NativeFilter.MINLINEAR_MAGPOINT_MIPLINEAR;
-            case Constants.TEXTURE_NEAREST_LINEAR:
-                return NativeFilter.MINLINEAR_MAGPOINT_MIPLINEAR;
-            case Constants.TEXTURE_NEAREST_NEAREST:
-                return NativeFilter.MINPOINT_MAGPOINT_MIPPOINT;
-            case Constants.TEXTURE_LINEAR_NEAREST_MIPNEAREST:
-                return NativeFilter.MINPOINT_MAGLINEAR_MIPPOINT;
-            case Constants.TEXTURE_LINEAR_NEAREST_MIPLINEAR:
-                return NativeFilter.MINPOINT_MAGLINEAR_MIPLINEAR;
-            case Constants.TEXTURE_LINEAR_LINEAR:
-                return NativeFilter.MINLINEAR_MAGLINEAR_MIPLINEAR;
-            case Constants.TEXTURE_LINEAR_NEAREST:
-                return NativeFilter.MINPOINT_MAGLINEAR_MIPLINEAR;
-            case Constants.TEXTURE_NEAREST_NEAREST_MIPLINEAR:
-                return NativeFilter.MINPOINT_MAGPOINT_MIPLINEAR;
-            case Constants.TEXTURE_LINEAR_LINEAR_MIPNEAREST:
-                return NativeFilter.MINLINEAR_MAGLINEAR_MIPLINEAR;
-            default:
-                throw new Error("Unexpected sampling mode: " + samplingMode + ".");
-        }
-    }
-
-    private static _GetNativeTextureFormat(format: number, type: number): number {
-        if (format == Constants.TEXTUREFORMAT_RGBA && type == Constants.TEXTURETYPE_UNSIGNED_INT) {
-            return NativeTextureFormat.RGBA8;
-        }
-        else if (format == Constants.TEXTUREFORMAT_RGBA && type == Constants.TEXTURETYPE_FLOAT) {
-            return NativeTextureFormat.RGBA32F;
-        }
-        else {
-            throw new Error("Unexpected texture format or type: format " + format + ", type " + type + ".");
-        }
-    }
-
     public createRenderTargetTexture(size: number | { width: number, height: number }, options: boolean | RenderTargetCreationOptions): NativeTexture {
         let fullOptions = new RenderTargetCreationOptions();
 
@@ -1333,7 +1284,7 @@ export class NativeEngine extends Engine {
             texture._webGLTexture!,
             width,
             height,
-            NativeEngine._GetNativeTextureFormat(fullOptions.format, fullOptions.type),
+            this._getNativeTextureFormat(fullOptions.format, fullOptions.type),
             fullOptions.samplingMode!,
             fullOptions.generateStencilBuffer ? true : false,
             fullOptions.generateDepthBuffer,
@@ -1360,7 +1311,7 @@ export class NativeEngine extends Engine {
 
     public updateTextureSamplingMode(samplingMode: number, texture: InternalTexture): void {
         if (texture._webGLTexture) {
-            var filter = this._getSamplingFilter(samplingMode);
+            var filter = this._getNativeSamplingMode(samplingMode);
             this._native.setTextureSampling(texture._webGLTexture, filter);
         }
         texture.samplingMode = samplingMode;
@@ -1501,11 +1452,11 @@ export class NativeEngine extends Engine {
     private _getAddressMode(wrapMode: number): number {
         switch (wrapMode) {
             case Constants.TEXTURE_WRAP_ADDRESSMODE:
-                return NativeAddressMode.WRAP;
+                return this._native.ADDRESS_MODE_WRAP;
             case Constants.TEXTURE_CLAMP_ADDRESSMODE:
-                return NativeAddressMode.CLAMP;
+                return this._native.ADDRESS_MODE_CLAMP;
             case Constants.TEXTURE_MIRROR_ADDRESSMODE:
-                return NativeAddressMode.MIRROR;
+                return this._native.ADDRESS_MODE_MIRROR;
             default:
                 throw new Error("Unexpected wrap mode: " + wrapMode + ".");
         }
@@ -1551,4 +1502,91 @@ export class NativeEngine extends Engine {
     public _uploadImageToTexture(texture: InternalTexture, image: HTMLImageElement, faceIndex: number = 0, lod: number = 0) {
         throw new Error("_uploadArrayBufferViewToTexture not implemented.");
     }
+
+    // JavaScript-to-Native conversion helper functions.
+
+    private _getNativeSamplingMode(samplingMode: number): number {
+        switch (samplingMode) {
+            case Constants.TEXTURE_NEAREST_NEAREST:
+                return this._native.TEXTURE_NEAREST_NEAREST;
+            case Constants.TEXTURE_LINEAR_LINEAR:
+                return this._native.TEXTURE_LINEAR_LINEAR;
+            case Constants.TEXTURE_LINEAR_LINEAR_MIPLINEAR:
+                return this._native.TEXTURE_LINEAR_LINEAR_MIPLINEAR;
+            case Constants.TEXTURE_NEAREST_NEAREST_MIPNEAREST:
+                return this._native.TEXTURE_NEAREST_NEAREST_MIPNEAREST;
+            case Constants.TEXTURE_NEAREST_LINEAR_MIPNEAREST:
+                return this._native.TEXTURE_NEAREST_LINEAR_MIPNEAREST;
+            case Constants.TEXTURE_NEAREST_LINEAR_MIPLINEAR:
+                return this._native.TEXTURE_NEAREST_LINEAR_MIPLINEAR;
+            case Constants.TEXTURE_NEAREST_LINEAR:
+                return this._native.TEXTURE_NEAREST_LINEAR;
+            case Constants.TEXTURE_NEAREST_NEAREST_MIPLINEAR:
+                return this._native.TEXTURE_NEAREST_NEAREST_MIPLINEAR;
+            case Constants.TEXTURE_LINEAR_NEAREST_MIPNEAREST:
+                return this._native.TEXTURE_LINEAR_NEAREST_MIPNEAREST;
+            case Constants.TEXTURE_LINEAR_NEAREST_MIPLINEAR:
+                return this._native.TEXTURE_LINEAR_NEAREST_MIPLINEAR;
+            case Constants.TEXTURE_LINEAR_LINEAR_MIPNEAREST:
+                return this._native.TEXTURE_LINEAR_LINEAR_MIPNEAREST;
+            case Constants.TEXTURE_LINEAR_NEAREST:
+                return this._native.TEXTURE_LINEAR_NEAREST;
+            default:
+                throw new Error(`Unsupported sampling mode: ${samplingMode}.`);
+        }
+    }
+
+    private _getNativeTextureFormat(format: number, type: number): number {
+        if (format == Constants.TEXTUREFORMAT_RGBA && type == Constants.TEXTURETYPE_UNSIGNED_INT) {
+            return this._native.TEXTURE_FORMAT_RGBA8;
+        }
+        else if (format == Constants.TEXTUREFORMAT_RGBA && type == Constants.TEXTURETYPE_FLOAT) {
+            return this._native.TEXTURE_FORMAT_RGBA32F;
+        }
+        else {
+            throw new Error(`Unsupported texture format or type: format ${format}, type ${type}.`);
+        }
+    }
+
+    private _getNativeAlphaMode(mode: number): number {
+        switch (mode) {
+            case Constants.ALPHA_DISABLE:
+                return this._native.ALPHA_DISABLE;
+            case Constants.ALPHA_ADD:
+                return this._native.ALPHA_ADD;
+            case Constants.ALPHA_COMBINE:
+                return this._native.ALPHA_COMBINE;
+            case Constants.ALPHA_SUBTRACT:
+                return this._native.ALPHA_SUBTRACT;
+            case Constants.ALPHA_MULTIPLY:
+                return this._native.ALPHA_MULTIPLY;
+            case Constants.ALPHA_MAXIMIZED:
+                return this._native.ALPHA_MAXIMIZED;
+            case Constants.ALPHA_ONEONE:
+                return this._native.ALPHA_ONEONE;
+            case Constants.ALPHA_PREMULTIPLIED:
+                return this._native.ALPHA_PREMULTIPLIED;
+            case Constants.ALPHA_PREMULTIPLIED_PORTERDUFF:
+                return this._native.ALPHA_PREMULTIPLIED_PORTERDUFF;
+            case Constants.ALPHA_INTERPOLATE:
+                return this._native.ALPHA_INTERPOLATE;
+            case Constants.ALPHA_SCREENMODE:
+                return this._native.ALPHA_SCREENMODE;
+            default:
+                throw new Error(`Unsupported alpha mode: ${mode}.`);
+        }
+    }
+
+    private _getNativeAttribType(type: number): number {
+        switch (type) {
+            case VertexBuffer.UNSIGNED_BYTE:
+                return this._native.ATTRIB_TYPE_UINT8;
+            case VertexBuffer.SHORT:
+                return this._native.ATTRIB_TYPE_INT16;
+            case VertexBuffer.FLOAT:
+                return this._native.ATTRIB_TYPE_FLOAT;
+            default:
+                throw new Error(`Unsupported attribute type: ${type}.`);
+        }
+    }
 }

+ 2 - 2
src/Materials/Node/nodeMaterialBlockConnectionPoint.ts

@@ -470,8 +470,8 @@ export class NodeMaterialConnectionPoint {
             serializationObject.exposedPortPosition = this.exposedPortPosition;
         }
 
-        if (this.isExposedOnFrame) {
-            serializationObject.isExposedOnFrame = this.isExposedOnFrame;
+        if (this.isExposedOnFrame || this.exposedPortPosition >= 0) {
+            serializationObject.isExposedOnFrame = true;
             serializationObject.exposedPortPosition = this.exposedPortPosition;
         }
 

+ 5 - 3
src/Materials/Textures/Procedurals/proceduralTexture.ts

@@ -22,6 +22,7 @@ import { _TypeStore } from '../../../Misc/typeStore';
 import { NodeMaterial } from '../../Node/nodeMaterial';
 import { RenderTargetTextureSize } from '../../../Engines/Extensions/engine.renderTarget';
 import { EngineStore } from '../../../Engines/engineStore';
+import { Constants } from '../../../Engines/constants';
 
 /**
  * Procedural texturing is a way to programmatically create a texture. There are 2 types of procedural textures: code-only, and code that references some classic 2D images, sometimes calmpler' images.
@@ -114,8 +115,9 @@ export class ProceduralTexture extends Texture {
      * @param fallbackTexture Define a fallback texture in case there were issues to create the custom texture
      * @param generateMipMaps Define if the texture should creates mip maps or not
      * @param isCube Define if the texture is a cube texture or not (this will render each faces of the cube)
+     * @param textureType The FBO internal texture type
      */
-    constructor(name: string, size: RenderTargetTextureSize, fragment: any, scene: Nullable<Scene>, fallbackTexture: Nullable<Texture> = null, generateMipMaps = true, isCube = false) {
+    constructor(name: string, size: RenderTargetTextureSize, fragment: any, scene: Nullable<Scene>, fallbackTexture: Nullable<Texture> = null, generateMipMaps = true, isCube = false, textureType = Constants.TEXTURETYPE_UNSIGNED_INT) {
         super(null, scene, !generateMipMaps);
 
         scene = this.getScene() || EngineStore.LastCreatedScene!;
@@ -138,11 +140,11 @@ export class ProceduralTexture extends Texture {
         this._fallbackTexture = fallbackTexture;
 
         if (isCube) {
-            this._texture = this._fullEngine.createRenderTargetCubeTexture(size as number, { generateMipMaps: generateMipMaps, generateDepthBuffer: false, generateStencilBuffer: false });
+            this._texture = this._fullEngine.createRenderTargetCubeTexture(size as number, { generateMipMaps: generateMipMaps, generateDepthBuffer: false, generateStencilBuffer: false, type: textureType });
             this.setFloat("face", 0);
         }
         else {
-            this._texture = this._fullEngine.createRenderTargetTexture(size, { generateMipMaps: generateMipMaps, generateDepthBuffer: false, generateStencilBuffer: false });
+            this._texture = this._fullEngine.createRenderTargetTexture(size, { generateMipMaps: generateMipMaps, generateDepthBuffer: false, generateStencilBuffer: false, type: textureType });
         }
 
         // VBO

+ 12 - 1
src/Materials/Textures/videoTexture.ts

@@ -18,6 +18,11 @@ export interface VideoTextureSettings {
     autoPlay?: boolean;
 
     /**
+     * Applies `muted` to video, if specified
+     */
+    muted?: boolean;
+
+    /**
      * Applies `loop` to video, if specified
      */
     loop?: boolean;
@@ -110,13 +115,15 @@ export class VideoTexture extends Texture {
         if (settings.poster) {
             this.video.poster = settings.poster;
         }
-
         if (settings.autoPlay !== undefined) {
             this.video.autoplay = settings.autoPlay;
         }
         if (settings.loop !== undefined) {
             this.video.loop = settings.loop;
         }
+        if (settings.muted !== undefined) {
+            this.video.muted = settings.muted;
+        }
 
         this.video.setAttribute("playsinline", "");
 
@@ -126,6 +133,10 @@ export class VideoTexture extends Texture {
         this._createInternalTextureOnEvent = (settings.poster && !settings.autoPlay) ? "play" : "canplay";
         this.video.addEventListener(this._createInternalTextureOnEvent, this._createInternalTexture);
 
+        if (settings.autoPlay) {
+            this.video.play();
+        }
+
         const videoHasEnoughData = (this.video.readyState >= this.video.HAVE_CURRENT_DATA);
         if (settings.poster &&
             (!settings.autoPlay || !videoHasEnoughData)) {

+ 1 - 0
src/Misc/index.ts

@@ -51,3 +51,4 @@ export * from "./dataStorage";
 export * from "./sceneRecorder";
 export * from "./khronosTextureContainer2";
 export * from "./trajectoryClassifier";
+export * from './timer';

+ 19 - 2
src/XR/features/WebXRHandTracking.ts

@@ -12,6 +12,7 @@ import { PhysicsImpostor } from "../../Physics/physicsImpostor";
 import { WebXRFeaturesManager } from "../webXRFeaturesManager";
 import { IDisposable } from "../../scene";
 import { Observable } from "../../Misc/observable";
+import { InstancedMesh } from "../../Meshes/instancedMesh";
 
 declare const XRHand: XRHand;
 
@@ -38,6 +39,13 @@ export interface IWebXRHandTrackingOptions {
          * It should have the general size of a single unit, as the instances will be scaled according to the provided radius
          */
         sourceMesh?: Mesh;
+
+        /**
+         * This function will be called after a mesh was created for a specific joint.
+         * Using this function you can either manipulate the instance or return a new mesh.
+         * When returning a new mesh the instance created before will be disposed
+         */
+        onHandJointMeshGenerated?: (meshInstance: InstancedMesh, jointId: number, controllerId: string) => Mesh | undefined;
         /**
          * Should the source mesh stay visible. Defaults to false
          */
@@ -235,7 +243,7 @@ export class WebXRHandTracking extends WebXRAbstractFeature {
      * This does not mean that the feature is enabled, but that the objects needed are well defined.
      */
     public isCompatible(): boolean {
-        return (typeof XRHand !== 'undefined');
+        return typeof XRHand !== "undefined";
     }
 
     /**
@@ -325,7 +333,16 @@ export class WebXRHandTracking extends WebXRAbstractFeature {
         const originalMesh = this.options.jointMeshes?.sourceMesh || SphereBuilder.CreateSphere("jointParent", { diameter: 1 });
         originalMesh.isVisible = !!this.options.jointMeshes?.keepOriginalVisible;
         for (let i = 0; i < hand.length; ++i) {
-            const newInstance = originalMesh.createInstance(`${xrController.uniqueId}-handJoint-${i}`);
+            let newInstance: AbstractMesh = originalMesh.createInstance(`${xrController.uniqueId}-handJoint-${i}`);
+            if (this.options.jointMeshes?.onHandJointMeshGenerated) {
+                const returnedMesh = this.options.jointMeshes.onHandJointMeshGenerated(newInstance as InstancedMesh, i, xrController.uniqueId);
+                if (returnedMesh) {
+                    if (returnedMesh !== newInstance) {
+                        newInstance.dispose();
+                        newInstance = returnedMesh;
+                    }
+                }
+            }
             newInstance.isPickable = false;
             if (this.options.jointMeshes?.enablePhysics) {
                 const props = this.options.jointMeshes.physicsProps || {};

+ 5 - 1
src/scene.ts

@@ -3440,11 +3440,14 @@ export class Scene extends AbstractScene implements IAnimatable, IClipPlanesHold
     /**
      * Use this function to stop evaluating active meshes. The current list will be keep alive between frames
      * @param skipEvaluateActiveMeshes defines an optional boolean indicating that the evaluate active meshes step must be completely skipped
+     * @param onSuccess optional success callback
+     * @param onError optional error callback
      * @returns the current scene
      */
-    public freezeActiveMeshes(skipEvaluateActiveMeshes = false): Scene {
+    public freezeActiveMeshes(skipEvaluateActiveMeshes = false, onSuccess?: () => void, onError?: (message: string) => void): Scene {
         this.executeWhenReady(() => {
             if (!this.activeCamera) {
+                onError && onError('No active camera found');
                 return;
             }
 
@@ -3459,6 +3462,7 @@ export class Scene extends AbstractScene implements IAnimatable, IClipPlanesHold
             for (var index = 0; index < this._activeMeshes.length; index++) {
                 this._activeMeshes.data[index]._freeze();
             }
+            onSuccess && onSuccess();
         });
         return this;
     }