Pārlūkot izejas kodu

Export alpha from PBR materials
Ignore base color when exporting a base texture from PBR material
Same for emissive color

noalak 8 gadi atpakaļ
vecāks
revīzija
9e1b362d43

+ 2 - 2
Exporters/3ds Max/BabylonExport.Entities/BabylonPBRMetallicRoughnessMaterial.cs

@@ -59,7 +59,7 @@ namespace BabylonExport.Entities
         public float occlusionStrength { get; set; }
 
         [DataMember]
-        public BabylonTexture occlusionTexture { get; set; }
+        public BabylonTexture occlusionTexture { get; set; } // ignored
 
         [DataMember]
         public float alphaCutOff { get; set; }
@@ -68,7 +68,7 @@ namespace BabylonExport.Entities
         public int transparencyMode { get; set; }
 
         [DataMember]
-        public bool doubleSided { get; set; }
+        public bool doubleSided { get; set; } // ignored
 
         public BabylonPBRMetallicRoughnessMaterial() : base()
         {

+ 3 - 1
Exporters/3ds Max/Max2Babylon/Exporter/BabylonExporter.GLTFExporter.Material.cs

@@ -353,12 +353,14 @@ namespace Max2Babylon
                 // --- Global ---
 
                 // Base color
+                // TODO - Unclear if alpha must be retreived from 'alpha' property of BABYLON.Material
+                // or from alpha channel of 'baseColor' of BABYLON.PBRMetallicRoughnessMaterial
                 gltfPbrMetallicRoughness.baseColorFactor = new float[4]
                 {
                     babylonPBRMetallicRoughnessMaterial.baseColor[0],
                     babylonPBRMetallicRoughnessMaterial.baseColor[1],
                     babylonPBRMetallicRoughnessMaterial.baseColor[2],
-                    1.0f // TODO - alpha
+                    babylonPBRMetallicRoughnessMaterial.alpha
                 };
                 gltfPbrMetallicRoughness.baseColorTexture = ExportTexture(babylonPBRMetallicRoughnessMaterial.baseTexture, gltf);
 

+ 29 - 15
Exporters/3ds Max/Max2Babylon/Exporter/BabylonExporter.Material.cs

@@ -214,9 +214,20 @@ namespace Max2Babylon
 
                 // --- Global ---
 
-                babylonMaterial.alpha = 1.0f - materialNode.MaxMaterial.GetXParency(0, false);
+                // Alpha
+                // ---
+                // TODO - Unclear if alpha must be stored within 'alpha' property of BABYLON.Material
+                // or within alpha channel of 'baseColor' of BABYLON.PBRMetallicRoughnessMaterial
+                // ---
+                // TODO - XParency seems computed from several parameters
+                // 'Transparency' property is one of them
+                // Which value to use?
+                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 = alphaFromXParency;
 
-                // TODO - Add alpha
                 babylonMaterial.baseColor = materialNode.MaxMaterial.GetDiffuse(0, false).ToArray();
 
                 babylonMaterial.metallic = propertyContainer.GetFloatProperty(6);
@@ -233,22 +244,17 @@ namespace Max2Babylon
                                                 ? materialNode.MaxMaterial.GetSelfIllumColor(0, false).ToArray()
                                                 : materialNode.MaxMaterial.GetDiffuse(0, false).Scale(materialNode.MaxMaterial.GetSelfIllum(0, false));
 
-                // TODO - occlusionStrength - use default? ignored?
-
-                // TODO - alphaCutOff - use default?
-
-                // TODO - transparencyMode - private or public ?
-
-                // TODO - doubleSided - use default?
-
                 // --- Textures ---
+                
+                babylonMaterial.baseTexture = ExportBaseColorAlphaTexture(materialNode, babylonScene, name);
 
-                // TODO - Add alpha
-                babylonMaterial.baseTexture = ExportPBRTexture(materialNode, 1, babylonScene);
+                if (babylonMaterial.alpha != 1.0f || (babylonMaterial.baseTexture != null && babylonMaterial.baseTexture.hasAlpha))
+                {
+                    babylonMaterial.transparencyMode = (int)BabylonPBRMetallicRoughnessMaterial.TransparencyMode.ALPHABLEND;
+                }
 
                 babylonMaterial.metallicRoughnessTexture = ExportMetallicRoughnessTexture(materialNode, babylonMaterial.metallic, babylonMaterial.roughness, babylonScene, name);
-
-                // TODO - environmentTexture - as simple as that?
+                
                 babylonMaterial.environmentTexture = ExportPBRTexture(materialNode, 3, babylonScene);
 
                 var normalMapAmount = propertyContainer.GetFloatProperty(91);
@@ -256,8 +262,16 @@ namespace Max2Babylon
                 
                 babylonMaterial.emissiveTexture = ExportPBRTexture(materialNode, 17, babylonScene);
                 
-                // TODO - occlusionTexture - ignored?
+                // Constraints
+                if (babylonMaterial.baseTexture != null)
+                {
+                    babylonMaterial.baseColor = new[] { 1.0f, 1.0f, 1.0f };
+                }
 
+                if (babylonMaterial.emissiveTexture != null)
+                {
+                    babylonMaterial.emissiveColor = new float[] { 0, 0, 0 };
+                }
 
                 babylonScene.MaterialsList.Add(babylonMaterial);
             }

