今回は、前々回より使用しているアウトラインシェーダーの応用です。

さて、アウトラインもこだわり出すと「線の数を増やしたい」あるいは「シルエット(輪郭線)のみ出したい 」という調整が必要になります。




今回は、アウトラインをカメラから見てどの位置に描くかをコントロールする仕組みを導入し、「線の数を増やす / 減らす」など、イラストレーターのような表現を目指します。
今回の目標と概要
前回のアウトラインの太さがが距離で変化する仕組みに対し、更に追加します。
黄色い枠の箇所が、今回作成するノードのグループです。

今回のポイント:視線ベクトルで「線の奥行き調整」
線の描画位置を動かすために、前回カメラとの距離で線の太さを変更した際に使用した手法を応用します。

これは、アウトラインを「メッシュの法線方向(表面から垂直)」に押すだけでなく、「カメラに向かう方向」に押す(ずらす)ことで、線が描画される奥行きを調整する仕組みです。
- 正の値で調整:線をカメラ側に手前にずらす→線がキャラより前に描画され目立つ。
- 負の値で調整:線をメッシュの奥にずらす→線がキャラに隠れて消える。
それでは、実際にその仕組みを作っていきます。
アウトラインをずらす仕組み
最初に、アウトラインを「頂点からカメラへ向かう方向」にどれだけずらすかを計算します。
1. Absolute World Position (絶対ワールド座標)

このノードは、マテリアルが適用されているメッシュの頂点一つ一つが、「ワールド(ゲーム空間)内のどこにいるか」を示す座標(位置情報)を出力します。
| 項目 | 説明 |
| 用途 | メッシュの頂点の「場所」を3次元座標(X, Y, Z)で取得する。 |
| 出力 | 3つの数値(Vector3)→ ワールド座標 (X, Y, Z)。 |
| 例え | 「キャラクターが立っている正確な場所」を教えてくれるノード。 |
2. Camera Position (カメラ座標)

このノードは、現在プレイヤーが見ているカメラが、「ワールド内のどこにいるか」を示す座標(位置情報)を出力します。
| 項目 | 説明 |
| 用途 | カメラの「場所」を3次元座標(X, Y, Z)で取得する。 |
| 出力 | 3 つの数値(Vector3) → カメラのワールド座標 (X, Y, Z)。 |
| 例え | 「プレイヤーの目の位置の住所」を教えてくれるノード。 |
3. Subtract (引き算) ノードの効果:視線ベクトルの生成

この 2 つの「場所」の情報をSubtract(引き算)ノードで計算することで、「ベクトル(方向と長さを持つ矢印)」が生成されます。
接続
方向ベクトルの計算:
Camera Position→Subtractの AAbsolute World Position→Subtractの B

Subtractの結果 = Camera Position - Absolute World Position
結果の解説
この引き算の結果得られるベクトルは、「メッシュの頂点からカメラの位置へ向かって伸びる矢印」、つまり視線ベクトル (View Vector) と呼ばれるものです。
| 項目 | 説明 |
| 効果 | 「そのメッシュを、カメラが見ている方向」が分かる。 |
| 用途 | このベクトルを使って、線が描画される位置をカメラの方向へ「ずらす(押し出す)」ことができます。 |
| 例え | 「キャラクターからカメラの瞳に向かって飛んでいく矢」の方向と勢い(長さ)を教えてくれる。 |
4. Normalize (ベクトルの長さを強制的に 1.0 に統一)
Subtractで得られたベクトルには、「長さ(勢い)」も含まれていますが、そのままでは遠くのオブジェクトほどベクトルが長くなり、オフセット量が大きくなってしまいます。
そこで、次に接続する Normalize ノードソ接続して、ベクトルの長さを強制的に 1.0 に統一します。

- Normalize の効果:「長さ(勢い)」を捨てて、「純粋な方向」だけを取り出す。

