* MaterialImporter を MaterialItem に分解

* MaterialImporter を interface から delegate に格下げ
* UniUnlit の導入により不要になった ShaderStore を削除
This commit is contained in:
ousttrue
2021-02-10 20:14:13 +09:00
parent c2de8bbe89
commit e2b2495e1c
11 changed files with 468 additions and 552 deletions

View File

@@ -106,12 +106,7 @@ namespace UniGLTF
#endregion
MaterialFactory m_materialFactory = new MaterialFactory();
public MaterialFactory MaterialFacotry => m_materialFactory;
public ImporterContext(IShaderStore shaderStore)
{
m_materialFactory.ShaderStore = shaderStore;
}
public MaterialFactory MaterialFactory => m_materialFactory;
public ImporterContext(MaterialImporter materialImporter)
{
@@ -573,13 +568,13 @@ namespace UniGLTF
MeshWithMaterials meshWithMaterials;
if (EnableLoadBalancing)
{
var buildMesh = MeshImporter.BuildMeshCoroutine(this, x);
var buildMesh = MeshImporter.BuildMeshCoroutine(MaterialFactory, x);
yield return buildMesh;
meshWithMaterials = buildMesh.Current as MeshWithMaterials;
}
else
{
meshWithMaterials = MeshImporter.BuildMesh(this, x);
meshWithMaterials = MeshImporter.BuildMesh(MaterialFactory, x);
}
var mesh = meshWithMaterials.Mesh;
@@ -605,7 +600,7 @@ namespace UniGLTF
for (int i = 0; i < GLTF.meshes.Count; ++i)
{
var meshContext = meshImporter.ReadMesh(this, i);
var meshWithMaterials = MeshImporter.BuildMesh(this, meshContext);
var meshWithMaterials = MeshImporter.BuildMesh(MaterialFactory, meshContext);
var mesh = meshWithMaterials.Mesh;
if (string.IsNullOrEmpty(mesh.name))
{
@@ -702,7 +697,7 @@ namespace UniGLTF
protected virtual IEnumerable<UnityEngine.Object> ObjectsForSubAsset()
{
HashSet<Texture2D> textures = new HashSet<Texture2D>();
foreach (var x in MaterialFacotry.GetTextures().SelectMany(y => y.GetTexturesForSaveAssets()))
foreach (var x in MaterialFactory.GetTextures().SelectMany(y => y.GetTexturesForSaveAssets()))
{
if (!textures.Contains(x))
{
@@ -710,7 +705,7 @@ namespace UniGLTF
}
}
foreach (var x in textures) { yield return x; }
foreach (var x in MaterialFacotry.GetMaterials()) { yield return x; }
foreach (var x in MaterialFactory.GetMaterials()) { yield return x.GetOrCreate(MaterialFactory.GetTexture); }
foreach (var x in Meshes) { yield return x.Mesh; }
foreach (var x in AnimationClips) { yield return x; }
}

View File

@@ -625,7 +625,7 @@ namespace UniGLTF
}
}
public static MeshWithMaterials BuildMesh(ImporterContext ctx, MeshImporter.MeshContext meshContext)
public static MeshWithMaterials BuildMesh(MaterialFactory ctx, MeshImporter.MeshContext meshContext)
{
var (mesh, recalculateTangents) = _BuildMesh(meshContext);
@@ -637,7 +637,7 @@ namespace UniGLTF
var result = new MeshWithMaterials
{
Mesh = mesh,
Materials = meshContext.MaterialIndices.Select(x => ctx.MaterialFacotry.GetMaterial(x)).ToArray()
Materials = meshContext.MaterialIndices.Select(x => ctx.GetMaterial(x).GetOrCreate(ctx.GetTexture)).ToArray()
};
if (meshContext.BlendShapes.Count > 0)
@@ -651,7 +651,7 @@ namespace UniGLTF
return result;
}
public static IEnumerator BuildMeshCoroutine(ImporterContext ctx, MeshImporter.MeshContext meshContext)
public static IEnumerator BuildMeshCoroutine(MaterialFactory ctx, MeshImporter.MeshContext meshContext)
{
var (mesh, recalculateTangents) = _BuildMesh(meshContext);
@@ -665,7 +665,7 @@ namespace UniGLTF
var result = new MeshWithMaterials
{
Mesh = mesh,
Materials = meshContext.MaterialIndices.Select(x => ctx.MaterialFacotry.GetMaterial(x)).ToArray()
Materials = meshContext.MaterialIndices.Select(x => ctx.GetMaterial(x).GetOrCreate(ctx.GetTexture)).ToArray()
};
yield return null;

View File

@@ -1,123 +0,0 @@
using UnityEngine;
namespace UniGLTF
{
public interface IShaderStore
{
Shader GetShader(glTFMaterial material);
}
public class ShaderStore : IShaderStore
{
readonly string m_defaultShaderName = "Standard";
Shader m_default;
Shader Default
{
get
{
if (m_default == null)
{
m_default = Shader.Find(m_defaultShaderName);
}
return m_default;
}
}
Shader m_vcolor;
Shader VColor
{
get
{
if (m_vcolor == null) m_vcolor = Shader.Find("UniGLTF/StandardVColor");
return m_vcolor;
}
}
Shader m_uniUnlit;
Shader UniUnlit
{
get
{
if (m_uniUnlit == null) m_uniUnlit = Shader.Find("UniGLTF/UniUnlit");
return m_uniUnlit;
}
}
Shader m_unlitTexture;
Shader UnlitTexture
{
get
{
if (m_unlitTexture == null) m_unlitTexture = Shader.Find("Unlit/Texture");
return m_unlitTexture;
}
}
Shader m_unlitColor;
Shader UnlitColor
{
get
{
if (m_unlitColor == null) m_unlitColor = Shader.Find("Unlit/Color");
return m_unlitColor;
}
}
Shader m_unlitTransparent;
Shader UnlitTransparent
{
get
{
if (m_unlitTransparent == null) m_unlitTransparent = Shader.Find("Unlit/Transparent");
return m_unlitTransparent;
}
}
Shader m_unlitCutout;
Shader UnlitCutout
{
get
{
if (m_unlitCutout == null) m_unlitCutout = Shader.Find("Unlit/Transparent Cutout");
return m_unlitCutout;
}
}
//ImporterContext m_context;
public ShaderStore(MaterialFactory _)
{
//m_context = context;
}
public static bool IsWhite(float[] color)
{
if (color == null) return false;
if(color.Length!=4)return false;
if(color[0]!=1
|| color[1]!=1
|| color[2]!=1
|| color[3] != 1)
{
return false;
}
return true;
}
public Shader GetShader(glTFMaterial material)
{
if (material == null)
{
return Default;
}
if(glTF_KHR_materials_unlit.IsEnable(material))
{
return UniUnlit;
}
// standard
return Default;
}
}
}

View File

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

View File

@@ -6,25 +6,13 @@ using UnityEngine;
namespace UniGLTF
{
public delegate TextureItem GetTextureItemFunc(int i);
public delegate Shader GetShaderFunc();
public delegate MaterialItemBase MaterialImporter(int i, glTFMaterial x, bool hasVertexColor);
public class MaterialFactory
{
public IShaderStore m_shaderStore;
public IShaderStore ShaderStore
{
set
{
m_shaderStore = value;
}
get
{
if (m_shaderStore == null)
{
m_shaderStore = new ShaderStore(this);
}
return m_shaderStore;
}
}
MaterialImporter m_materialImporter;
public MaterialImporter MaterialImporter
{
@@ -36,7 +24,7 @@ namespace UniGLTF
{
if (m_materialImporter == null)
{
m_materialImporter = new MaterialImporter(ShaderStore);
m_materialImporter = CreateMaterial;
}
return m_materialImporter;
}
@@ -60,22 +48,22 @@ namespace UniGLTF
m_textures.Add(item);
}
List<Material> m_materials = new List<Material>();
public void AddMaterial(Material material)
List<MaterialItemBase> m_materials = new List<MaterialItemBase>();
public void AddMaterial(MaterialItemBase material)
{
var originalName = material.name;
var originalName = material.Name;
int j = 2;
while (m_materials.Any(x => x.name == material.name))
while (m_materials.Any(x => x.Name == material.Name))
{
material.name = string.Format("{0}({1})", originalName, j++);
material.Name = string.Format("{0}({1})", originalName, j++);
}
m_materials.Add(material);
}
public IList<Material> GetMaterials()
public IList<MaterialItemBase> GetMaterials()
{
return m_materials;
}
public Material GetMaterial(int index)
public MaterialItemBase GetMaterial(int index)
{
if (index < 0) return null;
if (index >= m_materials.Count) return null;
@@ -173,17 +161,33 @@ namespace UniGLTF
{
if (gltf.materials == null || !gltf.materials.Any())
{
AddMaterial(MaterialImporter.CreateMaterial(0, null, false, GetTexture));
AddMaterial(MaterialImporter(0, null, false));
}
else
{
for (int i = 0; i < gltf.materials.Count; ++i)
{
AddMaterial(MaterialImporter.CreateMaterial(i, gltf.materials[i], gltf.MaterialHasVertexColor(i), GetTexture));
AddMaterial(MaterialImporter(i, gltf.materials[i], gltf.MaterialHasVertexColor(i)));
}
}
}
yield return null;
}
public static MaterialItemBase CreateMaterial(int i, glTFMaterial x, bool hasVertexColor)
{
if (x == null)
{
UnityEngine.Debug.LogWarning("glTFMaterial is empty");
return new PBRMaterialItem(i, x);
}
if (glTF_KHR_materials_unlit.IsEnable(x))
{
return new UnlitMaterialItem(i, x, hasVertexColor);
}
return new PBRMaterialItem(i, x);
}
}
}

View File

@@ -1,310 +0,0 @@
using UnityEngine;
using System;
using UnityEngine.Rendering;
#if UNITY_EDITOR
using UnityEditor;
#endif
namespace UniGLTF
{
public class MaterialImporter
{
IShaderStore m_shaderStore;
public MaterialImporter(IShaderStore shaderStore)
{
m_shaderStore = shaderStore;
}
public delegate TextureItem GetTextureFunc(int index);
private enum BlendMode
{
Opaque,
Cutout,
Fade,
Transparent
}
/// 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 virtual Material CreateMaterial(int i, glTFMaterial x, bool hasVertexColor, GetTextureFunc getTexture)
{
var shader = m_shaderStore.GetShader(x);
//Debug.LogFormat("[{0}]{1}", i, shader.name);
var material = new Material(shader);
#if UNITY_EDITOR
// textureImporter.SaveAndReimport(); may destroy this material
material.hideFlags = HideFlags.DontUnloadUnusedAsset;
#endif
material.name = (x == null || string.IsNullOrEmpty(x.name))
? string.Format("material_{0:00}", i)
: x.name
;
if (x == null)
{
Debug.LogWarning("glTFMaterial is empty");
return material;
}
// unlit material
if (glTF_KHR_materials_unlit.IsEnable(x))
{
// texture
if (x.pbrMetallicRoughness.baseColorTexture != null)
{
var texture = getTexture(x.pbrMetallicRoughness.baseColorTexture.index);
if (texture != null)
{
material.mainTexture = texture.Texture;
}
// Texture Offset and Scale
SetTextureOffsetAndScale(material, x.pbrMetallicRoughness.baseColorTexture, "_MainTex");
}
// color
if (x.pbrMetallicRoughness.baseColorFactor != null && x.pbrMetallicRoughness.baseColorFactor.Length == 4)
{
var color = x.pbrMetallicRoughness.baseColorFactor;
material.color = (new Color(color[0], color[1], color[2], color[3])).gamma;
}
//renderMode
if (x.alphaMode == "OPAQUE")
{
UniUnlit.Utils.SetRenderMode(material, UniUnlit.UniUnlitRenderMode.Opaque);
}
else if (x.alphaMode == "BLEND")
{
UniUnlit.Utils.SetRenderMode(material, UniUnlit.UniUnlitRenderMode.Transparent);
}
else if (x.alphaMode == "MASK")
{
UniUnlit.Utils.SetRenderMode(material, UniUnlit.UniUnlitRenderMode.Cutout);
material.SetFloat("_Cutoff", x.alphaCutoff);
}
else
{
// default OPAQUE
UniUnlit.Utils.SetRenderMode(material, UniUnlit.UniUnlitRenderMode.Opaque);
}
// culling
if (x.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;
}
// PBR material
if (x.pbrMetallicRoughness != null)
{
if (x.pbrMetallicRoughness.baseColorFactor != null && x.pbrMetallicRoughness.baseColorFactor.Length == 4)
{
var color = x.pbrMetallicRoughness.baseColorFactor;
material.color = (new Color(color[0], color[1], color[2], color[3])).gamma;
}
if (x.pbrMetallicRoughness.baseColorTexture != null && x.pbrMetallicRoughness.baseColorTexture.index != -1)
{
var texture = getTexture(x.pbrMetallicRoughness.baseColorTexture.index);
if (texture != null)
{
material.mainTexture = texture.Texture;
}
// Texture Offset and Scale
SetTextureOffsetAndScale(material, x.pbrMetallicRoughness.baseColorTexture, "_MainTex");
}
if (x.pbrMetallicRoughness.metallicRoughnessTexture != null && x.pbrMetallicRoughness.metallicRoughnessTexture.index != -1)
{
material.EnableKeyword("_METALLICGLOSSMAP");
var texture = getTexture(x.pbrMetallicRoughness.metallicRoughnessTexture.index);
if (texture != null)
{
var prop = "_MetallicGlossMap";
// Bake roughnessFactor values into a texture.
material.SetTexture(prop, texture.ConvertTexture(prop, x.pbrMetallicRoughness.roughnessFactor));
}
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
SetTextureOffsetAndScale(material, x.pbrMetallicRoughness.metallicRoughnessTexture, "_MetallicGlossMap");
}
else
{
material.SetFloat("_Metallic", x.pbrMetallicRoughness.metallicFactor);
material.SetFloat("_Glossiness", 1.0f - x.pbrMetallicRoughness.roughnessFactor);
}
}
if (x.normalTexture != null && x.normalTexture.index != -1)
{
material.EnableKeyword("_NORMALMAP");
var texture = getTexture(x.normalTexture.index);
if (texture != null)
{
var prop = "_BumpMap";
material.SetTexture(prop, texture.ConvertTexture(prop));
material.SetFloat("_BumpScale", x.normalTexture.scale);
}
// Texture Offset and Scale
SetTextureOffsetAndScale(material, x.normalTexture, "_BumpMap");
}
if (x.occlusionTexture != null && x.occlusionTexture.index != -1)
{
var texture = getTexture(x.occlusionTexture.index);
if (texture != null)
{
var prop = "_OcclusionMap";
material.SetTexture(prop, texture.ConvertTexture(prop));
material.SetFloat("_OcclusionStrength", x.occlusionTexture.strength);
}
// Texture Offset and Scale
SetTextureOffsetAndScale(material, x.occlusionTexture, "_OcclusionMap");
}
if (x.emissiveFactor != null
|| (x.emissiveTexture != null && x.emissiveTexture.index != -1))
{
material.EnableKeyword("_EMISSION");
material.globalIlluminationFlags &= ~MaterialGlobalIlluminationFlags.EmissiveIsBlack;
if (x.emissiveFactor != null && x.emissiveFactor.Length == 3)
{
material.SetColor("_EmissionColor", new Color(x.emissiveFactor[0], x.emissiveFactor[1], x.emissiveFactor[2]));
}
if (x.emissiveTexture != null && x.emissiveTexture.index != -1)
{
var texture = getTexture(x.emissiveTexture.index);
if (texture != null)
{
material.SetTexture("_EmissionMap", texture.Texture);
}
// Texture Offset and Scale
SetTextureOffsetAndScale(material, x.emissiveTexture, "_EmissionMap");
}
}
BlendMode blendMode = BlendMode.Opaque;
// https://forum.unity.com/threads/standard-material-shader-ignoring-setfloat-property-_mode.344557/#post-2229980
switch (x.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", x.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;
}
private static void SetTextureOffsetAndScale(Material material, glTFTextureInfo textureInfo, string propertyName)
{
if (glTF_KHR_texture_transform.TryGet(textureInfo, out glTF_KHR_texture_transform textureTransform))
{
Vector2 offset = new Vector2(0, 0);
Vector2 scale = new Vector2(1, 1);
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;
material.SetTextureOffset(propertyName, offset);
material.SetTextureScale(propertyName, scale);
}
}
}
}

View File

@@ -0,0 +1,346 @@
using System;
using UnityEngine;
using UnityEngine.Rendering;
namespace UniGLTF
{
public abstract class MaterialItemBase
{
protected int m_index;
protected glTFMaterial m_src;
public string Name { get; set; }
public MaterialItemBase(int i, glTFMaterial src)
{
m_index = i;
m_src = src;
Name = src != null ? m_src.name : "";
}
public abstract Material GetOrCreate(GetTextureItemFunc getTexture);
protected static void SetTextureOffsetAndScale(Material material, glTFTextureInfo textureInfo, string propertyName)
{
if (glTF_KHR_texture_transform.TryGet(textureInfo, out glTF_KHR_texture_transform textureTransform))
{
Vector2 offset = new Vector2(0, 0);
Vector2 scale = new Vector2(1, 1);
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;
material.SetTextureOffset(propertyName, offset);
material.SetTextureScale(propertyName, scale);
}
}
}
public class UnlitMaterialItem : MaterialItemBase
{
public const string UniUnlitShaderName = "UniGLTF/UniUnlit";
bool m_hasVertexColor;
public UnlitMaterialItem(int i, glTFMaterial src, bool hasVertexColor) : base(i, src)
{
m_hasVertexColor = hasVertexColor;
}
public override Material GetOrCreate(GetTextureItemFunc getTexture)
{
if (getTexture == null)
{
getTexture = _ => null;
}
var material = new Material(Shader.Find(UniUnlitShaderName));
#if UNITY_EDITOR
// textureImporter.SaveAndReimport(); may destroy this material
material.hideFlags = HideFlags.DontUnloadUnusedAsset;
#endif
material.name = (m_src == null || string.IsNullOrEmpty(m_src.name))
? string.Format("material_{0:00}", m_index)
: m_src.name
;
// texture
if (m_src.pbrMetallicRoughness.baseColorTexture != null)
{
var texture = getTexture(m_src.pbrMetallicRoughness.baseColorTexture.index);
if (texture != null)
{
material.mainTexture = texture.Texture;
}
// Texture Offset and Scale
SetTextureOffsetAndScale(material, m_src.pbrMetallicRoughness.baseColorTexture, "_MainTex");
}
// color
if (m_src.pbrMetallicRoughness.baseColorFactor != null && m_src.pbrMetallicRoughness.baseColorFactor.Length == 4)
{
var color = m_src.pbrMetallicRoughness.baseColorFactor;
material.color = (new Color(color[0], color[1], color[2], color[3])).gamma;
}
//renderMode
if (m_src.alphaMode == "OPAQUE")
{
UniUnlit.Utils.SetRenderMode(material, UniUnlit.UniUnlitRenderMode.Opaque);
}
else if (m_src.alphaMode == "BLEND")
{
UniUnlit.Utils.SetRenderMode(material, UniUnlit.UniUnlitRenderMode.Transparent);
}
else if (m_src.alphaMode == "MASK")
{
UniUnlit.Utils.SetRenderMode(material, UniUnlit.UniUnlitRenderMode.Cutout);
material.SetFloat("_Cutoff", m_src.alphaCutoff);
}
else
{
// default OPAQUE
UniUnlit.Utils.SetRenderMode(material, UniUnlit.UniUnlitRenderMode.Opaque);
}
// culling
if (m_src.doubleSided)
{
UniUnlit.Utils.SetCullMode(material, UniUnlit.UniUnlitCullMode.Off);
}
else
{
UniUnlit.Utils.SetCullMode(material, UniUnlit.UniUnlitCullMode.Back);
}
// VColor
if (m_hasVertexColor)
{
UniUnlit.Utils.SetVColBlendMode(material, UniUnlit.UniUnlitVertexColorBlendOp.Multiply);
}
UniUnlit.Utils.ValidateProperties(material, true);
return material;
}
}
/// 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 class PBRMaterialItem : MaterialItemBase
{
public const string PBRShaderName = "Standard";
private enum BlendMode
{
Opaque,
Cutout,
Fade,
Transparent
}
public PBRMaterialItem(int i, glTFMaterial src) : base(i, src)
{
}
public override Material GetOrCreate(GetTextureItemFunc getTexture)
{
if (getTexture == null)
{
getTexture = _ => null;
}
var material = new Material(Shader.Find(PBRShaderName));
#if UNITY_EDITOR
// textureImporter.SaveAndReimport(); may destroy this material
material.hideFlags = HideFlags.DontUnloadUnusedAsset;
#endif
material.name = (base.m_src == null || string.IsNullOrEmpty(base.m_src.name))
? string.Format("material_{0:00}", m_index)
: base.m_src.name
;
// PBR material
if (m_src != null)
{
if (m_src.pbrMetallicRoughness != null)
{
if (m_src.pbrMetallicRoughness.baseColorFactor != null && m_src.pbrMetallicRoughness.baseColorFactor.Length == 4)
{
var color = m_src.pbrMetallicRoughness.baseColorFactor;
material.color = (new Color(color[0], color[1], color[2], color[3])).gamma;
}
if (m_src.pbrMetallicRoughness.baseColorTexture != null && m_src.pbrMetallicRoughness.baseColorTexture.index != -1)
{
var texture = getTexture(m_src.pbrMetallicRoughness.baseColorTexture.index);
if (texture != null)
{
material.mainTexture = texture.Texture;
}
// Texture Offset and Scale
SetTextureOffsetAndScale(material, m_src.pbrMetallicRoughness.baseColorTexture, "_MainTex");
}
if (m_src.pbrMetallicRoughness.metallicRoughnessTexture != null && m_src.pbrMetallicRoughness.metallicRoughnessTexture.index != -1)
{
material.EnableKeyword("_METALLICGLOSSMAP");
var texture = getTexture(m_src.pbrMetallicRoughness.metallicRoughnessTexture.index);
if (texture != null)
{
var prop = "_MetallicGlossMap";
// Bake roughnessFactor values into a texture.
material.SetTexture(prop, texture.ConvertTexture(prop, m_src.pbrMetallicRoughness.roughnessFactor));
}
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
SetTextureOffsetAndScale(material, m_src.pbrMetallicRoughness.metallicRoughnessTexture, "_MetallicGlossMap");
}
else
{
material.SetFloat("_Metallic", m_src.pbrMetallicRoughness.metallicFactor);
material.SetFloat("_Glossiness", 1.0f - m_src.pbrMetallicRoughness.roughnessFactor);
}
}
if (m_src.normalTexture != null && m_src.normalTexture.index != -1)
{
material.EnableKeyword("_NORMALMAP");
var texture = getTexture(m_src.normalTexture.index);
if (texture != null)
{
var prop = "_BumpMap";
material.SetTexture(prop, texture.ConvertTexture(prop));
material.SetFloat("_BumpScale", m_src.normalTexture.scale);
}
// Texture Offset and Scale
SetTextureOffsetAndScale(material, m_src.normalTexture, "_BumpMap");
}
if (m_src.occlusionTexture != null && m_src.occlusionTexture.index != -1)
{
var texture = getTexture(m_src.occlusionTexture.index);
if (texture != null)
{
var prop = "_OcclusionMap";
material.SetTexture(prop, texture.ConvertTexture(prop));
material.SetFloat("_OcclusionStrength", m_src.occlusionTexture.strength);
}
// Texture Offset and Scale
SetTextureOffsetAndScale(material, m_src.occlusionTexture, "_OcclusionMap");
}
if (m_src.emissiveFactor != null
|| (m_src.emissiveTexture != null && m_src.emissiveTexture.index != -1))
{
material.EnableKeyword("_EMISSION");
material.globalIlluminationFlags &= ~MaterialGlobalIlluminationFlags.EmissiveIsBlack;
if (m_src.emissiveFactor != null && m_src.emissiveFactor.Length == 3)
{
material.SetColor("_EmissionColor", new Color(m_src.emissiveFactor[0], m_src.emissiveFactor[1], m_src.emissiveFactor[2]));
}
if (m_src.emissiveTexture != null && m_src.emissiveTexture.index != -1)
{
var texture = getTexture(m_src.emissiveTexture.index);
if (texture != null)
{
material.SetTexture("_EmissionMap", texture.Texture);
}
// Texture Offset and Scale
SetTextureOffsetAndScale(material, m_src.emissiveTexture, "_EmissionMap");
}
}
BlendMode blendMode = BlendMode.Opaque;
// https://forum.unity.com/threads/standard-material-shader-ignoring-setfloat-property-_mode.344557/#post-2229980
switch (m_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", m_src.alphaCutoff);
material.EnableKeyword("_ALPHATEST_ON");
material.DisableKeyword("_ALPHABLEND_ON");
material.DisableKeyword("_ALPHAPREMULTIPLY_ON");
material.renderQueue = 2450;
break;
default: // OPAQUE
blendMode = BlendMode.Opaque;
material.SetOverrideTag("RenderType", "");
material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One);
material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.Zero);
material.SetInt("_ZWrite", 1);
material.DisableKeyword("_ALPHATEST_ON");
material.DisableKeyword("_ALPHABLEND_ON");
material.DisableKeyword("_ALPHAPREMULTIPLY_ON");
material.renderQueue = -1;
break;
}
material.SetFloat("_Mode", (float)blendMode);
}
return material;
}
}
}

View File

@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: c7dc5ea1cfb854745a2f5c9f6701218f
guid: f49a88d3a0e6eb24e91af983452f59f6
MonoImporter:
externalObjects: {}
serializedVersion: 2

View File

@@ -32,9 +32,7 @@ namespace UniGLTF
var gltfMaterial = materialExporter.ExportMaterial(srcMaterial, textureManager);
gltfMaterial.pbrMetallicRoughness.baseColorTexture.extensions = gltfMaterial.pbrMetallicRoughness.baseColorTexture.extensions.Deserialize();
var shaderStore = new ShaderStore(null);
var materialImporter = new MaterialImporter(shaderStore);
var dstMaterial = materialImporter.CreateMaterial(0, gltfMaterial, false, x => null);
var dstMaterial = MaterialFactory.CreateMaterial(0, gltfMaterial, false).GetOrCreate(null);
Assert.AreEqual(dstMaterial.mainTextureOffset.x, offset.x, 0.3f);
Assert.AreEqual(dstMaterial.mainTextureOffset.y, offset.y, 0.2f);
@@ -70,7 +68,7 @@ namespace UniGLTF
Assert.AreEqual(glTF_KHR_materials_unlit.ExtensionNameUtf8, list[0].Key.GetUtf8String());
Assert.AreEqual(0, list[0].Value.GetObjectCount());
var material = new glTFMaterial
var gltfMaterial = new glTFMaterial
{
alphaMode = "OPAQUE",
pbrMetallicRoughness = new glTFPbrMetallicRoughness
@@ -80,22 +78,19 @@ namespace UniGLTF
extensions = extension,
};
Assert.IsTrue(glTF_KHR_materials_unlit.IsEnable(material));
Assert.IsTrue(glTF_KHR_materials_unlit.IsEnable(gltfMaterial));
var shaderStore = new ShaderStore(null);
var shader = shaderStore.GetShader(material);
Assert.AreEqual("UniGLTF/UniUnlit", shader.name);
var material = MaterialFactory.CreateMaterial(0, gltfMaterial, false).GetOrCreate(null);
Assert.AreEqual("UniGLTF/UniUnlit", material.shader.name);
}
}
[Test]
public void UnlitShaderImportTest()
{
var shaderStore = new ShaderStore(null);
{
// OPAQUE/Color
var shader = shaderStore.GetShader(new glTFMaterial
var gltfMaterial = new glTFMaterial
{
alphaMode = "OPAQUE",
pbrMetallicRoughness = new glTFPbrMetallicRoughness
@@ -103,13 +98,14 @@ namespace UniGLTF
baseColorFactor = new float[] { 1, 0, 0, 1 },
},
extensions = glTF_KHR_materials_unlit.Serialize().Deserialize(),
});
Assert.AreEqual("UniGLTF/UniUnlit", shader.name);
};
var material = MaterialFactory.CreateMaterial(0, gltfMaterial, false).GetOrCreate(null);
Assert.AreEqual("UniGLTF/UniUnlit", material.shader.name);
}
{
// OPAQUE/Texture
var shader = shaderStore.GetShader(new glTFMaterial
var gltfMaterial = new glTFMaterial
{
alphaMode = "OPAQUE",
pbrMetallicRoughness = new glTFPbrMetallicRoughness
@@ -117,13 +113,14 @@ namespace UniGLTF
baseColorTexture = new glTFMaterialBaseColorTextureInfo(),
},
extensions = glTF_KHR_materials_unlit.Serialize().Deserialize(),
});
Assert.AreEqual("UniGLTF/UniUnlit", shader.name);
};
var material = MaterialFactory.CreateMaterial(0, gltfMaterial, false).GetOrCreate(null);
Assert.AreEqual("UniGLTF/UniUnlit", material.shader.name);
}
{
// OPAQUE/Color/Texture
var shader = shaderStore.GetShader(new glTFMaterial
var gltfMaterial = new glTFMaterial
{
alphaMode = "OPAQUE",
pbrMetallicRoughness = new glTFPbrMetallicRoughness
@@ -132,13 +129,14 @@ namespace UniGLTF
baseColorTexture = new glTFMaterialBaseColorTextureInfo(),
},
extensions = glTF_KHR_materials_unlit.Serialize().Deserialize(),
});
Assert.AreEqual("UniGLTF/UniUnlit", shader.name);
};
var material = MaterialFactory.CreateMaterial(0, gltfMaterial, false).GetOrCreate(null);
Assert.AreEqual("UniGLTF/UniUnlit", material.shader.name);
}
{
// BLEND/Color
var shader = shaderStore.GetShader(new glTFMaterial
var gltfMaterial = new glTFMaterial
{
alphaMode = "BLEND",
pbrMetallicRoughness = new glTFPbrMetallicRoughness
@@ -146,13 +144,14 @@ namespace UniGLTF
baseColorFactor = new float[] { 1, 0, 0, 1 },
},
extensions = glTF_KHR_materials_unlit.Serialize().Deserialize(),
});
Assert.AreEqual("UniGLTF/UniUnlit", shader.name);
};
var material = MaterialFactory.CreateMaterial(0, gltfMaterial, false).GetOrCreate(null);
Assert.AreEqual("UniGLTF/UniUnlit", material.shader.name);
}
{
// BLEND/Texture
var shader = shaderStore.GetShader(new glTFMaterial
var gltfMaterial = new glTFMaterial
{
alphaMode = "BLEND",
pbrMetallicRoughness = new glTFPbrMetallicRoughness
@@ -160,13 +159,14 @@ namespace UniGLTF
baseColorTexture = new glTFMaterialBaseColorTextureInfo(),
},
extensions = glTF_KHR_materials_unlit.Serialize().Deserialize(),
});
Assert.AreEqual("UniGLTF/UniUnlit", shader.name);
};
var material = MaterialFactory.CreateMaterial(0, gltfMaterial, false).GetOrCreate(null);
Assert.AreEqual("UniGLTF/UniUnlit", material.shader.name);
}
{
// BLEND/Color/Texture
var shader = shaderStore.GetShader(new glTFMaterial
var gltfMaterial = new glTFMaterial
{
alphaMode = "BLEND",
pbrMetallicRoughness = new glTFPbrMetallicRoughness
@@ -175,13 +175,14 @@ namespace UniGLTF
baseColorTexture = new glTFMaterialBaseColorTextureInfo(),
},
extensions = glTF_KHR_materials_unlit.Serialize().Deserialize(),
});
Assert.AreEqual("UniGLTF/UniUnlit", shader.name);
};
var material = MaterialFactory.CreateMaterial(0, gltfMaterial, false).GetOrCreate(null);
Assert.AreEqual("UniGLTF/UniUnlit", material.shader.name);
}
{
// MASK/Texture
var shader = shaderStore.GetShader(new glTFMaterial
var gltfMaterial = new glTFMaterial
{
alphaMode = "MASK",
pbrMetallicRoughness = new glTFPbrMetallicRoughness
@@ -189,13 +190,14 @@ namespace UniGLTF
baseColorTexture = new glTFMaterialBaseColorTextureInfo(),
},
extensions = glTF_KHR_materials_unlit.Serialize().Deserialize(),
});
Assert.AreEqual("UniGLTF/UniUnlit", shader.name);
};
var material = MaterialFactory.CreateMaterial(0, gltfMaterial, false).GetOrCreate(null);
Assert.AreEqual("UniGLTF/UniUnlit", material.shader.name);
}
{
// MASK/Color/Texture
var shader = shaderStore.GetShader(new glTFMaterial
var gltfMaterial = new glTFMaterial
{
alphaMode = "MASK",
pbrMetallicRoughness = new glTFPbrMetallicRoughness
@@ -204,30 +206,27 @@ namespace UniGLTF
baseColorTexture = new glTFMaterialBaseColorTextureInfo(),
},
extensions = glTF_KHR_materials_unlit.Serialize().Deserialize(),
});
Assert.AreEqual("UniGLTF/UniUnlit", shader.name);
};
var material = MaterialFactory.CreateMaterial(0, gltfMaterial, false).GetOrCreate(null);
Assert.AreEqual("UniGLTF/UniUnlit", material.shader.name);
}
{
// default
var shader = shaderStore.GetShader(new glTFMaterial
var gltfMaterial = new glTFMaterial
{
extensions = glTF_KHR_materials_unlit.Serialize().Deserialize(),
});
Assert.AreEqual("UniGLTF/UniUnlit", shader.name);
};
var material = MaterialFactory.CreateMaterial(0, gltfMaterial, false).GetOrCreate(null);
Assert.AreEqual("UniGLTF/UniUnlit", material.shader.name);
}
}
[Test]
public void MaterialImportTest()
{
var shaderStore = new ShaderStore(null);
var materialImporter = new MaterialImporter(shaderStore);
{
var material = materialImporter.CreateMaterial(0, new glTFMaterial { }, false, null);
Assert.AreEqual("Standard", material.shader.name);
}
var material = MaterialFactory.CreateMaterial(0, new glTFMaterial { }, false).GetOrCreate(null);
Assert.AreEqual("Standard", material.shader.name);
}
[Test]

