浏览代码

Merge pull request #1550 from Palmer-JC/master

Compressed Textures Framework
David Catuhe 8 年之前
父节点
当前提交
76c2745cd7

二进制
Exporters/Blender/Blender2Babylon-5.0.zip


二进制
Exporters/Blender/Blender2Babylon-5.1.zip


+ 1 - 1
Exporters/Blender/readme.md

@@ -56,7 +56,7 @@ For a discussion of Tower of Babel exporter, along with the difference this expo
  * Child materials
  * Child materials
  * 32 bit vertex limit for multi-materials
  * 32 bit vertex limit for multi-materials
 * **Textures**
 * **Textures**
- * Name(s) - Multiples for compressed texture prioritization
+ * Name
  * Associated file
  * Associated file
  * Level
  * Level
  * Use alpha
  * Use alpha

+ 1 - 1
Exporters/Blender/src/__init__.py

@@ -1,7 +1,7 @@
 bl_info = {
 bl_info = {
     'name': 'Babylon.js',
     'name': 'Babylon.js',
     'author': 'David Catuhe, Jeff Palmer',
     'author': 'David Catuhe, Jeff Palmer',
-    'version': (5, 1, 0),
+    'version': (5, 1, 1),
     'blender': (2, 76, 0),
     'blender': (2, 76, 0),
     'location': 'File > Export > Babylon.js (.babylon)',
     'location': 'File > Export > Babylon.js (.babylon)',
     'description': 'Export Babylon.js scenes (.babylon)',
     'description': 'Export Babylon.js scenes (.babylon)',

+ 7 - 23
Exporters/Blender/src/exporter_settings_panel.py

@@ -1,9 +1,6 @@
 from .package_level import *
 from .package_level import *
 
 
 import bpy
 import bpy
-LEGACY      = 'LEGACY'
-INLINE      = 'INLINE'
-PRIORITIZED = 'PRIORITIZED'
 # Panel displayed in Scene Tab of properties, so settings can be saved in a .blend file
 # Panel displayed in Scene Tab of properties, so settings can be saved in a .blend file
 class ExporterSettingsPanel(bpy.types.Panel):
 class ExporterSettingsPanel(bpy.types.Panel):
     bl_label = get_title()
     bl_label = get_title()
@@ -36,21 +33,11 @@ class ExporterSettingsPanel(bpy.types.Panel):
         description='',
         description='',
         default = True
         default = True
         )
         )
-    bpy.types.Scene.textureMethod = bpy.props.EnumProperty(
-        name='Method',
-        description='How are textures to be implemented',
-        items = (
-                 (LEGACY     , 'Legacy'     , 'Just the single Blender texture'),
-                 (INLINE     , 'Inline'     , 'Place a base64 version of texture directly in the output'),
-                 (PRIORITIZED, 'Prioritized', 'Allow various compressed texture formats to be tried first')
-                ),
-        default = LEGACY
+    bpy.types.Scene.inlineTextures = bpy.props.BoolProperty(
+        name='inline',
+        description='turn textures into encoded strings, for direct inclusion into source code',
+        default = False
     )
     )
