string GetMMDShaderPath(PMD.PMDFormat.Material model_material, Texture2D texture) { string result = "MMD/"; if (IsTransparentMaterial(model_material, texture)) { result += "Transparent/"; } result += "PMDMaterial"; if (IsEdgeMaterial(model_material)) { result += "-with-Outline"; } if (IsCullBackMaterial(model_material)) { result += "-CullBack"; } if (IsNoCastShadowMaterial(model_material)) { result += "-NoCastShadow"; } #if MFU_ENABLE_NO_RECEIVE_SHADOW_SHADER //影受け無しのシェーダはまだ無いので無効化 if (IsNoReceiveShadowMaterial(model_material)) { result += "-NoReceiveShadow"; } #endif //MFU_ENABLE_NO_RECEIVE_SHADOW_SHADER return(result); }
//透過マテリアル確認(true:透過, false:不透明) bool IsTransparentMaterial(PMD.PMDFormat.Material model_material, Texture2D texture) { bool result = false; result = result || (model_material.alpha < 0.98f); //0.98f以上は不透明と見做す(0.98fに影生成情報を埋め込んでいる為) if (null != texture) { result = result || texture.alphaIsTransparency; } return(result); }
//影受け無しマテリアル確認(true:影受け無し, false:影受け) bool IsNoReceiveShadowMaterial(PMD.PMDFormat.Material model_material) { bool result; if (0.98f == model_material.alpha) //浮動小数点の比較だけど、0.98fとの同値確認でPMXエディタの0.98と一致したので一旦これで。 //影受け無し(不透明度が0.98fは特別扱いで影受け無し)なら { result = true; } else { //影受け有りなら result = false; } return(result); }
//エッジマテリアル確認(true:エッジ有り, false:無エッジ) bool IsEdgeMaterial(PMD.PMDFormat.Material model_material) { bool result; if (0 == model_material.edge_flag) { //エッジ無し result = false; } else { //エッジ有りなら result = true; } return(result); }
//無影マテリアル確認(true:無影, false:影放ち) bool IsNoCastShadowMaterial(PMD.PMDFormat.Material model_material) { bool result; if (0 == model_material.edge_flag) { //エッジ無し //無影 result = true; } else { //エッジ有りなら //影放ち result = false; } return(result); }
//背面カリングマテリアル確認(true:背面カリングする, false:背面カリングしない) bool IsCullBackMaterial(PMD.PMDFormat.Material model_material) { bool result; if (1.0f <= model_material.alpha) { //不透明なら //背面カリングする result = true; } else if (0.99f <= model_material.alpha) { //不透明の両面描画なら //背面カリングしない result = false; } else { //透過なら //背面カリングしない result = false; } return(result); }
// 色の生成 void EntryColors(Material[] mats) { // マテリアルの生成 for (int i = 0; i < mats.Length; i++) { // PMDフォーマットのマテリアルを取得 PMD.PMDFormat.Material pmdMat = format_.material_list.material[i]; //先にテクスチャ情報を検索 Texture2D main_texture = null; if (pmdMat.texture_file_name != "") { string path = format_.folder + "/" + pmdMat.texture_file_name; main_texture = AssetDatabase.LoadAssetAtPath(path, typeof(Texture2D)) as Texture2D; } //マテリアルに設定 switch (shader_type_) { case ShaderType.Default: // デフォルト mats[i] = new Material(Shader.Find("Transparent/Diffuse")); mats[i].color = pmdMat.diffuse_color; Color cbuf = mats[i].color; cbuf.a = pmdMat.alpha; // これでいいのか? mats[i].color = cbuf; break; case ShaderType.HalfLambert: // ハーフランバート mats[i] = new Material(Shader.Find("Custom/CharModel")); mats[i].SetFloat("_Cutoff", 1 - pmdMat.alpha); mats[i].color = pmdMat.diffuse_color; break; case ShaderType.MMDShader: mats[i] = new Material(Shader.Find(GetMMDShaderPath(pmdMat, main_texture))); // シェーダに依って値が有ったり無かったりするが、設定してもエラーに為らない様なので全部設定 mats[i].SetColor("_Color", pmdMat.diffuse_color); mats[i].SetColor("_AmbColor", pmdMat.mirror_color); 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); // ここでスフィアマップ string path = format_.folder + "/" + pmdMat.sphere_map_name; Texture sphere_map; if (System.IO.File.Exists(path)) { // ファイルの存在を確認 sphere_map = UnityEditor.AssetDatabase.LoadAssetAtPath(path, typeof(Texture)) as Texture; // 乗算と加算判定 string ext = System.IO.Path.GetExtension(pmdMat.sphere_map_name); switch (ext) { case ".spa": // 加算 mats[i].SetTexture("_SphereAddTex", sphere_map); mats[i].SetTextureScale("_SphereAddTex", new Vector2(1, -1)); break; case ".sph": // 乗算 mats[i].SetTexture("_SphereMulTex", sphere_map); mats[i].SetTextureScale("_SphereMulTex", new Vector2(1, -1)); break; default: // 加算扱い goto case ".spa"; } } // トゥーンの位置を取得 string toon_name = pmdMat.toon_index != 0xFF ? format_.toon_texture_list.toon_texture_file[pmdMat.toon_index] : "toon00.bmp"; string resource_path = UnityEditor.AssetDatabase.GetAssetPath(Shader.Find("MMD/HalfLambertOutline")); resource_path = System.IO.Path.GetDirectoryName(resource_path); // resourceディレクトリを取得 resource_path += "/toon/" + toon_name; // トゥーンが存在するか確認 if (!System.IO.File.Exists(resource_path)) { // 自前トゥーンの可能性がある resource_path = format_.folder + "/" + format_.toon_texture_list.toon_texture_file[pmdMat.toon_index]; if (!System.IO.File.Exists(resource_path)) { Debug.LogError("Do not exists toon texture: " + format_.toon_texture_list.toon_texture_file[pmdMat.toon_index]); break; } } // テクスチャの割り当て Texture toon_tex = UnityEditor.AssetDatabase.LoadAssetAtPath(resource_path, typeof(Texture)) as Texture; mats[i].SetTexture("_ToonTex", toon_tex); mats[i].SetTextureScale("_ToonTex", new Vector2(1, -1)); break; } // テクスチャが空でなければ登録 if (null != main_texture) { mats[i].mainTexture = main_texture; mats[i].mainTextureScale = new Vector2(1, -1); } } }