Sfoglia il codice sorgente

Invert vScale of compressed textures when invertY is set and invertY of ktx textures as they are inverted in the file

Trevor Baron 6 anni fa
parent
commit
434d8d326e

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

@@ -72,6 +72,7 @@
 - Added support for linking a bone to a transform node ([bghgary](https://github.com/bghgary))
 - Factored out `setDirection` function from `lookAt` for transform node ([bghgary](https://github.com/bghgary))
 - Add support for setting renderingGroupId and creating instances to `AxesViewer` ([bghgary](https://github.com/bghgary))
+- Invert vScale of compressed textures when invertY is set and invertY of ktx textures as they are inverted in the file ([TrevorDev](https://github.com/TrevorDev))
 
 ### glTF Loader
 

+ 12 - 7
src/Engine/babylon.engine.ts

@@ -4234,7 +4234,7 @@ module BABYLON {
          * * A base64 string of in-line texture data, e.g. 'data:image/jpg;base64,/...'
          * * An indicator that data being passed using the buffer parameter, e.g. 'data:mytexture.jpg'
          * @param noMipmap defines a boolean indicating that no mipmaps shall be generated.  Ignored for compressed textures.  They must be in the file
-         * @param invertY when true, image is flipped when loaded.  You probably want true. Ignored for compressed textures.  Must be flipped in the file
+         * @param invertY when true, image is flipped when loaded.  You probably want true. Certain compressed textures may invert this if their default is inverted (eg. ktx)
          * @param scene needed for loading to the correct scene
          * @param samplingMode mode with should be used sample / access the texture (Default: BABYLON.Texture.TRILINEAR_SAMPLINGMODE)
          * @param onLoad optional callback to be called upon successful completion
@@ -4279,7 +4279,7 @@ module BABYLON {
             texture.url = url;
             texture.generateMipMaps = !noMipmap;
             texture.samplingMode = samplingMode;
-            texture.invertY = invertY;
+            texture.invertY = invertY; // Note: texture.invertY may get inverted by the loader, eg. ktx is upsidedown by default
 
             if (!this._doNotHandleContextLost) {
                 // Keep a link to the buffer only if we plan to handle context lost
@@ -4306,7 +4306,7 @@ module BABYLON {
                         customFallback = true;
                         excludeLoaders.push(loader);
                         Tools.Warn((loader.constructor as any).name + " failed when trying to load " + texture.url + ", falling back to the next supported loader");
-                        this.createTexture(urlArg, noMipmap, invertY, scene, samplingMode, null, onError, buffer, texture, undefined, undefined, excludeLoaders);
+                        this.createTexture(urlArg, noMipmap, texture.invertY, scene, samplingMode, null, onError, buffer, texture, undefined, undefined, excludeLoaders);
                         return;
                     }
                 }
@@ -4316,7 +4316,7 @@ module BABYLON {
                         texture.onLoadedObservable.remove(onLoadObserver);
                     }
                     if (Tools.UseFallbackTexture) {
-                        this.createTexture(Tools.fallbackTexture, noMipmap, invertY, scene, samplingMode, null, onError, buffer, texture);
+                        this.createTexture(Tools.fallbackTexture, noMipmap, texture.invertY, scene, samplingMode, null, onError, buffer, texture);
                         return;
                     }
                 }
@@ -4333,7 +4333,7 @@ module BABYLON {
                         if (loadFailed) {
                             onInternalError("TextureLoader failed to load data");
                         } else {
-                            this._prepareWebGLTexture(texture, scene, width, height, invertY, !loadMipmap, isCompressed, () => {
+                            this._prepareWebGLTexture(texture, scene, width, height, texture.invertY, !loadMipmap, isCompressed, () => {
                                 done();
                                 return false;
                             }, samplingMode);
@@ -4356,7 +4356,7 @@ module BABYLON {
                         texture._buffer = img;
                     }
 
-                    this._prepareWebGLTexture(texture, scene, img.width, img.height, invertY, noMipmap, false, (potWidth, potHeight, continuationCallback) => {
+                    this._prepareWebGLTexture(texture, scene, img.width, img.height, texture.invertY, noMipmap, false, (potWidth, potHeight, continuationCallback) => {
                         let gl = this._gl;
                         var isPot = (img.width === potWidth && img.height === potHeight);
                         let internalFormat = format ? this._getInternalFormat(format) : ((extension === ".jpg") ? gl.RGB : gl.RGBA);
@@ -6182,6 +6182,7 @@ module BABYLON {
 
         private _prepareWebGLTexture(texture: InternalTexture, scene: Nullable<Scene>, width: number, height: number, invertY: boolean, noMipmap: boolean, isCompressed: boolean,
             processFunction: (width: number, height: number, continuationCallback: () => void) => boolean, samplingMode: number = Engine.TEXTURE_TRILINEAR_SAMPLINGMODE): void {
+            invertY = invertY === undefined ? true : invertY;
             var maxTextureSize = this.getCaps().maxTextureSize;
             var potWidth = Math.min(maxTextureSize, this.needPOTTextures ? Tools.GetExponentOfTwo(width, maxTextureSize) : width);
             var potHeight = Math.min(maxTextureSize, this.needPOTTextures ? Tools.GetExponentOfTwo(height, maxTextureSize) : height);
@@ -6201,7 +6202,11 @@ module BABYLON {
             }
 
             this._bindTextureDirectly(gl.TEXTURE_2D, texture, true);
-            this._unpackFlipY(invertY === undefined ? true : (invertY ? true : false));
+            if (isCompressed && invertY) {
+                // UNPACK_FLIP_Y_WEBGL is not supported by compressed textures so vScale needs to be inverted
+                texture._invertVScale = true;
+            }
+            this._unpackFlipY(invertY);
 
             texture.baseWidth = width;
             texture.baseHeight = height;

+ 2 - 3
src/Materials/Textures/Loaders/babylon.ktxTextureLoader.ts

@@ -59,14 +59,12 @@ module BABYLON {
             if (Array.isArray(data)) {
                 return;
             }
-
+            texture.invertY = !texture.invertY;
             var engine = texture.getEngine();
             var ktx = new KhronosTextureContainer(data, 6);
 
             var loadMipmap = ktx.numberOfMipmapLevels > 1 && texture.generateMipMaps;
 
-            engine._unpackFlipY(true);
-
             ktx.uploadLevels(texture, texture.generateMipMaps);
 
             texture.width = ktx.pixelWidth;
@@ -84,6 +82,7 @@ module BABYLON {
          */
         public loadData(data: ArrayBuffer, texture: InternalTexture,
             callback: (width: number, height: number, loadMipmap: boolean, isCompressed: boolean, done: () => void, loadFailed: boolean) => void): void {
+            texture.invertY = !texture.invertY;
             var ktx = new KhronosTextureContainer(data, 1);
 
             callback(ktx.pixelWidth, ktx.pixelHeight, false, true, () => {

+ 2 - 0
src/Materials/Textures/babylon.internalTexture.ts

@@ -138,6 +138,8 @@ module BABYLON {
 
         // Private
         /** @hidden */
+        public _invertVScale = false;
+        /** @hidden */
         public _initialSlot = -1;
         /** @hidden */
         public _designatedSlot = -1;

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

@@ -247,6 +247,9 @@ module BABYLON {
             scene.getEngine().onBeforeTextureInitObservable.notifyObservers(this);
 
             let load = () => {
+                if (this._texture && this._texture._invertVScale) {
+                    this.vScale *= -1;
+                }
                 if (this.onLoadObservable.hasObservers()) {
                     this.onLoadObservable.notifyObservers(this);
                 }