浏览代码

Adding better support for DDS

David Catuhe 8 年之前
父节点
当前提交
1e514b4b38

二进制
assets/textures/16testSpecularHDR.dds


二进制
assets/textures/DefaultEnvironmentMap.dds


二进制
assets/textures/testSpecularHDR.dds


文件差异内容过多而无法显示
+ 6505 - 6497
dist/preview release/babylon.d.ts


文件差异内容过多而无法显示
+ 39 - 38
dist/preview release/babylon.js


+ 129 - 37
dist/preview release/babylon.max.js

@@ -7343,6 +7343,10 @@ var BABYLON;
             if (!this._glRenderer) {
                 this._glRenderer = "Unknown renderer";
             }
+            // Constants
+            this._gl.HALF_FLOAT_OES = 0x8D61; // Half floating-point type (16-bit).
+            this._gl.RGBA16F = 0x881A; // RGBA 16-bit floating-point color-renderable internal sized format.
+            this._gl.RGBA32F = 0x8814; // RGBA 32-bit floating-point color-renderable internal sized format.            
             // Extensions
             this._caps.standardDerivatives = this._webGLVersion > 1 || (this._gl.getExtension('OES_standard_derivatives') !== null);
             this._caps.astc = this._gl.getExtension('WEBGL_compressed_texture_astc') || this._gl.getExtension('WEBKIT_WEBGL_compressed_texture_astc');
@@ -7365,7 +7369,7 @@ var BABYLON;
             this._caps.textureHalfFloat = this._webGLVersion > 1 || this._gl.getExtension('OES_texture_half_float');
             this._caps.textureHalfFloatLinearFiltering = this._webGLVersion > 1 || (this._caps.textureHalfFloat && this._gl.getExtension('OES_texture_half_float_linear'));
             if (this._webGLVersion > 1) {
-                Engine.HALF_FLOAT_OES = 0x140B;
+                this._gl.HALF_FLOAT_OES = 0x140B;
             }
             this._caps.textureHalfFloatRender = this._caps.textureHalfFloat && this._canRenderToHalfFloatFramebuffer();
             this._caps.textureLOD = this._webGLVersion > 1 || this._gl.getExtension('EXT_shader_texture_lod');
@@ -9182,7 +9186,7 @@ var BABYLON;
                         var info = BABYLON.Internals.DDSTools.GetDDSInfo(data);
                         var loadMipmap = (info.isRGB || info.isLuminance || info.mipmapCount > 1) && !noMipmap && ((info.width >> (info.mipmapCount - 1)) === 1);
                         prepareWebGLTexture(texture, _this._gl, scene, info.width, info.height, invertY, !loadMipmap, info.isFourCC, function () {
-                            BABYLON.Internals.DDSTools.UploadDDSLevels(_this._gl, _this.getCaps().s3tc, data, info, loadMipmap, 1);
+                            BABYLON.Internals.DDSTools.UploadDDSLevels(_this, data, info, loadMipmap, 1);
                         }, samplingMode);
                     };
                 }
@@ -9705,6 +9709,7 @@ var BABYLON;
             texture.references = 1;
             texture.onLoadedCallbacks = [];
             var isKTX = false;
+            var isDDS = false;
             var lastDot = rootUrl.lastIndexOf('.');
             var extension = rootUrl.substring(lastDot).toLowerCase();
             if (this._textureFormatInUse) {
@@ -9712,9 +9717,8 @@ var BABYLON;
                 rootUrl = rootUrl.substring(0, lastDot) + this._textureFormatInUse;
                 isKTX = true;
             }
-            var isDDS = this.getCaps().s3tc && (extension === ".dds");
-            if (isDDS) {
-                BABYLON.Tools.Warn("DDS files deprecated since 3.0, use KTX files");
+            else {
+                isDDS = (extension === ".dds");
             }
             if (isKTX) {
                 BABYLON.Tools.LoadFile(rootUrl, function (data) {
@@ -9739,8 +9743,10 @@ var BABYLON;
                     var info = BABYLON.Internals.DDSTools.GetDDSInfo(data);
                     var loadMipmap = (info.isRGB || info.isLuminance || info.mipmapCount > 1) && !noMipmap;
                     _this._bindTextureDirectly(gl.TEXTURE_CUBE_MAP, texture);
-                    gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, 1);
-                    BABYLON.Internals.DDSTools.UploadDDSLevels(_this._gl, _this.getCaps().s3tc, data, info, loadMipmap, 6);
+                    if (info.isCompressed) {
+                        gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, 1);
+                    }
+                    BABYLON.Internals.DDSTools.UploadDDSLevels(_this, data, info, loadMipmap, 6);
                     if (!noMipmap && !info.isFourCC && info.mipmapCount === 1) {
                         gl.generateMipmap(gl.TEXTURE_CUBE_MAP);
                     }
@@ -9753,6 +9759,7 @@ var BABYLON;
                     texture._width = info.width;
                     texture._height = info.height;
                     texture.isReady = true;
+                    texture.type = info.textureType;
                 }, null, null, true, onError);
             }
             else {
@@ -9882,7 +9889,7 @@ var BABYLON;
                 gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
                 gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
             }
-            else if (textureType === Engine.HALF_FLOAT_OES && !this._caps.textureHalfFloatLinearFiltering) {
+            else if (textureType === this._gl.HALF_FLOAT_OES && !this._caps.textureHalfFloatLinearFiltering) {
                 gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
                 gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
             }
@@ -10402,21 +10409,22 @@ var BABYLON;
                 this.fps = 1000.0 / (sum / (length - 1));
             }
         };
-        Engine.prototype._readTexturePixels = function (texture, width, height, faceIndex) {
+        Engine.prototype._readTexturePixels = function (texture, width, height, faceIndex, lodIndex) {
             if (faceIndex === void 0) { faceIndex = -1; }
+            if (lodIndex === void 0) { lodIndex = 0; }
             var gl = this._gl;
             if (!this._dummyFramebuffer) {
                 this._dummyFramebuffer = gl.createFramebuffer();
             }
             gl.bindFramebuffer(gl.FRAMEBUFFER, this._dummyFramebuffer);
             if (faceIndex > -1) {
-                gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_CUBE_MAP_POSITIVE_X + faceIndex, texture, 0);
+                gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_CUBE_MAP_POSITIVE_X + faceIndex, texture, lodIndex);
             }
             else {
-                gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0);
+                gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, lodIndex);
             }
             var readFormat = gl.RGBA;
-            var readType = gl.UNSIGNED_BYTE;
+            var readType = (texture.type !== undefined) ? texture.type : gl.UNSIGNED_BYTE;
             var buffer = new Uint8Array(4 * width * height);
             gl.readPixels(0, 0, width, height, readFormat, readType, buffer);
             gl.bindFramebuffer(gl.FRAMEBUFFER, null);
@@ -10480,7 +10488,7 @@ var BABYLON;
             }
             else if (type === Engine.TEXTURETYPE_HALF_FLOAT) {
                 // Add Half Float Constant.
-                return Engine.HALF_FLOAT_OES;
+                return this._gl.HALF_FLOAT_OES;
             }
             return this._gl.UNSIGNED_BYTE;
         };
@@ -10490,10 +10498,10 @@ var BABYLON;
                 return this._gl.RGBA;
             }
             if (type === Engine.TEXTURETYPE_FLOAT) {
-                return Engine.RGBA32F;
+                return this._gl.RGBA32F;
             }
             else if (type === Engine.TEXTURETYPE_HALF_FLOAT) {
-                return Engine.RGBA16F;
+                return this._gl.RGBA16F;
             }
             return this._gl.RGBA;
         };
@@ -10549,9 +10557,6 @@ var BABYLON;
     Engine._GREATER = 0x0204; //	Passed to depthFunction or stencilFunction to specify depth or stencil tests will pass if the new depth value is greater than the stored value.
     Engine._GEQUAL = 0x0206; //	Passed to depthFunction or stencilFunction to specify depth or stencil tests will pass if the new depth value is greater than or equal to the stored value.
     Engine._NOTEQUAL = 0x0205; //  Passed to depthFunction or stencilFunction to specify depth or stencil tests will pass if the new depth value is not equal to the stored value.
