Merge pull request #780 from ousttrue/fix/roughness_smooth_conversion

MetallicRoughnessOcclusion テクスチャーの取り廻しを中心に改修
This commit is contained in:
ousttrue
2021-03-17 17:51:18 +09:00
committed by GitHub
68 changed files with 1243 additions and 1101 deletions

View File

@@ -8,10 +8,7 @@ namespace UniGLTF
public static Task<Texture2D> LoadTaskAsync(UnityPath m_assetPath,
glTF gltf, int textureIndex)
{
var textureType = TextureIO.GetglTFTextureType(gltf, textureIndex);
var colorSpace = TextureIO.GetColorSpace(textureType);
var isLinear = colorSpace == RenderTextureReadWrite.Linear;
var sampler = gltf.GetSamplerFromTextureIndex(textureIndex);
var colorSpace = gltf.GetColorSpace(textureIndex);
//
// texture from assets
@@ -25,7 +22,7 @@ namespace UniGLTF
else
{
importer.maxTextureSize = 8192;
importer.sRGBTexture = !isLinear;
importer.sRGBTexture = colorSpace == RenderTextureReadWrite.sRGB;
importer.SaveAndReimport();
}
@@ -50,6 +47,7 @@ namespace UniGLTF
importer.SaveAndReimport();
}
var sampler = gltf.GetSamplerFromTextureIndex(textureIndex);
if (sampler != null)
{
TextureSamplerUtil.SetSampler(Texture, sampler);

View File

@@ -30,8 +30,8 @@ namespace UniGLTF
}
}
static bool s_foldMaterials;
static bool s_foldTextures;
static bool s_foldMaterials = true;
static bool s_foldTextures = true;
public static void OnGUIMaterial(ScriptedImporter importer, GltfParser parser)
{
@@ -56,7 +56,17 @@ namespace UniGLTF
s_foldTextures = EditorGUILayout.Foldout(s_foldTextures, "Remapped Textures");
if (s_foldTextures)
{
DrawRemapGUI<UnityEngine.Texture2D>(importer, GltfTextureEnumerator.Enumerate(parser.GLTF).Select(x => x.ConvertedName));
DrawRemapGUI<UnityEngine.Texture2D>(importer, GltfTextureEnumerator.Enumerate(parser.GLTF).Select(x =>
{
switch (x.TextureType)
{
case GetTextureParam.TextureTypes.NormalMap:
return x.GltflName;
default:
return x.ConvertedName;
}
}));
}
if (GUILayout.Button("Clear"))

View File

@@ -17,14 +17,7 @@ namespace UniGLTF
public override void OnImportAsset(AssetImportContext ctx)
{
try
{
ScriptedImporterImpl.Import(this, ctx, m_reverseAxis);
}
catch (System.Exception ex)
{
Debug.LogError(ex);
}
ScriptedImporterImpl.Import(this, ctx, m_reverseAxis);
}
}
}

View File

@@ -17,14 +17,7 @@ namespace UniGLTF
public override void OnImportAsset(AssetImportContext ctx)
{
try
{
ScriptedImporterImpl.Import(this, ctx, m_reverseAxis);
}
catch (System.Exception ex)
{
Debug.LogError(ex);
}
ScriptedImporterImpl.Import(this, ctx, m_reverseAxis);
}
}
}

View File

