using System; using System.Linq; using UniGLTF; using UniJSON; using UnityEngine; using ColorSpace = VRMShaders.ColorSpace; namespace UniVRM10 { internal static class MigrationPbrMaterial { private const string UsingGltfMaterialKeywordInVrmExtension = "VRM_USE_GLTFSHADER"; private const string ExporterVersionKey = "exporterVersion"; /// /// vanilla の gltf material を対象とする. /// KHR_materials_unlit 拡張や VRM.materialProperties で MToon を対象とするマテリアルは処理してはいけない。 /// public static void Migrate(glTF gltf, JsonNode vrm0XExtension) { var needMigrationRoughnessTextureValueSquared = false; var needMigrationEmissiveFactorGamma = false; if (vrm0XExtension.TryGet(ExporterVersionKey, out var vrm0XVersionStringNode)) { var vrm0XVersionString = vrm0XVersionStringNode.GetString(); if (Vrm0XVersion.ParseVersion(vrm0XVersionString, out var vrm0XVersion)) { needMigrationRoughnessTextureValueSquared = Vrm0XVersion.IsNewer( new Vrm0XVersion.Version { Major = 0, Minor = 69, Patch = 0, Pre = "", }, vrm0XVersion ); needMigrationEmissiveFactorGamma = Vrm0XVersion.IsNewer( new Vrm0XVersion.Version { Major = 0, Minor = 107, Patch = 0, Pre = "", }, vrm0XVersion ); } } for (var idx = 0; idx < gltf.materials.Count; ++idx) { MigrateMaterial(gltf, vrm0XExtension, idx, needMigrationRoughnessTextureValueSquared, needMigrationEmissiveFactorGamma); } } private static void MigrateMaterial(glTF gltf, JsonNode vrm0XExtension, int idx, bool needMigrationRoughnessTextureValueSquared, bool needMigrationEmissiveFactorGamma) { var src = gltf.materials[idx]; var vrm0XMaterial = vrm0XExtension["materialProperties"][idx]; // NOTE: ignore MToon if (MigrationMaterialUtil.GetShaderName(vrm0XMaterial) != UsingGltfMaterialKeywordInVrmExtension) return; // NOTE: ignore Unlit if (glTF_KHR_materials_unlit.IsEnable(src)) return; if (needMigrationRoughnessTextureValueSquared) { // NOTE: 非常に実装がめんどくさい、かつ刺さるシチュエーションがかなり少ないので放置. } if (needMigrationEmissiveFactorGamma && src.emissiveFactor != null && src.emissiveFactor.Length == 3) { var emissiveFactor = new Color(src.emissiveFactor[0], src.emissiveFactor[1], src.emissiveFactor[2]); if (UniGLTF.glTF_KHR_materials_emissive_strength.TryGet(src.extensions, out var emissiveStrength)) { emissiveFactor *= emissiveStrength.emissiveStrength; } else if (UniGLTF.Extensions.VRMC_materials_hdr_emissiveMultiplier.GltfDeserializer.TryGet(src.extensions, out var ex)) { if (ex.EmissiveMultiplier != null) { emissiveFactor *= ex.EmissiveMultiplier.Value; } } // NOTE: 新しい emissive_strength 拡張を書き込むため、拡張をまっさらにする var extensionsExport = new glTFExtensionExport(); src.extensions = extensionsExport; var linearEmissiveFactor = emissiveFactor.linear; if (linearEmissiveFactor.maxColorComponent > 1) { var maxColorComponent = linearEmissiveFactor.maxColorComponent; linearEmissiveFactor /= maxColorComponent; UniGLTF.glTF_KHR_materials_emissive_strength.Serialize(ref src.extensions, maxColorComponent); } src.emissiveFactor = linearEmissiveFactor.ToFloat3(ColorSpace.Linear, ColorSpace.Linear); } } } }