private Schema.MaterialPbrSpecularGlossiness ConvertMaterialPbrSpecularGlossiness(KHR_materials_pbrSpecularGlossiness runtimeMaterial) { var material = CreateInstance <Schema.MaterialPbrSpecularGlossiness>(); if (runtimeMaterial.DiffuseFactor.HasValue) { material.DiffuseFactor = runtimeMaterial.DiffuseFactor.Value.ToArray(); } if (runtimeMaterial.DiffuseTexture != null) { material.DiffuseTexture = ConvertTextureInfo(runtimeMaterial.DiffuseTexture); } if (runtimeMaterial.SpecularFactor.HasValue) { material.SpecularFactor = runtimeMaterial.SpecularFactor.Value.ToArray(); } if (runtimeMaterial.GlossinessFactor.HasValue) { material.GlossinessFactor = runtimeMaterial.GlossinessFactor.Value; } if (runtimeMaterial.SpecularGlossinessTexture != null) { material.SpecularGlossinessTexture = ConvertTextureInfo(runtimeMaterial.SpecularGlossinessTexture); } return(material); }
public Material_SpecularGlossiness(List <string> imageList) { Runtime.Image diffuseTextureImage = UseTexture(imageList, "Diffuse_Plane"); Runtime.Image specularGlossinessTextureImage = UseTexture(imageList, "SpecularGlossiness_Plane"); Runtime.Image baseColorTextureImage = UseTexture(imageList, "BaseColor_X"); // Track the common properties for use in the readme. CommonProperties.Add(new Property(PropertyName.ExtensionUsed, "Specular Glossiness")); CommonProperties.Add(new Property(PropertyName.ExtensionRequired, "Specular Glossiness")); CommonProperties.Add(new Property(PropertyName.BaseColorTexture, baseColorTextureImage)); Model CreateModel(Action <List <Property>, Runtime.MeshPrimitive, Runtime.Material, KHR_materials_pbrSpecularGlossiness> setProperties) { var properties = new List <Property>(); var meshPrimitive = MeshPrimitive.CreateSinglePlane(); var extension = new KHR_materials_pbrSpecularGlossiness(); meshPrimitive.Material = new Runtime.Material(); meshPrimitive.Material.Extensions = new List <Extension> { extension }; meshPrimitive.Material.MetallicRoughnessMaterial = new Runtime.PbrMetallicRoughness(); // Apply the common properties to the gltf. meshPrimitive.Material.MetallicRoughnessMaterial.BaseColorTexture = new Runtime.Texture { Source = baseColorTextureImage }; // Apply the properties that are specific to this gltf. setProperties(properties, meshPrimitive, meshPrimitive.Material, extension); // Create the gltf object. return(new Model { Properties = properties, GLTF = CreateGLTF(() => new Runtime.Scene { Nodes = new[] { new Runtime.Node { Mesh = new Runtime.Mesh { MeshPrimitives = new[] { meshPrimitive } }, }, }, }, extensionsUsed: new List <string> { "KHR_materials_pbrSpecularGlossiness" }, extensionsRequired: new List <string> { "KHR_materials_pbrSpecularGlossiness" }), }); } void SetVertexColor(List <Property> properties, Runtime.MeshPrimitive meshPrimitive) { var vertexColors = new[] { new Vector4(0.0f, 0.0f, 1.0f, 0.8f), new Vector4(1.0f, 0.0f, 0.0f, 0.8f), new Vector4(0.0f, 0.0f, 1.0f, 0.8f), new Vector4(1.0f, 0.0f, 0.0f, 0.8f) }; meshPrimitive.ColorComponentType = ColorComponentTypeEnum.FLOAT; meshPrimitive.ColorType = ColorTypeEnum.VEC3; meshPrimitive.Colors = vertexColors; properties.Add(new Property(PropertyName.VertexColor, "Vector3 Float")); } void SetDiffuseTexture(List <Property> properties, KHR_materials_pbrSpecularGlossiness extension) { extension.DiffuseTexture = new Runtime.Texture { Source = diffuseTextureImage }; properties.Add(new Property(PropertyName.DiffuseTexture, diffuseTextureImage)); } void SetDiffuseFactor(List <Property> properties, KHR_materials_pbrSpecularGlossiness extension) { var diffuseFactorValue = new Vector4(0.2f, 0.2f, 0.2f, 0.8f); extension.DiffuseFactor = diffuseFactorValue; properties.Add(new Property(PropertyName.DiffuseFactor, diffuseFactorValue)); } void SetSpecularGlossinessTexture(List <Property> properties, KHR_materials_pbrSpecularGlossiness extension) { extension.SpecularGlossinessTexture = new Runtime.Texture { Source = specularGlossinessTextureImage }; properties.Add(new Property(PropertyName.SpecularGlossinessTexture, specularGlossinessTextureImage)); } void SetSpecularFactor(List <Property> properties, KHR_materials_pbrSpecularGlossiness extension) { var specularFactorValue = new Vector3(0.4f, 0.4f, 0.4f); extension.SpecularFactor = specularFactorValue; properties.Add(new Property(PropertyName.SpecularFactor, specularFactorValue)); } void SetSpecularFactorToZero(List <Property> properties, KHR_materials_pbrSpecularGlossiness extension) { var specularFactorValue = new Vector3(0.0f, 0.0f, 0.0f); extension.SpecularFactor = specularFactorValue; properties.Add(new Property(PropertyName.SpecularFactor, specularFactorValue)); } void SetGlossinessFactor(List <Property> properties, KHR_materials_pbrSpecularGlossiness extension) { extension.GlossinessFactor = 0.3f; properties.Add(new Property(PropertyName.GlossinessFactor, extension.GlossinessFactor)); } Models = new List <Model> { CreateModel((properties, meshPrimitive, material, extension) => { // There are no properties set on this model. }), CreateModel((properties, meshPrimitive, material, extension) => { SetVertexColor(properties, meshPrimitive); SetSpecularFactorToZero(properties, extension); }), CreateModel((properties, meshPrimitive, material, extension) => { SetDiffuseTexture(properties, extension); SetSpecularFactorToZero(properties, extension); }), CreateModel((properties, meshPrimitive, material, extension) => { SetDiffuseFactor(properties, extension); SetSpecularFactorToZero(properties, extension); }), CreateModel((properties, meshPrimitive, material, extension) => { SetSpecularGlossinessTexture(properties, extension); }), CreateModel((properties, meshPrimitive, material, extension) => { SetSpecularFactor(properties, extension); }), CreateModel((properties, meshPrimitive, material, extension) => { SetGlossinessFactor(properties, extension); }), CreateModel((properties, meshPrimitive, material, extension) => { SetVertexColor(properties, meshPrimitive); SetDiffuseTexture(properties, extension); SetSpecularFactorToZero(properties, extension); }), CreateModel((properties, meshPrimitive, material, extension) => { SetDiffuseTexture(properties, extension); SetDiffuseFactor(properties, extension); SetSpecularFactorToZero(properties, extension); }), CreateModel((properties, meshPrimitive, material, extension) => { SetDiffuseTexture(properties, extension); SetGlossinessFactor(properties, extension); }), CreateModel((properties, meshPrimitive, material, extension) => { SetSpecularGlossinessTexture(properties, extension); SetSpecularFactor(properties, extension); }), CreateModel((properties, meshPrimitive, material, extension) => { SetSpecularGlossinessTexture(properties, extension); SetGlossinessFactor(properties, extension); }), CreateModel((properties, meshPrimitive, material, extension) => { SetDiffuseTexture(properties, extension); SetSpecularFactor(properties, extension); SetGlossinessFactor(properties, extension); }), CreateModel((properties, meshPrimitive, material, extension) => { SetVertexColor(properties, meshPrimitive); SetDiffuseTexture(properties, extension); SetDiffuseFactor(properties, extension); SetSpecularGlossinessTexture(properties, extension); SetSpecularFactor(properties, extension); SetGlossinessFactor(properties, extension); }), }; GenerateUsedPropertiesList(); }
public Compatibility(List <string> imageList) { NoSampleImages = true; // There are no common properties in this model group. Model CreateModel(Action <List <Property>, Asset, List <string>, List <string>, Runtime.MeshPrimitive> setProperties, Action <Schema.Gltf> postRuntimeChanges = null, Dictionary <Type, Type> schemaTypeMapping = null, bool?setLoadableTag = true) { var properties = new List <Property>(); var gltf = CreateGLTF(() => new Scene()); Runtime.MeshPrimitive meshPrimitive = MeshPrimitive.CreateSinglePlane(includeTextureCoords: false); var extensionsUsed = new List <string>(); var extensionsRequired = new List <string>(); // Apply the properties that are specific to this gltf. setProperties(properties, gltf.Asset, extensionsUsed, extensionsRequired, meshPrimitive); // Create the gltf object. if (extensionsUsed.Any()) { gltf.ExtensionsUsed = extensionsUsed; } if (extensionsRequired.Any()) { gltf.ExtensionsRequired = extensionsRequired; } gltf.Scenes.First().Nodes = new List <Node> { new Node { Mesh = new Runtime.Mesh { MeshPrimitives = new List <Runtime.MeshPrimitive> { meshPrimitive } }, }, }; var model = new Model { Properties = properties, GLTF = gltf }; model.Loadable = setLoadableTag; model.PostRuntimeChanges = postRuntimeChanges; if (schemaTypeMapping != null) { model.CreateSchemaInstance = type => { if (schemaTypeMapping.TryGetValue(type, out Type mappedType)) { type = mappedType; } return(Activator.CreateInstance(type)); }; } return(model); } Property SetMinVersion(Asset asset) { return(new Property(PropertyName.MinVersion, asset.MinVersion = "2.1")); } Property SetVersionCurrent(Asset asset) { return(new Property(PropertyName.Version, asset.Version = "2.0")); } Property SetVersionFuture(Asset asset) { return(new Property(PropertyName.Version, asset.Version = "2.1")); } void SetPostRuntimeAtRoot(Schema.Gltf gltf) { // Add an simulated feature at the root level. var experimentalGltf = (ExperimentalGltf)gltf; experimentalGltf.Lights = new[] { new ExperimentalLight { Color = new[] { 0.3f, 0.4f, 0.5f } } }; } void SetPostRuntimeInProperty(Schema.Gltf gltf) { // Add an simulated feature into an existing property. var experimentalNode = (ExperimentalNode)gltf.Nodes[0]; experimentalNode.Light = 0; } void SetPostRuntimeWithFallback(Schema.Gltf gltf) { // Add an simulated feature with a fallback option. gltf.Materials = new Schema.Material[] { new ExperimentalMaterial { AlphaMode = Schema.Material.AlphaModeEnum.BLEND, AlphaMode2 = ExperimentalAlphaMode2.QUANTUM, } }; } var experimentalSchemaTypeMapping = new Dictionary <Type, Type> { { typeof(Schema.Gltf), typeof(ExperimentalGltf) }, { typeof(Schema.Node), typeof(ExperimentalNode) }, { typeof(Schema.Material), typeof(ExperimentalMaterial) }, }; var shouldLoad = ":white_check_mark:"; Models = new List <Model> { CreateModel((properties, asset, extensionsUsed, extensionsRequired, meshPrimitive) => { properties.Add(SetVersionCurrent(asset)); properties.Add(new Property(PropertyName.ModelShouldLoad, shouldLoad)); }), CreateModel((properties, asset, extensionsUsed, extensionsRequired, meshPrimitive) => { properties.Add(SetVersionFuture(asset)); properties.Add(new Property(PropertyName.Description, "Light object added at root")); properties.Add(new Property(PropertyName.ModelShouldLoad, shouldLoad)); }, SetPostRuntimeAtRoot, experimentalSchemaTypeMapping), CreateModel((properties, asset, extensionsUsed, extensionsRequired, meshPrimitive) => { properties.Add(SetVersionFuture(asset)); properties.Add(new Property(PropertyName.Description, "Light property added to node object")); properties.Add(new Property(PropertyName.ModelShouldLoad, shouldLoad)); }, SetPostRuntimeInProperty, experimentalSchemaTypeMapping), CreateModel((properties, asset, extensionsUsed, extensionsRequired, meshPrimitive) => { properties.Add(SetVersionFuture(asset)); properties.Add(new Property(PropertyName.Description, "Alpha mode updated with a new enum value, and a fallback value")); properties.Add(new Property(PropertyName.ModelShouldLoad, shouldLoad)); }, SetPostRuntimeWithFallback, experimentalSchemaTypeMapping), CreateModel((properties, asset, extensionsUsed, extensionsRequired, meshPrimitive) => { properties.Add(SetMinVersion(asset)); properties.Add(SetVersionFuture(asset)); properties.Add(new Property(PropertyName.Description, "Requires a specific version or higher")); properties.Add(new Property(PropertyName.ModelShouldLoad, "Only in version 2.1 or higher")); }, null, null, setLoadableTag: false), CreateModel((properties, asset, extensionsUsed, extensionsRequired, meshPrimitive) => { properties.Add(SetVersionCurrent(asset)); var emptyTexture = new Texture(); var extension = new FAKE_materials_quantumRendering { PlanckFactor = new Vector4(0.2f, 0.2f, 0.2f, 0.8f), CopenhagenTexture = new TextureInfo { Texture = emptyTexture }, EntanglementFactor = new Vector3(0.4f, 0.4f, 0.4f), ProbabilisticFactor = 0.3f, SuperpositionCollapseTexture = new TextureInfo { Texture = emptyTexture }, }; meshPrimitive.Material = new Runtime.Material { Extensions = new List <Extension> { extension } }; extensionsUsed.Add(extension.Name); extensionsRequired.Add(extension.Name); properties.Add(new Property(PropertyName.Description, "Extension required")); properties.Add(new Property(PropertyName.ModelShouldLoad, ":x:")); }, null, null, setLoadableTag: false), CreateModel((properties, asset, extensionsUsed, extensionsRequired, meshPrimitive) => { properties.Add(SetVersionCurrent(asset)); var extension = new KHR_materials_pbrSpecularGlossiness { SpecularFactor = new Vector3(0.04f, 0.04f, 0.04f), GlossinessFactor = 0.0f, }; meshPrimitive.Material = new Runtime.Material { // Metallic-Roughness PbrMetallicRoughness = new PbrMetallicRoughness { MetallicFactor = 0.0f }, // Specular-Glossiness Extensions = new[] { extension }, }; extensionsUsed.Add(extension.Name); properties.Add(new Property(PropertyName.Description, "Specular Glossiness extension used but not required")); properties.Add(new Property(PropertyName.ModelShouldLoad, shouldLoad)); }), }; GenerateUsedPropertiesList(); }
private void ExportMaterial(BabylonMaterial babylonMaterial, GLTF gltf) { var name = babylonMaterial.name; var id = babylonMaterial.id; logger.RaiseMessage("GLTFExporter.Material | Export material named: " + name, 1); GLTFMaterial gltfMaterial = null; IGLTFMaterialExporter customMaterialExporter = exportParameters.customGLTFMaterialExporter; if (customMaterialExporter != null && customMaterialExporter.GetGltfMaterial(babylonMaterial, gltf, logger, out gltfMaterial)) { gltfMaterial.index = gltf.MaterialsList.Count; gltf.MaterialsList.Add(gltfMaterial); } else if (babylonMaterial is BabylonStandardMaterial babylonStandardMaterial) { // --- prints --- #region prints logger.RaiseVerbose("GLTFExporter.Material | babylonMaterial data", 2); logger.RaiseVerbose("GLTFExporter.Material | babylonMaterial.alpha=" + babylonMaterial.alpha, 3); logger.RaiseVerbose("GLTFExporter.Material | babylonMaterial.alphaMode=" + babylonMaterial.alphaMode, 3); logger.RaiseVerbose("GLTFExporter.Material | babylonMaterial.backFaceCulling=" + babylonMaterial.backFaceCulling, 3); logger.RaiseVerbose("GLTFExporter.Material | babylonMaterial.wireframe=" + babylonMaterial.wireframe, 3); // Ambient for (int i = 0; i < babylonStandardMaterial.ambient.Length; i++) { logger.RaiseVerbose("GLTFExporter.Material | babylonStandardMaterial.ambient[" + i + "]=" + babylonStandardMaterial.ambient[i], 3); } // Diffuse logger.RaiseVerbose("GLTFExporter.Material | babylonStandardMaterial.diffuse.Length=" + babylonStandardMaterial.diffuse.Length, 3); for (int i = 0; i < babylonStandardMaterial.diffuse.Length; i++) { logger.RaiseVerbose("GLTFExporter.Material | babylonStandardMaterial.diffuse[" + i + "]=" + babylonStandardMaterial.diffuse[i], 3); } if (babylonStandardMaterial.diffuseTexture == null) { logger.RaiseVerbose("GLTFExporter.Material | babylonStandardMaterial.diffuseTexture=null", 3); } else { logger.RaiseVerbose("GLTFExporter.Material | babylonStandardMaterial.diffuseTexture.name=" + babylonStandardMaterial.diffuseTexture.name, 3); } // Normal / bump if (babylonStandardMaterial.bumpTexture == null) { logger.RaiseVerbose("GLTFExporter.Material | babylonStandardMaterial.bumpTexture=null", 3); } else { logger.RaiseVerbose("GLTFExporter.Material | babylonStandardMaterial.bumpTexture.name=" + babylonStandardMaterial.bumpTexture.name, 3); } // Opacity if (babylonStandardMaterial.opacityTexture == null) { logger.RaiseVerbose("GLTFExporter.Material | babylonStandardMaterial.opacityTexture=null", 3); } else { logger.RaiseVerbose("GLTFExporter.Material | babylonStandardMaterial.opacityTexture.name=" + babylonStandardMaterial.opacityTexture.name, 3); } // Specular for (int i = 0; i < babylonStandardMaterial.specular.Length; i++) { logger.RaiseVerbose("GLTFExporter.Material | babylonStandardMaterial.specular[" + i + "]=" + babylonStandardMaterial.specular[i], 3); } logger.RaiseVerbose("GLTFExporter.Material | babylonStandardMaterial.specularPower=" + babylonStandardMaterial.specularPower, 3); if (babylonStandardMaterial.specularTexture == null) { logger.RaiseVerbose("GLTFExporter.Material | babylonStandardMaterial.specularTexture=null", 3); } else { logger.RaiseVerbose("GLTFExporter.Material | babylonStandardMaterial.specularTexture.name=" + babylonStandardMaterial.specularTexture.name, 3); } // Occlusion if (babylonStandardMaterial.ambientTexture == null) { logger.RaiseVerbose("GLTFExporter.Material | babylonStandardMaterial.ambientTexture=null", 3); } else { logger.RaiseVerbose("GLTFExporter.Material | babylonStandardMaterial.ambientTexture.name=" + babylonStandardMaterial.ambientTexture.name, 3); } // Emissive for (int i = 0; i < babylonStandardMaterial.emissive.Length; i++) { logger.RaiseVerbose("GLTFExporter.Material | babylonStandardMaterial.emissive[" + i + "]=" + babylonStandardMaterial.emissive[i], 3); } if (babylonStandardMaterial.emissiveTexture == null) { logger.RaiseVerbose("GLTFExporter.Material | babylonStandardMaterial.emissiveTexture=null", 3); } else { logger.RaiseVerbose("GLTFExporter.Material | babylonStandardMaterial.emissiveTexture.name=" + babylonStandardMaterial.emissiveTexture.name, 3); } #endregion // -------------------------------- // --------- gltfMaterial --------- // -------------------------------- logger.RaiseMessage("GLTFExporter.Material | create gltfMaterial", 2); gltfMaterial = new GLTFMaterial { name = name }; gltfMaterial.id = babylonMaterial.id; gltfMaterial.index = gltf.MaterialsList.Count; gltf.MaterialsList.Add(gltfMaterial); //Custom user properties if (babylonStandardMaterial.metadata != null && babylonStandardMaterial.metadata.Count != 0) { gltfMaterial.extras = babylonStandardMaterial.metadata; } // Alpha GLTFMaterial.AlphaMode alphaMode; float?alphaCutoff; getAlphaMode(babylonStandardMaterial, out alphaMode, out alphaCutoff); gltfMaterial.alphaMode = alphaMode; if (alphaCutoff.HasValue && alphaCutoff.Value != 0.5f) // do not export glTF default value { gltfMaterial.alphaCutoff = alphaCutoff; } // DoubleSided gltfMaterial.doubleSided = !babylonMaterial.backFaceCulling; // Normal gltfMaterial.normalTexture = ExportTexture(babylonStandardMaterial.bumpTexture, gltf); // Occlusion 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 --- // -------------------------------- logger.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; string baseColorBitmapName = null; string metallicRoughnessBitmapName = null; GLTFTextureInfo textureInfoBC = null; GLTFTextureInfo textureInfoMR = null; if (exportParameters.writeTextures) { // Diffuse Bitmap diffuseBitmap = null; if (babylonStandardMaterial.diffuseTexture != null) { if (babylonStandardMaterial.diffuseTexture.bitmap != null) { // Diffuse color map has been computed by the exporter diffuseBitmap = babylonStandardMaterial.diffuseTexture.bitmap; } else { // Diffuse color map is straight input diffuseBitmap = TextureUtilities.LoadTexture(babylonStandardMaterial.diffuseTexture.originalPath, logger); babylonStandardMaterial.diffuseTexture.bitmap = diffuseBitmap; } } // 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 = TextureUtilities.LoadTexture(babylonStandardMaterial.specularTexture.originalPath, logger); } } // Opacity / Alpha / Transparency Bitmap opacityBitmap = null; if ((babylonStandardMaterial.diffuseTexture == null || babylonStandardMaterial.diffuseTexture.hasAlpha == false) && babylonStandardMaterial.opacityTexture != null) { opacityBitmap = TextureUtilities.LoadTexture(babylonStandardMaterial.opacityTexture.originalPath, logger); } if ((diffuseBitmap != null && (specularBitmap != null || opacityBitmap != null)) || specularBitmap != null || opacityBitmap != null) { // Retreive dimensions int width = 0; int height = 0; var haveSameDimensions = TextureUtilities.GetMinimalBitmapDimensions(out width, out height, diffuseBitmap, specularBitmap, opacityBitmap); if (!haveSameDimensions) { logger.RaiseError("Diffuse, specular and opacity maps should have same dimensions", 2); } baseColorBitmapName = (babylonStandardMaterial.diffuseTexture != null ? Path.GetFileNameWithoutExtension(babylonStandardMaterial.diffuseTexture.name) : TextureUtilities.ColorToStringName(Color.FromArgb(255, (int)(babylonStandardMaterial.diffuse[0]), (int)(babylonStandardMaterial.diffuse[1]), (int)(babylonStandardMaterial.diffuse[2])))) + (babylonStandardMaterial.opacityTexture != null ? "_alpha_" + Path.GetFileNameWithoutExtension(babylonStandardMaterial.opacityTexture.name) : "") + ".png"; metallicRoughnessBitmapName = "MR_" + baseColorBitmapName + "_spec_" + (babylonStandardMaterial.specularTexture != null ? Path.GetFileNameWithoutExtension(babylonStandardMaterial.specularTexture.name) : TextureUtilities.ColorToStringName(Color.FromArgb(255, (int)(babylonStandardMaterial.specular[0]), (int)(babylonStandardMaterial.specular[1]), (int)(babylonStandardMaterial.specular[2])))) + "_gloss_" + babylonStandardMaterial.specularPower + ".png"; // 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 if (baseColorBitmap != null || babylonTexture.bitmap != null) { textureInfoBC = ExportBitmapTexture(gltf, babylonTexture, baseColorBitmap, baseColorBitmapName); gltfPbrMetallicRoughness.baseColorTexture = textureInfoBC; } if (isTextureOk(babylonStandardMaterial.specularTexture)) { textureInfoMR = ExportBitmapTexture(gltf, babylonTexture, metallicRoughnessBitmap, metallicRoughnessBitmapName); gltfPbrMetallicRoughness.metallicRoughnessTexture = textureInfoMR; } //register the texture AddStandText(_key, textureInfoBC, textureInfoMR); } // Constraints if (gltfPbrMetallicRoughness.baseColorTexture != null) { gltfPbrMetallicRoughness.baseColorFactor[3] = 1.0f; } if (gltfPbrMetallicRoughness.metallicRoughnessTexture != null) { gltfPbrMetallicRoughness.metallicFactor = 1.0f; gltfPbrMetallicRoughness.roughnessFactor = 1.0f; } } } else if (typeof(BabylonPBRBaseSimpleMaterial).IsAssignableFrom(babylonMaterial.GetType())) { var babylonPBRBaseSimpleMaterial = babylonMaterial as BabylonPBRBaseSimpleMaterial; // --- prints --- #region prints logger.RaiseVerbose("GLTFExporter.Material | babylonMaterial data", 2); logger.RaiseVerbose("GLTFExporter.Material | babylonMaterial.alpha=" + babylonMaterial.alpha, 3); logger.RaiseVerbose("GLTFExporter.Material | babylonMaterial.alphaMode=" + babylonMaterial.alphaMode, 3); logger.RaiseVerbose("GLTFExporter.Material | babylonMaterial.backFaceCulling=" + babylonMaterial.backFaceCulling, 3); logger.RaiseVerbose("GLTFExporter.Material | babylonMaterial.wireframe=" + babylonMaterial.wireframe, 3); // Global logger.RaiseVerbose("GLTFExporter.Material | babylonPBRBaseSimpleMaterial.maxSimultaneousLights=" + babylonPBRBaseSimpleMaterial.maxSimultaneousLights, 3); logger.RaiseVerbose("GLTFExporter.Material | babylonPBRBaseSimpleMaterial.disableLighting=" + babylonPBRBaseSimpleMaterial.disableLighting, 3); logger.RaiseVerbose("GLTFExporter.Material | babylonPBRBaseSimpleMaterial.alphaCutOff=" + babylonPBRBaseSimpleMaterial.alphaCutOff, 3); logger.RaiseVerbose("GLTFExporter.Material | babylonPBRBaseSimpleMaterial.transparencyMode=" + babylonPBRBaseSimpleMaterial.transparencyMode, 3); logger.RaiseVerbose("GLTFExporter.Material | babylonPBRBaseSimpleMaterial.doubleSided=" + babylonPBRBaseSimpleMaterial.doubleSided, 3); // Base color logger.RaiseVerbose("GLTFExporter.Material | babylonPBRBaseSimpleMaterial.baseColor.Length=" + babylonPBRBaseSimpleMaterial.baseColor.Length, 3); for (int i = 0; i < babylonPBRBaseSimpleMaterial.baseColor.Length; i++) { logger.RaiseVerbose("GLTFExporter.Material | babylonPBRBaseSimpleMaterial.baseColor[" + i + "]=" + babylonPBRBaseSimpleMaterial.baseColor[i], 3); } if (babylonPBRBaseSimpleMaterial.baseTexture == null) { logger.RaiseVerbose("GLTFExporter.Material | babylonPBRBaseSimpleMaterial.baseTexture=null", 3); } // Normal / bump if (babylonPBRBaseSimpleMaterial.normalTexture == null) { logger.RaiseVerbose("GLTFExporter.Material | babylonPBRBaseSimpleMaterial.normalTexture=null", 3); } logger.RaiseVerbose("GLTFExporter.Material | babylonPBRBaseSimpleMaterial.invertNormalMapX=" + babylonPBRBaseSimpleMaterial.invertNormalMapX, 3); logger.RaiseVerbose("GLTFExporter.Material | babylonPBRBaseSimpleMaterial.invertNormalMapY=" + babylonPBRBaseSimpleMaterial.invertNormalMapY, 3); // Emissive for (int i = 0; i < babylonPBRBaseSimpleMaterial.emissive.Length; i++) { logger.RaiseVerbose("GLTFExporter.Material | babylonPBRBaseSimpleMaterial.emissiveColor[" + i + "]=" + babylonPBRBaseSimpleMaterial.emissive[i], 3); } if (babylonPBRBaseSimpleMaterial.emissiveTexture == null) { logger.RaiseVerbose("GLTFExporter.Material | babylonPBRBaseSimpleMaterial.emissiveTexture=null", 3); } // Ambient occlusion logger.RaiseVerbose("GLTFExporter.Material | babylonPBRBaseSimpleMaterial.occlusionStrength=" + babylonPBRBaseSimpleMaterial.occlusionStrength, 3); if (babylonPBRBaseSimpleMaterial.occlusionTexture == null) { logger.RaiseVerbose("GLTFExporter.Material | babylonPBRBaseSimpleMaterial.occlusionTexture=null", 3); } if (babylonMaterial is BabylonPBRMetallicRoughnessMaterial pbrMRMatPrint) { // Metallic+roughness logger.RaiseVerbose("GLTFExporter.Material | babylonPBRMetallicRoughnessMaterial.metallic=" + pbrMRMatPrint.metallic, 3); logger.RaiseVerbose("GLTFExporter.Material | babylonPBRMetallicRoughnessMaterial.roughness=" + pbrMRMatPrint.roughness, 3); if (pbrMRMatPrint.metallicRoughnessTexture == null) { logger.RaiseVerbose("GLTFExporter.Material | babylonPBRMetallicRoughnessMaterial.metallicRoughnessTexture=null", 3); } } else if (babylonMaterial is BabylonPBRSpecularGlossinessMaterial pbrSGMatPrint) { // Metallic+roughness logger.RaiseVerbose("GLTFExporter.Material | babylonPBRSpecularGlossinessMaterial.specular=" + pbrSGMatPrint.specularColor, 3); logger.RaiseVerbose("GLTFExporter.Material | babylonPBRSpecularGlossinessMaterial.glossiness=" + pbrSGMatPrint.glossiness, 3); if (pbrSGMatPrint.specularGlossinessTexture == null) { logger.RaiseVerbose("GLTFExporter.Material | babylonPBRSpecularGlossinessMaterial.specularGlossinessTexture=null", 3); } } #endregion // -------------------------------- // --------- gltfMaterial --------- // -------------------------------- logger.RaiseMessage("GLTFExporter.Material | create gltfMaterial", 2); gltfMaterial = new GLTFMaterial { name = name }; gltfMaterial.id = babylonMaterial.id; gltfMaterial.index = gltf.MaterialsList.Count; gltf.MaterialsList.Add(gltfMaterial); //Custom user properties if (babylonMaterial.metadata != null && babylonMaterial.metadata.Count != 0) { gltfMaterial.extras = babylonMaterial.metadata; } // Alpha GLTFMaterial.AlphaMode alphaMode; float?alphaCutoff; getAlphaMode(babylonPBRBaseSimpleMaterial, out alphaMode, out alphaCutoff); gltfMaterial.alphaMode = alphaMode; if (alphaCutoff.HasValue && alphaCutoff.Value != 0.5f) // do not export glTF default value { gltfMaterial.alphaCutoff = alphaCutoff; } // DoubleSided gltfMaterial.doubleSided = babylonPBRBaseSimpleMaterial.doubleSided; // Normal gltfMaterial.normalTexture = ExportTexture(babylonPBRBaseSimpleMaterial.normalTexture, gltf); // Occlusion if (babylonPBRBaseSimpleMaterial.occlusionTexture != null) { if (babylonPBRBaseSimpleMaterial.occlusionTexture.bitmap != null) { // ORM texture has been merged manually by the exporter // Occlusion is defined as well as metallic and/or roughness logger.RaiseVerbose("Occlusion is defined as well as metallic and/or roughness", 2); gltfMaterial.occlusionTexture = ExportBitmapTexture(gltf, babylonPBRBaseSimpleMaterial.occlusionTexture); } else { // ORM texture was already merged or only occlusion is defined logger.RaiseVerbose("ORM texture was already merged or only occlusion is defined", 2); gltfMaterial.occlusionTexture = ExportTexture(babylonPBRBaseSimpleMaterial.occlusionTexture, gltf); } } // Emissive gltfMaterial.emissiveFactor = babylonPBRBaseSimpleMaterial.emissive; gltfMaterial.emissiveTexture = ExportTexture(babylonPBRBaseSimpleMaterial.emissiveTexture, gltf); // -------------------------------- // --- gltfPbrMetallicRoughness --- // -------------------------------- if (babylonMaterial is BabylonPBRMetallicRoughnessMaterial pbrMRMat) { // Metallic+roughness logger.RaiseVerbose("GLTFExporter.Material | babylonPBRMetallicRoughnessMaterial.metallic=" + pbrMRMat.metallic, 3); logger.RaiseVerbose("GLTFExporter.Material | babylonPBRMetallicRoughnessMaterial.roughness=" + pbrMRMat.roughness, 3); if (pbrMRMat.metallicRoughnessTexture == null) { logger.RaiseVerbose("GLTFExporter.Material | babylonPBRMetallicRoughnessMaterial.metallicRoughnessTexture=null", 3); } logger.RaiseMessage("GLTFExporter.Material | create gltfPbrMetallicRoughness", 2); var gltfPbrMetallicRoughness = new GLTFPBRMetallicRoughness(); gltfMaterial.pbrMetallicRoughness = gltfPbrMetallicRoughness; // --- Global --- // Base color gltfPbrMetallicRoughness.baseColorFactor = new float[4] { pbrMRMat.baseColor[0], pbrMRMat.baseColor[1], pbrMRMat.baseColor[2], pbrMRMat.alpha }; if (pbrMRMat.baseTexture != null) { gltfPbrMetallicRoughness.baseColorTexture = ExportBaseColorTexture(gltf, pbrMRMat.baseTexture); } // Metallic roughness gltfPbrMetallicRoughness.metallicFactor = pbrMRMat.metallic; gltfPbrMetallicRoughness.roughnessFactor = pbrMRMat.roughness; if (pbrMRMat.metallicRoughnessTexture != null) { if (pbrMRMat.metallicRoughnessTexture == pbrMRMat.occlusionTexture) { // Occlusion is defined as well as metallic and/or roughness // Use same texture logger.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 logger.RaiseVerbose("Occlusion is not defined, only metallic and/or roughness", 2); if (pbrMRMat.metallicRoughnessTexture.bitmap != null) { // Metallic & roughness texture has been merged manually by the exporter // Write bitmap file logger.RaiseVerbose("Metallic & roughness texture has been merged manually by the exporter", 2); gltfPbrMetallicRoughness.metallicRoughnessTexture = ExportBitmapTexture(gltf, pbrMRMat.metallicRoughnessTexture); } else { // Metallic & roughness texture was already merged // Copy file logger.RaiseVerbose("Metallic & roughness texture was already merged", 2); gltfPbrMetallicRoughness.metallicRoughnessTexture = ExportTexture(pbrMRMat.metallicRoughnessTexture, gltf); } } } } else if (babylonMaterial is BabylonPBRSpecularGlossinessMaterial pbrSGMat) { var ext = new KHR_materials_pbrSpecularGlossiness() { specularFactor = pbrSGMat.specularColor, glossinessFactor = pbrSGMat.glossiness, diffuseTexture = ExportTexture(pbrSGMat.diffuseTexture, gltf), specularGlossinessTexture = ExportTexture(pbrSGMat.specularGlossinessTexture, gltf) }; gltfMaterial.extensions = gltfMaterial.extensions ?? new GLTFExtensions(); // ensure extensions exist gltfMaterial.extensions.AddExtension(gltf, "KHR_materials_pbrSpecularGlossiness", ext); } } else if (babylonMaterial.GetType() == typeof(BabylonFurMaterial)) { // TODO - Implement proper handling of BabylonFurMaterial once gLTF spec has support var babylonPBRFurMaterial = babylonMaterial as BabylonFurMaterial; gltfMaterial = new GLTFMaterial { name = name }; gltfMaterial.id = babylonMaterial.id; gltfMaterial.index = gltf.MaterialsList.Count; gltf.MaterialsList.Add(gltfMaterial); //Custom user properties if (babylonPBRFurMaterial.metadata != null && babylonPBRFurMaterial.metadata.Count != 0) { gltfMaterial.extras = babylonPBRFurMaterial.metadata; } } else { logger.RaiseWarning("GLTFExporter.Material | Unsupported material type: " + babylonMaterial.GetType(), 2); } if (gltfMaterial != null && babylonMaterial.isUnlit) { // Add Unlit extension if (!exportParameters.enableKHRMaterialsUnlit) { logger.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(); } } }