Browse Source

Merge pull request #6387 from TrevorDev/basisFileSupport

.basis file support
David Catuhe 6 năm trước cách đây
mục cha
commit
05488c5fc6

BIN
Playground/textures/houseWithAlpha.basis


BIN
Playground/textures/plane.basis


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 1 - 0
dist/preview release/basisTranscoder/basis_transcoder.js


BIN
dist/preview release/basisTranscoder/basis_transcoder.wasm


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

@@ -4,7 +4,7 @@
 - WIP: Node Material (NEED DOC AND SAMPLES) ([Deltakosh](https://github.com/deltakosh/))
 - WIP: Node material editor (NEED DOC AND VIDEOS) ([Deltakosh](https://github.com/deltakosh/)/[TrevorDev](https://github.com/TrevorDev))
 - WIP: WebGPU support (NEED DOC AND SAMPLES) ([Sebavan](https://github.com/sebavan/)
-- WIP: .basis texture file format support (NEED DEMO) ([TrevorDev](https://github.com/TrevorDev))
+- WIP: .basis file format texture support (NEED DEMO) ([TrevorDev](https://github.com/TrevorDev))
 
 ## Optimizations
 

+ 3 - 3
src/Cameras/VR/webVRCamera.ts

@@ -407,7 +407,7 @@ export class WebVRFreeCamera extends FreeCamera implements PoseControlled {
 
     private _leftController: Nullable<WebVRController>;
     /**
-     * The controller corrisponding to the users left hand.
+     * The controller corresponding to the users left hand.
      */
     public get leftController(): Nullable<WebVRController> {
         if (!this._leftController) {
@@ -419,7 +419,7 @@ export class WebVRFreeCamera extends FreeCamera implements PoseControlled {
 
     private _rightController: Nullable<WebVRController>;
     /**
-     * The controller corrisponding to the users right hand.
+     * The controller corresponding to the users right hand.
      */
     public get rightController(): Nullable<WebVRController> {
         if (!this._rightController) {
@@ -432,7 +432,7 @@ export class WebVRFreeCamera extends FreeCamera implements PoseControlled {
     /**
      * Casts a ray forward from the vrCamera's gaze.
      * @param length Length of the ray (default: 100)
-     * @returns the ray corrisponding to the gaze
+     * @returns the ray corresponding to the gaze
      */
     public getForwardRay(length = 100): Ray {
         if (this.leftCamera) {

+ 25 - 10
src/Engines/engine.ts

@@ -4324,11 +4324,6 @@ export class Engine {
                         this._bindTextureDirectly(gl.TEXTURE_2D, source, true);
                         gl.texImage2D(gl.TEXTURE_2D, 0, internalFormat, internalFormat, gl.UNSIGNED_BYTE, img);
 
-                        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
-                        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
-                        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
-                        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
-
                         this._rescaleTexture(source, texture, scene, internalFormat, () => {
                             this._releaseTexture(source);
                             this._bindTextureDirectly(gl.TEXTURE_2D, texture, true);
@@ -4359,7 +4354,21 @@ export class Engine {
         return texture;
     }
 
-    private _rescaleTexture(source: InternalTexture, destination: InternalTexture, scene: Nullable<Scene>, internalFormat: number, onComplete: () => void): void {
+    /**
+     * @hidden
+     * Rescales a texture
+     * @param source input texutre
+     * @param destination destination texture
+     * @param scene scene to use to render the resize
+     * @param internalFormat format to use when resizing
+     * @param onComplete callback to be called when resize has completed
+     */
+    public _rescaleTexture(source: InternalTexture, destination: InternalTexture, scene: Nullable<Scene>, internalFormat: number, onComplete: () => void): void {
+        this._gl.texParameteri(this._gl.TEXTURE_2D, this._gl.TEXTURE_MAG_FILTER, this._gl.LINEAR);
+        this._gl.texParameteri(this._gl.TEXTURE_2D, this._gl.TEXTURE_MIN_FILTER, this._gl.LINEAR);
+        this._gl.texParameteri(this._gl.TEXTURE_2D, this._gl.TEXTURE_WRAP_S, this._gl.CLAMP_TO_EDGE);
+        this._gl.texParameteri(this._gl.TEXTURE_2D, this._gl.TEXTURE_WRAP_T, this._gl.CLAMP_TO_EDGE);
+
         let rtt = this.createRenderTargetTexture({
             width: destination.width,
             height: destination.height,
@@ -4987,12 +4996,12 @@ export class Engine {
     }
 
     /** @hidden */
-    public _uploadDataToTextureDirectly(texture: InternalTexture, imageData: ArrayBufferView, faceIndex: number = 0, lod: number = 0): void {
+    public _uploadDataToTextureDirectly(texture: InternalTexture, imageData: ArrayBufferView, faceIndex: number = 0, lod: number = 0, babylonInternalFormat?: number, useTextureWidthAndHeight = false): void {
         var gl = this._gl;
 
         var textureType = this._getWebGLTextureType(texture.type);
         var format = this._getInternalFormat(texture.format);
-        var internalFormat = this._getRGBABufferInternalSizedFormat(texture.type, format);
+        var internalFormat = babylonInternalFormat === undefined ? this._getRGBABufferInternalSizedFormat(texture.type, format) : this._getInternalFormat(babylonInternalFormat);
 
         this._unpackFlipY(texture.invertY);
 
@@ -5003,8 +5012,8 @@ export class Engine {
 
         const lodMaxWidth = Math.round(Scalar.Log2(texture.width));
         const lodMaxHeight = Math.round(Scalar.Log2(texture.height));
-        const width = Math.pow(2, Math.max(lodMaxWidth - lod, 0));
-        const height = Math.pow(2, Math.max(lodMaxHeight - lod, 0));
+        const width = useTextureWidthAndHeight ? texture.width : Math.pow(2, Math.max(lodMaxWidth - lod, 0));
+        const height = useTextureWidthAndHeight ? texture.height : Math.pow(2, Math.max(lodMaxHeight - lod, 0));
 
         gl.texImage2D(target, lod, internalFormat, width, height, 0, format, textureType, imageData);
     }
@@ -6100,6 +6109,12 @@ export class Engine {
                     return this._gl.HALF_FLOAT_OES;
                 case Engine.TEXTURETYPE_UNSIGNED_BYTE:
                     return this._gl.UNSIGNED_BYTE;
+                case Engine.TEXTURETYPE_UNSIGNED_SHORT_4_4_4_4:
+                    return this._gl.UNSIGNED_SHORT_4_4_4_4;
+                case Engine.TEXTURETYPE_UNSIGNED_SHORT_5_5_5_1:
+                    return this._gl.UNSIGNED_SHORT_5_5_5_1;
+                case Engine.TEXTURETYPE_UNSIGNED_SHORT_5_6_5:
+                    return this._gl.UNSIGNED_SHORT_5_6_5;
             }
             return this._gl.UNSIGNED_BYTE;
         }

+ 1 - 1
src/Gamepads/Controllers/webVRController.ts

@@ -52,7 +52,7 @@ export abstract class WebVRController extends PoseEnabledController {
     }
 
     /**
-     * X and Y axis corrisponding to the controllers joystick
+     * X and Y axis corresponding to the controllers joystick
      */
     public pad: StickValues = { x: 0, y: 0 };
 

+ 1 - 1
src/Gamepads/Controllers/windowsMotionController.ts

@@ -26,7 +26,7 @@ class LoadedMeshInfo {
      */
     public rootNode: AbstractMesh;
     /**
-     * Node of the mesh corrisponding to the direction the ray should be cast from the controller
+     * Node of the mesh corresponding to the direction the ray should be cast from the controller
      */
     public pointingPoseNode: TransformNode;
     /**

+ 111 - 0
src/Materials/Textures/Loaders/basisTextureLoader.ts

@@ -0,0 +1,111 @@
+import { Nullable } from "../../../types";
+import { Engine } from "../../../Engines/engine";
+import { InternalTexture } from "../../../Materials/Textures/internalTexture";
+import { IInternalTextureLoader } from "../../../Materials/Textures/internalTextureLoader";
+import { _TimeToken } from "../../../Instrumentation/timeToken";
+import { _DepthCullingState, _StencilState, _AlphaState } from "../../../States/index";
+import { BasisTools } from "../../../Misc/basis";
+
+/**
+ * Loader for .basis file format
+ */
+export class _BasisTextureLoader implements IInternalTextureLoader {
+    /**
+     * Defines whether the loader supports cascade loading the different faces.
+     */
+    public readonly supportCascades = false;
+
+    /**
+     * This returns if the loader support the current file information.
+     * @param extension defines the file extension of the file being loaded
+     * @param textureFormatInUse defines the current compressed format in use iun the engine
+     * @param fallback defines the fallback internal texture if any
+     * @param isBase64 defines whether the texture is encoded as a base64
+     * @param isBuffer defines whether the texture data are stored as a buffer
+     * @returns true if the loader can load the specified file
+     */
+    public canLoad(extension: string, textureFormatInUse: Nullable<string>, fallback: Nullable<InternalTexture>, isBase64: boolean, isBuffer: boolean): boolean {
+        return extension.indexOf(".basis") === 0;
+    }
+
+    /**
+     * Transform the url before loading if required.
+     * @param rootUrl the url of the texture
+     * @param textureFormatInUse defines the current compressed format in use iun the engine
+     * @returns the transformed texture
+     */
+    public transformUrl(rootUrl: string, textureFormatInUse: Nullable<string>): string {
+        return rootUrl;
+    }
+
+    /**
+     * Gets the fallback url in case the load fail. This can return null to allow the default fallback mecanism to work
+     * @param rootUrl the url of the texture
+     * @param textureFormatInUse defines the current compressed format in use iun the engine
+     * @returns the fallback texture
+     */
+    public getFallbackTextureUrl(rootUrl: string, textureFormatInUse: Nullable<string>): Nullable<string> {
+        return null;
+    }
+
+    /**
+     * Uploads the cube texture data to the WebGl Texture. It has already been bound.
+     * @param data contains the texture data
+     * @param texture defines the BabylonJS internal texture
+     * @param createPolynomials will be true if polynomials have been requested
+     * @param onLoad defines the callback to trigger once the texture is ready
+     * @param onError defines the callback to trigger in case of error
+     */
+    public loadCubeData(data: string | ArrayBuffer | (string | ArrayBuffer)[], texture: InternalTexture, createPolynomials: boolean, onLoad: Nullable<(data?: any) => void>, onError: Nullable<(message?: string, exception?: any) => void>): void {
+        throw ".basis not supported in Cube.";
+    }
+
+    /**
+     * Uploads the 2D texture data to the WebGl Texture. It has alreday been bound once in the callback.
+     * @param data contains the texture data
+     * @param texture defines the BabylonJS internal texture
+     * @param callback defines the method to call once ready to upload
+     */
+    public loadData(data: ArrayBuffer, texture: InternalTexture,
+        callback: (width: number, height: number, loadMipmap: boolean, isCompressed: boolean, done: () => void) => void): void {
+        // Verify Basis Module is loaded and detect file info and format
+        BasisTools.VerifyBasisModuleAsync().then(() => {
+            var loadedFile = BasisTools.LoadBasisFile(data);
+            var fileInfo = BasisTools.GetFileInfo(loadedFile);
+            var format = BasisTools.GetSupportedTranscodeFormat(texture.getEngine(), fileInfo);
+            texture._invertVScale = true;
+
+            // TODO this should be done in web worker
+            var transcodeResult = BasisTools.TranscodeFile(format, fileInfo, loadedFile);
+
+            // Upload data to texture
+            callback(fileInfo.width, fileInfo.height, false, true, () => {
+                if (transcodeResult.fallbackToRgb565) {
+                    texture.type = Engine.TEXTURETYPE_UNSIGNED_SHORT_5_6_5;
+                    texture.format = Engine.TEXTUREFORMAT_RGB;
+
+                    // Create non power of two texture
+                    let source = new InternalTexture(texture.getEngine(), InternalTexture.DATASOURCE_TEMP);
+
+                    source.type = Engine.TEXTURETYPE_UNSIGNED_SHORT_5_6_5;
+                    source.format = Engine.TEXTUREFORMAT_RGB;
+                    source.width = fileInfo.alignedWidth;
+                    source.height = fileInfo.alignedHeight;
+                    texture.getEngine()._bindTextureDirectly(source.getEngine()._gl.TEXTURE_2D, source, true);
+                    texture.getEngine()._uploadDataToTextureDirectly(source, transcodeResult.pixels, 0, 0, Engine.TEXTUREFORMAT_RGB, true);
+
+                    // Resize to power of two
+                    source.getEngine()._rescaleTexture(source, texture, texture.getEngine().scenes[0], source.getEngine()._getInternalFormat(Engine.TEXTUREFORMAT_RGB), () => {
+                        source.getEngine()._releaseTexture(source);
+                        source.getEngine()._bindTextureDirectly(source.getEngine()._gl.TEXTURE_2D, texture, true);
+                    });
+                }else {
+                    texture.getEngine()._uploadCompressedDataToTextureDirectly(texture, BasisTools.GetInternalFormatFromBasisFormat(format!), fileInfo.width, fileInfo.height, transcodeResult.pixels, 0, 0);
+                }
+            });
+        });
+    }
+}
+
+// Register the loader.
+Engine._TextureLoaders.push(new _BasisTextureLoader());

+ 2 - 1
src/Materials/Textures/Loaders/index.ts

@@ -1,4 +1,5 @@
 export * from "./ddsTextureLoader";
 export * from "./envTextureLoader";
 export * from "./ktxTextureLoader";
-export * from "./tgaTextureLoader";
+export * from "./tgaTextureLoader";
+export * from "./basisTextureLoader";

+ 1 - 1
src/Materials/Textures/Procedurals/proceduralTexture.ts

@@ -143,7 +143,7 @@ export class ProceduralTexture extends Texture {
 
     /**
      * The effect that is created when initializing the post process.
-     * @returns The created effect corrisponding the the postprocess.
+     * @returns The created effect corresponding the the postprocess.
      */
     public getEffect(): Effect {
         return this._effect;

+ 244 - 0
src/Misc/basis.ts

@@ -0,0 +1,244 @@
+import { Nullable } from '../types';
+import { Engine } from '../Engines/engine';
+import { Tools } from './tools';
+
+/**
+ * Info about the .basis files
+ */
+class BasisFileInfo {
+    /**
+     * If the file has alpha
+     */
+    public hasAlpha: boolean;
+    /**
+     * Width of the image
+     */
+    public width: number;
+    /**
+     * Height of the image
+     */
+    public height: number;
+    /**
+     * Aligned width used when falling back to Rgb565 ((width + 3) & ~3)
+     */
+    public alignedWidth: number;
+    /**
+     * Aligned height used when falling back to Rgb565 ((height + 3) & ~3)
+     */
+    public alignedHeight: number;
+}
+
+/**
+ * Used to load .Basis files
+ * See https://github.com/BinomialLLC/basis_universal/tree/master/webgl
+ */
+export class BasisTools {
+    private static _IgnoreSupportedFormats = false;
+    private static _LoadScriptPromise: any = null;
+    // TODO should load from cdn location as fallback once it exists
+    private static _FallbackURL = "../dist/preview%20release/basisTranscoder/basis_transcoder.js";
+    private static _BASIS_FORMAT = {
+        cTFETC1: 0,
+        cTFBC1: 1,
+        cTFBC4: 2,
+        cTFPVRTC1_4_OPAQUE_ONLY: 3,
+        cTFBC7_M6_OPAQUE_ONLY: 4,
+        cTFETC2: 5,
+        cTFBC3: 6,
+        cTFBC5: 7,
+    };
+    /**
+     * Basis module can be aquired from https://github.com/BinomialLLC/basis_universal/tree/master/webgl
+     * This should be set prior to loading a .basis texture
+     */
+    public static BasisModule: Nullable<any> = null;
+
+    /**
+     * Verifies that the BasisModule has been populated and falls back to loading from the web if not availible
+     * @returns promise which will resolve if the basis module was loaded
+     */
+    public static VerifyBasisModuleAsync() {
+        // Complete if module has been populated
+        if (BasisTools.BasisModule) {
+            return Promise.resolve();
+        }
+
+        // Otherwise load script from fallback url
+        if (!this._LoadScriptPromise) {
+            this._LoadScriptPromise = Tools.LoadScriptAsync(BasisTools._FallbackURL, "basis_transcoder").then((success) => {
+                return new Promise((res, rej) => {
+                    if ((window as any).Module) {
+                        (window as any).Module.onRuntimeInitialized = () => {
+                            BasisTools.BasisModule = (window as any).Module;
+                            BasisTools.BasisModule.initializeBasis();
+                            res();
+                        };
+                    }else {
+                        rej("Unable to load .basis texture, BasisTools.BasisModule should be populated");
+                    }
+                });
+            });
+        }
+        return this._LoadScriptPromise;
+    }
+
+    /**
+     * Verifies that the basis module has been populated and creates a bsis file from the image data
+     * @param data array buffer of the .basis file
+     * @returns the Basis file
+     */
+    public static LoadBasisFile(data: ArrayBuffer) {
+        return new BasisTools.BasisModule.BasisFile(new Uint8Array(data));
+    }
+
+    /**
+     * Detects the supported transcode format for the file
+     * @param engine Babylon engine
+     * @param fileInfo info about the file
+     * @returns the chosed format or null if none are supported
+     */
+    public static GetSupportedTranscodeFormat(engine: Engine, fileInfo: BasisFileInfo): Nullable<number> {
+        var caps = engine.getCaps();
+        var format = null;
+        if (caps.etc1) {
+            format = BasisTools._BASIS_FORMAT.cTFETC1;
+        }else if (caps.s3tc) {
+            format = fileInfo.hasAlpha ? BasisTools._BASIS_FORMAT.cTFBC3 : BasisTools._BASIS_FORMAT.cTFBC1;
+        }else if (caps.pvrtc) {
+            format = BasisTools._BASIS_FORMAT.cTFPVRTC1_4_OPAQUE_ONLY;
+        }else if (caps.etc2) {
+            format = BasisTools._BASIS_FORMAT.cTFETC2;
+        }
+        return format;
+    }
+
+    /**
+     * Get the internal format to be passed to texImage2D corresponding to the .basis format value
+     * @param basisFormat format chosen from GetSupportedTranscodeFormat
+     * @returns internal format corresponding to the Basis format
+     */
+    public static GetInternalFormatFromBasisFormat(basisFormat: number) {
+        // TODO more formats need to be added here and validated
+        var COMPRESSED_RGB_S3TC_DXT1_EXT  = 0x83F0;
+        var COMPRESSED_RGBA_S3TC_DXT5_EXT = 0x83F3;
+        var RGB_ETC1_Format = 36196;
+
+        // var COMPRESSED_RGBA_S3TC_DXT1_EXT = 0x83F1;
+        // var COMPRESSED_RGBA_S3TC_DXT3_EXT = 0x83F2;
+
+        if (basisFormat === this._BASIS_FORMAT.cTFETC1) {
+            return RGB_ETC1_Format;
+        }else if (basisFormat === this._BASIS_FORMAT.cTFBC1) {
+            return COMPRESSED_RGB_S3TC_DXT1_EXT;
+        }else if (basisFormat === this._BASIS_FORMAT.cTFBC3) {
+            return COMPRESSED_RGBA_S3TC_DXT5_EXT;
+        }else {
+            // TODO find value for these formats
+            // else if(basisFormat === this.BASIS_FORMAT.cTFBC4){
+            // }else if(basisFormat === this.BASIS_FORMAT.cTFPVRTC1_4_OPAQUE_ONLY){
+            // }else if(basisFormat === this.BASIS_FORMAT.cTFBC7_M6_OPAQUE_ONLY){
+            // }else if(basisFormat === this.BASIS_FORMAT.cTFETC2){
+            // }else if(basisFormat === this.BASIS_FORMAT.cTFBC5){
+            // }
+            throw "Basis format not found or supported";
+        }
+    }
+
+    /**
+     * Retreives information about the basis file eg. dimensions
+     * @param basisFile the basis file to get the info from
+     * @returns information about the basis file
+     */
+    public static GetFileInfo(basisFile: any): BasisFileInfo {
+        var hasAlpha = basisFile.getHasAlpha();
+        var width = basisFile.getImageWidth(0, 0);
+        var height = basisFile.getImageHeight(0, 0);
+        var alignedWidth = (width + 3) & ~3;
+        var alignedHeight = (height + 3) & ~3;
+        var info = { hasAlpha, width, height, alignedWidth, alignedHeight };
+        return info;
+    }
+
+    /**
+     * Transcodes the basis file to the requested format to be transferred to the gpu
+     * @param format fromat to be transferred to
+     * @param fileInfo information about the loaded file
+     * @param loadedFile the loaded basis file
+     * @returns the resulting pixels and if the transcode fell back to using Rgb565
+     */
+    public static TranscodeFile(format: Nullable<number>, fileInfo: BasisFileInfo, loadedFile: any) {
+        if (BasisTools._IgnoreSupportedFormats) {
+            format = null;
+        }
+        var needsConversion = false;
+        if (format === null) {
+            needsConversion = true;
+            format = fileInfo.hasAlpha ? BasisTools._BASIS_FORMAT.cTFBC3 : BasisTools._BASIS_FORMAT.cTFBC1;
+        }
+
+        if (!loadedFile.startTranscoding()) {
+            loadedFile.close();
+            loadedFile.delete();
+            throw "transcode failed";
+        }
+        var dstSize = loadedFile.getImageTranscodedSizeInBytes(0, 0, format);
+        var dst = new Uint8Array(dstSize);
+        if (!loadedFile.transcodeImage(dst, 0, 0, format, 1, 0)) {
+            loadedFile.close();
+            loadedFile.delete();
+            throw "transcode failed";
+        }
+        loadedFile.close();
+        loadedFile.delete();
+
+        // If no supported format is found, load as dxt and convert to rgb565
+        if (needsConversion) {
+            dst = BasisTools.ConvertDxtToRgb565(dst, 0, fileInfo.alignedWidth, fileInfo.alignedHeight);
+        }
+
+        return {
+            fallbackToRgb565: needsConversion, pixels: dst
+        };
+    }
+
+    /**
+     * From https://github.com/BinomialLLC/basis_universal/blob/master/webgl/texture/dxt-to-rgb565.js
+     * An unoptimized version of dxtToRgb565.  Also, the floating
+     * point math used to compute the colors actually results in
+     * slightly different colors compared to hardware DXT decoders.
+     * @param src dxt src pixels
+     * @param srcByteOffset offset for the start of src
+     * @param  width aligned width of the image
+     * @param  height aligned height of the image
+     * @return the converted pixels
+     */
+    public static ConvertDxtToRgb565(src: Uint16Array, srcByteOffset: number, width: number, height: number): Uint16Array {
+        var c = new Uint16Array(4);
+        var dst = new Uint16Array(width * height);
+
+        var blockWidth = width / 4;
+        var blockHeight = height / 4;
+        for (var blockY = 0; blockY < blockHeight; blockY++) {
+            for (var blockX = 0; blockX < blockWidth; blockX++) {
+            var i = srcByteOffset + 8 * (blockY * blockWidth + blockX);
+            c[0] = src[i] | (src[i + 1] << 8);
+            c[1] = src[i + 2] | (src[i + 3] << 8);
+            c[2] = (2 * (c[0] & 0x1f) + 1 * (c[1] & 0x1f)) / 3
+                    | (((2 * (c[0] & 0x7e0) + 1 * (c[1] & 0x7e0)) / 3) & 0x7e0)
+                    | (((2 * (c[0] & 0xf800) + 1 * (c[1] & 0xf800)) / 3) & 0xf800);
+            c[3] = (2 * (c[1] & 0x1f) + 1 * (c[0] & 0x1f)) / 3
+                    | (((2 * (c[1] & 0x7e0) + 1 * (c[0] & 0x7e0)) / 3) & 0x7e0)
+                    | (((2 * (c[1] & 0xf800) + 1 * (c[0] & 0xf800)) / 3) & 0xf800);
+            for (var row = 0; row < 4; row++) {
+                var m = src[i + 4 + row];
+                var dstI = (blockY * 4 + row) * width + blockX * 4;
+                dst[dstI++] = c[m & 0x3];
+                dst[dstI++] = c[(m >> 2) & 0x3];
+                dst[dstI++] = c[(m >> 4) & 0x3];
+                dst[dstI++] = c[(m >> 6) & 0x3];
+            }
+            }
+        }
+        return dst;
+    }
+}

+ 1 - 1
src/Misc/tools.ts

@@ -1054,7 +1054,7 @@ export class Tools {
      * @param scriptId defines the id of the script element
      * @returns a promise request object
      */
-    public static LoadScriptAsync(scriptUrl: string, scriptId?: string): Nullable<Promise<boolean>> {
+    public static LoadScriptAsync(scriptUrl: string, scriptId?: string): Promise<boolean> {
         return new Promise<boolean>((resolve, reject) => {
             if (!DomManagement.IsWindowObjectExist()) {
                 resolve(false);

+ 2 - 2
src/PostProcesses/convolutionPostProcess.ts

@@ -16,7 +16,7 @@ export class ConvolutionPostProcess extends PostProcess {
     /**
      * Creates a new instance ConvolutionPostProcess
      * @param name The name of the effect.
-     * @param kernel Array of 9 values corrisponding to the 3x3 kernel to be applied
+     * @param kernel Array of 9 values corresponding to the 3x3 kernel to be applied
      * @param options The required width/height ratio to downsize to before computing the render pass.
      * @param camera The camera to apply the render pass to.
      * @param samplingMode The sampling mode to be used when computing the pass. (default: 0)
@@ -25,7 +25,7 @@ export class ConvolutionPostProcess extends PostProcess {
      * @param textureType Type of textures used when performing the post process. (default: 0)
      */
     constructor(name: string,
-        /** Array of 9 values corrisponding to the 3x3 kernel to be applied */
+        /** Array of 9 values corresponding to the 3x3 kernel to be applied */
         public kernel: number[],
         options: number | PostProcessOptions, camera: Nullable<Camera>, samplingMode?: number, engine?: Engine, reusable?: boolean, textureType: number = Constants.TEXTURETYPE_UNSIGNED_INT) {
         super(name, "convolution", ["kernel", "screenSize"], null, options, camera, samplingMode, engine, reusable, null, textureType);

+ 2 - 2
src/PostProcesses/postProcess.ts

@@ -357,7 +357,7 @@ export class PostProcess {
 
     /**
      * The effect that is created when initializing the post process.
-     * @returns The created effect corrisponding the the postprocess.
+     * @returns The created effect corresponding the the postprocess.
      */
     public getEffect(): Effect {
         return this._effect;
@@ -576,7 +576,7 @@ export class PostProcess {
 
     /**
      * Binds all textures and uniforms to the shader, this will be run on every pass.
-     * @returns the effect corrisponding to this post process. Null if not compiled or not ready.
+     * @returns the effect corresponding to this post process. Null if not compiled or not ready.
      */
     public apply(): Nullable<Effect> {
         // Check