Merge branch 'master' into fix/samples_urp_scene

This commit is contained in:
ousttrue 2024-09-03 15:20:09 +09:00 committed by GitHub
commit 8ffbd7751a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
152 changed files with 2678 additions and 1350 deletions

View File

@ -19,35 +19,7 @@ namespace UniGLTF
public ScriptedImporterAxes m_reverseAxis = default;
[SerializeField]
[Header("Experimental")]
public RenderPipelineTypes m_renderPipeline;
void OnValidate()
{
if (m_renderPipeline == UniGLTF.RenderPipelineTypes.UniversalRenderPipeline)
{
if (Shader.Find(UniGLTF.UrpGltfPbrMaterialImporter.ShaderName) == null)
{
Debug.LogWarning("URP is not installed. Force to BuiltinRenderPipeline");
m_renderPipeline = UniGLTF.RenderPipelineTypes.BuiltinRenderPipeline;
}
}
}
static IMaterialDescriptorGenerator GetMaterialGenerator(RenderPipelineTypes renderPipeline)
{
switch (renderPipeline)
{
case RenderPipelineTypes.BuiltinRenderPipeline:
return new BuiltInGltfMaterialDescriptorGenerator();
case RenderPipelineTypes.UniversalRenderPipeline:
return new UrpGltfMaterialDescriptorGenerator();
default:
throw new System.NotImplementedException();
}
}
public ImporterRenderPipelineTypes m_renderPipeline;
/// <summary>
/// glb をパースして、UnityObject化、さらにAsset化する
@ -55,7 +27,8 @@ namespace UniGLTF
/// <param name="scriptedImporter"></param>
/// <param name="context"></param>
/// <param name="reverseAxis"></param>
protected static void Import(ScriptedImporter scriptedImporter, AssetImportContext context, Axes reverseAxis, RenderPipelineTypes renderPipeline)
/// <param name="renderPipeline"></param>
protected static void Import(ScriptedImporter scriptedImporter, AssetImportContext context, Axes reverseAxis, ImporterRenderPipelineTypes renderPipeline)
{
UniGLTFLogger.Log("OnImportAsset to " + scriptedImporter.assetPath);
@ -68,10 +41,11 @@ namespace UniGLTF
.Where(x => x.Value != null)
.ToDictionary(kv => new SubAssetKey(kv.Value.GetType(), kv.Key.name), kv => kv.Value);
IMaterialDescriptorGenerator materialGenerator = GetMaterialGenerator(renderPipeline);
var materialGenerator = GetMaterialDescriptorGenerator(renderPipeline);
var importerContextSettings = new ImporterContextSettings(loadAnimation: true, invertAxis: reverseAxis);
using (var data = new AutoGltfFileParser(scriptedImporter.assetPath).Parse())
using (var loader = new ImporterContext(data, extractedObjects, materialGenerator: materialGenerator))
using (var loader = new ImporterContext(data, extractedObjects, materialGenerator: materialGenerator, settings: importerContextSettings))
{
// Configure TextureImporter to Extracted Textures.
foreach (var textureInfo in loader.TextureDescriptorGenerator.Get().GetEnumerable())
@ -79,7 +53,6 @@ namespace UniGLTF
TextureImporterConfigurator.Configure(textureInfo, loader.TextureFactory.ExternalTextures);
}
loader.InvertAxis = reverseAxis;
var loaded = loader.Load();
loaded.ShowMeshes();
@ -94,5 +67,16 @@ namespace UniGLTF
context.SetMainObject(root);
}
}
private static IMaterialDescriptorGenerator GetMaterialDescriptorGenerator(ImporterRenderPipelineTypes renderPipeline)
{
return renderPipeline switch
{
ImporterRenderPipelineTypes.Auto => MaterialDescriptorGeneratorUtility .GetValidGltfMaterialDescriptorGenerator(),
ImporterRenderPipelineTypes.BuiltinRenderPipeline => MaterialDescriptorGeneratorUtility .GetGltfMaterialDescriptorGenerator(RenderPipelineTypes.BuiltinRenderPipeline),
ImporterRenderPipelineTypes.UniversalRenderPipeline => MaterialDescriptorGeneratorUtility .GetGltfMaterialDescriptorGenerator(RenderPipelineTypes.UniversalRenderPipeline),
_ => MaterialDescriptorGeneratorUtility.GetValidGltfMaterialDescriptorGenerator(),
};
}
}
}

View File

