diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/GltfTextureEnumerator.cs b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/GltfTextureEnumerator.cs index 32b7ffe37..771a14c4e 100644 --- a/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/GltfTextureEnumerator.cs +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/GltfTextureEnumerator.cs @@ -28,7 +28,8 @@ namespace UniGLTF // emission if (m.emissiveTexture != null) { - yield return TextureFactory.CreateSRGB(parser, m.emissiveTexture.index); + var (offset, scale) = MaterialFactory.GetTextureOffsetAndScale(m.emissiveTexture); + yield return TextureFactory.CreateSRGB(parser, m.emissiveTexture.index, offset, scale); } // normal diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/MaterialFactory.cs b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/MaterialFactory.cs index 85e31b785..7e81d1522 100644 --- a/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/MaterialFactory.cs +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/MaterialFactory.cs @@ -164,13 +164,13 @@ namespace UniGLTF } return $"material_{index:00}"; } - - public static void SetTextureOffsetAndScale(Material material, glTFTextureInfo textureInfo, string propertyName) + + public static (Vector2, Vector2) GetTextureOffsetAndScale(glTFTextureInfo textureInfo) { + Vector2 offset = new Vector2(0, 0); + Vector2 scale = new Vector2(1, 1); if (glTF_KHR_texture_transform.TryGet(textureInfo, out glTF_KHR_texture_transform textureTransform)) { - Vector2 offset = new Vector2(0, 0); - Vector2 scale = new Vector2(1, 1); if (textureTransform.offset != null && textureTransform.offset.Length == 2) { offset = new Vector2(textureTransform.offset[0], textureTransform.offset[1]); @@ -181,10 +181,14 @@ namespace UniGLTF } offset.y = (offset.y + scale.y - 1.0f) * -1.0f; - - material.SetTextureOffset(propertyName, offset); - material.SetTextureScale(propertyName, scale); } + return (offset, scale); + } + + public static void SetTextureOffsetAndScale(Material material, string propertyName, Vector2 offset, Vector2 scale) + { + material.SetTextureOffset(propertyName, offset); + material.SetTextureScale(propertyName, scale); } public static Task DefaultCreateMaterialAsync(IAwaitCaller awaitCaller, GltfParser parser, int i, GetTextureAsyncFunc getTexture) diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/PBRMaterialItem.cs b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/PBRMaterialItem.cs index cd4538c6a..b17721f16 100644 --- a/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/PBRMaterialItem.cs +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/PBRMaterialItem.cs @@ -46,7 +46,8 @@ namespace UniGLTF public static TextureImportParam BaseColorTexture(GltfParser parser, glTFMaterial src) { - return TextureFactory.CreateSRGB(parser, src.pbrMetallicRoughness.baseColorTexture.index); + var (offset, scale) = MaterialFactory.GetTextureOffsetAndScale(src.pbrMetallicRoughness.baseColorTexture); + return TextureFactory.CreateSRGB(parser, src.pbrMetallicRoughness.baseColorTexture.index, offset, scale); } public static TextureImportParam StandardTexture(GltfParser parser, glTFMaterial src) @@ -58,16 +59,19 @@ namespace UniGLTF metallicFactor = src.pbrMetallicRoughness.metallicFactor; roughnessFactor = src.pbrMetallicRoughness.roughnessFactor; } + var (offset, scale) = MaterialFactory.GetTextureOffsetAndScale(src.pbrMetallicRoughness.metallicRoughnessTexture); return TextureFactory.CreateStandard(parser, src.pbrMetallicRoughness?.metallicRoughnessTexture?.index, src.occlusionTexture?.index, + offset, scale, metallicFactor, roughnessFactor); } public static TextureImportParam NormalTexture(GltfParser parser, glTFMaterial src) { - return TextureFactory.CreateNormal(parser, src.normalTexture.index); + var (offset, scale) = MaterialFactory.GetTextureOffsetAndScale(src.normalTexture); + return TextureFactory.CreateNormal(parser, src.normalTexture.index, offset, scale); } public static async Task CreateAsync(IAwaitCaller awaitCaller, GltfParser parser, int i, GetTextureAsyncFunc getTexture) @@ -101,10 +105,11 @@ namespace UniGLTF if (src.pbrMetallicRoughness.baseColorTexture != null && src.pbrMetallicRoughness.baseColorTexture.index != -1) { - material.mainTexture = await getTexture(awaitCaller, parser.GLTF, BaseColorTexture(parser, src)); + var param = BaseColorTexture(parser, src); + material.mainTexture = await getTexture(awaitCaller, parser.GLTF, param); // Texture Offset and Scale - MaterialFactory.SetTextureOffsetAndScale(material, src.pbrMetallicRoughness.baseColorTexture, "_MainTex"); + MaterialFactory.SetTextureOffsetAndScale(material, "_MainTex", param.Offset, param.Scale); } if (src.pbrMetallicRoughness.metallicRoughnessTexture != null && src.pbrMetallicRoughness.metallicRoughnessTexture.index != -1) @@ -122,7 +127,8 @@ namespace UniGLTF material.SetFloat("_GlossMapScale", 1.0f); // Texture Offset and Scale - MaterialFactory.SetTextureOffsetAndScale(material, src.pbrMetallicRoughness.metallicRoughnessTexture, "_MetallicGlossMap"); + var (offset, scale) = MaterialFactory.GetTextureOffsetAndScale(src.pbrMetallicRoughness.metallicRoughnessTexture); + MaterialFactory.SetTextureOffsetAndScale(material, "_MetallicGlossMap", offset, scale); } else { @@ -134,7 +140,8 @@ namespace UniGLTF if (src.normalTexture != null && src.normalTexture.index != -1) { material.EnableKeyword("_NORMALMAP"); - var texture = await getTexture(awaitCaller, parser.GLTF, NormalTexture(parser, src)); + var param = NormalTexture(parser, src); + var texture = await getTexture(awaitCaller, parser.GLTF, param); if (texture != null) { material.SetTexture(TextureImportParam.NORMAL_PROP, texture); @@ -142,7 +149,7 @@ namespace UniGLTF } // Texture Offset and Scale - MaterialFactory.SetTextureOffsetAndScale(material, src.normalTexture, "_BumpMap"); + MaterialFactory.SetTextureOffsetAndScale(material, "_BumpMap", param.Offset, param.Scale); } if (src.occlusionTexture != null && src.occlusionTexture.index != -1) @@ -155,7 +162,8 @@ namespace UniGLTF } // Texture Offset and Scale - MaterialFactory.SetTextureOffsetAndScale(material, src.occlusionTexture, "_OcclusionMap"); + var (offset, scale) = MaterialFactory.GetTextureOffsetAndScale(src.occlusionTexture); + MaterialFactory.SetTextureOffsetAndScale(material, "_OcclusionMap", offset, scale); } if (src.emissiveFactor != null @@ -171,14 +179,17 @@ namespace UniGLTF if (src.emissiveTexture != null && src.emissiveTexture.index != -1) { - var texture = await getTexture(awaitCaller, parser.GLTF, TextureFactory.CreateSRGB(parser, src.emissiveTexture.index)); + var (offset, scale) = MaterialFactory.GetTextureOffsetAndScale(src.emissiveTexture); + var param = TextureFactory.CreateSRGB(parser, src.emissiveTexture.index, offset, scale); + var texture = await getTexture(awaitCaller, parser.GLTF, param); if (texture != null) { material.SetTexture("_EmissionMap", texture); } // Texture Offset and Scale - MaterialFactory.SetTextureOffsetAndScale(material, src.emissiveTexture, "_EmissionMap"); + + MaterialFactory.SetTextureOffsetAndScale(material, "_EmissionMap", param.Offset, param.Scale); } } diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/UnlitMaterialItem.cs b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/UnlitMaterialItem.cs index 03f7b9a6c..96b4f6d7c 100644 --- a/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/UnlitMaterialItem.cs +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/UnlitMaterialItem.cs @@ -22,10 +22,11 @@ namespace UniGLTF // texture if (src.pbrMetallicRoughness.baseColorTexture != null) { - material.mainTexture = await getTexture(awaitCaller, parser.GLTF, TextureFactory.CreateSRGB(parser, src.pbrMetallicRoughness.baseColorTexture.index)); + var (offset, scale) = MaterialFactory.GetTextureOffsetAndScale(src.pbrMetallicRoughness.baseColorTexture); + material.mainTexture = await getTexture(awaitCaller, parser.GLTF, TextureFactory.CreateSRGB(parser, src.pbrMetallicRoughness.baseColorTexture.index, offset, scale)); // Texture Offset and Scale - MaterialFactory.SetTextureOffsetAndScale(material, src.pbrMetallicRoughness.baseColorTexture, "_MainTex"); + MaterialFactory.SetTextureOffsetAndScale(material, "_MainTex", offset, scale); } // color diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/TextureIO/TextureFactory.cs b/Assets/UniGLTF/Runtime/UniGLTF/IO/TextureIO/TextureFactory.cs index a42ed1613..62676055e 100644 --- a/Assets/UniGLTF/Runtime/UniGLTF/IO/TextureIO/TextureFactory.cs +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/TextureIO/TextureFactory.cs @@ -273,23 +273,23 @@ namespace UniGLTF } } - public static TextureImportParam CreateSRGB(GltfParser parser, int textureIndex) + public static TextureImportParam CreateSRGB(GltfParser parser, int textureIndex, Vector2 offset, Vector2 scale) { var name = CreateNameExt(parser.GLTF, textureIndex, TextureImportTypes.sRGB); var sampler = CreateSampler(parser.GLTF, textureIndex); GetTextureBytesAsync getTextureBytesAsync = () => Task.FromResult(ToArray(parser.GLTF.GetImageBytesFromTextureIndex(parser.Storage, textureIndex))); - return new TextureImportParam(name, sampler, TextureImportTypes.sRGB, default, default, getTextureBytesAsync, default, default, default, default, default); + return new TextureImportParam(name, offset, scale, sampler, TextureImportTypes.sRGB, default, default, getTextureBytesAsync, default, default, default, default, default); } - public static TextureImportParam CreateNormal(GltfParser parser, int textureIndex) + public static TextureImportParam CreateNormal(GltfParser parser, int textureIndex, Vector2 offset, Vector2 scale) { var name = CreateNameExt(parser.GLTF, textureIndex, TextureImportTypes.NormalMap); var sampler = CreateSampler(parser.GLTF, textureIndex); GetTextureBytesAsync getTextureBytesAsync = () => Task.FromResult(ToArray(parser.GLTF.GetImageBytesFromTextureIndex(parser.Storage, textureIndex))); - return new TextureImportParam(name, sampler, TextureImportTypes.NormalMap, default, default, getTextureBytesAsync, default, default, default, default, default); + return new TextureImportParam(name, offset, scale, sampler, TextureImportTypes.NormalMap, default, default, getTextureBytesAsync, default, default, default, default, default); } - public static TextureImportParam CreateStandard(GltfParser parser, int? metallicRoughnessTextureIndex, int? occlusionTextureIndex, float metallicFactor, float roughnessFactor) + public static TextureImportParam CreateStandard(GltfParser parser, int? metallicRoughnessTextureIndex, int? occlusionTextureIndex, Vector2 offset, Vector2 scale, float metallicFactor, float roughnessFactor) { TextureImportName name = default; @@ -312,23 +312,7 @@ namespace UniGLTF getOcclusionAsync = () => Task.FromResult(ToArray(parser.GLTF.GetImageBytesFromTextureIndex(parser.Storage, occlusionTextureIndex.Value))); } - return new TextureImportParam(name, sampler, TextureImportTypes.StandardMap, metallicFactor, roughnessFactor, getMetallicRoughnessAsync, getOcclusionAsync, default, default, default, default); - } - - public static TextureImportParam Create(GltfParser parser, int index, string prop, float metallicFactor, float roughnessFactor) - { - switch (prop) - { - case TextureImportParam.NORMAL_PROP: - return CreateNormal(parser, index); - - case TextureImportParam.OCCLUSION_PROP: - case TextureImportParam.METALLIC_GLOSS_PROP: - return CreateStandard(parser, index, default, metallicFactor, roughnessFactor); - - default: - return CreateSRGB(parser, index); - } + return new TextureImportParam(name, offset, scale, sampler, TextureImportTypes.StandardMap, metallicFactor, roughnessFactor, getMetallicRoughnessAsync, getOcclusionAsync, default, default, default, default); } public static TextureImportName CreateNameExt(glTF gltf, int textureIndex, TextureImportTypes textureType) diff --git a/Assets/VRM/Runtime/IO/VRMImporterContext.cs b/Assets/VRM/Runtime/IO/VRMImporterContext.cs index ce18012ee..e85f9f42b 100644 --- a/Assets/VRM/Runtime/IO/VRMImporterContext.cs +++ b/Assets/VRM/Runtime/IO/VRMImporterContext.cs @@ -297,7 +297,7 @@ namespace VRM meta.Title = gltfMeta.title; if (gltfMeta.texture >= 0) { - meta.Thumbnail = await TextureFactory.GetTextureAsync(awaitCaller, GLTF, TextureFactory.CreateSRGB(Parser, gltfMeta.texture)); + meta.Thumbnail = await TextureFactory.GetTextureAsync(awaitCaller, GLTF, TextureFactory.CreateSRGB(Parser, gltfMeta.texture, Vector2.zero, Vector2.one)); } meta.AllowedUser = gltfMeta.allowedUser; meta.ViolentUssage = gltfMeta.violentUssage; diff --git a/Assets/VRM/Runtime/IO/VRMMaterialImporter.cs b/Assets/VRM/Runtime/IO/VRMMaterialImporter.cs index af75fc1d5..29496a5a5 100644 --- a/Assets/VRM/Runtime/IO/VRMMaterialImporter.cs +++ b/Assets/VRM/Runtime/IO/VRMMaterialImporter.cs @@ -56,13 +56,14 @@ namespace VRM { material.SetFloat(kv.Key, kv.Value); } + + var offsetScaleMap = new Dictionary(); foreach (var kv in item.vectorProperties) { if (item.textureProperties.ContainsKey(kv.Key)) { // texture offset & scale - material.SetTextureOffset(kv.Key, new Vector2(kv.Value[0], kv.Value[1])); - material.SetTextureScale(kv.Key, new Vector2(kv.Value[2], kv.Value[3])); + offsetScaleMap.Add(kv.Key, kv.Value); } else { @@ -71,13 +72,22 @@ namespace VRM material.SetVector(kv.Key, v); } } + foreach (var kv in item.textureProperties) { - var param = TextureFactory.Create(parser, kv.Value, kv.Key, 1, 1); + var (offset, scale) = (Vector2.zero, Vector2.one); + if (offsetScaleMap.TryGetValue(kv.Key, out float[] value)) + { + offset = new Vector2(value[0], value[1]); + scale = new Vector2(value[2], value[3]); + } + + var param = VRMTextureParam.Create(parser, kv.Value, offset, scale, kv.Key, 1, 1); var texture = await getTexture(awaitCaller, parser.GLTF, param); if (texture != null) { material.SetTexture(kv.Key, texture); + MaterialFactory.SetTextureOffsetAndScale(material, kv.Key, offset, scale); } } foreach (var kv in item.keywordMap) diff --git a/Assets/VRM/Runtime/IO/VRMTextureEnumerator.cs b/Assets/VRM/Runtime/IO/VRMTextureEnumerator.cs index 5988d2015..7750ac618 100644 --- a/Assets/VRM/Runtime/IO/VRMTextureEnumerator.cs +++ b/Assets/VRM/Runtime/IO/VRMTextureEnumerator.cs @@ -1,5 +1,6 @@ using System.Collections.Generic; using UniGLTF; +using UnityEngine; using VRMShaders; namespace VRM @@ -20,10 +21,26 @@ namespace VRM if (vrmMaterial.shader == MToon.Utils.ShaderName) { // MToon + var offsetScaleMap = new Dictionary(); + foreach (var kv in vrmMaterial.vectorProperties) + { + if (vrmMaterial.textureProperties.ContainsKey(kv.Key)) + { + // texture offset & scale + offsetScaleMap.Add(kv.Key, kv.Value); + } + } foreach (var kv in vrmMaterial.textureProperties) { + var (offset, scale) = (Vector2.zero, Vector2.one); + if (offsetScaleMap.TryGetValue(kv.Key, out float[] value)) + { + offset = new Vector2(value[0], value[1]); + scale = new Vector2(value[2], value[3]); + } + // SRGB color or normalmap - yield return TextureFactory.Create(parser, kv.Value, kv.Key, default, default); + yield return VRMTextureParam.Create(parser, kv.Value, offset, scale, kv.Key, default, default); } } else @@ -39,7 +56,7 @@ namespace VRM // thumbnail if (m_vrm.meta != null && m_vrm.meta.texture != -1) { - yield return TextureFactory.CreateSRGB(parser, m_vrm.meta.texture); + yield return TextureFactory.CreateSRGB(parser, m_vrm.meta.texture, Vector2.zero, Vector2.one); } } } diff --git a/Assets/VRM/Runtime/IO/VRMTextureParam.cs b/Assets/VRM/Runtime/IO/VRMTextureParam.cs new file mode 100644 index 000000000..666fb2ba4 --- /dev/null +++ b/Assets/VRM/Runtime/IO/VRMTextureParam.cs @@ -0,0 +1,26 @@ +using System; +using UniGLTF; +using UnityEngine; +using VRMShaders; + +namespace VRM +{ + public static class VRMTextureParam + { + public static TextureImportParam Create(GltfParser parser, int index, Vector2 offset, Vector2 scale, string prop, float metallicFactor, float roughnessFactor) + { + switch (prop) + { + case TextureImportParam.NORMAL_PROP: + return TextureFactory.CreateNormal(parser, index, offset, scale); + + default: + return TextureFactory.CreateSRGB(parser, index, offset, scale); + + case TextureImportParam.OCCLUSION_PROP: + case TextureImportParam.METALLIC_GLOSS_PROP: + throw new NotImplementedException(); + } + } + } +} diff --git a/Assets/VRM/Runtime/IO/VRMTextureParam.cs.meta b/Assets/VRM/Runtime/IO/VRMTextureParam.cs.meta new file mode 100644 index 000000000..43d5a7e6d --- /dev/null +++ b/Assets/VRM/Runtime/IO/VRMTextureParam.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 58277bcba49b13142acfa67d40041970 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/VRMShaders/Runtime/TextureImportParam.cs b/Assets/VRMShaders/Runtime/TextureImportParam.cs index e619901d5..8e59e5c2f 100644 --- a/Assets/VRMShaders/Runtime/TextureImportParam.cs +++ b/Assets/VRMShaders/Runtime/TextureImportParam.cs @@ -1,6 +1,6 @@ using System; using System.Threading.Tasks; - +using UnityEngine; namespace VRMShaders { @@ -29,6 +29,9 @@ namespace VRMShaders public string ConvertedName => Name.ConvertedName; public string ConvertedFileName => Name.ConvertedFileName; public string Uri => Name.Uri; + + public Vector2 Offset; + public Vector2 Scale; public SamplerParam Sampler; @@ -48,7 +51,7 @@ namespace VRMShaders /// public bool ExtractConverted => TextureType == TextureImportTypes.StandardMap; - public TextureImportParam(TextureImportName name, SamplerParam sampler, TextureImportTypes textureType, float metallicFactor, float roughnessFactor, + public TextureImportParam(TextureImportName name, Vector2 offset, Vector2 scale, SamplerParam sampler, TextureImportTypes textureType, float metallicFactor, float roughnessFactor, GetTextureBytesAsync i0, GetTextureBytesAsync i1, GetTextureBytesAsync i2, @@ -57,6 +60,8 @@ namespace VRMShaders GetTextureBytesAsync i5) { Name = name; + Offset = offset; + Scale = scale; Sampler = sampler; TextureType = textureType; MetallicFactor = metallicFactor;