mirror of
https://github.com/vrm-c/UniVRM.git
synced 2026-05-11 21:14:19 -05:00
202 lines
6.5 KiB
C#
202 lines
6.5 KiB
C#
using System;
|
|
using System.Linq;
|
|
using UnityEngine;
|
|
#if UNITY_EDITOR
|
|
using UnityEditor;
|
|
#endif
|
|
|
|
|
|
namespace UniGLTF
|
|
{
|
|
public interface ITextureConverter
|
|
{
|
|
Texture2D GetImportTexture(Texture2D texture);
|
|
Texture2D GetExportTexture(Texture2D texture);
|
|
}
|
|
|
|
public static class TextureConverter
|
|
{
|
|
public delegate Color32 ColorConversion(Color32 color);
|
|
|
|
public static Texture2D Convert(Texture2D texture, glTFTextureTypes textureType, ColorConversion colorConversion, Material convertMaterial)
|
|
{
|
|
var copyTexture = TextureItem.CopyTexture(texture, TextureIO.GetColorSpace(textureType), convertMaterial);
|
|
if (colorConversion != null)
|
|
{
|
|
copyTexture.SetPixels32(copyTexture.GetPixels32().Select(x => colorConversion(x)).ToArray());
|
|
copyTexture.Apply();
|
|
}
|
|
copyTexture.name = texture.name;
|
|
return copyTexture;
|
|
}
|
|
|
|
public static void AppendTextureExtension(Texture texture, string extension)
|
|
{
|
|
if (!texture.name.EndsWith(extension))
|
|
{
|
|
texture.name = texture.name + extension;
|
|
}
|
|
}
|
|
|
|
public static void RemoveTextureExtension(Texture texture, string extension)
|
|
{
|
|
if (texture.name.EndsWith(extension))
|
|
{
|
|
texture.name = texture.name.Replace(extension, "");
|
|
}
|
|
}
|
|
}
|
|
|
|
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);
|
|
TextureConverter.AppendTextureExtension(converted, m_extension);
|
|
return converted;
|
|
}
|
|
|
|
public Texture2D GetExportTexture(Texture2D texture)
|
|
{
|
|
var converted = TextureConverter.Convert(texture, glTFTextureTypes.Metallic, Export, null);
|
|
TextureConverter.RemoveTextureExtension(converted, m_extension);
|
|
return converted;
|
|
}
|
|
|
|
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,
|
|
// 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,
|
|
// 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,
|
|
};
|
|
}
|
|
}
|
|
|
|
public class NormalConverter : ITextureConverter
|
|
{
|
|
private const string m_extension = ".normal";
|
|
|
|
private Material m_decoder;
|
|
private Material GetDecoder()
|
|
{
|
|
if (m_decoder == null)
|
|
{
|
|
m_decoder = new Material(Shader.Find("UniGLTF/NormalMapDecoder"));
|
|
}
|
|
return m_decoder;
|
|
}
|
|
|
|
private Material m_encoder;
|
|
private Material GetEncoder()
|
|
{
|
|
if (m_encoder == null)
|
|
{
|
|
m_encoder = new Material(Shader.Find("UniGLTF/NormalMapEncoder"));
|
|
}
|
|
return m_encoder;
|
|
}
|
|
|
|
// GLTF data to Unity texture
|
|
// ConvertToNormalValueFromRawColorWhenCompressionIsRequired
|
|
public Texture2D GetImportTexture(Texture2D texture)
|
|
{
|
|
var mat = GetEncoder();
|
|
var converted = TextureConverter.Convert(texture, glTFTextureTypes.Normal, null, mat);
|
|
TextureConverter.AppendTextureExtension(converted, m_extension);
|
|
return converted;
|
|
}
|
|
|
|
// Unity texture to GLTF data
|
|
// ConvertToRawColorWhenNormalValueIsCompressed
|
|
public Texture2D GetExportTexture(Texture2D texture)
|
|
{
|
|
var mat = GetDecoder();
|
|
var converted = TextureConverter.Convert(texture, glTFTextureTypes.Normal, null, mat);
|
|
TextureConverter.RemoveTextureExtension(converted, m_extension);
|
|
return converted;
|
|
}
|
|
}
|
|
|
|
public class OcclusionConverter : ITextureConverter
|
|
{
|
|
private const string m_extension = ".occlusion";
|
|
|
|
public Texture2D GetImportTexture(Texture2D texture)
|
|
{
|
|
var converted = TextureConverter.Convert(texture, glTFTextureTypes.Occlusion, Import, null);
|
|
TextureConverter.AppendTextureExtension(converted, m_extension);
|
|
return converted;
|
|
}
|
|
|
|
public Texture2D GetExportTexture(Texture2D texture)
|
|
{
|
|
var converted = TextureConverter.Convert(texture, glTFTextureTypes.Occlusion, Export, null);
|
|
TextureConverter.RemoveTextureExtension(converted, m_extension);
|
|
return converted;
|
|
}
|
|
|
|
public Color32 Import(Color32 src)
|
|
{
|
|
return new Color32
|
|
{
|
|
r = 0,
|
|
g = src.r,
|
|
b = 0,
|
|
a = 255,
|
|
};
|
|
}
|
|
|
|
public Color32 Export(Color32 src)
|
|
{
|
|
return new Color32
|
|
{
|
|
r = src.g,
|
|
g = 0,
|
|
b = 0,
|
|
a = 255,
|
|
};
|
|
}
|
|
}
|
|
}
|