Ledの日記: MMEfx2MMM
背景
MikuMikuDance+MMEで使用する.fxファイルとMikuMikuMoving(MMM)で使用する.fxmファイルはどちらも基本的にHLSLで書くことになっているが、いくつか仕様に差異があるため、一つのシェーダをそのまま相互利用はできない。このためコミュニティのシェーダ開発者は手作業で相互の対応を行っているか、あるいは片方(たいていの場合MMD+MME)でしか利用できないという現状がある。つまりMMD+MMEの方がメジャーで、3Dモデルも付帯ツールもMMDでの動作をターゲットにして作られることが多い。このためMMMでの動画制作には不遇な面もある。
一方で、MMMはUI上優れた点もあるので、動画作成者の中にはMMMをメインで使っている人もいるようだ。例えば複数ボーンの操作であるとか、ボーンやカメラの多段化、字幕などと呼ばれる機能がMMMでは標準で搭載されているのだが、MMDで同様のことをやろうとするとひと手間余計にかかる。
そういうわけでMMD+MME用に書かれているシェーダをMMMで使用するためのフィルタがあると便利である。また、MMD+MME用に作られて配布されている.fxファイルは「非営利の利用なら自分で勝手に編集して再配布してもいいよ、商用の時だけ相談してね」という程度の緩い使用許諾であることが多いのでライセンス上の問題は発生しにくそうだ。そういうわけで、MMD+MME用のシェーダ.fxファイルを食わせるとMMM用のシェーダを吐くような、まあそういうものを作りたいな、というわけ。
現在の進捗状況
MMD+MME用シェーダをMMM用シェーダに書き換える手作業を何回かやってみた。
機械的にできそうなシェーダの書き換えルールを洗い出した。
自動化のためのツールをC#で書いている。
なお、開発言語をC#とするのはMMMにプラグイン機能があって、MMMプラグインはC#で書くことになっているため。余裕があればMMMプラグインとして配布するのがしっくりくるだろう。
-----
MME用の.fxファイルをMMMに持っていくときの手順を忘れてた。ツイッターには書いたがすぐに検索しづらくなるのでこっちに転記、MMM対応とはつまり
エッジ描画処理を修正
// 輪郭描画用テクニック
technique EdgeTec < string MMDPass = "edge"; > {
pass DrawEdge {
// MMM対応ここから ///////////////////////
AlphaBlendEnable = FALSE;
AlphaTestEnable = FALSE;
// MMM対応ここまで ///////////////////////
VertexShader = compile vs_2_0 ColorRender_VS();
PixelShader = compile ps_2_0 ColorRender_PS();
}
}
各頂点シェーダの引数に以下を追加
MMM_SKINNING_INPUT IN,
各頂点シェーダの最初に以下を書く
MMM_SKINNING_OUTPUT SkinOut = MMM_SkinnedPositionNormal(IN.Pos, IN.Normal, IN.BlendWeight, IN.BlendIndices, IN.SdefC, IN.SdefR0, IN.SdefR1);
その後、頂点シェーダの引数変数にSkinOutのメンバから代入
エッジの頂点シェーダだけ、最初にこれを追加
Pos += float4(SkinOut.Normal, 0) * IN.EdgeWeight * EdgeWidth * distance(SkinOut.Position.xyz, CameraPosition);
なお、Posは各シェーダの変数名(POSITIONセマンティクス)に合わせる。
MMDPass="object"のtechniqueを消した後 MMDPass="object_ss"をMMDPass="object"に書き換える
MMMのエフェクトではuse_subtextureは未定義なのでグローバル変数で常にfalseとして定義する。サブテクスチャを使いたいときどうするかは今後の課題。
---
MMM_GetToonColorとかMMM_GetSelfShadowToonColorとかを無視してfull.fxのシャドウ処理をベタッと貼っても動く。ただしLightDirectionをLightDirection[0]にする。
---
以下のライト関連の記述はMME用そのままでも動作するらしい。
// ライト関連
//float4x4 LightWorldViewProjMatrix : WORLDVIEWPROJECTION < string Object = "Light"; > ;
//float4x4 LightViewProjMatrix : VIEWPROJECTION< string Object ="Light"; >;
//float3 LightDirection : DIRECTION < string Object = "Light"; >;
//ライト関連
bool LightEnables[MMM_LightCount] : LIGHTENABLES; // 有効フラグ
float4x4 LightWVPMatrices[MMM_LightCount] : LIGHTWVPMATRICES; // 座標変換行列
#define LightWorldViewProjMatrix LightWVPMatrices[0]
float3 LightDirections[MMM_LightCount] : LIGHTDIRECTIONS; // 方向
#define LightDirection LightDirections[0]
float3 LightPositions[MMM_LightCount] : LIGHTPOSITIONS; // ライト位置
float LightZFars[MMM_LightCount] : LIGHTZFARS; // ライトzFar値
// ライト色
//float3 LightDiffuse : DIFFUSE ;
//float3 LightAmbient : AMBIENT ;
//float3 LightSpecular : SPECULAR ;
// ライト色
float3 LightDiffuses[MMM_LightCount] : LIGHTDIFFUSECOLORS;
#define LightDiffuse LightDiffuses[0]
float3 LightAmbients[MMM_LightCount] : LIGHTAMBIENTCOLORS;
#define LightAmbient LightAmbients[0]
float3 LightSpeculars[MMM_LightCount] : LIGHTSPECULARCOLORS;
#define LightSpecular LightSpeculars[0]
//float3 MaterialToon : TOONCOLOR;
float4 MaterialToon : TOONCOLOR; // MMM独自
float EdgeWidth : EDGEWIDTH; // MMM独自
MMEfx2MMM More ログイン