例によって本家と全く同じ処理というわけではありませんのでご注意ください。
MMDはトゥーン用テクスチャを10個持っています。
そして、モデルデータにはそのインデックスが入っています。
PMDファイルの内部構造についてはこちらのサイトが詳しいです。
MMDのモデルデータ(PMD)形式 めも4 - 通りすがりの記憶
拡張仕様でデフォルトのテクスチャ以外も使えるようですが、
読み込み位置が遠いので今回は対応しません。
よって、テクスチャを10個読み込んで、
インデックスデータを読み込めば下準備完了です。
トゥーンレンダリング自体も、単純な仕様を選べば難しいものではありません。
今回はディレクショナルライトと、法線ベクトルの内積を取り、
180度(光が強く当たる) ~ 90度以下(光が当たらない)の値を取ります。(-1 ~ 1の値になります)
この値を元に、テクスチャ座標の0(光が強く当たる) ~ 1(光が当たらない)として使います。
通常の拡散反射の計算ですと角度によってなめらかに光の強さが変わりますが、
テクスチャから色を取る事によって段階的に光の強さが変わります。
こんな感じのシェーダを書きました
| 1 | float force = 1; | 
|---|---|
| 2 | if (minDepth >= input.lpos.z) // 深度バッファシャドウの判定 | 
| 3 | { | 
| 4 | // 法線と光線の角度を内積として取得する | 
| 5 | force = dot(normalize(input.normal), normalize(directionalLightDirection)); | 
| 6 | |
| 7 | // テクスチャ座標に変換する | 
| 8 | force = saturate(force + 1); | 
| 9 | } | 
| 10 | |
| 11 | // 与えられた値を元にtoonテクスチャから色を拾い、拡散反射光として扱う | 
| 12 | float3 diffuse = toonTex.Sample(clampSampler, float2(0, force)); | 
実行するとこうなります。顔の影などが、ある点から表示されているのがわかります。