@@ -1,3 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEditor;
@@ -40,6 +41,12 @@ namespace UniGLTF
externalObjectMap.Where(x => x.Value != null).Select(x => (x.Value.name, x.Value)).Concat(
EnumerateTexturesFromUri(externalObjectMap, parser, UnityPath.FromUnityPath(scriptedImporter.assetPath).Parent))))
{
// settings TextureImporters
foreach (var textureInfo in GltfTextureEnumerator.Enumerate(parser.GLTF))
{
TextureImporterConfigurator.Configure(textureInfo, loaded.TextureFactory.ExternalMap);
}
loaded.InvertAxis = reverseAxis;
loaded.Load();
loaded.ShowMeshes();
@@ -69,8 +76,7 @@ namespace UniGLTF
{
switch (texParam.TextureType)
{
case GetTextureParam.METALLIC_GLOSS_PROP:
case GetTextureParam.OCCLUSION_PROP:
case GetTextureParam.TextureTypes.StandardMap:
break;
default:

View File

@@ -70,8 +70,7 @@ namespace UniGLTF
switch (param.TextureType)
{
case GetTextureParam.METALLIC_GLOSS_PROP:
case GetTextureParam.OCCLUSION_PROP:
case GetTextureParam.TextureTypes.StandardMap:
{
// write converted texture
targetPath = $"{m_path}/{param.ConvertedName}.png";
@@ -130,40 +129,13 @@ namespace UniGLTF
EditorApplication.delayCall += () =>
{
// Wait for the texture assets to be imported
foreach (var kv in extractor.Textures)
{
var targetPath = kv.Key;
var param = kv.Value;
// TextureImporter
var targetTextureImporter = AssetImporter.GetAtPath(targetPath) as TextureImporter;
if (targetTextureImporter != null)
{
switch (param.TextureType)
{
case GetTextureParam.OCCLUSION_PROP:
case GetTextureParam.METALLIC_GLOSS_PROP:
#if VRM_DEVELOP
Debug.Log($"{targetPath} => linear");
#endif
targetTextureImporter.sRGBTexture = false;
targetTextureImporter.SaveAndReimport();
break;
case GetTextureParam.NORMAL_PROP:
#if VRM_DEVELOP
Debug.Log($"{targetPath} => normalmap");
#endif
targetTextureImporter.textureType = TextureImporterType.NormalMap;
targetTextureImporter.SaveAndReimport();
break;
}
}
else
{
throw new FileNotFoundException(targetPath);
}
// remap
var externalObject = AssetDatabase.LoadAssetAtPath<UnityEngine.Texture2D>(targetPath);
if (externalObject != null)

View File

@@ -0,0 +1,74 @@
using System;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
namespace UniGLTF
{
public static class TextureImporterConfigurator
{
public static void ConfigureNormalMap(Texture2D texture)
{
var path = UnityPath.FromAsset(texture);
if (AssetImporter.GetAtPath(path.Value) is TextureImporter textureImporter)
{
#if VRM_DEVELOP
Debug.Log($"{path} => normalmap");
#endif
textureImporter.textureType = TextureImporterType.NormalMap;
textureImporter.SaveAndReimport();
}
else
{
throw new System.IO.FileNotFoundException($"{path}");
}
}
public static void ConfigureLinear(Texture2D texture)
{
var path = UnityPath.FromAsset(texture);
if (AssetImporter.GetAtPath(path.Value) is TextureImporter textureImporter)
{
#if VRM_DEVELOP
Debug.Log($"{path} => linear");
#endif
textureImporter.sRGBTexture = false;
textureImporter.SaveAndReimport();
}
else
{
throw new System.IO.FileNotFoundException($"{path}");
}
}
public static void Configure(GetTextureParam textureInfo, IDictionary<string, Texture2D> ExternalMap)
{
switch (textureInfo.TextureType)
{
case GetTextureParam.TextureTypes.NormalMap:
{
if (ExternalMap.TryGetValue(textureInfo.GltflName, out Texture2D external))
{
ConfigureNormalMap(external);
}
}
break;
case GetTextureParam.TextureTypes.StandardMap:
{
if (ExternalMap.TryGetValue(textureInfo.ConvertedName, out Texture2D external))
{
ConfigureLinear(external);
}
}
break;
case GetTextureParam.TextureTypes.sRGB:
break;
default:
throw new NotImplementedException();
}
}
}
}

View File

@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 55c6531d46a98a845b19cbe1f938eab1
guid: 193b7c6393807a04f8aafabc23478f8e
MonoImporter:
externalObjects: {}
serializedVersion: 2

View File

@@ -5,12 +5,10 @@ namespace UniGLTF
{
public enum glTFTextureTypes
{
BaseColor,
Metallic,
OcclusionMetallicRoughness,
Normal,
Occlusion,
Emissive,
Unknown
SRGB,
Linear,
}
public interface IglTFTextureinfo
@@ -38,19 +36,13 @@ namespace UniGLTF
[Serializable]
public class glTFMaterialBaseColorTextureInfo : glTFTextureInfo
{
public override glTFTextureTypes TextureType
{
get { return glTFTextureTypes.BaseColor; }
}
public override glTFTextureTypes TextureType => glTFTextureTypes.SRGB;
}
[Serializable]
public class glTFMaterialMetallicRoughnessTextureInfo : glTFTextureInfo
{
public override glTFTextureTypes TextureType
{
get { return glTFTextureTypes.Metallic; }
}
public override glTFTextureTypes TextureType => glTFTextureTypes.OcclusionMetallicRoughness;
}
[Serializable]
@@ -70,19 +62,13 @@ namespace UniGLTF
[JsonSchema(Minimum = 0.0, Maximum = 1.0)]
public float strength = 1.0f;
public override glTFTextureTypes TextureType
{
get { return glTFTextureTypes.Occlusion; }
}
public override glTFTextureTypes TextureType => glTFTextureTypes.OcclusionMetallicRoughness;
}
[Serializable]
public class glTFMaterialEmissiveTextureInfo : glTFTextureInfo
{
public override glTFTextureTypes TextureType
{
get { return glTFTextureTypes.Emissive; }
}
public override glTFTextureTypes TextureType => glTFTextureTypes.SRGB;
}
[Serializable]

View File

@@ -1,16 +0,0 @@
using System;
using System.Collections.Generic;
using UnityEngine;
#if UNITY_EDITOR
#endif
namespace UniGLTF
{
public interface ITextureExporter
{
(Byte[] bytes, string mine) GetBytesWithMime(Texture texture, glTFTextureTypes textureType);
IEnumerable<(Texture texture, glTFTextureTypes textureType)> GetTextures(Material m);
int ExportTexture(glTF gltf, int bufferIndex, Texture texture, glTFTextureTypes textureType);
}
}

View File

@@ -56,6 +56,7 @@ namespace UniGLTF
};
#endif
}
m_textureFactory = new TextureFactory(loadTextureAsync, externalObjectMap);
m_materialFactory = new MaterialFactory(GLTF, Storage, externalObjectMap);
}

View File

@@ -1,12 +0,0 @@
fileFormatVersion: 2
guid: 99662edfbf59e8f458bcba3b62b13050
timeCreated: 1533622882
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 79721770f23ba6748abc1720cd99ad74
guid: 84cb103042e9924459b7dfc465ef4cef
folderAsset: yes
DefaultImporter:
externalObjects: {}

View File

@@ -8,6 +8,7 @@ namespace UniGLTF
{
public static IEnumerable<GetTextureParam> EnumerateTextures(glTF gltf, glTFMaterial m)
{
int? metallicRoughnessTexture = default;
if (m.pbrMetallicRoughness != null)
{
// base color
@@ -17,16 +18,16 @@ namespace UniGLTF
}
// metallic roughness
if (m.pbrMetallicRoughness?.metallicRoughnessTexture != null)
if (m.pbrMetallicRoughness?.metallicRoughnessTexture != null && m.pbrMetallicRoughness.metallicRoughnessTexture.index != -1)
{
yield return PBRMaterialItem.MetallicRoughnessTexture(gltf, m);
metallicRoughnessTexture = m.pbrMetallicRoughness?.metallicRoughnessTexture?.index;
}
}
// emission
if (m.emissiveTexture != null)
{
yield return GetTextureParam.Create(gltf, m.emissiveTexture.index);
yield return GetTextureParam.CreateSRGB(gltf, m.emissiveTexture.index);
}
// normal
@@ -36,9 +37,16 @@ namespace UniGLTF
}
// occlusion
if (m.occlusionTexture != null)
int? occlusionTexture = default;
if (m.occlusionTexture != null && m.occlusionTexture.index != -1)
{
yield return PBRMaterialItem.OcclusionTexture(gltf, m);
occlusionTexture = m.occlusionTexture.index;
}
// metallicSmooth and occlusion
if (metallicRoughnessTexture.HasValue || occlusionTexture.HasValue)
{
yield return PBRMaterialItem.StandardTexture(gltf, m);
}
}

View File

@@ -1,6 +1,5 @@
using System.Collections.Generic;
using System;
using UniGLTF.UniUnlit;
using UniJSON;
using UnityEngine;
@@ -15,27 +14,26 @@ namespace UniGLTF
public interface IMaterialExporter
{
glTFMaterial ExportMaterial(Material m, TextureExportManager textureManager);
glTFMaterial ExportMaterial(Material m, TextureExporter textureManager);
}
public class MaterialExporter : IMaterialExporter
{
public virtual glTFMaterial ExportMaterial(Material m, TextureExportManager textureManager)
public virtual glTFMaterial ExportMaterial(Material m, TextureExporter textureManager)
{
var material = CreateMaterial(m);
// common params
material.name = m.name;
Export_Color(m, textureManager, material);
Export_Metallic(m, textureManager, material);
Export_Normal(m, textureManager, material);
Export_Occlusion(m, textureManager, material);
Export_Emission(m, textureManager, material);
Export_Normal(m, textureManager, material);
Export_OcclusionMetallicRoughness(m, textureManager, material);
return material;
}
static void Export_Color(Material m, TextureExportManager textureManager, glTFMaterial material)
static void Export_Color(Material m, TextureExporter textureManager, glTFMaterial material)
{
if (m.HasProperty("_Color"))
{
@@ -44,7 +42,7 @@ namespace UniGLTF
if (m.HasProperty("_MainTex"))
{
var index = textureManager.CopyAndGetIndex(m.GetTexture("_MainTex"), RenderTextureReadWrite.sRGB);
var index = textureManager.ExportSRGB(m.GetTexture("_MainTex"));
if (index != -1)
{
material.pbrMetallicRoughness.baseColorTexture = new glTFMaterialBaseColorTextureInfo()
@@ -57,36 +55,49 @@ namespace UniGLTF
}
}
static void Export_Metallic(Material m, TextureExportManager textureManager, glTFMaterial material)
/// <summary>
/// Occlusion, Metallic, Roughness
/// </summary>
/// <param name="m"></param>
/// <param name="textureManager"></param>
/// <param name="material"></param>
static void Export_OcclusionMetallicRoughness(Material m, TextureExporter textureManager, glTFMaterial material)
{
int index = -1;
Texture metallicSmoothTexture = default;
float smoothness = 1.0f;
if (m.HasProperty("_MetallicGlossMap"))
{
float smoothness = 0.0f;
if (m.HasProperty("_GlossMapScale"))
{
smoothness = m.GetFloat("_GlossMapScale");
}
metallicSmoothTexture = m.GetTexture("_MetallicGlossMap");
}
// Bake smoothness values into a texture.
var converter = new MetallicRoughnessConverter(smoothness);
index = textureManager.ConvertAndGetIndex(m.GetTexture("_MetallicGlossMap"), converter);
if (index != -1)
Texture occlusionTexture = default;
var occlusionStrength = 1.0f;
if (m.HasProperty("_OcclusionMap"))
{
occlusionTexture = m.GetTexture("_OcclusionMap");
if (occlusionTexture != null && m.HasProperty("_OcclusionStrength"))
{
material.pbrMetallicRoughness.metallicRoughnessTexture =
new glTFMaterialMetallicRoughnessTextureInfo()
{
index = index,
};
Export_MainTextureTransform(m, material.pbrMetallicRoughness.metallicRoughnessTexture);
occlusionStrength = m.GetFloat("_OcclusionStrength");
}
}
if (index != -1)
int index = textureManager.ExportMetallicSmoothnessOcclusion(metallicSmoothTexture, smoothness, occlusionTexture);
if (index != -1 && metallicSmoothTexture != null)
{
material.pbrMetallicRoughness.metallicFactor = 1.0f;
material.pbrMetallicRoughness.metallicRoughnessTexture =
new glTFMaterialMetallicRoughnessTextureInfo()
{
index = index,
};
Export_MainTextureTransform(m, material.pbrMetallicRoughness.metallicRoughnessTexture);
// Set 1.0f as hard-coded. See: https://github.com/dwango/UniVRM/issues/212.
material.pbrMetallicRoughness.metallicFactor = 1.0f;
material.pbrMetallicRoughness.roughnessFactor = 1.0f;
}
else
@@ -101,13 +112,23 @@ namespace UniGLTF
material.pbrMetallicRoughness.roughnessFactor = 1.0f - m.GetFloat("_Glossiness");
}
}
if (index != -1 && occlusionTexture != null)
{
material.occlusionTexture = new glTFMaterialOcclusionTextureInfo()
{
index = index,
strength = occlusionStrength,
};
Export_MainTextureTransform(m, material.occlusionTexture);
}
}
static void Export_Normal(Material m, TextureExportManager textureManager, glTFMaterial material)
static void Export_Normal(Material m, TextureExporter textureManager, glTFMaterial material)
{
if (m.HasProperty("_BumpMap"))
{
var index = textureManager.ConvertAndGetIndex(m.GetTexture("_BumpMap"), new NormalConverter());
var index = textureManager.ExportNormal(m.GetTexture("_BumpMap"));
if (index != -1)
{
material.normalTexture = new glTFMaterialNormalTextureInfo()
@@ -125,29 +146,7 @@ namespace UniGLTF
}
}
static void Export_Occlusion(Material m, TextureExportManager textureManager, glTFMaterial material)
{
if (m.HasProperty("_OcclusionMap"))
{
var index = textureManager.ConvertAndGetIndex(m.GetTexture("_OcclusionMap"), new OcclusionConverter());
if (index != -1)
{
material.occlusionTexture = new glTFMaterialOcclusionTextureInfo()
{
index = index,
};
Export_MainTextureTransform(m, material.occlusionTexture);
}
if (index != -1 && m.HasProperty("_OcclusionStrength"))
{
material.occlusionTexture.strength = m.GetFloat("_OcclusionStrength");
}
}
}
static void Export_Emission(Material m, TextureExportManager textureManager, glTFMaterial material)
static void Export_Emission(Material m, TextureExporter textureManager, glTFMaterial material)
{
if (m.IsKeywordEnabled("_EMISSION") == false)
return;
@@ -164,7 +163,7 @@ namespace UniGLTF
if (m.HasProperty("_EmissionMap"))
{
var index = textureManager.CopyAndGetIndex(m.GetTexture("_EmissionMap"), RenderTextureReadWrite.sRGB);
var index = textureManager.ExportSRGB(m.GetTexture("_EmissionMap"));
if (index != -1)
{
material.emissiveTexture = new glTFMaterialEmissiveTextureInfo()

View File

@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 9968c71baa1b1c04c94b0d3191cf513a
guid: 89f71b1d593633c47bfd4cfef050ae0d
MonoImporter:
externalObjects: {}
serializedVersion: 2

View File

@@ -0,0 +1,230 @@

using System.Threading.Tasks;
using UnityEngine;
namespace UniGLTF
{
/// StandardShader variables
///
/// _Color
/// _MainTex
/// _Cutoff
/// _Glossiness
/// _Metallic
/// _MetallicGlossMap
/// _BumpScale
/// _BumpMap
/// _Parallax
/// _ParallaxMap
/// _OcclusionStrength
/// _OcclusionMap
/// _EmissionColor
/// _EmissionMap
/// _DetailMask
/// _DetailAlbedoMap
/// _DetailNormalMapScale
/// _DetailNormalMap
/// _UVSec
/// _EmissionScaleUI
/// _EmissionColorUI
/// _Mode
/// _SrcBlend
/// _DstBlend
/// _ZWrite
public static class PBRMaterialItem
{
public const string ShaderName = "Standard";
private enum BlendMode
{
Opaque,
Cutout,
Fade,
Transparent
}
public static GetTextureParam BaseColorTexture(glTF gltf, glTFMaterial src)
{
return GetTextureParam.CreateSRGB(gltf, src.pbrMetallicRoughness.baseColorTexture.index);
}
public static GetTextureParam StandardTexture(glTF gltf, glTFMaterial src)
{
var metallicFactor = 1.0f;
var roughnessFactor = 1.0f;
if (src.pbrMetallicRoughness != null)
{
metallicFactor = src.pbrMetallicRoughness.metallicFactor;
roughnessFactor = src.pbrMetallicRoughness.roughnessFactor;
}
return GetTextureParam.CreateStandard(gltf,
src.pbrMetallicRoughness?.metallicRoughnessTexture?.index,
src.occlusionTexture?.index,
metallicFactor,
roughnessFactor);
}
public static GetTextureParam NormalTexture(glTF gltf, glTFMaterial src)
{
return GetTextureParam.CreateNormal(gltf, src.normalTexture.index);
}
public static async Task<Material> CreateAsync(IAwaitCaller awaitCaller, glTF gltf, int i, GetTextureAsyncFunc getTexture)
{
if (getTexture == null)
{
getTexture = (IAwaitCaller _awaitCaller, glTF _gltf, GetTextureParam _param) => Task.FromResult<Texture2D>(null);
}
if (i < 0 || i >= gltf.materials.Count)
{
return MaterialFactory.CreateMaterial(i, null, ShaderName);
}
var src = gltf.materials[i];
var material = MaterialFactory.CreateMaterial(i, src, ShaderName);
var standardParam = default(GetTextureParam);
if (src.pbrMetallicRoughness != null || src.occlusionTexture != null)
{
if (src.pbrMetallicRoughness.metallicRoughnessTexture != null || src.occlusionTexture != null)
{
standardParam = StandardTexture(gltf, src);
}
if (src.pbrMetallicRoughness.baseColorFactor != null && src.pbrMetallicRoughness.baseColorFactor.Length == 4)
{
var color = src.pbrMetallicRoughness.baseColorFactor;
material.color = (new Color(color[0], color[1], color[2], color[3])).gamma;
}
if (src.pbrMetallicRoughness.baseColorTexture != null && src.pbrMetallicRoughness.baseColorTexture.index != -1)
{
material.mainTexture = await getTexture(awaitCaller, gltf, BaseColorTexture(gltf, src));
// Texture Offset and Scale
MaterialFactory.SetTextureOffsetAndScale(material, src.pbrMetallicRoughness.baseColorTexture, "_MainTex");
}
if (src.pbrMetallicRoughness.metallicRoughnessTexture != null && src.pbrMetallicRoughness.metallicRoughnessTexture.index != -1)
{
material.EnableKeyword("_METALLICGLOSSMAP");
var texture = await getTexture(awaitCaller, gltf, standardParam);
if (texture != null)
{
material.SetTexture(GetTextureParam.METALLIC_GLOSS_PROP, texture);
}
material.SetFloat("_Metallic", 1.0f);
// Set 1.0f as hard-coded. See: https://github.com/dwango/UniVRM/issues/212.
material.SetFloat("_GlossMapScale", 1.0f);
// Texture Offset and Scale
MaterialFactory.SetTextureOffsetAndScale(material, src.pbrMetallicRoughness.metallicRoughnessTexture, "_MetallicGlossMap");
}
else
{
material.SetFloat("_Metallic", src.pbrMetallicRoughness.metallicFactor);
material.SetFloat("_Glossiness", 1.0f - src.pbrMetallicRoughness.roughnessFactor);
}
}
if (src.normalTexture != null && src.normalTexture.index != -1)
{
material.EnableKeyword("_NORMALMAP");
var texture = await getTexture(awaitCaller, gltf, NormalTexture(gltf, src));
if (texture != null)
{
material.SetTexture(GetTextureParam.NORMAL_PROP, texture);
material.SetFloat("_BumpScale", src.normalTexture.scale);
}
// Texture Offset and Scale
MaterialFactory.SetTextureOffsetAndScale(material, src.normalTexture, "_BumpMap");
}
if (src.occlusionTexture != null && src.occlusionTexture.index != -1)
{
var texture = await getTexture(awaitCaller, gltf, standardParam);
if (texture != null)
{
material.SetTexture(GetTextureParam.OCCLUSION_PROP, texture);
material.SetFloat("_OcclusionStrength", src.occlusionTexture.strength);
}
// Texture Offset and Scale
MaterialFactory.SetTextureOffsetAndScale(material, src.occlusionTexture, "_OcclusionMap");
}
if (src.emissiveFactor != null
|| (src.emissiveTexture != null && src.emissiveTexture.index != -1))
{
material.EnableKeyword("_EMISSION");
material.globalIlluminationFlags &= ~MaterialGlobalIlluminationFlags.EmissiveIsBlack;
if (src.emissiveFactor != null && src.emissiveFactor.Length == 3)
{
material.SetColor("_EmissionColor", new Color(src.emissiveFactor[0], src.emissiveFactor[1], src.emissiveFactor[2]));
}
if (src.emissiveTexture != null && src.emissiveTexture.index != -1)
{
var texture = await getTexture(awaitCaller, gltf, GetTextureParam.CreateSRGB(gltf, src.emissiveTexture.index));
if (texture != null)
{
material.SetTexture("_EmissionMap", texture);
}
// Texture Offset and Scale
MaterialFactory.SetTextureOffsetAndScale(material, src.emissiveTexture, "_EmissionMap");
}
}
BlendMode blendMode = BlendMode.Opaque;
// https://forum.unity.com/threads/standard-material-shader-ignoring-setfloat-property-_mode.344557/#post-2229980
switch (src.alphaMode)
{
case "BLEND":
blendMode = BlendMode.Fade;
material.SetOverrideTag("RenderType", "Transparent");
material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.SrcAlpha);
material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha);
material.SetInt("_ZWrite", 0);
material.DisableKeyword("_ALPHATEST_ON");
material.EnableKeyword("_ALPHABLEND_ON");
material.DisableKeyword("_ALPHAPREMULTIPLY_ON");
material.renderQueue = 3000;
break;
case "MASK":
blendMode = BlendMode.Cutout;
material.SetOverrideTag("RenderType", "TransparentCutout");
material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One);
material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.Zero);
material.SetInt("_ZWrite", 1);
material.SetFloat("_Cutoff", src.alphaCutoff);
material.EnableKeyword("_ALPHATEST_ON");
material.DisableKeyword("_ALPHABLEND_ON");
material.DisableKeyword("_ALPHAPREMULTIPLY_ON");
material.renderQueue = 2450;
break;
default: // OPAQUE
blendMode = BlendMode.Opaque;
material.SetOverrideTag("RenderType", "");
material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One);
material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.Zero);
material.SetInt("_ZWrite", 1);
material.DisableKeyword("_ALPHATEST_ON");
material.DisableKeyword("_ALPHABLEND_ON");
material.DisableKeyword("_ALPHAPREMULTIPLY_ON");
material.renderQueue = -1;
break;
}
material.SetFloat("_Mode", (float)blendMode);
return material;
}
}
}

View File

@@ -21,7 +21,7 @@ namespace UniGLTF
// texture
if (src.pbrMetallicRoughness.baseColorTexture != null)
{
material.mainTexture = await getTexture(awaitCaller, gltf, GetTextureParam.Create(gltf, src.pbrMetallicRoughness.baseColorTexture.index));
material.mainTexture = await getTexture(awaitCaller, gltf, GetTextureParam.CreateSRGB(gltf, src.pbrMetallicRoughness.baseColorTexture.index));
// Texture Offset and Scale
MaterialFactory.SetTextureOffsetAndScale(material, src.pbrMetallicRoughness.baseColorTexture, "_MainTex");

View File

@@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: bafc2eb5323419940a4991a8045bedc3
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,225 +0,0 @@

using System.Threading.Tasks;
using UnityEngine;
namespace UniGLTF
{
/// StandardShader variables
///
/// _Color
/// _MainTex
/// _Cutoff
/// _Glossiness
/// _Metallic
/// _MetallicGlossMap
/// _BumpScale
/// _BumpMap
/// _Parallax
/// _ParallaxMap
/// _OcclusionStrength
/// _OcclusionMap
/// _EmissionColor
/// _EmissionMap
/// _DetailMask
/// _DetailAlbedoMap
/// _DetailNormalMapScale
/// _DetailNormalMap
/// _UVSec
/// _EmissionScaleUI
/// _EmissionColorUI
/// _Mode
/// _SrcBlend
/// _DstBlend
/// _ZWrite
public static class PBRMaterialItem
{
public const string ShaderName = "Standard";
private enum BlendMode
{
Opaque,
Cutout,
Fade,
Transparent
}
public static GetTextureParam BaseColorTexture(glTF gltf, glTFMaterial src)
{
return GetTextureParam.Create(gltf, src.pbrMetallicRoughness.baseColorTexture.index);
}
public static GetTextureParam MetallicRoughnessTexture(glTF gltf, glTFMaterial src)
{
return GetTextureParam.CreateMetallic(gltf,
src.pbrMetallicRoughness.metallicRoughnessTexture.index,
src.pbrMetallicRoughness.metallicFactor);
}
public static GetTextureParam OcclusionTexture(glTF gltf, glTFMaterial src)
{
return GetTextureParam.CreateOcclusion(gltf, src.occlusionTexture.index);
}
public static GetTextureParam NormalTexture(glTF gltf, glTFMaterial src)
{
return GetTextureParam.CreateNormal(gltf, src.normalTexture.index);
}
public static async Task<Material> CreateAsync(IAwaitCaller awaitCaller, glTF gltf, int i, GetTextureAsyncFunc getTexture)
{
if (getTexture == null)
{
getTexture = (_x, _y, _z) => Task.FromResult<Texture2D>(null);
}
// PBR material
var material = default(Material);
if (i >= 0 && i < gltf.materials.Count)
{
var src = gltf.materials[i];
material = MaterialFactory.CreateMaterial(i, src, ShaderName);
if (src.pbrMetallicRoughness != null)
{
if (src.pbrMetallicRoughness.baseColorFactor != null && src.pbrMetallicRoughness.baseColorFactor.Length == 4)
{
var color = src.pbrMetallicRoughness.baseColorFactor;
material.color = (new Color(color[0], color[1], color[2], color[3])).gamma;
}
if (src.pbrMetallicRoughness.baseColorTexture != null && src.pbrMetallicRoughness.baseColorTexture.index != -1)
{
material.mainTexture = await getTexture(awaitCaller, gltf, BaseColorTexture(gltf, src));
// Texture Offset and Scale
MaterialFactory.SetTextureOffsetAndScale(material, src.pbrMetallicRoughness.baseColorTexture, "_MainTex");
}
if (src.pbrMetallicRoughness.metallicRoughnessTexture != null && src.pbrMetallicRoughness.metallicRoughnessTexture.index != -1)
{
material.EnableKeyword("_METALLICGLOSSMAP");
var texture = await getTexture(awaitCaller, gltf, MetallicRoughnessTexture(gltf, src));
if (texture != null)
{
material.SetTexture(GetTextureParam.METALLIC_GLOSS_PROP, texture);
}
material.SetFloat("_Metallic", 1.0f);
// Set 1.0f as hard-coded. See: https://github.com/dwango/UniVRM/issues/212.
material.SetFloat("_GlossMapScale", 1.0f);
// Texture Offset and Scale
MaterialFactory.SetTextureOffsetAndScale(material, src.pbrMetallicRoughness.metallicRoughnessTexture, "_MetallicGlossMap");
}
else
{
material.SetFloat("_Metallic", src.pbrMetallicRoughness.metallicFactor);
material.SetFloat("_Glossiness", 1.0f - src.pbrMetallicRoughness.roughnessFactor);
}
}
if (src.normalTexture != null && src.normalTexture.index != -1)
{
material.EnableKeyword("_NORMALMAP");
var texture = await getTexture(awaitCaller, gltf, NormalTexture(gltf, src));
if (texture != null)
{
material.SetTexture(GetTextureParam.NORMAL_PROP, texture);
material.SetFloat("_BumpScale", src.normalTexture.scale);
}
// Texture Offset and Scale
MaterialFactory.SetTextureOffsetAndScale(material, src.normalTexture, "_BumpMap");
}
if (src.occlusionTexture != null && src.occlusionTexture.index != -1)
{
var texture = await getTexture(awaitCaller, gltf, OcclusionTexture(gltf, src));
if (texture != null)
{
material.SetTexture(GetTextureParam.OCCLUSION_PROP, texture);
material.SetFloat("_OcclusionStrength", src.occlusionTexture.strength);
}
// Texture Offset and Scale
MaterialFactory.SetTextureOffsetAndScale(material, src.occlusionTexture, "_OcclusionMap");
}
if (src.emissiveFactor != null
|| (src.emissiveTexture != null && src.emissiveTexture.index != -1))
{
material.EnableKeyword("_EMISSION");
material.globalIlluminationFlags &= ~MaterialGlobalIlluminationFlags.EmissiveIsBlack;
if (src.emissiveFactor != null && src.emissiveFactor.Length == 3)
{
material.SetColor("_EmissionColor", new Color(src.emissiveFactor[0], src.emissiveFactor[1], src.emissiveFactor[2]));
}
if (src.emissiveTexture != null && src.emissiveTexture.index != -1)
{
var texture = await getTexture(awaitCaller, gltf, GetTextureParam.Create(gltf, src.emissiveTexture.index));
if (texture != null)
{
material.SetTexture("_EmissionMap", texture);
}
// Texture Offset and Scale
MaterialFactory.SetTextureOffsetAndScale(material, src.emissiveTexture, "_EmissionMap");
}
}
BlendMode blendMode = BlendMode.Opaque;
// https://forum.unity.com/threads/standard-material-shader-ignoring-setfloat-property-_mode.344557/#post-2229980
switch (src.alphaMode)
{
case "BLEND":
blendMode = BlendMode.Fade;
material.SetOverrideTag("RenderType", "Transparent");
material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.SrcAlpha);
material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha);
material.SetInt("_ZWrite", 0);
material.DisableKeyword("_ALPHATEST_ON");
material.EnableKeyword("_ALPHABLEND_ON");
material.DisableKeyword("_ALPHAPREMULTIPLY_ON");
material.renderQueue = 3000;
break;
case "MASK":
blendMode = BlendMode.Cutout;
material.SetOverrideTag("RenderType", "TransparentCutout");
material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One);
material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.Zero);
material.SetInt("_ZWrite", 1);
material.SetFloat("_Cutoff", src.alphaCutoff);
material.EnableKeyword("_ALPHATEST_ON");
material.DisableKeyword("_ALPHABLEND_ON");
material.DisableKeyword("_ALPHAPREMULTIPLY_ON");
material.renderQueue = 2450;
break;
default: // OPAQUE
blendMode = BlendMode.Opaque;
material.SetOverrideTag("RenderType", "");
material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One);
material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.Zero);
material.SetInt("_ZWrite", 1);
material.DisableKeyword("_ALPHATEST_ON");
material.DisableKeyword("_ALPHABLEND_ON");
material.DisableKeyword("_ALPHAPREMULTIPLY_ON");
material.renderQueue = -1;
break;
}
material.SetFloat("_Mode", (float)blendMode);
}
else
{
material = MaterialFactory.CreateMaterial(i, null, ShaderName);
}
return material;
}
}
}