-    Engine.HALF_FLOAT_OES = 0x8D61; // Half floating-point type (16-bit).
-    Engine.RGBA16F = 0x881A; // RGBA 16-bit floating-point color-renderable internal sized format.
-    Engine.RGBA32F = 0x8814; // RGBA 32-bit floating-point color-renderable internal sized format.
     // Stencil Actions Constants.
     Engine._KEEP = 0x1E00;
     Engine._REPLACE = 0x1E01;
@@ -19113,17 +19118,28 @@ var BABYLON;
         BaseTexture.prototype.clone = function () {
             return null;
         };
-        BaseTexture.prototype.readPixels = function (faceIndex) {
+        Object.defineProperty(BaseTexture.prototype, "textureType", {
+            get: function () {
+                if (!this._texture) {
+                    return BABYLON.Engine.TEXTURETYPE_UNSIGNED_INT;
+                }
+                return (this._texture.type !== undefined) ? this._texture.type : BABYLON.Engine.TEXTURETYPE_UNSIGNED_INT;
+            },
+            enumerable: true,
+            configurable: true
+        });
+        BaseTexture.prototype.readPixels = function (faceIndex, lodIndex) {
             if (faceIndex === void 0) { faceIndex = 0; }
+            if (lodIndex === void 0) { lodIndex = 0; }
             if (!this._texture) {
                 return null;
             }
             var size = this.getSize();
             var engine = this.getScene().getEngine();
             if (this._texture.isCube) {
-                return engine._readTexturePixels(this._texture, size.width, size.height, faceIndex);
+                return engine._readTexturePixels(this._texture, size.width, size.height, faceIndex, lodIndex);
             }
-            return engine._readTexturePixels(this._texture, size.width, size.height);
+            return engine._readTexturePixels(this._texture, size.width, size.height, -1, lodIndex);
         };
         BaseTexture.prototype.releaseInternalTexture = function () {
             if (this._texture) {
@@ -31777,6 +31793,10 @@ var BABYLON;
             }
             return activeTextures;
         };
+        PBRMetallicRoughnessMaterial.prototype.clone = function (name) {
+            var _this = this;
+            return BABYLON.SerializationHelper.Clone(function () { return new PBRMetallicRoughnessMaterial(name, _this.getScene()); }, this);
+        };
         /**
          * Serialize the material to a parsable JSON object.
          */
@@ -31864,6 +31884,10 @@ var BABYLON;
             }
             return activeTextures;
         };
+        PBRSpecularGlossinessMaterial.prototype.clone = function (name) {
+            var _this = this;
+            return BABYLON.SerializationHelper.Clone(function () { return new PBRSpecularGlossinessMaterial(name, _this.getScene()); }, this);
+        };
         /**
          * Serialize the material to a parsable JSON object.
          */
@@ -50608,8 +50632,8 @@ var BABYLON;
                 effect.setFloat("base", _this.base);
                 effect.setFloat("near", _this._scene.activeCamera.minZ);
                 effect.setFloat("far", _this._scene.activeCamera.maxZ);
-                effect.setFloat("xViewport", Math.tan(_this._scene.activeCamera.fov / 2) * _this._scene.activeCamera.minZ * _this._scene.getEngine().getAspectRatio(_this._scene.activeCamera, true));
-                effect.setFloat("yViewport", Math.tan(_this._scene.activeCamera.fov / 2) * _this._scene.activeCamera.minZ);
+                effect.setFloat("xViewport", Math.tan(_this._scene.activeCamera.fov / 2) * _this._scene.getEngine().getAspectRatio(_this._scene.activeCamera, true));
+                effect.setFloat("yViewport", Math.tan(_this._scene.activeCamera.fov / 2));
                 effect.setMatrix("projection", _this._scene.getProjectionMatrix());
                 effect.setTexture("textureSampler", _this._depthTexture);
                 effect.setTexture("normalSampler", _this._normalTexture);
@@ -60749,6 +60773,10 @@ var BABYLON;
         var FOURCC_DXT1 = FourCCToInt32("DXT1");
         var FOURCC_DXT3 = FourCCToInt32("DXT3");
         var FOURCC_DXT5 = FourCCToInt32("DXT5");
+        var FOURCC_DX10 = FourCCToInt32("DX10");
+        var FOURCC_D3DFMT_R16G16B16A16F = 113;
+        var FOURCC_D3DFMT_R32G32B32A32F = 116;
+        var DXGI_FORMAT_R16G16B16A16_FLOAT = 10;
         var headerLengthInt = 31; // The header length in 32 bit ints
         // Offsets into the header array
         var off_magic = 0;
@@ -60766,16 +60794,36 @@ var BABYLON;
         var off_AMask = 26;
         var off_caps1 = 27;
         var off_caps2 = 28;
