Pārlūkot izejas kodu

mip map support

Trevor Baron 6 gadi atpakaļ
vecāks
revīzija
6814d52fcd

+ 15 - 7
src/Materials/Textures/Loaders/basisTextureLoader.ts

@@ -81,7 +81,8 @@ export class _BasisTextureLoader implements IInternalTextureLoader {
             }
             }
         };
         };
         BasisTools.TranscodeAsync(data, transcodeConfig).then((result)=>{
         BasisTools.TranscodeAsync(data, transcodeConfig).then((result)=>{
-            callback(result.fileInfo.width, result.fileInfo.height, false, true, () => {
+            var rootImage = result.fileInfo.images[0].levels[0];
+            callback(rootImage.width, rootImage.height, false, true, () => {
                 texture._invertVScale = true;
                 texture._invertVScale = true;
                 if(result.format === -1){
                 if(result.format === -1){
                     // No compatable compressed format found, fallback to RGB
                     // No compatable compressed format found, fallback to RGB
@@ -93,10 +94,11 @@ export class _BasisTextureLoader implements IInternalTextureLoader {
 
 
                     source.type = Engine.TEXTURETYPE_UNSIGNED_SHORT_5_6_5;
                     source.type = Engine.TEXTURETYPE_UNSIGNED_SHORT_5_6_5;
                     source.format = Engine.TEXTUREFORMAT_RGB;
                     source.format = Engine.TEXTUREFORMAT_RGB;
-                    source.width = result.fileInfo.alignedWidth;
-                    source.height = result.fileInfo.alignedHeight;
+                    // Fallback requires aligned width/height
+                    source.width = (rootImage.width + 3) & ~3;;
+                    source.height =(rootImage.height + 3) & ~3;
                     texture.getEngine()._bindTextureDirectly(source.getEngine()._gl.TEXTURE_2D, source, true);
                     texture.getEngine()._bindTextureDirectly(source.getEngine()._gl.TEXTURE_2D, source, true);
-                    texture.getEngine()._uploadDataToTextureDirectly(source, result.pixels, 0, 0, Engine.TEXTUREFORMAT_RGB, true);
+                    texture.getEngine()._uploadDataToTextureDirectly(source, rootImage.transcodedPixels, 0, 0, Engine.TEXTUREFORMAT_RGB, true);
 
 
                     // Resize to power of two
                     // Resize to power of two
                     source.getEngine()._rescaleTexture(source, texture, texture.getEngine().scenes[0], source.getEngine()._getInternalFormat(Engine.TEXTUREFORMAT_RGB), () => {
                     source.getEngine()._rescaleTexture(source, texture, texture.getEngine().scenes[0], source.getEngine()._getInternalFormat(Engine.TEXTUREFORMAT_RGB), () => {
@@ -104,13 +106,19 @@ export class _BasisTextureLoader implements IInternalTextureLoader {
                         source.getEngine()._bindTextureDirectly(source.getEngine()._gl.TEXTURE_2D, texture, true);
                         source.getEngine()._bindTextureDirectly(source.getEngine()._gl.TEXTURE_2D, texture, true);
                     });
                     });
                 }else{
                 }else{
-                    texture.width = result.fileInfo.width;
-                    texture.height = result.fileInfo.height;
-                    texture.getEngine()._uploadCompressedDataToTextureDirectly(texture, BasisTools.GetInternalFormatFromBasisFormat(result.format!), result.fileInfo.width, result.fileInfo.height, result.pixels, 0, 0);
+                    texture.width = rootImage.width;
+                    texture.height = rootImage.height;
+
+                    // Upload all mip levels in the file
+                    result.fileInfo.images[0].levels.forEach((level, index)=>{
+                        texture.getEngine()._uploadCompressedDataToTextureDirectly(texture, BasisTools.GetInternalFormatFromBasisFormat(result.format!), level.width, level.height, level.transcodedPixels, 0, index);
+                    })
+
                     if(texture.getEngine().webGLVersion < 2 && (Scalar.Log2(texture.width) % 1 !== 0 || Scalar.Log2(texture.height) % 1 !== 0)){
                     if(texture.getEngine().webGLVersion < 2 && (Scalar.Log2(texture.width) % 1 !== 0 || Scalar.Log2(texture.height) % 1 !== 0)){
                         Tools.Warn("Loaded .basis texture width and height are not a power of two. Texture wrapping will be set to Texture.CLAMP_ADDRESSMODE as other modes are not supported with non power of two dimensions in webGL 1.");
                         Tools.Warn("Loaded .basis texture width and height are not a power of two. Texture wrapping will be set to Texture.CLAMP_ADDRESSMODE as other modes are not supported with non power of two dimensions in webGL 1.");
                         texture._cachedWrapU = Texture.CLAMP_ADDRESSMODE;
                         texture._cachedWrapU = Texture.CLAMP_ADDRESSMODE;
                     }
                     }
+                    
                 }
                 }
             })
             })
         })
         })

+ 75 - 53
src/Misc/basis.ts

@@ -10,21 +10,9 @@ class BasisFileInfo {
      */
      */
     public hasAlpha: boolean;
     public hasAlpha: boolean;
     /**
     /**
-     * Width of the image
+     * Info about each image of the basis file
      */
      */
-    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;
+    public images: Array<{levels: Array<{width: number, height: number, transcodedPixels: ArrayBufferView}>}>
 }
 }
 
 
 /**
 /**
@@ -52,6 +40,14 @@ export class BasisTranscodeConfiguration {
          */
          */
         etc2?:boolean;
         etc2?:boolean;
     };
     };
