private void ExportMaterial(BabylonMaterial babylonMaterial, GLTF gltf)
        {
            var name = babylonMaterial.name;
            var id   = babylonMaterial.id;

            RaiseMessage("GLTFExporter.Material | Export material named: " + name, 1);

            GLTFMaterial gltfMaterial = null;

            if (babylonMaterial.GetType() == typeof(BabylonStandardMaterial))
            {
                var babylonStandardMaterial = babylonMaterial as BabylonStandardMaterial;


                // --- prints ---
                #region prints

                RaiseVerbose("GLTFExporter.Material | babylonMaterial data", 2);
                RaiseVerbose("GLTFExporter.Material | babylonMaterial.alpha=" + babylonMaterial.alpha, 3);
                RaiseVerbose("GLTFExporter.Material | babylonMaterial.alphaMode=" + babylonMaterial.alphaMode, 3);
                RaiseVerbose("GLTFExporter.Material | babylonMaterial.backFaceCulling=" + babylonMaterial.backFaceCulling, 3);
                RaiseVerbose("GLTFExporter.Material | babylonMaterial.wireframe=" + babylonMaterial.wireframe, 3);

                // Ambient
                for (int i = 0; i < babylonStandardMaterial.ambient.Length; i++)
                {
                    RaiseVerbose("GLTFExporter.Material | babylonStandardMaterial.ambient[" + i + "]=" + babylonStandardMaterial.ambient[i], 3);
                }

                // Diffuse
                RaiseVerbose("GLTFExporter.Material | babylonStandardMaterial.diffuse.Length=" + babylonStandardMaterial.diffuse.Length, 3);
                for (int i = 0; i < babylonStandardMaterial.diffuse.Length; i++)
                {
                    RaiseVerbose("GLTFExporter.Material | babylonStandardMaterial.diffuse[" + i + "]=" + babylonStandardMaterial.diffuse[i], 3);
                }
                if (babylonStandardMaterial.diffuseTexture == null)
                {
                    RaiseVerbose("GLTFExporter.Material | babylonStandardMaterial.diffuseTexture=null", 3);
                }
                else
                {
                    RaiseVerbose("GLTFExporter.Material | babylonStandardMaterial.diffuseTexture.name=" + babylonStandardMaterial.diffuseTexture.name, 3);
                }

                // Normal / bump
                if (babylonStandardMaterial.bumpTexture == null)
                {
                    RaiseVerbose("GLTFExporter.Material | babylonStandardMaterial.bumpTexture=null", 3);
                }
                else
                {
                    RaiseVerbose("GLTFExporter.Material | babylonStandardMaterial.bumpTexture.name=" + babylonStandardMaterial.bumpTexture.name, 3);
                }

                // Opacity
                if (babylonStandardMaterial.opacityTexture == null)
                {
                    RaiseVerbose("GLTFExporter.Material | babylonStandardMaterial.opacityTexture=null", 3);
                }
                else
                {
                    RaiseVerbose("GLTFExporter.Material | babylonStandardMaterial.opacityTexture.name=" + babylonStandardMaterial.opacityTexture.name, 3);
                }

                // Specular
                for (int i = 0; i < babylonStandardMaterial.specular.Length; i++)
                {
                    RaiseVerbose("GLTFExporter.Material | babylonStandardMaterial.specular[" + i + "]=" + babylonStandardMaterial.specular[i], 3);
                }
                RaiseVerbose("GLTFExporter.Material | babylonStandardMaterial.specularPower=" + babylonStandardMaterial.specularPower, 3);
                if (babylonStandardMaterial.specularTexture == null)
                {
                    RaiseVerbose("GLTFExporter.Material | babylonStandardMaterial.specularTexture=null", 3);
                }
                else
                {
                    RaiseVerbose("GLTFExporter.Material | babylonStandardMaterial.specularTexture.name=" + babylonStandardMaterial.specularTexture.name, 3);
                }

                // Occlusion
                if (babylonStandardMaterial.ambientTexture == null)
                {
                    RaiseVerbose("GLTFExporter.Material | babylonStandardMaterial.ambientTexture=null", 3);
                }
                else
                {
                    RaiseVerbose("GLTFExporter.Material | babylonStandardMaterial.ambientTexture.name=" + babylonStandardMaterial.ambientTexture.name, 3);
                }

                // Emissive
                for (int i = 0; i < babylonStandardMaterial.emissive.Length; i++)
                {
                    RaiseVerbose("GLTFExporter.Material | babylonStandardMaterial.emissive[" + i + "]=" + babylonStandardMaterial.emissive[i], 3);
                }
                if (babylonStandardMaterial.emissiveTexture == null)
                {
                    RaiseVerbose("GLTFExporter.Material | babylonStandardMaterial.emissiveTexture=null", 3);
                }
                else
                {
                    RaiseVerbose("GLTFExporter.Material | babylonStandardMaterial.emissiveTexture.name=" + babylonStandardMaterial.emissiveTexture.name, 3);
                }
                #endregion


                // --------------------------------
                // --------- gltfMaterial ---------
                // --------------------------------

                RaiseMessage("GLTFExporter.Material | create gltfMaterial", 2);
                gltfMaterial = new GLTFMaterial
                {
                    name = name
                };
                gltfMaterial.id    = babylonMaterial.id;
                gltfMaterial.index = gltf.MaterialsList.Count;
                gltf.MaterialsList.Add(gltfMaterial);

                // Alpha
                string alphaMode;
                float? alphaCutoff;
                getAlphaMode(babylonStandardMaterial, out alphaMode, out alphaCutoff);
                gltfMaterial.alphaMode   = alphaMode;
                gltfMaterial.alphaCutoff = alphaCutoff;

                // DoubleSided
                gltfMaterial.doubleSided = !babylonMaterial.backFaceCulling;

                // Normal
                gltfMaterial.normalTexture = ExportTexture(babylonStandardMaterial.bumpTexture, gltf);

                // Occulison
                gltfMaterial.occlusionTexture = ExportTexture(babylonStandardMaterial.ambientTexture, gltf);

                // Emissive
                gltfMaterial.emissiveFactor = babylonStandardMaterial.emissive;
                // linkEmissiveWithDiffuse attribute doesn't have an equivalent in gltf format
                // When true, the emissive texture needs to be manually multiplied with diffuse texture
                // Otherwise, the emissive texture is assumed to be already pre-multiplied
                if (babylonStandardMaterial.linkEmissiveWithDiffuse)
                {
                    // Even when no emissive texture is provided, the self illumination value needs to be multiplied to the diffuse texture in order to get the pre-multiplied emissive (texture)
                    if (babylonStandardMaterial.emissiveTexture != null || babylonStandardMaterial.selfIllum > 0)
                    {
                        // Default emissive is the raw value of the self illumination
                        // It is not the babylon emissive value which is already pre-multiplied with diffuse color
                        float[] defaultEmissive = new float[] { 1, 1, 1 }.Multiply(babylonStandardMaterial.selfIllum);
                        gltfMaterial.emissiveTexture = ExportEmissiveTexture(babylonStandardMaterial, gltf, defaultEmissive, babylonStandardMaterial.diffuse);
                    }
                }
                else
                {
                    gltfMaterial.emissiveTexture = ExportTexture(babylonStandardMaterial.emissiveTexture, gltf);
                }

                // Constraints
                if (gltfMaterial.emissiveTexture != null)
                {
                    gltfMaterial.emissiveFactor = new[] { 1.0f, 1.0f, 1.0f };
                }

                // --------------------------------
                // --- gltfPbrMetallicRoughness ---
                // --------------------------------

                RaiseMessage("GLTFExporter.Material | create gltfPbrMetallicRoughness", 2);
                var gltfPbrMetallicRoughness = new GLTFPBRMetallicRoughness();
                gltfMaterial.pbrMetallicRoughness = gltfPbrMetallicRoughness;

                // --- Global ---

                SpecularGlossiness _specularGlossiness = new SpecularGlossiness
                {
                    diffuse    = new BabylonColor3(babylonStandardMaterial.diffuse),
                    opacity    = babylonMaterial.alpha,
                    specular   = new BabylonColor3(babylonStandardMaterial.specular),
                    glossiness = babylonStandardMaterial.specularPower / 256
                };

                MetallicRoughness _metallicRoughness = ConvertToMetallicRoughness(_specularGlossiness, true);

                // Base color
                gltfPbrMetallicRoughness.baseColorFactor = new float[4]
                {
                    _metallicRoughness.baseColor.r,
                    _metallicRoughness.baseColor.g,
                    _metallicRoughness.baseColor.b,
                    _metallicRoughness.opacity
                };

                // Metallic roughness
                gltfPbrMetallicRoughness.metallicFactor  = _metallicRoughness.metallic;
                gltfPbrMetallicRoughness.roughnessFactor = _metallicRoughness.roughness;


                // --- Textures ---
                var babylonTexture = babylonStandardMaterial.diffuseTexture != null ? babylonStandardMaterial.diffuseTexture :
                                     babylonStandardMaterial.specularTexture != null ? babylonStandardMaterial.specularTexture :
                                     babylonStandardMaterial.opacityTexture != null ? babylonStandardMaterial.opacityTexture :
                                     null;

                if (babylonTexture != null)
                {
                    //Check if the texture already exist
                    var _key = SetStandText(babylonStandardMaterial);

                    if (GetStandTextInfo(_key) != null)
                    {
                        var _pairBCMR = GetStandTextInfo(_key);
                        gltfPbrMetallicRoughness.baseColorTexture         = _pairBCMR.baseColor;
                        gltfPbrMetallicRoughness.metallicRoughnessTexture = _pairBCMR.metallicRoughness;
                    }
                    else
                    {
                        bool isAlphaInTexture = (isTextureOk(babylonStandardMaterial.diffuseTexture) && babylonStandardMaterial.diffuseTexture.hasAlpha) ||
                                                isTextureOk(babylonStandardMaterial.opacityTexture);

                        Bitmap baseColorBitmap         = null;
                        Bitmap metallicRoughnessBitmap = null;

                        GLTFTextureInfo textureInfoBC = new GLTFTextureInfo();
                        GLTFTextureInfo textureInfoMR = new GLTFTextureInfo();

                        if (exportParameters.writeTextures)
                        {
                            // Diffuse
                            Bitmap diffuseBitmap = null;
                            if (babylonStandardMaterial.diffuseTexture != null)
                            {
                                diffuseBitmap = LoadTexture(babylonStandardMaterial.diffuseTexture.originalPath);
                            }

                            // Specular
                            Bitmap specularBitmap = null;
                            if (babylonStandardMaterial.specularTexture != null)
                            {
                                if (babylonStandardMaterial.specularTexture.bitmap != null)
                                {
                                    // Specular color map has been computed by the exporter
                                    specularBitmap = babylonStandardMaterial.specularTexture.bitmap;
                                }
                                else
                                {
                                    // Specular color map is straight input
                                    specularBitmap = LoadTexture(babylonStandardMaterial.specularTexture.originalPath);
                                }
                            }

                            // Opacity / Alpha / Transparency
                            Bitmap opacityBitmap = null;
                            if ((babylonStandardMaterial.diffuseTexture == null || babylonStandardMaterial.diffuseTexture.hasAlpha == false) && babylonStandardMaterial.opacityTexture != null)
                            {
                                opacityBitmap = LoadTexture(babylonStandardMaterial.opacityTexture.originalPath);
                            }

                            if (diffuseBitmap != null || specularBitmap != null || opacityBitmap != null)
                            {
                                // Retreive dimensions
                                int width              = 0;
                                int height             = 0;
                                var haveSameDimensions = _getMinimalBitmapDimensions(out width, out height, diffuseBitmap, specularBitmap, opacityBitmap);
                                if (!haveSameDimensions)
                                {
                                    RaiseError("Diffuse, specular and opacity maps should have same dimensions", 2);
                                }

                                // Create baseColor+alpha and metallic+roughness maps
                                baseColorBitmap         = new Bitmap(width, height);
                                metallicRoughnessBitmap = new Bitmap(width, height);
                                for (int x = 0; x < width; x++)
                                {
                                    for (int y = 0; y < height; y++)
                                    {
                                        SpecularGlossiness specularGlossinessTexture = new SpecularGlossiness
                                        {
                                            diffuse = diffuseBitmap != null ? new BabylonColor3(diffuseBitmap.GetPixel(x, y)) :
                                                      _specularGlossiness.diffuse,
                                            opacity = diffuseBitmap != null && babylonStandardMaterial.diffuseTexture.hasAlpha ? diffuseBitmap.GetPixel(x, y).A / 255.0f :
                                                      opacityBitmap != null && babylonStandardMaterial.opacityTexture.getAlphaFromRGB ? opacityBitmap.GetPixel(x, y).R / 255.0f :
                                                      opacityBitmap != null && babylonStandardMaterial.opacityTexture.getAlphaFromRGB == false?opacityBitmap.GetPixel(x, y).A / 255.0f :
                                                      _specularGlossiness.opacity,
                                            specular = specularBitmap != null ? new BabylonColor3(specularBitmap.GetPixel(x, y)) :
                                                       _specularGlossiness.specular,
                                            glossiness = babylonStandardMaterial.useGlossinessFromSpecularMapAlpha && specularBitmap != null?specularBitmap.GetPixel(x, y).A / 255.0f :
                                                         _specularGlossiness.glossiness
                                        };

                                        var displayPrints = x == width / 2 && y == height / 2;
                                        MetallicRoughness metallicRoughnessTexture = ConvertToMetallicRoughness(specularGlossinessTexture, displayPrints);

                                        Color colorBase = Color.FromArgb(
                                            (int)(metallicRoughnessTexture.opacity * 255),
                                            (int)(metallicRoughnessTexture.baseColor.r * 255),
                                            (int)(metallicRoughnessTexture.baseColor.g * 255),
                                            (int)(metallicRoughnessTexture.baseColor.b * 255)
                                            );
                                        baseColorBitmap.SetPixel(x, y, colorBase);

                                        // The metalness values are sampled from the B channel.
                                        // The roughness values are sampled from the G channel.
                                        // These values are linear. If other channels are present (R or A), they are ignored for metallic-roughness calculations.
                                        Color colorMetallicRoughness = Color.FromArgb(
                                            0,
                                            (int)(metallicRoughnessTexture.roughness * 255),
                                            (int)(metallicRoughnessTexture.metallic * 255)
                                            );
                                        metallicRoughnessBitmap.SetPixel(x, y, colorMetallicRoughness);
                                    }
                                }
                            }
                        }

                        //export textures
                        var baseColorFileName = babylonMaterial.name + "_baseColor" + (isAlphaInTexture ? ".png" : ".jpg");
                        textureInfoBC = ExportBitmapTexture(gltf, babylonTexture, baseColorBitmap, baseColorFileName);
                        gltfPbrMetallicRoughness.baseColorTexture = textureInfoBC;

                        // If no specular map is defined, the metallic and roughness values are be driven by the global parameters
                        if (babylonStandardMaterial.specularTexture != null)
                        {
                            textureInfoMR = ExportBitmapTexture(gltf, babylonTexture, metallicRoughnessBitmap, babylonMaterial.name + "_metallicRoughness" + ".jpg");
                            gltfPbrMetallicRoughness.metallicRoughnessTexture = textureInfoMR;
                        }

                        //register the texture
                        AddStandText(_key, textureInfoBC, textureInfoMR);
                    }

                    // Constraints
                    if (gltfPbrMetallicRoughness.baseColorTexture != null)
                    {
                        gltfPbrMetallicRoughness.baseColorFactor = new[] { 1.0f, 1.0f, 1.0f, 1.0f };
                    }

                    if (gltfPbrMetallicRoughness.metallicRoughnessTexture != null)
                    {
                        gltfPbrMetallicRoughness.metallicFactor  = 1.0f;
                        gltfPbrMetallicRoughness.roughnessFactor = 1.0f;
                    }
                }
            }
            else if (babylonMaterial.GetType() == typeof(BabylonPBRMetallicRoughnessMaterial))
            {
                var babylonPBRMetallicRoughnessMaterial = babylonMaterial as BabylonPBRMetallicRoughnessMaterial;


                // --- prints ---
                #region prints

                RaiseVerbose("GLTFExporter.Material | babylonMaterial data", 2);
                RaiseVerbose("GLTFExporter.Material | babylonMaterial.alpha=" + babylonMaterial.alpha, 3);
                RaiseVerbose("GLTFExporter.Material | babylonMaterial.alphaMode=" + babylonMaterial.alphaMode, 3);
                RaiseVerbose("GLTFExporter.Material | babylonMaterial.backFaceCulling=" + babylonMaterial.backFaceCulling, 3);
                RaiseVerbose("GLTFExporter.Material | babylonMaterial.wireframe=" + babylonMaterial.wireframe, 3);

                // Global
                RaiseVerbose("GLTFExporter.Material | babylonPBRMetallicRoughnessMaterial.maxSimultaneousLights=" + babylonPBRMetallicRoughnessMaterial.maxSimultaneousLights, 3);
                RaiseVerbose("GLTFExporter.Material | babylonPBRMetallicRoughnessMaterial.disableLighting=" + babylonPBRMetallicRoughnessMaterial.disableLighting, 3);
                RaiseVerbose("GLTFExporter.Material | babylonPBRMetallicRoughnessMaterial.alphaCutOff=" + babylonPBRMetallicRoughnessMaterial.alphaCutOff, 3);
                RaiseVerbose("GLTFExporter.Material | babylonPBRMetallicRoughnessMaterial.transparencyMode=" + babylonPBRMetallicRoughnessMaterial.transparencyMode, 3);
                RaiseVerbose("GLTFExporter.Material | babylonPBRMetallicRoughnessMaterial.doubleSided=" + babylonPBRMetallicRoughnessMaterial.doubleSided, 3);

                // Base color
                RaiseVerbose("GLTFExporter.Material | babylonPBRMetallicRoughnessMaterial.baseColor.Length=" + babylonPBRMetallicRoughnessMaterial.baseColor.Length, 3);
                for (int i = 0; i < babylonPBRMetallicRoughnessMaterial.baseColor.Length; i++)
                {
                    RaiseVerbose("GLTFExporter.Material | babylonPBRMetallicRoughnessMaterial.baseColor[" + i + "]=" + babylonPBRMetallicRoughnessMaterial.baseColor[i], 3);
                }
                if (babylonPBRMetallicRoughnessMaterial.baseTexture == null)
                {
                    RaiseVerbose("GLTFExporter.Material | babylonPBRMetallicRoughnessMaterial.baseTexture=null", 3);
                }

                // Metallic+roughness
                RaiseVerbose("GLTFExporter.Material | babylonPBRMetallicRoughnessMaterial.metallic=" + babylonPBRMetallicRoughnessMaterial.metallic, 3);
                RaiseVerbose("GLTFExporter.Material | babylonPBRMetallicRoughnessMaterial.roughness=" + babylonPBRMetallicRoughnessMaterial.roughness, 3);
                if (babylonPBRMetallicRoughnessMaterial.metallicRoughnessTexture == null)
                {
                    RaiseVerbose("GLTFExporter.Material | babylonPBRMetallicRoughnessMaterial.metallicRoughnessTexture=null", 3);
                }

                // Normal / bump
                if (babylonPBRMetallicRoughnessMaterial.normalTexture == null)
                {
                    RaiseVerbose("GLTFExporter.Material | babylonPBRMetallicRoughnessMaterial.normalTexture=null", 3);
                }
                RaiseVerbose("GLTFExporter.Material | babylonPBRMetallicRoughnessMaterial.invertNormalMapX=" + babylonPBRMetallicRoughnessMaterial.invertNormalMapX, 3);
                RaiseVerbose("GLTFExporter.Material | babylonPBRMetallicRoughnessMaterial.invertNormalMapY=" + babylonPBRMetallicRoughnessMaterial.invertNormalMapY, 3);

                // Emissive
                for (int i = 0; i < babylonPBRMetallicRoughnessMaterial.emissive.Length; i++)
                {
                    RaiseVerbose("GLTFExporter.Material | babylonPBRMetallicRoughnessMaterial.emissiveColor[" + i + "]=" + babylonPBRMetallicRoughnessMaterial.emissive[i], 3);
                }
                if (babylonPBRMetallicRoughnessMaterial.emissiveTexture == null)
                {
                    RaiseVerbose("GLTFExporter.Material | babylonPBRMetallicRoughnessMaterial.emissiveTexture=null", 3);
                }

                // Ambient occlusion
                RaiseVerbose("GLTFExporter.Material | babylonPBRMetallicRoughnessMaterial.occlusionStrength=" + babylonPBRMetallicRoughnessMaterial.occlusionStrength, 3);
                if (babylonPBRMetallicRoughnessMaterial.occlusionTexture == null)
                {
                    RaiseVerbose("GLTFExporter.Material | babylonPBRMetallicRoughnessMaterial.occlusionTexture=null", 3);
                }
                #endregion


                // --------------------------------
                // --------- gltfMaterial ---------
                // --------------------------------

                RaiseMessage("GLTFExporter.Material | create gltfMaterial", 2);
                gltfMaterial = new GLTFMaterial
                {
                    name = name
                };
                gltfMaterial.id    = babylonMaterial.id;
                gltfMaterial.index = gltf.MaterialsList.Count;
                gltf.MaterialsList.Add(gltfMaterial);

                // Alpha
                string alphaMode;
                float? alphaCutoff;
                getAlphaMode(babylonPBRMetallicRoughnessMaterial, out alphaMode, out alphaCutoff);
                gltfMaterial.alphaMode   = alphaMode;
                gltfMaterial.alphaCutoff = alphaCutoff;

                // DoubleSided
                gltfMaterial.doubleSided = babylonPBRMetallicRoughnessMaterial.doubleSided;

                // Normal
                gltfMaterial.normalTexture = ExportTexture(babylonPBRMetallicRoughnessMaterial.normalTexture, gltf);

                // Occulison
                if (babylonPBRMetallicRoughnessMaterial.occlusionTexture != null)
                {
                    if (babylonPBRMetallicRoughnessMaterial.occlusionTexture.bitmap != null)
                    {
                        // ORM texture has been merged manually by the exporter
                        // Occlusion is defined as well as metallic and/or roughness
                        RaiseVerbose("Occlusion is defined as well as metallic and/or roughness", 2);
                        gltfMaterial.occlusionTexture = ExportBitmapTexture(gltf, babylonPBRMetallicRoughnessMaterial.occlusionTexture);
                    }
                    else
                    {
                        // ORM texture was already merged or only occlusion is defined
                        RaiseVerbose("ORM texture was already merged or only occlusion is defined", 2);
                        gltfMaterial.occlusionTexture = ExportTexture(babylonPBRMetallicRoughnessMaterial.occlusionTexture, gltf);
                    }
                }

                // Emissive
                gltfMaterial.emissiveFactor  = babylonPBRMetallicRoughnessMaterial.emissive;
                gltfMaterial.emissiveTexture = ExportTexture(babylonPBRMetallicRoughnessMaterial.emissiveTexture, gltf);


                // --------------------------------
                // --- gltfPbrMetallicRoughness ---
                // --------------------------------

                RaiseMessage("GLTFExporter.Material | create gltfPbrMetallicRoughness", 2);
                var gltfPbrMetallicRoughness = new GLTFPBRMetallicRoughness();
                gltfMaterial.pbrMetallicRoughness = gltfPbrMetallicRoughness;

                // --- Global ---

                // Base color
                gltfPbrMetallicRoughness.baseColorFactor = new float[4]
                {
                    babylonPBRMetallicRoughnessMaterial.baseColor[0],
                    babylonPBRMetallicRoughnessMaterial.baseColor[1],
                    babylonPBRMetallicRoughnessMaterial.baseColor[2],
                    babylonPBRMetallicRoughnessMaterial.alpha
                };
                if (babylonPBRMetallicRoughnessMaterial.baseTexture != null)
                {
                    if (babylonPBRMetallicRoughnessMaterial.baseTexture.bitmap != null)
                    {
                        gltfPbrMetallicRoughness.baseColorTexture = ExportBitmapTexture(gltf, babylonPBRMetallicRoughnessMaterial.baseTexture);
                    }
                    else
                    {
                        gltfPbrMetallicRoughness.baseColorTexture = ExportTexture(babylonPBRMetallicRoughnessMaterial.baseTexture, gltf);
                    }
                }

                // Metallic roughness
                gltfPbrMetallicRoughness.metallicFactor  = babylonPBRMetallicRoughnessMaterial.metallic;
                gltfPbrMetallicRoughness.roughnessFactor = babylonPBRMetallicRoughnessMaterial.roughness;
                if (babylonPBRMetallicRoughnessMaterial.metallicRoughnessTexture != null)
                {
                    if (babylonPBRMetallicRoughnessMaterial.metallicRoughnessTexture == babylonPBRMetallicRoughnessMaterial.occlusionTexture)
                    {
                        // Occlusion is defined as well as metallic and/or roughness
                        // Use same texture
                        RaiseVerbose("Occlusion is defined as well as metallic and/or roughness", 2);
                        gltfPbrMetallicRoughness.metallicRoughnessTexture = gltfMaterial.occlusionTexture;
                    }
                    else
                    {
                        // Occlusion is not defined, only metallic and/or roughness
                        RaiseVerbose("Occlusion is not defined, only metallic and/or roughness", 2);

                        if (babylonPBRMetallicRoughnessMaterial.metallicRoughnessTexture.bitmap != null)
                        {
                            // Metallic & roughness texture has been merged manually by the exporter
                            // Write bitmap file
                            RaiseVerbose("Metallic & roughness texture has been merged manually by the exporter", 2);
                            gltfPbrMetallicRoughness.metallicRoughnessTexture = ExportBitmapTexture(gltf, babylonPBRMetallicRoughnessMaterial.metallicRoughnessTexture);
                        }
                        else
                        {
                            // Metallic & roughness texture was already merged
                            // Copy file
                            RaiseVerbose("Metallic & roughness texture was already merged", 2);
                            gltfPbrMetallicRoughness.metallicRoughnessTexture = ExportTexture(babylonPBRMetallicRoughnessMaterial.metallicRoughnessTexture, gltf);
                        }
                    }
                }
            }
            else
            {
                RaiseWarning("GLTFExporter.Material | Unsupported material type: " + babylonMaterial.GetType(), 2);
            }

            if (gltfMaterial != null && babylonMaterial.isUnlit)
            {
                // Add Unlit extension
                if (!exportParameters.enableKHRMaterialsUnlit)
                {
                    RaiseWarning("GLTFExporter.Material | KHR_materials_unlit has not been enabled for export!", 2);
                }
                else
                {
                    if (gltfMaterial.extensions == null)
                    {
                        gltfMaterial.extensions = new GLTFExtensions();
                    }
                    if (gltf.extensionsUsed == null)
                    {
                        gltf.extensionsUsed = new System.Collections.Generic.List <string>();
                    }
                    if (!gltf.extensionsUsed.Contains("KHR_materials_unlit"))
                    {
                        gltf.extensionsUsed.Add("KHR_materials_unlit");
                    }
                    gltfMaterial.extensions["KHR_materials_unlit"] = new object();
                }
            }
        }
