diff --git a/Assets/VRM/UniGLTF/Editor/Tests/TextureTests.cs b/Assets/VRM/UniGLTF/Editor/Tests/TextureTests.cs
index 4237f9156..e56302191 100644
--- a/Assets/VRM/UniGLTF/Editor/Tests/TextureTests.cs
+++ b/Assets/VRM/UniGLTF/Editor/Tests/TextureTests.cs
@@ -31,4 +31,99 @@ namespace UniGLTF
Assert.AreEqual(glFilter.LINEAR_MIPMAP_LINEAR, sampler.magFilter);
}
}
+
+ public class MetallicRoughnessConverterTests
+ {
+ [Test]
+ public void ExportingColorTest()
+ {
+ {
+ var smoothness = 1.0f;
+ var conv = new MetallicRoughnessConverter(smoothness);
+ Assert.That(
+ conv.Export(new Color32(255, 255, 255, 255)),
+ // r <- 0 : (Unused)
+ // g <- 0 : ((1 - s.a(as float) * smoothness) ^ 2)(as int8)
+ // b <- 255 : Same metallic (src.r)
+ // a <- 255 : (Unused)
+ Is.EqualTo(new Color32(0, 0, 255, 255)));
+ }
+
+ {
+ var smoothness = 0.5f;
+ var conv = new MetallicRoughnessConverter(smoothness);
+ Assert.That(
+ conv.Export(new Color32(255, 255, 255, 255)),
+ // r <- 0 : (Unused)
+ // g <- 63 : ((1 - s.a(as float) * smoothness) ^ 2)(as int8)
+ // b <- 255 : Same metallic (src.r)
+ // a <- 255 : (Unused)
+ Is.EqualTo(new Color32(0, 63, 255, 255)));
+ }
+
+ {
+ var smoothness = 0.0f;
+ var conv = new MetallicRoughnessConverter(smoothness);
+ Assert.That(
+ conv.Export(new Color32(255, 255, 255, 255)),
+ // r <- 0 : (Unused)
+ // g <- 255 : ((1 - s.a(as float) * smoothness) ^ 2)(as int8)
+ // b <- 255 : Same metallic (src.r)
+ // a <- 255 : (Unused)
+ Is.EqualTo(new Color32(0, 255, 255, 255)));
+ }
+ }
+
+ [Test]
+ public void ImportingColorTest()
+ {
+ {
+ var roughnessFactor = 1.0f;
+ var conv = new MetallicRoughnessConverter(roughnessFactor);
+ Assert.That(
+ conv.Import(new Color32(255, 255, 255, 255)),
+ // r <- 255 : Same metallic (src.r)
+ // g <- 0 : (Unused)
+ // b <- 0 : (Unused)
+ // a <- 255 : ((1 - sqrt(s.g(as float) * roughnessFactor)))(as int8)
+ Is.EqualTo(new Color32(255, 0, 0, 0)));
+ }
+
+ {
+ var roughnessFactor = 1.0f;
+ var conv = new MetallicRoughnessConverter(roughnessFactor);
+ Assert.That(
+ conv.Import(new Color32(255, 63, 255, 255)),
+ // r <- 255 : Same metallic (src.r)
+ // g <- 0 : (Unused)
+ // b <- 0 : (Unused)
+ // a <- 255 : ((1 - sqrt(s.g(as float) * roughnessFactor)))(as int8)
+ Is.EqualTo(new Color32(255, 0, 0, 128))); // smoothness 0.5 * src.a 1.0
+ }
+
+ {
+ var roughnessFactor = 0.5f;
+ var conv = new MetallicRoughnessConverter(roughnessFactor);
+ Assert.That(
+ conv.Import(new Color32(255, 255, 255, 255)),
+ // r <- 255 : Same metallic (src.r)
+ // g <- 0 : (Unused)
+ // b <- 0 : (Unused)
+ // a <- 255 : ((1 - sqrt(s.g(as float) * roughnessFactor)))(as int8)
+ Is.EqualTo(new Color32(255, 0, 0, 74)));
+ }
+
+ {
+ var roughnessFactor = 0.0f;
+ var conv = new MetallicRoughnessConverter(roughnessFactor);
+ Assert.That(
+ conv.Import(new Color32(255, 255, 255, 255)),
+ // r <- 255 : Same metallic (src.r)
+ // g <- 0 : (Unused)
+ // b <- 0 : (Unused)
+ // a <- 255 : ((1 - sqrt(s.g(as float) * roughnessFactor)))(as int8)
+ Is.EqualTo(new Color32(255, 0, 0, 255)));
+ }
+ }
+ }
}
diff --git a/Assets/VRM/UniGLTF/Scripts/IO/MaterialExporter.cs b/Assets/VRM/UniGLTF/Scripts/IO/MaterialExporter.cs
index 613971d76..e8943e336 100644
--- a/Assets/VRM/UniGLTF/Scripts/IO/MaterialExporter.cs
+++ b/Assets/VRM/UniGLTF/Scripts/IO/MaterialExporter.cs
@@ -61,20 +61,30 @@ namespace UniGLTF
int index = -1;
if (m.HasProperty("_MetallicGlossMap"))
{
- index = textureManager.ConvertAndGetIndex(m.GetTexture("_MetallicGlossMap"), new MetallicRoughnessConverter());
+ float smoothness = 0.0f;
+ if (m.HasProperty("_GlossMapScale"))
+ {
+ smoothness = m.GetFloat("_GlossMapScale");
+ }
+
+ // Bake smoothness values into a texture.
+ var converter = new MetallicRoughnessConverter(smoothness);
+ index = textureManager.ConvertAndGetIndex(m.GetTexture("_MetallicGlossMap"), converter);
if (index != -1)
{
- material.pbrMetallicRoughness.metallicRoughnessTexture = new glTFMaterialMetallicRoughnessTextureInfo()
- {
- index = index,
- };
+ material.pbrMetallicRoughness.metallicRoughnessTexture =
+ new glTFMaterialMetallicRoughnessTextureInfo()
+ {
+ index = index,
+ };
}
}
- if (index != -1 && m.HasProperty("_GlossMapScale"))
+ if (index != -1)
{
material.pbrMetallicRoughness.metallicFactor = 1.0f;
- material.pbrMetallicRoughness.roughnessFactor = 1.0f - m.GetFloat("_GlossMapScale");
+ // Set 1.0f as hard-coded. See: https://github.com/dwango/UniVRM/issues/212.
+ material.pbrMetallicRoughness.roughnessFactor = 1.0f;
}
else
{
@@ -82,11 +92,11 @@ namespace UniGLTF
{
material.pbrMetallicRoughness.metallicFactor = m.GetFloat("_Metallic");
}
+
if (m.HasProperty("_Glossiness"))
{
material.pbrMetallicRoughness.roughnessFactor = 1.0f - m.GetFloat("_Glossiness");
}
-
}
}
diff --git a/Assets/VRM/UniGLTF/Scripts/IO/MaterialImporter.cs b/Assets/VRM/UniGLTF/Scripts/IO/MaterialImporter.cs
index 335b32397..31db25670 100644
--- a/Assets/VRM/UniGLTF/Scripts/IO/MaterialImporter.cs
+++ b/Assets/VRM/UniGLTF/Scripts/IO/MaterialImporter.cs
@@ -164,11 +164,13 @@ namespace UniGLTF
if (texture != null)
{
var prop = "_MetallicGlossMap";
- material.SetTexture(prop, texture.ConvertTexture(prop));
+ // Bake roughnessFactor values into a texture.
+ material.SetTexture(prop, texture.ConvertTexture(prop, x.pbrMetallicRoughness.roughnessFactor));
}
material.SetFloat("_Metallic", 1.0f);
- material.SetFloat("_GlossMapScale", 1.0f - x.pbrMetallicRoughness.roughnessFactor);
+ // Set 1.0f as hard-coded. See: https://github.com/dwango/UniVRM/issues/212.
+ material.SetFloat("_GlossMapScale", 1.0f);
}
else
{
diff --git a/Assets/VRM/UniGLTF/Scripts/IO/TextureConverter.cs b/Assets/VRM/UniGLTF/Scripts/IO/TextureConverter.cs
index b10e27682..d6323588a 100644
--- a/Assets/VRM/UniGLTF/Scripts/IO/TextureConverter.cs
+++ b/Assets/VRM/UniGLTF/Scripts/IO/TextureConverter.cs
@@ -1,3 +1,4 @@
+using System;
using System.Linq;
using UnityEngine;
#if UNITY_EDITOR
@@ -46,10 +47,17 @@ namespace UniGLTF
}
}
- class MetallicRoughnessConverter : ITextureConverter
+ public class MetallicRoughnessConverter : ITextureConverter
{
private const string m_extension = ".metallicRoughness";
+ private float _smoothnessOrRoughness;
+
+ public MetallicRoughnessConverter(float smoothnessOrRoughness)
+ {
+ _smoothnessOrRoughness = smoothnessOrRoughness;
+ }
+
public Texture2D GetImportTexture(Texture2D texture)
{
var converted = TextureConverter.Convert(texture, glTFTextureTypes.Metallic, Import, null);
@@ -66,28 +74,46 @@ namespace UniGLTF
public Color32 Import(Color32 src)
{
+ // Roughness(glTF): dst.g -> Smoothness(Unity): src.a (with conversion)
+ // Metallic(glTF) : dst.b -> Metallic(Unity) : src.r
+
+ var pixelRoughnessFactor = (src.g * _smoothnessOrRoughness) / 255.0f; // roughness
+ var pixelSmoothness = 1.0f - Mathf.Sqrt(pixelRoughnessFactor);
+
return new Color32
{
r = src.b,
g = 0,
b = 0,
- a = (byte)(255 - src.g),
+ // Bake roughness values into a texture.
+ // See: https://github.com/dwango/UniVRM/issues/212.
+ a = (byte)Mathf.Clamp(pixelSmoothness * 255, 0, 255),
};
}
public Color32 Export(Color32 src)
{
+ // Smoothness(Unity): src.a -> Roughness(glTF): dst.g (with conversion)
+ // Metallic(Unity) : src.r -> Metallic(glTF) : dst.b
+
+ var pixelSmoothness = (src.a * _smoothnessOrRoughness) / 255.0f; // smoothness
+ // https://blogs.unity3d.com/jp/2016/01/25/ggx-in-unity-5-3/
+ var pixelRoughnessFactorSqrt = (1.0f - pixelSmoothness);
+ var pixelRoughnessFactor = pixelRoughnessFactorSqrt * pixelRoughnessFactorSqrt;
+
return new Color32
{
r = 0,
- g = (byte)(255 - src.a),
+ // Bake smoothness values into a texture.
+ // See: https://github.com/dwango/UniVRM/issues/212.
+ g = (byte)Mathf.Clamp(pixelRoughnessFactor * 255, 0, 255),
b = src.r,
a = 255,
};
}
}
- class NormalConverter : ITextureConverter
+ public class NormalConverter : ITextureConverter
{
private const string m_extension = ".normal";
@@ -132,7 +158,7 @@ namespace UniGLTF
}
}
- class OcclusionConverter : ITextureConverter
+ public class OcclusionConverter : ITextureConverter
{
private const string m_extension = ".occlusion";
diff --git a/Assets/VRM/UniGLTF/Scripts/IO/TextureItem.cs b/Assets/VRM/UniGLTF/Scripts/IO/TextureItem.cs
index 1f79ca13f..87f7fb26a 100644
--- a/Assets/VRM/UniGLTF/Scripts/IO/TextureItem.cs
+++ b/Assets/VRM/UniGLTF/Scripts/IO/TextureItem.cs
@@ -30,7 +30,13 @@ namespace UniGLTF
get { return m_converts; }
}
- public Texture2D ConvertTexture(string prop)
+ ///
+ ///
+ ///
+ ///
+ /// used only when converting MetallicRoughness maps
+ ///
+ public Texture2D ConvertTexture(string prop, float smoothnessOrRoughness = 1.0f)
{
var convertedTexture = Converts.FirstOrDefault(x => x.Key == prop);
if (convertedTexture.Value != null)
@@ -63,7 +69,7 @@ namespace UniGLTF
if (prop == "_MetallicGlossMap")
{
- var converted = new MetallicRoughnessConverter().GetImportTexture(Texture);
+ var converted = new MetallicRoughnessConverter(smoothnessOrRoughness).GetImportTexture(Texture);
m_converts.Add(prop, converted);
return converted;
}