魔法エフェクトや炎、モヤモヤした煙などのクオリティを高める上で、オブジェクトが地面や壁とぶつかる境界をいかに自然になじませるかは非常に重要です。これを実現するのが『Soft Particles(ソフトパーティクル)』技術ですが、URPのShader Graphで実装する際、ノードの組み合わせ手順やレンダラーの設定を誤ると全く機能しません。本記事では、このソフトパーティクルの基本原理を『水に入った瞬間に透明になる氷』の例え話を交えて分かりやすく解説し、完璧になじむマテリアルのノード構築法を提示します。
1. 例え話で理解する:『水に入ると溶け込んで見えなくなる氷』
この不自然な境界線バグと、その解決策であるソフトパーティクルの仕組みを、『水の中に薄い氷の板を沈めるビジュアル』に例えて考えてみましょう。
あなたが透明なアクリル板(エフェクト)を、砂浜(地面の3Dモデル)にグサッと乱暴に突き刺したとします。アクリル板は不溶性なので、砂とアクリルが交差する境界には、パキッとした鋭い直線状の切れ込み(CG感の強い交差線)が誰の目にも見えてしまいます。
これに対し、もし突き刺す板が『水の中に沈めると、水底の深さに応じて自動的に色が変化し、水と接触している境界部分だけが水に溶けて完全になじむ特殊な氷の板(Soft Particles)』だったらどうでしょうか。この氷は、底(シーン深度)からの深さ(深度の差)がゼロに近づく境界エリアにおいて、自身を徐々に水の色(背景色)へと同化させ、最終的に透明(アルファ0)へフェードアウトします。水面から飛び出ている深い部分だけがはっきりと見え、水底に近い部分はふわっと溶け込むように見えなくなるため、アクリル板のような不自然な交差線は完全に消失し、水中にエフェクトが美しく馴染んで一体化します。
ソフトパーティクルとは、『現在のピクセルが背景の地面とどれだけ近い距離にあるか』を瞬時に計算し、その距離の差(深度差)が近づくにつれて、マテリアルの透明度(Alpha)を自動的に0へと滑らかに落としていく技術のことです。
2. 解決策A:Shader Graphでの正しいノード接続手順
Shader Graphでこの『背景との深度差によるフェード』を実装するためには、現在のレンダリングピクセルの画面深度(Screen Depth)と、背景にあるシーンの深度(Scene Depth)の差分を求めるノードネットワークを組みます。
ノード構築の手順:
- Shader Graphエディタを開き、空いているスペースに『Screen Position』ノードを作成します(Modeは `Raw` に設定します)。
- 『Screen Position』の `Out` ポートから『Split』ノードに接続し、Wチャンネル(このW値がカメラから現在の描画ピクセルまでの『線形深度(距離)』に相当します)を取り出します。
- 次に、『Scene Depth』ノードを作成します(Sampling Modeは `Eye` に設定し、背景の線形深度を取得します)。
- 『Scene Depth』の出力から『Screen Position』のWチャンネルの値を引き算する『Subtract』ノードを作成します(`Scene Depth - Screen Depth (W)`)。これにより、オブジェクトと地面との「距離差」が求まります。
- この距離差を調整するために、さらに『Divide』ノード(または `Multiply`)を接続します。割る数値(例: `0.5` など)が、フェードが完了するまでの「ソフトネスの距離(メートル)」になります。この値はプロパティ化して外部から調整できるようにするのが一般的です。
- 値が `0` 以下や `1` 以上になって描画が破綻するのを防ぐため、必ず『Saturate』ノード(または `Clamp` で 0〜1 に制限)を接続します。
- 最後に、この出力値をエフェクトマテリアルの元々のアルファ値(Alpha)に対して『Multiply(乗算)』し、マスタースタックの `Alpha` ポートに接続します。
このノード構成により、地面に刺さる境界部分のアルファ値が自動的にゼロに近づき、パキッとした鋭い直線が完全に消え去ります。
3. 解決策B:URP レンダラー設定の有効化(必須プロセス)
Shader Graphでノードを正しく組んでも、地面がすり抜けたり、機能しない場合があります。これは、URPのレンダラー側で背景の深度情報をテクスチャとして生成する設定が無効になっていることが原因です。
設定手順:
- プロジェクトウィンドウで、現在アクティブな『Universal Render Pipeline Asset (URP Asset)』を選択します。
- インスペクター上で、『Depth Texture』というチェックボックスを探します。
- この『Depth Texture』に必ず **チェック(有効)** を入れます。
このチェックが入ることで、Unityは背景の不透明オブジェクトを描画し終えた段階で、画面全体の深度情報を格納した『_CameraDepthTexture』をGPUメモリ内に生成し、Shader Graphの『Scene Depth』ノードが正しいシーン深度をサンプリングできるようになります。これにより、ソフトパーティクルが完璧に機能するようになります。