Пример #2
0
        private BabylonMaterial ExportMaterialAnimations(BabylonMaterial babylonMaterial, IIGameMaterial material, BabylonExporter exporter)
        {
            var animations = new List <BabylonAnimation>();

            int numProps = material.IPropertyContainer.NumberOfProperties;

            for (int i = 0; i < numProps; ++i)
            {
                IIGameProperty property = material.IPropertyContainer.GetProperty(i);

                if (property == null)
                {
                    continue;
                }

                if (!property.IsPropAnimated)
                {
                    continue;
                }

                IParamDef paramDef     = property.MaxParamBlock2?.GetParamDef(property.ParamID);
                string    propertyName = property.Name.ToUpperInvariant();

                switch (propertyName)
                {
                case "BASECOLOR":
                {
                    if (property.IGameControl.GetMaxControl(IGameControlType.Point4).NumKeys > 0)
                    {
                        exporter.ExportColor4Animation(property.Name, animations,
                                                       key => material.IPropertyContainer.GetPoint4Property(property.Name, key).ToArray());
                    }
                    break;
                }

                case "EMISSIVE":
                {
                    if (property.IGameControl.GetMaxControl(IGameControlType.Point3).NumKeys > 0)
                    {
                        exporter.ExportColor3Animation(property.Name, animations,
                                                       key => material.IPropertyContainer.GetPoint3Property(property.Name, key).ToArray());
                    }
                    break;
                }

                case "WIPERANIMSTATE1":
                case "WIPERANIMSTATE2":
                case "WIPERANIMSTATE3":
                case "WIPERANIMSTATE4":
                case "METALLIC":
                case "ROUGHNESS":
                case "UVOFFSETU":
                case "UVOFFSETV":
                case "UVTILINGU":
                case "UVTILINGV":
                case "UVROTATION":
                {
                    if (property.IGameControl.GetMaxControl(IGameControlType.Float).NumKeys > 0)
                    {
                        exporter.ExportFloatAnimation(property.Name, animations,
                                                      key => new[] { material.IPropertyContainer.GetFloatProperty(property.Name, key, 0) });
                    }
                    break;
                }

                default:
                    break;
                }
            }

            babylonMaterial.animations = animations.ToArray();
            return(babylonMaterial);
        }
        private void ExportMaterial(BabylonMaterial babylonMaterial, GLTF gltf)
        {
            var name = babylonMaterial.name;
            var id   = babylonMaterial.id;

            RaiseMessage("GLTFExporter.Material | Export material named: " + name, 1);

            if (babylonMaterial.GetType() == typeof(BabylonStandardMaterial))
            {
                var babylonStandardMaterial = babylonMaterial as BabylonStandardMaterial;


                // --- prints ---
                #region prints

                RaiseVerbose("GLTFExporter.Material | babylonMaterial data", 2);
                RaiseVerbose("GLTFExporter.Material | babylonMaterial.alpha=" + babylonMaterial.alpha, 3);
                RaiseVerbose("GLTFExporter.Material | babylonMaterial.alphaMode=" + babylonMaterial.alphaMode, 3);
                RaiseVerbose("GLTFExporter.Material | babylonMaterial.backFaceCulling=" + babylonMaterial.backFaceCulling, 3);
                RaiseVerbose("GLTFExporter.Material | babylonMaterial.wireframe=" + babylonMaterial.wireframe, 3);

                // Ambient
                for (int i = 0; i < babylonStandardMaterial.ambient.Length; i++)
                {
                    RaiseVerbose("GLTFExporter.Material | babylonStandardMaterial.ambient[" + i + "]=" + babylonStandardMaterial.ambient[i], 3);
                }

                // Diffuse
                RaiseVerbose("GLTFExporter.Material | babylonStandardMaterial.diffuse.Length=" + babylonStandardMaterial.diffuse.Length, 3);
                for (int i = 0; i < babylonStandardMaterial.diffuse.Length; i++)
                {
                    RaiseVerbose("GLTFExporter.Material | babylonStandardMaterial.diffuse[" + i + "]=" + babylonStandardMaterial.diffuse[i], 3);
                }
                if (babylonStandardMaterial.diffuseTexture == null)
                {
                    RaiseVerbose("GLTFExporter.Material | babylonStandardMaterial.diffuseTexture=null", 3);
                }
                else
                {
                    RaiseVerbose("GLTFExporter.Material | babylonStandardMaterial.diffuseTexture.name=" + babylonStandardMaterial.diffuseTexture.name, 3);
                }

                // Normal / bump
                if (babylonStandardMaterial.bumpTexture == null)
                {
                    RaiseVerbose("GLTFExporter.Material | babylonStandardMaterial.bumpTexture=null", 3);
                }
                else
                {
                    RaiseVerbose("GLTFExporter.Material | babylonStandardMaterial.bumpTexture.name=" + babylonStandardMaterial.bumpTexture.name, 3);
                }

                // Opacity
                if (babylonStandardMaterial.opacityTexture == null)
                {
                    RaiseVerbose("GLTFExporter.Material | babylonStandardMaterial.opacityTexture=null", 3);
                }
                else
                {
                    RaiseVerbose("GLTFExporter.Material | babylonStandardMaterial.opacityTexture.name=" + babylonStandardMaterial.opacityTexture.name, 3);
                }

                // Specular
                for (int i = 0; i < babylonStandardMaterial.specular.Length; i++)
                {
                    RaiseVerbose("GLTFExporter.Material | babylonStandardMaterial.specular[" + i + "]=" + babylonStandardMaterial.specular[i], 3);
                }
                RaiseVerbose("GLTFExporter.Material | babylonStandardMaterial.specularPower=" + babylonStandardMaterial.specularPower, 3);
                if (babylonStandardMaterial.specularTexture == null)
                {
                    RaiseVerbose("GLTFExporter.Material | babylonStandardMaterial.specularTexture=null", 3);
                }
                else
                {
                    RaiseVerbose("GLTFExporter.Material | babylonStandardMaterial.specularTexture.name=" + babylonStandardMaterial.specularTexture.name, 3);
                }

                // Occlusion
                if (babylonStandardMaterial.ambientTexture == null)
                {
                    RaiseVerbose("GLTFExporter.Material | babylonStandardMaterial.ambientTexture=null", 3);
                }
                else
                {
                    RaiseVerbose("GLTFExporter.Material | babylonStandardMaterial.ambientTexture.name=" + babylonStandardMaterial.ambientTexture.name, 3);
                }

                // Emissive
                for (int i = 0; i < babylonStandardMaterial.emissive.Length; i++)
                {
                    RaiseVerbose("GLTFExporter.Material | babylonStandardMaterial.emissive[" + i + "]=" + babylonStandardMaterial.emissive[i], 3);
                }
                if (babylonStandardMaterial.emissiveTexture == null)
                {
                    RaiseVerbose("GLTFExporter.Material | babylonStandardMaterial.emissiveTexture=null", 3);
                }
                else
                {
                    RaiseVerbose("GLTFExporter.Material | babylonStandardMaterial.emissiveTexture.name=" + babylonStandardMaterial.emissiveTexture.name, 3);
                }
                #endregion


                // --------------------------------
                // --------- gltfMaterial ---------
                // --------------------------------

                RaiseMessage("GLTFExporter.Material | create gltfMaterial", 2);
                var gltfMaterial = new GLTFMaterial
                {
                    name = name
                };
                gltfMaterial.id    = babylonMaterial.id;
                gltfMaterial.index = gltf.MaterialsList.Count;
                gltf.MaterialsList.Add(gltfMaterial);

                // Alpha
                string alphaMode;
                float? alphaCutoff;
                getAlphaMode(babylonStandardMaterial, out alphaMode, out alphaCutoff);
                gltfMaterial.alphaMode   = alphaMode;
                gltfMaterial.alphaCutoff = alphaCutoff;

                // DoubleSided
                gltfMaterial.doubleSided = !babylonMaterial.backFaceCulling;

                // Normal
                gltfMaterial.normalTexture = ExportTexture(babylonStandardMaterial.bumpTexture, gltf);

                // Occulison
                gltfMaterial.occlusionTexture = ExportTexture(babylonStandardMaterial.ambientTexture, gltf);

                // Emissive
                gltfMaterial.emissiveFactor  = babylonStandardMaterial.emissive;
                gltfMaterial.emissiveTexture = ExportTexture(babylonStandardMaterial.emissiveTexture, gltf);

                // Constraints
                if (gltfMaterial.emissiveTexture != null)
                {
                    gltfMaterial.emissiveFactor = new[] { 1.0f, 1.0f, 1.0f };
                }

                // --------------------------------
                // --- gltfPbrMetallicRoughness ---
                // --------------------------------

                RaiseMessage("GLTFExporter.Material | create gltfPbrMetallicRoughness", 2);
                var gltfPbrMetallicRoughness = new GLTFPBRMetallicRoughness();
                gltfMaterial.pbrMetallicRoughness = gltfPbrMetallicRoughness;

                // --- Global ---

                SpecularGlossiness _specularGlossiness = new SpecularGlossiness
                {
                    diffuse    = new BabylonColor3(babylonStandardMaterial.diffuse),
                    opacity    = babylonMaterial.alpha,
                    specular   = new BabylonColor3(babylonStandardMaterial.specular),
                    glossiness = babylonStandardMaterial.specularPower / 256
                };

                MetallicRoughness _metallicRoughness = ConvertToMetallicRoughness(_specularGlossiness, true);

                // Base color
                gltfPbrMetallicRoughness.baseColorFactor = new float[4]
                {
                    _metallicRoughness.baseColor.r,
                    _metallicRoughness.baseColor.g,
                    _metallicRoughness.baseColor.b,
                    _metallicRoughness.opacity
                };

                // Metallic roughness
                gltfPbrMetallicRoughness.metallicFactor  = _metallicRoughness.metallic;
                gltfPbrMetallicRoughness.roughnessFactor = _metallicRoughness.roughness;


                // --- Textures ---
                var babylonTexture = babylonStandardMaterial.diffuseTexture != null ? babylonStandardMaterial.diffuseTexture :
                                     babylonStandardMaterial.specularTexture != null ? babylonStandardMaterial.specularTexture :
                                     babylonStandardMaterial.opacityTexture != null ? babylonStandardMaterial.opacityTexture :
                                     null;

                if (babylonTexture != null)
                {
                    bool isAlphaInTexture = (isTextureOk(babylonStandardMaterial.diffuseTexture) && babylonStandardMaterial.diffuseTexture.hasAlpha) ||
                                            isTextureOk(babylonStandardMaterial.opacityTexture);

                    Bitmap baseColorBitmap         = null;
                    Bitmap metallicRoughnessBitmap = null;

                    if (CopyTexturesToOutput)
                    {
                        // Diffuse
                        Bitmap diffuseBitmap = null;
                        if (babylonStandardMaterial.diffuseTexture != null)
                        {
                            diffuseBitmap = LoadTexture(babylonStandardMaterial.diffuseTexture.originalPath);
                        }

                        // Specular
                        Bitmap specularBitmap = null;
                        if (babylonStandardMaterial.specularTexture != null)
                        {
                            specularBitmap = LoadTexture(babylonStandardMaterial.specularTexture.originalPath);
                        }

                        // Opacity / Alpha / Transparency
                        Bitmap opacityBitmap = null;
                        if ((babylonStandardMaterial.diffuseTexture == null || babylonStandardMaterial.diffuseTexture.hasAlpha == false) && babylonStandardMaterial.opacityTexture != null)
                        {
                            opacityBitmap = LoadTexture(babylonStandardMaterial.opacityTexture.originalPath);
                        }

                        if (diffuseBitmap != null || specularBitmap != null || opacityBitmap != null)
                        {
                            // Retreive dimensions
                            int width              = 0;
                            int height             = 0;
                            var haveSameDimensions = _getMinimalBitmapDimensions(out width, out height, diffuseBitmap, specularBitmap, opacityBitmap);
                            if (!haveSameDimensions)
                            {
                                RaiseWarning("Diffuse, specular and opacity maps should have same dimensions", 2);
                            }

                            // Create baseColor+alpha and metallic+roughness maps
                            baseColorBitmap         = new Bitmap(width, height);
                            metallicRoughnessBitmap = new Bitmap(width, height);
                            for (int x = 0; x < width; x++)
                            {
                                for (int y = 0; y < height; y++)
                                {
                                    SpecularGlossiness specularGlossinessTexture = new SpecularGlossiness
                                    {
                                        diffuse = diffuseBitmap != null ? new BabylonColor3(diffuseBitmap.GetPixel(x, y)) :
                                                  _specularGlossiness.diffuse,
                                        opacity = diffuseBitmap != null && babylonStandardMaterial.diffuseTexture.hasAlpha ? diffuseBitmap.GetPixel(x, y).A / 255.0f :
                                                  opacityBitmap != null && babylonStandardMaterial.opacityTexture.getAlphaFromRGB ? opacityBitmap.GetPixel(x, y).R / 255.0f :
                                                  opacityBitmap != null && babylonStandardMaterial.opacityTexture.getAlphaFromRGB == false?opacityBitmap.GetPixel(x, y).A / 255.0f :
                                                  _specularGlossiness.opacity,
                                        specular = specularBitmap != null ? new BabylonColor3(specularBitmap.GetPixel(x, y)) :
                                                   _specularGlossiness.specular,
                                        glossiness = babylonStandardMaterial.useGlossinessFromSpecularMapAlpha && specularBitmap != null?specularBitmap.GetPixel(x, y).A / 255.0f :
                                                     _specularGlossiness.glossiness
                                    };

                                    var displayPrints = x == width / 2 && y == height / 2;
                                    MetallicRoughness metallicRoughnessTexture = ConvertToMetallicRoughness(specularGlossinessTexture, displayPrints);

                                    Color colorBase = Color.FromArgb(
                                        (int)(metallicRoughnessTexture.opacity * 255),
                                        (int)(metallicRoughnessTexture.baseColor.r * 255),
                                        (int)(metallicRoughnessTexture.baseColor.g * 255),
                                        (int)(metallicRoughnessTexture.baseColor.b * 255)
                                        );
                                    baseColorBitmap.SetPixel(x, y, colorBase);

                                    // The metalness values are sampled from the B channel.
                                    // The roughness values are sampled from the G channel.
                                    // These values are linear. If other channels are present (R or A), they are ignored for metallic-roughness calculations.
                                    Color colorMetallicRoughness = Color.FromArgb(
                                        0,
                                        (int)(metallicRoughnessTexture.roughness * 255),
                                        (int)(metallicRoughnessTexture.metallic * 255)
                                        );
                                    metallicRoughnessBitmap.SetPixel(x, y, colorMetallicRoughness);
                                }
                            }
                        }
                    }

                    // Export maps and textures
                    var baseColorFileName = babylonMaterial.name + "_baseColor" + (isAlphaInTexture ? ".png" : ".jpg");
                    gltfPbrMetallicRoughness.baseColorTexture = ExportBitmapTexture(gltf, babylonTexture, baseColorBitmap, baseColorFileName);
                    if (isTextureOk(babylonStandardMaterial.specularTexture))
                    {
                        gltfPbrMetallicRoughness.metallicRoughnessTexture = ExportBitmapTexture(gltf, babylonTexture, metallicRoughnessBitmap, babylonMaterial.name + "_metallicRoughness" + ".jpg");
                    }

                    // Constraints
                    if (gltfPbrMetallicRoughness.baseColorTexture != null)
                    {
                        gltfPbrMetallicRoughness.baseColorFactor = new[] { 1.0f, 1.0f, 1.0f, 1.0f };
                    }

                    if (gltfPbrMetallicRoughness.metallicRoughnessTexture != null)
                    {
                        gltfPbrMetallicRoughness.metallicFactor  = 1.0f;
                        gltfPbrMetallicRoughness.roughnessFactor = 1.0f;
                    }
                }
            }
            else if (babylonMaterial.GetType() == typeof(BabylonPBRMetallicRoughnessMaterial))
            {
                var babylonPBRMetallicRoughnessMaterial = babylonMaterial as BabylonPBRMetallicRoughnessMaterial;


                // --- prints ---
                #region prints

                RaiseVerbose("GLTFExporter.Material | babylonMaterial data", 2);
                RaiseVerbose("GLTFExporter.Material | babylonMaterial.alpha=" + babylonMaterial.alpha, 3);
                RaiseVerbose("GLTFExporter.Material | babylonMaterial.alphaMode=" + babylonMaterial.alphaMode, 3);
                RaiseVerbose("GLTFExporter.Material | babylonMaterial.backFaceCulling=" + babylonMaterial.backFaceCulling, 3);
                RaiseVerbose("GLTFExporter.Material | babylonMaterial.wireframe=" + babylonMaterial.wireframe, 3);

                // Global
                RaiseVerbose("GLTFExporter.Material | babylonPBRMetallicRoughnessMaterial.maxSimultaneousLights=" + babylonPBRMetallicRoughnessMaterial.maxSimultaneousLights, 3);
                RaiseVerbose("GLTFExporter.Material | babylonPBRMetallicRoughnessMaterial.disableLighting=" + babylonPBRMetallicRoughnessMaterial.disableLighting, 3);
                RaiseVerbose("GLTFExporter.Material | babylonPBRMetallicRoughnessMaterial.alphaCutOff=" + babylonPBRMetallicRoughnessMaterial.alphaCutOff, 3);
                RaiseVerbose("GLTFExporter.Material | babylonPBRMetallicRoughnessMaterial.transparencyMode=" + babylonPBRMetallicRoughnessMaterial.transparencyMode, 3);
                RaiseVerbose("GLTFExporter.Material | babylonPBRMetallicRoughnessMaterial.doubleSided=" + babylonPBRMetallicRoughnessMaterial.doubleSided, 3);

                // Base color
                RaiseVerbose("GLTFExporter.Material | babylonPBRMetallicRoughnessMaterial.baseColor.Length=" + babylonPBRMetallicRoughnessMaterial.baseColor.Length, 3);
                for (int i = 0; i < babylonPBRMetallicRoughnessMaterial.baseColor.Length; i++)
                {
                    RaiseVerbose("GLTFExporter.Material | babylonPBRMetallicRoughnessMaterial.baseColor[" + i + "]=" + babylonPBRMetallicRoughnessMaterial.baseColor[i], 3);
                }
                if (babylonPBRMetallicRoughnessMaterial.baseTexture == null)
                {
                    RaiseVerbose("GLTFExporter.Material | babylonPBRMetallicRoughnessMaterial.baseTexture=null", 3);
                }

                // Metallic+roughness
                RaiseVerbose("GLTFExporter.Material | babylonPBRMetallicRoughnessMaterial.metallic=" + babylonPBRMetallicRoughnessMaterial.metallic, 3);
                RaiseVerbose("GLTFExporter.Material | babylonPBRMetallicRoughnessMaterial.roughness=" + babylonPBRMetallicRoughnessMaterial.roughness, 3);
                if (babylonPBRMetallicRoughnessMaterial.metallicRoughnessTexture == null)
                {
                    RaiseVerbose("GLTFExporter.Material | babylonPBRMetallicRoughnessMaterial.metallicRoughnessTexture=null", 3);
                }

                // Normal / bump
                if (babylonPBRMetallicRoughnessMaterial.normalTexture == null)
                {
                    RaiseVerbose("GLTFExporter.Material | babylonPBRMetallicRoughnessMaterial.normalTexture=null", 3);
                }
                RaiseVerbose("GLTFExporter.Material | babylonPBRMetallicRoughnessMaterial.invertNormalMapX=" + babylonPBRMetallicRoughnessMaterial.invertNormalMapX, 3);
                RaiseVerbose("GLTFExporter.Material | babylonPBRMetallicRoughnessMaterial.invertNormalMapY=" + babylonPBRMetallicRoughnessMaterial.invertNormalMapY, 3);

                // Emissive
                for (int i = 0; i < babylonPBRMetallicRoughnessMaterial.emissive.Length; i++)
                {
                    RaiseVerbose("GLTFExporter.Material | babylonPBRMetallicRoughnessMaterial.emissiveColor[" + i + "]=" + babylonPBRMetallicRoughnessMaterial.emissive[i], 3);
                }
                if (babylonPBRMetallicRoughnessMaterial.emissiveTexture == null)
                {
                    RaiseVerbose("GLTFExporter.Material | babylonPBRMetallicRoughnessMaterial.emissiveTexture=null", 3);
                }

                // Ambient occlusion
                RaiseVerbose("GLTFExporter.Material | babylonPBRMetallicRoughnessMaterial.occlusionStrength=" + babylonPBRMetallicRoughnessMaterial.occlusionStrength, 3);
                if (babylonPBRMetallicRoughnessMaterial.occlusionTexture == null)
                {
                    RaiseVerbose("GLTFExporter.Material | babylonPBRMetallicRoughnessMaterial.occlusionTexture=null", 3);
                }
                #endregion


                // --------------------------------
                // --------- gltfMaterial ---------
                // --------------------------------

                RaiseMessage("GLTFExporter.Material | create gltfMaterial", 2);
                var gltfMaterial = new GLTFMaterial
                {
                    name = name
                };
                gltfMaterial.id    = babylonMaterial.id;
                gltfMaterial.index = gltf.MaterialsList.Count;
                gltf.MaterialsList.Add(gltfMaterial);

                // Alpha
                string alphaMode;
                float? alphaCutoff;
                getAlphaMode(babylonPBRMetallicRoughnessMaterial, out alphaMode, out alphaCutoff);
                gltfMaterial.alphaMode   = alphaMode;
                gltfMaterial.alphaCutoff = alphaCutoff;

                // DoubleSided
                gltfMaterial.doubleSided = babylonPBRMetallicRoughnessMaterial.doubleSided;

                // Normal
                gltfMaterial.normalTexture = ExportTexture(babylonPBRMetallicRoughnessMaterial.normalTexture, gltf);

                // Occulison
                gltfMaterial.occlusionTexture = ExportTexture(babylonPBRMetallicRoughnessMaterial.occlusionTexture, gltf);

                // Emissive
                gltfMaterial.emissiveFactor  = babylonPBRMetallicRoughnessMaterial.emissive;
                gltfMaterial.emissiveTexture = ExportTexture(babylonPBRMetallicRoughnessMaterial.emissiveTexture, gltf);


                // --------------------------------
                // --- gltfPbrMetallicRoughness ---
                // --------------------------------

                RaiseMessage("GLTFExporter.Material | create gltfPbrMetallicRoughness", 2);
                var gltfPbrMetallicRoughness = new GLTFPBRMetallicRoughness();
                gltfMaterial.pbrMetallicRoughness = gltfPbrMetallicRoughness;

                // --- Global ---

                // Base color
                gltfPbrMetallicRoughness.baseColorFactor = new float[4]
                {
                    babylonPBRMetallicRoughnessMaterial.baseColor[0],
                    babylonPBRMetallicRoughnessMaterial.baseColor[1],
                    babylonPBRMetallicRoughnessMaterial.baseColor[2],
                    babylonPBRMetallicRoughnessMaterial.alpha
                };
                gltfPbrMetallicRoughness.baseColorTexture = ExportBitmapTexture(gltf, babylonPBRMetallicRoughnessMaterial.baseTexture);

                // Metallic roughness
                gltfPbrMetallicRoughness.metallicFactor           = babylonPBRMetallicRoughnessMaterial.metallic;
                gltfPbrMetallicRoughness.roughnessFactor          = babylonPBRMetallicRoughnessMaterial.roughness;
                gltfPbrMetallicRoughness.metallicRoughnessTexture = ExportBitmapTexture(gltf, babylonPBRMetallicRoughnessMaterial.metallicRoughnessTexture);
            }
            else
            {
                RaiseWarning("GLTFExporter.Material | Unsupported material type: " + babylonMaterial.GetType(), 2);
            }
        }