+    /**
+     * If mipmap levels should be loaded for transcoded images (Default: true)
+     */
+    loadMipmapLevels?:boolean
+    /**
+     * Index of a single image to load (Default: all images)
+     */
+    loadSingleImage?:number
 }
 }
 
 
 /**
 /**
@@ -139,7 +135,7 @@ export class BasisTools {
      * @param config configuration options for the transcoding
      * @param config configuration options for the transcoding
      * @returns a promise resulting in the transcoded image
      * @returns a promise resulting in the transcoded image
      */
      */
-    public static TranscodeAsync(imageData: ArrayBuffer, config:BasisTranscodeConfiguration):Promise<{fileInfo:any, pixels: any, format:number}>{
+    public static TranscodeAsync(imageData: ArrayBuffer, config:BasisTranscodeConfiguration):Promise<{fileInfo:BasisFileInfo, format:number}>{
         return new Promise((res)=>{
         return new Promise((res)=>{
             this._CreateWorkerAsync().then(()=>{
             this._CreateWorkerAsync().then(()=>{
                 var messageHandler = (msg:any)=>{
                 var messageHandler = (msg:any)=>{
@@ -191,15 +187,51 @@ function workerFunc(): void {
             })
             })
         }else if(event.data.action === "transcode"){
         }else if(event.data.action === "transcode"){
             // Transcode the basis image and return the resulting pixels
             // Transcode the basis image and return the resulting pixels
+            var config:BasisTranscodeConfiguration = event.data.config;
             var imgData = event.data.imageData;
             var imgData = event.data.imageData;
             var loadedFile = new Module.BasisFile(new Uint8Array(imgData));
             var loadedFile = new Module.BasisFile(new Uint8Array(imgData));
             var fileInfo = GetFileInfo(loadedFile);
             var fileInfo = GetFileInfo(loadedFile);
             var format = event.data.ignoreSupportedFormats ? null : GetSupportedTranscodeFormat(event.data.config, fileInfo);
             var format = event.data.ignoreSupportedFormats ? null : GetSupportedTranscodeFormat(event.data.config, fileInfo);
-            var transcodeResult = TranscodeFile(format, fileInfo, loadedFile);
-            if(transcodeResult.fallbackToRgb565){
+
+            var needsConversion = false;
+            if (format === null) {
+                needsConversion = true;
+                format = fileInfo.hasAlpha ? _BASIS_FORMAT.cTFBC3 : _BASIS_FORMAT.cTFBC1;
+            }
+
+            // Begin transcode
+            if (!loadedFile.startTranscoding()) {
+                loadedFile.close();
+                loadedFile.delete();
+                throw "transcode failed";
+            }
+
+            var buffers:Array<any> = [];
+            fileInfo.images.forEach((image, imageIndex)=>{
+                if(config.loadSingleImage === undefined || config.loadSingleImage === imageIndex){
+                    if(config.loadMipmapLevels === false){
+                        var levelInfo = image.levels[0];
+                        levelInfo.transcodedPixels = TranscodeLevel(loadedFile, imageIndex, 0, format!, needsConversion);
+                        buffers.push(levelInfo.transcodedPixels.buffer)
+                    }else{
+                        image.levels.forEach((levelInfo, levelIndex)=>{
+                            levelInfo.transcodedPixels = TranscodeLevel(loadedFile, imageIndex, levelIndex, format!, needsConversion);
+                            buffers.push(levelInfo.transcodedPixels.buffer)
+                            
+                        })
+                    }
+                }
+            })
+
+            // Close file
+            loadedFile.close();
+            loadedFile.delete();
+
+           
+            if(needsConversion){
                 format = -1;
                 format = -1;
             }
             }
-            postMessage({action: "transcode", pixels:transcodeResult.pixels, fileInfo: fileInfo, format: format}, [transcodeResult.pixels.buffer]);
+            postMessage({action: "transcode", fileInfo: fileInfo, format: format}, buffers);
         }
         }
        
        
     };
     };
@@ -233,51 +265,41 @@ function workerFunc(): void {
      */
      */
     function GetFileInfo(basisFile: any): BasisFileInfo {
     function GetFileInfo(basisFile: any): BasisFileInfo {
         var hasAlpha = basisFile.getHasAlpha();
         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 };
+        var imageCount = basisFile.getNumImages();
+        var images = []
+        for(var i = 0;i<imageCount;i++){
+            var imageInfo = {
+                levels: ([] as Array<any>)
+            }
+            var levelCount = basisFile.getNumLevels(i);
+            for(var level = 0;level < levelCount;level++){
+                var levelInfo = {
+                    width: basisFile.getImageWidth(i, level),
+                    height: basisFile.getImageHeight(i, level)
+                }
+                imageInfo.levels.push(levelInfo);
+            }
+            images.push(imageInfo)
+        }
+        var info = { hasAlpha, images };
         return info;
         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
-     */
-    function TranscodeFile(format: Nullable<number>, fileInfo: BasisFileInfo, loadedFile: any) {
-        var needsConversion = false;
-        if (format === null) {
-            needsConversion = true;
-            format = fileInfo.hasAlpha ? _BASIS_FORMAT.cTFBC3 : _BASIS_FORMAT.cTFBC1;
-        }
-
-        if (!loadedFile.startTranscoding()) {
-            loadedFile.close();
-            loadedFile.delete();
-            throw "transcode failed";
-        }
-        var dstSize = loadedFile.getImageTranscodedSizeInBytes(0, 0, format);
+    function TranscodeLevel(loadedFile:any, imageIndex:number, levelIndex:number, format: number, convertToRgb565: boolean){
+        var dstSize = loadedFile.getImageTranscodedSizeInBytes(imageIndex, levelIndex, format);
         var dst = new Uint8Array(dstSize);
         var dst = new Uint8Array(dstSize);
-        if (!loadedFile.transcodeImage(dst, 0, 0, format, 1, 0)) {
+        if (!loadedFile.transcodeImage(dst, imageIndex, levelIndex, format, 1, 0)) {
             loadedFile.close();
             loadedFile.close();
             loadedFile.delete();
             loadedFile.delete();
             throw "transcode failed";
             throw "transcode failed";
         }
         }
-        loadedFile.close();
-        loadedFile.delete();
-
         // If no supported format is found, load as dxt and convert to rgb565
         // If no supported format is found, load as dxt and convert to rgb565
-        if (needsConversion) {
-            dst = ConvertDxtToRgb565(dst, 0, fileInfo.alignedWidth, fileInfo.alignedHeight);
+        if (convertToRgb565) {
+            var alignedWidth = (loadedFile.getImageWidth(imageIndex, levelIndex) + 3) & ~3;
+            var alignedHeight = (loadedFile.getImageHeight(imageIndex, levelIndex) + 3) & ~3;
+            dst = ConvertDxtToRgb565(dst, 0, alignedWidth, alignedHeight);
         }
         }
-
-        return {
-            fallbackToRgb565: needsConversion, pixels: dst
-        };
+        return dst;
     }
     }
 
 
     /**
     /**