View File

@@ -1,10 +0,0 @@
using UnityEngine;
namespace UniGLTF
{
public interface ITextureConverter
{
Texture2D GetImportTexture(Texture2D texture);
Texture2D GetExportTexture(Texture2D texture);
}
}

View File

@@ -1,67 +0,0 @@
using UnityEngine;
namespace UniGLTF
{
public class MetallicRoughnessConverter : ITextureConverter
{
private float _smoothnessOrRoughness;
public MetallicRoughnessConverter(float smoothnessOrRoughness)
{
_smoothnessOrRoughness = smoothnessOrRoughness;
}
public Texture2D GetImportTexture(Texture2D texture)
{
var converted = TextureConverter.Convert(texture, glTFTextureTypes.Metallic, Import, null);
return converted;
}
public Texture2D GetExportTexture(Texture2D texture)
{
var converted = TextureConverter.Convert(texture, glTFTextureTypes.Metallic, Export, null);
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,
};
}
}
}

View File

@@ -1,46 +0,0 @@
using UnityEngine;
namespace UniGLTF
{
public class NormalConverter : ITextureConverter
{
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);
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);
return converted;
}
}
}

View File

@@ -1,42 +0,0 @@
using UnityEngine;
namespace UniGLTF
{
public class OcclusionConverter : ITextureConverter
{
public Texture2D GetImportTexture(Texture2D texture)
{
var converted = TextureConverter.Convert(texture, glTFTextureTypes.Occlusion, Import, null);
return converted;
}
public Texture2D GetExportTexture(Texture2D texture)
{
var converted = TextureConverter.Convert(texture, glTFTextureTypes.Occlusion, Export, null);
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,
};
}
}
}