Пример #4
0
        private void ExportMaterial(IIGameMaterial materialNode, BabylonScene babylonScene)
        {
            var name = materialNode.MaterialName;
            var id   = materialNode.MaxMaterial.GetGuid().ToString();

            // Check if the material was already exported. The material id is unique.
            if (babylonScene.MaterialsList.FirstOrDefault(m => m.id == id) != null)
            {
                return;
            }

            RaiseMessage(name, 1);

            // --- prints ---
            #region prints
            {
                RaiseVerbose("materialNode.MaterialClass=" + materialNode.MaterialClass, 2);
                RaiseVerbose("materialNode.NumberOfTextureMaps=" + materialNode.NumberOfTextureMaps, 2);

                var propertyContainer = materialNode.IPropertyContainer;
                RaiseVerbose("propertyContainer=" + propertyContainer, 2);
                if (propertyContainer != null)
                {
                    RaiseVerbose("propertyContainer.NumberOfProperties=" + propertyContainer.NumberOfProperties, 3);
                    for (int i = 0; i < propertyContainer.NumberOfProperties; i++)
                    {
                        var prop = propertyContainer.GetProperty(i);
                        if (prop != null)
                        {
                            RaiseVerbose("propertyContainer.GetProperty(" + i + ")=" + prop.Name, 3);
                            switch (prop.GetType_)
                            {
                            case PropType.StringProp:
                                string propertyString = "";
                                RaiseVerbose("prop.GetPropertyValue(ref propertyString, 0)=" + prop.GetPropertyValue(ref propertyString, 0), 4);
                                RaiseVerbose("propertyString=" + propertyString, 4);
                                break;

                            case PropType.IntProp:
                                int propertyInt = 0;
                                RaiseVerbose("prop.GetPropertyValue(ref propertyInt, 0)=" + prop.GetPropertyValue(ref propertyInt, 0), 4);
                                RaiseVerbose("propertyInt=" + propertyInt, 4);
                                break;

                            case PropType.FloatProp:
                                float propertyFloat = 0;
                                RaiseVerbose("prop.GetPropertyValue(ref propertyFloat, 0, true)=" + prop.GetPropertyValue(ref propertyFloat, 0, true), 4);
                                RaiseVerbose("propertyFloat=" + propertyFloat, 4);
                                RaiseVerbose("prop.GetPropertyValue(ref propertyFloat, 0, false)=" + prop.GetPropertyValue(ref propertyFloat, 0, false), 4);
                                RaiseVerbose("propertyFloat=" + propertyFloat, 4);
                                break;

                            case PropType.Point3Prop:
                                IPoint3 propertyPoint3 = Loader.Global.Point3.Create(0, 0, 0);
                                RaiseVerbose("prop.GetPropertyValue(ref propertyPoint3, 0)=" + prop.GetPropertyValue(propertyPoint3, 0), 4);
                                RaiseVerbose("propertyPoint3=" + Point3ToString(propertyPoint3), 4);
                                break;

                            case PropType.Point4Prop:
                                IPoint4 propertyPoint4 = Loader.Global.Point4.Create(0, 0, 0, 0);
                                RaiseVerbose("prop.GetPropertyValue(ref propertyPoint4, 0)=" + prop.GetPropertyValue(propertyPoint4, 0), 4);
                                RaiseVerbose("propertyPoint4=" + Point4ToString(propertyPoint4), 4);
                                break;

                            case PropType.UnknownProp:
                            default:
                                RaiseVerbose("Unknown property type", 4);
                                break;
                            }
                        }
                        else
                        {
                            RaiseVerbose("propertyContainer.GetProperty(" + i + ") IS NULL", 3);
                        }
                    }
                }
            }
            #endregion

            if (materialNode.SubMaterialCount > 0)
            {
                var babylonMultimaterial = new BabylonMultiMaterial {
                    name = name, id = id
                };

                var guids = new List <string>();

                for (var index = 0; index < materialNode.SubMaterialCount; index++)
                {
                    var subMat = materialNode.GetSubMaterial(index);

                    if (subMat != null)
                    {
                        if (subMat.SubMaterialCount > 0)
                        {
                            RaiseError("MultiMaterials as inputs to other MultiMaterials are not supported!");
                        }
                        else
                        {
                            guids.Add(subMat.MaxMaterial.GetGuid().ToString());

                            if (!referencedMaterials.Contains(subMat))
                            {
                                referencedMaterials.Add(subMat);
                                ExportMaterial(subMat, babylonScene);
                            }
                        }
                    }
                    else
                    {
                        guids.Add(Guid.Empty.ToString());
                    }
                }

                babylonMultimaterial.materials = guids.ToArray();

                babylonScene.MultiMaterialsList.Add(babylonMultimaterial);
                return;
            }

            var  unlitProperty = materialNode.IPropertyContainer.QueryProperty("BabylonUnlit");
            bool isUnlit       = unlitProperty != null?unlitProperty.GetBoolValue() : false;

            // check custom exporters first, to allow custom exporters of supported material classes
            materialExporters.TryGetValue(new ClassIDWrapper(materialNode.MaxMaterial.ClassID), out IMaterialExporter materialExporter);


            var stdMat = materialNode.MaxMaterial.NumParamBlocks > 0 ? materialNode.MaxMaterial.GetParamBlock(0).Owner as IStdMat2 : null;

            if (isBabylonExported && materialExporter != null && materialExporter is IBabylonMaterialExporter)
            {
                IBabylonMaterialExporter babylonMaterialExporter = materialExporter as IBabylonMaterialExporter;
                BabylonMaterial          babylonMaterial         = babylonMaterialExporter.ExportBabylonMaterial(materialNode);
                if (babylonMaterial == null)
                {
                    string message = string.Format("Custom Babylon material exporter failed to export | Exporter: '{0}' | Material Name: '{1}' | Material Class: '{2}'",
                                                   babylonMaterialExporter.GetType().ToString(), materialNode.MaterialName, materialNode.MaterialClass);
                    RaiseWarning(message, 2);
                }
                else
                {
                    babylonScene.MaterialsList.Add(babylonMaterial);
                }
            }
            else if (isGltfExported && materialExporter != null && materialExporter is IGLTFMaterialExporter)
            {
                // add a basic babylon material to the list to forward the max material reference
                var babylonMaterial = new BabylonMaterial(id)
                {
                    maxGameMaterial = materialNode,
                    name            = name
                };
                babylonScene.MaterialsList.Add(babylonMaterial);
            }
            else if (stdMat != null)
            {
                var babylonMaterial = new BabylonStandardMaterial(id)
                {
                    maxGameMaterial = materialNode,
                    name            = name,
                    isUnlit         = isUnlit,
                    diffuse         = materialNode.MaxMaterial.GetDiffuse(0, false).ToArray(),
                    alpha           = 1.0f - materialNode.MaxMaterial.GetXParency(0, false)
                };

                babylonMaterial.backFaceCulling = !stdMat.TwoSided;
                babylonMaterial.wireframe       = stdMat.Wire;

                var isSelfIllumColor = materialNode.MaxMaterial.GetSelfIllumColorOn(0, false);
                var maxSpecularColor = materialNode.MaxMaterial.GetSpecular(0, false).ToArray();

                if (isUnlit == false)
                {
                    babylonMaterial.ambient       = materialNode.MaxMaterial.GetAmbient(0, false).ToArray();
                    babylonMaterial.specular      = maxSpecularColor.Multiply(materialNode.MaxMaterial.GetShinStr(0, false));
                    babylonMaterial.specularPower = materialNode.MaxMaterial.GetShininess(0, false) * 256;
                    babylonMaterial.emissive      =
                        isSelfIllumColor
                            ? materialNode.MaxMaterial.GetSelfIllumColor(0, false).ToArray()
                            : materialNode.MaxMaterial.GetDiffuse(0, false).Scale(materialNode.MaxMaterial.GetSelfIllum(0, false)); // compute the pre-multiplied emissive color

                    // If Self-Illumination color checkbox is checked
                    // Then self-illumination is assumed to be pre-multiplied
                    // Otherwise self-illumination needs to be multiplied with diffuse
                    // linkEmissiveWithDiffuse attribute tells the Babylon engine to perform such multiplication
                    babylonMaterial.linkEmissiveWithDiffuse = !isSelfIllumColor;
                    // useEmissiveAsIllumination attribute tells the Babylon engine to use pre-multiplied emissive as illumination
                    babylonMaterial.useEmissiveAsIllumination = isSelfIllumColor;

                    // Store the emissive value (before multiplication) for gltf
                    babylonMaterial.selfIllum = materialNode.MaxMaterial.GetSelfIllum(0, false);
                }

                // Textures

                BabylonFresnelParameters fresnelParameters;
                babylonMaterial.diffuseTexture = ExportTexture(stdMat, 1, out fresnelParameters, babylonScene);                // Diffuse
                if (fresnelParameters != null)
                {
                    babylonMaterial.diffuseFresnelParameters = fresnelParameters;
                }
                if ((babylonMaterial.alpha == 1.0f && babylonMaterial.opacityTexture == null) &&
                    babylonMaterial.diffuseTexture != null &&
                    (babylonMaterial.diffuseTexture.originalPath.EndsWith(".tif") || babylonMaterial.diffuseTexture.originalPath.EndsWith(".tiff")) &&
                    babylonMaterial.diffuseTexture.hasAlpha)
                {
                    RaiseWarning($"Diffuse texture named {babylonMaterial.diffuseTexture.originalPath} is a .tif file and its Alpha Source is 'Image Alpha' by default.", 2);
                    RaiseWarning($"If you don't want material to be in BLEND mode, set diffuse texture Alpha Source to 'None (Opaque)'", 2);
                }

                babylonMaterial.opacityTexture = ExportTexture(stdMat, 6, out fresnelParameters, babylonScene, false, true);   // Opacity
                if (fresnelParameters != null)
                {
                    babylonMaterial.opacityFresnelParameters = fresnelParameters;
                    if (babylonMaterial.alpha == 1 &&
                        babylonMaterial.opacityTexture == null)
                    {
                        babylonMaterial.alpha = 0;
                    }
                }

                if (isUnlit == false)
                {
                    babylonMaterial.ambientTexture = ExportTexture(stdMat, 0, out fresnelParameters, babylonScene);                // Ambient

                    babylonMaterial.specularTexture = ExportSpecularTexture(materialNode, maxSpecularColor, babylonScene);

                    babylonMaterial.emissiveTexture = ExportTexture(stdMat, 5, out fresnelParameters, babylonScene);               // Emissive
                    if (fresnelParameters != null)
                    {
                        babylonMaterial.emissiveFresnelParameters = fresnelParameters;
                        if (babylonMaterial.emissive[0] == 0 &&
                            babylonMaterial.emissive[1] == 0 &&
                            babylonMaterial.emissive[2] == 0 &&
                            babylonMaterial.emissiveTexture == null)
                        {
                            babylonMaterial.emissive = new float[] { 1, 1, 1 };
                        }
                    }

                    babylonMaterial.bumpTexture       = ExportTexture(stdMat, 8, out fresnelParameters, babylonScene);             // Bump
                    babylonMaterial.reflectionTexture = ExportTexture(stdMat, 9, out fresnelParameters, babylonScene, true);       // Reflection
                    if (fresnelParameters != null)
                    {
                        if (babylonMaterial.reflectionTexture == null)
                        {
                            RaiseWarning("Fallout cannot be used with reflection channel without a texture", 2);
                        }
                        else
                        {
                            babylonMaterial.reflectionFresnelParameters = fresnelParameters;
                        }
                    }
                }

                // Constraints
                if (babylonMaterial.diffuseTexture != null)
                {
                    babylonMaterial.diffuse = new[] { 1.0f, 1.0f, 1.0f };
                }

                if (babylonMaterial.emissiveTexture != null)
                {
                    babylonMaterial.emissive = new float[] { 0, 0, 0 };
                }

                if (babylonMaterial.opacityTexture != null && babylonMaterial.diffuseTexture != null &&
                    babylonMaterial.diffuseTexture.name == babylonMaterial.opacityTexture.name &&
                    babylonMaterial.diffuseTexture.hasAlpha && !babylonMaterial.opacityTexture.getAlphaFromRGB)
                {
                    // This is a alpha testing purpose
                    babylonMaterial.opacityTexture          = null;
                    babylonMaterial.diffuseTexture.hasAlpha = true;
                    RaiseWarning("Opacity texture was removed because alpha from diffuse texture can be use instead", 2);
                    RaiseWarning("If you do not want this behavior, just set Alpha Source = None on your diffuse texture", 2);
                }

                babylonScene.MaterialsList.Add(babylonMaterial);
            }
            else if (isPhysicalMaterial(materialNode))
            {
                var propertyContainer = materialNode.IPropertyContainer;

                var babylonMaterial = new BabylonPBRMetallicRoughnessMaterial(id)
                {
                    maxGameMaterial = materialNode,
                    name            = name,
                    isUnlit         = isUnlit
                };

                // --- Global ---

                // Alpha
                //var alphaFromXParency = 1.0f - materialNode.MaxMaterial.GetXParency(0, false);
                var alphaFromPropertyContainer = 1.0f - propertyContainer.GetFloatProperty(17);
                //RaiseMessage("alphaFromXParency=" + alphaFromXParency, 2);
                //RaiseMessage("alphaFromPropertyContainer=" + alphaFromPropertyContainer, 2);
                babylonMaterial.alpha = alphaFromPropertyContainer;

                babylonMaterial.baseColor = materialNode.MaxMaterial.GetDiffuse(0, false).ToArray();

                var invertRoughness = propertyContainer.GetBoolProperty(5);
                if (isUnlit == false)
                {
                    babylonMaterial.metallic = propertyContainer.GetFloatProperty(6);

                    babylonMaterial.roughness = propertyContainer.GetFloatProperty(4);
                    if (invertRoughness)
                    {
                        // Inverse roughness
                        babylonMaterial.roughness = 1 - babylonMaterial.roughness;
                    }

                    // Self illumination is computed from emission color, luminance, temperature and weight
                    babylonMaterial.emissive = materialNode.MaxMaterial.GetSelfIllumColorOn(0, false)
                                                    ? materialNode.MaxMaterial.GetSelfIllumColor(0, false).ToArray()
                                                    : materialNode.MaxMaterial.GetDiffuse(0, false).Scale(materialNode.MaxMaterial.GetSelfIllum(0, false));
                }
                else
                {
                    // Ignore specified roughness and metallic values
                    babylonMaterial.metallic  = 0;
                    babylonMaterial.roughness = 0.9f;
                }

                // --- Textures ---
                // 1 - base color ; 9 - transparancy weight
                ITexmap colorTexmap = _getTexMap(materialNode, 1);
                ITexmap alphaTexmap = _getTexMap(materialNode, 9);
                babylonMaterial.baseTexture = ExportBaseColorAlphaTexture(colorTexmap, alphaTexmap, babylonMaterial.baseColor, babylonMaterial.alpha, babylonScene, name);

                if (isUnlit == false)
                {
                    // Metallic, roughness, ambient occlusion
                    ITexmap metallicTexmap         = _getTexMap(materialNode, 5);
                    ITexmap roughnessTexmap        = _getTexMap(materialNode, 4);
                    ITexmap ambientOcclusionTexmap = _getTexMap(materialNode, 6); // Use diffuse roughness map as ambient occlusion

                    // Check if MR or ORM textures are already merged
                    bool areTexturesAlreadyMerged = false;
                    if (metallicTexmap != null && roughnessTexmap != null)
                    {
                        string sourcePathMetallic  = getSourcePath(metallicTexmap);
                        string sourcePathRoughness = getSourcePath(roughnessTexmap);

                        if (sourcePathMetallic == sourcePathRoughness)
                        {
                            if (ambientOcclusionTexmap != null && exportParameters.mergeAOwithMR)
                            {
                                string sourcePathAmbientOcclusion = getSourcePath(ambientOcclusionTexmap);
                                if (sourcePathMetallic == sourcePathAmbientOcclusion)
                                {
                                    // Metallic, roughness and ambient occlusion are already merged
                                    RaiseVerbose("Metallic, roughness and ambient occlusion are already merged", 2);
                                    BabylonTexture ormTexture = ExportTexture(metallicTexmap, babylonScene);
                                    babylonMaterial.metallicRoughnessTexture = ormTexture;
                                    babylonMaterial.occlusionTexture         = ormTexture;
                                    areTexturesAlreadyMerged = true;
                                }
                            }
                            else
                            {
                                // Metallic and roughness are already merged
                                RaiseVerbose("Metallic and roughness are already merged", 2);
                                BabylonTexture ormTexture = ExportTexture(metallicTexmap, babylonScene);
                                babylonMaterial.metallicRoughnessTexture = ormTexture;
                                areTexturesAlreadyMerged = true;
                            }
                        }
                    }
                    if (areTexturesAlreadyMerged == false)
                    {
                        if (metallicTexmap != null || roughnessTexmap != null)
                        {
                            // Merge metallic, roughness and ambient occlusion
                            RaiseVerbose("Merge metallic and roughness (and ambient occlusion if `mergeAOwithMR` is enabled)", 2);
                            BabylonTexture ormTexture = ExportORMTexture(exportParameters.mergeAOwithMR ? ambientOcclusionTexmap : null, roughnessTexmap, metallicTexmap, babylonMaterial.metallic, babylonMaterial.roughness, babylonScene, invertRoughness);
                            babylonMaterial.metallicRoughnessTexture = ormTexture;

                            if (ambientOcclusionTexmap != null)
                            {
                                if (exportParameters.mergeAOwithMR)
                                {
                                    // if the ambient occlusion texture map uses a different set of texture coordinates than
                                    // metallic roughness, create a new instance of the ORM BabylonTexture with the different texture
                                    // coordinate indices
                                    var ambientOcclusionTexture = _getBitmapTex(ambientOcclusionTexmap);
                                    var texCoordIndex           = ambientOcclusionTexture.UVGen.MapChannel - 1;
                                    if (texCoordIndex != ormTexture.coordinatesIndex)
                                    {
                                        babylonMaterial.occlusionTexture = new BabylonTexture(ormTexture);
                                        babylonMaterial.occlusionTexture.coordinatesIndex = texCoordIndex;
                                        // Set UVs/texture transform for the ambient occlusion texture
                                        var uvGen = _exportUV(ambientOcclusionTexture.UVGen, babylonMaterial.occlusionTexture);
                                    }
                                    else
                                    {
                                        babylonMaterial.occlusionTexture = ormTexture;
                                    }
                                }
                                else
                                {
                                    babylonMaterial.occlusionTexture = ExportPBRTexture(materialNode, 6, babylonScene);
                                }
                            }
                        }
                        else if (ambientOcclusionTexmap != null)
                        {
                            // Simply export occlusion texture
                            RaiseVerbose("Simply export occlusion texture", 2);
                            babylonMaterial.occlusionTexture = ExportTexture(ambientOcclusionTexmap, babylonScene);
                        }
                    }
                    if (ambientOcclusionTexmap != null && !exportParameters.mergeAOwithMR && babylonMaterial.occlusionTexture == null)
                    {
                        RaiseVerbose("Exporting occlusion texture without merging with metallic roughness", 2);
                        babylonMaterial.occlusionTexture = ExportTexture(ambientOcclusionTexmap, babylonScene);
                    }

                    var normalMapAmount = propertyContainer.GetFloatProperty(91);
                    babylonMaterial.normalTexture = ExportPBRTexture(materialNode, 30, babylonScene, normalMapAmount);

                    babylonMaterial.emissiveTexture = ExportPBRTexture(materialNode, 17, babylonScene);
                }


                if (babylonMaterial.alpha != 1.0f || (babylonMaterial.baseTexture != null && babylonMaterial.baseTexture.hasAlpha))
                {
                    var  alphaTestProperty = materialNode.IPropertyContainer.QueryProperty("BabylonAlphaTest");
                    bool isAlphaTest       = alphaTestProperty != null?alphaTestProperty.GetBoolValue() : false;

                    babylonMaterial.transparencyMode = isAlphaTest ? (int)BabylonPBRMetallicRoughnessMaterial.TransparencyMode.ALPHATEST : (int)BabylonPBRMetallicRoughnessMaterial.TransparencyMode.ALPHABLEND;
                }

                if (babylonMaterial.emissiveTexture != null)
                {
                    babylonMaterial.emissive = new[] { 1.0f, 1.0f, 1.0f };
                }

                if (babylonMaterial.metallicRoughnessTexture != null)
                {
                    babylonMaterial.metallic  = 1.0f;
                    babylonMaterial.roughness = 1.0f;
                }

                babylonScene.MaterialsList.Add(babylonMaterial);
            }
            else if (isArnoldMaterial(materialNode))
            {
                var propertyContainer = materialNode.IPropertyContainer;
                var babylonMaterial   = new BabylonPBRMetallicRoughnessMaterial(id)
                {
                    name    = name,
                    isUnlit = isUnlit
                };

                // Alpha
                babylonMaterial.alpha = 1.0f - propertyContainer.GetFloatProperty(32);

                // Color: base * weight
                float[] baseColor  = propertyContainer.GetPoint3Property(5).ToArray();
                float   baseWeight = propertyContainer.GetFloatProperty(2);
                babylonMaterial.baseColor = baseColor.Multiply(baseWeight);

                // Metallic & roughness
                bool invertRoughness = false;
                babylonMaterial.roughness = propertyContainer.GetFloatProperty(17); // specular_roughness
                babylonMaterial.metallic  = propertyContainer.GetFloatProperty(29);

                // Emissive: emission_color * emission
                float[] emissionColor  = propertyContainer.QueryProperty("emission_color").GetPoint3Property().ToArray();
                float   emissionWeight = propertyContainer.QueryProperty("emission").GetFloatValue();
                if (emissionColor != null && emissionWeight > 0f)
                {
                    babylonMaterial.emissive = emissionColor.Multiply(emissionWeight);
                }

                // --- Textures ---
                // 1 - base_color ; 5 - specular_roughness ; 9 - metalness ; 10 - transparent
                ITexmap colorTexmap = _getTexMap(materialNode, 1);
                ITexmap alphaTexmap = _getTexMap(materialNode, 10);
                babylonMaterial.baseTexture = ExportBaseColorAlphaTexture(colorTexmap, alphaTexmap, babylonMaterial.baseColor, babylonMaterial.alpha, babylonScene, name);

                if (isUnlit == false)
                {
                    // Metallic, roughness
                    ITexmap metallicTexmap         = _getTexMap(materialNode, 9);
                    ITexmap roughnessTexmap        = _getTexMap(materialNode, 5);
                    ITexmap ambientOcclusionTexmap = _getTexMap(materialNode, 6); // Use diffuse roughness map as ambient occlusion

                    // Check if MR textures are already merged
                    bool areTexturesAlreadyMerged = false;
                    if (metallicTexmap != null && roughnessTexmap != null)
                    {
                        string sourcePathMetallic  = getSourcePath(metallicTexmap);
                        string sourcePathRoughness = getSourcePath(roughnessTexmap);

                        if (sourcePathMetallic == sourcePathRoughness)
                        {
                            // Metallic and roughness are already merged
                            RaiseVerbose("Metallic and roughness are already merged", 2);
                            BabylonTexture ormTexture = ExportTexture(metallicTexmap, babylonScene);
                            babylonMaterial.metallicRoughnessTexture = ormTexture;
                            // The already merged map is assumed to contain Ambient Occlusion in R channel

                            if (ambientOcclusionTexmap != null)
                            {
                                // if the ambient occlusion texture map uses a different set of texture coordinates than
                                // metallic roughness, create a new instance of the ORM BabylonTexture with the different texture
                                // coordinate indices

                                var ambientOcclusionTexture = _getBitmapTex(ambientOcclusionTexmap);
                                var texCoordIndex           = ambientOcclusionTexture.UVGen.MapChannel - 1;
                                if (texCoordIndex != ormTexture.coordinatesIndex)
                                {
                                    babylonMaterial.occlusionTexture = new BabylonTexture(ormTexture);
                                    babylonMaterial.occlusionTexture.coordinatesIndex = texCoordIndex;
                                    // Set UVs/texture transform for the ambient occlusion texture
                                    var uvGen = _exportUV(ambientOcclusionTexture.UVGen, babylonMaterial.occlusionTexture);
                                }
                                else
                                {
                                    babylonMaterial.occlusionTexture = ormTexture;
                                }
                            }
                            else
                            {
                                babylonMaterial.occlusionTexture = ormTexture;
                            }
                            areTexturesAlreadyMerged = true;
                        }
                    }
                    if (areTexturesAlreadyMerged == false)
                    {
                        if (metallicTexmap != null || roughnessTexmap != null)
                        {
                            // Merge metallic, roughness
                            RaiseVerbose("Merge metallic and roughness", 2);
                            BabylonTexture ormTexture = ExportORMTexture(null, roughnessTexmap, metallicTexmap, babylonMaterial.metallic, babylonMaterial.roughness, babylonScene, invertRoughness);
                            babylonMaterial.metallicRoughnessTexture = ormTexture;
                        }
                    }

                    var numOfTexMapSlots = materialNode.MaxMaterial.NumSubTexmaps;

                    for (int i = 0; i < numOfTexMapSlots; i++)
                    {
                        if (materialNode.MaxMaterial.GetSubTexmapSlotName(i) == "normal")
                        {
                            babylonMaterial.normalTexture = ExportPBRTexture(materialNode, i, babylonScene);
                        }

                        else if (materialNode.MaxMaterial.GetSubTexmapSlotName(i) == "emission")
                        {
                            babylonMaterial.emissiveTexture = ExportPBRTexture(materialNode, i, babylonScene);
                        }
                    }
                }

                // Constraints
                if (babylonMaterial.baseTexture != null)
                {
                    babylonMaterial.baseColor = new[] { 1.0f, 1.0f, 1.0f };
                    babylonMaterial.alpha     = 1.0f;
                }

                if (babylonMaterial.alpha != 1.0f || (babylonMaterial.baseTexture != null && babylonMaterial.baseTexture.hasAlpha))
                {
                    babylonMaterial.transparencyMode = (int)BabylonPBRMetallicRoughnessMaterial.TransparencyMode.ALPHABLEND;
                }

                if (babylonMaterial.metallicRoughnessTexture != null)
                {
                    babylonMaterial.metallic  = 1.0f;
                    babylonMaterial.roughness = 1.0f;
                }

                // Add the material to the scene
                babylonScene.MaterialsList.Add(babylonMaterial);
            }
            else
            {
                // isMaterialExportable check should prevent this to happen
                RaiseError("Unsupported material type: " + materialNode.MaterialClass, 2);
            }
        }
