diff --git a/Assets/UniGLTF/Runtime/Extensions/ColorConversionExtensions.cs b/Assets/UniGLTF/Runtime/Extensions/ColorConversionExtensions.cs new file mode 100644 index 000000000..6de7f163b --- /dev/null +++ b/Assets/UniGLTF/Runtime/Extensions/ColorConversionExtensions.cs @@ -0,0 +1,73 @@ +using System; +using UnityEngine; + +namespace UniGLTF +{ + public enum ColorSpace + { + sRGB, + Linear, + } + + public static class ColorConversionExtensions + { + public static float[] ToFloat4(this Color src, ColorSpace srcColorSpace, ColorSpace dstColorSpace) + { + var dst = src.ConvertColorSpace(srcColorSpace, dstColorSpace); + return new float[] {dst.r, dst.g, dst.b, dst.a}; + } + + public static float[] ToFloat3(this Color src, ColorSpace srcColorSpace, ColorSpace dstColorSpace) + { + var dst = src.ConvertColorSpace(srcColorSpace, dstColorSpace); + return new float[] {dst.r, dst.g, dst.b}; + } + + public static Color ToColor4(this float[] src, ColorSpace srcColorSpace, ColorSpace dstColorSpace) + { + if (src == null || src.Length < 4) + { + Debug.LogWarning("Invalid argument."); + return Color.magenta; + } + + return new Color(src[0], src[1], src[2], src[3]).ConvertColorSpace(srcColorSpace, dstColorSpace); + } + + public static Color ToColor3(this float[] src, ColorSpace srcColorSpace, ColorSpace dstColorSpace) + { + if (src == null || src.Length < 3) + { + Debug.LogWarning("Invalid argument."); + return Color.magenta; + } + + return new Color(src[0], src[1], src[2], 1f).ConvertColorSpace(srcColorSpace, dstColorSpace); + } + + private static Color ConvertColorSpace(this Color srcColor, ColorSpace srcColorSpace, ColorSpace dstColorSpace) + { + // Need pattern matching :( + if (srcColorSpace == ColorSpace.sRGB && dstColorSpace == ColorSpace.sRGB) + { + return srcColor; + } + else if (srcColorSpace == ColorSpace.sRGB && dstColorSpace == ColorSpace.Linear) + { + return srcColor.linear; + } + else if (srcColorSpace == ColorSpace.Linear && dstColorSpace == ColorSpace.sRGB) + { + return srcColor.gamma; + } + else if (srcColorSpace == ColorSpace.Linear && dstColorSpace == ColorSpace.Linear) + { + return srcColor; + } + else + { + throw new ArgumentException(); + } + } + } +} \ No newline at end of file diff --git a/Assets/UniGLTF/Runtime/Extensions/ColorConversionExtensions.cs.meta b/Assets/UniGLTF/Runtime/Extensions/ColorConversionExtensions.cs.meta new file mode 100644 index 000000000..7c0672cd9 --- /dev/null +++ b/Assets/UniGLTF/Runtime/Extensions/ColorConversionExtensions.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: c2b6bc13ed6e459e98834507edfede07 +timeCreated: 1620378376 \ No newline at end of file diff --git a/Assets/UniGLTF/Runtime/Extensions/UnityExtensions.cs b/Assets/UniGLTF/Runtime/Extensions/UnityExtensions.cs index 37018488f..f51247633 100644 --- a/Assets/UniGLTF/Runtime/Extensions/UnityExtensions.cs +++ b/Assets/UniGLTF/Runtime/Extensions/UnityExtensions.cs @@ -281,11 +281,6 @@ namespace UniGLTF return new float[] { v.x, v.y, v.z, v.w }; } - public static float[] ToArray(this Color c) - { - return new float[] { c.r, c.g, c.b, c.a }; - } - public static void ReverseRecursive(this Transform root, IAxisInverter axisInverter) { var globalMap = root.Traverse().ToDictionary(x => x, x => PosRot.FromGlobalTransform(x)); diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/GltfPBRMaterial.cs b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/GltfPBRMaterial.cs index 434a8b826..b38096100 100644 --- a/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/GltfPBRMaterial.cs +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/GltfPBRMaterial.cs @@ -1,8 +1,6 @@ -using System.Threading.Tasks; -using UnityEngine; +using UnityEngine; using VRMShaders; - namespace UniGLTF { /// @@ -103,8 +101,9 @@ namespace UniGLTF if (src.pbrMetallicRoughness.baseColorFactor != null && src.pbrMetallicRoughness.baseColorFactor.Length == 4) { - var color = src.pbrMetallicRoughness.baseColorFactor; - param.Colors.Add("_Color", (new Color(color[0], color[1], color[2], color[3])).gamma); + param.Colors.Add("_Color", + src.pbrMetallicRoughness.baseColorFactor.ToColor4(ColorSpace.Linear, ColorSpace.sRGB) + ); } if (src.pbrMetallicRoughness.baseColorTexture != null && src.pbrMetallicRoughness.baseColorTexture.index != -1) @@ -153,7 +152,9 @@ namespace UniGLTF if (src.emissiveFactor != null && src.emissiveFactor.Length == 3) { - param.Colors.Add("_EmissionColor", new Color(src.emissiveFactor[0], src.emissiveFactor[1], src.emissiveFactor[2])); + param.Colors.Add("_EmissionColor", + src.emissiveFactor.ToColor3(ColorSpace.Linear, ColorSpace.Linear) + ); } if (src.emissiveTexture != null && src.emissiveTexture.index != -1) diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/GltfUnlitMaterial.cs b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/GltfUnlitMaterial.cs index 06a6b842f..18283cf2b 100644 --- a/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/GltfUnlitMaterial.cs +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/GltfUnlitMaterial.cs @@ -36,8 +36,9 @@ namespace UniGLTF // color if (src.pbrMetallicRoughness.baseColorFactor != null && src.pbrMetallicRoughness.baseColorFactor.Length == 4) { - var color = src.pbrMetallicRoughness.baseColorFactor; - param.Colors.Add("_Color", (new Color(color[0], color[1], color[2], color[3])).gamma); + param.Colors.Add("_Color", + src.pbrMetallicRoughness.baseColorFactor.ToColor4(ColorSpace.Linear, ColorSpace.sRGB) + ); } //renderMode diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/MaterialExporter.cs b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/MaterialExporter.cs index b0fc0a210..461c011ee 100644 --- a/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/MaterialExporter.cs +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/MaterialExporter.cs @@ -38,7 +38,7 @@ namespace UniGLTF { if (m.HasProperty("_Color")) { - material.pbrMetallicRoughness.baseColorFactor = m.color.linear.ToArray(); + material.pbrMetallicRoughness.baseColorFactor = m.GetColor("_Color").ToFloat4(ColorSpace.sRGB, ColorSpace.Linear); } if (m.HasProperty("_MainTex")) @@ -161,7 +161,7 @@ namespace UniGLTF { color /= color.maxColorComponent; } - material.emissiveFactor = new float[] { color.r, color.g, color.b }; + material.emissiveFactor = color.ToFloat3(ColorSpace.Linear, ColorSpace.Linear); } if (m.HasProperty("_EmissionMap")) diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/TextureIO/ColorSpace.cs b/Assets/UniGLTF/Runtime/UniGLTF/IO/TextureIO/ColorSpace.cs deleted file mode 100644 index 1274075ee..000000000 --- a/Assets/UniGLTF/Runtime/UniGLTF/IO/TextureIO/ColorSpace.cs +++ /dev/null @@ -1,52 +0,0 @@ -using System; -using System.Linq; -using UnityEngine; - -namespace UniGLTF -{ - public static class ColorSpace - { - public static RenderTextureReadWrite GetColorSpace(this glTFTextureTypes textureType) - { - switch (textureType) - { - case glTFTextureTypes.SRGB: - return RenderTextureReadWrite.sRGB; - case glTFTextureTypes.OcclusionMetallicRoughness: - case glTFTextureTypes.Normal: - return RenderTextureReadWrite.Linear; - default: - throw new NotImplementedException(); - } - } - - public static bool TryGetglTFTextureType(this glTF glTf, int textureIndex, out glTFTextureTypes textureType) - { - foreach (var material in glTf.materials) - { - var textureInfo = material.GetTextures().FirstOrDefault(x => (x != null) && x.index == textureIndex); - if (textureInfo != null) - { - textureType = textureInfo.TextureType; - return true; - } - } - - // textureIndex is not used by Material. - textureType = default; - return false; - } - - public static RenderTextureReadWrite GetColorSpace(this glTF gltf, int textureIndex) - { - if (TryGetglTFTextureType(gltf, textureIndex, out glTFTextureTypes textureType)) - { - return GetColorSpace(textureType); - } - else - { - return RenderTextureReadWrite.sRGB; - } - } - } -} diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/TextureIO/ColorSpace.cs.meta b/Assets/UniGLTF/Runtime/UniGLTF/IO/TextureIO/ColorSpace.cs.meta deleted file mode 100644 index d5bf0544c..000000000 --- a/Assets/UniGLTF/Runtime/UniGLTF/IO/TextureIO/ColorSpace.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 1a3edb24329fd454db97cac12f30c0d8 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/VRM/Runtime/IO/VRMMaterialExporter.cs b/Assets/VRM/Runtime/IO/VRMMaterialExporter.cs index e484d256a..7b65783d2 100644 --- a/Assets/VRM/Runtime/IO/VRMMaterialExporter.cs +++ b/Assets/VRM/Runtime/IO/VRMMaterialExporter.cs @@ -5,6 +5,7 @@ using UniGLTF; using UniGLTF.ShaderPropExporter; using UnityEngine; using VRMShaders; +using ColorSpace = UniGLTF.ColorSpace; namespace VRM { @@ -160,7 +161,8 @@ namespace VRM { case ShaderPropertyType.Color: { - var value = m.GetColor(kv.Key).ToArray(); + // No color conversion. Because color property is serialized to raw float array. + var value = m.GetColor(kv.Key).ToFloat4(ColorSpace.Linear, ColorSpace.Linear); material.vectorProperties.Add(kv.Key, value); } break; diff --git a/Assets/VRM10/Runtime/IO/Vrm10MaterialExporter.cs b/Assets/VRM10/Runtime/IO/Vrm10MaterialExporter.cs index 234053eef..edd5ee869 100644 --- a/Assets/VRM10/Runtime/IO/Vrm10MaterialExporter.cs +++ b/Assets/VRM10/Runtime/IO/Vrm10MaterialExporter.cs @@ -1,6 +1,7 @@ using UniGLTF; using UnityEngine; using VRMShaders; +using ColorSpace = UniGLTF.ColorSpace; namespace UniVRM10 { @@ -23,14 +24,14 @@ namespace UniVRM10 pbrMetallicRoughness = new glTFPbrMetallicRoughness { - baseColorFactor = def.Color.LitColor.ToArray(), + baseColorFactor = def.Color.LitColor.ToFloat4(ColorSpace.sRGB, ColorSpace.Linear), baseColorTexture = new glTFMaterialBaseColorTextureInfo { index = textureExporter.ExportSRGB(def.Color.LitMultiplyTexture), }, }, - emissiveFactor = def.Emission.EmissionColor.ToArray(), + emissiveFactor = def.Emission.EmissionColor.ToFloat3(ColorSpace.Linear, ColorSpace.Linear), }; // VRMC_materials_mtoon diff --git a/Assets/VRM10/Runtime/IO/Vrm10MaterialImporter.cs b/Assets/VRM10/Runtime/IO/Vrm10MaterialImporter.cs index 5ca26aa08..3f42855c1 100644 --- a/Assets/VRM10/Runtime/IO/Vrm10MaterialImporter.cs +++ b/Assets/VRM10/Runtime/IO/Vrm10MaterialImporter.cs @@ -1,45 +1,11 @@ -using System; -using System.Collections.Generic; -using System.Threading.Tasks; -using UniGLTF; +using UniGLTF; using UnityEngine; using VRMShaders; - namespace UniVRM10 { public static class Vrm10MaterialImporter { - public static Color ToColor4(this float[] src, Color defaultValue = default) - { - if (src == null || src.Length != 4) - { - throw new NotImplementedException(); - } - - var v = new Vector4( - src[0], - src[1], - src[2], - src[3] - ); - return v; - } - public static Color ToColor3(this float[] src, Color defaultValue = default) - { - if (src == null || src.Length < 3) - { - throw new NotImplementedException(); - } - - var v = new Vector4( - src[0], - src[1], - src[2] - ); - return v; - } - /// /// VMRC_materials_mtoon の場合にマテリアル生成情報を作成する /// @@ -75,8 +41,15 @@ namespace UniVRM10 } { // var color = mtoon.Color; - material.SetColor(MToon.Utils.PropColor, m.pbrMetallicRoughness.baseColorFactor.ToColor4()); - if (mtoon.ShadeColorFactor != null) material.SetColor(MToon.Utils.PropShadeColor, mtoon.ShadeColorFactor.ToColor3()); + material.SetColor(MToon.Utils.PropColor, m.pbrMetallicRoughness.baseColorFactor + .ToColor4(UniGLTF.ColorSpace.Linear, UniGLTF.ColorSpace.sRGB) + ); + if (mtoon.ShadeColorFactor != null) + { + material.SetColor(MToon.Utils.PropShadeColor, mtoon.ShadeColorFactor + .ToColor3(UniGLTF.ColorSpace.Linear, UniGLTF.ColorSpace.sRGB) + ); + } material.SetFloat(MToon.Utils.PropCutoff, m.alphaCutoff); } { @@ -91,17 +64,29 @@ namespace UniVRM10 } } { - material.SetColor(MToon.Utils.PropEmissionColor, m.emissiveFactor.ToColor3()); + material.SetColor(MToon.Utils.PropEmissionColor, + m.emissiveFactor.ToColor3(UniGLTF.ColorSpace.Linear, UniGLTF.ColorSpace.Linear) + ); } { - if (mtoon.ParametricRimColorFactor != null) material.SetColor(MToon.Utils.PropRimColor, mtoon.ParametricRimColorFactor.ToColor3()); + if (mtoon.ParametricRimColorFactor != null) + { + material.SetColor(MToon.Utils.PropRimColor, mtoon.ParametricRimColorFactor + .ToColor3(UniGLTF.ColorSpace.Linear, UniGLTF.ColorSpace.sRGB) + ); + } if (mtoon.RimLightingMixFactor.HasValue) material.SetFloat(MToon.Utils.PropRimLightingMix, mtoon.RimLightingMixFactor.Value); if (mtoon.ParametricRimFresnelPowerFactor.HasValue) material.SetFloat(MToon.Utils.PropRimFresnelPower, mtoon.ParametricRimFresnelPowerFactor.Value); if (mtoon.ParametricRimLiftFactor.HasValue) material.SetFloat(MToon.Utils.PropRimLift, mtoon.ParametricRimLiftFactor.Value); } { if (mtoon.OutlineWidthFactor.HasValue) material.SetFloat(MToon.Utils.PropOutlineWidth, mtoon.OutlineWidthFactor.Value); - if (mtoon.OutlineColorFactor != null) material.SetColor(MToon.Utils.PropOutlineColor, mtoon.OutlineColorFactor.ToColor3()); + if (mtoon.OutlineColorFactor != null) + { + material.SetColor(MToon.Utils.PropOutlineColor, mtoon.OutlineColorFactor + .ToColor3(UniGLTF.ColorSpace.Linear, UniGLTF.ColorSpace.sRGB) + ); + } if (mtoon.OutlineLightingMixFactor.HasValue) material.SetFloat(MToon.Utils.PropOutlineLightingMix, mtoon.OutlineLightingMixFactor.Value); // private diff --git a/Assets/VRM10/Runtime/Migration/MigrationMToon.cs b/Assets/VRM10/Runtime/Migration/MigrationMToon.cs index f74402795..1a07cf141 100644 --- a/Assets/VRM10/Runtime/Migration/MigrationMToon.cs +++ b/Assets/VRM10/Runtime/Migration/MigrationMToon.cs @@ -5,25 +5,15 @@ using UniGLTF; using UniGLTF.Extensions.VRMC_materials_mtoon; using UniJSON; using UnityEngine; - +using ColorSpace = UniGLTF.ColorSpace; namespace UniVRM10 { public static class MigrationMToon { - static float[] ToFloat4(this Color color) + static Color ToColor(JsonNode node, ColorSpace srcColorSpace, ColorSpace dstColorSpace) { - return new float[] { color.r, color.g, color.b, color.a }; - } - - static float[] ToFloat3(this Color color) - { - return new float[] { color.r, color.g, color.b }; - } - - static Color ToColor(JsonNode node) - { - return node.ArrayItems().Select(x => x.GetSingle()).ToArray().ToColor4(); + return node.ArrayItems().Select(x => x.GetSingle()).ToArray().ToColor4(srcColorSpace, dstColorSpace); } static float[] ToFloat4(JsonNode node) @@ -90,23 +80,23 @@ namespace UniVRM10 switch (key) { case "_Color": - definition.Color.LitColor = ToColor(kv.Value); + definition.Color.LitColor = ToColor(kv.Value, ColorSpace.sRGB, ColorSpace.sRGB); break; case "_ShadeColor": - definition.Color.ShadeColor = ToColor(kv.Value); + definition.Color.ShadeColor = ToColor(kv.Value, ColorSpace.sRGB, ColorSpace.sRGB); break; case "_EmissionColor": - definition.Emission.EmissionColor = ToColor(kv.Value); + definition.Emission.EmissionColor = ToColor(kv.Value, ColorSpace.Linear, ColorSpace.Linear); break; case "_OutlineColor": - definition.Outline.OutlineColor = ToColor(kv.Value); + definition.Outline.OutlineColor = ToColor(kv.Value, ColorSpace.sRGB, ColorSpace.sRGB); break; case "_RimColor": - definition.Rim.RimColor = ToColor(kv.Value); + definition.Rim.RimColor = ToColor(kv.Value, ColorSpace.sRGB, ColorSpace.sRGB); break; case "_MainTex": @@ -315,7 +305,7 @@ namespace UniVRM10 var dst = new VRMC_materials_mtoon(); // Color - gltfMaterial.pbrMetallicRoughness.baseColorFactor = mtoon.Definition.Color.LitColor.ToFloat4(); + gltfMaterial.pbrMetallicRoughness.baseColorFactor = mtoon.Definition.Color.LitColor.ToFloat4(ColorSpace.sRGB, ColorSpace.Linear); if (mtoon.TextureIndexMap.MainTex.HasValue) { gltfMaterial.pbrMetallicRoughness.baseColorTexture = new glTFMaterialBaseColorTextureInfo @@ -332,7 +322,7 @@ namespace UniVRM10 (value[2], value[3]) ); } - dst.ShadeColorFactor = mtoon.Definition.Color.ShadeColor.ToFloat3(); + dst.ShadeColorFactor = mtoon.Definition.Color.ShadeColor.ToFloat3(ColorSpace.sRGB, ColorSpace.Linear); if (mtoon.TextureIndexMap.ShadeTexture.HasValue) { dst.ShadeMultiplyTexture = new TextureInfo { Index = mtoon.TextureIndexMap.ShadeTexture.Value }; @@ -340,7 +330,7 @@ namespace UniVRM10 gltfMaterial.alphaCutoff = mtoon.Definition.Color.CutoutThresholdValue; // Outline - dst.OutlineColorFactor = ToFloat3(mtoon.Definition.Outline.OutlineColor); + dst.OutlineColorFactor = mtoon.Definition.Outline.OutlineColor.ToFloat3(ColorSpace.sRGB, ColorSpace.Linear); dst.OutlineLightingMixFactor = mtoon.Definition.Outline.OutlineLightingMixValue; dst.OutlineWidthMode = (UniGLTF.Extensions.VRMC_materials_mtoon.OutlineWidthMode)mtoon.Definition.Outline.OutlineWidthMode; dst.OutlineWidthFactor = mtoon.Definition.Outline.OutlineWidthValue; @@ -350,7 +340,7 @@ namespace UniVRM10 } // Emission - gltfMaterial.emissiveFactor = mtoon.Definition.Emission.EmissionColor.ToFloat3(); + gltfMaterial.emissiveFactor = mtoon.Definition.Emission.EmissionColor.ToFloat3(ColorSpace.Linear, ColorSpace.Linear); if (mtoon.TextureIndexMap.EmissionMap.HasValue) { gltfMaterial.emissiveTexture = new glTFMaterialEmissiveTextureInfo @@ -413,7 +403,7 @@ namespace UniVRM10 dst.RenderQueueOffsetNumber = mtoon.Definition.Rendering.RenderQueueOffsetNumber; // rim - dst.ParametricRimColorFactor = mtoon.Definition.Rim.RimColor.ToFloat3(); + dst.ParametricRimColorFactor = mtoon.Definition.Rim.RimColor.ToFloat3(ColorSpace.sRGB, ColorSpace.Linear); if (mtoon.TextureIndexMap.RimTexture.HasValue) { dst.RimMultiplyTexture = new TextureInfo { Index = mtoon.TextureIndexMap.RimTexture.Value }; diff --git a/Assets/VRM10/Runtime/UnityExtensions.cs b/Assets/VRM10/Runtime/UnityExtensions.cs index 936d2bcf8..b2c7dc1ee 100644 --- a/Assets/VRM10/Runtime/UnityExtensions.cs +++ b/Assets/VRM10/Runtime/UnityExtensions.cs @@ -273,11 +273,6 @@ namespace UniVRM10 return new float[] { v.x, v.y, v.z, v.w }; } - public static float[] ToArray(this Color c) - { - return new float[] { c.r, c.g, c.b, c.a }; - } - public static void ReverseZRecursive(this Transform root) { var globalMap = root.Traverse().ToDictionary(x => x, x => PosRot.FromGlobalTransform(x));