View File

@@ -1,92 +0,0 @@
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
namespace UniGLTF
{
public class TextureExportManager
{
List<Texture> m_textures;
public List<Texture> Textures
{
get { return m_textures; }
}
List<Texture> m_exportTextures;
public Texture GetExportTexture(int index)
{
if (index < 0 || index >= m_exportTextures.Count)
{
return null;
}
if (m_exportTextures[index] != null)
{
// コピー変換済み
return m_exportTextures[index];
}
// オリジナル
return m_textures[index];
}
public TextureExportManager(IEnumerable<Texture> textures)
{
if (textures == null)
{
// empty list for UnitTest
textures = new Texture[] { };
}
m_textures = textures.ToList();
m_exportTextures = new List<Texture>(Enumerable.Repeat<Texture>(null, m_textures.Count));
}
public int CopyAndGetIndex(Texture texture, RenderTextureReadWrite readWrite)
{
if (texture == null)
{
return -1;
}
var index = m_textures.IndexOf(texture);
if (index == -1)
{
// ありえない?
return -1;
}
#if UNITY_EDITOR
if (!string.IsNullOrEmpty(UnityEditor.AssetDatabase.GetAssetPath(texture)))
{
m_exportTextures[index] = texture;
return index;
}
#endif
// ToDo: may already exists
m_exportTextures[index] = TextureConverter.CopyTexture(texture, readWrite, null);
return index;
}
public int ConvertAndGetIndex(Texture texture, ITextureConverter converter)
{
if (texture == null)
{
return -1;
}
var index = m_textures.IndexOf(texture);
if (index == -1)
{
// ありえない?
return -1;
}
m_exportTextures[index] = converter.GetExportTexture(texture as Texture2D);
return index;
}
}
}

View File

@@ -1,12 +0,0 @@
fileFormatVersion: 2
guid: 435499f173753ac418331fe0f967b789
timeCreated: 1541561421
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,189 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
#if UNITY_EDITOR
using System.Reflection;
using UnityEditor;
#endif
namespace UniGLTF
{
public class TextureIO : ITextureExporter
{
public static RenderTextureReadWrite GetColorSpace(glTFTextureTypes textureType)
{
switch (textureType)
{
case glTFTextureTypes.Metallic:
case glTFTextureTypes.Normal:
case glTFTextureTypes.Occlusion:
return RenderTextureReadWrite.Linear;
case glTFTextureTypes.BaseColor:
case glTFTextureTypes.Emissive:
return RenderTextureReadWrite.sRGB;
default:
return RenderTextureReadWrite.sRGB;
}
}
public static glTFTextureTypes GetglTFTextureType(string shaderName, string propName)
{
switch (propName)
{
case "_Color":
return glTFTextureTypes.BaseColor;
case "_MetallicGlossMap":
return glTFTextureTypes.Metallic;
case "_BumpMap":
return glTFTextureTypes.Normal;
case "_OcclusionMap":
return glTFTextureTypes.Occlusion;
case "_EmissionMap":
return glTFTextureTypes.Emissive;
default:
return glTFTextureTypes.Unknown;
}
}
public static glTFTextureTypes GetglTFTextureType(glTF glTf, int textureIndex)
{
foreach (var material in glTf.materials)
{
var textureInfo = material.GetTextures().FirstOrDefault(x => (x != null) && x.index == textureIndex);
if (textureInfo != null)
{
return textureInfo.TextureType;
}
}
return glTFTextureTypes.Unknown;
}
#if UNITY_EDITOR
public static void MarkTextureAssetAsNormalMap(string assetPath)
{
if (string.IsNullOrEmpty(assetPath))
{
return;
}
var textureImporter = AssetImporter.GetAtPath(assetPath) as TextureImporter;
if (null == textureImporter)
{
return;
}
//Debug.LogFormat("[MarkTextureAssetAsNormalMap] {0}", assetPath);
textureImporter.textureType = TextureImporterType.NormalMap;
textureImporter.SaveAndReimport();
}
#endif
public virtual IEnumerable<(Texture texture, glTFTextureTypes textureType)> GetTextures(Material m)
{
var props = ShaderPropExporter.PreShaderPropExporter.GetPropsForSupportedShader(m.shader.name);
if (props == null)
{
yield return (m.mainTexture, glTFTextureTypes.BaseColor);
}
foreach (var prop in props.Properties)
{
if (prop.ShaderPropertyType == ShaderPropExporter.ShaderPropertyType.TexEnv)
{
yield return (m.GetTexture(prop.Key), GetglTFTextureType(m.shader.name, prop.Key));
}
}
}
public virtual (Byte[] bytes, string mine) GetBytesWithMime(Texture texture, glTFTextureTypes textureType)
{
#if UNITY_EDITOR
var path = UnityPath.FromAsset(texture);
if (path.IsUnderAssetsFolder)
{
var textureImporter = AssetImporter.GetAtPath(path.Value) as TextureImporter;
var getSizeMethod = typeof(TextureImporter).GetMethod("GetWidthAndHeight", BindingFlags.NonPublic | BindingFlags.Instance);
if (textureImporter != null && getSizeMethod != null)
{
var args = new object[2] { 0, 0 };
getSizeMethod.Invoke(textureImporter, args);
var originalWidth = (int)args[0];
var originalHeight = (int)args[1];
var originalSize = Mathf.Max(originalWidth, originalHeight);
var requiredMaxSize = textureImporter.maxTextureSize;
// Resized exporting if MaxSize setting value is smaller than original image size.
if (originalSize > requiredMaxSize)
{
return
(
TextureConverter.CopyTexture(texture, GetColorSpace(textureType), null).EncodeToPNG(),
"image/png"
);
}
}
if (path.Extension == ".png")
{
return
(
System.IO.File.ReadAllBytes(path.FullPath),
"image/png"
);
}
if (path.Extension == ".jpg")
{
return
(
System.IO.File.ReadAllBytes(path.FullPath),
"image/jpeg"
);
}
}
#endif
return
(
TextureConverter.CopyTexture(texture, TextureIO.GetColorSpace(textureType), null).EncodeToPNG(),
"image/png"
);
}
public int ExportTexture(glTF gltf, int bufferIndex, Texture texture, glTFTextureTypes textureType)
{
var bytesWithMime = GetBytesWithMime(texture, textureType); ;
// add view
var view = gltf.buffers[bufferIndex].Append(bytesWithMime.bytes, glBufferTarget.NONE);
var viewIndex = gltf.AddBufferView(view);
// add image
var imageIndex = gltf.images.Count;
gltf.images.Add(new glTFImage
{
name = GetTextureParam.RemoveSuffix(texture.name),
bufferView = viewIndex,
mimeType = bytesWithMime.mine,
});
// add sampler
var samplerIndex = gltf.samplers.Count;
var sampler = TextureSamplerUtil.Export(texture);
gltf.samplers.Add(sampler);
// add texture
gltf.textures.Add(new glTFTexture
{
sampler = samplerIndex,
source = imageIndex,
});
return imageIndex;
}
}
}

View File

@@ -1,12 +0,0 @@
fileFormatVersion: 2
guid: eca1330a83e17a14eb99fc6ea1697922
timeCreated: 1533533316
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: a4bd2e8f388fb204186d743f337ddb83
guid: 2b2634da9b588264c8ea8a81578080b2
folderAsset: yes
DefaultImporter:
externalObjects: {}

View File

@@ -0,0 +1,52 @@
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;
}
}
}
}

View File

@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 268e807d3ea7f0f45882d20bf318cf8b
guid: 1a3edb24329fd454db97cac12f30c0d8
MonoImporter:
externalObjects: {}
serializedVersion: 2

View File

