アニメやCG制作を中心に活躍しているプロジェクトスタジオQBlenderでのアニメ制作の実務テクニックを解説! これから導入を考えている方や、アニメ業界を志望する学生の方へ、これまで培ってきたノウハウを紹介します。

はじめに

こんにちは。プロジェクトスタジオQ、モデリングディレクターの林田 樹です。

この記事は「トゥーンシェーダのつくり方(前篇)」の続きになります。前回と重複する説明はいくつか省いている箇所がありますので、合わせてお読みください。

主要な制作アプリケーション
Blender 3.0

第3回:トゥーンシェーダのつくり方(後篇)

この記事で説明するトゥーンシェーダも「トゥーンシェーダのつくり方(前篇)」で説明したものと基本的な使い方は同じで、中身が少しちがうものになります。

こちらのメリットは

●アセットごと、パーツごとにライトを分けられる
●Eevee・Cyclesどちらのレンダラでも使用できる
●シェーダーコンパイルにほとんど時間がかからない(軽い)

といったものがあります。前篇で解説した「toonShading1」より設定方法やアセットの取り回しが少し複雑になるので、案件によって2つのトゥーンシェーダを使い分けています。

ハーフランバートを使ったトゥーンシェーダ

これから説明するトゥーンシェーダは説明のため、「toonShading2」と呼びます。

「toonShading2」の項目

名前

解説

hl

ハイライト

normal

通常⾊

sdw1

1号影

sdw2

2号影

hl_threshold

ハイライトの閾値

sdw1_threshold

1号影の閾値

sdw2_threshold

2号影の閾値

hlMap

ハイライトの出やすさを設定するテクスチャを挿す場所

shadeMap

影の出やすさを設定するテクスチャを挿す場所

normalMap

ノーマルマップを挿す場所

normalMapStrength

ノーマルマップの影響度 ノーマルマップを挿さない場合は0にします

mainLight

シェーディング⽤のライトの⽅向を取得するグループノードを挿す場所

highLight

スペキュラー⽤のライトの⽅向を取得するグループノードを挿す場所

transparency

透明度

partsMsk

部位ごとのRGBマスク

陰影の作成

前回解説した「toonShading1」ではディフューズシェーダを使っていたのでライトから見て球の反対側に影が大きく出るため、もっと明るい範囲を増やしたい場合はライトを足すしかありませんでした。また、2号影の範囲もあまり絞ることができません。そこで、陰影の範囲をもち上げてライトで照らされた側から反対側まで滑らかなグラデーションになるようにして、すべての領域を0以上の明るさにしておきます。これはハーフランバートと呼ばれるものです。

つくるのにはライトのベクトルとメッシュの法線の内積をとるのですが、いったんライトのベクトルのとり方については置いておき、先に陰影のつくり方から説明します。ライトのベクトル(左端にある[Combine XYZ]ノード)とメッシュの法線を[VectorMath>DotProduct]に接続すると、擬似的にディフューズシェーダと同じような陰影になります。

次に[Math>MultiplyAdd]に接続して0.5で乗算し、0.5を加算するとハーフランバートができます。本来はさらに2乗して陰影を強調するのですが、今回は省いています。

こうしてできたグラデーションを[Math>Greather Than]ノードで二値化して、陰影のマスクを作成。後は「toonShading1」と同様です。左がハーフランバートの陰影。右が二値化して色を付け、トゥーン調にした結果です。2号影がライトの反対側の狭い範囲に出ています。

ハイライトの作成

陰影用のライトと同じ方向からハイライトをつくろうとすると、ほしい位置にハイライトが出ないことが多いので、ライト方向を取得する部分をもうひとつつくって分けています。

先程はハーフランバートの計算でしたが、ハイライトでは視点によって明るい位置が変化してほしいのでスペキュラをつくります。画像のようにノードを接続して陰影の上にハイライトの色が乗るようにしました。

テクスチャで陰影を補正

シェードマップ

ハーフランバートの計算結果にテクスチャを乗算します。

ハイライトマップ

ハイライトの計算結果にテクスチャを加算します。

ノーマルマップ

ノーマルマップを[NormalMap]ノードに接続します。

このときノーマルマップを255階調(1⾊あたり8bit)で作成している場合は「R」と「G」チャンネルを128にしてもシェーダ内で正確な0.5にならずに少し法線がずれてしまうので、「R」と「G」に0.99609375(1-(1/256))を乗算して補正しています。補正値は[VectorMath(Multiply)]のノードに直接⼊⼒してもいいですし、下記の画像のようにノードで⼊⼒してもいいです。ノードで組んだほうがほんの少し計算精度が上がります。

最後にジオメトリの元の法線とノーマルマップで変化させた法線を[Mix]ノードに繋いで[Fac]の値で2つの法線をON/OFFできるようにしておきます。

下記の画像はRGB(128,128,255)のノーマルマップを⼊⼒して影響度を100倍にしたものの⽐較です。
補正なしの⽅は法線の⾊がズレてUVの切れ⽬が⽬⽴っています。補正ありの⽅は何万倍にしてもズレは起きません。

  • 補正なし
  • 補正あり

グループにまとめる

ここまでのノードをいったんグループにまとめて、外からパラメータを調整できるように整えます。テクスチャやライト方向はグループノードの外に出したいので、それ以外のノードを選択してグループを作成します。

ライトのベクトルを取得する

続いて、これまで説明を省略していた[CombineXYZ]ノードの部分について説明していきます。こちらはライトのベクトルを取得するための専用ノードはありませんので、ドライバーを使って代用します。

[CombineXYZ]ノードを作成して、[X][Y][Z]それぞれに[Add Driver]で値を入力します。続いて、スペースを右クリックして[Edit Driver]を押すと設定項目が開くので、[Prop:]の部分にライト方向を取得したいオブジェクトを設定します。

