From 8f12896e2570b10fdd44f4baba1cd164dcd0d5fe Mon Sep 17 00:00:00 2001 From: "eral.r.l" Date: Tue, 3 Dec 2013 03:30:10 +0900 Subject: [PATCH] =?UTF-8?q?=E7=94=BB=E8=A7=92=E3=82=84=E3=82=B9=E3=82=B1?= =?UTF-8?q?=E3=83=BC=E3=83=AB=E3=81=AB=E4=BE=9D=E3=81=A3=E3=81=A6=E3=82=A8?= =?UTF-8?q?=E3=83=83=E3=82=B8=E5=B9=85=E3=81=8C=E5=A4=89=E3=82=8F=E3=82=8B?= =?UTF-8?q?=E4=B8=8D=E5=85=B7=E5=90=88=E3=81=AE=E4=BF=AE=E6=AD=A3=20?= =?UTF-8?q?=E3=82=A8=E3=83=83=E3=82=B8=E3=81=AB=E3=82=A8=E3=83=83=E3=82=B8?= =?UTF-8?q?=E4=B8=8D=E9=80=8F=E6=98=8E=E5=BA=A6=E3=81=8C=E5=8F=8D=E6=98=A0?= =?UTF-8?q?=E3=81=95=E3=82=8C=E3=81=A6=E3=81=84=E3=81=AA=E3=81=84=E4=B8=8D?= =?UTF-8?q?=E5=85=B7=E5=90=88=E3=81=AE=E4=BF=AE=E6=AD=A3=20=E3=82=A8?= =?UTF-8?q?=E3=83=87=E3=82=A3=E3=83=88=E6=99=82=E3=81=AB=E6=96=BC=E3=81=91?= =?UTF-8?q?=E3=82=8B=E3=82=A8=E3=83=83=E3=82=B8=E5=B9=85=E3=83=AA=E3=82=A2?= =?UTF-8?q?=E3=83=AB=E3=82=BF=E3=82=A4=E3=83=A0=E5=A4=89=E6=9B=B4=E3=81=AE?= =?UTF-8?q?=E5=AF=BE=E5=BF=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Editor/MMDEngineEditor.cs | 69 ++++++++++++++----- Editor/MMDLoader/Private/MMDConverter.cs | 15 ++-- Editor/MMDLoader/Private/PMXConverter.cs | 8 ++- Resources/MMDEngine.cs | 13 ++-- .../Shaders/MeshPmdMaterialVertFrag.cginc | 11 +-- 5 files changed, 79 insertions(+), 37 deletions(-) diff --git a/Editor/MMDEngineEditor.cs b/Editor/MMDEngineEditor.cs index 40b4f0d..dc1f1fa 100644 --- a/Editor/MMDEngineEditor.cs +++ b/Editor/MMDEngineEditor.cs @@ -53,22 +53,44 @@ private bool OnInspectorGUIforOutlineWidth() { MMDEngine self = (MMDEngine)target; bool is_update = false; + +#if !MFU_DISABLE_LEGACY_DATA_SUPPORT + if (0 == self.material_outline_widths.Length) { + //material_outline_widthsが設定されていないなら(昔の変換データ) + Material[] materials = GetMaterials(self); + if (0 < materials.Length) { + //マテリアルが有り、今のエッジ幅が0.0fで無いなら + //データ生成を試みる + self.material_outline_widths = materials.Select(x=>x.GetFloat("_OutlineWidth")).ToArray(); + } + } +#endif float outline_width = self.outline_width; outline_width = EditorGUILayout.Slider("Outline Width", outline_width, 0.0f, 2.0f); if (self.outline_width != outline_width) { //変更が掛かったなら + 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.RecordObject(self, "Outline Width Change"); + Undo.RecordObjects(record_objects, "Outline Width Change"); #else - Undo.RegisterUndo(self, "Outline Width Change"); + Undo.RegisterUndo(record_objects, "Outline Width Change"); #endif //更新 + const float c_default_scale = 0.085f; //0.085fの時にMMDと一致する様にしているので、それ以外なら補正 self.outline_width = outline_width; + foreach (var i in Enumerable.Range(0, materials.Length) + .Select(x=>new {material = materials[x], edge_size = self.material_outline_widths[x]})) { + i.material.SetFloat("_OutlineWidth", i.edge_size * outline_width * self.scale / c_default_scale); + } is_update = true; } + return is_update; } @@ -141,7 +163,7 @@ private bool OnInspectorGUIforIkList() } return is_update; } - + /// /// シェーダーリストの為のInspector描画 /// @@ -156,21 +178,7 @@ private bool OnInspectorGUIforShaderList() //シェーダーリスト内部 if (shader_display_) { //シェーダーリストを表示するなら - SkinnedMeshRenderer[] renderers = self.GetComponentsInChildren(); - Material[] materials = renderers.SelectMany(x=>x.sharedMaterials).Distinct().ToArray(); - if (1 < renderers.Length) { - //rendererが複数有る(≒PMX)なら - //PMXでは名前の先頭にはマテリアルインデックスが有るのでそれを参考にソート - //PMDではrendererが1つしか無く、かつソート済みの為不要 - System.Array.Sort(materials, (x,y)=>{ - string x_name = x.name.Substring(0, x.name.IndexOf('_')); - string y_name = y.name.Substring(0, y.name.IndexOf('_')); - int x_int, y_int; - Int32.TryParse(x_name, out x_int); - Int32.TryParse(y_name, out y_int); - return x_int - y_int; - }); - } + Material[] materials = GetMaterials(self); GUIStyle style = new GUIStyle(); style.margin.left = 10; EditorGUILayout.BeginVertical(style); @@ -411,6 +419,31 @@ static Shader CreateShaderFromShaderFlag(ShaderFlag flag) { return result; } + /// + /// 本来の順序で材質一覧の取得 + /// + /// 材質一覧 + /// 材質を取得するMMDEngine + static Material[] GetMaterials(MMDEngine engine) + { + SkinnedMeshRenderer[] renderers = engine.GetComponentsInChildren(); + Material[] result = renderers.SelectMany(x=>x.sharedMaterials).Distinct().ToArray(); + if (1 < renderers.Length) { + //rendererが複数有る(≒PMX)なら + //PMXでは名前の先頭にはマテリアルインデックスが有るのでそれを参考にソート + //PMDではrendererが1つしか無く、かつソート済みの為不要 + System.Array.Sort(result, (x,y)=>{ + string x_name = x.name.Substring(0, x.name.IndexOf('_')); + string y_name = y.name.Substring(0, y.name.IndexOf('_')); + int x_int, y_int; + Int32.TryParse(x_name, out x_int); + Int32.TryParse(y_name, out y_int); + return x_int - y_int; + }); + } + return result; + } + [Flags] private enum ShaderFlag { MmdShader = 1<< 0, //MMDシェーダー diff --git a/Editor/MMDLoader/Private/MMDConverter.cs b/Editor/MMDLoader/Private/MMDConverter.cs index baed843..78cd7bd 100644 --- a/Editor/MMDLoader/Private/MMDConverter.cs +++ b/Editor/MMDLoader/Private/MMDConverter.cs @@ -62,7 +62,10 @@ private GameObject CreateGameObject_(PMDFormat format, ShaderType shader_type, b BuildingBindpose(mesh, materials, bones); MMDEngine engine = root_game_object_.AddComponent(); + //スケール・エッジ幅 engine.scale = scale_; + engine.outline_width = default_outline_width; + engine.material_outline_widths = Enumerable.Repeat(1.0f, materials.Length).ToArray(); // IKの登録 if (use_ik_) @@ -326,10 +329,11 @@ void EntryColors(Material[] mats) mats[i].SetFloat("_Opacity", pmdMat.alpha); mats[i].SetColor("_SpecularColor", pmdMat.specular_color); mats[i].SetFloat("_Shininess", pmdMat.specularity); + // エッジ + const float c_default_scale = 0.085f; //0.085fの時にMMDと一致する様にしているので、それ以外なら補正 + mats[i].SetFloat("_OutlineWidth", default_outline_width * scale_ / c_default_scale); + mats[i].SetColor("_OutlineColor", default_outline_color); - // エッジ - mats[i].SetFloat("_OutlineWidth", 0.2f); // これぐらいがいい気がする - // ここでスフィアマップ string path = format_.folder + "/" + pmdMat.sphere_map_name; Texture sphere_map; @@ -1003,7 +1007,10 @@ private static string GetFilePathString(string src) { .Replace("\n", string.Empty) .Replace("\r", string.Empty); } - + + static float default_outline_width = 0.2f; //標準エッジ幅 + static Color default_outline_color = Color.black; //標準エッジ色 + GameObject root_game_object_; PMDFormat format_; ShaderType shader_type_; diff --git a/Editor/MMDLoader/Private/PMXConverter.cs b/Editor/MMDLoader/Private/PMXConverter.cs index 94d1624..7801972 100644 --- a/Editor/MMDLoader/Private/PMXConverter.cs +++ b/Editor/MMDLoader/Private/PMXConverter.cs @@ -45,8 +45,11 @@ private GameObject CreateGameObject_(PMXFormat format, bool use_rigidbody, bool scale_ = scale; root_game_object_ = new GameObject(format_.meta_header.name); MMDEngine engine = root_game_object_.AddComponent(); //MMDEngine追加 + //スケール・エッジ幅 engine.scale = scale_; - + engine.outline_width = 1.0f; + engine.material_outline_widths = format.material_list.material.Select(x=>x.edge_size).ToArray(); + MeshCreationInfo[] creation_info = CreateMeshCreationInfo(); // メッシュを作成する為の情報を作成 Mesh[] mesh = CreateMesh(creation_info); // メッシュの生成・設定 Material[][] materials = CreateMaterials(creation_info); // マテリアルの生成・設定 @@ -470,7 +473,8 @@ Material ConvertMaterial(PMXFormat.Material material) result.SetColor("_SpecularColor", material.specular_color); result.SetFloat("_Shininess", material.specularity); // エッジ - result.SetFloat("_OutlineWidth", material.edge_size); + 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); // スフィアテクスチャ diff --git a/Resources/MMDEngine.cs b/Resources/MMDEngine.cs index 2a2cefc..7a4b231 100644 --- a/Resources/MMDEngine.cs +++ b/Resources/MMDEngine.cs @@ -6,12 +6,15 @@ public class MMDEngine : MonoBehaviour { public float scale = 1.0f; //読み込みスケール - public float outline_width = 0.1f; public bool useRigidbody = false; public int[] groupTarget; // 非衝突剛体リスト public GameObject[] rigids; // 剛体リスト public GameObject[] joints; // ConfigurableJointの入っているボーンのリスト - +#if UNITY_EDITOR + public float outline_width; //エッジ幅係数(エディタ用) + public float[] material_outline_widths; //材質のエッジ幅(エディタ用) +#endif + // 訳があってこうなってる public int[] ignore1; public int[] ignore2; @@ -39,12 +42,6 @@ public class MMDEngine : MonoBehaviour { // Use this for initialization void Start () { - SkinnedMeshRenderer[] renderers = GetComponentsInChildren(); - foreach (var m in renderers.SelectMany(x=>x.sharedMaterials)) - { - m.SetFloat("_OutlineWidth", this.outline_width); - } - if (useRigidbody) { ignoreList = new List(); diff --git a/Resources/PMDMaterial/Shaders/MeshPmdMaterialVertFrag.cginc b/Resources/PMDMaterial/Shaders/MeshPmdMaterialVertFrag.cginc index 915da8f..f811a78 100644 --- a/Resources/PMDMaterial/Shaders/MeshPmdMaterialVertFrag.cginc +++ b/Resources/PMDMaterial/Shaders/MeshPmdMaterialVertFrag.cginc @@ -29,14 +29,15 @@ struct v2f v2f vert( appdata_base v ) { v2f o; - float4 pos = mul( UNITY_MATRIX_MVP, v.vertex ); - float width = 0.01 * _OutlineWidth; - float4 edge_pos = v.vertex + pos.w * width * float4( v.normal, 0.0 ); - o.pos = mul( UNITY_MATRIX_MVP, edge_pos ); + float4 pos = mul(UNITY_MATRIX_MVP, v.vertex); + float4 normal = mul(UNITY_MATRIX_MVP, float4(v.normal, 0.0)); + float width = _OutlineWidth / 1024.0; //目コピ調整値(算術根拠無し) + float depth_offset = pos.z / 4194304.0; //僅かに奥に移動(floatの仮数部は23bitなので(1<<21)程度で割った値は丸めに入らないが非常に小さな値の筈) + o.pos = pos + normal * float4(width, width, 0.0, 0.0) + float4(0.0, 0.0, depth_offset, 0.0); return o; } half4 frag( v2f i ) : COLOR { - return half4( _OutlineColor.rgb, _Opacity ); + return half4( _OutlineColor.rgb, _OutlineColor.a * _Opacity ); }