Пример #5
0
        private void AddParameterSamplerAnimation(BabylonMaterial babylonMaterial, GLTFAnimation gltfAnimation, GLTFExporter exporter, GLTF gltf, int startFrame, int endFrame)
        {
            var samplerList = gltfAnimation.SamplerList;
            // Combine babylon animations from .babylon file and cached ones
            var babylonAnimations = new List <BabylonAnimation>();

            if (babylonMaterial.animations != null)
            {
                babylonAnimations.AddRange(babylonMaterial.animations);
            }

            if (babylonAnimations.Count > 0)
            {
                if (babylonAnimations.Count > 0)
                {
                    exporter.logger.RaiseMessage("GLTFExporter.Animation | Export animations of node named: " + babylonMaterial.name, 2);
                }


                foreach (BabylonAnimation babylonAnimation in babylonAnimations)
                {
                    var babylonAnimationKeysInRange = babylonAnimation.keys.Where(key => key.frame >= startFrame && key.frame <= endFrame);
                    if (babylonAnimationKeysInRange.Count() <= 0)
                    {
                        continue;
                    }

                    string target_path = babylonAnimation.property;

                    // --- Input ---
                    var accessorInput = exporter._createAndPopulateInput(gltf, babylonAnimation, startFrame, endFrame);
                    if (accessorInput == null)
                    {
                        continue;
                    }

                    // --- Output ---
                    GLTFAccessor accessorOutput = FlightSimAsoboPropertyAnimationExtension._createAccessorOfProperty(target_path, gltf);
                    if (accessorOutput == null)
                    {
                        continue;
                    }

                    // Populate accessor
                    int numKeys = 0;
                    foreach (var babylonAnimationKey in babylonAnimationKeysInRange)
                    {
                        numKeys++;

                        // copy data before changing it in case animation groups overlap
                        float[] outputValues = new float[babylonAnimationKey.values.Length];
                        babylonAnimationKey.values.CopyTo(outputValues, 0);

                        // Store values as bytes
                        foreach (var outputValue in outputValues)
                        {
                            accessorOutput.bytesList.AddRange(BitConverter.GetBytes(outputValue));
                        }
                    }
                    ;
                    accessorOutput.count = numKeys;
                    if (accessorOutput.count == 0)
                    {
                        exporter.logger.RaiseWarning(String.Format("GLTFExporter.Animation | No frames to export in material animation \"{1}\" of node named \"{0}\". This will cause an error in the output gltf.", babylonMaterial.name, babylonAnimation.name));
                    }

                    // Animation sampler
                    var gltfAnimationSampler = new GLTFAnimationSampler
                    {
                        input  = accessorInput.index,
                        output = accessorOutput.index
                    };
                    gltfAnimationSampler.index = samplerList.Count;
                    samplerList.Add(gltfAnimationSampler);
                }
            }
        }