+ 112 - 13
Exporters/3ds Max/Max2Babylon/Exporter/BabylonExporter.Texture.cs

@@ -47,29 +47,118 @@ namespace Max2Babylon
             return null;
         }
 
-        private BabylonTexture ExportMetallicRoughnessTexture(IIGameMaterial materialNode, float metallic, float roughness, BabylonScene babylonScene, string materialName)
+        private BabylonTexture ExportBaseColorAlphaTexture(IIGameMaterial materialNode, BabylonScene babylonScene, string materialName)
         {
-            ITexmap metallicTexMap = _getTexMap(materialNode, 5);
-            ITexmap roughnessTexMap = _getTexMap(materialNode, 4);
+            ITexmap baseColorTexMap = _getTexMap(materialNode, 1);
+            ITexmap alphaTexMap = _getTexMap(materialNode, 9); // Transparency weight map
+
+            // --- Babylon texture ---
 
-            if (metallicTexMap == null && roughnessTexMap == null)
+            var baseColorTexture = _getBitmapTex(baseColorTexMap);
+            var alphaTexture = _getBitmapTex(alphaTexMap);
+
+            // Use one as a reference for UVs parameters
+            var texture = baseColorTexture != null ? baseColorTexture : alphaTexture;
+            if (texture == null)
             {
                 return null;
             }
 
-            // Use one as a reference for UVs parameters
-            var referenceTexMap = metallicTexMap != null ? metallicTexMap : roughnessTexMap;
+            var hasAlpha = alphaTexMap != null || (baseColorTexture != null && baseColorTexture.AlphaSource == 0); // Alpha source is 'Image Alpha'
+            
+            var babylonTexture = new BabylonTexture
+            {
+                name = materialName + "_baseColor" + (hasAlpha ? ".png" : ".jpg") // TODO - unsafe name, may conflict with another texture name
+            };
 
+            // Level
+            babylonTexture.level = 1.0f;
 
-            // --- Babylon texture ---
+            // Alpha
+            babylonTexture.hasAlpha = hasAlpha;
+            babylonTexture.getAlphaFromRGB = false;
 
-            if (referenceTexMap.GetParamBlock(0) == null || referenceTexMap.GetParamBlock(0).Owner == null)
+            // UVs
+            var uvGen = _exportUV(texture, babylonTexture);
+
+            // Is cube
+            _exportIsCube(texture, babylonTexture, false);
+
+
+            // --- Merge baseColor and alpha maps ---
+
+            // Load bitmaps
+            var baseColorBitmap = _loadTexture(baseColorTexMap);
+            var alphaBitmap = _loadTexture(alphaTexMap);
+
+            // Retreive dimensions
+            int width = 0;
+            int height = 0;
+            var haveSameDimensions = _getMinimalBitmapDimensions(out width, out height, baseColorBitmap, alphaBitmap);
+            if (!haveSameDimensions)
             {
-                return null;
+                RaiseWarning("Base color and transparency color maps should have same dimensions", 2);
             }
 
-            var texture = referenceTexMap.GetParamBlock(0).Owner as IBitmapTex;
+            var getAlphaFromRGB = false;
+            if (alphaTexture != null)
+            {
+                getAlphaFromRGB = (alphaTexture.AlphaSource == 2) || (alphaTexture.AlphaSource == 3); // 'RGB intensity' or 'None (Opaque)'
+            }
 
+            // Create baseColor+alpha map
+            Bitmap baseColorAlphaBitmap = new Bitmap(width, height);
+            for (int x = 0; x < width; x++)
+            {
+                for (int y = 0; y < height; y++)
+                {
+                    var baseColor = baseColorBitmap != null ? baseColorBitmap.GetPixel(x, y) : Color.FromArgb(255, 255, 255);
+
+                    Color baseColorAlpha;
+                    if (babylonTexture.hasAlpha)
+                    {
+                        if (alphaBitmap != null)
+                        {
+                            // Retreive alpha from alpha texture
+                            var alphaColor = alphaBitmap.GetPixel(x, y);
+                            var alpha = getAlphaFromRGB ? alphaColor.R : alphaColor.A;
+                            baseColorAlpha = Color.FromArgb(alpha, baseColor);
+                        }
+                        else
+                        {
+                            // Use all channels from base color
+                            baseColorAlpha = baseColor;
+                        }
+                    }
+                    else
+                    {
+                        // Only use RGB channels from base color
+                        baseColorAlpha = Color.FromArgb(baseColor.R, baseColor.G, baseColor.B);
+                    }
+                    baseColorAlphaBitmap.SetPixel(x, y, baseColorAlpha);
+                }
+            }
+
+            // Write bitmap
+            var absolutePath = Path.Combine(babylonScene.OutputPath, babylonTexture.name);
+            RaiseMessage($"Texture | write image '{babylonTexture.name}'", 2);
+            baseColorAlphaBitmap.Save(absolutePath);
+
+            return babylonTexture;
+        }
+
+        private BabylonTexture ExportMetallicRoughnessTexture(IIGameMaterial materialNode, float metallic, float roughness, BabylonScene babylonScene, string materialName)
+        {
+            ITexmap metallicTexMap = _getTexMap(materialNode, 5);
+            ITexmap roughnessTexMap = _getTexMap(materialNode, 4);
+
+            // --- Babylon texture ---
+            
+            var metallicTexture = _getBitmapTex(metallicTexMap);
+            var roughnessTexture = _getBitmapTex(roughnessTexMap);
+
+            // Use one as a reference for UVs parameters
+            var texture = metallicTexture != null ? metallicTexture : roughnessTexture;
             if (texture == null)
             {
                 return null;
@@ -170,12 +259,12 @@ namespace Max2Babylon
             if (forceAlpha)
             {
                 babylonTexture.hasAlpha = true;
-                babylonTexture.getAlphaFromRGB = (texture.AlphaSource == 2) || (texture.AlphaSource == 3);
+                babylonTexture.getAlphaFromRGB = (texture.AlphaSource == 2) || (texture.AlphaSource == 3); // 'RGB intensity' or 'None (Opaque)'
             }
             else
             {
-                babylonTexture.hasAlpha = (texture.AlphaSource != 3);
-                babylonTexture.getAlphaFromRGB = (texture.AlphaSource == 2);
+                babylonTexture.hasAlpha = (texture.AlphaSource != 3); // Not 'None (Opaque)'
+                babylonTexture.getAlphaFromRGB = (texture.AlphaSource == 2); // 'RGB intensity'
             }
 
             // UVs
@@ -408,6 +497,16 @@ namespace Max2Babylon
         // --------- Utils ---------
         // -------------------------
 
+        private IBitmapTex _getBitmapTex(ITexmap texMap)
+        {
+            if (texMap == null || texMap.GetParamBlock(0) == null || texMap.GetParamBlock(0).Owner == null)
+            {
+                return null;
+            }
+
+            return texMap.GetParamBlock(0).Owner as IBitmapTex;
+        }
+
         private ITexmap _getTexMap(IIGameMaterial materialNode, int index)
         {
             ITexmap texMap = null;