Преглед изворни кода

Merge pull request #4786 from kcoley/glTFSerializerHandleFloat32Arrays

glTFSerializer: Handle float32 image data
David Catuhe пре 7 година
родитељ
комит
ae442d283e
1 измењених фајлова са 129 додато и 108 уклоњено
  1. 129 108
      serializers/src/glTF/2.0/babylon.glTFMaterialExporter.ts

+ 129 - 108
serializers/src/glTF/2.0/babylon.glTFMaterialExporter.ts

@@ -585,6 +585,29 @@ module BABYLON.GLTF2 {
         }
 
         /**
+         * Converts an array of pixels to a Float32Array
+         * Throws an error if the pixel format is not supported
+         * @param pixels - array buffer containing pixel values
+         * @returns Float32 of pixels
+         */
+        private _convertPixelArrayToFloat32(pixels: ArrayBufferView): Float32Array {
+            if (pixels instanceof Uint8Array) {
+                const length = pixels.length;
+                const buffer = new Float32Array(pixels.length);
+                for (let i = 0; i < length; ++i) {
+                    buffer[i] = pixels[i] / 255;
+                }
+                return buffer;
+            }
+            else if (pixels instanceof Float32Array) {
+                return pixels;
+            }
+            else {
+                throw new Error('Unsupported pixel format!');
+            }
+        }
+
+        /**
          * Convert Specular Glossiness Textures to Metallic Roughness
          * See link below for info on the material conversions from PBR Metallic/Roughness and Specular/Glossiness
          * @link https://github.com/KhronosGroup/glTF/blob/master/extensions/2.0/Khronos/KHR_materials_pbrSpecularGlossiness/examples/convert-between-workflows-bjs/js/babylon.pbrUtilities.js
@@ -606,128 +629,126 @@ module BABYLON.GLTF2 {
 
                 let diffuseSize = resizedTextures.texture1.getSize();
 
-                let diffuseBuffer: Uint8Array;
-                let specularGlossinessBuffer: Uint8Array;
+                let diffuseBuffer: Float32Array;
+                let specularGlossinessBuffer: Float32Array;
 
                 const width = diffuseSize.width;
                 const height = diffuseSize.height;
 
-                let pixels = (resizedTextures.texture1.readPixels());
-                if (pixels instanceof Uint8Array) {
-                    diffuseBuffer = (resizedTextures.texture1.readPixels()) as Uint8Array;
-
-                    pixels = resizedTextures.texture2.readPixels();
-
-                    if (pixels instanceof Uint8Array) {
-                        specularGlossinessBuffer = (resizedTextures.texture2.readPixels()) as Uint8Array;
-
-                        const byteLength = specularGlossinessBuffer.byteLength;
-
-                        const metallicRoughnessBuffer = new Uint8Array(byteLength);
-                        const baseColorBuffer = new Uint8Array(byteLength);
+                let diffusePixels = resizedTextures.texture1.readPixels();
+                let specularPixels = resizedTextures.texture2.readPixels();
 
-                        const strideSize = 4;
-                        const maxBaseColor = Color3.Black();
-                        let maxMetallic = 0;
-                        let maxRoughness = 0;
-
-                        for (let h = 0; h < height; ++h) {
-                            for (let w = 0; w < width; ++w) {
-                                const offset = (width * h + w) * strideSize;
-
-                                const diffuseColor = Color3.FromInts(diffuseBuffer[offset], diffuseBuffer[offset + 1], diffuseBuffer[offset + 2]).toLinearSpace().multiply(factors.diffuseColor);
-                                const specularColor = Color3.FromInts(specularGlossinessBuffer[offset], specularGlossinessBuffer[offset + 1], specularGlossinessBuffer[offset + 2]).toLinearSpace().multiply(factors.specularColor);
-                                const glossiness = (specularGlossinessBuffer[offset + 3] / 255) * factors.glossiness;
+                if (diffusePixels) {
+                    diffuseBuffer = this._convertPixelArrayToFloat32(diffusePixels);
+                }
+                else {
+                    return Promise.reject("Failed to retrieve pixels from diffuse texture!");
+                }
+                if (specularPixels) {
+                    specularGlossinessBuffer = this._convertPixelArrayToFloat32(specularPixels);
+                }
+                else {
+                    return Promise.reject("Failed to retrieve pixels from specular glossiness texture!");
+                }
 
-                                const specularGlossiness: _IPBRSpecularGlossiness = {
-                                    diffuseColor: diffuseColor,
-                                    specularColor: specularColor,
-                                    glossiness: glossiness
-                                };
+                const byteLength = specularGlossinessBuffer.byteLength;
 
-                                const metallicRoughness = this._convertSpecularGlossinessToMetallicRoughness(specularGlossiness);
-                                maxBaseColor.r = Math.max(maxBaseColor.r, metallicRoughness.baseColor.r);
-                                maxBaseColor.g = Math.max(maxBaseColor.g, metallicRoughness.baseColor.g);
-                                maxBaseColor.b = Math.max(maxBaseColor.b, metallicRoughness.baseColor.b);
-                                maxMetallic = Math.max(maxMetallic, metallicRoughness.metallic);
-                                maxRoughness = Math.max(maxRoughness, metallicRoughness.roughness);
+                const metallicRoughnessBuffer = new Uint8Array(byteLength);
+                const baseColorBuffer = new Uint8Array(byteLength);
 
-                                baseColorBuffer[offset] = metallicRoughness.baseColor.r * 255;
-                                baseColorBuffer[offset + 1] = metallicRoughness.baseColor.g * 255;
-                                baseColorBuffer[offset + 2] = metallicRoughness.baseColor.b * 255;
-                                baseColorBuffer[offset + 3] = resizedTextures.texture1.hasAlpha ? diffuseBuffer[offset + 3] : 255;
+                const strideSize = 4;
+                const maxBaseColor = Color3.Black();
+                let maxMetallic = 0;
+                let maxRoughness = 0;
 
-                                metallicRoughnessBuffer[offset] = 0;
-                                metallicRoughnessBuffer[offset + 1] = metallicRoughness.roughness * 255;
-                                metallicRoughnessBuffer[offset + 2] = metallicRoughness.metallic * 255;
-                                metallicRoughnessBuffer[offset + 3] = 255;
+                for (let h = 0; h < height; ++h) {
+                    for (let w = 0; w < width; ++w) {
+                        const offset = (width * h + w) * strideSize;
 
-                            }
-                        }
+                        const diffuseColor = new Color3(diffuseBuffer[offset], diffuseBuffer[offset + 1], diffuseBuffer[offset + 2]).toLinearSpace().multiply(factors.diffuseColor);
+                        const specularColor = new Color3(specularGlossinessBuffer[offset], specularGlossinessBuffer[offset + 1], specularGlossinessBuffer[offset + 2]).toLinearSpace().multiply(factors.specularColor);
+                        const glossiness = (specularGlossinessBuffer[offset + 3]) * factors.glossiness;
 
-                        // Retrieves the metallic roughness factors from the maximum texture values.
-                        const metallicRoughnessFactors: _IPBRMetallicRoughness = {
-                            baseColor: maxBaseColor,
-                            metallic: maxMetallic,
-                            roughness: maxRoughness
+                        const specularGlossiness: _IPBRSpecularGlossiness = {
+                            diffuseColor: diffuseColor,
+                            specularColor: specularColor,
+                            glossiness: glossiness
                         };
 
-                        let writeOutMetallicRoughnessTexture = false;
-                        let writeOutBaseColorTexture = false;
-
-                        for (let h = 0; h < height; ++h) {
-                            for (let w = 0; w < width; ++w) {
-                                const destinationOffset = (width * h + w) * strideSize;
+                        const metallicRoughness = this._convertSpecularGlossinessToMetallicRoughness(specularGlossiness);
+                        maxBaseColor.r = Math.max(maxBaseColor.r, metallicRoughness.baseColor.r);
+                        maxBaseColor.g = Math.max(maxBaseColor.g, metallicRoughness.baseColor.g);
+                        maxBaseColor.b = Math.max(maxBaseColor.b, metallicRoughness.baseColor.b);
+                        maxMetallic = Math.max(maxMetallic, metallicRoughness.metallic);
+                        maxRoughness = Math.max(maxRoughness, metallicRoughness.roughness);
+
+                        baseColorBuffer[offset] = metallicRoughness.baseColor.r * 255;
+                        baseColorBuffer[offset + 1] = metallicRoughness.baseColor.g * 255;
+                        baseColorBuffer[offset + 2] = metallicRoughness.baseColor.b * 255;
+                        baseColorBuffer[offset + 3] = resizedTextures.texture1.hasAlpha ? diffuseBuffer[offset + 3] : 255;
+
+                        metallicRoughnessBuffer[offset] = 0;
+                        metallicRoughnessBuffer[offset + 1] = metallicRoughness.roughness * 255;
+                        metallicRoughnessBuffer[offset + 2] = metallicRoughness.metallic * 255;
+                        metallicRoughnessBuffer[offset + 3] = 255;
+                    }
+                }
 
-                                baseColorBuffer[destinationOffset] /= metallicRoughnessFactors.baseColor.r > _GLTFMaterialExporter._Epsilon ? metallicRoughnessFactors.baseColor.r : 1;
-                                baseColorBuffer[destinationOffset + 1] /= metallicRoughnessFactors.baseColor.g > _GLTFMaterialExporter._Epsilon ? metallicRoughnessFactors.baseColor.g : 1;
-                                baseColorBuffer[destinationOffset + 2] /= metallicRoughnessFactors.baseColor.b > _GLTFMaterialExporter._Epsilon ? metallicRoughnessFactors.baseColor.b : 1;
+                // Retrieves the metallic roughness factors from the maximum texture values.
+                const metallicRoughnessFactors: _IPBRMetallicRoughness = {
+                    baseColor: maxBaseColor,
+                    metallic: maxMetallic,
+                    roughness: maxRoughness
+                };
 
-                                const linearBaseColorPixel = Color3.FromInts(baseColorBuffer[destinationOffset], baseColorBuffer[destinationOffset + 1], baseColorBuffer[destinationOffset + 2]);
-                                const sRGBBaseColorPixel = linearBaseColorPixel.toGammaSpace();
-                                baseColorBuffer[destinationOffset] = sRGBBaseColorPixel.r * 255;
-                                baseColorBuffer[destinationOffset + 1] = sRGBBaseColorPixel.g * 255;
-                                baseColorBuffer[destinationOffset + 2] = sRGBBaseColorPixel.b * 255;
+                let writeOutMetallicRoughnessTexture = false;
+                let writeOutBaseColorTexture = false;
 
-                                if (!_GLTFMaterialExporter.FuzzyEquals(sRGBBaseColorPixel, Color3.White(), _GLTFMaterialExporter._Epsilon)) {
-                                    writeOutBaseColorTexture = true;
-                                }
+                for (let h = 0; h < height; ++h) {
+                    for (let w = 0; w < width; ++w) {
+                        const destinationOffset = (width * h + w) * strideSize;
 
-                                metallicRoughnessBuffer[destinationOffset + 1] /= metallicRoughnessFactors.roughness > _GLTFMaterialExporter._Epsilon ? metallicRoughnessFactors.roughness : 1;
-                                metallicRoughnessBuffer[destinationOffset + 2] /= metallicRoughnessFactors.metallic > _GLTFMaterialExporter._Epsilon ? metallicRoughnessFactors.metallic : 1;
+                        baseColorBuffer[destinationOffset] /= metallicRoughnessFactors.baseColor.r > _GLTFMaterialExporter._Epsilon ? metallicRoughnessFactors.baseColor.r : 1;
+                        baseColorBuffer[destinationOffset + 1] /= metallicRoughnessFactors.baseColor.g > _GLTFMaterialExporter._Epsilon ? metallicRoughnessFactors.baseColor.g : 1;
+                        baseColorBuffer[destinationOffset + 2] /= metallicRoughnessFactors.baseColor.b > _GLTFMaterialExporter._Epsilon ? metallicRoughnessFactors.baseColor.b : 1;
 
-                                const metallicRoughnessPixel = Color3.FromInts(255, metallicRoughnessBuffer[destinationOffset + 1], metallicRoughnessBuffer[destinationOffset + 2]);
+                        const linearBaseColorPixel = Color3.FromInts(baseColorBuffer[destinationOffset], baseColorBuffer[destinationOffset + 1], baseColorBuffer[destinationOffset + 2]);
+                        const sRGBBaseColorPixel = linearBaseColorPixel.toGammaSpace();
+                        baseColorBuffer[destinationOffset] = sRGBBaseColorPixel.r * 255;
+                        baseColorBuffer[destinationOffset + 1] = sRGBBaseColorPixel.g * 255;
+                        baseColorBuffer[destinationOffset + 2] = sRGBBaseColorPixel.b * 255;
 
-                                if (!_GLTFMaterialExporter.FuzzyEquals(metallicRoughnessPixel, Color3.White(), _GLTFMaterialExporter._Epsilon)) {
-                                    writeOutMetallicRoughnessTexture = true;
-                                }
-                            }
+                        if (!_GLTFMaterialExporter.FuzzyEquals(sRGBBaseColorPixel, Color3.White(), _GLTFMaterialExporter._Epsilon)) {
+                            writeOutBaseColorTexture = true;
                         }
 
-                        if (writeOutMetallicRoughnessTexture) {
-                            let promise = this._createBase64FromCanvasAsync(metallicRoughnessBuffer, width, height, mimeType).then(metallicRoughnessBase64 => {
-                                metallicRoughnessFactors.metallicRoughnessTextureBase64 = metallicRoughnessBase64;
-                            });
-                            promises.push(promise);
-                        }
-                        if (writeOutBaseColorTexture) {
-                            let promise = this._createBase64FromCanvasAsync(baseColorBuffer, width, height, mimeType).then(baseColorBase64 => {
-                                metallicRoughnessFactors.baseColorTextureBase64 = baseColorBase64;
-                            });
-                            promises.push(promise);
-                        }
+                        metallicRoughnessBuffer[destinationOffset + 1] /= metallicRoughnessFactors.roughness > _GLTFMaterialExporter._Epsilon ? metallicRoughnessFactors.roughness : 1;
+                        metallicRoughnessBuffer[destinationOffset + 2] /= metallicRoughnessFactors.metallic > _GLTFMaterialExporter._Epsilon ? metallicRoughnessFactors.metallic : 1;
 
-                        return Promise.all(promises).then(() => {
-                            return metallicRoughnessFactors;
-                        });
-                    }
-                    else {
-                        return Promise.reject("_ConvertSpecularGlossinessTexturesToMetallicRoughness: Pixel array buffer type not supported for texture: " + resizedTextures.texture2.name);
+                        const metallicRoughnessPixel = Color3.FromInts(255, metallicRoughnessBuffer[destinationOffset + 1], metallicRoughnessBuffer[destinationOffset + 2]);
+
+                        if (!_GLTFMaterialExporter.FuzzyEquals(metallicRoughnessPixel, Color3.White(), _GLTFMaterialExporter._Epsilon)) {
+                            writeOutMetallicRoughnessTexture = true;
+                        }
                     }
                 }
-                else {
-                    return Promise.reject("_ConvertSpecularGlossinessTexturesToMetallicRoughness: Pixel array buffer type not supported for texture: " + resizedTextures.texture1.name);
+
+                if (writeOutMetallicRoughnessTexture) {
+                    let promise = this._createBase64FromCanvasAsync(metallicRoughnessBuffer, width, height, mimeType).then(metallicRoughnessBase64 => {
+                        metallicRoughnessFactors.metallicRoughnessTextureBase64 = metallicRoughnessBase64;
+                    });
+                    promises.push(promise);
+                }
+                if (writeOutBaseColorTexture) {
+                    let promise = this._createBase64FromCanvasAsync(baseColorBuffer, width, height, mimeType).then(baseColorBase64 => {
+                        metallicRoughnessFactors.baseColorTextureBase64 = baseColorBase64;
+                    });
+                    promises.push(promise);
                 }
+
+                return Promise.all(promises).then(() => {
+                    return metallicRoughnessFactors;
+                });
             }
             else {
                 return Promise.reject("_ConvertSpecularGlossinessTexturesToMetallicRoughness: Scene from textures is missing!");
@@ -953,20 +974,20 @@ module BABYLON.GLTF2 {
                 }
                 if ((babylonPBRMaterial.albedoTexture || babylonPBRMaterial.reflectivityTexture) && hasTextureCoords) {
                     return this._convertSpecularGlossinessTexturesToMetallicRoughnessAsync(babylonPBRMaterial.albedoTexture, babylonPBRMaterial.reflectivityTexture, specGloss, mimeType).then(metallicRoughnessFactors => {
-                            if (metallicRoughnessFactors.baseColorTextureBase64) {
-                                const glTFBaseColorTexture = this._getTextureInfoFromBase64(metallicRoughnessFactors.baseColorTextureBase64, "bjsBaseColorTexture_" + (textures.length) + ".png", mimeType, babylonPBRMaterial.albedoTexture ? babylonPBRMaterial.albedoTexture.coordinatesIndex : null, samplerIndex);
-                                if (glTFBaseColorTexture) {
-                                    glTFPbrMetallicRoughness.baseColorTexture = glTFBaseColorTexture;
-                                }
+                        if (metallicRoughnessFactors.baseColorTextureBase64) {
+                            const glTFBaseColorTexture = this._getTextureInfoFromBase64(metallicRoughnessFactors.baseColorTextureBase64, "bjsBaseColorTexture_" + (textures.length) + ".png", mimeType, babylonPBRMaterial.albedoTexture ? babylonPBRMaterial.albedoTexture.coordinatesIndex : null, samplerIndex);
+                            if (glTFBaseColorTexture) {
+                                glTFPbrMetallicRoughness.baseColorTexture = glTFBaseColorTexture;
                             }
-                            if (metallicRoughnessFactors.metallicRoughnessTextureBase64) {
-                                const glTFMRColorTexture = this._getTextureInfoFromBase64(metallicRoughnessFactors.metallicRoughnessTextureBase64, "bjsMetallicRoughnessTexture_" + (textures.length) + ".png", mimeType, babylonPBRMaterial.reflectivityTexture ? babylonPBRMaterial.reflectivityTexture.coordinatesIndex : null, samplerIndex);
-                                if (glTFMRColorTexture) {
-                                    glTFPbrMetallicRoughness.metallicRoughnessTexture = glTFMRColorTexture;
-                                }
+                        }
+                        if (metallicRoughnessFactors.metallicRoughnessTextureBase64) {
+                            const glTFMRColorTexture = this._getTextureInfoFromBase64(metallicRoughnessFactors.metallicRoughnessTextureBase64, "bjsMetallicRoughnessTexture_" + (textures.length) + ".png", mimeType, babylonPBRMaterial.reflectivityTexture ? babylonPBRMaterial.reflectivityTexture.coordinatesIndex : null, samplerIndex);
+                            if (glTFMRColorTexture) {
+                                glTFPbrMetallicRoughness.metallicRoughnessTexture = glTFMRColorTexture;
                             }
+                        }
 
-                            return metallicRoughnessFactors;
+                        return metallicRoughnessFactors;
                     });
                 }
                 else {