/// <summary> /// Export dedicated to SpecGloss Material /// </summary> /// <param name="materialNode">the material node interface</param> /// <param name="babylonScene">the scene to export the material</param> private void ExportPbrSpecGlossMaterial(IIGameMaterial materialNode, BabylonScene babylonScene) { // build material decorator PbrSpecGlossDecorator maxDecorator = new PbrSpecGlossDecorator(materialNode); // get the custom babylon attribute decorator BabylonCustomAttributeDecorator babylonDecorator = maxDecorator.BabylonCustomAttributes; // the target material var babylonMaterial = new BabylonPBRSpecularGlossinessMaterial(maxDecorator.Id) { maxGameMaterial = materialNode, name = maxDecorator.Name, backFaceCulling = babylonDecorator.BackFaceCulling, doubleSided = !babylonDecorator.BackFaceCulling, separateCullingPass = babylonDecorator.SeparateCullingPass, isUnlit = babylonDecorator.IsUnlit, baseColor = maxDecorator.BaseColor.ToArray(), }; // --- Global --- if (babylonMaterial.isUnlit) { // Ignore values babylonMaterial.specularColor = BabylonPBRBaseSimpleMaterial.BlackColor(); babylonMaterial.glossiness = 0; } else { babylonMaterial.glossiness = maxDecorator.Glossiness; babylonMaterial.specularColor = maxDecorator.SpecularColor.ToArray(); babylonMaterial.emissive = maxDecorator.EmitColor.ToArray(); } // --- Textures --- float[] multiplyColor = null; if (exportParameters.exportTextures) { ITexmap diffuseTexMap = maxDecorator.BaseColorMap; ITexmap alphaTexMap = maxDecorator.OpacityMap; bool isOpacity = true; babylonMaterial.diffuseTexture = ExportBaseColorAlphaTexture(diffuseTexMap, alphaTexMap, babylonMaterial.baseColor, babylonMaterial.alpha, babylonScene, out multiplyColor, isOpacity); if (multiplyColor != null) { babylonMaterial.baseColor = multiplyColor; } if (!babylonMaterial.isUnlit) { // Metallic, roughness, ambient occlusion ITexmap specularTexMap = maxDecorator.SpecularMap; ITexmap glossinessTexMap = maxDecorator.GlossinessMap; ITexmap ambientOcclusionTexMap = maxDecorator.AmbientOcclusionMap; if (specularTexMap != null || glossinessTexMap != null) { // Merge Specular and Glossiness RaiseVerbose("Merge Specular and Glossiness", 2); BabylonTexture specularGlossinessTexture = ExportSpecularGlossinessTexture(babylonMaterial.specularColor, specularTexMap, babylonMaterial.glossiness, glossinessTexMap, babylonScene); babylonMaterial.specularGlossinessTexture = specularGlossinessTexture; } if (ambientOcclusionTexMap != null) { // Simply export occlusion texture RaiseVerbose("Export occlusion texture", 2); babylonMaterial.occlusionTexture = ExportTexture(ambientOcclusionTexMap, babylonScene); } var normalMapAmount = maxDecorator.BumpMapAmount; ITexmap normalTexMap = maxDecorator.NormalMap; babylonMaterial.normalTexture = ExportTexture(normalTexMap, babylonScene, normalMapAmount); ITexmap emitTexMap = maxDecorator.EmitColormMap; babylonMaterial.emissiveTexture = ExportTexture(emitTexMap, babylonScene); if (babylonMaterial.specularGlossinessTexture != null && !babylonDecorator.UseMaxFactor) { babylonMaterial.glossiness = glossinessTexMap != null ? 1.0f : 0.0f; babylonMaterial.specularColor = specularTexMap != null?BabylonPBRBaseSimpleMaterial.WhiteColor() : BabylonPBRBaseSimpleMaterial.BlackColor(); } } } // --- Finalize --- if (babylonMaterial.alpha != 1.0f || (babylonMaterial.diffuseTexture != null && babylonMaterial.diffuseTexture.hasAlpha)) { babylonMaterial.transparencyMode = (int)BabylonMaterial.TransparencyMode.ALPHABLEND; } if (babylonMaterial.transparencyMode == (int)BabylonMaterial.TransparencyMode.ALPHATEST) { // Set the alphaCutOff value explicitely to avoid different interpretations on different engines // Use the glTF default value rather than the babylon one babylonMaterial.alphaCutOff = 0.5f; } if (babylonMaterial.emissiveTexture != null) { babylonMaterial.emissive = new[] { 1.0f, 1.0f, 1.0f }; } // List all babylon material attributes // Those attributes are currently stored into the native material // They should not be exported as extra attributes var doNotExport = BabylonCustomAttributeDecorator.ListPrivatePropertyNames().ToList(); // Export the custom attributes of this material babylonMaterial.metadata = ExportExtraAttributes(materialNode, babylonScene, doNotExport); if (exportParameters.pbrFull) { var fullPBR = new BabylonPBRMaterial(babylonMaterial) { directIntensity = babylonDecorator.DirectIntensity, emissiveIntensity = babylonDecorator.EmissiveIntensity, environmentIntensity = babylonDecorator.EnvironementIntensity, specularIntensity = babylonDecorator.SpecularIntensity, maxGameMaterial = babylonMaterial.maxGameMaterial }; babylonScene.MaterialsList.Add(fullPBR); } else { // Add the material to the scene babylonScene.MaterialsList.Add(babylonMaterial); } }
/// <summary> /// Export dedicated to PbrMetalRough Material /// </summary> /// <param name="materialNode">the material node interface</param> /// <param name="babylonScene">the scene to export the material</param> private void ExportPbrMetalRoughMaterial(IIGameMaterial materialNode, BabylonScene babylonScene) { // build material decorator PbrMetalRoughDecorator maxDecorator = new PbrMetalRoughDecorator(materialNode); // get the custom babylon attribute decorator BabylonCustomAttributeDecorator babylonDecorator = maxDecorator.BabylonCustomAttributes; // the target material var babylonMaterial = new BabylonPBRMetallicRoughnessMaterial(maxDecorator.Id) { maxGameMaterial = materialNode, name = maxDecorator.Name, backFaceCulling = babylonDecorator.BackFaceCulling, doubleSided = !babylonDecorator.BackFaceCulling, separateCullingPass = babylonDecorator.SeparateCullingPass, isUnlit = babylonDecorator.IsUnlit, _unlit = babylonDecorator.IsUnlit, baseColor = maxDecorator.BaseColor.ToArray() }; // --- Global --- if (babylonMaterial.isUnlit) { // Ignore values babylonMaterial.metallic = 0; babylonMaterial.roughness = 0.9f; } else { babylonMaterial.metallic = maxDecorator.Metalness; babylonMaterial.roughness = maxDecorator.Roughness; babylonMaterial.emissive = maxDecorator.EmitColor.ToArray(); } // --- Textures --- float[] multiplyColor = null; if (exportParameters.exportTextures) { ITexmap baseColorTexMap = maxDecorator.BaseColorMap; ITexmap alphaTexMap = maxDecorator.OpacityMap; bool isOpacity = true; babylonMaterial.baseTexture = ExportBaseColorAlphaTexture(baseColorTexMap, alphaTexMap, babylonMaterial.baseColor, babylonMaterial.alpha, babylonScene, out multiplyColor, isOpacity); if (multiplyColor != null) { babylonMaterial.baseColor = multiplyColor; } if (!babylonMaterial.isUnlit) { // Metallic, roughness, ambient occlusion ITexmap metalnessTexMap = maxDecorator.MetalnessMap; ITexmap roughnessTexMap = maxDecorator.RoughnessMap; ITexmap ambientOcclusionTexMap = maxDecorator.AmbientOcclusionMap; // Check if MR or ORM textures are already merged bool areTexturesAlreadyMerged = false; if (metalnessTexMap != null && roughnessTexMap != null) { string sourcePathMetallic = getSourcePath(metalnessTexMap); string sourcePathRoughness = getSourcePath(roughnessTexMap); if (sourcePathMetallic == sourcePathRoughness) { if (ambientOcclusionTexMap != null && exportParameters.mergeAO) { 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(metalnessTexMap, 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(metalnessTexMap, babylonScene); babylonMaterial.metallicRoughnessTexture = ormTexture; areTexturesAlreadyMerged = true; } } } if (areTexturesAlreadyMerged == false) { if (metalnessTexMap != 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.mergeAO ? ambientOcclusionTexMap : null, roughnessTexMap, metalnessTexMap, babylonMaterial.metallic, babylonMaterial.roughness, babylonScene, false); babylonMaterial.metallicRoughnessTexture = ormTexture; if (ambientOcclusionTexMap != null) { if (exportParameters.mergeAO) { // 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 = ExportTexture(ambientOcclusionTexMap, babylonScene); } } } else if (ambientOcclusionTexMap != null) { // Simply export occlusion texture RaiseVerbose("Simply export occlusion texture", 2); babylonMaterial.occlusionTexture = ExportTexture(ambientOcclusionTexMap, babylonScene); } } if (ambientOcclusionTexMap != null && !exportParameters.mergeAO && babylonMaterial.occlusionTexture == null) { RaiseVerbose("Exporting occlusion texture without merging with metallic roughness", 2); babylonMaterial.occlusionTexture = ExportTexture(ambientOcclusionTexMap, babylonScene); } var normalMapAmount = maxDecorator.BumpMapAmount; ITexmap normalTexMap = maxDecorator.NormalMap; babylonMaterial.normalTexture = ExportTexture(normalTexMap, babylonScene, normalMapAmount); ITexmap emitTexMap = maxDecorator.EmitColormMap; babylonMaterial.emissiveTexture = ExportTexture(emitTexMap, babylonScene); if (babylonMaterial.metallicRoughnessTexture != null && !babylonDecorator.UseMaxFactor) { // Change the factor to zero if combining partial channel to avoid issue (in case of image compression). // ie - if no metallic map, then b MUST be fully black. However channel of jpeg MAY not beeing fully black // cause of the compression algorithm. Keeping MetallicFactor to 1 will make visible artifact onto texture. So set to Zero instead. babylonMaterial.metallic = areTexturesAlreadyMerged || metalnessTexMap != null ? 1.0f : 0.0f; babylonMaterial.roughness = areTexturesAlreadyMerged || roughnessTexMap != null ? 1.0f : 0.0f; } } } if (babylonMaterial.alpha != 1.0f || (babylonMaterial.baseTexture != null && babylonMaterial.baseTexture.hasAlpha)) { babylonMaterial.transparencyMode = (int)BabylonMaterial.TransparencyMode.ALPHABLEND; } if (babylonMaterial.transparencyMode == (int)BabylonMaterial.TransparencyMode.ALPHATEST) { // Set the alphaCutOff value explicitely to avoid different interpretations on different engines // Use the glTF default value rather than the babylon one babylonMaterial.alphaCutOff = 0.5f; } if (babylonMaterial.emissiveTexture != null) { babylonMaterial.emissive = new[] { 1.0f, 1.0f, 1.0f }; } // Add babylon attributes if (babylonDecorator.Properties == null) { AddPhysicalBabylonAttributes(materialNode.MaterialName, babylonMaterial); } // List all babylon material attributes // Those attributes are currently stored into the native material // They should not be exported as extra attributes var doNotExport = BabylonCustomAttributeDecorator.ListPrivatePropertyNames().ToList(); // Export the custom attributes of this material babylonMaterial.metadata = ExportExtraAttributes(materialNode, babylonScene, doNotExport); if (exportParameters.pbrFull) { var fullPBR = new BabylonPBRMaterial(babylonMaterial) { directIntensity = babylonDecorator.DirectIntensity, emissiveIntensity = babylonDecorator.EmissiveIntensity, environmentIntensity = babylonDecorator.EnvironementIntensity, specularIntensity = babylonDecorator.SpecularIntensity, maxGameMaterial = babylonMaterial.maxGameMaterial }; babylonScene.MaterialsList.Add(fullPBR); } else { // Add the material to the scene babylonScene.MaterialsList.Add(babylonMaterial); } }