Subtract の出力を → Normalize の Vector Input
これにより、距離に関係なく、アウトラインを常に安定した「カメラ方向」へ均一に押し出すことができるようになります。
アウトラインをずらす値
次に、アウトラインをずらす値を決める仕組みを作ります。

「奥行き調整量」の適用
Scalar Parameter を配置します

マテリアルグラフ上でTabキーを押すか右クリックしてScalar Parameterと入力します。

名前を Camera_Push_ZOffset とします。

デフォルト値例:0.2とします。
接続

この視線ベクトル(Normalizeの結果)と、前回のCamera_Push_ZOffset(奥行き調整量)をMultiply(掛け算)で組み合わせることで、「カメラ方向」に「指定した量だけ」アウトラインをずらす、という仕組みが完成します。

Normalizeの出力を →Multiplyの ACamera_Push_ZOffset→Multiplyの B
法線押し出しと「奥行き調整」の統合

線の太さ(Line_Thickness)を決めていた法線押し出しのベクトルと、ステップ 2-1 で計算した奥行き調整のベクトルを足し算します。

- 前回のノード(
Line_Thickness*VertexNormalの結果)を探します。 Addノードを配置します。

- Aピンに 法線押し出しの結果 を接続します。
- Bピンに ステップ 2-1 の
Multiplyの出力を接続します。 Addノードの出力を、マテリアル出力ノードのWorld Position Offsetピンに接続します。
World Position Offset =( 法線 * 太さ ) + (視線ベクトル * 奥行き調整 )
Zファイティングの安全策(Pixel Depth Offset)
描画順序を固定してちらつきをおさえるための処理です。本題ではありませんが、線が不安定になるのを防ぐため、この安全策は入れておくことを推奨します。
Zファイティング(Z-Fighting)とは

同じ位置に重なり合うポリゴン(面)がある場合に、どちらの面をレンダリング(描画)すべきかコンピュータが判断できず、画面上で面がチラチラと明滅して見える現象です。

Constantノードを配置し、値を0.01に設定します。(小さな正の値)Constantノードの出力を、マテリアル出力ノードのPixel Depth Offsetピンに接続します。
「見せたい線」「消したい線」の調整

マテリアルインスタンスを開き、Camera_Push_ZOffset の値を調整します。
余計な線を引っ込めて消す (内部線の消去)
トゥーンシェーダーはメッシュのすべての輪郭を描画します。キャラクターの目や口の中、服のシワなど、描画したくない内部の線は、この機能で消すことができます。

- 調整方法:Camera_Push_ZOffset に 非常に小さな負の値(例:-0.001)を設定します。
- 効果:アウトラインがメッシュの表面より奥に描画されるため、線がメッシュによって隠されて見えなくなります。これで、不要な内部線を一括で消すことができます。
髪の毛束など、必要な線を目立たせる

- 調整方法:Camera_Push_ZOffset に 小さな正の値(例:0.01 ~ 0.2)を設定します。
- 効果:線がカメラに向かってわずかに押し出されるため、線の数が増え、描画が安定し、チラつきも解消されます。これにより、髪の毛の細かいディテールも、くっきりと表示できるようになります。
注意

まとめ
今回はアウトラインの描画位置をカメラ方向へ微調整する「線の奥行き調整」機能を実装しました。
この機能は、Camera PositionとAbsolute World Positionの引き算(Subtract)で得られる視線ベクトルを利用しました。
主な成果は以下の通りです。
- 線の消去と強調:
Camera_Push_ZOffsetの値を調整することで、不要な内部線(Z-Fightingを含む)をメッシュの奥に引っ込めて消し、必要な輪郭線だけを手前に押し出して強調できるようになりました。 - 描画の安定化: 距離や角度に依存しない視線ベクトルで線を押し出すため、アウトラインの描画が常に安定し、プロのイラストのようなくっきりとした表現を実現しました。
「線の奥行き調整」は、アウトライン表現の自由度を高めるための便利なテクニックです。
皆さんも是非ご活用いただき、アニメ調の作品作りにお役立てください。