@ -0,0 +1,9 @@
namespace UniGLTF
{
public enum ImporterRenderPipelineTypes
{
Auto = 0,
BuiltinRenderPipeline = 1,
UniversalRenderPipeline = 2,
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: d4f38213d6e442ef986fd3e633991ba7
timeCreated: 1722347490

View File

@ -145,6 +145,7 @@ namespace UniGLTF
public int AppendToBuffer(NativeArray<byte> segment)
{
var gltfBufferView = _buffer.Extend(segment);
Gltf.buffers[0].byteLength = _buffer.Bytes.Count;
var viewIndex = Gltf.bufferViews.Count;
Gltf.bufferViews.Add(gltfBufferView);
return viewIndex;

View File

@ -12,12 +12,14 @@ namespace UniGLTF
/// </summary>
public class ImporterContext : IResponsibilityForDestroyObjects
{
private readonly ImporterContextSettings _settings;
public ITextureDescriptorGenerator TextureDescriptorGenerator { get; protected set; }
public IMaterialDescriptorGenerator MaterialDescriptorGenerator { get; protected set; }
public TextureFactory TextureFactory { get; }
public MaterialFactory MaterialFactory { get; }
public AnimationClipFactory AnimationClipFactory { get; }
public bool LoadAnimation { get; set; } = true;
private bool LoadAnimation => _settings.LoadAnimation;
public IReadOnlyDictionary<SubAssetKey, UnityEngine.Object> ExternalObjectMap;
@ -29,12 +31,15 @@ namespace UniGLTF
/// <param name="externalObjectMap">外部オブジェクトのリスト(主にScriptedImporterのRemapで使う)</param>
/// <param name="textureDeserializer">Textureロードをカスタマイズする</param>
/// <param name="materialGenerator">Materialロードをカスタマイズする(URP向け)</param>
/// <param name="settings">ImporterContextの設定</param>
public ImporterContext(
GltfData data,
IReadOnlyDictionary<SubAssetKey, UnityEngine.Object> externalObjectMap = null,
ITextureDeserializer textureDeserializer = null,
IMaterialDescriptorGenerator materialGenerator = null)
IMaterialDescriptorGenerator materialGenerator = null,
ImporterContextSettings settings = null)
{
_settings = settings ?? new ImporterContextSettings();
Data = data;
TextureDescriptorGenerator = new GltfTextureDescriptorGenerator(Data);
MaterialDescriptorGenerator = materialGenerator ?? MaterialDescriptorGeneratorUtility.GetValidGltfMaterialDescriptorGenerator();
@ -66,7 +71,7 @@ namespace UniGLTF
/// <summary>
/// GLTF から Unity に変換するときに反転させる軸
/// </summary>
public Axes InvertAxis = Axes.Z;
private Axes InvertAxis => _settings.InvertAxis;
public static List<string> UnsupportedExtensions = new List<string>
{

View File

@ -0,0 +1,19 @@
namespace UniGLTF
{
public class ImporterContextSettings
{
public bool LoadAnimation { get; }
public Axes InvertAxis { get; }
/// <summary>
/// ImporterContextの設定を指定する。
/// </summary>
/// <param name="loadAnimation">アニメーションをインポートする場合はtrueを指定(初期値はtrue)</param>
/// <param name="invertAxis">GLTF から Unity に変換するときに反転させる軸を指定(初期値はAxes.Z)</param>
public ImporterContextSettings(bool loadAnimation = true, Axes invertAxis = Axes.Z)
{
LoadAnimation = loadAnimation;
InvertAxis = invertAxis;
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 091d1bfaecd542b6a039fb7a3e3676f8
timeCreated: 1723863327

View File

@ -13,26 +13,15 @@ namespace UniGLTF
{
if (BuiltInGltfUnlitMaterialImporter.TryCreateParam(data, i, out var param)) return param;
if (BuiltInGltfPbrMaterialImporter.TryCreateParam(data, i, out param)) return param;
// fallback
if (Symbols.VRM_DEVELOP)
{
Debug.LogWarning($"material: {i} out of range. fallback");
}
return new MaterialDescriptor(
GltfMaterialImportUtils.ImportMaterialName(i, null),
BuiltInGltfPbrMaterialImporter.Shader,
null,
new Dictionary<string, TextureDescriptor>(),
new Dictionary<string, float>(),
new Dictionary<string, Color>(),
new Dictionary<string, Vector4>(),
new Action<Material>[]{});
return GetGltfDefault(GltfMaterialImportUtils.ImportMaterialName(i, null));
}
public MaterialDescriptor GetGltfDefault()
{
return BuiltInGltfDefaultMaterialImporter.CreateParam();
}
public MaterialDescriptor GetGltfDefault(string materialName = null) => BuiltInGltfDefaultMaterialImporter.CreateParam(materialName);
}
}

View File

@ -9,11 +9,11 @@ namespace UniGLTF
/// </summary>
public static class BuiltInGltfDefaultMaterialImporter
{
public static MaterialDescriptor CreateParam()
public static MaterialDescriptor CreateParam(string materialName = null)
{
// FIXME
return new MaterialDescriptor(
"__default__",
string.IsNullOrEmpty(materialName) ? "__default__" : materialName,
BuiltInGltfPbrMaterialImporter.Shader,
default,
new Dictionary<string, TextureDescriptor>(),

View File

@ -7,10 +7,19 @@ namespace UniGLTF
{
public static void ExportTextureTransform(Material src, glTFTextureInfo dstTextureInfo, string targetTextureName)
{
if (dstTextureInfo != null && src.HasProperty(targetTextureName))
if (src.HasProperty(targetTextureName))
{
var offset = src.GetTextureOffset(targetTextureName);
var scale = src.GetTextureScale(targetTextureName);
ExportTextureTransform(offset, scale, dstTextureInfo);
}
}
public static void ExportTextureTransform(Vector2 offset, Vector2 scale, glTFTextureInfo dstTextureInfo)
{
if (dstTextureInfo != null)
{
(scale, offset) = TextureTransform.VerticalFlipScaleOffset(scale, offset);
glTF_KHR_texture_transform.Serialize(dstTextureInfo, (offset.x, offset.y), (scale.x, scale.y));

View File

@ -6,7 +6,7 @@
{
return RenderPipelineUtility.GetRenderPipelineType() switch
{
RenderPipelineTypes.UniversalRenderPipeline => throw new System.NotImplementedException(),
RenderPipelineTypes.UniversalRenderPipeline => new UrpGltfMaterialExporter(),
RenderPipelineTypes.BuiltinRenderPipeline => new BuiltInGltfMaterialExporter(),
_ => new BuiltInGltfMaterialExporter(),
};

View File

@ -14,6 +14,6 @@
/// <summary>
/// Generate the MaterialDescriptor for the non-specified glTF material.
/// </summary>
MaterialDescriptor GetGltfDefault();
MaterialDescriptor GetGltfDefault(string materialName = null);
}
}

View File

@ -1,11 +1,14 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using UnityEngine;
namespace UniGLTF
{
public sealed class MaterialDescriptor
{
public delegate Task MaterialGenerateAsyncFunc(Material m, GetTextureAsyncFunc getTexture, IAwaitCaller awaitCaller);
public readonly string Name;
public readonly Shader Shader;
public readonly int? RenderQueue;
@ -14,6 +17,7 @@ namespace UniGLTF
public readonly IReadOnlyDictionary<string, Color> Colors;
public readonly IReadOnlyDictionary<string, Vector4> Vectors;
public readonly IReadOnlyList<Action<Material>> Actions;
public readonly IReadOnlyList<MaterialGenerateAsyncFunc> AsyncActions;
public SubAssetKey SubAssetKey => new SubAssetKey(SubAssetKey.MaterialType, Name);
@ -25,7 +29,8 @@ namespace UniGLTF
IReadOnlyDictionary<string, float> floatValues,
IReadOnlyDictionary<string, Color> colors,
IReadOnlyDictionary<string, Vector4> vectors,
IReadOnlyList<Action<Material>> actions)
IReadOnlyList<Action<Material>> actions,
IReadOnlyList<MaterialGenerateAsyncFunc> asyncActions = null)
{
Name = name;
Shader = shader;
@ -35,6 +40,7 @@ namespace UniGLTF
Colors = colors;
Vectors = vectors;
Actions = actions;
AsyncActions = asyncActions ?? new List<MaterialGenerateAsyncFunc>();
}
}
}

View File

@ -4,7 +4,12 @@ namespace UniGLTF
{
public static IMaterialDescriptorGenerator GetValidGltfMaterialDescriptorGenerator()
{
return RenderPipelineUtility.GetRenderPipelineType() switch
return GetGltfMaterialDescriptorGenerator(RenderPipelineUtility.GetRenderPipelineType());
}
public static IMaterialDescriptorGenerator GetGltfMaterialDescriptorGenerator(RenderPipelineTypes renderPipelineType)
{
return renderPipelineType switch
{
RenderPipelineTypes.UniversalRenderPipeline => new UrpGltfMaterialDescriptorGenerator(),
RenderPipelineTypes.BuiltinRenderPipeline => new BuiltInGltfMaterialDescriptorGenerator(),

View File

@ -10,11 +10,9 @@ namespace UniGLTF
public class MaterialFactory : IResponsibilityForDestroyObjects
{
private readonly IReadOnlyDictionary<SubAssetKey, Material> m_externalMap;
/// <summary>
/// デフォルトマテリアルの MaterialDescriptor は IMaterialDescriptorGenerator の実装によって異なるので外から渡す
/// </summary>
private readonly SubAssetKey m_defaultMaterialKey = new SubAssetKey(typeof(Material), "__UNIGLTF__DEFAULT__MATERIAL__");
private readonly MaterialDescriptor m_defaultMaterialParams;
private readonly List<MaterialLoadInfo> m_materials = new List<MaterialLoadInfo>();
/// <summary>
/// gltfPritmitive.material が無い場合のデフォルトマテリアル
@ -23,6 +21,9 @@ namespace UniGLTF
/// </summary>
private Material m_defaultMaterial;
public IReadOnlyList<MaterialLoadInfo> Materials => m_materials;
public MaterialFactory(IReadOnlyDictionary<SubAssetKey, Material> externalMaterialMap, MaterialDescriptor defaultMaterialParams)
{
m_externalMap = externalMaterialMap;
@ -45,18 +46,6 @@ namespace UniGLTF
}
}
List<MaterialLoadInfo> m_materials = new List<MaterialLoadInfo>();
public IReadOnlyList<MaterialLoadInfo> Materials => m_materials;
void Remove(Material material)
{
var index = m_materials.FindIndex(x => x.Asset == material);
if (index >= 0)
{
m_materials.RemoveAt(index);
}
}
public void Dispose()
{
foreach (var x in m_materials)
@ -67,6 +56,11 @@ namespace UniGLTF
UnityObjectDestroyer.DestroyRuntimeOrEditor(x.Asset);
}
}
if (m_defaultMaterial != null)
{
UnityObjectDestroyer.DestroyRuntimeOrEditor(m_defaultMaterial);
}
}
/// <summary>
@ -90,6 +84,12 @@ namespace UniGLTF
m_materials.Remove(x);
}
}
if (m_defaultMaterial != null)
{
take(m_defaultMaterialKey, m_defaultMaterial);
m_defaultMaterial = null;
}
}
public Material GetMaterial(int index)
@ -101,6 +101,12 @@ namespace UniGLTF
public async Task<Material> GetDefaultMaterialAsync(IAwaitCaller awaitCaller)
{
if (m_externalMap.ContainsKey(m_defaultMaterialKey))
{
m_defaultMaterial = m_externalMap[m_defaultMaterialKey];
return m_externalMap[m_defaultMaterialKey];
}
if (m_defaultMaterial == null)
{
m_defaultMaterial = await LoadAsync(m_defaultMaterialParams, (_, _) => null, awaitCaller);
@ -136,7 +142,8 @@ namespace UniGLTF
if (texture != null)
{
material.SetTexture(kv.Key, texture);
SetTextureOffsetAndScale(material, kv.Key, kv.Value.Offset, kv.Value.Scale);
material.SetTextureOffset(kv.Key, kv.Value.Offset);
material.SetTextureScale(kv.Key, kv.Value.Scale);
}
}
@ -165,15 +172,14 @@ namespace UniGLTF
action(material);
}
foreach (var asyncAction in matDesc.AsyncActions)
{
await asyncAction(material, getTexture, awaitCaller);
}
m_materials.Add(new MaterialLoadInfo(matDesc.SubAssetKey, material, false));
return material;
}
public static void SetTextureOffsetAndScale(Material material, string propertyName, Vector2 offset, Vector2 scale)
{
material.SetTextureOffset(propertyName, offset);
material.SetTextureScale(propertyName, scale);
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 4c2edd284a744a13bf888a4b29fac93a
timeCreated: 1722269836

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 70546771aa234567b5d7c4430548ac0f
timeCreated: 1722269920

View File

@ -0,0 +1,36 @@
using System;
using UnityEngine;
namespace UniGLTF
{
/// <summary>
/// フォールバック目的で最低限なにかをエクスポートする。
///
/// メインカラーとメインテクスチャをエクスポートする。
/// </summary>
public class UrpFallbackMaterialExporter
{
public glTFMaterial ExportMaterial(Material src, ITextureExporter textureExporter)
{
var dst = new glTFMaterial
{
name = src.name,
pbrMetallicRoughness = new glTFPbrMetallicRoughness(),
};
dst.pbrMetallicRoughness.baseColorFactor = src.color.ToFloat4(ColorSpace.sRGB, ColorSpace.Linear);
var index = textureExporter.RegisterExportingAsSRgb(src.mainTexture, false);
if (index >= 0)
{
dst.pbrMetallicRoughness.baseColorTexture = new glTFMaterialBaseColorTextureInfo
{
index = index,
texCoord = 0,
};
GltfMaterialExportUtils.ExportTextureTransform(src.mainTextureOffset, src.mainTextureScale, dst.pbrMetallicRoughness.baseColorTexture);
}
return dst;
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: c0269be076674f5988895ecd61b8d316
timeCreated: 1722612454

View File

@ -0,0 +1,239 @@
using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Rendering;
namespace UniGLTF
{
public class UrpLitMaterialExporter
{
public Shader Shader { get; set; }
/// <summary>
/// "Universal Render Pipeline/Lit" シェーダのマテリアルをエクスポートする。
///
/// プロパティに互換性がある他のシェーダを指定することもできる。
/// </summary>
public UrpLitMaterialExporter(Shader shader = null)
{
Shader = shader != null ? shader : Shader.Find("Universal Render Pipeline/Lit");
}
public bool TryExportMaterial(Material src, ITextureExporter textureExporter, out glTFMaterial dst)
{
try
{
if (src == null) throw new ArgumentNullException(nameof(src));
if (textureExporter == null) throw new ArgumentNullException(nameof(textureExporter));
if (src.shader != Shader || Shader == null) throw new UniGLTFShaderNotMatchedInternalException(src.shader);
dst = new glTFMaterial
{
name = src.name,
pbrMetallicRoughness = new glTFPbrMetallicRoughness(),
};
var context = new UrpLitContext(src);
foreach (var validation in EnumerateValidation(context))
{
if (!validation.CanExport)
{
Debug.LogError(validation.Message, src);
throw new UniGLTFNotSupportedException(validation.Message);
}
}
ExportSurfaceSettings(context, dst, textureExporter);
ExportBaseColor(context, dst, textureExporter);
ExportMetallicSmoothness(context, dst, textureExporter);
ExportOcclusion(context, dst, textureExporter);
ExportNormal(context, dst, textureExporter);
ExportEmission(context, dst, textureExporter);
return true;
}
catch (UniGLTFShaderNotMatchedInternalException)
{
dst = default;
return false;
}
catch (Exception e)
{
Debug.LogException(e);
dst = default;
return false;
}
}
public static void ExportSurfaceSettings(UrpBaseShaderContext context, glTFMaterial dst, ITextureExporter textureExporter)
{
dst.alphaMode = (context.SurfaceType, context.IsAlphaClipEnabled) switch
{
(UrpLitSurfaceType.Opaque, false) => glTFBlendMode.OPAQUE.ToString(),
(UrpLitSurfaceType.Opaque, true) => glTFBlendMode.MASK.ToString(),
(UrpLitSurfaceType.Transparent, false) => glTFBlendMode.BLEND.ToString(),
(UrpLitSurfaceType.Transparent, true) => glTFBlendMode.BLEND.ToString(), // NOTE: not supported in glTF
_ => throw new ArgumentOutOfRangeException()
};
dst.alphaCutoff = context.Cutoff;
dst.doubleSided = context.CullMode != CullMode.Back; // NOTE: cull front not supported in glTF
}
public static void ExportBaseColor(UrpBaseShaderContext context, glTFMaterial dst, ITextureExporter textureExporter)
{
dst.pbrMetallicRoughness.baseColorFactor = context.BaseColorSrgb.ToFloat4(ColorSpace.sRGB, ColorSpace.Linear);
if (context.BaseTexture != null)
{
var needsAlpha = context.SurfaceType != UrpLitSurfaceType.Opaque;
var index = textureExporter.RegisterExportingAsSRgb(context.BaseTexture, needsAlpha);
if (index >= 0)
{
dst.pbrMetallicRoughness.baseColorTexture = new glTFMaterialBaseColorTextureInfo
{
index = index,
texCoord = 0,
};
ExportBaseTexTransform(context, dst.pbrMetallicRoughness.baseColorTexture);
}
}
}
public static void ExportMetallicSmoothness(UrpLitContext context, glTFMaterial dst, ITextureExporter textureExporter)
{
// NOTE: maybe KHR_materials_specular
if (context.WorkflowType != UrpLitWorkflowType.Metallic) return;
// Metallic-Roughness
dst.pbrMetallicRoughness.metallicRoughnessTexture = null;
dst.pbrMetallicRoughness.metallicFactor = context.Metallic;
dst.pbrMetallicRoughness.roughnessFactor = 1.0f - context.Smoothness;
if (context.MetallicGlossMap != null)
{
var index = textureExporter.RegisterExportingAsCombinedGltfPbrParameterTextureFromUnityStandardTextures(
context.MetallicGlossMap,
context.Smoothness,
context.OcclusionTexture
);
if (index >= 0)
{
dst.pbrMetallicRoughness.metallicRoughnessTexture = new glTFMaterialMetallicRoughnessTextureInfo
{
index = index,
texCoord = 0,
};
ExportBaseTexTransform(context, dst.pbrMetallicRoughness.metallicRoughnessTexture);
dst.pbrMetallicRoughness.metallicFactor = 1.0f;
dst.pbrMetallicRoughness.roughnessFactor = 1.0f;
}
}
}
public void ExportOcclusion(UrpLitContext context, glTFMaterial dst, ITextureExporter textureExporter)
{
if (context.WorkflowType != UrpLitWorkflowType.Metallic) return;
// Occlusion
if (context.OcclusionTexture != null)
{
var index = textureExporter.RegisterExportingAsCombinedGltfPbrParameterTextureFromUnityStandardTextures(
context.MetallicGlossMap,
context.Smoothness,
context.OcclusionTexture
);
if (index >= 0)
{
dst.occlusionTexture = new glTFMaterialOcclusionTextureInfo
{
index = index,
texCoord = 0,
strength = context.OcclusionStrength,
};
ExportBaseTexTransform(context, dst.occlusionTexture);
}
}
}
public void ExportNormal(UrpLitContext context, glTFMaterial dst, ITextureExporter textureExporter)
{
if (context.BumpMap == null) return;
var index = textureExporter.RegisterExportingAsNormal(context.BumpMap);
if (index >= 0)
{
dst.normalTexture = new glTFMaterialNormalTextureInfo
{
index = index,
texCoord = 0,
scale = context.BumpScale,
};
ExportBaseTexTransform(context, dst.normalTexture);
}
}
public void ExportEmission(UrpLitContext context, glTFMaterial dst, ITextureExporter textureExporter)
{
if (!context.IsEmissionEnabled) return;
dst.emissiveFactor = context.EmissionColorLinear.ToFloat3(ColorSpace.Linear, ColorSpace.Linear);
if (context.EmissionTexture != null)
{
var index = textureExporter.RegisterExportingAsSRgb(context.EmissionTexture, true);
if (index >= 0)
{
dst.emissiveTexture = new glTFMaterialEmissiveTextureInfo
{
index = index,
texCoord = 0,
};
ExportBaseTexTransform(context, dst.emissiveTexture);
}
}
}
private static void ExportBaseTexTransform(UrpBaseShaderContext context, glTFTextureInfo dst)
{
GltfMaterialExportUtils.ExportTextureTransform(
context.BaseTextureOffset,
context.BaseTextureScale,
dst
);
}
public static IEnumerable<Validation> EnumerateValidation(UrpLitContext context)
{
var validationContext = ValidationContext.Create(context.Material);
// Surface Settings
if (context.WorkflowType != UrpLitWorkflowType.Metallic) yield return Error(ValidationMessage.WorkflowTypeNotSupported);
if (context.SurfaceType == UrpLitSurfaceType.Transparent && context.IsAlphaClipEnabled) yield return Warning(ValidationMessage.TransparentAlphaClipNotSupported);
if (context.CullMode == CullMode.Front) yield return Error(ValidationMessage.BackFaceRenderingNotSupported);
if (context.BlendMode == UrpLitBlendMode.Additive) yield return Error(ValidationMessage.AdditiveBlendModeNotSupported);
if (context.BlendMode == UrpLitBlendMode.Multiply) yield return Error(ValidationMessage.MultiplyBlendModeNotSupported);
// Etc Textures
if (context.ParallaxTexture != null) yield return Warning(ValidationMessage.ParallaxTextureNotSupported);
yield break;
Validation Error(ValidationMessage message)
{
return Validation.Error(message.ToString(), validationContext);
}
Validation Warning(ValidationMessage message)
{
return Validation.Warning(message.ToString(), validationContext);
}
}
public enum ValidationMessage
{
WorkflowTypeNotSupported,
TransparentAlphaClipNotSupported,
BackFaceRenderingNotSupported,
ParallaxTextureNotSupported,
AdditiveBlendModeNotSupported,
MultiplyBlendModeNotSupported,
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 8832f807c30a420d95aeaee15a1fbff7
timeCreated: 1722269933

View File

@ -0,0 +1,79 @@
using System;
using UniGLTF.UniUnlit;
using UnityEngine;
namespace UniGLTF
{
public class UrpUniUnlitMaterialExporter
{
public Shader Shader { get; set; }
/// <summary>
/// "UniGLTF/UniUnlit" シェーダのマテリアルをエクスポートする。
///
/// プロパティに互換性がある他のシェーダを指定することもできる。
/// </summary>
public UrpUniUnlitMaterialExporter(Shader shader = null)
{
Shader = shader != null ? shader : Shader.Find("UniGLTF/UniUnlit");
}
public bool TryExportMaterial(Material src, ITextureExporter textureExporter, out glTFMaterial dst)
{
try
{
if (src == null) throw new ArgumentNullException(nameof(src));
if (textureExporter == null) throw new ArgumentNullException(nameof(textureExporter));
if (src.shader != Shader || Shader == null) throw new UniGLTFShaderNotMatchedInternalException(src.shader);
dst = glTF_KHR_materials_unlit.CreateDefault();
dst.name = src.name;
var context = new UniUnlitContext(src);
dst.alphaMode = context.RenderMode switch
{
UniUnlitRenderMode.Opaque => glTFBlendMode.OPAQUE.ToString(),
UniUnlitRenderMode.Cutout => glTFBlendMode.MASK.ToString(),
UniUnlitRenderMode.Transparent => glTFBlendMode.BLEND.ToString(),
_ => throw new ArgumentOutOfRangeException(),
};
dst.alphaCutoff = context.Cutoff;
dst.doubleSided = context.CullMode != UniUnlitCullMode.Back;
dst.pbrMetallicRoughness.baseColorFactor = context.MainColorSrgb
.ToFloat4(ColorSpace.sRGB, ColorSpace.Linear);
if (context.MainTexture != null)
{
var needsAlpha = context.RenderMode != UniUnlitRenderMode.Opaque;
var index = textureExporter.RegisterExportingAsSRgb(context.MainTexture, needsAlpha);
if (index >= 0)
{
dst.pbrMetallicRoughness.baseColorTexture = new glTFMaterialBaseColorTextureInfo
{
index = index,
texCoord = 0,
};
GltfMaterialExportUtils.ExportTextureTransform(
context.MainTextureOffset,
context.MainTextureScale,
dst.pbrMetallicRoughness.baseColorTexture);
}
}
return true;
}
catch (UniGLTFShaderNotMatchedInternalException)
{
dst = default;
return false;
}
catch (Exception e)
{
Debug.LogException(e);
dst = default;
return false;
}
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 5b17f3928c684fc1a9beda10797b0e76
timeCreated: 1722613258

View File

@ -0,0 +1,50 @@
using System;
using UnityEngine;
namespace UniGLTF
{
public class UrpUnlitMaterialExporter
{
public Shader Shader { get; set; }
/// <summary>
/// "Universal Render Pipeline/Unlit" シェーダのマテリアルをエクスポートする。
///
/// プロパティに互換性がある他のシェーダを指定することもできる。
/// </summary>
public UrpUnlitMaterialExporter(Shader shader = null)
{
Shader = shader != null ? shader : Shader.Find("Universal Render Pipeline/Unlit");
}
public bool TryExportMaterial(Material src, ITextureExporter textureExporter, out glTFMaterial dst)
{
try
{
if (src == null) throw new ArgumentNullException(nameof(src));
if (textureExporter == null) throw new ArgumentNullException(nameof(textureExporter));
if (src.shader != Shader || Shader == null) throw new UniGLTFShaderNotMatchedInternalException(src.shader);
dst = glTF_KHR_materials_unlit.CreateDefault();
dst.name = src.name;
var context = new UrpUnlitContext(src);
UrpLitMaterialExporter.ExportSurfaceSettings(context, dst, textureExporter);
UrpLitMaterialExporter.ExportBaseColor(context, dst, textureExporter);
return true;
}
catch (UniGLTFShaderNotMatchedInternalException)
{
dst = default;
return false;
}
catch (Exception e)
{
Debug.LogException(e);
dst = default;
return false;
}
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: a90bb1e911744bbab916950324c70e52
timeCreated: 1722614768

View File

@ -0,0 +1,22 @@
using UnityEngine;
namespace UniGLTF
{
public class UrpGltfMaterialExporter : IMaterialExporter
{
public UrpLitMaterialExporter UrpLitExporter { get; set; } = new();
public UrpUnlitMaterialExporter UrpUnlitExporter { get; set; } = new();
public UrpUniUnlitMaterialExporter UrpUniUnlitExporter { get; set; } = new();
public UrpFallbackMaterialExporter FallbackExporter { get; set; } = new();
public glTFMaterial ExportMaterial(Material m, ITextureExporter textureExporter, GltfExportSettings settings)
{
if (UrpLitExporter.TryExportMaterial(m, textureExporter, out var dst)) return dst;
if (UrpUnlitExporter.TryExportMaterial(m, textureExporter, out dst)) return dst;
if (UrpUniUnlitExporter.TryExportMaterial(m, textureExporter, out dst)) return dst;
Debug.Log($"Material `{m.name}` fallbacks.");
return FallbackExporter.ExportMaterial(m, textureExporter);
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 943c27f3f6054f25b4c0bf7e4cd50eff
timeCreated: 1722269861

View File

@ -1,27 +1,65 @@
using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Rendering;
namespace UniGLTF
{
/// <summary>
/// Generate the descriptor of the glTF default material.
///
/// https://registry.khronos.org/glTF/specs/2.0/glTF-2.0.html#default-material
/// </summary>
public static class UrpGltfDefaultMaterialImporter
public class UrpGltfDefaultMaterialImporter
{
public static MaterialDescriptor CreateParam()
public Shader Shader { get; set; }
public UrpGltfDefaultMaterialImporter(Shader shader = null)
{
Shader = shader != null ? shader : Shader.Find("Universal Render Pipeline/Lit");
}
public MaterialDescriptor CreateParam(string materialName)
{
// FIXME
return new MaterialDescriptor(
"__default__",
UrpGltfPbrMaterialImporter.Shader,
default,
string.IsNullOrEmpty(materialName) ? "__default__" : materialName,
Shader,
null,
new Dictionary<string, TextureDescriptor>(),
new Dictionary<string, float>(),
new Dictionary<string, Color>(),
new Dictionary<string, Vector4>(),
new List<Action<Material>>()
new List<Action<Material>> { GenerateDefaultMaterial }
);
}
public static void GenerateDefaultMaterial(Material dst)
{
var context = new UrpLitContext(dst);
context.UnsafeEditMode = true;
context.SurfaceType = UrpLitSurfaceType.Opaque;
context.IsAlphaClipEnabled = false;
context.CullMode = CullMode.Back;
context.BaseColorSrgb = new Color(1, 1, 1, 1);
context.BaseTexture = null;
context.WorkflowType = UrpLitWorkflowType.Metallic;
context.SmoothnessTextureChannel = UrpLitSmoothnessMapChannel.SpecularMetallicAlpha;
context.Metallic = 1f;
context.Smoothness = 0f;
context.MetallicGlossMap = null;
context.OcclusionTexture = null;
context.BumpMap = null;
context.IsEmissionEnabled = false;
context.EmissionColorLinear = new Color(0, 0, 0, 0);
context.EmissionTexture = null;
context.Validate();
}
}
}

View File

@ -1,6 +1,8 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using UnityEngine;
using UnityEngine.Rendering;
namespace UniGLTF
{
@ -9,26 +11,19 @@ namespace UniGLTF
///
/// see: https://github.com/Unity-Technologies/Graphics/blob/v7.5.3/com.unity.render-pipelines.universal/Editor/UniversalRenderPipelineMaterialUpgrader.cs#L354-L379
/// </summary>
public static class UrpGltfPbrMaterialImporter
public class UrpGltfPbrMaterialImporter
{
public const string ShaderName = "Universal Render Pipeline/Lit";
/// <summary>
/// Universal Render Pipeline/Lit とプロパティやキーワードに互換があるカスタムシェーダに置換可能。
/// </summary>
public Shader Shader { get; set; }
private static readonly int SrcBlend = Shader.PropertyToID("_SrcBlend");
private static readonly int DstBlend = Shader.PropertyToID("_DstBlend");
private static readonly int ZWrite = Shader.PropertyToID("_ZWrite");
private static readonly int Cutoff = Shader.PropertyToID("_Cutoff");
public static Shader Shader => Shader.Find(ShaderName);
private enum BlendMode
public UrpGltfPbrMaterialImporter(Shader shader = null)
{
Opaque,
Cutout,
Fade,
Transparent
Shader = shader != null ? shader : Shader.Find("Universal Render Pipeline/Lit");
}
public static bool TryCreateParam(GltfData data, int i, out MaterialDescriptor matDesc)
public bool TryCreateParam(GltfData data, int i, out MaterialDescriptor matDesc)
{
if (i < 0 || i >= data.GLTF.materials.Count)
{
@ -36,161 +31,142 @@ namespace UniGLTF
return false;
}
var textureSlots = new Dictionary<string, TextureDescriptor>();
var floatValues = new Dictionary<string, float>();
var colors = new Dictionary<string, Color>();
var vectors = new Dictionary<string, Vector4>();
var actions = new List<Action<Material>>();
var src = data.GLTF.materials[i];
TextureDescriptor? standardTexDesc = default;
if (src.pbrMetallicRoughness != null || src.occlusionTexture != null)
{
if (src.pbrMetallicRoughness.metallicRoughnessTexture != null || src.occlusionTexture != null)
{
if (GltfPbrTextureImporter.TryStandardTexture(data, src, out var key, out var desc))
{
if (string.IsNullOrEmpty(desc.UnityObjectName))
{
throw new ArgumentNullException();
}
standardTexDesc = desc;
}
}
if (src.pbrMetallicRoughness.baseColorFactor != null && src.pbrMetallicRoughness.baseColorFactor.Length == 4)
{
// from _Color !
colors.Add("_BaseColor",
src.pbrMetallicRoughness.baseColorFactor.ToColor4(ColorSpace.Linear, ColorSpace.sRGB)
);
}
if (src.pbrMetallicRoughness.baseColorTexture != null && src.pbrMetallicRoughness.baseColorTexture.index != -1)
{
if (GltfPbrTextureImporter.TryBaseColorTexture(data, src, out var key, out var desc))
{
// from _MainTex !
textureSlots.Add("_BaseMap", desc);
}
}
if (src.pbrMetallicRoughness.metallicRoughnessTexture != null && src.pbrMetallicRoughness.metallicRoughnessTexture.index != -1 && standardTexDesc.HasValue)
{
actions.Add(material => material.EnableKeyword("_METALLICSPECGLOSSMAP"));
textureSlots.Add("_MetallicGlossMap", standardTexDesc.Value);
// Set 1.0f as hard-coded. See: https://github.com/dwango/UniVRM/issues/212.
floatValues.Add("_Metallic", 1.0f);
floatValues.Add("_GlossMapScale", 1.0f);
// default value is 0.5 !
floatValues.Add("_Smoothness", 1.0f);
}
else
{
floatValues.Add("_Metallic", src.pbrMetallicRoughness.metallicFactor);
// from _Glossiness !
floatValues.Add("_Smoothness", 1.0f - src.pbrMetallicRoughness.roughnessFactor);
}
}
if (src.normalTexture != null && src.normalTexture.index != -1)
{
actions.Add(material => material.EnableKeyword("_NORMALMAP"));
if (GltfPbrTextureImporter.TryNormalTexture(data, src, out var key, out var desc))
{
textureSlots.Add("_BumpMap", desc);
floatValues.Add("_BumpScale", src.normalTexture.scale);
}
}
if (src.occlusionTexture != null && src.occlusionTexture.index != -1 && standardTexDesc.HasValue)
{
textureSlots.Add("_OcclusionMap", standardTexDesc.Value);
floatValues.Add("_OcclusionStrength", src.occlusionTexture.strength);
}
if (src.emissiveFactor != null
|| (src.emissiveTexture != null && src.emissiveTexture.index != -1))
{
actions.Add(material =>
{
material.EnableKeyword("_EMISSION");
material.globalIlluminationFlags &= ~MaterialGlobalIlluminationFlags.EmissiveIsBlack;
});
var emissiveFactor = GltfMaterialImportUtils.ImportLinearEmissiveFactor(data, src);
if (emissiveFactor.HasValue)
{
colors.Add("_EmissionColor", emissiveFactor.Value);
}
if (src.emissiveTexture != null && src.emissiveTexture.index != -1)
{
if (GltfPbrTextureImporter.TryEmissiveTexture(data, src, out var key, out var desc))
{
textureSlots.Add("_EmissionMap", desc);
}
}
}
actions.Add(material =>
{
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);
});
matDesc = new MaterialDescriptor(
GltfMaterialImportUtils.ImportMaterialName(i, src),
Shader,
null,
textureSlots,
floatValues,
colors,
vectors,
actions);
new Dictionary<string, TextureDescriptor>(),
new Dictionary<string, float>(),
new Dictionary<string, Color>(),
new Dictionary<string, Vector4>(),
new List<Action<Material>>(),
new [] { (MaterialDescriptor.MaterialGenerateAsyncFunc)AsyncAction }
);
return true;
Task AsyncAction(Material x, GetTextureAsyncFunc y, IAwaitCaller z) => GenerateMaterialAsync(data, src, x, y, z);
}
public static async Task GenerateMaterialAsync(GltfData data, glTFMaterial src, Material dst, GetTextureAsyncFunc getTextureAsync, IAwaitCaller awaitCaller)
{
var context = new UrpLitContext(dst);
context.UnsafeEditMode = true;
ImportSurfaceSettings(src, context);
await ImportBaseColorAsync(data, src, context, getTextureAsync, awaitCaller);
await ImportMetallicSmoothnessAsync(data, src, context, getTextureAsync, awaitCaller);
await ImportOcclusionAsync(data, src, context, getTextureAsync, awaitCaller);
await ImportNormalAsync(data, src, context, getTextureAsync, awaitCaller);
await ImportEmissionAsync(data, src, context, getTextureAsync, awaitCaller);
context.Validate();
}
public static void ImportSurfaceSettings(glTFMaterial src, UrpLitContext context)
{
context.SurfaceType = src.alphaMode switch
{
"OPAQUE" => UrpLitSurfaceType.Opaque,
"MASK" => UrpLitSurfaceType.Transparent,
"BLEND" => UrpLitSurfaceType.Transparent,
_ => UrpLitSurfaceType.Opaque,
};
context.BlendMode = context.SurfaceType switch
{
UrpLitSurfaceType.Transparent => UrpLitBlendMode.Alpha,
_ => UrpLitBlendMode.Alpha,
};
context.IsAlphaClipEnabled = src.alphaMode switch
{
"MASK" => true,
_ => false,
};
context.Cutoff = src.alphaCutoff;
context.CullMode = src.doubleSided ? CullMode.Off : CullMode.Back;
}
public static async Task ImportBaseColorAsync(GltfData data, glTFMaterial src, UrpLitContext context, GetTextureAsyncFunc getTextureAsync, IAwaitCaller awaitCaller)
{
var baseColorFactor = GltfMaterialImportUtils.ImportLinearBaseColorFactor(data, src);
if (baseColorFactor.HasValue)
{
context.BaseColorSrgb = baseColorFactor.Value.gamma;
}
if (src is { pbrMetallicRoughness: { baseColorTexture: { index: >= 0 } } })
{
if (GltfPbrTextureImporter.TryBaseColorTexture(data, src, out _, out var desc))
{
context.BaseTexture = await getTextureAsync(desc, awaitCaller);
context.BaseTextureOffset = desc.Offset;
context.BaseTextureScale = desc.Scale;
}
}
}
public static async Task ImportMetallicSmoothnessAsync(GltfData data, glTFMaterial src, UrpLitContext context, GetTextureAsyncFunc getTextureAsync, IAwaitCaller awaitCaller)
{
context.WorkflowType = UrpLitWorkflowType.Metallic;
context.SmoothnessTextureChannel = UrpLitSmoothnessMapChannel.SpecularMetallicAlpha;
context.Metallic = src.pbrMetallicRoughness.metallicFactor;
context.Smoothness = 1.0f - src.pbrMetallicRoughness.roughnessFactor;
if (src is { pbrMetallicRoughness: { metallicRoughnessTexture: { index: >= 0 } } })
{
if (GltfPbrTextureImporter.TryStandardTexture(data, src, out _, out var desc))
{
context.MetallicGlossMap = await getTextureAsync(desc, awaitCaller);
context.Metallic = 1;
context.Smoothness = 1;
}
}
}
public static async Task ImportOcclusionAsync(GltfData data, glTFMaterial src, UrpLitContext context, GetTextureAsyncFunc getTextureAsync, IAwaitCaller awaitCaller)
{
if (src is { occlusionTexture: { index: >= 0 } })
{
if (GltfPbrTextureImporter.TryStandardTexture(data, src, out _, out var desc))
{
context.OcclusionTexture = await getTextureAsync(desc, awaitCaller);
context.OcclusionStrength = src.occlusionTexture.strength;
}
}
}
private static async Task ImportNormalAsync(GltfData data, glTFMaterial src, UrpLitContext context, GetTextureAsyncFunc getTextureAsync, IAwaitCaller awaitCaller)
{
if (src.normalTexture is { index: >= 0 })
{
if (GltfPbrTextureImporter.TryNormalTexture(data, src, out _, out var desc))
{
context.BumpMap = await getTextureAsync(desc, awaitCaller);
context.BumpScale = src.normalTexture.scale;
}
}
}
private static async Task ImportEmissionAsync(GltfData data, glTFMaterial src, UrpLitContext context, GetTextureAsyncFunc getTextureAsync, IAwaitCaller awaitCaller)
{
var emissiveFactor = GltfMaterialImportUtils.ImportLinearEmissiveFactor(data, src);
if (emissiveFactor.HasValue)
{
context.EmissionColorLinear = emissiveFactor.Value;
}
if (src is { emissiveTexture: { index: >= 0 } })
{
if (GltfPbrTextureImporter.TryEmissiveTexture(data, src, out _, out var desc))
{
context.EmissionTexture = await getTextureAsync(desc, awaitCaller);
}
}
if (context.EmissionColorLinear is {maxColorComponent: > 0} || context.EmissionTexture != null)
{
context.IsEmissionEnabled = true;
}
}
}
}

View File

@ -1,6 +1,3 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using UnityEngine;
namespace UniGLTF
@ -10,30 +7,22 @@ namespace UniGLTF
/// </summary>
public sealed class UrpGltfMaterialDescriptorGenerator : IMaterialDescriptorGenerator
{
public UrpGltfPbrMaterialImporter PbrMaterialImporter { get; } = new();
public UrpGltfDefaultMaterialImporter DefaultMaterialImporter { get; } = new();
public MaterialDescriptor Get(GltfData data, int i)
{
if (BuiltInGltfUnlitMaterialImporter.TryCreateParam(data, i, out var param)) return param;
if (UrpGltfPbrMaterialImporter.TryCreateParam(data, i, out param)) return param;
// fallback
if (PbrMaterialImporter.TryCreateParam(data, i, out param)) return param;
// NOTE: Fallback to default material
if (Symbols.VRM_DEVELOP)
{
Debug.LogWarning($"material: {i} out of range. fallback");
}
return new MaterialDescriptor(
GltfMaterialImportUtils.ImportMaterialName(i, null),
UrpGltfPbrMaterialImporter.Shader,
null,
new Dictionary<string, TextureDescriptor>(),
new Dictionary<string, float>(),
new Dictionary<string, Color>(),
new Dictionary<string, Vector4>(),
new Collection<Action<Material>>());
return GetGltfDefault(GltfMaterialImportUtils.ImportMaterialName(i, null));
}
public MaterialDescriptor GetGltfDefault()
{
return UrpGltfDefaultMaterialImporter.CreateParam();
}
public MaterialDescriptor GetGltfDefault(string materialName = null) => DefaultMaterialImporter.CreateParam(materialName);
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 4a35a0639a7f4eb4b2c5fb8225803ce3
timeCreated: 1722270899

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 2100c40775e3446bb05f63f32820930a
timeCreated: 1722270911

View File

@ -0,0 +1,163 @@
using UnityEngine;
using UnityEngine.Rendering;
namespace UniGLTF
{
public abstract class UrpBaseShaderContext
{
private static readonly int Surface = Shader.PropertyToID("_Surface");
private static readonly int AlphaClip = Shader.PropertyToID("_AlphaClip");
private static readonly int Blend = Shader.PropertyToID("_Blend");
private static readonly int Cull = Shader.PropertyToID("_Cull");
private static readonly int BaseColorProp = Shader.PropertyToID("_BaseColor");
private static readonly int BaseMap = Shader.PropertyToID("_BaseMap");
private static readonly int CutoffProp = Shader.PropertyToID("_Cutoff");
private static readonly int ZWrite = Shader.PropertyToID("_ZWrite");
private static readonly int SrcBlend = Shader.PropertyToID("_SrcBlend");
private static readonly int DstBlend = Shader.PropertyToID("_DstBlend");
private static readonly string SurfaceTypeTransparentKeyword = "_SURFACE_TYPE_TRANSPARENT";
private static readonly string AlphaTestOnKeyword = "_ALPHATEST_ON";
private static readonly string AlphaPremultiplyOnKeyword = "_ALPHAPREMULTIPLY_ON";
private static readonly string AlphaModulateOnKeyword = "_ALPHAMODULATE_ON";
protected UrpBaseShaderContext(Material material)
{
Material = material;
}
public Material Material { get; }
/// <summary>
/// これが有効な場合、Validate() 関数が呼ばれるべき場合でも自動的に呼ばれなくなります。
///
/// 処理最適化目的で使用できます。
/// </summary>
public bool UnsafeEditMode { get; set; } = false;
public UrpLitSurfaceType SurfaceType
{
get => (UrpLitSurfaceType)Material.GetFloat(Surface);
set
{
Material.SetFloat(Surface, (float)value);
if (!UnsafeEditMode) Validate();
}
}
public UrpLitBlendMode BlendMode
{
get => (UrpLitBlendMode)Material.GetFloat(Blend);
set
{
Material.SetFloat(Blend, (float)value);
if (!UnsafeEditMode) Validate();
}
}
public bool IsAlphaClipEnabled
{
get => Material.GetFloat(AlphaClip) >= 0.5f;
set
{
Material.SetFloat(AlphaClip, value ? 1.0f : 0.0f);
if (!UnsafeEditMode) Validate();
}
}
public CullMode CullMode
{
get => (CullMode)Material.GetFloat(Cull);
set
{
Material.SetFloat(Cull, (float)value);
Material.doubleSidedGI = value != CullMode.Back;
}
}
public Color BaseColorSrgb
{
get => Material.GetColor(BaseColorProp);
set => Material.SetColor(BaseColorProp, value);
}
public Texture BaseTexture
{
get => Material.GetTexture(BaseMap);
set => Material.SetTexture(BaseMap, value);
}
public Vector2 BaseTextureOffset
{
get => Material.GetTextureOffset(BaseMap);
set => Material.SetTextureOffset(BaseMap, value);
}
public Vector2 BaseTextureScale
{
get => Material.GetTextureScale(BaseMap);
set => Material.SetTextureScale(BaseMap, value);
}
public float Cutoff
{
get => Material.GetFloat(CutoffProp);
set => Material.SetFloat(CutoffProp, value);
}
public virtual void Validate()
{
// Surface Type
var surfaceType = (UrpLitSurfaceType)Material.GetFloat(Surface);
Material.SetKeyword(SurfaceTypeTransparentKeyword, surfaceType != UrpLitSurfaceType.Opaque);
// Alpha Clip
var alphaClip = Material.GetFloat(AlphaClip) >= 0.5f;
Material.SetKeyword(AlphaTestOnKeyword, alphaClip);
// Blend Mode
var blendMode = (UrpLitBlendMode)Material.GetFloat(Blend);
Material.SetKeyword(AlphaPremultiplyOnKeyword, blendMode == UrpLitBlendMode.Premultiply);
Material.SetKeyword(AlphaModulateOnKeyword, blendMode == UrpLitBlendMode.Additive);
// ZWrite
var zWrite = surfaceType == UrpLitSurfaceType.Opaque;
Material.SetFloat(ZWrite, zWrite ? 1.0f : 0.0f);
Material.SetShaderPassEnabled("DepthOnly", zWrite);
// Render Settings
Material.SetFloat(SrcBlend, (surfaceType, blendMode) switch
{
(UrpLitSurfaceType.Opaque, _) => (float)UnityEngine.Rendering.BlendMode.One,
(UrpLitSurfaceType.Transparent, UrpLitBlendMode.Alpha) => (float)UnityEngine.Rendering.BlendMode.SrcAlpha,
(UrpLitSurfaceType.Transparent, UrpLitBlendMode.Premultiply) => (float)UnityEngine.Rendering.BlendMode.One,
(UrpLitSurfaceType.Transparent, UrpLitBlendMode.Additive) => (float)UnityEngine.Rendering.BlendMode.One,
(UrpLitSurfaceType.Transparent, UrpLitBlendMode.Multiply) => (float)UnityEngine.Rendering.BlendMode.DstColor,
_ => (float)UnityEngine.Rendering.BlendMode.One,
});
Material.SetFloat(DstBlend, (surfaceType, blendMode) switch
{
(UrpLitSurfaceType.Opaque, _) => (float)UnityEngine.Rendering.BlendMode.Zero,
(UrpLitSurfaceType.Transparent, UrpLitBlendMode.Alpha) => (float)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha,
(UrpLitSurfaceType.Transparent, UrpLitBlendMode.Premultiply) => (float)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha,
(UrpLitSurfaceType.Transparent, UrpLitBlendMode.Additive) => (float)UnityEngine.Rendering.BlendMode.One,
(UrpLitSurfaceType.Transparent, UrpLitBlendMode.Multiply) => (float)UnityEngine.Rendering.BlendMode.Zero,
_ => (float) UnityEngine.Rendering.BlendMode.Zero,
});
Material.SetOverrideTag("RenderType", (surfaceType, alphaClip) switch
{
(UrpLitSurfaceType.Opaque, false) => "Opaque",
(UrpLitSurfaceType.Opaque, true) => "TransparentCutout",
(UrpLitSurfaceType.Transparent, _) => "Transparent",
_ => "Opaque",
});
Material.renderQueue = (surfaceType, alphaClip) switch
{
(UrpLitSurfaceType.Opaque, false) => (int)RenderQueue.Geometry,
(UrpLitSurfaceType.Opaque, true) => (int)RenderQueue.AlphaTest,
(UrpLitSurfaceType.Transparent, _) => (int)RenderQueue.Transparent,
_ => Material.shader.renderQueue,
};
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: a0a218f533e64925a87626ce8129f264
timeCreated: 1722615731

View File

@ -0,0 +1,10 @@
namespace UniGLTF
{
public enum UrpLitBlendMode
{
Alpha = 0,
Premultiply = 1,
Additive = 2,
Multiply = 3,
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 307c409e09f74fed8caaaedfdf794ef9
timeCreated: 1722351228

View File

@ -0,0 +1,204 @@
using System;
using UnityEngine;
using UnityEngine.Rendering;
namespace UniGLTF
{
/// <summary>
/// "Universal Render Pipeline/Lit" シェーダーのプロパティを操作するためのクラス
///
/// glTF との読み書きに必要な機能だけ実装する
///
/// 非対応項目
/// - Detail Texture
/// - Specular Highlights Toggle
/// - Environment Reflections Toggle
/// - Sorting Priority
/// </summary>
public class UrpLitContext : UrpBaseShaderContext
{
private static readonly int WorkflowMode = Shader.PropertyToID("_WorkflowMode");
private static readonly int EmissionColor = Shader.PropertyToID("_EmissionColor");
private static readonly int EmissionMap = Shader.PropertyToID("_EmissionMap");
private static readonly int OcclusionMap = Shader.PropertyToID("_OcclusionMap");
private static readonly int ParallaxMap = Shader.PropertyToID("_ParallaxMap");
private static readonly int SmoothnessProp = Shader.PropertyToID("_Smoothness");
private static readonly int SmoothnessTextureChannelProp = Shader.PropertyToID("_SmoothnessTextureChannel");
private static readonly int MetallicProp = Shader.PropertyToID("_Metallic");
private static readonly int MetallicGlossMapProp = Shader.PropertyToID("_MetallicGlossMap");
private static readonly int SpecColorProp = Shader.PropertyToID("_SpecColor");
private static readonly int SpecGlossMapProp = Shader.PropertyToID("_SpecGlossMap");
private static readonly int BumpScaleProp = Shader.PropertyToID("_BumpScale");
private static readonly int BumpMapProp = Shader.PropertyToID("_BumpMap");
private static readonly string SpecularSetupKeyword = "_SPECULAR_SETUP";
private static readonly string MetallicSpecGlossMapKeyword = "_METALLICSPECGLOSSMAP";
private static readonly string SmoothnessTextureAlbedoChannelAKeyword = "_SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A";
private static readonly string NormalMapKeyword = "_NORMALMAP";
private static readonly string EmissionKeyword = "_EMISSION";
private static readonly string OcclusionMapKeyword = "_OCCLUSIONMAP";
private static readonly string ParallaxMapKeyword = "_PARALLAXMAP";
private static readonly int OcclusionStrengthProp = Shader.PropertyToID("_OcclusionStrength");
private static readonly int ParallaxProp = Shader.PropertyToID("_Parallax");
public UrpLitContext(Material material) : base(material)
{
}
public UrpLitWorkflowType WorkflowType
{
get => (UrpLitWorkflowType)Material.GetFloat(WorkflowMode);
set
{
Material.SetFloat(WorkflowMode, (float)value);
if (!UnsafeEditMode) Validate();
}
}
public float Smoothness
{
get => Material.GetFloat(SmoothnessProp);
set => Material.SetFloat(SmoothnessProp, value);
}
public UrpLitSmoothnessMapChannel SmoothnessTextureChannel
{
// NOTE: Float Prop 以外に条件があるので、Keyword から読み取った方が確実
get => Material.IsKeywordEnabled(SmoothnessTextureAlbedoChannelAKeyword) ? UrpLitSmoothnessMapChannel.AlbedoAlpha : UrpLitSmoothnessMapChannel.SpecularMetallicAlpha;
set
{
Material.SetFloat(SmoothnessTextureChannelProp, (float)value);
if (!UnsafeEditMode) Validate();
}
}
public float Metallic
{
// NOTE: Metallic ワークフロー専用
get => Material.GetFloat(MetallicProp);
set => Material.SetFloat(MetallicProp, value);
}
public Texture MetallicGlossMap
{
// NOTE: Metallic ワークフロー専用
get => Material.GetTexture(MetallicGlossMapProp);
set => Material.SetTexture(MetallicGlossMapProp, value);
}
public Color SpecColorSrgb
{
// NOTE: Specular ワークフロー専用
get => Material.GetColor(SpecColorProp);
set => Material.SetColor(SpecColorProp, value);
}
public Texture SpecGlossMap
{
// NOTE: Specular ワークフロー専用
get => Material.GetTexture(SpecGlossMapProp);
set => Material.SetTexture(SpecGlossMapProp, value);
}
public float BumpScale
{
get => Material.GetFloat(BumpScaleProp);
set => Material.SetFloat(BumpScaleProp, value);
}
public Texture BumpMap
{
get => Material.GetTexture(BumpMapProp);
set
{
Material.SetTexture(BumpMapProp, value);
Material.SetKeyword(NormalMapKeyword, value != null);
}
}
public bool IsEmissionEnabled
{
get => Material.IsKeywordEnabled(EmissionKeyword);
set
{
Material.SetKeyword(EmissionKeyword, value);
if (value)
{
Material.globalIlluminationFlags &= ~MaterialGlobalIlluminationFlags.EmissiveIsBlack;
}
else
{
Material.globalIlluminationFlags |= MaterialGlobalIlluminationFlags.EmissiveIsBlack;
}
}
}
public Color EmissionColorLinear
{
get => Material.GetColor(EmissionColor);
set => Material.SetColor(EmissionColor, value);
}
public Texture EmissionTexture
{
get => Material.GetTexture(EmissionMap);
set => Material.SetTexture(EmissionMap, value);
}
public float OcclusionStrength
{
get => Material.GetFloat(OcclusionStrengthProp);
set => Material.SetFloat(OcclusionStrengthProp, value);
}
public Texture OcclusionTexture
{
get => Material.GetTexture(OcclusionMap);
set
{
Material.SetTexture(OcclusionMap, value);
Material.SetKeyword(OcclusionMapKeyword, value != null);
}
}
public float Parallax
{
get => Material.GetFloat(ParallaxProp);
set => Material.SetFloat(ParallaxProp, value);
}
public Texture ParallaxTexture
{
get => Material.GetTexture(ParallaxMap);
set
{
Material.SetTexture(ParallaxMap, value);
Material.SetKeyword(ParallaxMapKeyword, value != null);
}
}
/// <summary>
/// 複数のプロパティに関連して設定されるキーワードやプロパティなどを更新する
/// </summary>
public override void Validate()
{
base.Validate();
// Workflow
var workflowType = (UrpLitWorkflowType)Material.GetFloat(WorkflowMode);
var isSpecularSetup = workflowType == UrpLitWorkflowType.Specular;
Material.SetKeyword(SpecularSetupKeyword, isSpecularSetup);
// GlossMap
var glossMapName = isSpecularSetup ? SpecGlossMapProp : MetallicGlossMapProp;
var hasGlossMap = Material.GetTexture(glossMapName) != null;
Material.SetKeyword(MetallicSpecGlossMapKeyword, hasGlossMap);
// SmoothnessTextureChannel
var isOpaque = SurfaceType == UrpLitSurfaceType.Opaque;
var smoothnessMapChannel = (UrpLitSmoothnessMapChannel)Material.GetFloat(SmoothnessTextureChannelProp);
Material.SetKeyword(SmoothnessTextureAlbedoChannelAKeyword, isOpaque && smoothnessMapChannel == UrpLitSmoothnessMapChannel.AlbedoAlpha);
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: c15ac3fb36ff4e7d8ec271e2cf1fb263
timeCreated: 1722270619

View File

@ -0,0 +1,8 @@
namespace UniGLTF
{
public enum UrpLitSmoothnessMapChannel
{
SpecularMetallicAlpha = 0,
AlbedoAlpha = 1,
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 5669057b7c2d45de9167a335f222c61d
timeCreated: 1722344104

View File

@ -0,0 +1,8 @@
namespace UniGLTF
{
public enum UrpLitSurfaceType
{
Opaque = 0,
Transparent = 1,
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 404bf44062364d41a91735181e6ead33
timeCreated: 1722270974

View File

@ -0,0 +1,8 @@
namespace UniGLTF
{
public enum UrpLitWorkflowType
{
Specular = 0,
Metallic = 1,
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: a76aba2bef494654948abea5eef21fac
timeCreated: 1722271263

View File

@ -0,0 +1,12 @@
using UnityEngine;
namespace UniGLTF
{
public class UrpUnlitContext : UrpBaseShaderContext
{
public UrpUnlitContext(Material material) : base(material)
{
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 3fe15309261045ba937d6a8dafb6a93d
timeCreated: 1722616677

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: f0ed4e9ca99a4447896accb69a065c2e
timeCreated: 1722343812

View File

@ -0,0 +1,19 @@
using UnityEngine;
namespace UniGLTF
{
internal static class InternalMaterialUtils
{
public static void SetKeyword(this Material material, string keyword, bool enabled)
{
if (enabled)
{
material.EnableKeyword(keyword);
}
else
{
material.DisableKeyword(keyword);
}
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: cc1b44f784074898b268882d75b86e23
timeCreated: 1722343798

View File

@ -0,0 +1,9 @@
using UnityEngine;
namespace UniGLTF
{
internal class UniGLTFShaderNotMatchedInternalException : UniGLTFException
{
public UniGLTFShaderNotMatchedInternalException(Shader shader) : base(shader != null ? shader.name : "") { }
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 7857ff1b8d15440f9886f293a747ebb1
timeCreated: 1722617046

View File

@ -4,8 +4,8 @@ namespace UniGLTF
public static partial class PackageVersion
{
public const int MAJOR = 0;
public const int MINOR = 124;
public const int PATCH = 2;
public const string VERSION = "0.124.2";
public const int MINOR = 125;
public const int PATCH = 0;
public const string VERSION = "0.125.0";
}
}

View File

@ -4,8 +4,8 @@ namespace UniGLTF
public static partial class UniGLTFVersion
{
public const int MAJOR = 2;
public const int MINOR = 60;
public const int PATCH = 2;
public const string VERSION = "2.60.2";
public const int MINOR = 61;
public const int PATCH = 0;
public const string VERSION = "2.61.0";
}
}

View File

@ -52,7 +52,9 @@ namespace UniGLTF
}
[System.Diagnostics.Conditional("VRM_DEVELOP")]
#if UNITY_2022_OR_NEWER
[HideInCallstack]
#endif
public static void Log(string msg, UnityEngine.Object context = null) => s_logger.LogFormat(LogType.Log, context, msg);
}
}

View File

@ -31,7 +31,7 @@ namespace UniGLTF.GltfViewer
LoadPathAsync(path);
}
async void LoadPathAsync(VRMShaders.PathObject path)
async void LoadPathAsync(PathObject path)
{
if (_instance)
{

View File

@ -2,10 +2,10 @@ namespace UniGLTF.GltfViewer
{
public static class OpenFileDialog
{
public static VRMShaders.PathObject Show(string title, params string[] extensions)
public static PathObject Show(string title, params string[] extensions)
{
#if UNITY_STANDALONE_WIN
return VRMShaders.PathObject.FromFullPath(FileDialogForWindows.FileDialog(title, extensions));
return PathObject.FromFullPath(FileDialogForWindows.FileDialog(title, extensions));
#else
UnityEngine.Debug.LogWarning("Non-Windows runtime file dialogs are not yet implemented.");
return default;

View File

@ -119,7 +119,11 @@ namespace UniHumanoid
builder.AddLeg(0.1f, 0.3f, 0.4f, 0.1f, 0.1f);
var description = AvatarDescription.Create(builder.Skeleton);
var animator = GetComponentOrThrow<Animator>();
var animator = GetComponent<Animator>();
if (animator == null)
{
throw new System.ArgumentException("no animator");
}
animator.avatar = description.CreateAvatar(root);
// create SkinnedMesh for bone visualize
@ -132,7 +136,8 @@ namespace UniHumanoid
renderer.sharedMaterial = m_material;
//root.gameObject.AddComponent<BoneMapping>();
if (TryGetComponent<HumanPoseTransfer>(out var transfer))
var transfer = GetComponent<HumanPoseTransfer>();
if (transfer != null)
{
transfer.Avatar = animator.avatar;
transfer.Setup();

View File

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

View File

Before

Width:  |  Height:  |  Size: 79 B

After

Width:  |  Height:  |  Size: 79 B

View File

@ -3,7 +3,7 @@ guid: fc1ba24d4a4141d4d9e9ae0a0d3ecd0a
TextureImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 11
serializedVersion: 12
mipmaps:
mipMapMode: 0
enableMipMap: 0
@ -24,6 +24,7 @@ TextureImporter:
streamingMipmaps: 0
streamingMipmapsPriority: 0
vTOnly: 0
ignoreMasterTextureLimit: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
@ -62,6 +63,7 @@ TextureImporter:
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 0
cookieLightType: 1
platformSettings:
- serializedVersion: 3
buildTarget: DefaultTexturePlatform
@ -99,6 +101,18 @@ TextureImporter:
overridden: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: Server
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 0
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites: []
@ -112,6 +126,7 @@ TextureImporter:
edges: []
weights: []
secondaryTextures: []
nameFileIdTable: {}
spritePackingTag:
pSDRemoveMatte: 0
pSDShowRemoveMatteOption: 0

View File

Before

Width:  |  Height:  |  Size: 79 B

After

Width:  |  Height:  |  Size: 79 B

View File

@ -3,7 +3,7 @@ guid: b5d17df8d14f2324692a7c69f24cf658
TextureImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 11
serializedVersion: 12
mipmaps:
mipMapMode: 0
enableMipMap: 1
@ -24,6 +24,7 @@ TextureImporter:
streamingMipmaps: 0
streamingMipmapsPriority: 0
vTOnly: 0
ignoreMasterTextureLimit: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
@ -62,6 +63,7 @@ TextureImporter:
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 0
cookieLightType: 1
platformSettings:
- serializedVersion: 3
buildTarget: DefaultTexturePlatform
@ -99,6 +101,18 @@ TextureImporter:
overridden: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: Server
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 0
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites: []
@ -112,6 +126,7 @@ TextureImporter:
edges: []
weights: []
secondaryTextures: []
nameFileIdTable: {}
spritePackingTag:
pSDRemoveMatte: 0
pSDShowRemoveMatteOption: 0

View File

Before

Width:  |  Height:  |  Size: 79 B

After

Width:  |  Height:  |  Size: 79 B

View File

@ -3,7 +3,7 @@ guid: 0f7acf68f1798ae48a5505519abac457
TextureImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 11
serializedVersion: 12
mipmaps:
mipMapMode: 0
enableMipMap: 0
@ -24,6 +24,7 @@ TextureImporter:
streamingMipmaps: 0
streamingMipmapsPriority: 0
vTOnly: 0
ignoreMasterTextureLimit: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
@ -62,6 +63,7 @@ TextureImporter:
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 0
cookieLightType: 1
platformSettings:
- serializedVersion: 3
buildTarget: DefaultTexturePlatform
@ -99,6 +101,18 @@ TextureImporter:
overridden: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: Server
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 0
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites: []
@ -112,6 +126,7 @@ TextureImporter:
edges: []
weights: []
secondaryTextures: []
nameFileIdTable: {}
spritePackingTag:
pSDRemoveMatte: 0
pSDShowRemoveMatteOption: 0

View File

Before

Width:  |  Height:  |  Size: 560 B

After

Width:  |  Height:  |  Size: 560 B

View File

@ -33,6 +33,8 @@ namespace UniGLTF
var tmp = AssetDatabase.LoadAssetAtPath<Mesh>(assetPath);
Assert.Null(tmp);
AssetDatabase.DeleteAsset(assetPath);
}
AssetDatabase.Refresh();

View File

@ -1,13 +1,10 @@
using NUnit.Framework;
using UnityEditor;
using UnityEngine;
namespace UniGLTF
{
public sealed class CopyTextureTests
{
private static string AssetPath = "Assets/VRMShaders/GLTF/IO/Tests";
private static readonly Color32 Black = new Color32(0, 0, 0, 255);
private static readonly Color32 Gray = new Color32(127, 127, 127, 255);
private static readonly Color32 White = new Color32(255, 255, 255, 255);
@ -32,7 +29,7 @@ namespace UniGLTF
[Test]
public void CopyFromNonReadableSRgbPng()
{
var nonReadableTex = AssetDatabase.LoadAssetAtPath<Texture2D>($"{AssetPath}/4x4_non_readable.png");
var nonReadableTex = TestAssets.LoadAsset<Texture2D>("4x4_non_readable.png");
Assert.False(nonReadableTex.isReadable);
var copiedTex = TextureConverter.CopyTexture(nonReadableTex, ColorSpace.sRGB, true, null);
var pixels = copiedTex.GetPixels32(miplevel: 0);
@ -46,7 +43,7 @@ namespace UniGLTF
[Test]
public void CopyFromNonReadableSRgbDds()
{
var compressedTex = AssetDatabase.LoadAssetAtPath<Texture2D>($"{AssetPath}/4x4_non_readable_compressed.dds");
var compressedTex = TestAssets.LoadAsset<Texture2D>("4x4_non_readable_compressed.dds");
Assert.False(compressedTex.isReadable);
var copiedTex = TextureConverter.CopyTexture(compressedTex, ColorSpace.sRGB, true, null);
var pixels = copiedTex.GetPixels32(miplevel: 0);
@ -60,7 +57,7 @@ namespace UniGLTF
[Test]
public void CopyAttributes()
{
var src = AssetDatabase.LoadAssetAtPath<Texture2D>($"{AssetPath}/4x4_non_readable.png");
var src = TestAssets.LoadAsset<Texture2D>("4x4_non_readable.png");
var dst = TextureConverter.CopyTexture(src, ColorSpace.sRGB, false, null);
Assert.AreEqual(src.name, dst.name);
Assert.AreEqual(src.anisoLevel, dst.anisoLevel);

View File

@ -1,18 +1,16 @@
using NUnit.Framework;
using UnityEditor;
using UnityEngine;
namespace UniGLTF
{
public sealed class EditorTextureSerializerTests
{
private static readonly string AssetPath = "Assets/UniGLTF/Tests/UniGLTF";
private static readonly string SrgbGrayImageName = "4x4_gray_import_as_srgb";
private static readonly string LinearGrayImageName = "4x4_gray_import_as_linear";
private static readonly string NormalMapGrayImageName = "4x4_gray_import_as_normal_map";
private static readonly Texture2D SrgbGrayTex = AssetDatabase.LoadAssetAtPath<Texture2D>($"{AssetPath}/{SrgbGrayImageName}.png");
private static readonly Texture2D LinearGrayTex = AssetDatabase.LoadAssetAtPath<Texture2D>($"{AssetPath}/{LinearGrayImageName}.png");
private static readonly Texture2D NormalMapGrayTex = AssetDatabase.LoadAssetAtPath<Texture2D>($"{AssetPath}/{NormalMapGrayImageName}.png");
private static readonly Texture2D SrgbGrayTex = TestAssets.LoadAsset<Texture2D>($"{SrgbGrayImageName}.png");
private static readonly Texture2D LinearGrayTex = TestAssets.LoadAsset<Texture2D>($"{LinearGrayImageName}.png");
private static readonly Texture2D NormalMapGrayTex = TestAssets.LoadAsset<Texture2D>($"{NormalMapGrayImageName}.png");
private static readonly Color32 JustGray = new Color32(127, 127, 127, 255);
private static readonly Color32 SrgbGrayInSrgb = JustGray;
private static readonly Color32 SrgbGrayInLinear = ((Color)SrgbGrayInSrgb).linear;
@ -113,23 +111,28 @@ namespace UniGLTF
{
// Prepare
var root = GameObject.CreatePrimitive(PrimitiveType.Cube);
var mat = new Material(Shader.Find("Standard"));
var mat = new Material(Shader.Find(BuiltInStandardMaterialExporter.TargetShaderName));
mat.SetTexture(propertyName, srcTex);
root.GetComponentOrThrow<MeshRenderer>().sharedMaterial = mat;
// Export glTF
var data = new ExportingGltfData();
using (var exporter = new gltfExporter(data, new GltfExportSettings
{
InverseAxis = Axes.X,
ExportOnlyBlendShapePosition = false,
UseSparseAccessorForMorphTarget = false,
DivideVertexBuffer = false,
}, textureSerializer: new EditorTextureSerializer()))
{
exporter.Prepare(root);
exporter.Export();
}
using var exporter = new gltfExporter(
data,
new GltfExportSettings
{
InverseAxis = Axes.X,
ExportOnlyBlendShapePosition = false,
UseSparseAccessorForMorphTarget = false,
DivideVertexBuffer = false,
},
materialExporter: new BuiltInGltfMaterialExporter(),
textureSerializer: new EditorTextureSerializer()
);
exporter.Prepare(root);
exporter.Export();
var gltf = data.Gltf;
Assert.AreEqual(1, gltf.images.Count);
var exportedImage = gltf.images[0];

View File

@ -0,0 +1,12 @@
namespace UniGLTF
{
public static class TestAssets
{
public static readonly string AssetPath = "Assets/UniGLTF/Tests/Objects";
public static T LoadAsset<T>(string filename) where T : UnityEngine.Object
{
return UnityEditor.AssetDatabase.LoadAssetAtPath<T>($"{AssetPath}/{filename}");
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 8519ebb2f0f84833a752bb564b59c47c
timeCreated: 1722263712

View File

@ -0,0 +1,52 @@
using UnityEngine;
namespace UniGLTF
{
public static class TestGltf
{
public static RuntimeGltfInstance LoadBytesAsBuiltInRP(byte[] bytes)
{
return GltfUtility.LoadBytesAsync(
"",
bytes,
awaitCaller: new ImmediateCaller(),
materialGenerator: new BuiltInGltfMaterialDescriptorGenerator()
).Result;
}
public static RuntimeGltfInstance LoadPathAsBuiltInRP(string path)
{
return GltfUtility.LoadAsync(
path,
awaitCaller: new ImmediateCaller(),
materialGenerator: new BuiltInGltfMaterialDescriptorGenerator()
).Result;
}
public static ExportingGltfData ExportAsBuiltInRP(GameObject gameObject, GltfExportSettings exportSettings = null)
{
var data = new ExportingGltfData();
using var exporter = new gltfExporter(
data,
exportSettings ?? new GltfExportSettings(),
progress: new EditorProgress(),
animationExporter: new EditorAnimationExporter(),
materialExporter: new BuiltInGltfMaterialExporter(),
textureSerializer: new EditorTextureSerializer()
);
exporter.Prepare(gameObject);
exporter.Export();
return data;
}
public static GameObject CreatePrimitiveAsBuiltInRP(PrimitiveType primitiveType)
{
var go = GameObject.CreatePrimitive(primitiveType);
var shader = Shader.Find("Standard");
var material = new Material(shader);
go.GetComponent<Renderer>().sharedMaterial = material;
return go;
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 11719ab072944cc2b7c0eaafa0cdff2e
timeCreated: 1722267047

View File

@ -1,17 +1,14 @@
using NUnit.Framework;
using UnityEditor;
using UnityEngine;
namespace UniGLTF
{
public class TextureBytesTests
{
static string AssetPath = "Assets/VRMShaders/GLTF/IO/Tests";
[Test]
public void NonReadablePng()
{
var nonReadableTex = AssetDatabase.LoadAssetAtPath<Texture2D>($"{AssetPath}/4x4_non_readable.png");
var nonReadableTex = TestAssets.LoadAsset<Texture2D>("4x4_non_readable.png");
Assert.False(nonReadableTex.isReadable);
var (bytes, mime) = new EditorTextureSerializer().ExportBytesWithMime(nonReadableTex, ColorSpace.sRGB);
Assert.NotNull(bytes);
@ -20,7 +17,7 @@ namespace UniGLTF
[Test]
public void NonReadableDds()
{
var readonlyTexture = AssetDatabase.LoadAssetAtPath<Texture2D>($"{AssetPath}/4x4_non_readable_compressed.dds");
var readonlyTexture = TestAssets.LoadAsset<Texture2D>("4x4_non_readable_compressed.dds");
Assert.False(readonlyTexture.isReadable);
var (bytes, mime) = new EditorTextureSerializer().ExportBytesWithMime(readonlyTexture, ColorSpace.sRGB);
Assert.NotNull(bytes);

View File

@ -100,18 +100,17 @@ namespace UniGLTF
// export
var data = new ExportingGltfData();
using var exporter = new gltfExporter(
data,
new GltfExportSettings(),
materialExporter: new BuiltInGltfMaterialExporter());
exporter.Prepare(go);
exporter.Export();
string json = null;
using (var exporter = new gltfExporter(data, new GltfExportSettings()))
{
exporter.Prepare(go);
exporter.Export();
// remove empty buffer
data.Gltf.buffers.Clear();
// remove empty buffer
data.Gltf.buffers.Clear();
json = data.Gltf.ToJson();
}
var json = data.Gltf.ToJson();
// parse
using (var parsed = GltfData.CreateFromExportForTest(data))
@ -353,12 +352,7 @@ namespace UniGLTF
[Test]
public void GlTFToJsonTest()
{
var data = new ExportingGltfData();
using (var exporter = new gltfExporter(data, new GltfExportSettings()))
{
exporter.Prepare(CreateSimpleScene());
exporter.Export();
}
var data = TestGltf.ExportAsBuiltInRP(CreateSimpleScene());
var expected = data.Gltf.ToJson().ParseAsJson();
expected.AddKey(Utf8String.From("meshes"));
@ -565,7 +559,7 @@ namespace UniGLTF
{
var shader = Shader.Find("Unlit/Color");
var cubeA = GameObject.CreatePrimitive(PrimitiveType.Cube);
var cubeA = TestGltf.CreatePrimitiveAsBuiltInRP(PrimitiveType.Cube);
{
cubeA.transform.SetParent(go.transform);
var material = new Material(shader);
@ -586,16 +580,8 @@ namespace UniGLTF
}
// export
var data = new ExportingGltfData();
var data = TestGltf.ExportAsBuiltInRP(go);
var gltf = data.Gltf;
var json = default(string);
using (var exporter = new gltfExporter(data, new GltfExportSettings()))
{
exporter.Prepare(go);
exporter.Export();
json = gltf.ToJson();
}
Assert.AreEqual(2, gltf.meshes.Count);
@ -658,22 +644,14 @@ namespace UniGLTF
try
{
{
var cube = GameObject.CreatePrimitive(PrimitiveType.Cube);
var cube = TestGltf.CreatePrimitiveAsBuiltInRP(PrimitiveType.Cube);
cube.transform.SetParent(go.transform);
UnityEngine.Object.DestroyImmediate(cube.GetComponent<MeshRenderer>());
}
// export
var data = new ExportingGltfData();
var data = TestGltf.ExportAsBuiltInRP(go);
var gltf = data.Gltf;
string json;
using (var exporter = new gltfExporter(data, new GltfExportSettings()))
{
exporter.Prepare(go);
exporter.Export();
json = gltf.ToJson();
}
Assert.AreEqual(0, gltf.meshes.Count);
Assert.AreEqual(1, gltf.nodes.Count);
@ -682,7 +660,7 @@ namespace UniGLTF
// import
using (var parsed = GltfData.CreateFromExportForTest(data))
{
using (var context = new ImporterContext(parsed))
using (var context = new ImporterContext(parsed, materialGenerator: new BuiltInGltfMaterialDescriptorGenerator()))
using (var loaded = context.Load())
{
Assert.AreEqual(1, loaded.transform.GetChildren().Count());
@ -708,14 +686,14 @@ namespace UniGLTF
try
{
{
var child = GameObject.CreatePrimitive(PrimitiveType.Cube);
var child = TestGltf.CreatePrimitiveAsBuiltInRP(PrimitiveType.Cube);
child.transform.SetParent(root.transform);
// remove MeshFilter
Component.DestroyImmediate(child.GetComponent<MeshFilter>());
}
{
var child = GameObject.CreatePrimitive(PrimitiveType.Cube);
var child = TestGltf.CreatePrimitiveAsBuiltInRP(PrimitiveType.Cube);
child.transform.SetParent(root.transform);
// set null
child.GetComponent<MeshFilter>().sharedMesh = null;
@ -727,16 +705,9 @@ namespace UniGLTF
Assert.True(vs.All(x => x.CanExport));
// export
var data = new ExportingGltfData();
var data = TestGltf.ExportAsBuiltInRP(root);
var gltf = data.Gltf;
string json;
using (var exporter = new gltfExporter(data, new GltfExportSettings()))
{
exporter.Prepare(root);
exporter.Export();
json = gltf.ToJson();
}
var json = gltf.ToJson();
Assert.AreEqual(0, gltf.meshes.Count);
Assert.AreEqual(2, gltf.nodes.Count);
@ -770,6 +741,42 @@ namespace UniGLTF
}
}
//
// https://github.com/vrm-c/UniVRM/pull/2413
//
[Test]
public void ExportingMeshByteLengthTest()
{
var validator = ScriptableObject.CreateInstance<MeshExportValidator>();
var root = new GameObject("root");
try
{
{
var child = TestGltf.CreatePrimitiveAsBuiltInRP(PrimitiveType.Cube);
child.transform.SetParent(root.transform);
}
// export
var data = TestGltf.ExportAsBuiltInRP(root);
var gltf = data.Gltf;
// cube
var expected =
// pos
(4*3)*24
// normal
+(4*3)*24
// uv
+(4*2)*24
// indices
+ 4 * 36;
Assert.AreEqual(expected, gltf.buffers[0].byteLength);
}
finally
{
GameObject.DestroyImmediate(root);
ScriptableObject.DestroyImmediate(validator);
}
}
[Serializable]
class CantConstruct
{

View File

@ -0,0 +1,80 @@
using UnityEngine;
namespace UniGLTF.UniUnlit
{
public class UniUnlitContext
{
public Material Material { get; }
public bool UnsafeEditMode { get; set; } = false;
public UniUnlitContext(Material material)
{
Material = material;
}
public UniUnlitRenderMode RenderMode
{
get => UniUnlitUtil.GetRenderMode(Material);
set
{
UniUnlitUtil.SetRenderMode(Material, value);
if (!UnsafeEditMode) UniUnlitUtil.ValidateProperties(Material, isRenderModeChangedByUser: true);
}
}
public UniUnlitCullMode CullMode
{
get => UniUnlitUtil.GetCullMode(Material);
set
{
UniUnlitUtil.SetCullMode(Material, value);
if (!UnsafeEditMode) UniUnlitUtil.ValidateProperties(Material);
}
}
public UniUnlitVertexColorBlendOp VColBlendMode
{
get => UniUnlitUtil.GetVColBlendMode(Material);
set
{
UniUnlitUtil.SetVColBlendMode(Material, value);
if (!UnsafeEditMode) UniUnlitUtil.ValidateProperties(Material);
}
}
public Color MainColorSrgb
{
get => Material.GetColor(UniUnlitUtil.PropNameColor);
set => Material.SetColor(UniUnlitUtil.PropNameColor, value);
}
public Texture MainTexture
{
get => Material.GetTexture(UniUnlitUtil.PropNameMainTex);
set => Material.SetTexture(UniUnlitUtil.PropNameMainTex, value);
}
public Vector2 MainTextureOffset
{
get => Material.GetTextureOffset(UniUnlitUtil.PropNameMainTex);
set => Material.SetTextureOffset(UniUnlitUtil.PropNameMainTex, value);
}
public Vector2 MainTextureScale
{
get => Material.GetTextureScale(UniUnlitUtil.PropNameMainTex);
set => Material.SetTextureScale(UniUnlitUtil.PropNameMainTex, value);
}
public float Cutoff
{
get => Material.GetFloat(UniUnlitUtil.PropNameCutoff);
set => Material.SetFloat(UniUnlitUtil.PropNameCutoff, value);
}
public void Validate()
{
UniUnlitUtil.ValidateProperties(Material, isRenderModeChangedByUser: true);
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 57963fbf465047bf83ed829f8a0022d3
timeCreated: 1722613449

View File

@ -1,6 +1,6 @@
{
"name": "com.vrmc.gltf",
"version": "0.124.2",
"version": "0.125.0",
"displayName": "UniGLTF",
"description": "GLTF importer and exporter",
"unity": "2021.3",

View File

@ -16,12 +16,17 @@ namespace VRM
/// </summary>
/// <param name="path">出力先</param>
/// <param name="settings">エクスポート設定</param>
public static byte[] Export(GameObject exportRoot, VRMMetaObject meta, VRMExportSettings settings)
public static byte[] Export(
GameObject exportRoot,
VRMMetaObject meta,
VRMExportSettings settings,
IMaterialExporter materialExporter = null
)
{
List<GameObject> destroy = new List<GameObject>();
try
{
return Export(exportRoot, meta, settings, destroy);
return Export(exportRoot, meta, settings, materialExporter, destroy);
}
finally
{
@ -143,9 +148,12 @@ namespace VRM
/// <param name="path"></param>
/// <param name="settings"></param>
/// <param name="destroy">作業が終わったらDestoryするべき一時オブジェクト</param>
static byte[] Export(GameObject exportRoot, VRMMetaObject meta,
VRMExportSettings settings,
List<GameObject> destroy)
private static byte[] Export(
GameObject exportRoot,
VRMMetaObject meta,
VRMExportSettings settings,
IMaterialExporter materialExporter,
List<GameObject> destroy)
{
var target = exportRoot;
@ -227,6 +235,7 @@ namespace VRM
var gltfExportSettings = settings.GltfExportSettings;
using (var exporter = new VRMExporter(data, gltfExportSettings,
animationExporter: settings.KeepAnimation ? new EditorAnimationExporter() : null,
materialExporter: materialExporter,
textureSerializer: new EditorTextureSerializer()))
{
exporter.Prepare(target);

View File

@ -76,10 +76,11 @@ namespace VRM
var map = texturePaths
.Select(x => x.LoadAsset<Texture>())
.ToDictionary(x => new SubAssetKey(x), x => x as UnityEngine.Object);
var settings = new ImporterContextSettings();
// 確実に Dispose するために敢えて再パースしている
using (var data = new GlbFileParser(vrmPath).Parse())
using (var context = new VRMImporterContext(new VRMData(data), externalObjectMap: map, loadAnimation: true))
using (var context = new VRMImporterContext(new VRMData(data), externalObjectMap: map, settings: settings))
{
var editor = new VRMEditorImporterContext(context, prefabPath);
foreach (var textureInfo in context.TextureDescriptorGenerator.Get().GetEnumerable())

View File

@ -41,21 +41,13 @@ namespace VRM
}
// fallback
Debug.LogWarning($"fallback");
return new MaterialDescriptor(
GltfMaterialImportUtils.ImportMaterialName(i, null),
BuiltInGltfPbrMaterialImporter.Shader,
null,
new Dictionary<string, TextureDescriptor>(),
new Dictionary<string, float>(),
new Dictionary<string, Color>(),
new Dictionary<string, Vector4>(),
new Action<Material>[]{});
if (Symbols.VRM_DEVELOP)
{
Debug.LogWarning($"material: {i} out of range. fallback");
}
return GetGltfDefault(GltfMaterialImportUtils.ImportMaterialName(i, null));
}
public MaterialDescriptor GetGltfDefault()
{
return BuiltInGltfDefaultMaterialImporter.CreateParam();
}
public MaterialDescriptor GetGltfDefault(string materialName = null) => BuiltInGltfDefaultMaterialImporter.CreateParam(materialName);
}
}

View File

@ -9,6 +9,9 @@ namespace VRM
{
private readonly glTF_VRM_extensions _vrm;
public UrpGltfPbrMaterialImporter PbrMaterialImporter { get; } = new();
public UrpGltfDefaultMaterialImporter DefaultMaterialImporter { get; } = new();
public UrpVrmMaterialDescriptorGenerator(glTF_VRM_extensions vrm)
{
_vrm = vrm;
@ -20,26 +23,16 @@ namespace VRM
// unlit "UniUnlit" work in URP
if (BuiltInGltfUnlitMaterialImporter.TryCreateParam(data, i, out var matDesc)) return matDesc;
// pbr "Standard" to "Universal Render Pipeline/Lit"
if (UrpGltfPbrMaterialImporter.TryCreateParam(data, i, out matDesc)) return matDesc;
// fallback
if (PbrMaterialImporter.TryCreateParam(data, i, out matDesc)) return matDesc;
// NOTE: Fallback to default material
if (Symbols.VRM_DEVELOP)
{
Debug.LogWarning($"material: {i} out of range. fallback");
}
return new MaterialDescriptor(
GltfMaterialImportUtils.ImportMaterialName(i, null),
UrpGltfPbrMaterialImporter.Shader,
null,
new Dictionary<string, TextureDescriptor>(),
new Dictionary<string, float>(),
new Dictionary<string, Color>(),
new Dictionary<string, Vector4>(),
new Action<Material>[]{});
return GetGltfDefault(GltfMaterialImportUtils.ImportMaterialName(i, null));
}
public MaterialDescriptor GetGltfDefault()
{
return UrpGltfDefaultMaterialImporter.CreateParam();
}
public MaterialDescriptor GetGltfDefault(string materialName = null) => DefaultMaterialImporter.CreateParam(materialName);
}
}

View File

@ -6,7 +6,12 @@ namespace VRM
{
public static IMaterialDescriptorGenerator GetValidVrmMaterialDescriptorGenerator(glTF_VRM_extensions vrm)
{
return RenderPipelineUtility.GetRenderPipelineType() switch
return GetVrmMaterialDescriptorGenerator(vrm, RenderPipelineUtility.GetRenderPipelineType());
}
public static IMaterialDescriptorGenerator GetVrmMaterialDescriptorGenerator(glTF_VRM_extensions vrm, RenderPipelineTypes renderPipelineType)
{
return renderPipelineType switch
{
RenderPipelineTypes.UniversalRenderPipeline => new UrpVrmMaterialDescriptorGenerator(vrm),
RenderPipelineTypes.BuiltinRenderPipeline => new BuiltInVrmMaterialDescriptorGenerator(vrm),

View File

@ -25,12 +25,11 @@ namespace VRM
IReadOnlyDictionary<SubAssetKey, Object> externalObjectMap = null,
ITextureDeserializer textureDeserializer = null,
IMaterialDescriptorGenerator materialGenerator = null,
bool loadAnimation = false)
: base(data.Data, externalObjectMap, textureDeserializer, materialGenerator ?? VrmMaterialDescriptorGeneratorUtility.GetValidVrmMaterialDescriptorGenerator(data.VrmExtension))
ImporterContextSettings settings = null)
: base(data.Data, externalObjectMap, textureDeserializer, materialGenerator ?? VrmMaterialDescriptorGeneratorUtility.GetValidVrmMaterialDescriptorGenerator(data.VrmExtension), settings ?? new ImporterContextSettings(false))
{
_data = data;
TextureDescriptorGenerator = new VrmTextureDescriptorGenerator(Data, VRM);
LoadAnimation = loadAnimation;
}
#region OnLoad

View File

@ -39,11 +39,12 @@ namespace VRM
{
materialGen = materialGeneratorCallback(vrm.VrmExtension);
}
var importerContextSettings = new ImporterContextSettings(loadAnimation);
using (var loader = new VRMImporterContext(
vrm,
textureDeserializer: textureDeserializer,
materialGenerator: materialGen,
loadAnimation: loadAnimation))
settings: importerContextSettings))
{
if (metaCallback != null)
{
@ -96,11 +97,12 @@ namespace VRM
{
materialGen = materialGeneratorCallback(vrm.VrmExtension);
}
var importerContextSettings = new ImporterContextSettings(loadAnimation: loadAnimation);
using (var loader = new VRMImporterContext(
vrm,
textureDeserializer: textureDeserializer,
materialGenerator: materialGen,
loadAnimation: loadAnimation))
settings: importerContextSettings))
{
if (metaCallback != null)
{

View File

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

View File

@ -0,0 +1,12 @@
using System.Collections.Generic;
using UnityEngine;
namespace VRM.SpringBone
{
struct SceneInfo
{
public IReadOnlyList<Transform> RootBones;
public Transform Center;
public VRMSpringBoneColliderGroup[] ColliderGroups;
}
}

View File

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

View File

@ -0,0 +1,18 @@
using UnityEngine;
namespace VRM.SpringBone
{
struct SphereCollider
{
public readonly Vector3 Position;
public readonly float Radius;
public SphereCollider(Transform transform, VRMSpringBoneColliderGroup.SphereCollider collider)
{
Position = transform.TransformPoint(collider.Offset);
var ls = transform.lossyScale;
var scale = Mathf.Max(Mathf.Max(ls.x, ls.y), ls.z);
Radius = scale * collider.Radius;
}
}
}

View File

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

View File

@ -0,0 +1,129 @@
using System.Collections.Generic;
using UnityEngine;
namespace VRM.SpringBone
{
/// <summary>
/// original from
/// http://rocketjump.skr.jp/unity3d/109/
/// </summary>
class SpringBoneJoint
{
Transform m_transform;
public Transform Head => m_transform;
private Vector3 m_boneAxis;
private Vector3 m_currentTail;
private readonly float m_length;
private Vector3 m_localDir;
private Vector3 m_prevTail;
public SpringBoneJoint(Transform center, Transform transform, Vector3 localChildPosition)
{
m_transform = transform;
var worldChildPosition = m_transform.TransformPoint(localChildPosition);
m_currentTail = center != null
? center.InverseTransformPoint(worldChildPosition)
: worldChildPosition;
m_prevTail = m_currentTail;
LocalRotation = transform.localRotation;
m_boneAxis = localChildPosition.normalized;
m_length = localChildPosition.magnitude;
}
public Vector3 Tail => m_transform.localToWorldMatrix.MultiplyPoint(m_boneAxis * m_length);
private Quaternion LocalRotation { get; }
float m_radius;
public void SetRadius(float radius)
{
m_radius = radius * m_transform.UniformedLossyScale();
}
private Quaternion ParentRotation =>
m_transform.parent != null
? m_transform.parent.rotation
: Quaternion.identity;
public void Update(Transform center,
float stiffnessForce, float dragForce, Vector3 external,
List<SphereCollider> colliders)
{
var currentTail = center != null
? center.TransformPoint(m_currentTail)
: m_currentTail;
var prevTail = center != null
? center.TransformPoint(m_prevTail)
: m_prevTail;
// verlet積分で次の位置を計算
var nextTail = currentTail
+ (currentTail - prevTail) * (1.0f - dragForce) // 前フレームの移動を継続する(減衰もあるよ)
+ ParentRotation * LocalRotation * m_boneAxis * stiffnessForce // 親の回転による子ボーンの移動目標
+ external; // 外力による移動量
// 長さをboneLengthに強制
var position = m_transform.position;
nextTail = position + (nextTail - position).normalized * m_length;
// Collisionで移動
nextTail = Collision(colliders, nextTail);
m_prevTail = center != null
? center.InverseTransformPoint(currentTail)
: currentTail;
m_currentTail = center != null
? center.InverseTransformPoint(nextTail)
: nextTail;
//回転を適用
m_transform.rotation = ApplyRotation(nextTail);
}
protected virtual Quaternion ApplyRotation(Vector3 nextTail)
{
var rotation = ParentRotation * LocalRotation;
return Quaternion.FromToRotation(rotation * m_boneAxis,
nextTail - m_transform.position) * rotation;
}
protected virtual Vector3 Collision(List<SpringBone.SphereCollider> colliders, Vector3 nextTail)
{
foreach (var collider in colliders)
{
var r = m_radius + collider.Radius;
if (Vector3.SqrMagnitude(nextTail - collider.Position) <= (r * r))
{
// ヒット。Colliderの半径方向に押し出す
var normal = (nextTail - collider.Position).normalized;
var posFromCollider = collider.Position + normal * (m_radius + collider.Radius);
// 長さをboneLengthに強制
nextTail = m_transform.position + (posFromCollider - m_transform.position).normalized * m_length;
}
}
return nextTail;
}
public void DrawGizmo(Transform center, Color color)
{
var currentTail = center != null
? center.TransformPoint(m_currentTail)
: m_currentTail;
var prevTail = center != null
? center.TransformPoint(m_prevTail)
: m_prevTail;
Gizmos.color = Color.gray;
Gizmos.DrawLine(currentTail, prevTail);
Gizmos.DrawWireSphere(prevTail, m_radius);
Gizmos.color = color;
Gizmos.DrawLine(currentTail, m_transform.position);
Gizmos.DrawWireSphere(currentTail, m_radius);
}
}
}

View File

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

View File

@ -0,0 +1,13 @@
using UnityEngine;
namespace VRM.SpringBone
{
struct SpringBoneSettings
{
public float StiffnessForce;
public Vector3 GravityDir;
public float GravityPower;
public float HitRadius;
public float DragForce;
}
}

View File

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

Some files were not shown because too many files have changed in this diff Show More