MMDエフェクト改変講座

概要

プログラミング何もわからんっていう人に、プログラミングに片足突っ込んでエフェクト改変を解説する記事です。(初歩的なものなので、プログラミングの知識がある方は知っている内容ばかりだと思います。)
かなり長いですが、内容がわかれば、簡単なエフェクト改変なら大抵できるようになれます。

※注意
他のプログラミング言語を元に勝手に考えてるだけなので、間違っている可能性があります。
あくまでプログラム的にどういう意味なの?という解説なので、画像の生成方法等の解説はしません。


下準備

まず、利用規約読みましょう。大事です。改変OKなら、fxファイルxファイルのコピーを取ります。何かあった時、元ファイルは残しておいた方が良いです。また、fxファイルとxファイルは同じ名前にして下さい。(例:ikClutテスト.x、ikClutテスト.fx)
どうやって紐付けているのか、分からないのですが(知っている方いれば、教えてください......)、同じファイル名で判断してるっぽいです。

コピー

準備が終わったので、fxファイルをメモ帳か何かで開いて下さい。
notepad ++というソフトを使えば、色分けされてて見やすいらしいです。
私は元々使ってたサクラエディタをそのまま使ってます。
開き方がわからない方、エディタを開いてfxファイルをドラッグ&ドロップ、もしくは、右クリック→プログラムから開く→任意のテキストエディタを選んで下さい。私の場合はここにサクラエディタが出ていますが、なければ、別のプログラムを選択、を選択して、任意のテキストエディタを選択して下さい。

開く


コメントについて

テキストエディタでfxファイルを開いてみましょう。

画像3


何書いてるんだ、って感じですが、読める箇所もありますね。
それは、製作者様が書いて下さっているコメント、いわば解説です。
私もコメントを読まないと、どのようにソースを修正すれば良いのかよくわかりません。ありがたく読みましょう。

しかし、プログラムは人間の言語を読むことは出来ません
そのまま書くと、謎の命令がある!とエラーを吐き出してしまいます。
そこで、ここは何が書いてあっても無視して下さい、と伝える必要があります。

言語によって変わるのですが、HLSL(エフェクトの言語)は下記の記号を書くと、コメントになります。

// コメントです。
/*  コメントです。  */

‘//‘がその後の行、’/*’と‘*/‘に囲まれた部分全てがコメントになります。

上記の説明を読んで、一回どの部分がコメントなのか、考えてみて下さい。
notepat++なら、コメント部分は色が変わるらしいので、見やすいと思います。

答え合わせです。
色を付けた部分がコメントです。

画像4