Пример #6
0
 private void ExportCommonBabylonAttributes0(MFnDependencyNode babylonAttributesDependencyNode, BabylonMaterial babylonMaterial)
 {
     // Backface Culling
     if (babylonAttributesDependencyNode.hasAttribute("babylonBackfaceCulling"))
     {
         bool v = babylonAttributesDependencyNode.findPlug("babylonBackfaceCulling").asBool();
         RaiseVerbose($"backfaceCulling={v}", 3);
         babylonMaterial.backFaceCulling = v;
     }
     // unlit
     if (babylonAttributesDependencyNode.hasAttribute("babylonUnlit"))
     {
         bool v = babylonAttributesDependencyNode.findPlug("babylonUnlit").asBool();
         RaiseVerbose($"isUnlit={v}", 3);
         babylonMaterial.isUnlit = v;
     }
     // max light
     if (babylonAttributesDependencyNode.hasAttribute("babylonMaxSimultaneousLights"))
     {
         int v = babylonAttributesDependencyNode.findPlug("babylonMaxSimultaneousLights").asInt();
         RaiseVerbose($"maxSimultaneousLights={v}", 3);
         babylonMaterial.maxSimultaneousLights = v;
     }
 }
        protected static void Init(MFnDependencyNode babylonAttributesDependencyNode, BabylonMaterial babylonMaterial = null)
        {
            // Ensure all attributes are setup
            if (babylonAttributesDependencyNode.hasAttribute("babylonBackfaceCulling") == false)
            {
                MGlobal.executeCommand($"addAttr -ln \"babylonBackfaceCulling\" -nn \"Backface Culling\" -at bool {babylonAttributesDependencyNode.name};");
            }
            if (babylonAttributesDependencyNode.hasAttribute("babylonUnlit") == false)
            {
                MGlobal.executeCommand($"addAttr -ln \"babylonUnlit\" -nn \"Unlit\" -at bool {babylonAttributesDependencyNode.name};");
            }
            if (babylonAttributesDependencyNode.hasAttribute("babylonMaxSimultaneousLights") == false)
            {
                MGlobal.executeCommand($"addAttr -ln \"babylonMaxSimultaneousLights\" -nn \"Max Simultaneous Lights\" -at long  -min 1 -dv 4 {babylonAttributesDependencyNode.name};");
            }

            // Initialise attributes according to babylon material
            if (babylonMaterial != null)
            {
                setAttributeValue(babylonAttributesDependencyNode.name + ".babylonBackfaceCulling", Convert.ToInt32(babylonMaterial.backFaceCulling));

                setAttributeValue(babylonAttributesDependencyNode.name + ".babylonUnlit", Convert.ToInt32(babylonMaterial.isUnlit));

                setAttributeValue(babylonAttributesDependencyNode.name + ".babylonMaxSimultaneousLights", babylonMaterial.maxSimultaneousLights);
            }
        }
 private void ExportMainCameraSkyboxToBabylon()
 {
     if (RenderSettings.sun != null)
     {
         var direction            = new Vector3(0, 0, 1);
         var transformedDirection = RenderSettings.sun.transform.TransformDirection(direction);
         SceneBuilder.SunlightDirection   = transformedDirection.ToFloat();
         SceneBuilder.SunlightIndentifier = GetID(RenderSettings.sun.gameObject);
     }
     if (Camera.main != null)
     {
         babylonScene.clearColor = Camera.main.backgroundColor.ToFloat(1.0f);
         if ((Camera.main.clearFlags & CameraClearFlags.Skybox) == CameraClearFlags.Skybox)
         {
             if (RenderSettings.skybox != null)
             {
                 bool           dds    = false;
                 BabylonTexture skytex = null;
                 if (RenderSettings.skybox.shader.name == "Skybox/Cubemap")
                 {
                     skytex                 = new BabylonCubeTexture();
                     skytex.name            = String.Format("{0}_Skybox", SceneName);
                     skytex.coordinatesMode = 5;
                     Cubemap cubeMap = RenderSettings.skybox.GetTexture("_Tex") as Cubemap;
                     if (cubeMap != null)
                     {
                         var srcTexturePath = AssetDatabase.GetAssetPath(cubeMap);
                         var srcTextureExt  = Path.GetExtension(srcTexturePath);
                         if (srcTextureExt.Equals(".dds", StringComparison.OrdinalIgnoreCase))
                         {
                             ExporterWindow.ReportProgress(1, "Exporting skybox direct draw surface... This may take a while.");
                             // ..
                             // Export Draw Surface Skybox Textures
                             // ..
                             dds               = true;
                             skytex.name      += ".dds";
                             skytex.extensions = null;
                             ((BabylonCubeTexture)skytex).prefiltered = true;
                             CopyCubemapTexture(skytex.name, cubeMap, skytex);
                         }
                         else
                         {
                             ExporterWindow.ReportProgress(1, "Baking skybox environment textures... This may take a while.");
                             var imageFormat = (BabylonImageFormat)ExporterWindow.exportationOptions.ImageEncodingOptions;
                             // ..
                             // Export Tone Mapped Cubemap To 6-Sided Skybox Textures
                             // ..
                             bool   jpeg            = (imageFormat == BabylonImageFormat.JPG);
                             string faceTextureExt  = (jpeg) ? ".jpg" : ".png";
                             string frontTextureExt = "_pz" + faceTextureExt;
                             string backTextureExt  = "_nz" + faceTextureExt;
                             string leftTextureExt  = "_px" + faceTextureExt;
                             string rightTextureExt = "_nx" + faceTextureExt;
                             string upTextureExt    = "_py" + faceTextureExt;
                             string downTextureExt  = "_ny" + faceTextureExt;
                             skytex.extensions = new string[] { leftTextureExt, upTextureExt, frontTextureExt, rightTextureExt, downTextureExt, backTextureExt };
                             Tools.SetTextureWrapMode(skytex, cubeMap);
                             var outputFile   = Path.Combine(babylonScene.OutputPath, skytex.name + faceTextureExt);
                             var splitterOpts = new BabylonSplitterOptions();
                             Tools.ExportSkybox(cubeMap, outputFile, splitterOpts, imageFormat);
                         }
                     }
                 }
                 else if (RenderSettings.skybox.shader.name == "Skybox/6 Sided" || RenderSettings.skybox.shader.name == "Mobile/Skybox")
                 {
                     skytex                 = new BabylonCubeTexture();
                     skytex.name            = String.Format("{0}_Skybox", SceneName);
                     skytex.coordinatesMode = 5;
                     // ..
                     // 6-Sided Skybox Textures (Tone Mapped Image Formats Only)
                     // ..
                     var frontTexture = RenderSettings.skybox.GetTexture("_FrontTex") as Texture2D;
                     var backTexture  = RenderSettings.skybox.GetTexture("_BackTex") as Texture2D;
                     var leftTexture  = RenderSettings.skybox.GetTexture("_LeftTex") as Texture2D;
                     var rightTexture = RenderSettings.skybox.GetTexture("_RightTex") as Texture2D;
                     var upTexture    = RenderSettings.skybox.GetTexture("_UpTex") as Texture2D;
                     var downTexture  = RenderSettings.skybox.GetTexture("_DownTex") as Texture2D;
                     DumpSkyboxTextures(ref skytex, ref frontTexture, ref backTexture, ref leftTexture, ref rightTexture, ref upTexture, ref downTexture);
                 }
                 else if (RenderSettings.skybox.name.Equals("Default-Skybox"))
                 {
                     skytex                 = new BabylonCubeTexture();
                     skytex.name            = String.Format("{0}_Skybox", SceneName);
                     skytex.coordinatesMode = 5;
                     // ..
                     // 6-Sided Skybox Textures (Toolkit Skybox Template Images)
                     // ..
                     string skyboxPath   = "Assets/Babylon/Template/Skybox/";
                     var    frontTexture = AssetDatabase.LoadAssetAtPath <Texture2D>(skyboxPath + "DefaultSkybox_pz.png");
                     var    backTexture  = AssetDatabase.LoadAssetAtPath <Texture2D>(skyboxPath + "DefaultSkybox_nz.png");
                     var    leftTexture  = AssetDatabase.LoadAssetAtPath <Texture2D>(skyboxPath + "DefaultSkybox_px.png");
                     var    rightTexture = AssetDatabase.LoadAssetAtPath <Texture2D>(skyboxPath + "DefaultSkybox_nx.png");
                     var    upTexture    = AssetDatabase.LoadAssetAtPath <Texture2D>(skyboxPath + "DefaultSkybox_py.png");
                     var    downTexture  = AssetDatabase.LoadAssetAtPath <Texture2D>(skyboxPath + "DefaultSkybox_ny.png");
                     DumpSkyboxTextures(ref skytex, ref frontTexture, ref backTexture, ref leftTexture, ref rightTexture, ref upTexture, ref downTexture);
                 }
                 else
                 {
                     UnityEngine.Debug.LogWarning("SKYBOX: " + RenderSettings.skybox.shader.name + " shader type is unsupported. Skybox and reflections will be disabled.");
                 }
                 if (skytex != null)
                 {
                     float  size = (SceneController != null) ? SceneController.skyboxOptions.skyboxMeshSize : 1000;
                     string tags = (SceneController != null) ? SceneController.skyboxOptions.skyboxMeshTags : String.Empty;
                     // ..
                     // PBR Skybox Material Support
                     // ..
                     bool  pbr    = (SceneController != null) ? SceneController.skyboxOptions.directDrawSurface.physicalBased : false;
                     float pbr_ms = (SceneController != null) ? SceneController.skyboxOptions.directDrawSurface.microSurface : 1.0f;
                     float pbr_cc = (SceneController != null) ? SceneController.skyboxOptions.directDrawSurface.cameraContrast : 1.0f;
                     float pbr_ce = (SceneController != null) ? SceneController.skyboxOptions.directDrawSurface.cameraExposure : 1.0f;
                     float pbr_di = (SceneController != null) ? SceneController.skyboxOptions.directDrawSurface.directIntensity : 1.0f;
                     float pbr_ei = (SceneController != null) ? SceneController.skyboxOptions.directDrawSurface.emissiveIntensity : 1.0f;
                     float pbr_si = (SceneController != null) ? SceneController.skyboxOptions.directDrawSurface.specularIntensity : 1.0f;
                     float pbr_ri = (SceneController != null) ? SceneController.skyboxOptions.directDrawSurface.environmentIntensity : 1.0f;
                     var   skybox = new BabylonMesh();
                     skybox.id = Guid.NewGuid().ToString();
                     skybox.infiniteDistance   = true;
                     skybox.numBoneInfluencers = Tools.GetMaxBoneInfluencers();
                     if (!String.IsNullOrEmpty(tags))
                     {
                         skybox.tags = tags;
                     }
                     skybox.name = "SceneSkyboxMesh";
                     Mesh boxMesh = Tools.CreateBoxMesh(size, size, size);
                     Tools.GenerateBabylonMeshData(boxMesh, skybox);
                     BabylonMaterial skyboxMaterial = null;
                     if (dds == true && pbr == true)
                     {
                         var skyboxMaterialPbr = new BabylonSystemMaterial {
                             name                      = "SceneSkyboxMaterial",
                             id                        = Guid.NewGuid().ToString(),
                             backFaceCulling           = false,
                             disableLighting           = true,
                             albedo                    = Color.white.ToFloat(),
                             ambient                   = Color.black.ToFloat(),
                             emissive                  = Color.black.ToFloat(),
                             metallic                  = null,
                             roughness                 = null,
                             sideOrientation           = 1,
                             reflectivity              = Color.white.ToFloat(),
                             reflection                = Color.white.ToFloat(),
                             microSurface              = pbr_ms,
                             cameraContrast            = pbr_cc,
                             cameraExposure            = pbr_ce,
                             directIntensity           = pbr_di,
                             emissiveIntensity         = pbr_ei,
                             specularIntensity         = pbr_si,
                             environmentIntensity      = pbr_ri,
                             maxSimultaneousLights     = 4,
                             useSpecularOverAlpha      = false,
                             useRadianceOverAlpha      = false,
                             usePhysicalLightFalloff   = false,
                             useAlphaFromAlbedoTexture = false,
                             useEmissiveAsIllumination = false,
                             reflectionTexture         = skytex
                         };
                         skyboxMaterial = skyboxMaterialPbr;
                     }
                     else
                     {
                         var skyboxMaterialStd = new BabylonDefaultMaterial {
                             name              = "SceneSkyboxMaterial",
                             id                = Guid.NewGuid().ToString(),
                             backFaceCulling   = false,
                             disableLighting   = true,
                             diffuse           = Color.black.ToFloat(),
                             specular          = Color.black.ToFloat(),
                             ambient           = Color.clear.ToFloat(),
                             reflectionTexture = skytex
                         };
                         skyboxMaterial = skyboxMaterialStd;
                     }
                     if (skyboxMaterial != null)
                     {
                         skybox.materialId = skyboxMaterial.id;
                         babylonScene.MeshesList.Add(skybox);
                         babylonScene.MaterialsList.Add(skyboxMaterial);
                         babylonScene.AddTextureCube("SceneSkyboxMaterial");
                     }
                 }
             }
         }
     }
 }