@@ -0,0 +1,135 @@
using System;
namespace UniGLTF
{
/// <summary>
/// STANDARD(Pbr) texture = occlusion + metallic + smoothness
/// </summary>
public struct GetTextureParam
{
public const string NORMAL_PROP = "_BumpMap";
public const string NORMAL_SUFFIX = ".normal";
public const string METALLIC_GLOSS_PROP = "_MetallicGlossMap";
public const string OCCLUSION_PROP = "_OcclusionMap";
public const string STANDARD_SUFFIX = ".standard";
public enum TextureTypes
{
sRGB,
NormalMap,
// Occlusion + Metallic + Smoothness
StandardMap,
Linear,
}
public static string RemoveSuffix(string src)
{
if (src.EndsWith(NORMAL_SUFFIX))
{
return src.Substring(0, src.Length - NORMAL_SUFFIX.Length);
}
else if (src.EndsWith(STANDARD_SUFFIX))
{
return src.Substring(0, src.Length - STANDARD_SUFFIX.Length);
}
else
{
return src;
}
}
readonly string m_name;
public string GltflName => m_name;
public string ConvertedName
{
get
{
switch (TextureType)
{
case TextureTypes.StandardMap: return $"{m_name}{STANDARD_SUFFIX}";
case TextureTypes.NormalMap: return $"{m_name}{NORMAL_SUFFIX}";
default: return m_name;
}
}
}
public readonly TextureTypes TextureType;
public readonly float MetallicFactor;
public readonly float RoughnessFactor;
public readonly ushort? Index0;
public readonly ushort? Index1;
public readonly ushort? Index2;
public readonly ushort? Index3;
public readonly ushort? Index4;
public readonly ushort? Index5;
/// <summary>
/// この種類は RGB チャンネルの組み換えが必用
/// </summary>
public bool ExtractConverted => TextureType == TextureTypes.StandardMap;
public GetTextureParam(string name, TextureTypes textureType, float metallicFactor, float roughnessFactor, int? i0, int? i1, int? i2, int? i3, int? i4, int? i5)
{
if (string.IsNullOrEmpty(name))
{
throw new ArgumentNullException();
}
m_name = name;
TextureType = textureType;
MetallicFactor = metallicFactor;
RoughnessFactor = roughnessFactor;
Index0 = (ushort?)i0;
Index1 = (ushort?)i1;
Index2 = (ushort?)i2;
Index3 = (ushort?)i3;
Index4 = (ushort?)i4;
Index5 = (ushort?)i5;
}
public static GetTextureParam CreateSRGB(glTF gltf, int textureIndex)
{
var name = gltf.textures[textureIndex].name;
return new GetTextureParam(name, TextureTypes.sRGB, default, default, textureIndex, default, default, default, default, default);
}
public static GetTextureParam Create(glTF gltf, int index, string prop, float metallicFactor, float roughnessFactor)
{
switch (prop)
{
case NORMAL_PROP:
return CreateNormal(gltf, index);
case OCCLUSION_PROP:
case METALLIC_GLOSS_PROP:
return CreateStandard(gltf, index, default, metallicFactor, roughnessFactor);
default:
return CreateSRGB(gltf, index);
}
}
public static GetTextureParam CreateNormal(glTF gltf, int textureIndex)
{
var name = gltf.textures[textureIndex].name;
return new GetTextureParam(name, TextureTypes.NormalMap, default, default, textureIndex, default, default, default, default, default);
}
public static GetTextureParam CreateStandard(glTF gltf, int? metallicRoughnessTextureIndex, int? occlusionTextureIndex, float metallicFactor, float roughnessFactor)
{
string name = default;
if (metallicRoughnessTextureIndex.HasValue)
{
name = gltf.textures[metallicRoughnessTextureIndex.Value].name;
}
else if (occlusionTextureIndex.HasValue)
{
name = gltf.textures[occlusionTextureIndex.Value].name;
}
return new GetTextureParam(name, TextureTypes.StandardMap, metallicFactor, roughnessFactor, metallicRoughnessTextureIndex, occlusionTextureIndex, default, default, default, default);
}
}
}

View File

@@ -0,0 +1,94 @@
using UnityEngine;
namespace UniGLTF
{
public static class GltfTextureExporter
{
/// <summary>
/// 画像のバイト列を得る
/// </summary>
/// <param name="bytes"></param>
/// <param name="texture"></param>
/// <returns></returns>
static (byte[] bytes, string mine) GetBytesWithMime(Texture2D texture)
{
#if UNITY_EDITOR
var path = UnityPath.FromAsset(texture);
if (path.IsUnderAssetsFolder)
{
if (path.Extension == ".png")
{
return
(
System.IO.File.ReadAllBytes(path.FullPath),
"image/png"
);
}
if (path.Extension == ".jpg")
{
return
(
System.IO.File.ReadAllBytes(path.FullPath),
"image/jpeg"
);
}
}
#endif
return
(
texture.EncodeToPNG(),
"image/png"
);
}
/// <summary>
/// gltf に texture を足す
///
/// * textures
/// * samplers
/// * images
/// * bufferViews
///
/// を更新し、textures の index を返す
///
/// </summary>
/// <param name="gltf"></param>
/// <param name="bufferIndex"></param>
/// <param name="texture"></param>
/// <returns>gltf texture index</returns>
public static int PushGltfTexture(this glTF gltf, int bufferIndex, Texture2D texture)
{
var bytesWithMime = GetBytesWithMime(texture);
// add view
var view = gltf.buffers[bufferIndex].Append(bytesWithMime.bytes, glBufferTarget.NONE);
var viewIndex = gltf.AddBufferView(view);
// add image
var imageIndex = gltf.images.Count;
gltf.images.Add(new glTFImage
{
name = GetTextureParam.RemoveSuffix(texture.name),
bufferView = viewIndex,
mimeType = bytesWithMime.mine,
});
// add sampler
var samplerIndex = gltf.samplers.Count;
var sampler = TextureSamplerUtil.Export(texture);
gltf.samplers.Add(sampler);
// add texture
var textureIndex = gltf.textures.Count;
gltf.textures.Add(new glTFTexture
{
sampler = samplerIndex,
source = imageIndex,
});
return textureIndex;
}
}
}

View File

@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: ae1f69c4441f3a74292499f75467c057
guid: edc800243b783ea4392e1d916789c803
MonoImporter:
externalObjects: {}
serializedVersion: 2

View File