-    bpy.types.Scene.texturePriority = bpy.props.StringProperty(
-        name='Order',
-        description='Space delimited list of extensions to try\nnot including format supplied by Blender\nwhich will be last.',
-        default = '.ASTC .DDS .ETC'
-        )
     bpy.types.Scene.textureDir = bpy.props.StringProperty(
     bpy.types.Scene.textureDir = bpy.props.StringProperty(
         name='Sub-directory',
         name='Sub-directory',
         description='The path below the output directory to write texture files (any separators OS dependent)',
         description='The path below the output directory to write texture files (any separators OS dependent)',
@@ -71,13 +58,10 @@ class ExporterSettingsPanel(bpy.types.Panel):
         layout.prop(scene, 'ignoreIKBones')
         layout.prop(scene, 'ignoreIKBones')
 
 
         box = layout.box()
         box = layout.box()
-        box.label(text='Texture Options:')
-        box.prop(scene, 'textureMethod')
-        row = box.row()
-        row.enabled = scene.textureMethod == PRIORITIZED
-        row.prop(scene, 'texturePriority')
+        box.label(text='Texture Location:')
+        box.prop(scene, 'inlineTextures')
         row = box.row()
         row = box.row()
-        row.enabled = scene.textureMethod != INLINE
+        row.enabled = not scene.inlineTextures
         row.prop(scene, 'textureDir')
         row.prop(scene, 'textureDir')
 
 
         box = layout.box()
         box = layout.box()

+ 4 - 5
Exporters/Blender/src/json_exporter.py

@@ -32,7 +32,7 @@ class JsonExporter:
 
 
             # assign texture location, purely temporary if inlining
             # assign texture location, purely temporary if inlining
             self.textureDir = path.dirname(filepath)
             self.textureDir = path.dirname(filepath)
-            if scene.textureMethod != INLINE:
+            if not scene.inlineTextures:
                 self.textureDir = path.join(self.textureDir, scene.textureDir)
                 self.textureDir = path.join(self.textureDir, scene.textureDir)
                 if not path.isdir(self.textureDir):
                 if not path.isdir(self.textureDir):
                     makedirs(self.textureDir)
                     makedirs(self.textureDir)
@@ -42,11 +42,10 @@ class JsonExporter:
             Logger.log('Scene settings used:', 1)
             Logger.log('Scene settings used:', 1)
             Logger.log('selected layers only:  ' + format_bool(scene.export_onlySelectedLayer), 2)
             Logger.log('selected layers only:  ' + format_bool(scene.export_onlySelectedLayer), 2)
             Logger.log('flat shading entire scene:  ' + format_bool(scene.export_flatshadeScene), 2)
             Logger.log('flat shading entire scene:  ' + format_bool(scene.export_flatshadeScene), 2)
-            Logger.log('texture Method:  ' + scene.textureMethod, 2)
-            if scene.textureMethod != INLINE:
+            Logger.log('inline textures:  ' + format_bool(scene.inlineTextures), 2)
+            if not scene.inlineTextures:
                 Logger.log('texture directory:  ' + self.textureDir, 2)
                 Logger.log('texture directory:  ' + self.textureDir, 2)
-            if scene.textureMethod == PRIORITIZED:
-                Logger.log('Priority Order:  ' + scene.texturePriority)
+                
             self.world = World(scene)
             self.world = World(scene)
 
 
             bpy.ops.screen.animation_cancel()
             bpy.ops.screen.animation_cancel()

+ 5 - 28
Exporters/Blender/src/material.py

@@ -1,4 +1,3 @@
-from .exporter_settings_panel import *
 from .logger import *
 from .logger import *
 from .package_level import *
 from .package_level import *
 
 
@@ -84,7 +83,7 @@ class Texture:
 
 
             # when coming from either a packed image or a baked image, then save_render
             # when coming from either a packed image or a baked image, then save_render
             if internalImage:
             if internalImage:
-                if exporter.scene.textureMethod == INLINE:
+                if exporter.scene.inlineTextures:
                     textureFile = path.join(exporter.textureDir, self.fileNoPath + 'temp')
                     textureFile = path.join(exporter.textureDir, self.fileNoPath + 'temp')
                 else:
                 else:
                     textureFile = path.join(exporter.textureDir, self.fileNoPath)
                     textureFile = path.join(exporter.textureDir, self.fileNoPath)
@@ -100,7 +99,7 @@ class Texture:
             ex = exc_info()
             ex = exc_info()
             Logger.warn('Error encountered processing image file:  ' + ', Error:  '+ str(ex[1]))
             Logger.warn('Error encountered processing image file:  ' + ', Error:  '+ str(ex[1]))
 
 
-        if exporter.scene.textureMethod == INLINE:
+        if exporter.scene.inlineTextures:
             # base64 is easiest from a file, so sometimes a temp file was made above;  need to delete those
             # base64 is easiest from a file, so sometimes a temp file was made above;  need to delete those
             with open(textureFile, "rb") as image_file:
             with open(textureFile, "rb") as image_file:
                 asString = b64encode(image_file.read()).decode()
                 asString = b64encode(image_file.read()).decode()
@@ -109,16 +108,6 @@ class Texture:
             if internalImage:
             if internalImage:
                 remove(textureFile)
                 remove(textureFile)
 
 
-        # build priority Order
-        if exporter.scene.textureMethod == PRIORITIZED:
-            nameNoExtension = self.fileNoPath.rpartition('.')[0]
-            self.priorityNames = []
-            for ext in exporter.scene.texturePriority.split():
-                self.priorityNames.append(nameNoExtension + ext)
-
-            # add blend image last
-            self.priorityNames.append(self.fileNoPath)
-
         # capture texture attributes
         # capture texture attributes
         self.slot = slot
         self.slot = slot
         self.level = level
         self.level = level
@@ -154,21 +143,7 @@ class Texture:
 # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
     def to_scene_file(self, file_handler):
     def to_scene_file(self, file_handler):
         file_handler.write(', \n"' + self.slot + '":{')
         file_handler.write(', \n"' + self.slot + '":{')
-        if hasattr(self,'encoded_URI'):
-            write_string(file_handler, 'base64String', self.encoded_URI)
-
-        elif hasattr(self,'priorityNames'):
-            file_handler.write('"name":[')
-            first = True
-            for name in self.priorityNames:
-                if first == False:
-                    file_handler.write(',')
-                file_handler.write('"' + name + '"')
-                first = False
-            file_handler.write(']')
-
-        else:
-            write_string(file_handler, 'name', self.fileNoPath, True)
+        write_string(file_handler, 'name', self.fileNoPath, True)
 
 
         write_float(file_handler, 'level', self.level)
         write_float(file_handler, 'level', self.level)
         write_float(file_handler, 'hasAlpha', self.hasAlpha)
         write_float(file_handler, 'hasAlpha', self.hasAlpha)
@@ -183,6 +158,8 @@ class Texture:
         write_int(file_handler, 'wrapU', self.wrapU)
         write_int(file_handler, 'wrapU', self.wrapU)
         write_int(file_handler, 'wrapV', self.wrapV)
         write_int(file_handler, 'wrapV', self.wrapV)
         write_int(file_handler, 'coordinatesIndex', self.coordinatesIndex)
         write_int(file_handler, 'coordinatesIndex', self.coordinatesIndex)
+        if hasattr(self,'encoded_URI'):
+            write_string(file_handler, 'base64String', self.encoded_URI)
         file_handler.write('}')
         file_handler.write('}')
 #===============================================================================
 #===============================================================================
 # need to evaluate the need to bake a mesh before even starting; class also stores specific types of bakes
 # need to evaluate the need to bake a mesh before even starting; class also stores specific types of bakes

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

@@ -14,7 +14,7 @@
 - Added `scene.multiPick` and `scene.multiPickWithRay` to return an array of pickedMesh objects ([deltakosh](https://github.com/deltakosh))
 - Added `scene.multiPick` and `scene.multiPickWithRay` to return an array of pickedMesh objects ([deltakosh](https://github.com/deltakosh))
 - Added `Effect.GetVertexShaderSource()` and `Effect.GetFragmentShaderSource()` ([deltakosh](https://github.com/deltakosh))
 - Added `Effect.GetVertexShaderSource()` and `Effect.GetFragmentShaderSource()` ([deltakosh](https://github.com/deltakosh))
 - New `Texture.LoadFromDataString()` to help loading base64 encoded textures ([deltakosh](https://github.com/deltakosh))
 - New `Texture.LoadFromDataString()` to help loading base64 encoded textures ([deltakosh](https://github.com/deltakosh))
-- You can now specify an array of string when loading a texture (they will be considered as fallbacks) ([deltakosh](https://github.com/deltakosh))
+- Added Engine detection of the compresed texture formats supported by Hw / browser.  You can specify those formats you have files for using `Engine.setTextureFormatToUse()`, and an appropriate one will be chosen. ([Palmer-JC](https://github.com/Palmer-JC/))
 - Added Bone.getAbsolutePosition and Bone.getAbsolutePositionToRef ([abow](https://github.com/abow))
 - Added Bone.getAbsolutePosition and Bone.getAbsolutePositionToRef ([abow](https://github.com/abow))
 - Added Bone.setYawPitchRoll ([abow](https://github.com/abow))
 - Added Bone.setYawPitchRoll ([abow](https://github.com/abow))
 - Added Bone.rotate ([abow](https://github.com/abow))
 - Added Bone.rotate ([abow](https://github.com/abow))

+ 3 - 12
src/Materials/Textures/babylon.texture.ts

@@ -71,16 +71,12 @@
         private _delayedOnLoad: () => void;
         private _delayedOnLoad: () => void;
         private _delayedOnError: () => void;
         private _delayedOnError: () => void;
         private _onLoadObservarble: Observable<boolean>;
         private _onLoadObservarble: Observable<boolean>;
-        private _delayReloadData: string | Array<string>
 
 
-        constructor(urlOrList: string | Array<string>, scene: Scene, noMipmap: boolean = false, invertY: boolean = true, samplingMode: number = Texture.TRILINEAR_SAMPLINGMODE, onLoad: () => void = null, onError: () => void = null, buffer: any = null, deleteBuffer: boolean = false) {
+        constructor(url: string, scene: Scene, noMipmap: boolean = false, invertY: boolean = true, samplingMode: number = Texture.TRILINEAR_SAMPLINGMODE, onLoad: () => void = null, onError: () => void = null, buffer: any = null, deleteBuffer: boolean = false) {
             super(scene);
             super(scene);
 
 
-            var url = <string>((urlOrList instanceof Array) ? urlOrList[0] : urlOrList);
-
             this.name = url;
             this.name = url;
             this.url = url;
             this.url = url;
-            this._delayReloadData = urlOrList;
             this._noMipmap = noMipmap;
             this._noMipmap = noMipmap;
             this._invertY = invertY;
             this._invertY = invertY;
             this._samplingMode = samplingMode;
             this._samplingMode = samplingMode;
@@ -104,7 +100,7 @@
 
 
             if (!this._texture) {
             if (!this._texture) {
                 if (!scene.useDelayedTextureLoading) {
                 if (!scene.useDelayedTextureLoading) {
-                    this._texture = scene.getEngine().createTexture(urlOrList, noMipmap, invertY, scene, this._samplingMode, load, onError, this._buffer);
+                    this._texture = scene.getEngine().createTexture(url, noMipmap, invertY, scene, this._samplingMode, load, onError, this._buffer);
                     if (deleteBuffer) {
                     if (deleteBuffer) {
                         delete this._buffer;
                         delete this._buffer;
                     }
                     }
@@ -132,7 +128,7 @@
             this._texture = this._getFromCache(this.url, this._noMipmap, this._samplingMode);
             this._texture = this._getFromCache(this.url, this._noMipmap, this._samplingMode);
 
 
             if (!this._texture) {
             if (!this._texture) {
-                this._texture = this.getScene().getEngine().createTexture(this._delayReloadData, this._noMipmap, this._invertY, this.getScene(), this._samplingMode, this._delayedOnLoad, this._delayedOnError, this._buffer);
+                this._texture = this.getScene().getEngine().createTexture(this.url, this._noMipmap, this._invertY, this.getScene(), this._samplingMode, this._delayedOnLoad, this._delayedOnError, this._buffer);
                 if (this._deleteBuffer) {
                 if (this._deleteBuffer) {
                     delete this._buffer;
                     delete this._buffer;
                 }
                 }
@@ -301,11 +297,6 @@
                     var texture: Texture;
                     var texture: Texture;
                     if (parsedTexture.base64String) {
                     if (parsedTexture.base64String) {
                         texture = Texture.CreateFromBase64String(parsedTexture.base64String, parsedTexture.name, scene);
                         texture = Texture.CreateFromBase64String(parsedTexture.base64String, parsedTexture.name, scene);
-                    } else if (parsedTexture.name instanceof Array) {
-                        for (var i = 0, len = parsedTexture.name.length; i < len; i++) {
-                            parsedTexture.name[i] = rootUrl + parsedTexture.name[i];
-                        }
-                        texture = new Texture(parsedTexture.name, scene);
                     } else {
                     } else {
                         texture = new Texture(rootUrl + parsedTexture.name, scene);
                         texture = new Texture(rootUrl + parsedTexture.name, scene);
                     }
                     }

+ 77 - 23
src/babylon.engine.ts

@@ -174,6 +174,10 @@
         public maxVertexAttribs: number;
         public maxVertexAttribs: number;
         public standardDerivatives: boolean;
         public standardDerivatives: boolean;
         public s3tc: WEBGL_compressed_texture_s3tc;
         public s3tc: WEBGL_compressed_texture_s3tc;
+        public pvrtc: any; //WEBGL_compressed_texture_pvrtc;
+        public etc1: any; //WEBGL_compressed_texture_etc1;
+        public etc2: any; //WEBGL_compressed_texture_etc;
+        public astc: any; //WEBGL_compressed_texture_astc;
         public textureFloat: boolean;
         public textureFloat: boolean;
         public textureAnisotropicFilterExtension: EXT_texture_filter_anisotropic;
         public textureAnisotropicFilterExtension: EXT_texture_filter_anisotropic;
         public maxAnisotropy: number;
         public maxAnisotropy: number;
@@ -481,7 +485,19 @@
 
 
         private _externalData: StringDictionary<Object>;
         private _externalData: StringDictionary<Object>;
         private _bindedRenderFunction: any;
         private _bindedRenderFunction: any;
-
+        
+        // Hardware supported Compressed Textures
+        private _texturesSupported = new Array<string>();
+        private _textureFormatInUse : string; 
+        
+        public get texturesSupported(): Array<string> {
+            return this._texturesSupported;
+        }
+        
+        public get textureFormatInUse(): string {
+            return this._textureFormatInUse;
+        }
+        
         /**
         /**
          * @constructor
          * @constructor
          * @param {HTMLCanvasElement} canvas - the canvas to be used for rendering
          * @param {HTMLCanvasElement} canvas - the canvas to be used for rendering
@@ -576,7 +592,13 @@
 
 
             // Extensions
             // Extensions
             this._caps.standardDerivatives = (this._gl.getExtension('OES_standard_derivatives') !== null);
             this._caps.standardDerivatives = (this._gl.getExtension('OES_standard_derivatives') !== null);
-            this._caps.s3tc = this._gl.getExtension('WEBGL_compressed_texture_s3tc');
+            
+            this._caps.astc  = this._gl.getExtension('WEBGL_compressed_texture_astc');
+            this._caps.s3tc  = this._gl.getExtension('WEBGL_compressed_texture_s3tc');
+            this._caps.pvrtc = this._gl.getExtension('WEBGL_compressed_texture_pvrtc') || this._gl.getExtension('WEBKIT_WEBGL_compressed_texture_pvrtc'); // 2nd is what iOS reports
+            this._caps.etc1  = this._gl.getExtension('WEBGL_compressed_texture_etc1');
+            this._caps.etc2  = this._gl.getExtension('WEBGL_compressed_texture_etc') || this._gl.getExtension('WEBGL_compressed_texture_es3_0'); // first is the final name, found hardware using 2nd
+            
             this._caps.textureFloat = (this._gl.getExtension('OES_texture_float') !== null);
             this._caps.textureFloat = (this._gl.getExtension('OES_texture_float') !== null);
             this._caps.textureAnisotropicFilterExtension = this._gl.getExtension('EXT_texture_filter_anisotropic') || this._gl.getExtension('WEBKIT_EXT_texture_filter_anisotropic') || this._gl.getExtension('MOZ_EXT_texture_filter_anisotropic');
             this._caps.textureAnisotropicFilterExtension = this._gl.getExtension('EXT_texture_filter_anisotropic') || this._gl.getExtension('WEBKIT_EXT_texture_filter_anisotropic') || this._gl.getExtension('MOZ_EXT_texture_filter_anisotropic');
             this._caps.maxAnisotropy = this._caps.textureAnisotropicFilterExtension ? this._gl.getParameter(this._caps.textureAnisotropicFilterExtension.MAX_TEXTURE_MAX_ANISOTROPY_EXT) : 0;
             this._caps.maxAnisotropy = this._caps.textureAnisotropicFilterExtension ? this._gl.getParameter(this._caps.textureAnisotropicFilterExtension.MAX_TEXTURE_MAX_ANISOTROPY_EXT) : 0;
@@ -592,7 +614,18 @@
             this._caps.textureHalfFloat = (this._gl.getExtension('OES_texture_half_float') !== null);
             this._caps.textureHalfFloat = (this._gl.getExtension('OES_texture_half_float') !== null);
             this._caps.textureHalfFloatLinearFiltering = this._gl.getExtension('OES_texture_half_float_linear');
             this._caps.textureHalfFloatLinearFiltering = this._gl.getExtension('OES_texture_half_float_linear');
             this._caps.textureHalfFloatRender = renderToHalfFloat;
             this._caps.textureHalfFloatRender = renderToHalfFloat;
-
+            
+            // Intelligently add supported commpressed formats in order to check for.
+            // Check for ASTC support first as it is most powerful and to be very cross platform.
+            // Next PVR & S3, which are probably superior to ETC1/2.  
+            // Likely no hardware which supports both PVR & S3, so order matters little.
+            // ETC2 is newer and handles ETC1, so check for first.
+            if (this._caps.astc ) this.texturesSupported.push('.astc');
+            if (this._caps.s3tc ) this.texturesSupported.push('.dds');
+            if (this._caps.pvrtc) this.texturesSupported.push('.pvr');
+            if (this._caps.etc2 ) this.texturesSupported.push('.etc2');
+            if (this._caps.etc1 ) this.texturesSupported.push('.etc1');
+            
             if (this._gl.getShaderPrecisionFormat) {
             if (this._gl.getShaderPrecisionFormat) {
                 var highp = this._gl.getShaderPrecisionFormat(this._gl.FRAGMENT_SHADER, this._gl.HIGH_FLOAT);
                 var highp = this._gl.getShaderPrecisionFormat(this._gl.FRAGMENT_SHADER, this._gl.HIGH_FLOAT);
                 this._caps.highPrecisionShaderSupported = highp.precision !== 0;
                 this._caps.highPrecisionShaderSupported = highp.precision !== 0;
@@ -665,6 +698,9 @@
             this._badOS = regexp.test(navigator.userAgent);
             this._badOS = regexp.test(navigator.userAgent);
 
 
             Tools.Log("Babylon.js engine (v" + Engine.Version + ") launched");
             Tools.Log("Babylon.js engine (v" + Engine.Version + ") launched");
+            if (this._texturesSupported.length > 0) {
+                Tools.Log("Compressed textures formats HW / browser supports: " + this._texturesSupported);
+            }
         }
         }
 
 
         public get webGLVersion(): string {
         public get webGLVersion(): string {
@@ -1923,21 +1959,53 @@
 
 
             texture.samplingMode = samplingMode;
             texture.samplingMode = samplingMode;
         }
         }
+        /**
+         * Set the compressed texture format to use, based on the formats you have,
+         * the formats supported by the hardware / browser, and those currently implemented
+         * in BJS.
+         * 
+         * Note: The result of this call is not taken into account texture is base64 or when
+         * using a database / manifest.
+         * 
+         * @param {Array<string>} formatsAvailable - Extension names including dot.  Case
+         * and order do not matter.
+         * @returns The extension selected.
+         */
+        public setTextureFormatToUse(formatsAvailable : Array<string>) : string {
+            for (var i = 0, len1 = this.texturesSupported.length; i < len1; i++) {
+                // code to allow the formats to be added as they can be developed / hw tested
+                if (this._texturesSupported[i] === '.astc') continue;
+                if (this._texturesSupported[i] === '.pvr' ) continue;
+                if (this._texturesSupported[i] === '.etc1') continue;
+                if (this._texturesSupported[i] === '.etc2') continue;
+                
+                for (var j = 0, len2 = formatsAvailable.length; j < len2; j++) {
+                    if (this._texturesSupported[i] === formatsAvailable[j].toLowerCase()) {
+                        return this._textureFormatInUse = this._texturesSupported[i];
+                    }
+                }
+            }
+            // actively set format to nothing, to allow this to be called more than once
+            // and possibly fail the 2nd time
+            return this._textureFormatInUse = null;
+        }
 
 
-        public createTexture(urlOrList: string | Array<string>, noMipmap: boolean, invertY: boolean, scene: Scene, samplingMode: number = Texture.TRILINEAR_SAMPLINGMODE, onLoad: () => void = null, onError: () => void = null, buffer: any = null): WebGLTexture {
+        public createTexture(url: string, noMipmap: boolean, invertY: boolean, scene: Scene, samplingMode: number = Texture.TRILINEAR_SAMPLINGMODE, onLoad: () => void = null, onError: () => void = null, buffer: any = null): WebGLTexture {
             var texture = this._gl.createTexture();
             var texture = this._gl.createTexture();
 
 
-            var url = <string>((urlOrList.constructor === Array) ? urlOrList[0] : urlOrList);
-
             var extension: string;
             var extension: string;
             var fromData: any = false;
             var fromData: any = false;
             if (url.substr(0, 5) === "data:") {
             if (url.substr(0, 5) === "data:") {
                 fromData = true;
                 fromData = true;
             }
             }
 
 
-            if (!fromData)
-                extension = url.substr(url.length - 4, 4).toLowerCase();
-            else {
+            if (!fromData) {
+                var lastDot = url.lastIndexOf('.')
+                extension = url.substring(lastDot).toLowerCase();
+                if (this._textureFormatInUse && !fromData && !scene.database) {
+                    url = url.substring(0, lastDot) + this._textureFormatInUse;
+                }
+            } else {
                 var oldUrl = url;
                 var oldUrl = url;
                 fromData = oldUrl.split(':');
                 fromData = oldUrl.split(':');
                 url = oldUrl;
                 url = oldUrl;
@@ -1981,20 +2049,6 @@
                     callback(buffer);
                     callback(buffer);
 
 
             } else if (isDDS) {
             } else if (isDDS) {
-                if (!this.getCaps().s3tc) {
-                    if (urlOrList instanceof Array) {
-                        var newList = (<Array<string>>urlOrList).slice(1);
-
-                        if (newList.length > 0) {
-                            return this.createTexture(newList, noMipmap, invertY, scene, samplingMode, onLoad, onError, buffer);
-                        }
-                    }
-
-                    onerror();
-
-                    return null;
-                }
-
                 callback = (data) => {
                 callback = (data) => {
                     var info = Internals.DDSTools.GetDDSInfo(data);
                     var info = Internals.DDSTools.GetDDSInfo(data);