Пример #9
0
        private void ExportMaterial(BabylonMaterial babylonMaterial, GLTF gltf)
        {
            var name = babylonMaterial.name;
            var id   = babylonMaterial.id;

            RaiseMessage("GLTFExporter.Material | Export material named: " + name, 1);

            if (babylonMaterial.GetType() == typeof(BabylonStandardMaterial))
            {
                var babylonStandardMaterial = babylonMaterial as BabylonStandardMaterial;


                // --- prints ---

                RaiseMessage("GLTFExporter.Material | babylonMaterial data", 2);
                RaiseMessage("GLTFExporter.Material | babylonMaterial.alpha=" + babylonMaterial.alpha, 3);
                RaiseMessage("GLTFExporter.Material | babylonMaterial.backFaceCulling=" + babylonMaterial.backFaceCulling, 3);
                RaiseMessage("GLTFExporter.Material | babylonMaterial.wireframe=" + babylonMaterial.wireframe, 3);
                RaiseMessage("GLTFExporter.Material | babylonStandardMaterial.specularPower=" + babylonStandardMaterial.specularPower, 3);

                // Ambient
                for (int i = 0; i < babylonStandardMaterial.ambient.Length; i++)
                {
                    RaiseMessage("GLTFExporter.Material | babylonStandardMaterial.ambient[" + i + "]=" + babylonStandardMaterial.ambient[i], 3);
                }

                // Diffuse
                RaiseMessage("GLTFExporter.Material | babylonStandardMaterial.diffuse.Length=" + babylonStandardMaterial.diffuse.Length, 3);
                for (int i = 0; i < babylonStandardMaterial.diffuse.Length; i++)
                {
                    RaiseMessage("GLTFExporter.Material | babylonStandardMaterial.diffuse[" + i + "]=" + babylonStandardMaterial.diffuse[i], 3);
                }
                if (babylonStandardMaterial.diffuseTexture == null)
                {
                    RaiseMessage("GLTFExporter.Material | babylonStandardMaterial.diffuseTexture=null", 3);
                }

                // Normal / bump
                if (babylonStandardMaterial.bumpTexture == null)
                {
                    RaiseMessage("GLTFExporter.Material | babylonStandardMaterial.bumpTexture=null", 3);
                }

                // Specular
                for (int i = 0; i < babylonStandardMaterial.specular.Length; i++)
                {
                    RaiseMessage("GLTFExporter.Material | babylonStandardMaterial.specular[" + i + "]=" + babylonStandardMaterial.specular[i], 3);
                }
                RaiseMessage("GLTFExporter.Material | babylonStandardMaterial.specularPower=" + babylonStandardMaterial.specularPower, 3);

                // Occlusion
                if (babylonStandardMaterial.ambientTexture == null)
                {
                    RaiseMessage("GLTFExporter.Material | babylonStandardMaterial.ambientTexture=null", 3);
                }

                // Emissive
                for (int i = 0; i < babylonStandardMaterial.emissive.Length; i++)
                {
                    RaiseMessage("GLTFExporter.Material | babylonStandardMaterial.emissive[" + i + "]=" + babylonStandardMaterial.emissive[i], 3);
                }
                if (babylonStandardMaterial.emissiveTexture == null)
                {
                    RaiseMessage("GLTFExporter.Material | babylonStandardMaterial.emissiveTexture=null", 3);
                }


                // --------------------------------
                // --------- gltfMaterial ---------
                // --------------------------------

                RaiseMessage("GLTFExporter.Material | create gltfMaterial", 2);
                var gltfMaterial = new GLTFMaterial
                {
                    name = name
                };
                gltfMaterial.id    = babylonMaterial.id;
                gltfMaterial.index = gltf.MaterialsList.Count;
                gltf.MaterialsList.Add(gltfMaterial);

                // Alpha
                string alphaMode;
                float? alphaCutoff;
                getAlphaMode(babylonStandardMaterial, out alphaMode, out alphaCutoff);
                gltfMaterial.alphaMode   = alphaMode;
                gltfMaterial.alphaCutoff = alphaCutoff;

                // DoubleSided
                gltfMaterial.doubleSided = !babylonMaterial.backFaceCulling;

                // Normal
                gltfMaterial.normalTexture = ExportTexture(babylonStandardMaterial.bumpTexture, gltf);

                // Occulison
                gltfMaterial.occlusionTexture = ExportTexture(babylonStandardMaterial.ambientTexture, gltf);

                // Emissive
                gltfMaterial.emissiveFactor  = babylonStandardMaterial.emissive;
                gltfMaterial.emissiveTexture = ExportTexture(babylonStandardMaterial.emissiveTexture, gltf);


                // --------------------------------
                // --- gltfPbrMetallicRoughness ---
                // --------------------------------

                RaiseMessage("GLTFExporter.Material | create gltfPbrMetallicRoughness", 2);
                var gltfPbrMetallicRoughness = new GLTFPBRMetallicRoughness();
                gltfMaterial.pbrMetallicRoughness = gltfPbrMetallicRoughness;

                // --- Global ---

                SpecularGlossiness _specularGlossiness = new SpecularGlossiness
                {
                    diffuse    = new BabylonColor3(babylonStandardMaterial.diffuse),
                    opacity    = babylonMaterial.alpha,
                    specular   = new BabylonColor3(babylonStandardMaterial.specular),
                    glossiness = babylonStandardMaterial.specularPower / 256
                };

                MetallicRoughness _metallicRoughness = ConvertToMetallicRoughness(_specularGlossiness, true);

                // Base color
                gltfPbrMetallicRoughness.baseColorFactor = new float[4]
                {
                    _metallicRoughness.baseColor.r,
                    _metallicRoughness.baseColor.g,
                    _metallicRoughness.baseColor.b,
                    _metallicRoughness.opacity
                };

                // Metallic roughness
                gltfPbrMetallicRoughness.metallicFactor  = _metallicRoughness.metallic;
                gltfPbrMetallicRoughness.roughnessFactor = _metallicRoughness.roughness;


                // --- Textures ---

                if (babylonStandardMaterial.diffuseTexture != null)
                {
                    Func <string, Bitmap> loadTexture = delegate(string textureName)
                    {
                        var pathDiffuse = Path.Combine(gltf.OutputPath, textureName);
                        if (File.Exists(pathDiffuse))
                        {
                            return(new Bitmap(pathDiffuse));
                        }
                        else
                        {
                            RaiseWarning(string.Format("GLTFExporter.Material | Texture {0} not found.", textureName), 2);
                            return(null);
                        }
                    };

                    Bitmap diffuseBitmap = loadTexture(babylonStandardMaterial.diffuseTexture.name);

                    if (diffuseBitmap != null)
                    {
                        Bitmap specularBitmap = null;
                        if (babylonStandardMaterial.specularTexture != null)
                        {
                            specularBitmap = loadTexture(babylonStandardMaterial.specularTexture.name);
                        }

                        Bitmap opacityBitmap = null;
                        if (babylonStandardMaterial.diffuseTexture.hasAlpha == false && babylonStandardMaterial.opacityTexture != null)
                        {
                            opacityBitmap = loadTexture(babylonStandardMaterial.opacityTexture.name);
                        }

                        // Retreive dimension from diffuse map
                        var width  = diffuseBitmap.Width;
                        var height = diffuseBitmap.Height;

                        // Create base color and metallic+roughness maps
                        Bitmap baseColorBitmap         = new Bitmap(width, height);
                        Bitmap metallicRoughnessBitmap = new Bitmap(width, height);
                        for (int x = 0; x < width; x++)
                        {
                            for (int y = 0; y < height; y++)
                            {
                                var diffuse = diffuseBitmap.GetPixel(x, y);
                                SpecularGlossiness specularGlossinessTexture = new SpecularGlossiness
                                {
                                    diffuse = new BabylonColor3(diffuse),
                                    opacity = babylonStandardMaterial.diffuseTexture.hasAlpha? diffuse.A / 255.0f :
                                              opacityBitmap != null && babylonStandardMaterial.opacityTexture.getAlphaFromRGB ? opacityBitmap.GetPixel(x, y).R / 255.0f :
                                              opacityBitmap != null && babylonStandardMaterial.opacityTexture.getAlphaFromRGB == false?opacityBitmap.GetPixel(x, y).A / 255.0f :
                                              1,
                                    specular = specularBitmap != null ? new BabylonColor3(specularBitmap.GetPixel(x, y)) :
                                               new BabylonColor3(),
                                    glossiness = babylonStandardMaterial.useGlossinessFromSpecularMapAlpha && specularBitmap != null?specularBitmap.GetPixel(x, y).A / 255.0f :
                                                 babylonStandardMaterial.specularPower / 256.0f
                                };

                                var displayPrints = x == width / 2 && y == height / 2;
                                MetallicRoughness metallicRoughnessTexture = ConvertToMetallicRoughness(specularGlossinessTexture, displayPrints);

                                Color colorBase = Color.FromArgb(
                                    (int)(metallicRoughnessTexture.opacity * 255),
                                    (int)(metallicRoughnessTexture.baseColor.r * 255),
                                    (int)(metallicRoughnessTexture.baseColor.g * 255),
                                    (int)(metallicRoughnessTexture.baseColor.b * 255)
                                    );
                                baseColorBitmap.SetPixel(x, y, colorBase);

                                // The metalness values are sampled from the B channel.
                                // The roughness values are sampled from the G channel.
                                // These values are linear. If other channels are present (R or A), they are ignored for metallic-roughness calculations.
                                Color colorMetallicRoughness = Color.FromArgb(
                                    0,
                                    (int)(metallicRoughnessTexture.roughness * 255),
                                    (int)(metallicRoughnessTexture.metallic * 255)
                                    );
                                metallicRoughnessBitmap.SetPixel(x, y, colorMetallicRoughness);
                            }
                        }

                        // Export maps and textures
                        gltfPbrMetallicRoughness.baseColorTexture         = ExportBitmapTexture(babylonStandardMaterial.diffuseTexture, baseColorBitmap, babylonMaterial.name + "_baseColor" + ".png", gltf);
                        gltfPbrMetallicRoughness.metallicRoughnessTexture = ExportBitmapTexture(babylonStandardMaterial.diffuseTexture, metallicRoughnessBitmap, babylonMaterial.name + "_metallicRoughness" + ".jpg", gltf);
                    }
                }
            }
        }