ほぼコメントですね(笑
コメントとは解説、と言いましたが、よくわからない箇所もコメントになっています。理由は後ほど説明します。

とりあえず、プログラム的に意味のある行は下記の5行です。
他は削除しても動作には何も影響はありません。

#define USE_CLUT_NUM	4
#define ClutTexName1	"clut_retro3.png"
#define ClutTexName2	"clut_retro3.png"
#define ClutTexName3	"clut_bluegray.png"
#define ClutTexName4	"clut_orange.png"



変数について

ここから、中身について理解していきましょう。
5行目のコメントを読むと、「使用するCLUTの枚数。1,2,4のどれか」と書いています。更に読み進めてみましょう。
31行目のコメントでは、「ClutTexName1で指定したCLUTのみ使う」と書かれています。CLUTはClutTexName1で指定するもののようです。
ソース内を探してみると、16行目にClutTexName1があります。(他の行はコメントなので、無効)
この部分でCLUTを指定しているようですね。

#define ClutTexName1	"clut_retro3.png"

ざっくり言うと、ここではパラメータを指定しています。
例えば、エフェクトメイキングでは、パーティクルのゆらぎモーフを0.4に設定します、等と解説しますよね。
ClutTexName1は、モーフ名だと思っておいて下さい。
モーフ名をClutTexName1と命名して、モーフの値をclut_retro3.pngに設定するよ!と宣言しているのです。
続くClutTexName2、ClutTexName3、ClutTexName4も同じことをしています。
これを変数、と言います。

#define ClutTexName1	"clut_retro3.png"
#define ClutTexName2	"clut_retro3.png"
#define ClutTexName3	"clut_bluegray.png"
#define ClutTexName4	"clut_orange.png"

残りの#defineの意味も説明していきます。
#defineは値の定義みたいなものです。プログラムというものは、面倒臭いやつで、その値がどのような種類の値なのか、定義する必要があります。

floatが説明しやすいのでfloatで説明させて下さい。
floatは、パラメータが数値であると定義するものです。こんな感じです。

float num = 1.0;


float3だと3つの数値、float4だと4つの数値です。

float3 num3 = (1.0, 1.0, 1.0);
float4 num4 = (1.0, 1.0, 1.0, 1.0);

他にも文字を定義するString等色々ありますが、覚えなくとも元々書いてある値を真似て書けば問題ありません
※#defineはfloatとは種類が違うので、本来であれば分けて説明するべきものですが、わかりやすさ重視でまとめて解説しています。

今回、3つの塊しかありませんが、4つ以上の場合もあります。定義が増えたんだな~くらいに考えておいて下さい。

const float num = 1.0;

正直、const等はエフェクトを1から作りたい!っていう人以外はわからなくて良いです。知りたい人は、定数について調べて下さい。


エフェクトの構成について

今までの解説で、コメントの「以下は弄らない方が良い設定項目」、より上の部分について、何をしているのか何となくわかったかと思います。 では、下の部分は何をしているのでしょうか。

処理部分


下は、エフェクトをMMDにどう描写するのか?という実際の処理部分になります。
上部でパラメータを設定し、下部で設定したパラメータを受け取り、処理を行なうという流れです。
上部でclut_retro3.pngをClutTexName1と命名しているので、ClutTexName1と書けば、clut_retro3.pngを呼び出すことが出来ます。
下部部分にClutTexName1がないか探してみましょう。

DECL_CLUT(ClutTex1, ClutSamp1, ClutTexName1);

どうやらここで使われているようです。……何を書いているのか全くわかりませんね。
上部はただ値を宣言しているだけで、その値に意味を与えているのがこの部分です。
もしコメントがなければ、ここからどのようにパラメータが使用されているか読み取る必要があります。コメントに感謝しましょう。


記載ルールについて

実際に書き換える前に、記載ルールについて説明します。
プログラムは少しでもルールに外れるとエラーを起こします。
先程ちらっと注意書きしましたが、#defineとfloatは少し種類が違うので、異なる記載ルールを持っています。

#define moji "hoge.png"
#define num 1.0

float num = 1.0;
float3 num3 = (1.0, 1.0, 1.0);

・文字を指定する場合は、""で囲む。
・#define以外は”=”と”;”が必要
・数値を複数書く場合はコンマ区切り

他にも複数数値は()でくくる、など色々記載ルールはあります。
何故かエラーが出る、という場合、どこが違うのか元ファイルと比較してみて下さい
【”】を誤って消していた、float3でコンマとピリオドを間違えた等、よくやります。
今回は、例として16行目末尾の【"】を消してみます。

間違い

MMDに読み込んでみると下記のエラーが出ました。

画像15

もし、エラーが出ても慌てず、そのエラーメッセージを読んでみて下さい
(16,22):errorと書いてあります。
今回、【”】を抜いた行は16行目です。このように、エラーメッセージは間違い発見の手助けになります
(もっと詳しく解説すると、String(文字)が列の最後まで続いているよ、的なことが書かれています。)


修正してみる

#define ClutTexName1	"clut_retro3.png"
#define ClutTexName2	"clut_retro3.png"
#define ClutTexName3	"clut_bluegray.png"
#define ClutTexName4	"clut_orange.png"


いよいよ修正してみましょう。
書き換えるのは、最後の塊であるパラメータ部分のみです。他は触らないで下さい。
値の末尾がpngであることから、画像ファイルらしいということがわかります。フォルダの中身を見てみます。

画像8


同じ名前の画像ファイルがありました。
どうやら、この画像ファイルを使っているようです。つまり、違う画像を指定すると、違う色味のikClutが出来るのではないでしょうか。
ということで、適当に違う画像のファイル名に変えたいと思います。
すぐ上の【clut_retro2.png】にでも書き換えてみましょうか。

コメントアウト

……と思ったら、コメント部分に既にありますね。
10行目の//を削除して、11行目に//を足せば簡単に切り替えが出来そうです。書き換えると、画像1枚目から2枚目へとエフェクトの表示が変わりました。

画像10

画像11

コードをコメントにする意味がわかったでしょうか?
このように、コードをコメントにすることをコメントアウトと言います。
たまに、コメント部分にコメントアウトして下さい、と書いてあることがあるので、//を書いてコメントアウトしてやって下さい。

ちなみに、ClutTexName1は二つ以上書く意味はありません
例えば、瞳AL、爪AL、アクセサリーALというモーフがあるとします。
メイキングで、それら全てがAL0.3、AL0.4、AL0.7と説明されると、どのALやねん、とわからなくなりますよね。それと同じです。
実際の動きとして、基本的にエラーにはなりませんが、適応されるのは1つだけなので、意味がないです
名前は一意にして下さい。


パスについて

さて!これでikClut改変の説明は終わりです、長々とありがとうございました!…と言いたいところですが、説明はまだ終わりません。。。
パスという知識についても必要になります。
例えば、新たなフォルダを作成し、ここに先程の画像を移動させます。

移動

今回はtestというフォルダを作成し、clut_retro3.pngを移動させました。
その状態でエフェクトを読み込んでみます。

画像15


エラーになりましたね。
実は、画像名を指定するだけではダメで、どこにある画像なのか?も一緒に書く必要があります
そのことを、パスと言います

パスには、絶対パス相対パスの2種類があります。
例えば、Aさんがどこにいるのか説明するとします。
Aさんは東京都品川区〜にいます。その住所は、実は貴方の隣の建物でした。隣の建物にいるよ、とも説明出来ますね。
東京〜と説明するのが絶対パス隣の建物にいる、と説明するのが相対パスの考え方です。
相対パスの場合、編集しているfxファイルを起点として見ます。
今回はtestというフォルダに画像があるので、testフォルダを見に行く必要があります。

#define ClutTexName1	"test/clut_retro3.png"

このように書き換えることで、無事にエフェクトを読み込むことが出来ました。先ほどは同じフォルダに画像があったため、何も書かないで大丈夫でした。
画像ファイルが少ない場合、同じフォルダでも良いと思いますが、多い場合はtestフォルダのように新しいフォルダを作成した方がすっきりするので、おすすめです。

ちなみに、配布されているエフェクトは相対パスが使われています
難しいかもしれませんが、今までの解説を元に、なぜ相対パスが使用されているのか、考えてみて下さい。

……考えましたか?
絶対パスだと十中八九動かないからです。
絶対パスはファイルのある場所まですべて書きます。
(例 C:\MikuMikuDance_v932x64\userFile\Effect\ikClut\test\clut_retro3.png)
すなわち、エフェクト配布者と、私たち利用者のフォルダ構成が全く同じでなければなりません
相対パスであれば、fxファイルからのフォルダ構成が同じであれば読み込めるので、相対パスが使われています。

パスの書き方についてさらりと書いているので、わからない方はネット上でパスの書き方について調べてみて下さい。
それでもわからない場合は、同じフォルダに入れるのがファイル名だけで良いので簡単です。

余談ですが、パスはモデルやMMDファイルにも使われています。
モデルが真っ白になった!MMDで素材が読み込めなくなった!という経験がありませんか?
pmxやemmファイルがパス情報を保持しているからです。
パスの場所を探しにいき、その場所に素材がなければ読み込めません。

……ふぅ。やっとikClutの説明が終わりました。
上部だけですが、ikClutの中身が読めるようになっているのではないでしょうか。(なっていて欲しい。)
コメントを読んでいると、USE_CLUT_NUMでCULTの枚数を変更でき、1枚目はClutTexName1、2枚目はClutTexName2、3枚目はClutTexName3、4枚目はClutTexName4で設定するようですので、お好きに変えて試してみて下さい。
読み込む画像ファイルも、自分で作ってみると幅が広がります。
何か間違えても、最悪MMDが落ちるだけです。


他のエフェクトも見てみる1

せっかくなので、私がいつも改変方法を理解する為によくやっていることを解説したいと思います。
まずはWinMergeというソフトをDLして下さい。
このソフトは、二つのファイルの差異を出してくれるものです。
見てもらった方が早いですね。

画像15


今回はPostMovie_赤系.fx、PostMovie_青系.fxを読み込みました。オレンジ部分が差異のある箇所です。
全体色調とグラデ色の項目が違うようです。
コントラスト制御については、小数点があるのかないのかだけなので、同じです。

float3の値の意味ですが、だいたい左からRGBです。
float4ではRGBにアルファ値が追加されます。
R値、つまり一番左の数値が一番高い右側がPostMovie_赤系、B値、一番右の数値が一番高い左側がPostMovie_青系です。

PostMovieの中身が、概ね今まで解説したルールの通りになっていることがわかるかと思いますので(1番下のfloatは見た目上数値ではありませんが、数値です。)、他の項目も触ってみて、どのように変わるのか見るのも楽しいですよ。

まぁ、基本、指定するパラメータは数値かパスかのどちらかです
元の値がパスであればパスを、数値であれば数値を書いて下さい。


他のエフェクトも見てみる2

最後にもう1点だけ解説します。
ray-mmdのmaterialのmaterial_cloth.fxです。

#define ALBEDO_MAP_FROM 3
#define ALBEDO_MAP_UV_FLIP 0
#define ALBEDO_MAP_APPLY_SCALE 0
#define ALBEDO_MAP_APPLY_DIFFUSE 1
#define ALBEDO_MAP_APPLY_MORPH_COLOR 0
#define ALBEDO_MAP_FILE "albedo.png"

const float3 albedo = 1.0;
const float2 albedoMapLoopNum = 1.0;

// ~中略

const float3 customB = 1;
const float2 customBMapLoopNum = 1.0;

#include "../material_common_2.0.fxsub"

中略していますが、material_cloth.fxの中身はパラメータのみで、処理部分がありません。どうやって処理しているのでしょうか。

#include "../material_common_2.0.fxsub"

実はこの部分が処理部分です。
includeとは含むという意味です。
material_common_2.0.fxsubを含む、つまり、material_common_2.0.fxsubというファイルの中身が、ここに書いているのと同等の意味になります。
material_common_2.0.fxsubの中身を見てみましょう。

画像15

rayのように、長くてファイル数が多い場合は、処理部分を切り出している時があります
もし、フォルダを移動させると、material_common_2.0.fxsubが読み込めなくなるので、エラーが発生します。
気を付けて下さい。


最後に

長い解説なのに、ここまで読んで下さり、ありがとうございました!!
解説を読んで、エフェクト改変ができるようになれば嬉しいです。
改変できるようになりました!ってもし教えてくれると、私が喜びます。
エフェクト配布してくれても、私が喜びます。(その際は、必ず再配布OKか確認して下さい。)
とりあえず、エフェクト弄って遊んでみて下さい。
エフェクト改変楽しいですよ!良きMMDライフを〜!!


クレジット
ikClut(ikeno様)、Postmovie(ビームマンP様)、ray-mmd(Rui様)
今回解説に使用させて頂きました。ありがとうございます。
何か問題あれば、ご指摘下さい。





この記事が気に入ったらサポートをしてみませんか?