diff --git a/Editor/MMDEngineEditor.cs b/Editor/MMDEngineEditor.cs index dc1f1fa..01934f0 100644 --- a/Editor/MMDEngineEditor.cs +++ b/Editor/MMDEngineEditor.cs @@ -37,7 +37,8 @@ public override void OnInspectorGUI() is_dirty = OnInspectorGUIforUseRigidbody() || is_dirty; is_dirty = OnInspectorGUIforIkList() || is_dirty; is_dirty = OnInspectorGUIforShaderList() || is_dirty; - + is_dirty = OnInspectorGUIforRenderQueue() || is_dirty; + if (is_dirty) { //更新が有ったなら //Inspector更新 @@ -215,7 +216,9 @@ private bool OnInspectorGUIforShaderList() , new {flag=ShaderFlag.Hidden, reverse=false} }; //マテリアル - foreach (var material in materials) { + for (int i = 0, i_max = materials.Length; i < i_max; ++i) { + Material material = materials[i]; + EditorGUILayout.BeginHorizontal(); { //ラベル @@ -256,7 +259,8 @@ private bool OnInspectorGUIforShaderList() Undo.RegisterUndo(material, "Shader Change"); #endif - SetShader(material, flag); + int render_queue = ((self.enable_render_queue)? self.render_queue_value + i: -1); + SetShader(material, flag, render_queue); is_update = true; } } @@ -269,6 +273,92 @@ private bool OnInspectorGUIforShaderList() return is_update; } + /// + /// カスタムレンダーキューの為のInspector描画 + /// + /// 更新が有ったか(true:更新有り, false:未更新) + private bool OnInspectorGUIforRenderQueue() + { + MMDEngine self = (MMDEngine)target; + bool is_update = false; + +#if !MFU_DISABLE_LEGACY_DATA_SUPPORT + if ((false == self.enable_render_queue) && (0 == self.render_queue_value)) { + //カスタムレンダーキュー関連が設定されていないなら(昔の変換データ) + //無効状態で初期化 + self.enable_render_queue = false; + const int c_render_queue_transparent = 3000; + self.render_queue_value = c_render_queue_transparent; + } +#endif + + bool enable_render_queue = self.enable_render_queue; + enable_render_queue = EditorGUILayout.Toggle("Render Queue", enable_render_queue); + if (self.enable_render_queue != enable_render_queue) { + //変更が掛かったなら + is_update = true; + } + int render_queue_value = -1; + if (enable_render_queue) { + //有効なら + render_queue_value = self.render_queue_value; + render_queue_value = EditorGUILayout.IntField("Render Queue Value", render_queue_value); + if (self.render_queue_value != render_queue_value) { + //変更が掛かったなら + is_update = true; + } + } + + if (is_update) { + //変更が掛かったなら + Material[] materials = GetMaterials(self); + //Undo登録 + var record_objects = materials.Select(x=>(UnityEngine.Object)x) //マテリアル全てと + .Concat(new UnityEngine.Object[]{self}) //UnityEngine + .ToArray(); +#if !UNITY_4_2 //4.3以降 + Undo.RecordObjects(record_objects, "Render Queue Change"); +#else + Undo.RegisterUndo(record_objects, "Render Queue Change"); +#endif + //更新 + self.enable_render_queue = enable_render_queue; + if (enable_render_queue) { + //有効化 + self.render_queue_value = render_queue_value; + for (int i = 0, i_max = materials.Length; i < i_max; ++i) { + var material = materials[i]; + ShaderFlag flag = AnalyzeShaderFlag(material); + if (0 != (flag & ShaderFlag.MmdShader)) { + //Mmdシェーダーなら + //カスタムレンダーキュー + if (0 != (flag & ShaderFlag.Transparent)) { + //透過なら + //マテリアル順にカスタムレンダーキューを設定 + material.renderQueue = render_queue_value + i; + } else { + //不透明なら + //カスタムレンダーキューを解除 + material.renderQueue = -1; + } + } + } + } else { + //無効化 + foreach (var material in materials) { + ShaderFlag flag = AnalyzeShaderFlag(material); + if (0 != (flag & ShaderFlag.MmdShader)) { + //Mmdシェーダーなら + //カスタムレンダーキューを解除 + material.renderQueue = -1; + } + } + } + } + + return is_update; + } + /// /// MMDシェーダー確認 /// @@ -357,7 +447,8 @@ static ShaderFlag AnalyzeShaderFlag(Material material) { /// /// マテリアル /// シェーダーフラグ - static void SetShader(Material material, ShaderFlag flag) { + /// 透過の場合に設定するレンダーキュー + static void SetShader(Material material, ShaderFlag flag, int render_queue) { if (0 != (flag & ShaderFlag.MmdShader)) { //Mmdシェーダーなら material.shader = CreateShaderFromShaderFlag(flag); @@ -371,6 +462,16 @@ static void SetShader(Material material, ShaderFlag flag) { float original_shader_type = (float)(int)flag; material.SetFloat("_DummyOriginalShaderType", original_shader_type); material.SetColor("_DummyColor", new Color(1.0f, 0.0f, 1.0f, 1.0f)); + } + //カスタムレンダーキュー + if (0 != (flag & ShaderFlag.Transparent)) { + //透過なら + //マテリアル順にカスタムレンダーキューを設定 + material.renderQueue = render_queue; + } else { + //不透明なら + //カスタムレンダーキューを解除 + material.renderQueue = -1; } } } diff --git a/Editor/MMDLoader/Private/AlphaReadableTexture.cs b/Editor/MMDLoader/Private/AlphaReadableTexture.cs new file mode 100644 index 0000000..ca5e0a5 --- /dev/null +++ b/Editor/MMDLoader/Private/AlphaReadableTexture.cs @@ -0,0 +1,123 @@ +using UnityEngine; +using UnityEditor; +using System.Collections.Generic; +using System.Linq; + +public class AlphaReadableTexture : System.IDisposable { + + /// + /// コンストラクタ + /// + /// テクスチャ相対パスリスト + /// カレントディレクトリ("/"終わり、テクスチャの相対パス基点) + /// 解析作業用ディレクトリ("/"終わり、このディレクトリの下に解析作業用ディレクトリを作ります) + public AlphaReadableTexture(string[] texture_path_list, string current_directory, string temporary_directory) + { + texture_path_list_ = texture_path_list; + current_directory_ = current_directory; + temporary_directory_ = temporary_directory + directory_name + "/"; + + //テクスチャ作成 + foreach (string texture_path in texture_path_list_.Where(x=>!string.IsNullOrEmpty(x)).Distinct()) { + CreateReadableTexture(texture_path); + } + AssetDatabase.Refresh(); + //テクスチャ取得 + textures_ = texture_path_list_.Select(x=>GetReadableTexture(x)).ToArray(); + } + + /// + /// 読み込み可能テクスチャの取得 + /// + /// 読み込み可能テクスチャ + public Texture2D[] textures {get{return textures_;}} + + /// + /// Disposeインターフェース + /// + public void Dispose() + { + //テクスチャ破棄 + foreach (string texture_path in texture_path_list_.Where(x=>!string.IsNullOrEmpty(x)).Distinct()) { + DeleteReadableTexture(texture_path); + } + //ディレクトリの破棄 + string path = Application.dataPath + "/../" + temporary_directory_; //"Asset/"が被るので1階層上がる + if (System.IO.Directory.Exists(path)) { + System.IO.Directory.Delete(path, true); + } + } + + /// + /// 解析対象ディレクトリ名の取得 + /// + /// The directory_name. + public static string directory_name {get{return "AlphaReadableTextureDirectory.MmdForUnity";}} + + /// + /// 読み込み可能テクスチャの作成 + /// + /// テクスチャパス + private void CreateReadableTexture(string texture_path) + { + if (!string.IsNullOrEmpty(texture_path)) { + string base_texture_path = current_directory_ + texture_path; + string readable_texture_path = temporary_directory_ + texture_path; + CreateDirectoryPath(System.IO.Path.GetDirectoryName(readable_texture_path)); + bool is_copy_success = AssetDatabase.CopyAsset(base_texture_path, readable_texture_path); + if (!is_copy_success) { + throw new System.InvalidOperationException(); + } + } + } + + /// + /// 読み込み可能テクスチャの取得 + /// + /// 読み込み可能テクスチャ + /// テクスチャパス + private Texture2D GetReadableTexture(string texture_path) + { + Texture2D result = null; + if (!string.IsNullOrEmpty(texture_path)) { + string readable_texture_path = temporary_directory_ + texture_path; + result = (Texture2D)AssetDatabase.LoadAssetAtPath(readable_texture_path, typeof(Texture2D)); + } + return result; + } + + /// + /// 読み込み可能テクスチャの削除 + /// + /// テクスチャパス + private void DeleteReadableTexture(string texture_path) + { + if (!string.IsNullOrEmpty(texture_path)) { + string readable_texture_path = temporary_directory_ + texture_path; + AssetDatabase.DeleteAsset(readable_texture_path); + } + } + + /// + /// ディレクトリの作成(親ディレクトリが無ければ再帰的に作成) + /// + /// ディレクトリパス + private static void CreateDirectoryPath(string path) + { + //親ディレクトリ作成 + string parent_path = System.IO.Path.GetDirectoryName(path); + if (!string.IsNullOrEmpty(parent_path) && !System.IO.Directory.Exists(parent_path)) { + CreateDirectoryPath(parent_path); + } + //カレントディレクトリ作成 + if (!System.IO.Directory.Exists(path)) { + string name = System.IO.Path.GetFileName(path); + AssetDatabase.CreateFolder(parent_path, name); + } + } + + private Texture2D[] textures_; //読み込み可能テクスチャ + private string[] texture_path_list_; //解析するテクスチャリスト + private string current_directory_; //カレントディレクトリ + private string temporary_directory_; //解析作業用ディレクトリ +} diff --git a/Editor/MMDLoader/Private/AlphaReadableTextureDirectoryImporter.cs b/Editor/MMDLoader/Private/AlphaReadableTextureDirectoryImporter.cs new file mode 100644 index 0000000..97d0c2a --- /dev/null +++ b/Editor/MMDLoader/Private/AlphaReadableTextureDirectoryImporter.cs @@ -0,0 +1,28 @@ +using UnityEngine; +using UnityEditor; +using System.Collections.Generic; + +public class AlphaReadableTextureDirectoryImporter : AssetPostprocessor { + + /// + /// テクスチャプリプロセッサ + /// + void OnPreprocessTexture() { + if (-1 != assetPath.IndexOf(AlphaReadableTexture.directory_name)) { + //MmdForUnityの解析用ディレクトリなら + TextureImporter importer = (TextureImporter)assetImporter; + importer.isReadable = true; //読み込み可能とする + importer.textureFormat = TextureImporterFormat.Alpha8; //アルファのみ + importer.mipmapEnabled = false; //mipmapを作成しない + if (importer.DoesSourceTextureHaveAlpha()) { + //アルファが有れば + //透過フラグを立てる + importer.alphaIsTransparency = true; + } else { + //アルファが無ければ + //解像度を最小化 + importer.maxTextureSize = 1; + } + } + } +} diff --git a/Editor/MMDLoader/Private/PMXConverter.cs b/Editor/MMDLoader/Private/PMXConverter.cs index 7801972..77461e2 100644 --- a/Editor/MMDLoader/Private/PMXConverter.cs +++ b/Editor/MMDLoader/Private/PMXConverter.cs @@ -6,7 +6,7 @@ namespace MMD { - public class PMXConverter + public class PMXConverter : System.IDisposable { /// /// GameObjectを作成する @@ -17,8 +17,11 @@ public class PMXConverter /// IKを使用するか /// スケール public static GameObject CreateGameObject(PMXFormat format, bool use_rigidbody, bool use_mecanim, bool use_ik, float scale) { - PMXConverter converter = new PMXConverter(); - return converter.CreateGameObject_(format, use_rigidbody, use_mecanim, use_ik, scale); + GameObject result; + using (PMXConverter converter = new PMXConverter()) { + result = converter.CreateGameObject_(format, use_rigidbody, use_mecanim, use_ik, scale); + } + return result; } /// @@ -29,6 +32,16 @@ public static GameObject CreateGameObject(PMXFormat format, bool use_rigidbody, /// private PMXConverter() {} + /// + /// Disposeインターフェース + /// + public void Dispose() + { + if (null != alpha_readable_texture_) { + alpha_readable_texture_.Dispose(); + } + } + /// /// GameObjectを作成する /// @@ -49,6 +62,9 @@ private GameObject CreateGameObject_(PMXFormat format, bool use_rigidbody, bool engine.scale = scale_; engine.outline_width = 1.0f; engine.material_outline_widths = format.material_list.material.Select(x=>x.edge_size).ToArray(); + engine.enable_render_queue = false; //初期値無効 + const int c_render_queue_transparent = 3000; + engine.render_queue_value = c_render_queue_transparent; MeshCreationInfo[] creation_info = CreateMeshCreationInfo(); // メッシュを作成する為の情報を作成 Mesh[] mesh = CreateMesh(creation_info); // メッシュの生成・設定 @@ -425,6 +441,12 @@ void CreateAssetForMesh(Mesh mesh, int index) /// メッシュ作成情報 Material[][] CreateMaterials(MeshCreationInfo[] creation_info) { + // 適当なフォルダに投げる + string path = format_.meta_header.folder + "/Materials/"; + if (!System.IO.Directory.Exists(path)) { + AssetDatabase.CreateFolder(format_.meta_header.folder, "Materials"); + } + //全マテリアルを作成 Material[] materials = EntryAttributesForMaterials(); CreateAssetForMaterials(materials); @@ -444,17 +466,266 @@ Material[][] CreateMaterials(MeshCreationInfo[] creation_info) /// マテリアル Material[] EntryAttributesForMaterials() { - return format_.material_list.material.Select(x=>ConvertMaterial(x)) - .ToArray(); + //材質モーフが透過を要望するか + bool[] is_transparent_by_material = IsTransparentByMaterial(); //材質 + bool[] is_transparent_by_material_morph = IsTransparentByMaterialMorph(); //材質モーフ + bool[] is_transparent_by_texture_alpha = IsTransparentByTextureAlpha(); //テクスチャのアルファ値(UV考慮済み) + + return Enumerable.Range(0, format_.material_list.material.Length) + .Select(x=>new {material_index = (uint)x + , is_transparent = is_transparent_by_material[x] || is_transparent_by_material_morph[x] || is_transparent_by_texture_alpha[x] + } + ) + .Select(x=>ConvertMaterial(x.material_index, x.is_transparent)) + .ToArray(); + } + + /// + /// 材質に依る透過確認 + /// + /// 透過かの配列(true:透過, false:不透明) + bool[] IsTransparentByMaterial() + { + //拡散色とエッジ色の透過確認 + bool[] result = format_.material_list.material.Select(x=>(x.diffuse_color.a < 1.0f) || (x.edge_color.a < 1.0f)) + .ToArray(); + return result; + } + + /// + /// 材質モーフに依る透過確認 + /// + /// 透過かの配列(true:透過, false:不透明) + bool[] IsTransparentByMaterialMorph() + { + bool[] result = Enumerable.Repeat(false, format_.material_list.material.Length) + .ToArray(); + var transparent_material_indices = format_.morph_list.morph_data.Where(x=>PMXFormat.MorphData.MorphType.Material==x.morph_type) //材質モーフなら + .SelectMany(x=>x.morph_offset) //材質モーフオフセット取得 + .Select(x=>(PMXFormat.MaterialMorphOffset)x) //材質モーフオフセットにキャスト + .Where(x=>(PMXFormat.MaterialMorphOffset.OffsetMethod.Mul==x.offset_method)&&((x.diffuse.a < 1.0f)||(x.edge_color.a < 1.0f))) //拡散色かエッジ色が透過に為るなら + .Select(x=>x.material_index) //マテリアルインデックス取得 + .Distinct(); //重複除去 + foreach (uint material_index in transparent_material_indices) { + //材質モーフに依って透過が要望されているなら + //透過扱いにする + if (material_index < (uint)format_.material_list.material.Length) { + //単体モーフのマテリアルインデックスなら + //対象マテリアルだけ透過扱い + result[material_index] = true; + } else { + //全対象モーフのマテリアルインデックスなら + //全て透過扱い + result = Enumerable.Repeat(true, result.Length).ToArray(); + break; + } + } + return result; + } + + /// + /// テクスチャのアルファ値に依る透過確認 + /// + /// 透過かの配列(true:透過, false:不透明) + bool[] IsTransparentByTextureAlpha() + { + Texture2D[] textures = GetTextureList(); + Vector2[][] uvs = GetUvList(); + bool[] result = Enumerable.Range(0, format_.material_list.material.Length) + .Select(x=>((null != textures[x]) + ? IsTransparentByTextureAlphaWithUv(textures[x], uvs[x]) + : false + )) + .ToArray(); + return result; + } + + /// + /// テクスチャの取得 + /// + /// テクスチャ配列 + Texture2D[] GetTextureList() + { + string[] texture_path = format_.material_list.material.Select(x=>x.usually_texture_index) //材質が使用しているテクスチャインデックスを取得 + .Select(x=>((x + /// UVの取得 + /// + /// UV配列 + /// + /// UVモーフにて改変される場合は未適応(0.0f)と全適応(1.0f)の2段階のみを扱い、中間適応は考慮しない。 + /// 複数のUVモーフが同一頂点に掛かる場合に多重適応すると単体では参照出来無い領域迄参照出来る様に為るが、これは考慮しない。 + /// 同様にグループモーフに依る1.0f超えも考慮しない。 + /// + Vector2[][] GetUvList() + { + uint[][] vertex_list = CreateMeshCreationInfoPacks().Select(x=>x.plane_indices).ToArray(); + + Dictionary[] uv_morphs = format_.morph_list.morph_data + .Where(x=>PMXFormat.MorphData.MorphType.Uv==x.morph_type) //UVモーフなら + .Select(x=>x.morph_offset.Select(y=>(PMXFormat.UVMorphOffset)y) + .ToDictionary(z=>z.vertex_index, z=>z.uv_offset) //頂点インデックスでディクショナリ化 + ) //UVモーフオフセット取得 + .ToArray(); + + List[] result = vertex_list.Select(x=>x.Select(y=>format_.vertex_list.vertex[y].uv).ToList()).ToArray(); + + //材質走査 + bool is_cancel = false; + for (int material_index = 0, material_index_max = result.Length; material_index < material_index_max; ++material_index) { + //UVモーフ走査 + for (int uv_morph_index = 0, uv_morph_index_max = uv_morphs.Length; uv_morph_index < uv_morph_index_max; ++uv_morph_index) { + var uv_morph = uv_morphs[uv_morph_index]; + //ブログレスパー更新 + is_cancel = EditorUtility.DisplayCancelableProgressBar("Create UV Area Infomation" + , "Material:[" + material_index + "|" + material_index_max + "]" + + format_.material_list.material[material_index].name + + "\t" + + "UV Morph:[" + uv_morph_index + "|" + uv_morph_index_max + "]" + + format_.morph_list.morph_data.Where(x=>PMXFormat.MorphData.MorphType.Uv==x.morph_type).Skip(uv_morph_index).First().morph_name + , ((((float)uv_morph_index / (float)uv_morph_index_max) + (float)material_index) / (float)material_index_max) + ); + if (is_cancel) { + break; + } + + //先行UVモーフ対象確認(三角形構成を無視して全頂点をUVモーフ参照) + var vertex_dictionary = vertex_list[material_index].Distinct().ToDictionary(x=>x, x=>true); //(UVモーフに設定されている頂点数依りも三角形構成頂点の方が多いと思うので、そちら側をlogNにする為に辞書作成) + if (uv_morph.Keys.Any(x=>vertex_dictionary.ContainsKey(x))) { + //UVモーフ対象なら + //頂点走査(三角形構成頂点走査) + for (int vertex_index = 0, vertex_index_max = vertex_list[material_index].Length; vertex_index < vertex_index_max; vertex_index+=3) { + //三角形構成頂点インデックス取り出し + uint[] tri_vertices = new []{vertex_list[material_index][vertex_index+0] + , vertex_list[material_index][vertex_index+1] + , vertex_list[material_index][vertex_index+2] + }; + //UVモーフ対象確認 + if (tri_vertices.Any(x=>uv_morph.ContainsKey(x))) { + //UVモーフ対象なら + //適応したUV値を作成 + var tri_uv = tri_vertices.Select(x=>new{original_uv = format_.vertex_list.vertex[x].uv + , add_uv = ((uv_morph.ContainsKey(x))? uv_morph[x]: Vector4.zero) + } + ) + .Select(x=>new Vector2(x.original_uv.x + x.add_uv.x, x.original_uv.y + x.add_uv.y)); + //追加 + result[material_index].AddRange(tri_uv); + } + } + } + } + if (is_cancel) { + break; + } + } + EditorUtility.ClearProgressBar(); + + return result.Select(x=>x.ToArray()).ToArray(); + } + + /// + /// UV値を考慮した、テクスチャのアルファ値に依る透過確認 + /// + /// 透過か(true:透過, false:不透明) + /// テクスチャ + /// UV値(3つ単位で三角形を構成する) + static bool IsTransparentByTextureAlphaWithUv(Texture2D texture, Vector2[] uvs) + { + bool result = true; + if (TextureFormat.Alpha8 == texture.format) { + //ファイルがDDS以外なら(AlphaReadableTextureDirectoryImporterに依ってDDS以外はAlpha8に為る) + //alphaIsTransparencyを確認する + result = texture.alphaIsTransparency; //アルファ値を持たないなら透過フラグが立っていない + } + if (result) { + //アルファ値を持つなら + //詳細確認 + result = Enumerable.Range(0, uvs.Length / 3) //3つ単位で取り出す為の元インデックス + .Select(x=>x*3) //3つ間隔に変換 + .Any(x=>IsTransparentByTextureAlphaWithUv(texture, uvs[x+0],uvs[x+1],uvs[x+2])); //三角形を透過確認、どれかが透過していたら透過とする + } + return result; + } + + /// + /// UV値を考慮した、テクスチャのアルファ値に依る透過確認 + /// + /// 透過か(true:透過, false:不透明) + /// テクスチャ + /// 三角形頂点のUV値 + /// 三角形頂点のUV値 + /// 三角形頂点のUV値 + /// + /// 理想ならば全テクセルを確認しなければならないが、 + /// 現在の実装では三角形を構成する各頂点のUV・重心・各辺の中心点の7点のテクセルしか確認していない + /// + static bool IsTransparentByTextureAlphaWithUv(Texture2D texture, Vector2 uv1, Vector2 uv2, Vector2 uv3) + { + bool result = true; //透過 + do { + //座標系が相違しているので補正 + uv1.Set(uv1.x, 1.0f - uv1.y - (1.0f / texture.height)); + uv2.Set(uv2.x, 1.0f - uv2.y - (1.0f / texture.height)); + uv3.Set(uv3.x, 1.0f - uv3.y - (1.0f / texture.height)); + + const float c_threshold = 253.0f / 255.0f; //253程度迄は不透明として見逃す + + //頂点直下 + if (texture.GetPixelBilinear(uv1.x, uv1.y).a < c_threshold) { + break; + } + if (texture.GetPixelBilinear(uv2.x, uv2.y).a < c_threshold) { + break; + } + if (texture.GetPixelBilinear(uv3.x, uv3.y).a < c_threshold) { + break; + } + + //重心 + Vector2 center = new Vector2((uv1.x + uv2.x + uv3.x) / 3.0f, (uv1.y + uv2.y + uv3.y) / 3.0f); + if (texture.GetPixelBilinear(center.x, center.y).a < c_threshold) { + break; + } + + //辺中央 + Vector2 uv12 = new Vector2((uv1.x + uv2.x) / 2.0f, (uv1.y + uv2.y) / 2.0f); + if (texture.GetPixelBilinear(uv12.x, uv12.y).a < c_threshold) { + break; + } + Vector2 uv23 = new Vector2((uv2.x + uv3.x) / 2.0f, (uv2.y + uv3.y) / 2.0f); + if (texture.GetPixelBilinear(uv23.x, uv23.y).a < c_threshold) { + break; + } + Vector2 uv31 = new Vector2((uv3.x + uv1.x) / 2.0f, (uv3.y + uv1.y) / 2.0f); + if (texture.GetPixelBilinear(uv31.x, uv31.y).a < c_threshold) { + break; + } + + //此処迄来たら不透明 + result = false; + } while(false); + return result; } /// /// マテリアルをUnity用に変換する /// /// Unity用マテリアル - /// PMX用マテリアル - Material ConvertMaterial(PMXFormat.Material material) + /// PMX用マテリアルインデックス + /// 透過か + Material ConvertMaterial(uint material_index, bool is_transparent) { + PMXFormat.Material material = format_.material_list.material[material_index]; + //先にテクスチャ情報を検索 Texture2D main_texture = null; if (material.usually_texture_index < format_.texture_list.texture_file.Length) { @@ -464,7 +735,8 @@ Material ConvertMaterial(PMXFormat.Material material) } //マテリアルに設定 - Material result = new Material(Shader.Find(GetMmdShaderPath(material, main_texture))); + string shader_path = GetMmdShaderPath(material, main_texture, is_transparent); + Material result = new Material(Shader.Find(shader_path)); // シェーダに依って値が有ったり無かったりするが、設定してもエラーに為らない様なので全部設定 result.SetColor("_Color", material.diffuse_color); @@ -476,7 +748,19 @@ Material ConvertMaterial(PMXFormat.Material material) const float c_default_scale = 0.085f; //0.085fの時にMMDと一致する様にしているので、それ以外なら補正 result.SetFloat("_OutlineWidth", material.edge_size * scale_ / c_default_scale); result.SetColor("_OutlineColor", material.edge_color); - + //カスタムレンダーキュー + { + MMDEngine engine = root_game_object_.GetComponent(); + if (engine.enable_render_queue && IsTransparentMaterial(is_transparent)) { + //カスタムレンダーキューが有効 かつ マテリアルが透過なら + //マテリアル順に並べる + result.renderQueue = engine.render_queue_value + (int)material_index; + } else { + //非透明なら + result.renderQueue = -1; + } + } + // スフィアテクスチャ if (material.sphere_texture_index < format_.texture_list.texture_file.Length) { string sphere_texture_file_name = format_.texture_list.texture_file[material.sphere_texture_index]; @@ -535,9 +819,10 @@ Material ConvertMaterial(PMXFormat.Material material) /// MMDシェーダーパス /// シェーダーを設定するマテリアル /// シェーダーに設定するメインテクスチャ - string GetMmdShaderPath(PMXFormat.Material material, Texture2D texture) { + /// 透過か + string GetMmdShaderPath(PMXFormat.Material material, Texture2D texture, bool is_transparent) { string result = "MMD/"; - if (IsTransparentMaterial(material, texture)) { + if (IsTransparentMaterial(is_transparent)) { result += "Transparent/"; } result += "PMDMaterial"; @@ -562,15 +847,9 @@ string GetMmdShaderPath(PMXFormat.Material material, Texture2D texture) { /// 透過マテリアル確認 /// /// true:透過, false:不透明 - /// シェーダーを設定するマテリアル - /// シェーダーに設定するメインテクスチャ - bool IsTransparentMaterial(PMXFormat.Material material, Texture2D texture) { - bool result = false; - result = result || (material.diffuse_color.a < 1.0f); - if (null != texture) { - result = result || texture.alphaIsTransparency; - } - return result; + /// 透過か + bool IsTransparentMaterial(bool is_transparent) { + return is_transparent; } /// @@ -648,12 +927,8 @@ bool IsNoReceiveShadowMaterial(PMXFormat.Material material) { /// /// 対象マテリアル void CreateAssetForMaterials(Material[] materials) { - // 適当なフォルダに投げる string path = format_.meta_header.folder + "/Materials/"; - if (!System.IO.Directory.Exists(path)) { - AssetDatabase.CreateFolder(format_.meta_header.folder, "Materials"); - } - + for (int i = 0, i_max = materials.Length; i < i_max; ++i) { string name = GetFilePathString(format_.material_list.material[i].name); string file_name = path + i.ToString() + "_" + name + ".asset"; @@ -1743,11 +2018,12 @@ private static string GetFilePathString(string src) { const uint c_max_vertex_count_in_mesh = 65535; //meshに含まれる最大頂点数(Unity3D的には65536迄入ると思われるが、ushort.MaxValueは特別な値として使うのでその分を除外) - GameObject root_game_object_; - PMXFormat format_; - bool use_rigidbody_; - bool use_mecanim_; - bool use_ik_; - float scale_; + GameObject root_game_object_; + PMXFormat format_; + bool use_rigidbody_; + bool use_mecanim_; + bool use_ik_; + float scale_; + AlphaReadableTexture alpha_readable_texture_ = null; } } diff --git a/Resources/MMDEngine.cs b/Resources/MMDEngine.cs index 7a4b231..62e7763 100644 --- a/Resources/MMDEngine.cs +++ b/Resources/MMDEngine.cs @@ -13,6 +13,8 @@ public class MMDEngine : MonoBehaviour { #if UNITY_EDITOR public float outline_width; //エッジ幅係数(エディタ用) public float[] material_outline_widths; //材質のエッジ幅(エディタ用) + public bool enable_render_queue; //カスタムレンダーキューの使用 + public int render_queue_value; //カスタムレンダーキュー値 #endif // 訳があってこうなってる diff --git a/Resources/PMDMaterial/Shaders/MeshPmdMaterialOutline-Trans-CullBack-NoCastShadow.shader b/Resources/PMDMaterial/Shaders/MeshPmdMaterialOutline-Trans-CullBack-NoCastShadow.shader index d640519..0192079 100644 --- a/Resources/PMDMaterial/Shaders/MeshPmdMaterialOutline-Trans-CullBack-NoCastShadow.shader +++ b/Resources/PMDMaterial/Shaders/MeshPmdMaterialOutline-Trans-CullBack-NoCastShadow.shader @@ -37,8 +37,7 @@ Shader "MMD/Transparent/PMDMaterial-with-Outline-CullBack-NoCastShadow" // Settings Tags { - // JUST After Transparent - "Queue" = "Transparent+1" + "Queue" = "Transparent" "RenderType" = "Transparent" } diff --git a/Resources/PMDMaterial/Shaders/MeshPmdMaterialOutline-Trans-CullBack.shader b/Resources/PMDMaterial/Shaders/MeshPmdMaterialOutline-Trans-CullBack.shader index 372464b..0c30e15 100644 --- a/Resources/PMDMaterial/Shaders/MeshPmdMaterialOutline-Trans-CullBack.shader +++ b/Resources/PMDMaterial/Shaders/MeshPmdMaterialOutline-Trans-CullBack.shader @@ -37,8 +37,7 @@ Shader "MMD/Transparent/PMDMaterial-with-Outline-CullBack" // Settings Tags { - // JUST After Transparent - "Queue" = "Transparent+1" + "Queue" = "Transparent" "RenderType" = "Transparent" } diff --git a/Resources/PMDMaterial/Shaders/MeshPmdMaterialOutline-Trans-NoCastShadow.shader b/Resources/PMDMaterial/Shaders/MeshPmdMaterialOutline-Trans-NoCastShadow.shader index 5c4f10a..2aa00e5 100644 --- a/Resources/PMDMaterial/Shaders/MeshPmdMaterialOutline-Trans-NoCastShadow.shader +++ b/Resources/PMDMaterial/Shaders/MeshPmdMaterialOutline-Trans-NoCastShadow.shader @@ -37,7 +37,7 @@ Shader "MMD/Transparent/PMDMaterial-with-Outline-NoCastShadow" // Settings Tags { - "Queue" = "Transparent+1" + "Queue" = "Transparent" "RenderType" = "Transparent" } diff --git a/Resources/PMDMaterial/Shaders/MeshPmdMaterialOutline-Trans.shader b/Resources/PMDMaterial/Shaders/MeshPmdMaterialOutline-Trans.shader index d1a21b5..7cfdaaa 100644 --- a/Resources/PMDMaterial/Shaders/MeshPmdMaterialOutline-Trans.shader +++ b/Resources/PMDMaterial/Shaders/MeshPmdMaterialOutline-Trans.shader @@ -37,8 +37,7 @@ Shader "MMD/Transparent/PMDMaterial-with-Outline" // Settings Tags { - // JUST After Transparent - "Queue" = "Transparent+1" + "Queue" = "Transparent" "RenderType" = "Transparent" }