Пример #10
0
        private IList <BabylonAnimationGroup> ExportAnimationGroups(BabylonScene babylonScene)
        {
            IList <BabylonAnimationGroup> animationGroups = new List <BabylonAnimationGroup>();

            // Retrieve and parse animation group data
            AnimationGroupList animationList = AnimationGroupList.InitAnimationGroups(logger);

            foreach (AnimationGroup animGroup in animationList)
            {
                logger?.RaiseMessage("Exporter.animationGroups | " + animGroup.Name, 1);
                BabylonAnimationGroup animationGroup = new BabylonAnimationGroup
                {
                    name               = animGroup.Name,
                    from               = animGroup.FrameStart,
                    to                 = animGroup.FrameEnd,
                    keepNonAnimated    = animGroup.KeepNonAnimated,
                    targetedAnimations = new List <BabylonTargetedAnimation>()
                };

                // add animations of each nodes contained in the animGroup
                foreach (Guid guid in animGroup.NodeGuids)
                {
                    IINode maxNode = Tools.GetINodeByGuid(guid);

                    // node could have been deleted, silently ignore it
                    if (maxNode == null)
                    {
                        continue;
                    }

                    if (exportParameters.exportAsSubmodel && !maxNode.Selected)
                    {
                        continue;
                    }


                    // Helpers can be exported as dummies and as bones
                    string nodeId = maxNode.GetGuid().ToString();
                    string boneId = isGltfExported?maxNode.GetGuid().ToString(): maxNode.GetGuid().ToString() + "-bone";   // the suffix "-bone" is added in babylon export format to assure the uniqueness of IDs

                    // Node
                    BabylonNode node = null;
                    babylonScene.NodeMap.TryGetValue(nodeId, out node);
                    if (node != null)
                    {
                        if (node.animations != null && node.animations.Length != 0)
                        {
                            IList <BabylonAnimation> animations = GetSubAnimations(node, animationGroup.from, animationGroup.to);

                            if (!animGroup.KeepStaticAnimation)
                            {
                                RemoveStaticAnimations(ref animations);
                            }

                            foreach (BabylonAnimation animation in animations)
                            {
                                BabylonTargetedAnimation targetedAnimation = new BabylonTargetedAnimation
                                {
                                    animation = animation,
                                    targetId  = nodeId
                                };

                                animationGroup.targetedAnimations.Add(targetedAnimation);
                            }
                        }
                    }

                    // bone
                    BabylonBone bone  = null;
                    int         index = 0;
                    while (index < babylonScene.SkeletonsList.Count && bone == null)
                    {
                        BabylonSkeleton skel = babylonScene.SkeletonsList[index];
                        bone = skel.bones.FirstOrDefault(b => b.id == boneId);
                        index++;
                    }

                    if (bone != null)
                    {
                        if (bone.animation != null)
                        {
                            IList <BabylonAnimation> animations = GetSubAnimations(bone, animationGroup.from, animationGroup.to);
                            foreach (BabylonAnimation animation in animations)
                            {
                                BabylonTargetedAnimation targetedAnimation = new BabylonTargetedAnimation
                                {
                                    animation = animation,
                                    targetId  = boneId
                                };

                                animationGroup.targetedAnimations.Add(targetedAnimation);
                            }
                        }
                    }
                }

                // add animations of each nodes contained in the animGroup
                foreach (Guid guid in animGroup.MaterialGuids)
                {
                    IMtl maxMtl = Tools.GetIMtlByGuid(guid);

                    // mat could have been deleted, silently ignore it
                    if (maxMtl == null)
                    {
                        continue;
                    }

                    string matId = maxMtl.GetGuid().ToString();

                    // Material
                    BabylonMaterial material = null;
                    material = babylonScene.MaterialsList.FirstOrDefault(x => x.id == matId);
                    if (material != null)
                    {
                        if (material.animations != null && material.animations.Length != 0)
                        {
                            IList <BabylonAnimation> animations = GetSubAnimations(material, animationGroup.from, animationGroup.to);
                            foreach (BabylonAnimation animation in animations)
                            {
                                BabylonTargetedAnimation targetedAnimation = new BabylonTargetedAnimation
                                {
                                    animation = animation,
                                    targetId  = matId
                                };

                                animationGroup.targetedAnimations.Add(targetedAnimation);
                            }
                        }
                    }
                }

                if (animationGroup.targetedAnimations.Count > 0)
                {
                    animationGroups.Add(animationGroup);
                }
            }

            return(animationGroups);
        }
Пример #11
0
        private void ExportMaterial(Material materialNode, BabylonScene babylonScene)
        {
            var name = materialNode._Mtl.Name;
            var id   = materialNode.GetGuid().ToString();

            RaiseMessage(name, true);

            if (materialNode.NumSubMaterials > 0)
            {
                var babylonMultimaterial = new BabylonMultiMaterial();
                babylonMultimaterial.name = name;
                babylonMultimaterial.id   = id;

                var guids = new List <string>();

                for (var index = 0; index < materialNode.NumSubMaterials; index++)
                {
                    var subMat = materialNode.GetSubMaterial(index) as Material;

                    if (subMat != null)
                    {
                        guids.Add(subMat.GetGuid().ToString());

                        if (!referencedMaterials.Contains(subMat))
                        {
                            referencedMaterials.Add(subMat);
                            ExportMaterial(subMat, babylonScene);
                        }
                    }
                    else
                    {
                        guids.Add(Guid.Empty.ToString());
                    }
                }

                babylonMultimaterial.materials = guids.ToArray();

                babylonScene.MultiMaterialsList.Add(babylonMultimaterial);
                return;
            }


            var babylonMaterial = new BabylonMaterial();

            babylonMaterial.name = name;
            babylonMaterial.id   = id;

            babylonMaterial.ambient       = materialNode.GetAmbient(0).ToArray();
            babylonMaterial.diffuse       = materialNode.GetDiffuse(0).ToArray();
            babylonMaterial.specular      = materialNode.GetSpecular(0).Scale(materialNode.GetShinyStrength(0));
            babylonMaterial.specularPower = materialNode.GetShininess(0) * 256;

            babylonMaterial.emissive = materialNode.SelfIlluminationColorOn ? materialNode.GetSelfIllumColor(0).ToArray() : materialNode.GetDiffuse(0).Scale(materialNode.GetSelfIllumination(0));
            babylonMaterial.alpha    = 1.0f - materialNode.GetTransparency(0);

            var stdMat = materialNode._Mtl.GetParamBlock(0).Owner as IStdMat2;

            if (stdMat != null)
            {
                // Textures
                babylonMaterial.ambientTexture    = ExportTexture(stdMat, 0, babylonScene); // Ambient
                babylonMaterial.diffuseTexture    = ExportTexture(stdMat, 1, babylonScene); // Diffuse
                babylonMaterial.specularTexture   = ExportTexture(stdMat, 2, babylonScene); // Specular
                babylonMaterial.emissiveTexture   = ExportTexture(stdMat, 5, babylonScene); // Emissive
                babylonMaterial.opacityTexture    = ExportTexture(stdMat, 6, babylonScene); // Opacity
                babylonMaterial.bumpTexture       = ExportTexture(stdMat, 8, babylonScene); // Bump
                babylonMaterial.reflectionTexture = ExportTexture(stdMat, 9, babylonScene); // Reflection

                // Constraints
                if (babylonMaterial.diffuseTexture != null)
                {
                    babylonMaterial.emissive = new [] { 1.0f, 1.0f, 1.0f };
                }

                if (babylonMaterial.emissiveTexture != null)
                {
                    babylonMaterial.emissive = new float[] { 0, 0, 0 };
                }

                if (babylonMaterial.opacityTexture != null && babylonMaterial.diffuseTexture != null &&
                    babylonMaterial.diffuseTexture.name == babylonMaterial.opacityTexture.name &&
                    babylonMaterial.diffuseTexture.hasAlpha && !babylonMaterial.opacityTexture.getAlphaFromRGB)
                {
                    // This is a alpha testing purpose
                    babylonMaterial.opacityTexture          = null;
                    babylonMaterial.diffuseTexture.hasAlpha = true;
                    RaiseWarning("Opacity texture was removed because alpha from diffuse texture can be use instead", true);
                    RaiseWarning("If you do not want this behavior, just set Alpha Source = None on your diffuse texture", true);
                }
            }

            babylonScene.MaterialsList.Add(babylonMaterial);
        }
        void DumpStandardMaterial(NovaStandardMaterial stdMaterial, BabylonScene babylonScene)
        {
            var babylonMaterial = new BabylonMaterial();

            babylonScene.MaterialsList.Add(babylonMaterial);

            babylonMaterial.name            = stdMaterial.Name;
            babylonMaterial.id              = stdMaterial.ID.ToString();
            babylonMaterial.alpha           = stdMaterial.Alpha;
            babylonMaterial.ambient         = (stdMaterial.Ambient * (1.0f - stdMaterial.SelfIllumination)).ToArray();
            babylonMaterial.diffuse         = (stdMaterial.Diffuse * (1.0f - stdMaterial.SelfIllumination)).ToArray();
            babylonMaterial.emissive        = (stdMaterial.Emissive * stdMaterial.SelfIllumination).ToArray();
            babylonMaterial.specular        = stdMaterial.Specular.ToArray();
            babylonMaterial.specularPower   = stdMaterial.SpecularSharpness;
            babylonMaterial.backFaceCulling = (stdMaterial.CullMode == NovaCull.CounterClockwise);

            if (stdMaterial.DiffuseTexture != null && stdMaterial.DiffuseTexture.HasTextureData && stdMaterial.OpacityTexture != null && stdMaterial.OpacityTexture.HasTextureData)
            {
                if (stdMaterial.DiffuseTexture.LoadedTexture == stdMaterial.OpacityTexture.LoadedTexture)
                {
                    stdMaterial.DiffuseTexture = stdMaterial.OpacityTexture;
                    stdMaterial.OpacityTexture = null;
                }
            }

            if (stdMaterial.DiffuseTexture != null && stdMaterial.DiffuseTexture.HasTextureData && !stdMaterial.DiffuseTexture.IsVideo && !stdMaterial.DiffuseTexture.IsCubeRender)
            {
                babylonMaterial.diffuseTexture = new BabylonTexture();
                DumpTexture(stdMaterial.DiffuseTexture, babylonMaterial.diffuseTexture, babylonScene);
            }

            if (stdMaterial.AmbientTexture != null && stdMaterial.AmbientTexture.HasTextureData && !stdMaterial.AmbientTexture.IsVideo && !stdMaterial.AmbientTexture.IsCubeRender)
            {
                babylonMaterial.ambientTexture = new BabylonTexture();
                DumpTexture(stdMaterial.AmbientTexture, babylonMaterial.ambientTexture, babylonScene);
            }

            if (stdMaterial.OpacityTexture != null && stdMaterial.OpacityTexture.HasTextureData && !stdMaterial.OpacityTexture.IsVideo && !stdMaterial.OpacityTexture.IsCubeRender)
            {
                babylonMaterial.opacityTexture = new BabylonTexture();
                DumpTexture(stdMaterial.OpacityTexture, babylonMaterial.opacityTexture, babylonScene);
            }

            if (mirrorsMaterials.ContainsKey(stdMaterial))
            {
                babylonMaterial.reflectionTexture = new BabylonTexture();
                var novaObject = mirrorsMaterials[stdMaterial];
                DumpRenderTargetTexture(stdMaterial.ReflectionTexture, babylonMaterial.reflectionTexture, novaObject.MirrorMapSize, novaObject.MirrorLevel, novaObject.MirroredObjects);

                AttachMirrorPlane(babylonMaterial.reflectionTexture, novaObject);
            }
            else if (stdMaterial.ReflectionTexture != null && stdMaterial.ReflectionTexture.HasTextureData && !stdMaterial.ReflectionTexture.IsVideo && !stdMaterial.ReflectionTexture.IsCubeRender)
            {
                babylonMaterial.reflectionTexture = new BabylonTexture();
                DumpTexture(stdMaterial.ReflectionTexture, babylonMaterial.reflectionTexture, babylonScene);
            }

            if (stdMaterial.EmissiveTexture != null && stdMaterial.EmissiveTexture.HasTextureData && !stdMaterial.EmissiveTexture.IsVideo && !stdMaterial.EmissiveTexture.IsCubeRender)
            {
                babylonMaterial.emissiveTexture = new BabylonTexture();
                DumpTexture(stdMaterial.EmissiveTexture, babylonMaterial.emissiveTexture, babylonScene);
            }

            if (stdMaterial.SpecularTexture != null && stdMaterial.SpecularTexture.HasTextureData && !stdMaterial.SpecularTexture.IsVideo && !stdMaterial.SpecularTexture.IsCubeRender)
            {
                babylonMaterial.specularTexture = new BabylonTexture();
                DumpTexture(stdMaterial.SpecularTexture, babylonMaterial.specularTexture, babylonScene);
            }

            if (stdMaterial.BumpTexture != null && stdMaterial.BumpTexture.HasTextureData && !stdMaterial.BumpTexture.IsVideo && !stdMaterial.BumpTexture.IsCubeRender)
            {
                babylonMaterial.bumpTexture = new BabylonTexture();
                DumpTexture(stdMaterial.BumpTexture, babylonMaterial.bumpTexture, babylonScene);
                babylonMaterial.bumpTexture.level /= 2.0f;
            }
        }
        void DumpPerPixelShader(NovaPerPixelShader ppShader, BabylonScene babylonScene)
        {
            var babylonMaterial = new BabylonMaterial();

            babylonScene.MaterialsList.Add(babylonMaterial);

            babylonMaterial.name            = ppShader.Name;
            babylonMaterial.id              = ppShader.ID.ToString();
            babylonMaterial.alpha           = ppShader.Alpha;
            babylonMaterial.ambient         = (ppShader.Ambient * (1.0f - ppShader.SelfIllumination)).ToArray();
            babylonMaterial.diffuse         = (ppShader.Diffuse * (1.0f - ppShader.SelfIllumination)).ToArray();
            babylonMaterial.emissive        = (ppShader.Emissive * ppShader.SelfIllumination).ToArray();
            babylonMaterial.specular        = ppShader.Specular.ToArray();
            babylonMaterial.specularPower   = ppShader.SpecularSharpness;
            babylonMaterial.backFaceCulling = (ppShader.CullMode == NovaCull.CounterClockwise);

            if (ppShader.DiffuseTexture != null && ppShader.DiffuseTexture.HasTextureData && ppShader.OpacityTexture != null && ppShader.OpacityTexture.HasTextureData)
            {
                if (ppShader.DiffuseTexture.LoadedTexture == ppShader.OpacityTexture.LoadedTexture)
                {
                    ppShader.DiffuseTexture = ppShader.OpacityTexture;
                    ppShader.OpacityTexture = null;
                }
            }

            if (ppShader.DiffuseTexture != null && ppShader.DiffuseTexture.HasTextureData && !ppShader.DiffuseTexture.IsVideo && !ppShader.DiffuseTexture.IsCubeRender)
            {
                babylonMaterial.diffuseTexture = new BabylonTexture();
                DumpTexture(ppShader.DiffuseTexture, babylonMaterial.diffuseTexture, babylonScene);
            }

            if (ppShader.AmbientTexture != null && ppShader.AmbientTexture.HasTextureData && !ppShader.AmbientTexture.IsVideo && !ppShader.AmbientTexture.IsCubeRender)
            {
                babylonMaterial.ambientTexture = new BabylonTexture();
                DumpTexture(ppShader.AmbientTexture, babylonMaterial.ambientTexture, babylonScene);
            }

            if (ppShader.OpacityTexture != null && ppShader.OpacityTexture.HasTextureData && !ppShader.OpacityTexture.IsVideo && !ppShader.OpacityTexture.IsCubeRender)
            {
                babylonMaterial.opacityTexture = new BabylonTexture();
                DumpTexture(ppShader.OpacityTexture, babylonMaterial.opacityTexture, babylonScene);
            }

            if (mirrorsMaterials.ContainsKey(ppShader))
            {
                babylonMaterial.reflectionTexture = new BabylonTexture();
                var novaObject = mirrorsMaterials[ppShader];
                DumpRenderTargetTexture(ppShader.ReflectionTexture, babylonMaterial.reflectionTexture, novaObject.MirrorMapSize, novaObject.MirrorLevel, novaObject.MirroredObjects);

                AttachMirrorPlane(babylonMaterial.reflectionTexture, novaObject);
            }
            else if (ppShader.ReflectionTexture != null && ppShader.ReflectionTexture.HasTextureData && !ppShader.ReflectionTexture.IsVideo && !ppShader.ReflectionTexture.IsCubeRender)
            {
                babylonMaterial.reflectionTexture = new BabylonTexture();
                DumpTexture(ppShader.ReflectionTexture, babylonMaterial.reflectionTexture, babylonScene);
            }

            // Refraction
            if (ppShader.RefractionLevel > 0)
            {
                babylonMaterial.alpha = 1.0f - ppShader.RefractionLevel;
            }

            if (ppShader.EmissiveTexture != null && ppShader.EmissiveTexture.HasTextureData && !ppShader.EmissiveTexture.IsVideo && !ppShader.EmissiveTexture.IsCubeRender)
            {
                babylonMaterial.emissiveTexture = new BabylonTexture();
                DumpTexture(ppShader.EmissiveTexture, babylonMaterial.emissiveTexture, babylonScene);
            }

            if (ppShader.SpecularTexture != null && ppShader.SpecularTexture.HasTextureData && !ppShader.SpecularTexture.IsVideo && !ppShader.SpecularTexture.IsCubeRender)
            {
                babylonMaterial.specularTexture = new BabylonTexture();
                DumpTexture(ppShader.SpecularTexture, babylonMaterial.specularTexture, babylonScene);
            }

            if (ppShader.BumpTexture != null && ppShader.BumpTexture.HasTextureData && !ppShader.BumpTexture.IsVideo && !ppShader.BumpTexture.IsCubeRender)
            {
                babylonMaterial.bumpTexture = new BabylonTexture();
                DumpTexture(ppShader.BumpTexture, babylonMaterial.bumpTexture, babylonScene);
                babylonMaterial.bumpTexture.level /= 2.0f;
            }
        }