View File

@@ -42,7 +42,7 @@ namespace VRM
{
VRM = vrm;
// override material importer
MaterialFacotry.MaterialImporter = new VRMMaterialImporter(new ShaderStore(MaterialFacotry), VRM.materialProperties);
MaterialFactory.MaterialImporter = new VRMMaterialImporter(VRM.materialProperties).CreateMaterial;
}
else
{
@@ -193,7 +193,7 @@ namespace VRM
}
}
var material = MaterialFacotry.GetMaterials().FirstOrDefault(y => y.name == x.materialName);
var material = MaterialFactory.GetMaterials().FirstOrDefault(y => y.Name == x.materialName).GetOrCreate(MaterialFactory.GetTexture);
var propertyName = x.propertyName;
if (x.propertyName.FastEndsWith("_ST_S")
|| x.propertyName.FastEndsWith("_ST_T"))
@@ -305,7 +305,7 @@ namespace VRM
meta.Reference = gltfMeta.reference;
meta.Title = gltfMeta.title;
var thumbnail = MaterialFacotry.GetTexture(gltfMeta.texture);
var thumbnail = MaterialFactory.GetTexture(gltfMeta.texture);
if (thumbnail != null)
{
// ロード済み
@@ -316,7 +316,7 @@ namespace VRM
// 作成する(先行ロード用)
if (gltfMeta.texture >= 0 && gltfMeta.texture < GLTF.textures.Count)
{
var t = new TextureItem(gltfMeta.texture, MaterialFacotry.CreateTextureLoader(gltfMeta.texture));
var t = new TextureItem(gltfMeta.texture, MaterialFactory.CreateTextureLoader(gltfMeta.texture));
t.Process(GLTF, Storage);
meta.Thumbnail = t.Texture;
}

View File

@@ -6,14 +6,8 @@ using System;
namespace VRM
{
public class VRMMaterialImporter : MaterialImporter
public class MToonMaterialItem : MaterialItemBase
{
List<glTF_VRM_Material> m_materials;
public VRMMaterialImporter(IShaderStore shaderStore, List<glTF_VRM_Material> materials) : base(shaderStore)
{
m_materials = materials;
}
static string[] VRM_SHADER_NAMES =
{
"Standard",
@@ -26,15 +20,18 @@ namespace VRM
"VRM/UnlitTransparentZWrite",
};
public override Material CreateMaterial(int i, glTFMaterial src, bool hasVertexColor, GetTextureFunc getTexture)
{
if (i == 0 && m_materials.Count == 0)
{
// dummy
return new Material(Shader.Find("Standard"));
}
glTF_VRM_Material m_vrmMaterial;
bool m_hasVertexColor;
var item = m_materials[i];
public MToonMaterialItem(int i, glTFMaterial src, bool hasVertexColor, glTF_VRM_Material vrmMaterial) : base(i, src)
{
m_hasVertexColor = hasVertexColor;
m_vrmMaterial = vrmMaterial;
}
public override Material GetOrCreate(GetTextureItemFunc getTexture)
{
var item = m_vrmMaterial;
var shaderName = item.shader;
var shader = Shader.Find(shaderName);
if (shader == null)
@@ -50,7 +47,7 @@ namespace VRM
{
Debug.LogWarningFormat("unknown shader {0}.", shaderName);
}
return base.CreateMaterial(i, src, hasVertexColor, getTexture);
return MaterialFactory.CreateMaterial(m_index, m_src, m_hasVertexColor).GetOrCreate(getTexture);
}
//
@@ -121,4 +118,24 @@ namespace VRM
return material;
}
}
public class VRMMaterialImporter
{
List<glTF_VRM_Material> m_materials;
public VRMMaterialImporter(List<glTF_VRM_Material> materials)
{
m_materials = materials;
}
public MaterialItemBase CreateMaterial(int i, glTFMaterial src, bool hasVertexColor)
{
if (i == 0 && m_materials.Count == 0)
{
// dummy
return new PBRMaterialItem(i, src);
}
return new MToonMaterialItem(i, src, hasVertexColor, m_materials[i]);
}
}
}