MMDの輪郭線(エッジ)の太さと色はどこで決まるか|材質の指定と頂点ごとの倍率

髪の毛先や顔の一部だけ輪郭線を消す、という指定がPMXにはあります。材質ではなく頂点ごとに書くもので、three.jsの描画はこれを読んでいませんでした。

最終更新: 2026-10-06 · 実PMX 3体とステージ1つの材質と頂点を three.js 同梱のパーサで読んで数え、人物Aの顔に寄った画面で直す前と後の画素を比べて確認

このサイトの再生は、2026-10-06から頂点ごとの輪郭線の倍率を当てています。

材質ごとの指定は3つ

項目中身three.jsのMMDLoader
描画フラグ 0x10この材質に輪郭線を描くか読む(描くかどうか)
エッジ色赤・緑・青・不透明度読む(色と不透明度)
エッジサイズ太さ(1が標準)読む(300で割って画面上の太さにする)
モデル材質輪郭線ありエッジサイズ輪郭線なしの材質の例
人物A(ad_ik2)53400.7が35、0.4が3、0.5と0.68が1ずつ目・白目・瞳レンズ・眉・ハイライト・チーク・髪影
アリシア22120.8が11、1.0が1eye・eyebrush・tere(照れ)・hairShadow
ステージ2317すべて1.0床・天井・壁

目・眉・頬の赤み・影の材質は、どのモデルも輪郭線を切っていました。輪郭線の色は、人物Aでは赤みのある色(0.45, 0.20, 0.30)や濃い灰色など10通り、不透明度は0.6〜0.7でした。真っ黒の不透明度1ではありません。

three.jsは輪郭線を「画面上の太さ」として描きます(カメラから遠くても細くならない。MMDのスケールと単位)。エッジサイズを300で割った値を太さにしていて、ソースには「TODO: better calculation?」と書かれています。MMD本体と同じ太さに見えるかは、ここでは確かめていません。

頂点ごとの「エッジ倍率」

PMXの頂点には、位置・法線・UV・ウェイトのほかにエッジ倍率(Float32)が1つあります。材質のエッジサイズに掛ける値で、0にするとその頂点のまわりだけ輪郭線が消えます。

モデル頂点倍率が1でない頂点どこ
人物A(ad_ik2)39,540342(0が340、0.5が2)顔00の182頂点・髪00の160頂点
人物A(ad_org8)40,688342(同上)同上
アリシア22,3110—
ステージ4,6690—

three.jsのOutlineEffectは、この倍率を見ていません。 頂点シェーダに const float ratio = 1.0; と書かれ、「TODO: support outline thickness ratio for each vertex」のままです。パーサは倍率を読んでいるのに、描くときは全頂点を1として扱っていました。

このサイトでの直し方と結果

モデルを読み込むときに倍率を頂点の属性として持たせ、輪郭線のシェーダの ratio をその属性に置き換えました。倍率を持たないモデル(全頂点が1のもの)には属性を足さず、そのときは1として描くので、今までと同じ太さになります。

人物Aの頭に寄った画面(1200×900、物理を止めて比較)で、直す前と後で変わった画素は、正面554・横507・後ろ350でした。拡大して見比べると、変わったのは主に髪の毛先の輪郭線で、作者が倍率0にしたところの線が消えています。

  • PMD(古い形式)にも頂点ごとの「輪郭線を描かない」指定がありますが、手元に実物が無く確かめられないため、PMDには当てていません。
  • three.jsは、PMDの輪郭線を材質ごとに黒・太さ0.003で描きます(PMDの材質は色と太さを持たないため)。