Пример #14
0
        private void ExportCommonBabylonAttributes(MFnDependencyNode babylonAttributesDependencyNode, BabylonMaterial babylonMaterial)
        {
            bool backfaceCulling = babylonAttributesDependencyNode.findPlug("babylonBackfaceCulling").asBool();

            RaiseVerbose("backfaceCulling=" + backfaceCulling, 3);
            babylonMaterial.backFaceCulling = backfaceCulling;

            int maxSimultaneousLights = babylonAttributesDependencyNode.findPlug("babylonMaxSimultaneousLights").asInt();

            RaiseVerbose("maxSimultaneousLights=" + maxSimultaneousLights, 3);
            babylonMaterial.maxSimultaneousLights = maxSimultaneousLights;

            bool unlit = babylonAttributesDependencyNode.findPlug("babylonUnlit").asBool();

            RaiseVerbose("unlit=" + unlit, 3);
            babylonMaterial.isUnlit = unlit;
        }
        private void ExportMaterial(IIGameMaterial materialNode, BabylonScene babylonScene)
        {
            var name = materialNode.MaterialName;
            var id   = materialNode.MaxMaterial.GetGuid().ToString();

            RaiseMessage(name, 1);

            if (materialNode.SubMaterialCount > 0)
            {
                var babylonMultimaterial = new BabylonMultiMaterial {
                    name = name, id = id
                };

                var guids = new List <string>();

                for (var index = 0; index < materialNode.SubMaterialCount; index++)
                {
                    var subMat = materialNode.GetSubMaterial(index);

                    if (subMat != null)
                    {
                        guids.Add(subMat.MaxMaterial.GetGuid().ToString());

                        if (!referencedMaterials.Contains(subMat))
                        {
                            referencedMaterials.Add(subMat);
                            ExportMaterial(subMat, babylonScene);
                        }
                    }
                    else
                    {
                        guids.Add(Guid.Empty.ToString());
                    }
                }

                babylonMultimaterial.materials = guids.ToArray();

                babylonScene.MultiMaterialsList.Add(babylonMultimaterial);
                return;
            }

            var babylonMaterial = new BabylonMaterial
            {
                name          = name,
                id            = id,
                ambient       = materialNode.MaxMaterial.GetAmbient(0, false).ToArray(),
                diffuse       = materialNode.MaxMaterial.GetDiffuse(0, false).ToArray(),
                specular      = materialNode.MaxMaterial.GetSpecular(0, false).Scale(materialNode.MaxMaterial.GetShinStr(0, false)),
                specularPower = materialNode.MaxMaterial.GetShininess(0, false) * 256,
                emissive      =
                    materialNode.MaxMaterial.GetSelfIllumColorOn(0, false)
                        ? materialNode.MaxMaterial.GetSelfIllumColor(0, false).ToArray()
                        : materialNode.MaxMaterial.GetDiffuse(0, false).Scale(materialNode.MaxMaterial.GetSelfIllum(0, false)),
                alpha = 1.0f - materialNode.MaxMaterial.GetXParency(0, false)
            };


            var stdMat = materialNode.MaxMaterial.GetParamBlock(0).Owner as IStdMat2;

            if (stdMat != null)
            {
                babylonMaterial.backFaceCulling = !stdMat.TwoSided;
                babylonMaterial.wireframe       = stdMat.Wire;

                // Textures
                BabylonFresnelParameters fresnelParameters;

                babylonMaterial.ambientTexture = ExportTexture(stdMat, 0, out fresnelParameters, babylonScene);                // Ambient
                babylonMaterial.diffuseTexture = ExportTexture(stdMat, 1, out fresnelParameters, babylonScene);                // Diffuse
                if (fresnelParameters != null)
                {
                    babylonMaterial.diffuseFresnelParameters = fresnelParameters;
                }

                babylonMaterial.specularTexture = ExportTexture(stdMat, 2, out fresnelParameters, babylonScene);               // Specular
                babylonMaterial.emissiveTexture = ExportTexture(stdMat, 5, out fresnelParameters, babylonScene);               // Emissive
                if (fresnelParameters != null)
                {
                    babylonMaterial.emissiveFresnelParameters = fresnelParameters;
                    if (babylonMaterial.emissive[0] == 0 &&
                        babylonMaterial.emissive[1] == 0 &&
                        babylonMaterial.emissive[2] == 0 &&
                        babylonMaterial.emissiveTexture == null)
                    {
                        babylonMaterial.emissive = new float[] { 1, 1, 1 };
                    }
                }

                babylonMaterial.opacityTexture = ExportTexture(stdMat, 6, out fresnelParameters, babylonScene, false, true);   // Opacity
                if (fresnelParameters != null)
                {
                    babylonMaterial.opacityFresnelParameters = fresnelParameters;
                    if (babylonMaterial.alpha == 1 &&
                        babylonMaterial.opacityTexture == null)
                    {
                        babylonMaterial.alpha = 0;
                    }
                }

                babylonMaterial.bumpTexture       = ExportTexture(stdMat, 8, out fresnelParameters, babylonScene);             // Bump
                babylonMaterial.reflectionTexture = ExportTexture(stdMat, 9, out fresnelParameters, babylonScene, true);       // Reflection
                if (fresnelParameters != null)
                {
                    if (babylonMaterial.reflectionTexture == null)
                    {
                        RaiseWarning("Fallout cannot be used with reflection channel without a texture", 2);
                    }
                    else
                    {
                        babylonMaterial.reflectionFresnelParameters = fresnelParameters;
                    }
                }

                // Constraints
                if (babylonMaterial.diffuseTexture != null)
                {
                    babylonMaterial.diffuse = new[] { 1.0f, 1.0f, 1.0f };
                }

                if (babylonMaterial.emissiveTexture != null)
                {
                    babylonMaterial.emissive = new float[] { 0, 0, 0 };
                }

                if (babylonMaterial.opacityTexture != null && babylonMaterial.diffuseTexture != null &&
                    babylonMaterial.diffuseTexture.name == babylonMaterial.opacityTexture.name &&
                    babylonMaterial.diffuseTexture.hasAlpha && !babylonMaterial.opacityTexture.getAlphaFromRGB)
                {
                    // This is a alpha testing purpose
                    babylonMaterial.opacityTexture          = null;
                    babylonMaterial.diffuseTexture.hasAlpha = true;
                    RaiseWarning("Opacity texture was removed because alpha from diffuse texture can be use instead", 2);
                    RaiseWarning("If you do not want this behavior, just set Alpha Source = None on your diffuse texture", 2);
                }
            }

            babylonScene.MaterialsList.Add(babylonMaterial);
        }
        private BabylonMaterial DumpMaterial(Material material, Renderer renderer)
        {
            if (!materialsDictionary.ContainsKey(material.name))
            {
                var bMat = new BabylonMaterial
                {
                    name     = material.name,
                    id       = Guid.NewGuid().ToString(),
                    diffuse  = new float[4],
                    specular = new float[4]
                };

                bMat.diffuse[0] = 1.0f;
                bMat.diffuse[1] = 1.0f;
                bMat.diffuse[2] = 1.0f;
                bMat.diffuse[3] = 1.0f;

                if (material.HasProperty("_Color"))
                {
                    bMat.diffuse = material.color.ToFloat();
                }

                if (material.HasProperty("_SpecColor"))
                {
                    var specColor = material.GetColor("_SpecColor");
                    bMat.specular = specColor.ToFloat();
                }

                if (material.HasProperty("_Shininess"))
                {
                    var specShininess = material.GetFloat("_Shininess");
                    bMat.specularPower = specShininess * 128;
                }

                if (material.HasProperty("_Emission"))
                {
                    var emissiveColor = material.GetColor("_Emission");
                    bMat.emissive = emissiveColor.ToFloat();
                }

                if (material.mainTexture)
                {
                    var mainTexturePath = AssetDatabase.GetAssetPath(material.mainTexture);
                    bMat.diffuseTexture = new BabylonTexture
                    {
                        uScale  = material.mainTextureScale.x,
                        vScale  = material.mainTextureScale.y,
                        uOffset = material.mainTextureOffset.x,
                        vOffset = material.mainTextureOffset.y
                    };

                    var mainTexture2D = material.mainTexture as Texture2D;

                    CopyTexture(mainTexturePath, mainTexture2D, bMat.diffuseTexture);

                    var alphaCuttOff = 0f;

                    if (material.HasProperty("_Cutoff"))
                    {
                        alphaCuttOff = material.GetFloat("_Cutoff");
                    }

                    if ((mainTexture2D && mainTexture2D.alphaIsTransparency) || alphaCuttOff > 0)
                    {
                        bMat.diffuseTexture.hasAlpha = true;
                        bMat.backFaceCulling         = false;
                    }

                    bMat.diffuse[0] = 1.0f;
                    bMat.diffuse[1] = 1.0f;
                    bMat.diffuse[2] = 1.0f;
                    bMat.diffuse[3] = 1.0f;
                }

                bMat.bumpTexture       = DumpTextureFromMaterial(material, "_BumpMap");
                bMat.emissiveTexture   = DumpTextureFromMaterial(material, "_Illum");
                bMat.ambientTexture    = DumpTextureFromMaterial(material, "_LightMap");
                bMat.reflectionTexture = DumpTextureFromMaterial(material, "_Cube");

                //if (bMat.ambientTexture == null && renderer.lightmapIndex >= 0 && renderer.lightmapIndex != 255 && LightmapSettings.lightmaps.Length > renderer.lightmapIndex)
                //{
                //    var lightmap = LightmapSettings.lightmaps[renderer.lightmapIndex].lightmapFar;
                //    bMat.ambientTexture = DumpTexture(lightmap);
                //    bMat.ambientTexture.coordinatesIndex = 1;

                //    bMat.ambientTexture.uScale = renderer.lightmapTilingOffset.x;
                //    bMat.ambientTexture.vScale = renderer.lightmapTilingOffset.y;

                //    bMat.ambientTexture.uOffset = renderer.lightmapTilingOffset.z;
                //    bMat.ambientTexture.vOffset = renderer.lightmapTilingOffset.w;
                //}

                materialsDictionary.Add(bMat.name, bMat);
                return(bMat);
            }

            return(materialsDictionary[material.name]);
        }