@@ -36,17 +36,15 @@ namespace UniGLTF
//
// texture from image(png etc) bytes
//
var textureType = TextureIO.GetglTFTextureType(gltf, textureIndex);
var colorSpace = TextureIO.GetColorSpace(textureType);
var isLinear = colorSpace == RenderTextureReadWrite.Linear;
var sampler = gltf.GetSamplerFromTextureIndex(textureIndex);
var texture = new Texture2D(2, 2, TextureFormat.ARGB32, false, isLinear);
var colorSpace = gltf.GetColorSpace(textureIndex);
var texture = new Texture2D(2, 2, TextureFormat.ARGB32, false, colorSpace == RenderTextureReadWrite.Linear);
texture.name = gltf.textures[textureIndex].name;
if (imageBytes != null)
{
texture.LoadImage(imageBytes);
}
var sampler = gltf.GetSamplerFromTextureIndex(textureIndex);
if (sampler != null)
{
TextureSamplerUtil.SetSampler(texture, sampler);

View File

@@ -0,0 +1,47 @@
using UnityEngine;
namespace UniGLTF
{
public static class NormalConverter
{
private static Material m_decoder;
private static Material Decoder
{
get
{
if (m_decoder == null)
{
m_decoder = new Material(Shader.Find("UniGLTF/NormalMapDecoder"));
}
return m_decoder;
}
}
private static Material m_encoder;
private static Material Encoder
{
get
{
if (m_encoder == null)
{
m_encoder = new Material(Shader.Find("UniGLTF/NormalMapEncoder"));
}
return m_encoder;
}
}
// GLTF data to Unity texture
// ConvertToNormalValueFromRawColorWhenCompressionIsRequired
public static Texture2D Import(Texture2D texture)
{
return TextureConverter.Convert(texture, glTFTextureTypes.Normal, null, Encoder);
}
// Unity texture to GLTF data
// ConvertToRawColorWhenNormalValueIsCompressed
public static Texture2D Export(Texture texture)
{
return TextureConverter.Convert(texture, glTFTextureTypes.Normal, null, Decoder);
}
}
}

View File

@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 5c6170d9d89ac7f43b6860805e5e6214
guid: 3640a6aad209c3f4d9178b078af8362f
MonoImporter:
externalObjects: {}
serializedVersion: 2

View File

@@ -0,0 +1,160 @@
using System;
using System.Linq;
using UnityEngine;
namespace UniGLTF
{
/// <summary>
///
/// * https://github.com/vrm-c/UniVRM/issues/781
///
/// Unity = glTF
/// Occlusion: unity.g = glTF.r
/// Roughness: unity.a = 1 - glTF.g * roughnessFactor
/// Metallic : unity.r = glTF.b * metallicFactor
///
/// glTF = Unity
/// Occlusion: glTF.r = unity.g
/// Roughness: glTF.g = 1 - unity.a * smoothness
/// Metallic : glTF.b = unity.r
///
/// </summary>
public static class OcclusionMetallicRoughnessConverter
{
public static Texture2D Import(Texture2D metallicRoughnessTexture,
float metallicFactor, float roughnessFactor, Texture2D occlusionTexture)
{
if (metallicRoughnessTexture != null && occlusionTexture != null)
{
if (metallicRoughnessTexture == occlusionTexture)
{
var copyMetallicRoughness = TextureConverter.CopyTexture(metallicRoughnessTexture, glTFTextureTypes.OcclusionMetallicRoughness, null);
var metallicRoughnessPixels = copyMetallicRoughness.GetPixels32();
for (int i = 0; i < metallicRoughnessPixels.Length; ++i)
{
metallicRoughnessPixels[i] = ImportPixel(metallicRoughnessPixels[i], metallicFactor, roughnessFactor, metallicRoughnessPixels[i]);
}
copyMetallicRoughness.SetPixels32(metallicRoughnessPixels);
copyMetallicRoughness.Apply();
copyMetallicRoughness.name = metallicRoughnessTexture.name;
return copyMetallicRoughness;
}
else
{
var copyMetallicRoughness = TextureConverter.CopyTexture(metallicRoughnessTexture, glTFTextureTypes.OcclusionMetallicRoughness, null);
var metallicRoughnessPixels = copyMetallicRoughness.GetPixels32();
var copyOcclusion = TextureConverter.CopyTexture(occlusionTexture, glTFTextureTypes.OcclusionMetallicRoughness, null);
var occlusionPixels = copyOcclusion.GetPixels32();
if (metallicRoughnessPixels.Length != occlusionPixels.Length)
{
throw new NotImplementedException();
}
for (int i = 0; i < metallicRoughnessPixels.Length; ++i)
{
metallicRoughnessPixels[i] = ImportPixel(metallicRoughnessPixels[i], metallicFactor, roughnessFactor, occlusionPixels[i]);
}
copyMetallicRoughness.SetPixels32(metallicRoughnessPixels);
copyMetallicRoughness.Apply();
copyMetallicRoughness.name = metallicRoughnessTexture.name;
return copyMetallicRoughness;
}
}
else if (metallicRoughnessTexture != null)
{
var copyTexture = TextureConverter.CopyTexture(metallicRoughnessTexture, glTFTextureTypes.OcclusionMetallicRoughness, null);
copyTexture.SetPixels32(copyTexture.GetPixels32().Select(x => ImportPixel(x, metallicFactor, roughnessFactor, default)).ToArray());
copyTexture.Apply();
copyTexture.name = metallicRoughnessTexture.name;
return copyTexture;
}
else if (occlusionTexture != null)
{
throw new NotImplementedException("occlusion only");
}
else
{
throw new ArgumentNullException("no texture");
}
}
public static Color32 ImportPixel(Color32 metallicRoughness, float metallicFactor, float roughnessFactor, Color32 occlusion)
{
var dst = new Color32
{
r = (byte)(metallicRoughness.b * metallicFactor), // Metallic
g = occlusion.r, // Occlusion
b = 0, // not used
a = (byte)(255 - metallicRoughness.g * roughnessFactor), // Roughness to Smoothness
};
return dst;
}
public static Texture2D Export(Texture metallicSmoothTexture, float smoothness, Texture occlusionTexture)
{
if (metallicSmoothTexture != null && occlusionTexture != null)
{
if (metallicSmoothTexture == occlusionTexture)
{
var copyTexture = TextureConverter.CopyTexture(metallicSmoothTexture, glTFTextureTypes.OcclusionMetallicRoughness, null);
copyTexture.SetPixels32(copyTexture.GetPixels32().Select(x => ExportPixel(x, smoothness, x)).ToArray());
copyTexture.Apply();
copyTexture.name = metallicSmoothTexture.name;
return copyTexture;
}
else
{
var copyMetallicSmooth = TextureConverter.CopyTexture(metallicSmoothTexture, glTFTextureTypes.OcclusionMetallicRoughness, null);
var metallicSmoothPixels = copyMetallicSmooth.GetPixels32();
var copyOcclusion = TextureConverter.CopyTexture(occlusionTexture, glTFTextureTypes.OcclusionMetallicRoughness, null);
var occlusionPixels = copyOcclusion.GetPixels32();
if (metallicSmoothPixels.Length != occlusionPixels.Length)
{
throw new NotImplementedException();
}
for (int i = 0; i < metallicSmoothPixels.Length; ++i)
{
metallicSmoothPixels[i] = ExportPixel(metallicSmoothPixels[i], smoothness, occlusionPixels[i]);
}
copyMetallicSmooth.SetPixels32(metallicSmoothPixels);
copyMetallicSmooth.Apply();
copyMetallicSmooth.name = metallicSmoothTexture.name;
return copyMetallicSmooth;
}
}
else if (metallicSmoothTexture)
{
var copyTexture = TextureConverter.CopyTexture(metallicSmoothTexture, glTFTextureTypes.OcclusionMetallicRoughness, null);
copyTexture.SetPixels32(copyTexture.GetPixels32().Select(x => ExportPixel(x, smoothness, default)).ToArray());
copyTexture.Apply();
copyTexture.name = metallicSmoothTexture.name;
return copyTexture;
}
else if (occlusionTexture)
{
var copyTexture = TextureConverter.CopyTexture(occlusionTexture, glTFTextureTypes.OcclusionMetallicRoughness, null);
copyTexture.SetPixels32(copyTexture.GetPixels32().Select(x => ExportPixel(default, smoothness, x)).ToArray());
copyTexture.Apply();
copyTexture.name = occlusionTexture.name;
return copyTexture;
}
else
{
throw new ArgumentNullException();
}
}
public static Color32 ExportPixel(Color32 metallicSmooth, float smoothness, Color32 occlusion)
{
var dst = new Color32
{
r = occlusion.g, // Occlusion
g = (byte)(255 - metallicSmooth.a * smoothness), // Roughness from Smoothness
b = metallicSmooth.r, // Metallic
a = 255, // not used
};
return dst;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 9de35f7c2673d5d48b84d494e71f25ff
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -14,9 +14,9 @@ namespace UniGLTF
{
public delegate Color32 ColorConversion(Color32 color);
public static Texture2D Convert(Texture2D texture, glTFTextureTypes textureType, ColorConversion colorConversion, Material convertMaterial)
public static Texture2D Convert(Texture texture, glTFTextureTypes textureType, ColorConversion colorConversion, Material convertMaterial)
{
var copyTexture = CopyTexture(texture, TextureIO.GetColorSpace(textureType), convertMaterial);
var copyTexture = CopyTexture(texture, textureType, convertMaterial);
if (colorConversion != null)
{
copyTexture.SetPixels32(copyTexture.GetPixels32().Select(x => colorConversion(x)).ToArray());
@@ -126,10 +126,10 @@ namespace UniGLTF
}
#endif
public static Texture2D CopyTexture(Texture src, RenderTextureReadWrite colorSpace, Material material)
public static Texture2D CopyTexture(Texture src, glTFTextureTypes textureType, Material material)
{
Texture2D dst = null;
RenderTextureReadWrite colorSpace = textureType.GetColorSpace();
var renderTexture = new RenderTexture(src.width, src.height, 0, RenderTextureFormat.ARGB32, colorSpace);
using (var scope = new ColorSpaceScope(colorSpace))

View File

@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 0342907cb8901f44b8792016ac152fcd
guid: 843bfd183520d064ea63b4716d26b7cc
MonoImporter:
externalObjects: {}
serializedVersion: 2

View File

@@ -0,0 +1,224 @@
using System;
using System.Collections.Generic;
using UnityEngine;
using System.Reflection;
#if UNITY_EDITOR
using UnityEditor;
#endif
namespace UniGLTF
{
/// <summary>
/// glTF にエクスポートする Texture2D を蓄えて index を確定させる
/// </summary>
public class TextureExporter
{
struct ExportKey
{
public readonly Texture Src;
public readonly glTFTextureTypes TextureType;
public ExportKey(Texture src, glTFTextureTypes type)
{
if (src == null)
{
throw new ArgumentNullException();
}
Src = src;
TextureType = type;
}
}
Dictionary<ExportKey, int> m_exportMap = new Dictionary<ExportKey, int>();
/// <summary>
/// Export する Texture2D のリスト。これが gltf.textures になる
/// </summary>
/// <typeparam name="Texture2D"></typeparam>
/// <returns></returns>
public readonly List<Texture2D> Exported = new List<Texture2D>();
/// <summary>
/// Texture の export index を得る
/// </summary>
/// <param name="src"></param>
/// <param name="textureType"></param>
/// <returns></returns>
public int GetTextureIndex(Texture src, glTFTextureTypes textureType)
{
if (src == null)
{
return -1;
}
return m_exportMap[new ExportKey(src, textureType)];
}
/// <summary>
/// TextureImporter.maxTextureSize が元のテクスチャーより小さいか否かの判定
/// </summary>
/// <param name="src"></param>
/// <returns></returns>
static bool CopyIfMaxTextureSizeIsSmaller(Texture src)
{
#if UNITY_EDITOR
var textureImporter = AssetImporter.GetAtPath(UnityPath.FromAsset(src).Value) as TextureImporter;
var getSizeMethod = typeof(TextureImporter).GetMethod("GetWidthAndHeight", BindingFlags.NonPublic | BindingFlags.Instance);
if (textureImporter != null && getSizeMethod != null)
{
var args = new object[2] { 0, 0 };
getSizeMethod.Invoke(textureImporter, args);
var originalWidth = (int)args[0];
var originalHeight = (int)args[1];
var originalSize = Mathf.Max(originalWidth, originalHeight);
if (textureImporter.maxTextureSize < originalSize)
{
return true;
}
}
#endif
return false;
}
/// <summary>
/// 元の Asset が存在して、 TextureImporter に設定された画像サイズが小さくない
/// </summary>
/// <param name="src"></param>
/// <param name="texture2D"></param>
/// <returns></returns>
static bool UseAsset(Texture2D texture2D)
{
#if UNITY_EDITOR
if (texture2D != null && !string.IsNullOrEmpty(UnityEditor.AssetDatabase.GetAssetPath(texture2D)))
{
if (CopyIfMaxTextureSizeIsSmaller(texture2D))
{
return false;
}
return true;
}
#endif
return false;
}
/// <summary>
/// sRGBなテクスチャーを処理し、index を確定させる
/// </summary>
/// <param name="src"></param>
/// <returns></returns>
public int ExportSRGB(Texture src)
{
if (src == null)
{
return -1;
}
// cache
if (m_exportMap.TryGetValue(new ExportKey(src, glTFTextureTypes.SRGB), out var index))
{
return index;
}
// get Texture2D
index = Exported.Count;
var texture2D = src as Texture2D;
if (UseAsset(texture2D))
{
// do nothing
}
else
{
texture2D = TextureConverter.CopyTexture(src, glTFTextureTypes.SRGB, null);
}
Exported.Add(texture2D);
m_exportMap.Add(new ExportKey(src, glTFTextureTypes.SRGB), index);
return index;
}
/// <summary>
/// Linearなテクスチャーを処理し、index を確定させる
/// </summary>
/// <param name="src"></param>
/// <returns></returns>
public int ExportLinear(Texture src)
{
throw new NotImplementedException();
}
/// <summary>
/// Standard の Metallic, Smoothness, Occlusion をまとめ、index を確定させる
/// </summary>
/// <param name="metallicSmoothTexture"></param>
/// <param name="smoothness"></param>
/// <param name="occlusionTexture"></param>
/// <returns></returns>
public int ExportMetallicSmoothnessOcclusion(Texture metallicSmoothTexture, float smoothness, Texture occlusionTexture)
{
if (metallicSmoothTexture == null && occlusionTexture == null)
{
return -1;
}
// cache
if (m_exportMap.TryGetValue(new ExportKey(metallicSmoothTexture, glTFTextureTypes.OcclusionMetallicRoughness), out var index))
{
return index;
}
if (m_exportMap.TryGetValue(new ExportKey(occlusionTexture, glTFTextureTypes.OcclusionMetallicRoughness), out index))
{
return index;
}
//
// Unity と glTF で互換性が無いので必ず変換が必用
//
index = Exported.Count;
var texture2D = OcclusionMetallicRoughnessConverter.Export(metallicSmoothTexture, smoothness, occlusionTexture);
Exported.Add(texture2D);
m_exportMap.Add(new ExportKey(metallicSmoothTexture, glTFTextureTypes.OcclusionMetallicRoughness), index);
if (occlusionTexture != metallicSmoothTexture && occlusionTexture != null)
{
m_exportMap.Add(new ExportKey(occlusionTexture, glTFTextureTypes.OcclusionMetallicRoughness), index);
}
return index;
}
/// <summary>
/// Normal のテクスチャを変換し index を確定させる
/// </summary>
/// <param name="normalTexture"></param>
/// <returns></returns>
public int ExportNormal(Texture src)
{
if (src == null)
{
return -1;
}
// cache
if (m_exportMap.TryGetValue(new ExportKey(src, glTFTextureTypes.Normal), out var index))
{
return index;
}
// get Texture2D
index = Exported.Count;
var texture2D = src as Texture2D;
if (UseAsset(texture2D))
{
// EditorAsset を使うので変換不要
}
else
{
// 後で Bitmap を使うために変換する
texture2D = NormalConverter.Export(src);
}
Exported.Add(texture2D);
m_exportMap.Add(new ExportKey(src, glTFTextureTypes.Normal), index);
return index;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 65fdfff6cc4b1e14a882259e903fc830
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -46,24 +46,26 @@ namespace UniGLTF
public delegate Task<Texture2D> GetTextureAsyncFunc(IAwaitCaller awaitCaller, glTF gltf, GetTextureParam param);
public class TextureFactory : IDisposable
{
Dictionary<string, Texture2D> m_externalMap;
public readonly Dictionary<string, Texture2D> ExternalMap;
public bool TryGetExternal(GetTextureParam param, bool used, out Texture2D external)
{
if (param.Index0.HasValue && m_externalMap != null)
if (param.Index0.HasValue && ExternalMap != null)
{
var cacheName = param.ConvertedName;
if (param.TextureType == GetTextureParam.NORMAL_PROP)
if (param.TextureType == GetTextureParam.TextureTypes.NormalMap)
{
cacheName = param.GltflName;
}
if (m_externalMap.TryGetValue(cacheName, out external))
{
if (!m_textureCache.ContainsKey(cacheName))
if (m_textureCache.TryGetValue(cacheName, out TextureLoadInfo normalInfo))
{
m_textureCache.Add(cacheName, new TextureLoadInfo(external, used, true));
external = normalInfo.Texture;
return true;
}
return external;
}
if (ExternalMap.TryGetValue(cacheName, out external))
{
m_textureCache.Add(cacheName, new TextureLoadInfo(external, used, true));
return true;
}
}
external = default;
@@ -78,7 +80,7 @@ namespace UniGLTF
LoadTextureAsync = loadTextureAsync;
if (externalMap != null)
{
m_externalMap = externalMap
ExternalMap = externalMap
.Select(kv => (kv.Item1, kv.Item2 as Texture2D))
.Where(kv => kv.Item2 != null)
.ToDictionary(kv => kv.Item1, kv => kv.Item2);
@@ -164,31 +166,25 @@ namespace UniGLTF
switch (param.TextureType)
{
case GetTextureParam.NORMAL_PROP:
case GetTextureParam.TextureTypes.NormalMap:
{
var baseTexture = await GetOrCreateBaseTexture(awaitCaller, gltf, param.Index0.Value, false);
var converted = new NormalConverter().GetImportTexture(baseTexture.Texture);
var converted = NormalConverter.Import(baseTexture.Texture);
converted.name = param.ConvertedName;
var info = new TextureLoadInfo(converted, true, false);
m_textureCache.Add(converted.name, info);
return info.Texture;
}
case GetTextureParam.METALLIC_GLOSS_PROP:
{
// Bake roughnessFactor values into a texture.
var baseTexture = await GetOrCreateBaseTexture(awaitCaller, gltf, param.Index0.Value, false);
var converted = new MetallicRoughnessConverter(param.MetallicFactor).GetImportTexture(baseTexture.Texture);
converted.name = param.ConvertedName;
var info = new TextureLoadInfo(converted, true, false);
m_textureCache.Add(converted.name, info);
return info.Texture;
}
case GetTextureParam.OCCLUSION_PROP:
case GetTextureParam.TextureTypes.StandardMap:
{
var baseTexture = await GetOrCreateBaseTexture(awaitCaller, gltf, param.Index0.Value, false);
var converted = new OcclusionConverter().GetImportTexture(baseTexture.Texture);
TextureLoadInfo occlusionBaseTexture = default;
if (param.Index1.HasValue)
{
occlusionBaseTexture = await GetOrCreateBaseTexture(awaitCaller, gltf, param.Index1.Value, false);
}
var converted = OcclusionMetallicRoughnessConverter.Import(baseTexture.Texture, param.MetallicFactor, param.RoughnessFactor, occlusionBaseTexture.Texture);
converted.name = param.ConvertedName;
var info = new TextureLoadInfo(converted, true, false);
m_textureCache.Add(converted.name, info);

View File

@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: f3929edbda61f9346906bfab93411b98
guid: 62f23c5ca623a9f4083c25a63b2c82af
MonoImporter:
externalObjects: {}
serializedVersion: 2

View File

@@ -1,126 +0,0 @@
using System;
namespace UniGLTF
{
public struct GetTextureParam
{
public const string NORMAL_PROP = "_BumpMap";
public const string NORMAL_SUFFIX = ".normal";
public const string METALLIC_GLOSS_PROP = "_MetallicGlossMap";
public const string METALLIC_GLOSS_SUFFIX = ".metallicRoughness";
public const string OCCLUSION_PROP = "_OcclusionMap";
public const string OCCLUSION_SUFFIX = ".occlusion";
public static string RemoveSuffix(string src)
{
if (src.EndsWith(NORMAL_SUFFIX))
{
return src.Substring(0, src.Length - NORMAL_SUFFIX.Length);
}
else if (src.EndsWith(METALLIC_GLOSS_SUFFIX))
{
return src.Substring(0, src.Length - METALLIC_GLOSS_SUFFIX.Length);
}
else if (src.EndsWith(OCCLUSION_SUFFIX))
{
return src.Substring(0, src.Length - OCCLUSION_SUFFIX.Length);
}
else
{
return src;
}
}
readonly string m_name;
public string GltflName => m_name;
public string ConvertedName
{
get
{
switch (TextureType)
{
case METALLIC_GLOSS_PROP: return $"{m_name}{METALLIC_GLOSS_SUFFIX}";
case OCCLUSION_PROP: return $"{m_name}{OCCLUSION_SUFFIX}";
case NORMAL_PROP: return $"{m_name}{NORMAL_SUFFIX}";
default: return m_name;
}
}
}
public readonly string TextureType;
public readonly float MetallicFactor;
public readonly ushort? Index0;
public readonly ushort? Index1;
public readonly ushort? Index2;
public readonly ushort? Index3;
public readonly ushort? Index4;
public readonly ushort? Index5;
/// <summary>
/// この種類は変換済みをExtract
/// </summary>
public bool ExtractConverted => TextureType == OCCLUSION_PROP || TextureType == METALLIC_GLOSS_PROP;
public GetTextureParam(string name, string textureType, float metallicFactor, int i0, int i1, int i2, int i3, int i4, int i5)
{
if (string.IsNullOrEmpty(name))
{
throw new ArgumentNullException();
}
m_name = name;
TextureType = textureType;
MetallicFactor = metallicFactor;
Index0 = (ushort)i0;
Index1 = (ushort)i1;
Index2 = (ushort)i2;
Index3 = (ushort)i3;
Index4 = (ushort)i4;
Index5 = (ushort)i5;
}
public static GetTextureParam Create(glTF gltf, int textureIndex)
{
var name = gltf.textures[textureIndex].name;
return new GetTextureParam(name, default, default, textureIndex, default, default, default, default, default);
}
public static GetTextureParam Create(glTF gltf, int index, string prop)
{
switch (prop)
{
case NORMAL_PROP:
return CreateNormal(gltf, index);
case OCCLUSION_PROP:
return CreateOcclusion(gltf, index);
case METALLIC_GLOSS_PROP:
return CreateMetallic(gltf, index, 1);
default:
return Create(gltf, index);
}
}
public static GetTextureParam CreateNormal(glTF gltf, int textureIndex)
{
var name = gltf.textures[textureIndex].name;
return new GetTextureParam(name, NORMAL_PROP, default, textureIndex, default, default, default, default, default);
}
public static GetTextureParam CreateMetallic(glTF gltf, int textureIndex, float metallicFactor)
{
var name = gltf.textures[textureIndex].name;
return new GetTextureParam(name, METALLIC_GLOSS_PROP, metallicFactor, textureIndex, default, default, default, default, default);
}
public static GetTextureParam CreateOcclusion(glTF gltf, int textureIndex)
{
var name = gltf.textures[textureIndex].name;
return new GetTextureParam(name, OCCLUSION_PROP, default, textureIndex, default, default, default, default, default);
}
}
}

View File

@@ -47,35 +47,13 @@ namespace UniGLTF
private set;
}
public TextureExportManager TextureManager;
public TextureExporter TextureManager;
protected virtual IMaterialExporter CreateMaterialExporter()
{
return new MaterialExporter();
}
private ITextureExporter _textureExporter;
public ITextureExporter TextureExporter
{
get
{
if (_textureExporter != null)
{
return _textureExporter;
}
else
{
_textureExporter = new TextureIO();
return _textureExporter;
}
}
set
{
_textureExporter = value;
}
}
/// <summary>
/// このエクスポーターがサポートするExtension
/// </summary>
@@ -201,22 +179,21 @@ namespace UniGLTF
#region Materials and Textures
Materials = Nodes.SelectMany(x => x.GetSharedMaterials()).Where(x => x != null).Distinct().ToList();
var unityTextures = Materials.SelectMany(x => TextureExporter.GetTextures(x)).Where(x => x.texture != null).Distinct().ToList();
TextureManager = new TextureExportManager(unityTextures.Select(x => x.texture));
TextureManager = new TextureExporter();
var materialExporter = CreateMaterialExporter();
glTF.materials = Materials.Select(x => materialExporter.ExportMaterial(x, TextureManager)).ToList();
for (int i = 0; i < unityTextures.Count; ++i)
for (int i = 0; i < TextureManager.Exported.Count; ++i)
{
var unityTexture = unityTextures[i];
TextureExporter.ExportTexture(glTF, bufferIndex, TextureManager.GetExportTexture(i), unityTexture.textureType);
var unityTexture = TextureManager.Exported[i];
glTF.PushGltfTexture(bufferIndex, unityTexture);
}
#endregion
#region Meshes
var unityMeshes = MeshWithRenderer.FromNodes(Nodes).Where(x=> x.Mesh.vertices.Any()).ToList();
var unityMeshes = MeshWithRenderer.FromNodes(Nodes).Where(x => x.Mesh.vertices.Any()).ToList();
MeshBlendShapeIndexMap = new Dictionary<Mesh, Dictionary<int, int>>();
foreach (var (mesh, gltfMesh, blendShapeIndexMap) in MeshExporter.ExportMeshes(

View File

@@ -19,7 +19,7 @@ namespace UniGLTF
filterMode = FilterMode.Bilinear,
};
var textureManager = new TextureExportManager(new Texture[] { tex0 });
var textureManager = new TextureExporter();
var srcMaterial = new Material(Shader.Find("Standard"));
var offset = new Vector2(0.3f, 0.2f);
@@ -255,7 +255,7 @@ namespace UniGLTF
material.SetColor("_EmissionColor", new Color(0, 1, 2, 1));
material.EnableKeyword("_EMISSION");
var materialExporter = new MaterialExporter();
var textureExportManager = new TextureExportManager(new Texture[] { });
var textureExportManager = new TextureExporter();
var gltfMaterial = materialExporter.ExportMaterial(material, textureExportManager);
Assert.AreEqual(gltfMaterial.emissiveFactor, new float[] { 0, 0.5f, 1 });

View File

@@ -14,7 +14,7 @@ namespace UniGLTF
wrapMode = TextureWrapMode.Clamp,
filterMode = FilterMode.Trilinear,
};
var textureManager = new TextureExportManager(new Texture[] {tex0});
var textureManager = new TextureExporter();
var material = new Material(Shader.Find("Standard"));
material.mainTexture = tex0;
@@ -22,7 +22,7 @@ namespace UniGLTF
var materialExporter = new MaterialExporter();
materialExporter.ExportMaterial(material, textureManager);
var convTex0 = textureManager.GetExportTexture(0);
var convTex0 = textureManager.Exported[0];
var sampler = TextureSamplerUtil.Export(convTex0);
Assert.AreEqual(glWrap.CLAMP_TO_EDGE, sampler.wrapS);
@@ -39,9 +39,8 @@ namespace UniGLTF
{
{
var smoothness = 1.0f;
var conv = new MetallicRoughnessConverter(smoothness);
Assert.That(
conv.Export(new Color32(255, 255, 255, 255)),
OcclusionMetallicRoughnessConverter.ExportPixel(new Color32(255, 255, 255, 255), smoothness, default),
// r <- 0 : (Unused)
// g <- 0 : ((1 - src.a(as float) * smoothness) ^ 2)(as uint8)
// b <- 255 : Same metallic (src.r)
@@ -51,21 +50,19 @@ namespace UniGLTF
{
var smoothness = 0.5f;
var conv = new MetallicRoughnessConverter(smoothness);
Assert.That(
conv.Export(new Color32(255, 255, 255, 255)),
OcclusionMetallicRoughnessConverter.ExportPixel(new Color32(255, 255, 255, 255), smoothness, default),
// r <- 0 : (Unused)
// g <- 63 : ((1 - src.a(as float) * smoothness) ^ 2)(as uint8)
// b <- 255 : Same metallic (src.r)
// a <- 255 : (Unused)
Is.EqualTo(new Color32(0, 63, 255, 255)));
Is.EqualTo(new Color32(0, 127, 255, 255)));
}
{
var smoothness = 0.0f;
var conv = new MetallicRoughnessConverter(smoothness);
Assert.That(
conv.Export(new Color32(255, 255, 255, 255)),
OcclusionMetallicRoughnessConverter.ExportPixel(new Color32(255, 255, 255, 255), smoothness, default),
// r <- 0 : (Unused)
// g <- 255 : ((1 - src.a(as float) * smoothness) ^ 2)(as uint8)
// b <- 255 : Same metallic (src.r)
@@ -79,9 +76,8 @@ namespace UniGLTF
{
{
var roughnessFactor = 1.0f;
var conv = new MetallicRoughnessConverter(roughnessFactor);
Assert.That(
conv.Import(new Color32(255, 255, 255, 255)),
OcclusionMetallicRoughnessConverter.ImportPixel(new Color32(255, 255, 255, 255), 1.0f, roughnessFactor, default),
// r <- 255 : Same metallic (src.r)
// g <- 0 : (Unused)
// b <- 0 : (Unused)
@@ -91,33 +87,30 @@ namespace UniGLTF
{
var roughnessFactor = 1.0f;
var conv = new MetallicRoughnessConverter(roughnessFactor);
Assert.That(
conv.Import(new Color32(255, 63, 255, 255)),
OcclusionMetallicRoughnessConverter.ImportPixel(new Color32(255, 128, 255, 255), 1.0f, roughnessFactor, default),
// r <- 255 : Same metallic (src.r)
// g <- 0 : (Unused)
// b <- 0 : (Unused)
// a <- 128 : ((1 - sqrt(src.g(as float) * roughnessFactor)))(as uint8)
Is.EqualTo(new Color32(255, 0, 0, 128))); // smoothness 0.5 * src.a 1.0
Is.EqualTo(new Color32(255, 0, 0, 127))); // 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)),
OcclusionMetallicRoughnessConverter.ImportPixel(new Color32(255, 255, 255, 255), 1.0f, roughnessFactor, default),
// r <- 255 : Same metallic (src.r)
// g <- 0 : (Unused)
// b <- 0 : (Unused)
// a <- 74 : ((1 - sqrt(src.g(as float) * roughnessFactor)))(as uint8)
Is.EqualTo(new Color32(255, 0, 0, 74)));
Is.EqualTo(new Color32(255, 0, 0, 127)));
}
{
var roughnessFactor = 0.0f;
var conv = new MetallicRoughnessConverter(roughnessFactor);
Assert.That(
conv.Import(new Color32(255, 255, 255, 255)),
OcclusionMetallicRoughnessConverter.ImportPixel(new Color32(255, 255, 255, 255), 1.0f, roughnessFactor, default),
// r <- 255 : Same metallic (src.r)
// g <- 0 : (Unused)
// b <- 0 : (Unused)

View File

@@ -10,7 +10,7 @@ namespace VRM.Samples
{
var material = Resources.Load<Material>(resourceName);
var exporter = new VRMMaterialExporter();
var textureManager = new UniGLTF.TextureExportManager(null);
var textureManager = new UniGLTF.TextureExporter();
var exported = exporter.ExportMaterial(material, textureManager);
// parse glTFExtensionExport to glTFExtensionImport

View File

@@ -4,6 +4,7 @@ using UnityEngine;
using UniGLTF;
using System;
using System.Collections.Generic;
using System.Linq;
namespace VRM
{
@@ -58,14 +59,24 @@ namespace VRM
var parser = new GltfParser();
parser.ParseGlb(File.ReadAllBytes(path));
Action<IEnumerable<string>> onCompleted = _ =>
Action<IEnumerable<string>> onCompleted = texturePaths =>
{
//
// after textures imported
//
var map = texturePaths.Select(x =>
{
var texture = AssetDatabase.LoadAssetAtPath(x, typeof(Texture2D));
return (texture.name, texture);
}).ToArray();
using (var context = new VRMImporterContext(parser))
{
var editor = new VRMEditorImporterContext(context, prefabPath);
foreach (var textureInfo in new VRMTextureEnumerator(context.VRM).Enumerate(parser.GLTF))
{
TextureImporterConfigurator.Configure(textureInfo, map.ToDictionary(x => x.name, x => x.texture as Texture2D));
}
context.Load();
editor.SaveAsAsset();
}

View File

@@ -25,7 +25,14 @@ namespace VRM
var ext = Path.GetExtension(path).ToLower();
if (ext == ".vrm")
{
ImportVrm(UnityPath.FromUnityPath(path));
try
{
ImportVrm(UnityPath.FromUnityPath(path));
}
catch (VRMImporterContext.NotVrm0Exception)
{
// is not vrm0
}
}
}
}
@@ -49,9 +56,14 @@ namespace VRM
var texture = AssetDatabase.LoadAssetAtPath(x, typeof(Texture2D));
return (texture.name, texture);
}).ToArray();
using (var context = new VRMImporterContext(parser, null, map))
{
var editor = new VRMEditorImporterContext(context, prefabPath);
foreach (var textureInfo in new VRMTextureEnumerator(context.VRM).Enumerate(parser.GLTF))
{
TextureImporterConfigurator.Configure(textureInfo, map.ToDictionary(x => x.name, x => x.texture as Texture2D));
}
context.Load();
editor.SaveAsAsset();
}

View File

@@ -1,5 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using UniGLTF;
using UniJSON;
@@ -113,7 +112,7 @@ namespace VRM
VRM.meta.title = meta.Title;
if (meta.Thumbnail != null)
{
VRM.meta.texture = TextureExporter.ExportTexture(glTF, glTF.buffers.Count - 1, meta.Thumbnail, glTFTextureTypes.Unknown);
VRM.meta.texture = glTF.PushGltfTexture(glTF.buffers.Count - 1, meta.Thumbnail);
}
VRM.meta.licenseType = meta.LicenseType;
@@ -138,7 +137,7 @@ namespace VRM
VRM.meta.title = meta.Title;
if (meta.Thumbnail != null)
{
VRM.meta.texture = TextureExporter.ExportTexture(glTF, glTF.buffers.Count - 1, meta.Thumbnail, glTFTextureTypes.Unknown);
VRM.meta.texture = TextureManager.ExportSRGB(meta.Thumbnail);
}
// ussage permission
@@ -201,7 +200,7 @@ namespace VRM
// materials
foreach (var m in Materials)
{
VRM.materialProperties.Add(VRMMaterialExporter.CreateFromMaterial(m, TextureManager.Textures));
VRM.materialProperties.Add(VRMMaterialExporter.CreateFromMaterial(m, TextureManager));
}
// Serialize VRM

View File

@@ -10,6 +10,12 @@ namespace VRM
{
public class VRMImporterContext : ImporterContext
{
public class NotVrm0Exception : Exception
{
public NotVrm0Exception()
{ }
}
public VRM.glTF_VRM_extensions VRM { get; private set; }
public VRMImporterContext(GltfParser parser,
@@ -25,7 +31,7 @@ namespace VRM
}
else
{
throw new KeyNotFoundException("not vrm0");
throw new NotVrm0Exception();
}
}
@@ -292,7 +298,7 @@ namespace VRM
meta.Title = gltfMeta.title;
if (gltfMeta.texture >= 0)
{
meta.Thumbnail = await TextureFactory.GetTextureAsync(awaitCaller, GLTF, GetTextureParam.Create(GLTF, gltfMeta.texture));
meta.Thumbnail = await TextureFactory.GetTextureAsync(awaitCaller, GLTF, GetTextureParam.CreateSRGB(GLTF, gltfMeta.texture));
}
meta.AllowedUser = gltfMeta.allowedUser;
meta.ViolentUssage = gltfMeta.violentUssage;

View File

@@ -107,7 +107,7 @@ namespace VRM
// "Queue",
};
public static glTF_VRM_Material CreateFromMaterial(Material m, List<Texture> textures)
public static glTF_VRM_Material CreateFromMaterial(Material m, TextureExporter textureExporter)
{
var material = new glTF_VRM_Material
{
@@ -160,7 +160,10 @@ namespace VRM
var texture = m.GetTexture(kv.Key);
if (texture != null)
{
var value = textures.IndexOf(texture);
var value = kv.Key == "_BumpMap"
? textureExporter.ExportNormal(texture)
: textureExporter.ExportSRGB(texture)
;
if (value == -1)
{
Debug.LogFormat("not found {0}", texture.name);

View File

@@ -73,7 +73,7 @@ namespace VRM
}
foreach (var kv in item.textureProperties)
{
var param = GetTextureParam.Create(gltf, kv.Value, kv.Key);
var param = GetTextureParam.Create(gltf, kv.Value, kv.Key, 1, 1);
var texture = await getTexture(awaitCaller, gltf, param);
if (texture != null)
{

View File

@@ -22,7 +22,7 @@ namespace VRM
foreach (var kv in vrmMaterial.textureProperties)
{
// SRGB color or normalmap
yield return GetTextureParam.Create(gltf, kv.Value, kv.Key);
yield return GetTextureParam.Create(gltf, kv.Value, kv.Key, default, default);
}
}
else
@@ -38,7 +38,7 @@ namespace VRM
// thumbnail
if (m_vrm.meta != null && m_vrm.meta.texture != -1)
{
yield return GetTextureParam.Create(gltf, m_vrm.meta.texture);
yield return GetTextureParam.CreateSRGB(gltf, m_vrm.meta.texture);
}
}
}