[Path:]は取得したい回転を入力します。今回はオブジェクトのZ方向の向きをライトの向きとしたいので、[CombineXYZ]ノード[X][Y][Z]それぞれに

X: matrix_world[2][0]
Y: matrix_world[2][1]
Z: matrix_world[2][2]

と入力して下さい。
これで指定したオブジェクトの向きをシェーダに伝えることができるようになります。

アセットをリンクで読み込む場合

ライトの角度をドライバーで取得する方法ですが、アセットをリンクで読み込んで[LibraryOverride]にしてもライトを回転したときに陰影を動かすことができません。これはリンクされたマテリアル内の値は外部から更新してもリセットされてしまうためです。

そのためアセットをリンクで読み込みたい場合はライトの角度をドライバーではなく別の方法で取得する必要があります。マテリアル内の値は更新できませんが、オブジェクトを指定して、その位置をシェーダに伝えることはできるので、2つのオブジェクトの位置の差をとってベクトルとして使うことにします。

エンプティを2つ作成して画像のようにノードを変更してください。これで[emptyPos1]から[emptyPos2]に向かうベクトルとなります。

ボーンや他のオブジェクトに親子付けして回転させる場合は[emptyPos1]と[emptyPos2]が回転しないようにコンストレイントなどで固定してください。

ライトのベクトルを共有する

先程の状態までだとライト方向を取得する[CombineXYZ]ノードを複数のマテリアルにそれぞれ作成しなければいけないので、後からライト方向を取得するオブジェクトを変えたい場合にはとても不便です。

このような場合にはたとえひとつのノードでもグループ化して共有することで値の変更を複数のマテリアルに反映させることが出来ます。

[mainLight]に接続するグループノードを変更することで、別々のライトで照らすことができます。2つのライトを作成し、それぞれに対応したライトのグループノードを作成しています。グループノードをリストから切り替えるとオブジェクトを照らすライトが切り替わっているのが確認できます。これにより、マテリアルごとにどのライトで照らすか決めることができるので、例えば顔用と体用のライトに分けたりすることができます。

「toonShading2」のつくり方の場合はライトがシェーダと関連付けられているので、ライトもアセットの一部となります。他のシーンに読み込むときはメッシュやリグと一緒にライトも読み込んでください。

ほかのコンポジット用素材を追加する

陰影や色以外に法線や位置なども共通して出力したい場合はそれらの要素も「toonShading」内に入れておきます。下記の画像は上から順に法線、フォールオフ、ワールド位置を出すためのノードになります。位置など、もともとノードとして用意してあるものはそのまま[AOV Output]に接続すればOKです。

よく使う部位ごとのマスク素材などはグループノード[Input]から直接[AOV Output]に色を接続すればOKです。キャラクターの場合、身体が赤、服が緑、髪が青といったようにRGBのマスク素材として使用します。

部分的なマスク素材などマテリアルごとに個別でつくる追加素材は「toonShading」には含めずに作成します。

「toonShading」を作品全体で共有して複数のアセットで使う

最後に前回解説した「トゥーンシェーダのつくり方(前篇)」と今回の「トゥーンシェーダのつくり方(後篇)」で作成した「toonShading」グループノードをアセットに読み込んで使う手順について説明していきます。

もし「toonShading」をアセットごとにローカルにもっていた場合は後で中の計算を調整することになったとき、それまで作成していたすべてのアセットを開いてマテリアルを修正する必要があります。これでは大変すぎるのでオリジナルの「toonShading」を更新したら全てのアセット内の「toonShading」も更新されて常に最新の状態になるようにしておきます。

そのために「toonShading」をリンクで読み込みます。今回は全アセットがリンク読み込みするために「Z:\asset\cgw\utility」フォルダの中に「toonShading.blend」というシーンデータをひとつつくりました。そこから「toonShading」のグループノードだけをリンクで読み込んできます。

まずはシーンデータを選択します。このときアセットのディレクトリが変わってもパスが切れないように、リンク読み込みするときに[Relative Path]を無効にして絶対パスで読み込んでください。

Blenderはデータを読み込むときにシーンデータをまるごとではなくオブジェクトやマテリアルごとにひとつずつ指定して読み込むことができます。

[NodeTree]を選択して、中にある「toonShading」を選択してLinkを押してください。

これでリンク読み込みは完了です。

アウトライナーから[Blender File]を開くと、一番下にリンクしているデータの参照パスが書かれているのでここでリンクできているか確認できます。

共有するシーンデータは作品の共有データ置き場に置いておき、外部の協力会社も含めてすべての作業者が同じパスで読み込むように合わせておきましょう。

まとめ

以上が2つめのトゥーンシェーダのつくり方と共有の方法の説明でした。

グループにまとめることで他のマテリアルと設定を共有することができるので便利ですが、小さい機能ごとにグループをつくって、さらにそのグループを何度も繰り返し繋げるようなノードの組み方は、余分なノードがグループ内に含まれて計算が増えるだけなのでオススメしません。

「グループ化=共通の処理」と考えると、どのノードまでをグループに含むのかも重要になってきますので、闇雲にグループ化するのではなく、使い所を理解してノードを組んでいけるようになると良いかと思います。

さて、次回は「半透明の設定方法」と「影の出し方」の説明を予定しています。ここまで読んでいただきありがとうございました。次回もよろしくお願いいたします。

株式会社プロジェクトスタジオQ

スタジオカラー・ドワンゴ・麻生塾の3社共同プロジェクトとして、2017年に福岡に設立されたアニメーション制作スタジオ。アニメCGコンテスト「Award:Q/Project Studio Q Anime CG Award 2022」を主宰(現在、受付は終了しています)。
studio-q.co.jp