おもちゃラボ

Unityで遊びを作っていきます

【AR Foundation】モデルに影をつける

ARのモデルを表示するとき、現実感を出すためには「影」の存在が重要になります。
影があることで床との接地面が分かりやすくなり「そこに置かれている感」がアップします。

f:id:nn_hokuson:20200804201438j:plain

この記事では次の流れでモデルに影を付ける方法を紹介します。

  1. 丸影を表示する
  2. 投影テクスチャシャドウを表示する
  3. 影のパラメータ設定について

AR Foundationを使って影付きのモデルを表示する方法はこちらの記事を参照下さい。

nn-hokuson.hatenablog.com

また、AR Foundationの基礎になっているARKitについては「swiftで作る ARKit超入門」がオススメです!こちらも、ぜひご参照ください。
booth.pm

丸影

一番手軽に影を表示する方法は、モデルの足元に影のテクスチャを配置しておくことです。一般的に丸影と呼ばれる方法で、レンダリングのコストも小さく昔から使われている手法です。

f:id:nn_hokuson:20200804172707p:plain:w350

ここでは、まず丸影の作り方から始めましょう。次のような影のテクスチャを用意するか、下の画像をダウンロードしてお使い下さい。

f:id:nn_hokuson:20200804172914p:plain:w200

影のテクスチャをプロジェクトウインドウにドラッグ&ドロップします。影のテクスチャはアルファレイヤ(透明レイヤ)を含んでいるため、影のテクスチャを選択して、インスペクタから「Alpha Is Transparency」にチェックを入れて「Apply」を押して下さい。

f:id:nn_hokuson:20200804173159j:plain:w300

次に影を表示する平面オブジェクトを作成します。ヒエラルキーウインドウの「+」→「3D Object」→「Plane」を選択してPlaneを生成し、サイズを調節してからモデルの足元に移動します。移動したPlaneはモデルにドラッグ&ドロップして子要素にしておきましょう。

f:id:nn_hokuson:20200804173501j:plain

作成したPlaneに影のテクスチャをドラッグ&ドロップします。透明度を反映させるため、インスペクタからShaderを変更します。Particle/Standard Unlitを選択して、「Rendering Mode」を「Fade」に設定して下さい。

その下の「Color Mode」は「Multiply」のままでOKです。これにより下の色と乗算されるため、必ず影の部分が周りの部分に比べて暗くなります。

f:id:nn_hokuson:20200804174028j:plain

これで丸影付きのモデルが作成できました。

投影テクスチャシャドウ

丸影は作成するのも簡単ですし、描画コストも安いのですが、いかんせん見た目がイマイチです。

そこで、もう少しちゃんとした影を付ける場合、Unityが描画してくれる影を利用します。先程の丸影と同じように足元にPlaneを配置すると、下図左のように影が表示されますね。この影の部分だけを残して、その他の部分は透明(下図右)になるようなシェーダを作ります。

f:id:nn_hokuson:20200804181730j:plain

プロジェクトウィンドウで右クリックして「Create」→「Shader」→「Unlit Shader」を選択し「ARShadow」という名前で保存して下さい。

f:id:nn_hokuson:20200804180549p:plain:w100

作成できたら、次のシェーダプログラムを入力して下さい。

Shader "Custom/ARShadow"
{
    SubShader {
        Pass {
            Tags { "LightMode" = "ForwardBase" "RenderType"="Opaque" "Queue"="Geometry+1" "ForceNoShadowCasting"="True"  }
	    LOD 150
	    Blend Zero SrcColor
	    ZWrite On
        
            CGPROGRAM
 
            #pragma vertex vert
            #pragma fragment frag
            #include "UnityCG.cginc" 
            #pragma multi_compile_fwdbase
            #include "AutoLight.cginc"
  
            struct v2f
            {
                float4 pos : SV_POSITION;
                LIGHTING_COORDS(0,1)
            };
  
            v2f vert(appdata_base v) {
                v2f o;
                o.pos = UnityObjectToClipPos (v.vertex);
                TRANSFER_VERTEX_TO_FRAGMENT(o);                 
                return o;
            }
 
            fixed4 frag(v2f i) : COLOR {
                float attenuation = LIGHT_ATTENUATION(i);
                return fixed4(1.0,1.0,1.0,1.0) * attenuation;
            }
 
            ENDCG
        }
    }
    Fallback "VertexLit"

}

このシェーダの中ではv2f構造体の中でLIGHTING_COORDSを使ってライトマップとシャドウマップ用のTEXCOORDを生成しています。フラグメントシェーダではLIGHT_ATTENUATIONを使って、先程適宜したライトマップとシャドウマップから光の減衰具合を調べています。これにより影のある場所だけが不透明になり、その他の部分は透明な画像になります。

Unityのシェーダに関しては次の記事も合わせてご覧ください。

nn-hokuson.hatenablog.com

ARShadowシェーダファイルを選択した状態で右クリックして、「Create」→「Material」を選択してください。これによりARShadowが適用されたマテリアルが作成できます。このマテリアルを足元のPlaneにドラッグ&ドロップして下さい。

f:id:nn_hokuson:20200804184408j:plain

影の調整

最後に影の見栄えについて調整をしていきます。ここでは「影の解像度」と「影の濃さ」についての設定方法を紹介します。

影の解像度

Unityでモデルの影を表示したとき、次図のようにガタガタで粗い影になってしまうことがあります。

f:id:nn_hokuson:20200804185357p:plain:w300

この場合は、UnityのメニューバーからEdit→Project Settingsを選択してProject Settingsウインドウを開いて下さい。左カラムから「Quality」を選択し、「Shadow Distance」を 10程度の値に設定してみて下さい。

f:id:nn_hokuson:20200804185857j:plain:w500

影の濃さ

デフォルトでは影が真っ黒で濃すぎることが多いです。そこで影の色を薄くします。
f:id:nn_hokuson:20200804190605g:plain

影の濃さはDirectional Lightのインスペクタから設定します。ライトを選択した状態でインスペクタのRealtime Shadows → Strengthを0.5程度に下げてみましょう。
f:id:nn_hokuson:20200804190312j:plain:w350