+        var off_caps3 = 29;
+        var off_caps4 = 30;
+        var off_dxgiFormat = 32;
         ;
         var DDSTools = (function () {
             function DDSTools() {
             }
             DDSTools.GetDDSInfo = function (arrayBuffer) {
                 var header = new Int32Array(arrayBuffer, 0, headerLengthInt);
+                var extendedHeader = new Int32Array(arrayBuffer, 0, headerLengthInt + 4);
                 var mipmapCount = 1;
                 if (header[off_flags] & DDSD_MIPMAPCOUNT) {
                     mipmapCount = Math.max(1, header[off_mipmapCount]);
                 }
+                var fourCC = header[off_pfFourCC];
+                var dxgiFormat = (fourCC === FOURCC_DX10) ? extendedHeader[off_dxgiFormat] : 0;
+                var textureType = BABYLON.Engine.TEXTURETYPE_UNSIGNED_INT;
+                switch (fourCC) {
+                    case FOURCC_D3DFMT_R16G16B16A16F:
+                        textureType = BABYLON.Engine.TEXTURETYPE_HALF_FLOAT;
+                        break;
+                    case FOURCC_D3DFMT_R32G32B32A32F:
+                        textureType = BABYLON.Engine.TEXTURETYPE_FLOAT;
+                        break;
+                    case FOURCC_DX10:
+                        if (dxgiFormat === DXGI_FORMAT_R16G16B16A16_FLOAT) {
+                            textureType = BABYLON.Engine.TEXTURETYPE_HALF_FLOAT;
+                            break;
+                        }
+                }
                 return {
                     width: header[off_width],
                     height: header[off_height],
@@ -60783,19 +60831,28 @@ var BABYLON;
                     isFourCC: (header[off_pfFlags] & DDPF_FOURCC) === DDPF_FOURCC,
                     isRGB: (header[off_pfFlags] & DDPF_RGB) === DDPF_RGB,
                     isLuminance: (header[off_pfFlags] & DDPF_LUMINANCE) === DDPF_LUMINANCE,
-                    isCube: (header[off_caps2] & DDSCAPS2_CUBEMAP) === DDSCAPS2_CUBEMAP
+                    isCube: (header[off_caps2] & DDSCAPS2_CUBEMAP) === DDSCAPS2_CUBEMAP,
+                    isCompressed: (fourCC === FOURCC_DXT1 || fourCC === FOURCC_DXT3 || FOURCC_DXT1 === FOURCC_DXT5),
+                    dxgiFormat: dxgiFormat,
+                    textureType: textureType
                 };
             };
+            DDSTools.GetHalfFloatRGBAArrayBuffer = function (width, height, dataOffset, dataLength, arrayBuffer) {
+                return new Uint16Array(arrayBuffer, dataOffset, dataLength);
+            };
+            DDSTools.GetFloatRGBAArrayBuffer = function (width, height, dataOffset, dataLength, arrayBuffer) {
+                return new Float32Array(arrayBuffer, dataOffset, dataLength);
+            };
             DDSTools.GetRGBAArrayBuffer = function (width, height, dataOffset, dataLength, arrayBuffer) {
                 var byteArray = new Uint8Array(dataLength);
                 var srcData = new Uint8Array(arrayBuffer);
                 var index = 0;
-                for (var y = height - 1; y >= 0; y--) {
+                for (var y = 0; y < height; y++) {
                     for (var x = 0; x < width; x++) {
                         var srcPos = dataOffset + (x + y * width) * 4;
-                        byteArray[index + 2] = srcData[srcPos];
-                        byteArray[index + 1] = srcData[srcPos + 1];
                         byteArray[index] = srcData[srcPos + 2];
+                        byteArray[index + 1] = srcData[srcPos + 1];
+                        byteArray[index + 2] = srcData[srcPos];
                         byteArray[index + 3] = srcData[srcPos + 3];
                         index += 4;
                     }
@@ -60806,12 +60863,12 @@ var BABYLON;
                 var byteArray = new Uint8Array(dataLength);
                 var srcData = new Uint8Array(arrayBuffer);
                 var index = 0;
-                for (var y = height - 1; y >= 0; y--) {
+                for (var y = 0; y < height; y++) {
                     for (var x = 0; x < width; x++) {
                         var srcPos = dataOffset + (x + y * width) * 3;
-                        byteArray[index + 2] = srcData[srcPos];
-                        byteArray[index + 1] = srcData[srcPos + 1];
                         byteArray[index] = srcData[srcPos + 2];
+                        byteArray[index + 1] = srcData[srcPos + 1];
+                        byteArray[index + 2] = srcData[srcPos];
                         index += 3;
                     }
                 }
@@ -60821,7 +60878,7 @@ var BABYLON;
                 var byteArray = new Uint8Array(dataLength);
                 var srcData = new Uint8Array(arrayBuffer);
                 var index = 0;
-                for (var y = height - 1; y >= 0; y--) {
+                for (var y = 0; y < height; y++) {
                     for (var x = 0; x < width; x++) {
                         var srcPos = dataOffset + (x + y * width);
                         byteArray[index] = srcData[srcPos];
@@ -60830,8 +60887,10 @@ var BABYLON;
                 }
                 return byteArray;
             };
-            DDSTools.UploadDDSLevels = function (gl, ext, arrayBuffer, info, loadMipmaps, faces) {
-                var header = new Int32Array(arrayBuffer, 0, headerLengthInt), fourCC, blockBytes, internalFormat, width, height, dataLength, dataOffset, byteArray, mipmapCount, i;
+            DDSTools.UploadDDSLevels = function (engine, arrayBuffer, info, loadMipmaps, faces) {
+                var gl = engine._gl;
+                var ext = engine.getCaps().s3tc;
+                var header = new Int32Array(arrayBuffer, 0, headerLengthInt), fourCC, blockBytes, internalFormat, format, width, height, dataLength, dataOffset, byteArray, mipmapCount, i;
                 if (header[off_magic] != DDS_MAGIC) {
                     BABYLON.Tools.Error("Invalid magic number in DDS header");
                     return;
@@ -60840,6 +60899,13 @@ var BABYLON;
                     BABYLON.Tools.Error("Unsupported format, must contain a FourCC, RGB or LUMINANCE code");
                     return;
                 }
+                if (info.isCompressed && !ext) {
+                    BABYLON.Tools.Error("Compressed textures are not supported on this platform.");
+                    return;
+                }
+                var bpp = header[off_RGBbpp];
+                dataOffset = header[off_size] + 4;
+                var computeFormats = false;
                 if (info.isFourCC) {
                     fourCC = header[off_pfFourCC];
                     switch (fourCC) {
@@ -60855,23 +60921,49 @@ var BABYLON;
                             blockBytes = 16;
                             internalFormat = ext.COMPRESSED_RGBA_S3TC_DXT5_EXT;
                             break;
+                        case FOURCC_D3DFMT_R16G16B16A16F:
+                            computeFormats = true;
+                            break;
+                        case FOURCC_D3DFMT_R32G32B32A32F:
+                            computeFormats = true;
+                            break;
+                        case FOURCC_DX10:
+                            // There is an additionnal header so dataOffset need to be changed
+                            dataOffset += 5 * 4; // 5 uints
+                            if (info.dxgiFormat === DXGI_FORMAT_R16G16B16A16_FLOAT) {
+                                computeFormats = true;
+                                break;
+                            }
                         default:
                             console.error("Unsupported FourCC code:", Int32ToFourCC(fourCC));
                             return;
                     }
                 }
+                if (computeFormats) {
+                    format = engine._getWebGLTextureType(info.textureType);
+                    internalFormat = engine._getRGBABufferInternalSizedFormat(info.textureType);
+                }
                 mipmapCount = 1;
                 if (header[off_flags] & DDSD_MIPMAPCOUNT && loadMipmaps !== false) {
                     mipmapCount = Math.max(1, header[off_mipmapCount]);
                 }
-                var bpp = header[off_RGBbpp];
                 for (var face = 0; face < faces; face++) {
                     var sampler = faces === 1 ? gl.TEXTURE_2D : (gl.TEXTURE_CUBE_MAP_POSITIVE_X + face);
                     width = header[off_width];
                     height = header[off_height];
-                    dataOffset = header[off_size] + 4;
                     for (i = 0; i < mipmapCount; ++i) {
-                        if (info.isRGB) {
+                        if (!info.isCompressed && info.isFourCC) {
+                            dataLength = width * height * 4;
+                            var floatArray;
+                            if (bpp === 128) {
+                                floatArray = DDSTools.GetFloatRGBAArrayBuffer(width, height, dataOffset, dataLength, arrayBuffer);
+                            }
+                            else {
+                                floatArray = DDSTools.GetHalfFloatRGBAArrayBuffer(width, height, dataOffset, dataLength, arrayBuffer);
+                            }
+                            gl.texImage2D(sampler, i, internalFormat, width, height, 0, gl.RGBA, format, floatArray);
+                        }
+                        else if (info.isRGB) {
                             if (bpp === 24) {
                                 dataLength = width * height * 3;
                                 byteArray = DDSTools.GetRGBArrayBuffer(width, height, dataOffset, dataLength, arrayBuffer);
@@ -60896,7 +60988,7 @@ var BABYLON;
                             byteArray = new Uint8Array(arrayBuffer, dataOffset, dataLength);
                             gl.compressedTexImage2D(sampler, i, internalFormat, width, height, 0, byteArray);
                         }
-                        dataOffset += dataLength;
+                        dataOffset += width * height * (bpp / 8);
                         width *= 0.5;
                         height *= 0.5;
                         width = Math.max(1.0, width);

文件差异内容过多而无法显示
+ 6505 - 6497
dist/preview release/babylon.module.d.ts


文件差异内容过多而无法显示
+ 39 - 38
dist/preview release/babylon.worker.js


文件差异内容过多而无法显示
+ 11348 - 11340
dist/preview release/customConfigurations/minimalViewer/babylon.d.ts


文件差异内容过多而无法显示
+ 22 - 22
dist/preview release/customConfigurations/minimalViewer/babylon.js


+ 127 - 35
dist/preview release/customConfigurations/minimalViewer/babylon.max.js

@@ -7343,6 +7343,10 @@ var BABYLON;
             if (!this._glRenderer) {
                 this._glRenderer = "Unknown renderer";
             }
+            // Constants
+            this._gl.HALF_FLOAT_OES = 0x8D61; // Half floating-point type (16-bit).
+            this._gl.RGBA16F = 0x881A; // RGBA 16-bit floating-point color-renderable internal sized format.
+            this._gl.RGBA32F = 0x8814; // RGBA 32-bit floating-point color-renderable internal sized format.            
             // Extensions
             this._caps.standardDerivatives = this._webGLVersion > 1 || (this._gl.getExtension('OES_standard_derivatives') !== null);
             this._caps.astc = this._gl.getExtension('WEBGL_compressed_texture_astc') || this._gl.getExtension('WEBKIT_WEBGL_compressed_texture_astc');
@@ -7365,7 +7369,7 @@ var BABYLON;
             this._caps.textureHalfFloat = this._webGLVersion > 1 || this._gl.getExtension('OES_texture_half_float');
             this._caps.textureHalfFloatLinearFiltering = this._webGLVersion > 1 || (this._caps.textureHalfFloat && this._gl.getExtension('OES_texture_half_float_linear'));
             if (this._webGLVersion > 1) {
-                Engine.HALF_FLOAT_OES = 0x140B;
+                this._gl.HALF_FLOAT_OES = 0x140B;
             }
             this._caps.textureHalfFloatRender = this._caps.textureHalfFloat && this._canRenderToHalfFloatFramebuffer();
             this._caps.textureLOD = this._webGLVersion > 1 || this._gl.getExtension('EXT_shader_texture_lod');
@@ -9182,7 +9186,7 @@ var BABYLON;
                         var info = BABYLON.Internals.DDSTools.GetDDSInfo(data);
                         var loadMipmap = (info.isRGB || info.isLuminance || info.mipmapCount > 1) && !noMipmap && ((info.width >> (info.mipmapCount - 1)) === 1);
                         prepareWebGLTexture(texture, _this._gl, scene, info.width, info.height, invertY, !loadMipmap, info.isFourCC, function () {
-                            BABYLON.Internals.DDSTools.UploadDDSLevels(_this._gl, _this.getCaps().s3tc, data, info, loadMipmap, 1);
+                            BABYLON.Internals.DDSTools.UploadDDSLevels(_this, data, info, loadMipmap, 1);
                         }, samplingMode);
                     };
                 }
@@ -9705,6 +9709,7 @@ var BABYLON;
             texture.references = 1;
             texture.onLoadedCallbacks = [];
             var isKTX = false;
+            var isDDS = false;
             var lastDot = rootUrl.lastIndexOf('.');
             var extension = rootUrl.substring(lastDot).toLowerCase();
             if (this._textureFormatInUse) {
@@ -9712,9 +9717,8 @@ var BABYLON;
                 rootUrl = rootUrl.substring(0, lastDot) + this._textureFormatInUse;
                 isKTX = true;
             }
-            var isDDS = this.getCaps().s3tc && (extension === ".dds");
-            if (isDDS) {
-                BABYLON.Tools.Warn("DDS files deprecated since 3.0, use KTX files");
+            else {
+                isDDS = (extension === ".dds");
             }
             if (isKTX) {
                 BABYLON.Tools.LoadFile(rootUrl, function (data) {
@@ -9739,8 +9743,10 @@ var BABYLON;
                     var info = BABYLON.Internals.DDSTools.GetDDSInfo(data);
                     var loadMipmap = (info.isRGB || info.isLuminance || info.mipmapCount > 1) && !noMipmap;
                     _this._bindTextureDirectly(gl.TEXTURE_CUBE_MAP, texture);
-                    gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, 1);
-                    BABYLON.Internals.DDSTools.UploadDDSLevels(_this._gl, _this.getCaps().s3tc, data, info, loadMipmap, 6);
+                    if (info.isCompressed) {
+                        gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, 1);
+                    }
+                    BABYLON.Internals.DDSTools.UploadDDSLevels(_this, data, info, loadMipmap, 6);
                     if (!noMipmap && !info.isFourCC && info.mipmapCount === 1) {
                         gl.generateMipmap(gl.TEXTURE_CUBE_MAP);
                     }
@@ -9753,6 +9759,7 @@ var BABYLON;
                     texture._width = info.width;
                     texture._height = info.height;
                     texture.isReady = true;
+                    texture.type = info.textureType;
                 }, null, null, true, onError);
             }
             else {
@@ -9882,7 +9889,7 @@ var BABYLON;
                 gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
                 gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
             }
-            else if (textureType === Engine.HALF_FLOAT_OES && !this._caps.textureHalfFloatLinearFiltering) {
+            else if (textureType === this._gl.HALF_FLOAT_OES && !this._caps.textureHalfFloatLinearFiltering) {
                 gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
                 gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
             }
@@ -10402,21 +10409,22 @@ var BABYLON;
                 this.fps = 1000.0 / (sum / (length - 1));
             }
         };
-        Engine.prototype._readTexturePixels = function (texture, width, height, faceIndex) {
+        Engine.prototype._readTexturePixels = function (texture, width, height, faceIndex, lodIndex) {
             if (faceIndex === void 0) { faceIndex = -1; }
+            if (lodIndex === void 0) { lodIndex = 0; }
             var gl = this._gl;
             if (!this._dummyFramebuffer) {
                 this._dummyFramebuffer = gl.createFramebuffer();
             }
             gl.bindFramebuffer(gl.FRAMEBUFFER, this._dummyFramebuffer);
             if (faceIndex > -1) {
-                gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_CUBE_MAP_POSITIVE_X + faceIndex, texture, 0);
+                gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_CUBE_MAP_POSITIVE_X + faceIndex, texture, lodIndex);
             }
             else {
-                gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0);
+                gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, lodIndex);
             }
             var readFormat = gl.RGBA;
-            var readType = gl.UNSIGNED_BYTE;
+            var readType = (texture.type !== undefined) ? texture.type : gl.UNSIGNED_BYTE;
             var buffer = new Uint8Array(4 * width * height);
             gl.readPixels(0, 0, width, height, readFormat, readType, buffer);
             gl.bindFramebuffer(gl.FRAMEBUFFER, null);
@@ -10480,7 +10488,7 @@ var BABYLON;
             }
             else if (type === Engine.TEXTURETYPE_HALF_FLOAT) {
                 // Add Half Float Constant.
-                return Engine.HALF_FLOAT_OES;
+                return this._gl.HALF_FLOAT_OES;
             }
             return this._gl.UNSIGNED_BYTE;
         };
@@ -10490,10 +10498,10 @@ var BABYLON;
                 return this._gl.RGBA;
             }
             if (type === Engine.TEXTURETYPE_FLOAT) {
-                return Engine.RGBA32F;
+                return this._gl.RGBA32F;
             }
             else if (type === Engine.TEXTURETYPE_HALF_FLOAT) {
-                return Engine.RGBA16F;
+                return this._gl.RGBA16F;
             }
             return this._gl.RGBA;
         };
@@ -10549,9 +10557,6 @@ var BABYLON;
     Engine._GREATER = 0x0204; //	Passed to depthFunction or stencilFunction to specify depth or stencil tests will pass if the new depth value is greater than the stored value.
     Engine._GEQUAL = 0x0206; //	Passed to depthFunction or stencilFunction to specify depth or stencil tests will pass if the new depth value is greater than or equal to the stored value.
     Engine._NOTEQUAL = 0x0205; //  Passed to depthFunction or stencilFunction to specify depth or stencil tests will pass if the new depth value is not equal to the stored value.
-    Engine.HALF_FLOAT_OES = 0x8D61; // Half floating-point type (16-bit).
-    Engine.RGBA16F = 0x881A; // RGBA 16-bit floating-point color-renderable internal sized format.
-    Engine.RGBA32F = 0x8814; // RGBA 32-bit floating-point color-renderable internal sized format.
     // Stencil Actions Constants.
     Engine._KEEP = 0x1E00;
     Engine._REPLACE = 0x1E01;
@@ -19113,17 +19118,28 @@ var BABYLON;
         BaseTexture.prototype.clone = function () {
             return null;
         };
-        BaseTexture.prototype.readPixels = function (faceIndex) {
+        Object.defineProperty(BaseTexture.prototype, "textureType", {
+            get: function () {
+                if (!this._texture) {
+                    return BABYLON.Engine.TEXTURETYPE_UNSIGNED_INT;
+                }
+                return (this._texture.type !== undefined) ? this._texture.type : BABYLON.Engine.TEXTURETYPE_UNSIGNED_INT;
+            },
+            enumerable: true,
+            configurable: true
+        });
+        BaseTexture.prototype.readPixels = function (faceIndex, lodIndex) {
             if (faceIndex === void 0) { faceIndex = 0; }
+            if (lodIndex === void 0) { lodIndex = 0; }
             if (!this._texture) {
                 return null;
             }
             var size = this.getSize();
             var engine = this.getScene().getEngine();
             if (this._texture.isCube) {
-                return engine._readTexturePixels(this._texture, size.width, size.height, faceIndex);
+                return engine._readTexturePixels(this._texture, size.width, size.height, faceIndex, lodIndex);
             }
-            return engine._readTexturePixels(this._texture, size.width, size.height);
+            return engine._readTexturePixels(this._texture, size.width, size.height, -1, lodIndex);
         };
         BaseTexture.prototype.releaseInternalTexture = function () {
             if (this._texture) {
@@ -32636,6 +32652,10 @@ var BABYLON;
         var FOURCC_DXT1 = FourCCToInt32("DXT1");
         var FOURCC_DXT3 = FourCCToInt32("DXT3");
         var FOURCC_DXT5 = FourCCToInt32("DXT5");
+        var FOURCC_DX10 = FourCCToInt32("DX10");
+        var FOURCC_D3DFMT_R16G16B16A16F = 113;
+        var FOURCC_D3DFMT_R32G32B32A32F = 116;
+        var DXGI_FORMAT_R16G16B16A16_FLOAT = 10;
         var headerLengthInt = 31; // The header length in 32 bit ints
         // Offsets into the header array
         var off_magic = 0;
@@ -32653,16 +32673,36 @@ var BABYLON;
         var off_AMask = 26;
         var off_caps1 = 27;
         var off_caps2 = 28;
+        var off_caps3 = 29;
+        var off_caps4 = 30;
+        var off_dxgiFormat = 32;
         ;
         var DDSTools = (function () {
             function DDSTools() {
             }
             DDSTools.GetDDSInfo = function (arrayBuffer) {
                 var header = new Int32Array(arrayBuffer, 0, headerLengthInt);
+                var extendedHeader = new Int32Array(arrayBuffer, 0, headerLengthInt + 4);
                 var mipmapCount = 1;
                 if (header[off_flags] & DDSD_MIPMAPCOUNT) {
                     mipmapCount = Math.max(1, header[off_mipmapCount]);
                 }
+                var fourCC = header[off_pfFourCC];
+                var dxgiFormat = (fourCC === FOURCC_DX10) ? extendedHeader[off_dxgiFormat] : 0;
+                var textureType = BABYLON.Engine.TEXTURETYPE_UNSIGNED_INT;
+                switch (fourCC) {
+                    case FOURCC_D3DFMT_R16G16B16A16F:
+                        textureType = BABYLON.Engine.TEXTURETYPE_HALF_FLOAT;
+                        break;
+                    case FOURCC_D3DFMT_R32G32B32A32F:
+                        textureType = BABYLON.Engine.TEXTURETYPE_FLOAT;
+                        break;
+                    case FOURCC_DX10:
+                        if (dxgiFormat === DXGI_FORMAT_R16G16B16A16_FLOAT) {
+                            textureType = BABYLON.Engine.TEXTURETYPE_HALF_FLOAT;
+                            break;
+                        }
+                }
                 return {
                     width: header[off_width],
                     height: header[off_height],
@@ -32670,19 +32710,28 @@ var BABYLON;
                     isFourCC: (header[off_pfFlags] & DDPF_FOURCC) === DDPF_FOURCC,
                     isRGB: (header[off_pfFlags] & DDPF_RGB) === DDPF_RGB,
                     isLuminance: (header[off_pfFlags] & DDPF_LUMINANCE) === DDPF_LUMINANCE,
-                    isCube: (header[off_caps2] & DDSCAPS2_CUBEMAP) === DDSCAPS2_CUBEMAP
+                    isCube: (header[off_caps2] & DDSCAPS2_CUBEMAP) === DDSCAPS2_CUBEMAP,
+                    isCompressed: (fourCC === FOURCC_DXT1 || fourCC === FOURCC_DXT3 || FOURCC_DXT1 === FOURCC_DXT5),
+                    dxgiFormat: dxgiFormat,
+                    textureType: textureType
                 };
             };
+            DDSTools.GetHalfFloatRGBAArrayBuffer = function (width, height, dataOffset, dataLength, arrayBuffer) {
+                return new Uint16Array(arrayBuffer, dataOffset, dataLength);
+            };
+            DDSTools.GetFloatRGBAArrayBuffer = function (width, height, dataOffset, dataLength, arrayBuffer) {
+                return new Float32Array(arrayBuffer, dataOffset, dataLength);
+            };
             DDSTools.GetRGBAArrayBuffer = function (width, height, dataOffset, dataLength, arrayBuffer) {
                 var byteArray = new Uint8Array(dataLength);
                 var srcData = new Uint8Array(arrayBuffer);
                 var index = 0;
-                for (var y = height - 1; y >= 0; y--) {
+                for (var y = 0; y < height; y++) {
                     for (var x = 0; x < width; x++) {
                         var srcPos = dataOffset + (x + y * width) * 4;
-                        byteArray[index + 2] = srcData[srcPos];
-                        byteArray[index + 1] = srcData[srcPos + 1];
                         byteArray[index] = srcData[srcPos + 2];
+                        byteArray[index + 1] = srcData[srcPos + 1];
+                        byteArray[index + 2] = srcData[srcPos];
                         byteArray[index + 3] = srcData[srcPos + 3];
                         index += 4;
                     }
@@ -32693,12 +32742,12 @@ var BABYLON;
                 var byteArray = new Uint8Array(dataLength);
                 var srcData = new Uint8Array(arrayBuffer);
                 var index = 0;
-                for (var y = height - 1; y >= 0; y--) {
+                for (var y = 0; y < height; y++) {
                     for (var x = 0; x < width; x++) {
                         var srcPos = dataOffset + (x + y * width) * 3;
-                        byteArray[index + 2] = srcData[srcPos];
-                        byteArray[index + 1] = srcData[srcPos + 1];
                         byteArray[index] = srcData[srcPos + 2];
+                        byteArray[index + 1] = srcData[srcPos + 1];
+                        byteArray[index + 2] = srcData[srcPos];
                         index += 3;
                     }
                 }
@@ -32708,7 +32757,7 @@ var BABYLON;
                 var byteArray = new Uint8Array(dataLength);
                 var srcData = new Uint8Array(arrayBuffer);
                 var index = 0;
-                for (var y = height - 1; y >= 0; y--) {
+                for (var y = 0; y < height; y++) {
                     for (var x = 0; x < width; x++) {
                         var srcPos = dataOffset + (x + y * width);
                         byteArray[index] = srcData[srcPos];
@@ -32717,8 +32766,10 @@ var BABYLON;
                 }
                 return byteArray;
             };
-            DDSTools.UploadDDSLevels = function (gl, ext, arrayBuffer, info, loadMipmaps, faces) {
-                var header = new Int32Array(arrayBuffer, 0, headerLengthInt), fourCC, blockBytes, internalFormat, width, height, dataLength, dataOffset, byteArray, mipmapCount, i;
+            DDSTools.UploadDDSLevels = function (engine, arrayBuffer, info, loadMipmaps, faces) {
+                var gl = engine._gl;
+                var ext = engine.getCaps().s3tc;
+                var header = new Int32Array(arrayBuffer, 0, headerLengthInt), fourCC, blockBytes, internalFormat, format, width, height, dataLength, dataOffset, byteArray, mipmapCount, i;
                 if (header[off_magic] != DDS_MAGIC) {
                     BABYLON.Tools.Error("Invalid magic number in DDS header");
                     return;
@@ -32727,6 +32778,13 @@ var BABYLON;
                     BABYLON.Tools.Error("Unsupported format, must contain a FourCC, RGB or LUMINANCE code");
                     return;
                 }
+                if (info.isCompressed && !ext) {
+                    BABYLON.Tools.Error("Compressed textures are not supported on this platform.");
+                    return;
+                }
+                var bpp = header[off_RGBbpp];
+                dataOffset = header[off_size] + 4;
+                var computeFormats = false;
                 if (info.isFourCC) {
                     fourCC = header[off_pfFourCC];
                     switch (fourCC) {
@@ -32742,23 +32800,49 @@ var BABYLON;
                             blockBytes = 16;
                             internalFormat = ext.COMPRESSED_RGBA_S3TC_DXT5_EXT;
                             break;
+                        case FOURCC_D3DFMT_R16G16B16A16F:
+                            computeFormats = true;
+                            break;
+                        case FOURCC_D3DFMT_R32G32B32A32F:
+                            computeFormats = true;
+                            break;
+                        case FOURCC_DX10:
+                            // There is an additionnal header so dataOffset need to be changed
+                            dataOffset += 5 * 4; // 5 uints
+                            if (info.dxgiFormat === DXGI_FORMAT_R16G16B16A16_FLOAT) {
+                                computeFormats = true;
+                                break;
+                            }
                         default:
                             console.error("Unsupported FourCC code:", Int32ToFourCC(fourCC));
                             return;
                     }
                 }
+                if (computeFormats) {
+                    format = engine._getWebGLTextureType(info.textureType);
+                    internalFormat = engine._getRGBABufferInternalSizedFormat(info.textureType);
+                }
                 mipmapCount = 1;
                 if (header[off_flags] & DDSD_MIPMAPCOUNT && loadMipmaps !== false) {
                     mipmapCount = Math.max(1, header[off_mipmapCount]);
                 }
-                var bpp = header[off_RGBbpp];
                 for (var face = 0; face < faces; face++) {
                     var sampler = faces === 1 ? gl.TEXTURE_2D : (gl.TEXTURE_CUBE_MAP_POSITIVE_X + face);
                     width = header[off_width];
                     height = header[off_height];
-                    dataOffset = header[off_size] + 4;
                     for (i = 0; i < mipmapCount; ++i) {
-                        if (info.isRGB) {
+                        if (!info.isCompressed && info.isFourCC) {
+                            dataLength = width * height * 4;
+                            var floatArray;
+                            if (bpp === 128) {
+                                floatArray = DDSTools.GetFloatRGBAArrayBuffer(width, height, dataOffset, dataLength, arrayBuffer);
+                            }
+                            else {
+                                floatArray = DDSTools.GetHalfFloatRGBAArrayBuffer(width, height, dataOffset, dataLength, arrayBuffer);
+                            }
+                            gl.texImage2D(sampler, i, internalFormat, width, height, 0, gl.RGBA, format, floatArray);
+                        }
+                        else if (info.isRGB) {
                             if (bpp === 24) {
                                 dataLength = width * height * 3;
                                 byteArray = DDSTools.GetRGBArrayBuffer(width, height, dataOffset, dataLength, arrayBuffer);
@@ -32783,7 +32867,7 @@ var BABYLON;
                             byteArray = new Uint8Array(arrayBuffer, dataOffset, dataLength);
                             gl.compressedTexImage2D(sampler, i, internalFormat, width, height, 0, byteArray);
                         }
-                        dataOffset += dataLength;
+                        dataOffset += width * height * (bpp / 8);
                         width *= 0.5;
                         height *= 0.5;
                         width = Math.max(1.0, width);
@@ -36651,6 +36735,10 @@ var BABYLON;
             }
             return activeTextures;
         };
+        PBRMetallicRoughnessMaterial.prototype.clone = function (name) {
+            var _this = this;
+            return BABYLON.SerializationHelper.Clone(function () { return new PBRMetallicRoughnessMaterial(name, _this.getScene()); }, this);
+        };
         /**
          * Serialize the material to a parsable JSON object.
          */
@@ -36738,6 +36826,10 @@ var BABYLON;
             }
             return activeTextures;
         };
+        PBRSpecularGlossinessMaterial.prototype.clone = function (name) {
+            var _this = this;
+            return BABYLON.SerializationHelper.Clone(function () { return new PBRSpecularGlossinessMaterial(name, _this.getScene()); }, this);
+        };
         /**
          * Serialize the material to a parsable JSON object.
          */

文件差异内容过多而无法显示
+ 11348 - 11340
dist/preview release/customConfigurations/minimalViewer/babylon.module.d.ts


+ 14 - 14
dist/preview release/inspector/babylon.inspector.bundle.js

@@ -43,15 +43,15 @@ var INSPECTOR =
 /************************************************************************/
 /******/ ([
 /* 0 */
-/***/ function(module, exports, __webpack_require__) {
+/***/ (function(module, exports, __webpack_require__) {
 
 	__webpack_require__(1);
 	module.exports = __webpack_require__(5);
 
 
-/***/ },
+/***/ }),
 /* 1 */
-/***/ function(module, exports, __webpack_require__) {
+/***/ (function(module, exports, __webpack_require__) {
 
 	// style-loader: Adds some css to the DOM by adding a <style> tag
 
@@ -75,9 +75,9 @@ var INSPECTOR =
 		module.hot.dispose(function() { update(); });
 	}
 
-/***/ },
+/***/ }),
 /* 2 */
-/***/ function(module, exports, __webpack_require__) {
+/***/ (function(module, exports, __webpack_require__) {
 
 	exports = module.exports = __webpack_require__(3)();
 	// imports
@@ -90,9 +90,9 @@ var INSPECTOR =
 	// exports
 
 
-/***/ },
+/***/ }),
 /* 3 */
-/***/ function(module, exports) {
+/***/ (function(module, exports) {
 
 	/*
 		MIT License http://www.opensource.org/licenses/mit-license.php
@@ -146,9 +146,9 @@ var INSPECTOR =
 	};
 
 
-/***/ },
+/***/ }),
 /* 4 */
-/***/ function(module, exports, __webpack_require__) {
+/***/ (function(module, exports, __webpack_require__) {
 
 	/*
 		MIT License http://www.opensource.org/licenses/mit-license.php
@@ -398,9 +398,9 @@ var INSPECTOR =
 	}
 
 
-/***/ },
+/***/ }),
 /* 5 */
-/***/ function(module, exports, __webpack_require__) {
+/***/ (function(module, exports, __webpack_require__) {
 
 	/*** IMPORTS FROM imports-loader ***/
 	var Split = __webpack_require__(6);
@@ -413,9 +413,9 @@ var INSPECTOR =
 	module.exports = INSPECTOR;
 
 
-/***/ },
+/***/ }),
 /* 6 */
-/***/ function(module, exports, __webpack_require__) {
+/***/ (function(module, exports, __webpack_require__) {
 
 	// The programming goals of Split.js are to deliver readable, understandable and
 	// maintainable code, while at the same time manually optimizing for tiny minified file size,
@@ -987,5 +987,5 @@ var INSPECTOR =
 	}).call(window);
 
 
-/***/ }
+/***/ })
 /******/ ]);

+ 11 - 3
src/Materials/Textures/babylon.baseTexture.ts

@@ -198,7 +198,15 @@
             return null;
         }
 
-        public readPixels(faceIndex = 0): Uint8Array {
+        public get textureType(): number {
+            if (!this._texture) {
+                return Engine.TEXTURETYPE_UNSIGNED_INT;
+            }
+
+            return (this._texture.type !== undefined) ? this._texture.type : Engine.TEXTURETYPE_UNSIGNED_INT;
+        }
+
+        public readPixels(faceIndex = 0, lodIndex = 0): ArrayBufferView {
             if (!this._texture) {
                 return null;
             }
@@ -207,10 +215,10 @@
             var engine = this.getScene().getEngine();
 
             if (this._texture.isCube) {
-                return engine._readTexturePixels(this._texture, size.width, size.height, faceIndex);
+                return engine._readTexturePixels(this._texture, size.width, size.height, faceIndex, lodIndex);
             }
 
-            return engine._readTexturePixels(this._texture, size.width, size.height);
+            return engine._readTexturePixels(this._texture, size.width, size.height, -1, lodIndex);
         }
 
         public releaseInternalTexture(): void {

+ 96 - 16
src/Tools/babylon.dds.ts

@@ -52,6 +52,11 @@
     var FOURCC_DXT1 = FourCCToInt32("DXT1");
     var FOURCC_DXT3 = FourCCToInt32("DXT3");
     var FOURCC_DXT5 = FourCCToInt32("DXT5");
+    var FOURCC_DX10 = FourCCToInt32("DX10");
+    var FOURCC_D3DFMT_R16G16B16A16F = 113;
+    var FOURCC_D3DFMT_R32G32B32A32F = 116;
+
+    var DXGI_FORMAT_R16G16B16A16_FLOAT = 10;
 
     var headerLengthInt = 31; // The header length in 32 bit ints
 
@@ -74,6 +79,9 @@
     var off_AMask = 26;
     var off_caps1 = 27;
     var off_caps2 = 28;
+    var off_caps3 = 29;
+    var off_caps4 = 30;
+    var off_dxgiFormat = 32
 
     export interface DDSInfo {
         width: number;
@@ -82,18 +90,40 @@
         isFourCC: boolean;
         isRGB: boolean;
         isLuminance: boolean;
-        isCube: boolean
+        isCube: boolean;
+        isCompressed: boolean;
+        dxgiFormat: number;
+        textureType: number;
     };
 
     export class DDSTools {
         public static GetDDSInfo(arrayBuffer: any): DDSInfo {
             var header = new Int32Array(arrayBuffer, 0, headerLengthInt);
+            var extendedHeader = new Int32Array(arrayBuffer, 0, headerLengthInt + 4);
 
             var mipmapCount = 1;
             if (header[off_flags] & DDSD_MIPMAPCOUNT) {
                 mipmapCount = Math.max(1, header[off_mipmapCount]);
             }
 
+            var fourCC = header[off_pfFourCC];
+            var dxgiFormat = (fourCC === FOURCC_DX10) ? extendedHeader[off_dxgiFormat] : 0;
+            var textureType = Engine.TEXTURETYPE_UNSIGNED_INT;
+
+            switch (fourCC) {
+                case FOURCC_D3DFMT_R16G16B16A16F:  
+                    textureType = Engine.TEXTURETYPE_HALF_FLOAT;                           
+                    break;
+                case FOURCC_D3DFMT_R32G32B32A32F:
+                    textureType = Engine.TEXTURETYPE_FLOAT;
+                    break;                    
+                case FOURCC_DX10:
+                    if (dxgiFormat === DXGI_FORMAT_R16G16B16A16_FLOAT) {
+                        textureType = Engine.TEXTURETYPE_HALF_FLOAT;
+                        break;
+                    }
+            }
+  
             return {
                 width: header[off_width],
                 height: header[off_height],
@@ -101,20 +131,31 @@
                 isFourCC: (header[off_pfFlags] & DDPF_FOURCC) === DDPF_FOURCC,
                 isRGB: (header[off_pfFlags] & DDPF_RGB) === DDPF_RGB,
                 isLuminance: (header[off_pfFlags] & DDPF_LUMINANCE) === DDPF_LUMINANCE,
-                isCube: (header[off_caps2] & DDSCAPS2_CUBEMAP) === DDSCAPS2_CUBEMAP
+                isCube: (header[off_caps2] & DDSCAPS2_CUBEMAP) === DDSCAPS2_CUBEMAP,
+                isCompressed: (fourCC === FOURCC_DXT1 || fourCC === FOURCC_DXT3 || FOURCC_DXT1 === FOURCC_DXT5),
+                dxgiFormat: dxgiFormat,
+                textureType: textureType
             };
         }
+    
+        private static GetHalfFloatRGBAArrayBuffer(width: number, height: number, dataOffset: number, dataLength: number, arrayBuffer: ArrayBuffer): Uint16Array {   
+            return new Uint16Array(arrayBuffer, dataOffset, dataLength);
+        }           
+
+        private static GetFloatRGBAArrayBuffer(width: number, height: number, dataOffset: number, dataLength: number, arrayBuffer: ArrayBuffer): Float32Array {
+            return new Float32Array(arrayBuffer, dataOffset, dataLength);
+        }        
 
         private static GetRGBAArrayBuffer(width: number, height: number, dataOffset: number, dataLength: number, arrayBuffer: ArrayBuffer): Uint8Array {
             var byteArray = new Uint8Array(dataLength);
             var srcData = new Uint8Array(arrayBuffer);
             var index = 0;
-            for (var y = height - 1; y >= 0; y--) {
+            for (var y = 0; y < height; y++) {
                 for (var x = 0; x < width; x++) {
                     var srcPos = dataOffset + (x + y * width) * 4;
-                    byteArray[index + 2] = srcData[srcPos];
-                    byteArray[index + 1] = srcData[srcPos + 1];
                     byteArray[index] = srcData[srcPos + 2];
+                    byteArray[index + 1] = srcData[srcPos + 1];
+                    byteArray[index + 2] = srcData[srcPos];
                     byteArray[index + 3] = srcData[srcPos + 3];
                     index += 4;
                 }
@@ -127,12 +168,12 @@
             var byteArray = new Uint8Array(dataLength);
             var srcData = new Uint8Array(arrayBuffer);
             var index = 0;
-            for (var y = height - 1; y >= 0; y--) {
+            for (var y = 0; y < height; y++) {
                 for (var x = 0; x < width; x++) {
                     var srcPos = dataOffset + (x + y * width) * 3;
-                    byteArray[index + 2] = srcData[srcPos];
-                    byteArray[index + 1] = srcData[srcPos + 1];
                     byteArray[index] = srcData[srcPos + 2];
+                    byteArray[index + 1] = srcData[srcPos + 1];
+                    byteArray[index + 2] = srcData[srcPos];
                     index += 3;
                 }
             }
@@ -144,7 +185,7 @@
             var byteArray = new Uint8Array(dataLength);
             var srcData = new Uint8Array(arrayBuffer);
             var index = 0;
-            for (var y = height - 1; y >= 0; y--) {
+            for (var y = 0; y < height; y++) {
                 for (var x = 0; x < width; x++) {
                     var srcPos = dataOffset + (x + y * width);
                     byteArray[index] = srcData[srcPos];
@@ -155,9 +196,12 @@
             return byteArray;
         }
 
-        public static UploadDDSLevels(gl: WebGLRenderingContext, ext: any, arrayBuffer: any, info: DDSInfo, loadMipmaps: boolean, faces: number): void {
+        public static UploadDDSLevels(engine: Engine, arrayBuffer: any, info: DDSInfo, loadMipmaps: boolean, faces: number): void {
+            var gl = engine._gl;
+            var ext = engine.getCaps().s3tc;
+
             var header = new Int32Array(arrayBuffer, 0, headerLengthInt),
-                fourCC, blockBytes, internalFormat,
+                fourCC, blockBytes, internalFormat, format,
                 width, height, dataLength, dataOffset,
                 byteArray, mipmapCount, i;
 
@@ -171,6 +215,16 @@
                 return;
             }
 
+            if (info.isCompressed && !ext) {
+                Tools.Error("Compressed textures are not supported on this platform.");
+                return;
+            }
+
+            var bpp = header[off_RGBbpp];
+            dataOffset = header[off_size] + 4;
+
+            let computeFormats = false;
+
             if (info.isFourCC) {
                 fourCC = header[off_pfFourCC];
                 switch (fourCC) {
@@ -186,28 +240,54 @@
                     blockBytes = 16;
                     internalFormat = ext.COMPRESSED_RGBA_S3TC_DXT5_EXT;
                     break;
+                case FOURCC_D3DFMT_R16G16B16A16F:  
+                    computeFormats = true;
+                    break;
+                case FOURCC_D3DFMT_R32G32B32A32F:
+                    computeFormats = true;
+                    break;                    
+                case FOURCC_DX10:
+                    // There is an additionnal header so dataOffset need to be changed
+                    dataOffset += 5 * 4; // 5 uints
+
+                    if (info.dxgiFormat === DXGI_FORMAT_R16G16B16A16_FLOAT) {
+                        computeFormats = true;
+                        break;
+                    }
                 default:
                     console.error("Unsupported FourCC code:", Int32ToFourCC(fourCC));
                     return;
                 }
             }
 
+            if (computeFormats) {
+                format = engine._getWebGLTextureType(info.textureType);    
+                internalFormat = engine._getRGBABufferInternalSizedFormat(info.textureType);
+            }
+
             mipmapCount = 1;
             if (header[off_flags] & DDSD_MIPMAPCOUNT && loadMipmaps !== false) {
                 mipmapCount = Math.max(1, header[off_mipmapCount]);
             }
             
-            var bpp = header[off_RGBbpp];
-
             for (var face = 0; face < faces; face++) {
                 var sampler = faces === 1 ? gl.TEXTURE_2D : (gl.TEXTURE_CUBE_MAP_POSITIVE_X + face);
 
                 width = header[off_width];
                 height = header[off_height];
-                dataOffset = header[off_size] + 4;
 
                 for (i = 0; i < mipmapCount; ++i) {
-                    if (info.isRGB) {
+                    if (!info.isCompressed && info.isFourCC) {
+                        dataLength = width * height * 4;
+                        var floatArray: ArrayBufferView;
+                        if (bpp === 128) {
+                            floatArray = DDSTools.GetFloatRGBAArrayBuffer(width, height, dataOffset, dataLength, arrayBuffer);
+                        } else { // 64
+                            floatArray = DDSTools.GetHalfFloatRGBAArrayBuffer(width, height, dataOffset, dataLength, arrayBuffer);
+                        }
+
+                        gl.texImage2D(sampler, i, internalFormat, width, height, 0, gl.RGBA, format, floatArray);
+                    } else if (info.isRGB) {
                         if (bpp === 24) {
                             dataLength = width * height * 3;
                             byteArray = DDSTools.GetRGBArrayBuffer(width, height, dataOffset, dataLength, arrayBuffer);
@@ -230,7 +310,7 @@
                         byteArray = new Uint8Array(arrayBuffer, dataOffset, dataLength);
                         gl.compressedTexImage2D(sampler, i, internalFormat, width, height, 0, byteArray);
                     }
-                    dataOffset += dataLength;
+                    dataOffset += width * height * (bpp / 8);
                     width *= 0.5;
                     height *= 0.5;
 

+ 25 - 22
src/babylon.engine.ts

@@ -274,10 +274,6 @@
         private static _GEQUAL = 0x0206; //	Passed to depthFunction or stencilFunction to specify depth or stencil tests will pass if the new depth value is greater than or equal to the stored value.
         private static _NOTEQUAL = 0x0205; //  Passed to depthFunction or stencilFunction to specify depth or stencil tests will pass if the new depth value is not equal to the stored value.
 
-        private static HALF_FLOAT_OES = 0x8D61; // Half floating-point type (16-bit).
-        private static RGBA16F = 0x881A; // RGBA 16-bit floating-point color-renderable internal sized format.
-        private static RGBA32F = 0x8814; // RGBA 32-bit floating-point color-renderable internal sized format.
-
         public static get NEVER(): number {
             return Engine._NEVER;
         }
@@ -722,6 +718,11 @@
                 this._glRenderer = "Unknown renderer";
             }
 
+            // Constants
+            this._gl.HALF_FLOAT_OES = 0x8D61; // Half floating-point type (16-bit).
+            this._gl.RGBA16F = 0x881A; // RGBA 16-bit floating-point color-renderable internal sized format.
+            this._gl.RGBA32F = 0x8814; // RGBA 32-bit floating-point color-renderable internal sized format.            
+
             // Extensions
             this._caps.standardDerivatives = this._webGLVersion > 1 || (this._gl.getExtension('OES_standard_derivatives') !== null);
 
@@ -749,7 +750,7 @@
             this._caps.textureHalfFloat = this._webGLVersion > 1 || this._gl.getExtension('OES_texture_half_float');
             this._caps.textureHalfFloatLinearFiltering = this._webGLVersion > 1 || (this._caps.textureHalfFloat && this._gl.getExtension('OES_texture_half_float_linear'));
             if (this._webGLVersion > 1) {
-                Engine.HALF_FLOAT_OES = 0x140B;
+                this._gl.HALF_FLOAT_OES = 0x140B;
             }
             this._caps.textureHalfFloatRender = this._caps.textureHalfFloat && this._canRenderToHalfFloatFramebuffer();
 
@@ -2465,7 +2466,7 @@
                         var loadMipmap = (info.isRGB || info.isLuminance || info.mipmapCount > 1) && !noMipmap && ((info.width >> (info.mipmapCount - 1)) === 1);
                         prepareWebGLTexture(texture, this._gl, scene, info.width, info.height, invertY, !loadMipmap, info.isFourCC, () => {
 
-                            Internals.DDSTools.UploadDDSLevels(this._gl, this.getCaps().s3tc, data, info, loadMipmap, 1);
+                            Internals.DDSTools.UploadDDSLevels(this, data, info, loadMipmap, 1);
                         }, samplingMode);
                     };
                 }
@@ -3120,16 +3121,15 @@
             texture.onLoadedCallbacks = [];
 
             var isKTX = false;
+            var isDDS = false;
             var lastDot = rootUrl.lastIndexOf('.');
             var extension = rootUrl.substring(lastDot).toLowerCase();
             if (this._textureFormatInUse) {
                 extension = this._textureFormatInUse;
                 rootUrl = rootUrl.substring(0, lastDot) + this._textureFormatInUse;
                 isKTX = true;
-            }
-            var isDDS = this.getCaps().s3tc && (extension === ".dds");
-            if (isDDS) {
-                BABYLON.Tools.Warn("DDS files deprecated since 3.0, use KTX files");
+            } else {
+                isDDS = (extension === ".dds");
             }
 
             if (isKTX) {
@@ -3163,9 +3163,11 @@
                     var loadMipmap = (info.isRGB || info.isLuminance || info.mipmapCount > 1) && !noMipmap;
 
                     this._bindTextureDirectly(gl.TEXTURE_CUBE_MAP, texture);
-                    gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, 1);
+                    if (info.isCompressed) {
+                        gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, 1);
+                    }
 
-                    Internals.DDSTools.UploadDDSLevels(this._gl, this.getCaps().s3tc, data, info, loadMipmap, 6);
+                    Internals.DDSTools.UploadDDSLevels(this, data, info, loadMipmap, 6);
 
                     if (!noMipmap && !info.isFourCC && info.mipmapCount === 1) {
                         gl.generateMipmap(gl.TEXTURE_CUBE_MAP);
@@ -3183,6 +3185,7 @@
                     texture._width = info.width;
                     texture._height = info.height;
                     texture.isReady = true;
+                    texture.type = info.textureType;
                 }, null, null, true, onError);
             } else {
                 cascadeLoad(rootUrl, scene, imgs => {
@@ -3340,7 +3343,7 @@
                 gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
                 gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
             }
-            else if (textureType === Engine.HALF_FLOAT_OES && !this._caps.textureHalfFloatLinearFiltering) {
+            else if (textureType === this._gl.HALF_FLOAT_OES && !this._caps.textureHalfFloatLinearFiltering) {
                 gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
                 gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
             }
@@ -3962,7 +3965,7 @@
             }
         }
 
-        public _readTexturePixels(texture: WebGLTexture, width: number, height: number, faceIndex = -1): Uint8Array {
+        public _readTexturePixels(texture: WebGLTexture, width: number, height: number, faceIndex = -1, lodIndex = 0): ArrayBufferView {
             let gl = this._gl;
             if (!this._dummyFramebuffer) {
                 this._dummyFramebuffer = gl.createFramebuffer();
@@ -3970,13 +3973,13 @@
             gl.bindFramebuffer(gl.FRAMEBUFFER, this._dummyFramebuffer);
 
             if (faceIndex > -1) {
-                gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_CUBE_MAP_POSITIVE_X + faceIndex, texture, 0);            
+                gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_CUBE_MAP_POSITIVE_X + faceIndex, texture, lodIndex);            
             } else {
-                gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0);
+                gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, lodIndex);
             }
 
             let readFormat = gl.RGBA;
-            let readType = gl.UNSIGNED_BYTE;
+            let readType = (texture.type !== undefined) ? texture.type : gl.UNSIGNED_BYTE;
             let buffer = new Uint8Array(4 * width * height);
             gl.readPixels(0, 0, width, height, readFormat, readType, buffer);
             
@@ -4050,28 +4053,28 @@
             return successful;
         }
 
-        private _getWebGLTextureType(type: number): number {
+        public _getWebGLTextureType(type: number): number {
             if (type === Engine.TEXTURETYPE_FLOAT) {
                 return this._gl.FLOAT;
             }
             else if (type === Engine.TEXTURETYPE_HALF_FLOAT) {
                 // Add Half Float Constant.
-                return Engine.HALF_FLOAT_OES;
+                return this._gl.HALF_FLOAT_OES;
             }
 
             return this._gl.UNSIGNED_BYTE;
         };
 
-        private _getRGBABufferInternalSizedFormat(type: number): number {
+        public _getRGBABufferInternalSizedFormat(type: number): number {
             if (this._webGLVersion === 1) {
                 return this._gl.RGBA;
             }
 
             if (type === Engine.TEXTURETYPE_FLOAT) {
-                return Engine.RGBA32F;
+                return this._gl.RGBA32F;
             }
             else if (type === Engine.TEXTURETYPE_HALF_FLOAT) {
-                return Engine.RGBA16F;
+                return this._gl.RGBA16F;
             }
 
             return this._gl.RGBA;

+ 4 - 0
src/babylon.mixins.ts

@@ -50,6 +50,10 @@ interface WebGLRenderingContext {
     DRAW_FRAMEBUFFER: number;
     UNIFORM_BUFFER: number;
 
+    HALF_FLOAT_OES: number;
+    RGBA16F: number;
+    RGBA32F: number;
+    
     /* Multiple Render Targets */
     drawBuffers(buffers: number[]): void;
     readBuffer(src: number): void;