mirror of
https://github.com/vrm-c/UniVRM.git
synced 2026-08-23 11:05:29 -05:00
MaterialImportParam
This commit is contained in:
@@ -36,6 +36,8 @@ namespace UniGLTF
|
||||
MaterialFactory m_materialFactory;
|
||||
public MaterialFactory MaterialFactory => m_materialFactory;
|
||||
|
||||
public readonly GltfMaterialImporter GltfMaterialImporter = new GltfMaterialImporter();
|
||||
|
||||
TextureFactory m_textureFactory;
|
||||
public TextureFactory TextureFactory => m_textureFactory;
|
||||
|
||||
@@ -46,7 +48,7 @@ namespace UniGLTF
|
||||
{
|
||||
m_parser = parser;
|
||||
m_textureFactory = new TextureFactory(externalObjectMap);
|
||||
m_materialFactory = new MaterialFactory(m_parser, externalObjectMap);
|
||||
m_materialFactory = new MaterialFactory(externalObjectMap);
|
||||
}
|
||||
|
||||
#region Source
|
||||
@@ -111,7 +113,7 @@ namespace UniGLTF
|
||||
|
||||
using (MeasureTime("LoadMaterials"))
|
||||
{
|
||||
await m_materialFactory.LoadMaterialsAsync(m_awaitCaller, m_textureFactory.GetTextureAsync);
|
||||
await LoadMaterialsAsync();
|
||||
}
|
||||
|
||||
var meshImporter = new MeshImporter();
|
||||
@@ -171,6 +173,24 @@ namespace UniGLTF
|
||||
await OnLoadModel(m_awaitCaller, MeasureTime);
|
||||
}
|
||||
|
||||
public async Task LoadMaterialsAsync()
|
||||
{
|
||||
if (m_parser.GLTF.materials == null || m_parser.GLTF.materials.Count == 0)
|
||||
{
|
||||
// no material. work around.
|
||||
var param = GltfMaterialImporter.CreateParam(m_parser, 0);
|
||||
var material = await MaterialFactory.LoadAsync(param, TextureFactory.GetTextureAsync);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < m_parser.GLTF.materials.Count; ++i)
|
||||
{
|
||||
var param = GltfMaterialImporter.CreateParam(m_parser, i);
|
||||
var material = await MaterialFactory.LoadAsync(param, TextureFactory.GetTextureAsync);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual Task OnLoadModel(IAwaitCaller awaitCaller, Func<string, IDisposable> MeasureTime)
|
||||
{
|
||||
// do nothing
|
||||
|
||||
@@ -0,0 +1,99 @@
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using VRMShaders;
|
||||
|
||||
|
||||
namespace UniGLTF
|
||||
{
|
||||
public delegate bool TryCreateMaterialParamFromGltf(GltfParser parser, int i, out MaterialImportParam param);
|
||||
|
||||
public class GltfMaterialImporter
|
||||
{
|
||||
/// <summary>
|
||||
/// gltfMaterialを解釈する関数。
|
||||
/// 拡張するには、先頭に挿入するべし。
|
||||
/// </summary>
|
||||
/// <typeparam name="TryCreateMaterialParamFromGltf"></typeparam>
|
||||
/// <returns></returns>
|
||||
public readonly List<TryCreateMaterialParamFromGltf> GltfMaterialParamProcessors = new List<TryCreateMaterialParamFromGltf>();
|
||||
|
||||
public GltfMaterialImporter()
|
||||
{
|
||||
// unlit を試し
|
||||
GltfMaterialParamProcessors.Add(GltfUnlitMaterial.TryCreateParam);
|
||||
// PBR を作成する(失敗しない)
|
||||
GltfMaterialParamProcessors.Add(GltfPBRMaterial.TryCreateParam);
|
||||
}
|
||||
|
||||
public static string MaterialName(int index, glTFMaterial src)
|
||||
{
|
||||
if (src != null && !string.IsNullOrEmpty(src.name))
|
||||
{
|
||||
return src.name;
|
||||
}
|
||||
return $"material_{index:00}";
|
||||
}
|
||||
|
||||
public MaterialImportParam CreateParam(GltfParser parser, int i)
|
||||
{
|
||||
foreach (var tryCreate in GltfMaterialParamProcessors)
|
||||
{
|
||||
if (tryCreate(parser, i, out MaterialImportParam param))
|
||||
{
|
||||
return param;
|
||||
}
|
||||
}
|
||||
|
||||
// fallback
|
||||
#if VRM_DEVELOP
|
||||
Debug.LogWarning($"material: {i} out of range. fallback");
|
||||
#endif
|
||||
return new MaterialImportParam(MaterialName(i, null), GltfPBRMaterial.ShaderName);
|
||||
}
|
||||
|
||||
public static (Vector2, Vector2) GetTextureOffsetAndScale(glTFTextureInfo textureInfo)
|
||||
{
|
||||
Vector2 offset = new Vector2(0, 0);
|
||||
Vector2 scale = new Vector2(1, 1);
|
||||
if (glTF_KHR_texture_transform.TryGet(textureInfo, out glTF_KHR_texture_transform textureTransform))
|
||||
{
|
||||
if (textureTransform.offset != null && textureTransform.offset.Length == 2)
|
||||
{
|
||||
offset = new Vector2(textureTransform.offset[0], textureTransform.offset[1]);
|
||||
}
|
||||
if (textureTransform.scale != null && textureTransform.scale.Length == 2)
|
||||
{
|
||||
scale = new Vector2(textureTransform.scale[0], textureTransform.scale[1]);
|
||||
}
|
||||
|
||||
offset.y = (offset.y + scale.y - 1.0f) * -1.0f;
|
||||
}
|
||||
return (offset, scale);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// for unittest
|
||||
/// </summary>
|
||||
public static glTF CreateMaterialForTest(glTFMaterial material)
|
||||
{
|
||||
return new glTF
|
||||
{
|
||||
materials = new System.Collections.Generic.List<glTFMaterial> {
|
||||
material
|
||||
},
|
||||
textures = new List<glTFTexture>{
|
||||
new glTFTexture{
|
||||
name = "texture_0"
|
||||
}
|
||||
},
|
||||
images = new List<glTFImage>{
|
||||
new glTFImage{
|
||||
name = "image_0",
|
||||
mimeType = "image/png",
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 14bc3a4ce3e24924a9ae8bb1654a1b7b
|
||||
guid: 06d7ddbd9b8b38544a74013a6992210b
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
213
Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/GltfPBRMaterial.cs
Normal file
213
Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/GltfPBRMaterial.cs
Normal file
@@ -0,0 +1,213 @@
|
||||
using System.Threading.Tasks;
|
||||
using UnityEngine;
|
||||
using VRMShaders;
|
||||
|
||||
|
||||
namespace UniGLTF
|
||||
{
|
||||
/// <summary>
|
||||
/// Gltf から MaterialImportParam に変換する
|
||||
///
|
||||
/// 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
|
||||
///
|
||||
/// </summary>
|
||||
public static class GltfPBRMaterial
|
||||
{
|
||||
public const string ShaderName = "Standard";
|
||||
|
||||
private enum BlendMode
|
||||
{
|
||||
Opaque,
|
||||
Cutout,
|
||||
Fade,
|
||||
Transparent
|
||||
}
|
||||
|
||||
public static TextureImportParam BaseColorTexture(GltfParser parser, glTFMaterial src)
|
||||
{
|
||||
var (offset, scale) = GltfMaterialImporter.GetTextureOffsetAndScale(src.pbrMetallicRoughness.baseColorTexture);
|
||||
return GltfTextureImporter.CreateSRGB(parser, src.pbrMetallicRoughness.baseColorTexture.index, offset, scale);
|
||||
}
|
||||
|
||||
public static TextureImportParam StandardTexture(GltfParser parser, glTFMaterial src)
|
||||
{
|
||||
var metallicFactor = 1.0f;
|
||||
var roughnessFactor = 1.0f;
|
||||
if (src.pbrMetallicRoughness != null)
|
||||
{
|
||||
metallicFactor = src.pbrMetallicRoughness.metallicFactor;
|
||||
roughnessFactor = src.pbrMetallicRoughness.roughnessFactor;
|
||||
}
|
||||
var (offset, scale) = GltfMaterialImporter.GetTextureOffsetAndScale(src.pbrMetallicRoughness.metallicRoughnessTexture);
|
||||
return GltfTextureImporter.CreateStandard(parser,
|
||||
src.pbrMetallicRoughness?.metallicRoughnessTexture?.index,
|
||||
src.occlusionTexture?.index,
|
||||
offset, scale,
|
||||
metallicFactor,
|
||||
roughnessFactor);
|
||||
}
|
||||
|
||||
public static TextureImportParam NormalTexture(GltfParser parser, glTFMaterial src)
|
||||
{
|
||||
var (offset, scale) = GltfMaterialImporter.GetTextureOffsetAndScale(src.normalTexture);
|
||||
return GltfTextureImporter.CreateNormal(parser, src.normalTexture.index, offset, scale);
|
||||
}
|
||||
|
||||
public static bool TryCreateParam(GltfParser parser, int i, out MaterialImportParam param)
|
||||
{
|
||||
if (i < 0 || i >= parser.GLTF.materials.Count)
|
||||
{
|
||||
param = default;
|
||||
return false;
|
||||
}
|
||||
|
||||
var src = parser.GLTF.materials[i];
|
||||
param = new MaterialImportParam(GltfMaterialImporter.MaterialName(i, src), ShaderName);
|
||||
|
||||
var standardParam = default(TextureImportParam);
|
||||
if (src.pbrMetallicRoughness != null || src.occlusionTexture != null)
|
||||
{
|
||||
if (src.pbrMetallicRoughness.metallicRoughnessTexture != null || src.occlusionTexture != null)
|
||||
{
|
||||
standardParam = StandardTexture(parser, src);
|
||||
}
|
||||
|
||||
if (src.pbrMetallicRoughness.baseColorFactor != null && src.pbrMetallicRoughness.baseColorFactor.Length == 4)
|
||||
{
|
||||
var color = src.pbrMetallicRoughness.baseColorFactor;
|
||||
param.Colors.Add("_Color", (new Color(color[0], color[1], color[2], color[3])).gamma);
|
||||
}
|
||||
|
||||
if (src.pbrMetallicRoughness.baseColorTexture != null && src.pbrMetallicRoughness.baseColorTexture.index != -1)
|
||||
{
|
||||
var textureParam = BaseColorTexture(parser, src);
|
||||
param.TextureSlots.Add("_MainTex", textureParam);
|
||||
}
|
||||
|
||||
if (src.pbrMetallicRoughness.metallicRoughnessTexture != null && src.pbrMetallicRoughness.metallicRoughnessTexture.index != -1)
|
||||
{
|
||||
param.Actions.Add(material => material.EnableKeyword("_METALLICGLOSSMAP"));
|
||||
param.TextureSlots.Add("_MetallicGlossMap", standardParam);
|
||||
// Set 1.0f as hard-coded. See: https://github.com/dwango/UniVRM/issues/212.
|
||||
param.FloatValues.Add("_Metallic", 1.0f);
|
||||
param.FloatValues.Add("_GlossMapScale", 1.0f);
|
||||
}
|
||||
else
|
||||
{
|
||||
param.FloatValues.Add("_Metallic", src.pbrMetallicRoughness.metallicFactor);
|
||||
param.FloatValues.Add("_Glossiness", 1.0f - src.pbrMetallicRoughness.roughnessFactor);
|
||||
}
|
||||
}
|
||||
|
||||
if (src.normalTexture != null && src.normalTexture.index != -1)
|
||||
{
|
||||
param.Actions.Add(material => material.EnableKeyword("_NORMALMAP"));
|
||||
var textureParam = NormalTexture(parser, src);
|
||||
param.TextureSlots.Add("_BumpMap", textureParam);
|
||||
param.FloatValues.Add("_BumpScale", src.normalTexture.scale);
|
||||
}
|
||||
|
||||
if (src.occlusionTexture != null && src.occlusionTexture.index != -1)
|
||||
{
|
||||
param.TextureSlots.Add("_OcclusionMap", standardParam);
|
||||
param.FloatValues.Add("_OcclusionStrength", src.occlusionTexture.strength);
|
||||
}
|
||||
|
||||
if (src.emissiveFactor != null
|
||||
|| (src.emissiveTexture != null && src.emissiveTexture.index != -1))
|
||||
{
|
||||
param.Actions.Add(material => {
|
||||
material.EnableKeyword("_EMISSION");
|
||||
material.globalIlluminationFlags &= ~MaterialGlobalIlluminationFlags.EmissiveIsBlack;
|
||||
});
|
||||
|
||||
if (src.emissiveFactor != null && src.emissiveFactor.Length == 3)
|
||||
{
|
||||
param.Colors.Add("_EmissionColor", new Color(src.emissiveFactor[0], src.emissiveFactor[1], src.emissiveFactor[2]));
|
||||
}
|
||||
|
||||
if (src.emissiveTexture != null && src.emissiveTexture.index != -1)
|
||||
{
|
||||
var (offset, scale) = GltfMaterialImporter.GetTextureOffsetAndScale(src.emissiveTexture);
|
||||
var textureParam = GltfTextureImporter.CreateSRGB(parser, src.emissiveTexture.index, offset, scale);
|
||||
param.TextureSlots.Add("_EmissionMap", textureParam);
|
||||
}
|
||||
}
|
||||
|
||||
param.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);
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -42,7 +42,7 @@ namespace UniGLTF
|
||||
// base color
|
||||
if (m.pbrMetallicRoughness?.baseColorTexture != null)
|
||||
{
|
||||
yield return PBRMaterialItem.BaseColorTexture(parser, m);
|
||||
yield return GltfPBRMaterial.BaseColorTexture(parser, m);
|
||||
}
|
||||
|
||||
// metallic roughness
|
||||
@@ -55,14 +55,14 @@ namespace UniGLTF
|
||||
// emission
|
||||
if (m.emissiveTexture != null)
|
||||
{
|
||||
var (offset, scale) = MaterialFactory.GetTextureOffsetAndScale(m.emissiveTexture);
|
||||
var (offset, scale) = GltfMaterialImporter.GetTextureOffsetAndScale(m.emissiveTexture);
|
||||
yield return GltfTextureImporter.CreateSRGB(parser, m.emissiveTexture.index, offset, scale);
|
||||
}
|
||||
|
||||
// normal
|
||||
if (m.normalTexture != null)
|
||||
{
|
||||
yield return PBRMaterialItem.NormalTexture(parser, m);
|
||||
yield return GltfPBRMaterial.NormalTexture(parser, m);
|
||||
}
|
||||
|
||||
// occlusion
|
||||
@@ -75,7 +75,7 @@ namespace UniGLTF
|
||||
// metallicSmooth and occlusion
|
||||
if (metallicRoughnessTexture.HasValue || occlusionTexture.HasValue)
|
||||
{
|
||||
yield return PBRMaterialItem.StandardTexture(parser, m);
|
||||
yield return GltfPBRMaterial.StandardTexture(parser, m);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,88 @@
|
||||
using UnityEngine;
|
||||
using VRMShaders;
|
||||
|
||||
|
||||
namespace UniGLTF
|
||||
{
|
||||
public static class GltfUnlitMaterial
|
||||
{
|
||||
public const string ShaderName = "UniGLTF/UniUnlit";
|
||||
|
||||
public static bool TryCreateParam(GltfParser parser, int i, out MaterialImportParam param)
|
||||
{
|
||||
if (i < 0 || i >= parser.GLTF.materials.Count)
|
||||
{
|
||||
param = default;
|
||||
return false;
|
||||
}
|
||||
|
||||
var src = parser.GLTF.materials[i];
|
||||
if (!glTF_KHR_materials_unlit.IsEnable(src))
|
||||
{
|
||||
param = default;
|
||||
return false;
|
||||
}
|
||||
|
||||
param = new MaterialImportParam(GltfMaterialImporter.MaterialName(i, src), ShaderName);
|
||||
|
||||
// texture
|
||||
if (src.pbrMetallicRoughness.baseColorTexture != null)
|
||||
{
|
||||
var (offset, scale) = GltfMaterialImporter.GetTextureOffsetAndScale(src.pbrMetallicRoughness.baseColorTexture);
|
||||
var textureParam = GltfTextureImporter.CreateSRGB(parser, src.pbrMetallicRoughness.baseColorTexture.index, offset, scale);
|
||||
param.TextureSlots.Add("_MainTex", textureParam);
|
||||
}
|
||||
|
||||
// color
|
||||
if (src.pbrMetallicRoughness.baseColorFactor != null && src.pbrMetallicRoughness.baseColorFactor.Length == 4)
|
||||
{
|
||||
var color = src.pbrMetallicRoughness.baseColorFactor;
|
||||
param.Colors.Add("_Color", (new Color(color[0], color[1], color[2], color[3])).gamma);
|
||||
}
|
||||
|
||||
//renderMode
|
||||
param.Actions.Add(material =>
|
||||
{
|
||||
if (src.alphaMode == "OPAQUE")
|
||||
{
|
||||
UniUnlit.Utils.SetRenderMode(material, UniUnlit.UniUnlitRenderMode.Opaque);
|
||||
}
|
||||
else if (src.alphaMode == "BLEND")
|
||||
{
|
||||
UniUnlit.Utils.SetRenderMode(material, UniUnlit.UniUnlitRenderMode.Transparent);
|
||||
}
|
||||
else if (src.alphaMode == "MASK")
|
||||
{
|
||||
UniUnlit.Utils.SetRenderMode(material, UniUnlit.UniUnlitRenderMode.Cutout);
|
||||
material.SetFloat("_Cutoff", src.alphaCutoff);
|
||||
}
|
||||
else
|
||||
{
|
||||
// default OPAQUE
|
||||
UniUnlit.Utils.SetRenderMode(material, UniUnlit.UniUnlitRenderMode.Opaque);
|
||||
}
|
||||
|
||||
// culling
|
||||
if (src.doubleSided)
|
||||
{
|
||||
UniUnlit.Utils.SetCullMode(material, UniUnlit.UniUnlitCullMode.Off);
|
||||
}
|
||||
else
|
||||
{
|
||||
UniUnlit.Utils.SetCullMode(material, UniUnlit.UniUnlitCullMode.Back);
|
||||
}
|
||||
|
||||
// VColor
|
||||
var hasVertexColor = parser.GLTF.MaterialHasVertexColor(i);
|
||||
if (hasVertexColor)
|
||||
{
|
||||
UniUnlit.Utils.SetVColBlendMode(material, UniUnlit.UniUnlitVertexColorBlendOp.Multiply);
|
||||
}
|
||||
|
||||
UniUnlit.Utils.ValidateProperties(material, true);
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 77db57076c0650c469c3ff0d4853ce21
|
||||
timeCreated: 1533624711
|
||||
licenseType: Free
|
||||
guid: f9748317ec6964a47b0a1c4150fe62e8
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
@@ -1,246 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using UnityEngine;
|
||||
|
||||
namespace UniGLTF
|
||||
{
|
||||
public class MaterialFactory : IDisposable
|
||||
{
|
||||
GltfParser m_parser;
|
||||
Dictionary<string, Material> m_externalMap;
|
||||
public bool TryGetExternal(int index, out Material external)
|
||||
{
|
||||
if (m_externalMap != null)
|
||||
{
|
||||
var gltfMaterial = m_parser.GLTF.materials[index];
|
||||
if (m_externalMap.TryGetValue(gltfMaterial.name, out external))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
external = default;
|
||||
return false;
|
||||
}
|
||||
|
||||
public MaterialFactory(GltfParser parser, IEnumerable<(string, UnityEngine.Object)> externalMap)
|
||||
{
|
||||
m_parser = parser;
|
||||
if (externalMap != null)
|
||||
{
|
||||
m_externalMap = externalMap
|
||||
.Select(kv => (kv.Item1, kv.Item2 as Material))
|
||||
.Where(kv => kv.Item2 != null)
|
||||
.ToDictionary(kv => kv.Item1, kv => kv.Item2)
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
public delegate Task<Material> CreateMaterialAsyncFunc(IAwaitCaller awaitCaller, GltfParser parser, int i, GetTextureAsyncFunc getTexture);
|
||||
CreateMaterialAsyncFunc m_createMaterialAsync;
|
||||
public CreateMaterialAsyncFunc CreateMaterialAsync
|
||||
{
|
||||
set
|
||||
{
|
||||
m_createMaterialAsync = value;
|
||||
}
|
||||
get
|
||||
{
|
||||
if (m_createMaterialAsync == null)
|
||||
{
|
||||
m_createMaterialAsync = MaterialFactory.DefaultCreateMaterialAsync;
|
||||
}
|
||||
return m_createMaterialAsync;
|
||||
}
|
||||
}
|
||||
|
||||
public struct MaterialLoadInfo
|
||||
{
|
||||
public readonly Material Asset;
|
||||
public readonly bool UseExternal;
|
||||
|
||||
public bool IsSubAsset => !UseExternal;
|
||||
|
||||
public MaterialLoadInfo(Material asset, bool useExternal)
|
||||
{
|
||||
Asset = asset;
|
||||
UseExternal = useExternal;
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
if (!x.UseExternal)
|
||||
{
|
||||
// 外部の '.asset' からロードしていない
|
||||
#if VRM_DEVELOP
|
||||
// Debug.Log($"Destroy {x.Asset}");
|
||||
#endif
|
||||
UnityEngine.Object.DestroyImmediate(x.Asset, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 所有権(Dispose権)を移譲する
|
||||
///
|
||||
/// 所有権を移動する関数。
|
||||
///
|
||||
/// * 所有権が移動する。return true => ImporterContext.Dispose の対象から外れる
|
||||
/// * 所有権が移動しない。return false => Importer.Context.Dispose でDestroyされる
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="take"></param>
|
||||
public void TransferOwnership(Func<UnityEngine.Object, bool> take)
|
||||
{
|
||||
var list = new List<Material>();
|
||||
foreach (var x in m_materials)
|
||||
{
|
||||
if (!x.UseExternal)
|
||||
{
|
||||
// 外部の '.asset' からロードしていない
|
||||
if (take(x.Asset))
|
||||
{
|
||||
list.Add(x.Asset);
|
||||
}
|
||||
}
|
||||
}
|
||||
foreach (var x in list)
|
||||
{
|
||||
Remove(x);
|
||||
}
|
||||
}
|
||||
|
||||
public Material GetMaterial(int index)
|
||||
{
|
||||
if (index < 0) return null;
|
||||
if (index >= m_materials.Count) return null;
|
||||
return m_materials[index].Asset;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// テクスチャ生成
|
||||
/// </summary>
|
||||
/// <param name="getTexture"></param>
|
||||
/// <returns></returns>
|
||||
public async Task LoadMaterialsAsync(IAwaitCaller awaitCaller, GetTextureAsyncFunc getTexture)
|
||||
{
|
||||
if (m_parser.GLTF.materials == null || m_parser.GLTF.materials.Count == 0)
|
||||
{
|
||||
// no material. work around.
|
||||
var material = await CreateMaterialAsync(awaitCaller, m_parser, 0, getTexture);
|
||||
m_materials.Add(new MaterialLoadInfo(material, false));
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < m_parser.GLTF.materials.Count; ++i)
|
||||
{
|
||||
if (TryGetExternal(i, out Material material))
|
||||
{
|
||||
m_materials.Add(new MaterialLoadInfo(material, true));
|
||||
continue;
|
||||
}
|
||||
|
||||
material = await CreateMaterialAsync(awaitCaller, m_parser, i, getTexture);
|
||||
m_materials.Add(new MaterialLoadInfo(material, false));
|
||||
}
|
||||
}
|
||||
|
||||
public static string MaterialName(int index, glTFMaterial src)
|
||||
{
|
||||
if(src!=null && !string.IsNullOrEmpty(src.name))
|
||||
{
|
||||
return src.name;
|
||||
}
|
||||
return $"material_{index:00}";
|
||||
}
|
||||
|
||||
public static (Vector2, Vector2) GetTextureOffsetAndScale(glTFTextureInfo textureInfo)
|
||||
{
|
||||
Vector2 offset = new Vector2(0, 0);
|
||||
Vector2 scale = new Vector2(1, 1);
|
||||
if (glTF_KHR_texture_transform.TryGet(textureInfo, out glTF_KHR_texture_transform textureTransform))
|
||||
{
|
||||
if (textureTransform.offset != null && textureTransform.offset.Length == 2)
|
||||
{
|
||||
offset = new Vector2(textureTransform.offset[0], textureTransform.offset[1]);
|
||||
}
|
||||
if (textureTransform.scale != null && textureTransform.scale.Length == 2)
|
||||
{
|
||||
scale = new Vector2(textureTransform.scale[0], textureTransform.scale[1]);
|
||||
}
|
||||
|
||||
offset.y = (offset.y + scale.y - 1.0f) * -1.0f;
|
||||
}
|
||||
return (offset, scale);
|
||||
}
|
||||
|
||||
public static void SetTextureOffsetAndScale(Material material, string propertyName, Vector2 offset, Vector2 scale)
|
||||
{
|
||||
material.SetTextureOffset(propertyName, offset);
|
||||
material.SetTextureScale(propertyName, scale);
|
||||
}
|
||||
|
||||
public static Task<Material> DefaultCreateMaterialAsync(IAwaitCaller awaitCaller, GltfParser parser, int i, GetTextureAsyncFunc getTexture)
|
||||
{
|
||||
if (i < 0 || i >= parser.GLTF.materials.Count)
|
||||
{
|
||||
UnityEngine.Debug.LogWarning("glTFMaterial is empty");
|
||||
return PBRMaterialItem.CreateAsync(awaitCaller, parser, i, getTexture);
|
||||
}
|
||||
var x = parser.GLTF.materials[i];
|
||||
|
||||
if (glTF_KHR_materials_unlit.IsEnable(x))
|
||||
{
|
||||
var hasVertexColor = parser.GLTF.MaterialHasVertexColor(i);
|
||||
return UnlitMaterialItem.CreateAsync(awaitCaller, parser, i, getTexture, hasVertexColor);
|
||||
}
|
||||
|
||||
return PBRMaterialItem.CreateAsync(awaitCaller, parser, i, getTexture);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// for unittest
|
||||
/// </summary>
|
||||
/// <param name="i"></param>
|
||||
/// <param name="material"></param>
|
||||
/// <param name="getTexture"></param>
|
||||
/// <returns></returns>
|
||||
public static Material CreateMaterialForTest(int i, glTFMaterial material)
|
||||
{
|
||||
var gltf = new glTF
|
||||
{
|
||||
materials = new System.Collections.Generic.List<glTFMaterial> { material },
|
||||
textures = new List<glTFTexture>{
|
||||
new glTFTexture{
|
||||
name = "texture_0"
|
||||
}
|
||||
},
|
||||
images = new List<glTFImage>{
|
||||
new glTFImage{
|
||||
name = "image_0",
|
||||
mimeType = "image/png",
|
||||
}
|
||||
},
|
||||
};
|
||||
var task = DefaultCreateMaterialAsync(default(ImmediateCaller), new GltfParser{GLTF = gltf}, i, null);
|
||||
return task.Result;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,244 +0,0 @@
|
||||
|
||||
using System.Threading.Tasks;
|
||||
using UnityEngine;
|
||||
using VRMShaders;
|
||||
|
||||
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 TextureImportParam BaseColorTexture(GltfParser parser, glTFMaterial src)
|
||||
{
|
||||
var (offset, scale) = MaterialFactory.GetTextureOffsetAndScale(src.pbrMetallicRoughness.baseColorTexture);
|
||||
return GltfTextureImporter.CreateSRGB(parser, src.pbrMetallicRoughness.baseColorTexture.index, offset, scale);
|
||||
}
|
||||
|
||||
public static TextureImportParam StandardTexture(GltfParser parser, glTFMaterial src)
|
||||
{
|
||||
var metallicFactor = 1.0f;
|
||||
var roughnessFactor = 1.0f;
|
||||
if (src.pbrMetallicRoughness != null)
|
||||
{
|
||||
metallicFactor = src.pbrMetallicRoughness.metallicFactor;
|
||||
roughnessFactor = src.pbrMetallicRoughness.roughnessFactor;
|
||||
}
|
||||
var (offset, scale) = MaterialFactory.GetTextureOffsetAndScale(src.pbrMetallicRoughness.metallicRoughnessTexture);
|
||||
return GltfTextureImporter.CreateStandard(parser,
|
||||
src.pbrMetallicRoughness?.metallicRoughnessTexture?.index,
|
||||
src.occlusionTexture?.index,
|
||||
offset, scale,
|
||||
metallicFactor,
|
||||
roughnessFactor);
|
||||
}
|
||||
|
||||
public static TextureImportParam NormalTexture(GltfParser parser, glTFMaterial src)
|
||||
{
|
||||
var (offset, scale) = MaterialFactory.GetTextureOffsetAndScale(src.normalTexture);
|
||||
return GltfTextureImporter.CreateNormal(parser, src.normalTexture.index, offset, scale);
|
||||
}
|
||||
|
||||
public static async Task<Material> CreateAsync(IAwaitCaller awaitCaller, GltfParser parser, int i, GetTextureAsyncFunc getTexture)
|
||||
{
|
||||
if (getTexture == null)
|
||||
{
|
||||
getTexture = (TextureImportParam _param) => Task.FromResult<Texture2D>(null);
|
||||
}
|
||||
|
||||
var material = new Material(Shader.Find(ShaderName));
|
||||
if (i < 0 || i >= parser.GLTF.materials.Count)
|
||||
{
|
||||
material.name = MaterialFactory.MaterialName(i, null);
|
||||
return material;
|
||||
}
|
||||
|
||||
var src = parser.GLTF.materials[i];
|
||||
material.name = MaterialFactory.MaterialName(i, src);
|
||||
var standardParam = default(TextureImportParam);
|
||||
if (src.pbrMetallicRoughness != null || src.occlusionTexture != null)
|
||||
{
|
||||
if (src.pbrMetallicRoughness.metallicRoughnessTexture != null || src.occlusionTexture != null)
|
||||
{
|
||||
standardParam = StandardTexture(parser, 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)
|
||||
{
|
||||
var param = BaseColorTexture(parser, src);
|
||||
material.mainTexture = await getTexture(param);
|
||||
|
||||
// Texture Offset and Scale
|
||||
MaterialFactory.SetTextureOffsetAndScale(material, "_MainTex", param.Offset, param.Scale);
|
||||
}
|
||||
|
||||
if (src.pbrMetallicRoughness.metallicRoughnessTexture != null && src.pbrMetallicRoughness.metallicRoughnessTexture.index != -1)
|
||||
{
|
||||
material.EnableKeyword("_METALLICGLOSSMAP");
|
||||
|
||||
var texture = await getTexture(standardParam);
|
||||
if (texture != null)
|
||||
{
|
||||
material.SetTexture(TextureImportParam.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
|
||||
var (offset, scale) = MaterialFactory.GetTextureOffsetAndScale(src.pbrMetallicRoughness.metallicRoughnessTexture);
|
||||
MaterialFactory.SetTextureOffsetAndScale(material, "_MetallicGlossMap", offset, scale);
|
||||
}
|
||||
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 param = NormalTexture(parser, src);
|
||||
var texture = await getTexture(param);
|
||||
if (texture != null)
|
||||
{
|
||||
material.SetTexture(TextureImportParam.NORMAL_PROP, texture);
|
||||
material.SetFloat("_BumpScale", src.normalTexture.scale);
|
||||
}
|
||||
|
||||
// Texture Offset and Scale
|
||||
MaterialFactory.SetTextureOffsetAndScale(material, "_BumpMap", param.Offset, param.Scale);
|
||||
}
|
||||
|
||||
if (src.occlusionTexture != null && src.occlusionTexture.index != -1)
|
||||
{
|
||||
var texture = await getTexture(standardParam);
|
||||
if (texture != null)
|
||||
{
|
||||
material.SetTexture(TextureImportParam.OCCLUSION_PROP, texture);
|
||||
material.SetFloat("_OcclusionStrength", src.occlusionTexture.strength);
|
||||
}
|
||||
|
||||
// Texture Offset and Scale
|
||||
var (offset, scale) = MaterialFactory.GetTextureOffsetAndScale(src.occlusionTexture);
|
||||
MaterialFactory.SetTextureOffsetAndScale(material, "_OcclusionMap", offset, scale);
|
||||
}
|
||||
|
||||
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 (offset, scale) = MaterialFactory.GetTextureOffsetAndScale(src.emissiveTexture);
|
||||
var param = GltfTextureImporter.CreateSRGB(parser, src.emissiveTexture.index, offset, scale);
|
||||
var texture = await getTexture(param);
|
||||
if (texture != null)
|
||||
{
|
||||
material.SetTexture("_EmissionMap", texture);
|
||||
}
|
||||
|
||||
// Texture Offset and Scale
|
||||
|
||||
MaterialFactory.SetTextureOffsetAndScale(material, "_EmissionMap", param.Offset, param.Scale);
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,80 +0,0 @@
|
||||
|
||||
using System.Threading.Tasks;
|
||||
using UnityEngine;
|
||||
|
||||
namespace UniGLTF
|
||||
{
|
||||
public static class UnlitMaterialItem
|
||||
{
|
||||
public const string ShaderName = "UniGLTF/UniUnlit";
|
||||
|
||||
public static async Task<Material> CreateAsync(IAwaitCaller awaitCaller, GltfParser parser, int i, GetTextureAsyncFunc getTexture, bool hasVertexColor)
|
||||
{
|
||||
if (getTexture == null)
|
||||
{
|
||||
getTexture = (_) => Task.FromResult<Texture2D>(default);
|
||||
}
|
||||
|
||||
var src = parser.GLTF.materials[i];
|
||||
var material = new Material(Shader.Find(ShaderName));
|
||||
material.name = MaterialFactory.MaterialName(i, src);
|
||||
|
||||
// texture
|
||||
if (src.pbrMetallicRoughness.baseColorTexture != null)
|
||||
{
|
||||
var (offset, scale) = MaterialFactory.GetTextureOffsetAndScale(src.pbrMetallicRoughness.baseColorTexture);
|
||||
material.mainTexture = await getTexture(GltfTextureImporter.CreateSRGB(parser, src.pbrMetallicRoughness.baseColorTexture.index, offset, scale));
|
||||
|
||||
// Texture Offset and Scale
|
||||
MaterialFactory.SetTextureOffsetAndScale(material, "_MainTex", offset, scale);
|
||||
}
|
||||
|
||||
// color
|
||||
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;
|
||||
}
|
||||
|
||||
//renderMode
|
||||
if (src.alphaMode == "OPAQUE")
|
||||
{
|
||||
UniUnlit.Utils.SetRenderMode(material, UniUnlit.UniUnlitRenderMode.Opaque);
|
||||
}
|
||||
else if (src.alphaMode == "BLEND")
|
||||
{
|
||||
UniUnlit.Utils.SetRenderMode(material, UniUnlit.UniUnlitRenderMode.Transparent);
|
||||
}
|
||||
else if (src.alphaMode == "MASK")
|
||||
{
|
||||
UniUnlit.Utils.SetRenderMode(material, UniUnlit.UniUnlitRenderMode.Cutout);
|
||||
material.SetFloat("_Cutoff", src.alphaCutoff);
|
||||
}
|
||||
else
|
||||
{
|
||||
// default OPAQUE
|
||||
UniUnlit.Utils.SetRenderMode(material, UniUnlit.UniUnlitRenderMode.Opaque);
|
||||
}
|
||||
|
||||
// culling
|
||||
if (src.doubleSided)
|
||||
{
|
||||
UniUnlit.Utils.SetCullMode(material, UniUnlit.UniUnlitCullMode.Off);
|
||||
}
|
||||
else
|
||||
{
|
||||
UniUnlit.Utils.SetCullMode(material, UniUnlit.UniUnlitCullMode.Back);
|
||||
}
|
||||
|
||||
// VColor
|
||||
if (hasVertexColor)
|
||||
{
|
||||
UniUnlit.Utils.SetVColBlendMode(material, UniUnlit.UniUnlitVertexColorBlendOp.Multiply);
|
||||
}
|
||||
|
||||
UniUnlit.Utils.ValidateProperties(material, true);
|
||||
|
||||
return material;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,7 +4,7 @@ using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading.Tasks;
|
||||
using UnityEngine;
|
||||
|
||||
using VRMShaders;
|
||||
|
||||
namespace UniGLTF
|
||||
{
|
||||
|
||||
@@ -8,8 +8,6 @@ using VRMShaders;
|
||||
|
||||
namespace UniGLTF
|
||||
{
|
||||
public delegate Task<Texture2D> GetTextureAsyncFunc(TextureImportParam param);
|
||||
|
||||
/// <summary>
|
||||
/// glTFTexture を TextureImportParam に変換する
|
||||
/// </summary>
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
using UnityEngine;
|
||||
using UniJSON;
|
||||
using System.Linq;
|
||||
using VRMShaders;
|
||||
|
||||
namespace UniGLTF
|
||||
{
|
||||
@@ -31,12 +32,11 @@ namespace UniGLTF
|
||||
var gltfMaterial = materialExporter.ExportMaterial(srcMaterial, textureManager);
|
||||
gltfMaterial.pbrMetallicRoughness.baseColorTexture.extensions = gltfMaterial.pbrMetallicRoughness.baseColorTexture.extensions.Deserialize();
|
||||
|
||||
var dstMaterial = MaterialFactory.CreateMaterialForTest(0, gltfMaterial);
|
||||
|
||||
Assert.AreEqual(dstMaterial.mainTextureOffset.x, offset.x, 0.3f);
|
||||
Assert.AreEqual(dstMaterial.mainTextureOffset.y, offset.y, 0.2f);
|
||||
Assert.AreEqual(dstMaterial.mainTextureScale.x, scale.x, 0.5f);
|
||||
Assert.AreEqual(dstMaterial.mainTextureScale.y, scale.y, 0.6f);
|
||||
Assert.IsTrue(glTF_KHR_texture_transform.TryGet(gltfMaterial.pbrMetallicRoughness.baseColorTexture, out glTF_KHR_texture_transform t));
|
||||
Assert.AreEqual(t.offset[0], offset.x, 0.3f);
|
||||
Assert.AreEqual(t.offset[1], offset.y, 0.2f);
|
||||
Assert.AreEqual(t.scale[0], scale.x, 0.5f);
|
||||
Assert.AreEqual(t.scale[1], scale.y, 0.6f);
|
||||
}
|
||||
|
||||
[Test]
|
||||
@@ -79,8 +79,7 @@ namespace UniGLTF
|
||||
|
||||
Assert.IsTrue(glTF_KHR_materials_unlit.IsEnable(gltfMaterial));
|
||||
|
||||
var material = MaterialFactory.CreateMaterialForTest(0, gltfMaterial);
|
||||
Assert.AreEqual("UniGLTF/UniUnlit", material.shader.name);
|
||||
Assert.IsTrue(glTF_KHR_materials_unlit.IsEnable(gltfMaterial));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -98,8 +97,7 @@ namespace UniGLTF
|
||||
},
|
||||
extensions = glTF_KHR_materials_unlit.Serialize().Deserialize(),
|
||||
};
|
||||
var material = MaterialFactory.CreateMaterialForTest(0, gltfMaterial);
|
||||
Assert.AreEqual("UniGLTF/UniUnlit", material.shader.name);
|
||||
Assert.IsTrue(glTF_KHR_materials_unlit.IsEnable(gltfMaterial));
|
||||
}
|
||||
|
||||
{
|
||||
@@ -116,8 +114,7 @@ namespace UniGLTF
|
||||
},
|
||||
extensions = glTF_KHR_materials_unlit.Serialize().Deserialize(),
|
||||
};
|
||||
var material = MaterialFactory.CreateMaterialForTest(0, gltfMaterial);
|
||||
Assert.AreEqual("UniGLTF/UniUnlit", material.shader.name);
|
||||
Assert.IsTrue(glTF_KHR_materials_unlit.IsEnable(gltfMaterial));
|
||||
}
|
||||
|
||||
{
|
||||
@@ -135,8 +132,7 @@ namespace UniGLTF
|
||||
},
|
||||
extensions = glTF_KHR_materials_unlit.Serialize().Deserialize(),
|
||||
};
|
||||
var material = MaterialFactory.CreateMaterialForTest(0, gltfMaterial);
|
||||
Assert.AreEqual("UniGLTF/UniUnlit", material.shader.name);
|
||||
Assert.IsTrue(glTF_KHR_materials_unlit.IsEnable(gltfMaterial));
|
||||
}
|
||||
|
||||
{
|
||||
@@ -150,8 +146,7 @@ namespace UniGLTF
|
||||
},
|
||||
extensions = glTF_KHR_materials_unlit.Serialize().Deserialize(),
|
||||
};
|
||||
var material = MaterialFactory.CreateMaterialForTest(0, gltfMaterial);
|
||||
Assert.AreEqual("UniGLTF/UniUnlit", material.shader.name);
|
||||
Assert.IsTrue(glTF_KHR_materials_unlit.IsEnable(gltfMaterial));
|
||||
}
|
||||
|
||||
{
|
||||
@@ -168,8 +163,7 @@ namespace UniGLTF
|
||||
},
|
||||
extensions = glTF_KHR_materials_unlit.Serialize().Deserialize(),
|
||||
};
|
||||
var material = MaterialFactory.CreateMaterialForTest(0, gltfMaterial);
|
||||
Assert.AreEqual("UniGLTF/UniUnlit", material.shader.name);
|
||||
Assert.IsTrue(glTF_KHR_materials_unlit.IsEnable(gltfMaterial));
|
||||
}
|
||||
|
||||
{
|
||||
@@ -187,8 +181,7 @@ namespace UniGLTF
|
||||
},
|
||||
extensions = glTF_KHR_materials_unlit.Serialize().Deserialize(),
|
||||
};
|
||||
var material = MaterialFactory.CreateMaterialForTest(0, gltfMaterial);
|
||||
Assert.AreEqual("UniGLTF/UniUnlit", material.shader.name);
|
||||
Assert.IsTrue(glTF_KHR_materials_unlit.IsEnable(gltfMaterial));
|
||||
}
|
||||
|
||||
{
|
||||
@@ -205,8 +198,7 @@ namespace UniGLTF
|
||||
},
|
||||
extensions = glTF_KHR_materials_unlit.Serialize().Deserialize(),
|
||||
};
|
||||
var material = MaterialFactory.CreateMaterialForTest(0, gltfMaterial);
|
||||
Assert.AreEqual("UniGLTF/UniUnlit", material.shader.name);
|
||||
Assert.IsTrue(glTF_KHR_materials_unlit.IsEnable(gltfMaterial));
|
||||
}
|
||||
|
||||
{
|
||||
@@ -224,8 +216,7 @@ namespace UniGLTF
|
||||
},
|
||||
extensions = glTF_KHR_materials_unlit.Serialize().Deserialize(),
|
||||
};
|
||||
var material = MaterialFactory.CreateMaterialForTest(0, gltfMaterial);
|
||||
Assert.AreEqual("UniGLTF/UniUnlit", material.shader.name);
|
||||
Assert.IsTrue(glTF_KHR_materials_unlit.IsEnable(gltfMaterial));
|
||||
}
|
||||
|
||||
{
|
||||
@@ -234,16 +225,14 @@ namespace UniGLTF
|
||||
{
|
||||
extensions = glTF_KHR_materials_unlit.Serialize().Deserialize(),
|
||||
};
|
||||
var material = MaterialFactory.CreateMaterialForTest(0, gltfMaterial);
|
||||
Assert.AreEqual("UniGLTF/UniUnlit", material.shader.name);
|
||||
Assert.IsTrue(glTF_KHR_materials_unlit.IsEnable(gltfMaterial));
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void MaterialImportTest()
|
||||
{
|
||||
var material = MaterialFactory.CreateMaterialForTest(0, new glTFMaterial { });
|
||||
Assert.AreEqual("Standard", material.shader.name);
|
||||
Assert.IsFalse(glTF_KHR_materials_unlit.IsEnable(new glTFMaterial { }));
|
||||
}
|
||||
|
||||
[Test]
|
||||
|
||||
@@ -125,7 +125,7 @@ namespace VRM
|
||||
//
|
||||
// convert images(metallic roughness, occlusion map)
|
||||
//
|
||||
var task = m_context.MaterialFactory.LoadMaterialsAsync(default(ImmediateCaller), m_context.TextureFactory.GetTextureAsync);
|
||||
var task = m_context.LoadMaterialsAsync();
|
||||
if (!task.IsCompleted)
|
||||
{
|
||||
throw new Exception();
|
||||
|
||||
107
Assets/VRM/Runtime/IO/MToonMaterialImporter.cs
Normal file
107
Assets/VRM/Runtime/IO/MToonMaterialImporter.cs
Normal file
@@ -0,0 +1,107 @@
|
||||
using System.Collections.Generic;
|
||||
using UniGLTF;
|
||||
using UnityEngine;
|
||||
using VRMShaders;
|
||||
|
||||
|
||||
namespace VRM
|
||||
{
|
||||
public class MToonMaterialImporter
|
||||
{
|
||||
public static bool TryCreateParam(GltfParser parser, int i, glTF_VRM_Material vrmMaterial, out MaterialImportParam param)
|
||||
{
|
||||
if (vrmMaterial.shader == VRM.glTF_VRM_Material.VRM_USE_GLTFSHADER)
|
||||
{
|
||||
// fallback to gltf
|
||||
param = default;
|
||||
return false;
|
||||
}
|
||||
|
||||
//
|
||||
// restore VRM material
|
||||
//
|
||||
// use material.name, because material name may renamed in GltfParser.
|
||||
var name = parser.GLTF.materials[i].name;
|
||||
param = new MaterialImportParam(name, vrmMaterial.shader);
|
||||
|
||||
param.Actions.Add(material => material.renderQueue = vrmMaterial.renderQueue);
|
||||
|
||||
foreach (var kv in vrmMaterial.floatProperties)
|
||||
{
|
||||
param.FloatValues.Add(kv.Key, kv.Value);
|
||||
}
|
||||
|
||||
var offsetScaleMap = new Dictionary<string, float[]>();
|
||||
foreach (var kv in vrmMaterial.vectorProperties)
|
||||
{
|
||||
if (vrmMaterial.textureProperties.ContainsKey(kv.Key))
|
||||
{
|
||||
// texture offset & scale
|
||||
offsetScaleMap.Add(kv.Key, kv.Value);
|
||||
}
|
||||
else
|
||||
{
|
||||
// vector4
|
||||
var v = new Vector4(kv.Value[0], kv.Value[1], kv.Value[2], kv.Value[3]);
|
||||
param.Vectors.Add(kv.Key, v);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var kv in vrmMaterial.textureProperties)
|
||||
{
|
||||
var (offset, scale) = (Vector2.zero, Vector2.one);
|
||||
if (offsetScaleMap.TryGetValue(kv.Key, out float[] value))
|
||||
{
|
||||
offset = new Vector2(value[0], value[1]);
|
||||
scale = new Vector2(value[2], value[3]);
|
||||
}
|
||||
|
||||
var textureParam = MToonTextureParam.Create(parser, kv.Value, offset, scale, kv.Key, 1, 1);
|
||||
param.TextureSlots.Add(kv.Key, textureParam);
|
||||
}
|
||||
|
||||
foreach (var kv in vrmMaterial.keywordMap)
|
||||
{
|
||||
if (kv.Value)
|
||||
{
|
||||
param.Actions.Add(material => material.EnableKeyword(kv.Key));
|
||||
}
|
||||
else
|
||||
{
|
||||
param.Actions.Add(material => material.DisableKeyword(kv.Key));
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var kv in vrmMaterial.tagMap)
|
||||
{
|
||||
param.Actions.Add(material => material.SetOverrideTag(kv.Key, kv.Value));
|
||||
}
|
||||
|
||||
if (vrmMaterial.shader == MToon.Utils.ShaderName)
|
||||
{
|
||||
// TODO: Material拡張にMToonの項目が追加されたら旧バージョンのshaderPropから変換をかける
|
||||
// インポート時にUniVRMに含まれるMToonのバージョンに上書きする
|
||||
param.FloatValues[MToon.Utils.PropVersion] = MToon.Utils.VersionNumber;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
List<glTF_VRM_Material> m_materials;
|
||||
public MToonMaterialImporter(List<glTF_VRM_Material> materials)
|
||||
{
|
||||
m_materials = materials;
|
||||
}
|
||||
|
||||
public bool TryCreateParam(GltfParser parser, int i, out MaterialImportParam param)
|
||||
{
|
||||
if (TryCreateParam(parser, i, m_materials[i], out param))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
param = default;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Assets/VRM/Runtime/IO/MToonMaterialImporter.cs.meta
Normal file
11
Assets/VRM/Runtime/IO/MToonMaterialImporter.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 35c90d5d3fa706b4f87a92ce4dc59008
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -26,7 +26,7 @@ namespace VRM
|
||||
{
|
||||
VRM = vrm;
|
||||
// override material importer
|
||||
MaterialFactory.CreateMaterialAsync = new VRMMaterialImporter(VRM.materialProperties).CreateMaterialAsync;
|
||||
GltfMaterialImporter.GltfMaterialParamProcessors.Insert(0, new MToonMaterialImporter(VRM.materialProperties).TryCreateParam);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -1,139 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using UniGLTF;
|
||||
using UnityEngine;
|
||||
using System.Linq;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace VRM
|
||||
{
|
||||
public static class MToonMaterialItem
|
||||
{
|
||||
static string[] VRM_SHADER_NAMES =
|
||||
{
|
||||
"Standard",
|
||||
"VRM/MToon",
|
||||
"UniGLTF/UniUnlit",
|
||||
|
||||
"VRM/UnlitTexture",
|
||||
"VRM/UnlitCutout",
|
||||
"VRM/UnlitTransparent",
|
||||
"VRM/UnlitTransparentZWrite",
|
||||
};
|
||||
|
||||
public static async Task<Material> CreateAsync(IAwaitCaller awaitCaller, GltfParser parser, int m_index, glTF_VRM_Material vrmMaterial, GetTextureAsyncFunc getTexture)
|
||||
{
|
||||
var item = vrmMaterial;
|
||||
var shaderName = item.shader;
|
||||
var shader = Shader.Find(shaderName);
|
||||
if (shader == null)
|
||||
{
|
||||
//
|
||||
// no shader
|
||||
//
|
||||
if (VRM_SHADER_NAMES.Contains(shaderName))
|
||||
{
|
||||
Debug.LogErrorFormat("shader {0} not found. set Assets/VRM/Shaders/VRMShaders to Edit - project setting - Graphics - preloaded shaders", shaderName);
|
||||
}
|
||||
else
|
||||
{
|
||||
// #if VRM_DEVELOP
|
||||
// Debug.LogWarningFormat("unknown shader {0}.", shaderName);
|
||||
// #endif
|
||||
}
|
||||
return await MaterialFactory.DefaultCreateMaterialAsync(awaitCaller, parser, m_index, getTexture);
|
||||
}
|
||||
|
||||
//
|
||||
// restore VRM material
|
||||
//
|
||||
var material = new Material(shader);
|
||||
// use material.name, because material name may renamed in GltfParser.
|
||||
material.name = parser.GLTF.materials[m_index].name;
|
||||
material.renderQueue = item.renderQueue;
|
||||
|
||||
foreach (var kv in item.floatProperties)
|
||||
{
|
||||
material.SetFloat(kv.Key, kv.Value);
|
||||
}
|
||||
|
||||
var offsetScaleMap = new Dictionary<string, float[]>();
|
||||
foreach (var kv in item.vectorProperties)
|
||||
{
|
||||
if (item.textureProperties.ContainsKey(kv.Key))
|
||||
{
|
||||
// texture offset & scale
|
||||
offsetScaleMap.Add(kv.Key, kv.Value);
|
||||
}
|
||||
else
|
||||
{
|
||||
// vector4
|
||||
var v = new Vector4(kv.Value[0], kv.Value[1], kv.Value[2], kv.Value[3]);
|
||||
material.SetVector(kv.Key, v);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var kv in item.textureProperties)
|
||||
{
|
||||
var (offset, scale) = (Vector2.zero, Vector2.one);
|
||||
if (offsetScaleMap.TryGetValue(kv.Key, out float[] value))
|
||||
{
|
||||
offset = new Vector2(value[0], value[1]);
|
||||
scale = new Vector2(value[2], value[3]);
|
||||
}
|
||||
|
||||
var param = MToonTextureParam.Create(parser, kv.Value, offset, scale, kv.Key, 1, 1);
|
||||
var texture = await getTexture(param);
|
||||
if (texture != null)
|
||||
{
|
||||
material.SetTexture(kv.Key, texture);
|
||||
MaterialFactory.SetTextureOffsetAndScale(material, kv.Key, offset, scale);
|
||||
}
|
||||
}
|
||||
foreach (var kv in item.keywordMap)
|
||||
{
|
||||
if (kv.Value)
|
||||
{
|
||||
material.EnableKeyword(kv.Key);
|
||||
}
|
||||
else
|
||||
{
|
||||
material.DisableKeyword(kv.Key);
|
||||
}
|
||||
}
|
||||
foreach (var kv in item.tagMap)
|
||||
{
|
||||
material.SetOverrideTag(kv.Key, kv.Value);
|
||||
}
|
||||
|
||||
if (shaderName == MToon.Utils.ShaderName)
|
||||
{
|
||||
// TODO: Material拡張にMToonの項目が追加されたら旧バージョンのshaderPropから変換をかける
|
||||
// インポート時にUniVRMに含まれるMToonのバージョンに上書きする
|
||||
material.SetFloat(MToon.Utils.PropVersion, MToon.Utils.VersionNumber);
|
||||
}
|
||||
|
||||
return material;
|
||||
}
|
||||
}
|
||||
|
||||
public class VRMMaterialImporter
|
||||
{
|
||||
List<glTF_VRM_Material> m_materials;
|
||||
public VRMMaterialImporter(List<glTF_VRM_Material> materials)
|
||||
{
|
||||
m_materials = materials;
|
||||
}
|
||||
|
||||
public Task<Material> CreateMaterialAsync(IAwaitCaller awaitCaller, GltfParser parser, int i, GetTextureAsyncFunc getTexture)
|
||||
{
|
||||
if (i == 0 && m_materials.Count == 0)
|
||||
{
|
||||
// dummy
|
||||
return MaterialFactory.DefaultCreateMaterialAsync(awaitCaller, parser, i, getTexture);
|
||||
}
|
||||
|
||||
return MToonMaterialItem.CreateAsync(awaitCaller, parser, i, m_materials[i], getTexture);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -29,7 +29,7 @@ namespace VRM
|
||||
var vrmMaterial = VRMMaterialExporter.CreateFromMaterial(srcMaterial, textureManager);
|
||||
Assert.AreEqual(vrmMaterial.vectorProperties["_MainTex"], new float[]{0.3f, 0.2f, 0.5f, 0.6f});
|
||||
|
||||
var materialImporter = new VRMMaterialImporter(new System.Collections.Generic.List<glTF_VRM_Material>{ vrmMaterial });
|
||||
var materialImporter = new MToonMaterialImporter(new System.Collections.Generic.List<glTF_VRM_Material>{ vrmMaterial });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
163
Assets/VRMShaders/Runtime/MaterialFactory.cs
Normal file
163
Assets/VRMShaders/Runtime/MaterialFactory.cs
Normal file
@@ -0,0 +1,163 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using UnityEngine;
|
||||
|
||||
|
||||
namespace VRMShaders
|
||||
{
|
||||
public delegate Task<Texture2D> GetTextureAsyncFunc(TextureImportParam param);
|
||||
|
||||
public class MaterialFactory : IDisposable
|
||||
{
|
||||
Dictionary<string, Material> m_externalMap;
|
||||
|
||||
public MaterialFactory(IEnumerable<(string, UnityEngine.Object)> externalMap)
|
||||
{
|
||||
if (externalMap == null)
|
||||
{
|
||||
externalMap = Enumerable.Empty<(string, UnityEngine.Object)>();
|
||||
}
|
||||
m_externalMap = externalMap
|
||||
.Select(kv => (kv.Item1, kv.Item2 as Material))
|
||||
.Where(kv => kv.Item2 != null)
|
||||
.ToDictionary(kv => kv.Item1, kv => kv.Item2)
|
||||
;
|
||||
}
|
||||
|
||||
public struct MaterialLoadInfo
|
||||
{
|
||||
public readonly Material Asset;
|
||||
public readonly bool UseExternal;
|
||||
|
||||
public bool IsSubAsset => !UseExternal;
|
||||
|
||||
public MaterialLoadInfo(Material asset, bool useExternal)
|
||||
{
|
||||
Asset = asset;
|
||||
UseExternal = useExternal;
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
if (!x.UseExternal)
|
||||
{
|
||||
// 外部の '.asset' からロードしていない
|
||||
#if VRM_DEVELOP
|
||||
// Debug.Log($"Destroy {x.Asset}");
|
||||
#endif
|
||||
UnityEngine.Object.DestroyImmediate(x.Asset, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 所有権(Dispose権)を移譲する
|
||||
///
|
||||
/// 所有権を移動する関数。
|
||||
///
|
||||
/// * 所有権が移動する。return true => ImporterContext.Dispose の対象から外れる
|
||||
/// * 所有権が移動しない。return false => Importer.Context.Dispose でDestroyされる
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="take"></param>
|
||||
public void TransferOwnership(Func<UnityEngine.Object, bool> take)
|
||||
{
|
||||
var list = new List<Material>();
|
||||
foreach (var x in m_materials)
|
||||
{
|
||||
if (!x.UseExternal)
|
||||
{
|
||||
// 外部の '.asset' からロードしていない
|
||||
if (take(x.Asset))
|
||||
{
|
||||
list.Add(x.Asset);
|
||||
}
|
||||
}
|
||||
}
|
||||
foreach (var x in list)
|
||||
{
|
||||
Remove(x);
|
||||
}
|
||||
}
|
||||
|
||||
public Material GetMaterial(int index)
|
||||
{
|
||||
if (index < 0) return null;
|
||||
if (index >= m_materials.Count) return null;
|
||||
return m_materials[index].Asset;
|
||||
}
|
||||
|
||||
public async Task<Material> LoadAsync(MaterialImportParam param, GetTextureAsyncFunc getTexture)
|
||||
{
|
||||
if (m_externalMap.TryGetValue(param.Name, out Material material))
|
||||
{
|
||||
m_materials.Add(new MaterialLoadInfo(material, true));
|
||||
return material;
|
||||
}
|
||||
|
||||
if (getTexture == null)
|
||||
{
|
||||
getTexture = (_) => Task.FromResult<Texture2D>(null);
|
||||
}
|
||||
|
||||
material = new Material(Shader.Find(param.ShaderName));
|
||||
material.name = param.Name;
|
||||
|
||||
foreach(var kv in param.TextureSlots)
|
||||
{
|
||||
var texture = await getTexture(kv.Value);
|
||||
if(texture!=null){
|
||||
material.SetTexture(kv.Key, texture);
|
||||
SetTextureOffsetAndScale(material, kv.Key, kv.Value.Offset, kv.Value.Scale);
|
||||
}
|
||||
}
|
||||
|
||||
foreach(var kv in param.Colors)
|
||||
{
|
||||
material.SetColor(kv.Key, kv.Value);
|
||||
}
|
||||
|
||||
foreach(var kv in param.Vectors)
|
||||
{
|
||||
material.SetVector(kv.Key, kv.Value);
|
||||
}
|
||||
|
||||
foreach(var kv in param.FloatValues)
|
||||
{
|
||||
material.SetFloat(kv.Key, kv.Value);
|
||||
}
|
||||
|
||||
foreach(var action in param.Actions)
|
||||
{
|
||||
action(material);
|
||||
}
|
||||
|
||||
m_materials.Add(new MaterialLoadInfo(material, false));
|
||||
|
||||
return material;
|
||||
}
|
||||
|
||||
public static void SetTextureOffsetAndScale(Material material, string propertyName, Vector2 offset, Vector2 scale)
|
||||
{
|
||||
material.SetTextureOffset(propertyName, offset);
|
||||
material.SetTextureScale(propertyName, scale);
|
||||
}
|
||||
}
|
||||
}
|
||||
24
Assets/VRMShaders/Runtime/MaterialImportParam.cs
Normal file
24
Assets/VRMShaders/Runtime/MaterialImportParam.cs
Normal file
@@ -0,0 +1,24 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
|
||||
namespace VRMShaders
|
||||
{
|
||||
public class MaterialImportParam
|
||||
{
|
||||
public readonly string Name;
|
||||
public readonly string ShaderName;
|
||||
public readonly Dictionary<string, TextureImportParam> TextureSlots = new Dictionary<string, TextureImportParam>();
|
||||
public readonly Dictionary<string, float> FloatValues = new Dictionary<string, float>();
|
||||
public readonly Dictionary<string, Color> Colors = new Dictionary<string, Color>();
|
||||
public readonly Dictionary<string, Vector4> Vectors = new Dictionary<string, Vector4>();
|
||||
public readonly List<Action<Material>> Actions = new List<Action<Material>>();
|
||||
|
||||
public MaterialImportParam(string name, string shaderName)
|
||||
{
|
||||
Name = name;
|
||||
ShaderName = shaderName;
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Assets/VRMShaders/Runtime/MaterialImportParam.cs.meta
Normal file
11
Assets/VRMShaders/Runtime/MaterialImportParam.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0844821341efaf644b91bff72f813a2c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user