この記事ではPhotogrammetoryで作成した3Dモデルを使用して、シーンにあるオブジェクトに影を落とす方法を紹介します。
Photogrammetoryとは?
Photogrammetoryの技術を使うことで、ポリゴンモデリングやスカルプトモデリングすることなくメッシュデータとテクスチャデータを用意することができます。
ちゃんとした照明設備のあるスタジオを用意しない限りカメラで撮影した画像は太陽の光や照明の影響を受けた状態になるので、Materialを設定するときはUnlitのものを使うことが多いかと思います
UnityのStandardシェーダーを使用すると陰影が付いたテクスチャの上にライトの影響で陰影が付くので不自然な見た目になります。
Unlitシェーダーとは?
Unlitシェーダーとは「ライトの影響を受けないシェーダー」です。
ライトによる陰影が付かず、他のオブジェクトに影を落とすこともありません。
設定されたColorやTextureがそのまま描画されるので、ゲームではライトの影響を受ける必要のないUIやフラットな絵作りをする際に使われます。
UIが不自然に白く飛んでいたりする場合はUnlit/Textureシェーダーを使いましょう。
また、ライトに関する計算を一切行わないので一番軽いシェーダーです。
オブジェクトに影を落とす
Unlitシェーダーに対して、UnityのStandardシェーダーはライトの影響を受けるシェーダーです。
ライトの影響を受けるシェーダーを使っている場合、3DモデルについているMesh Rendererの「Cast Shadows」をオンオフすることで他のオブジェクトに影を落とすかどうかを切り替えることができます。
また、影を受ける方のオブジェクト側でも影を受けるかどうかを「Receive Shadows」で切り替えることができます。
今回目指すゴールは「Photogrammetoryで作った3Dモデルに陰影はつけたくないが、他のオブジェクトに影を落としたい」なのでUnlitなシェーダーにCast Shadow機能が付いたUnlit CastShadow Shaderシェーダーを実装します。
Unlit Cast Shadowシェーダーのプログラム
Unlitだけど影を落とすシェーダーは次のようになります。
Shader "Custom/Unlit/CastShadow" { Properties { _MainTex ("Texture", 2D) = "white" {} } SubShader { Tags {"RenderType"="Opaque" } LOD 100 // Pass to render object without lighting and shading Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag // make fog work #pragma multi_compile_fog #include "UnityCG.cginc" struct appdata { float4 vertex : POSITION; float2 uv : TEXCOORD0; }; struct v2f { float2 uv : TEXCOORD0; UNITY_FOG_COORDS(1) float4 vertex : SV_POSITION; }; sampler2D _MainTex; float4 _MainTex_ST; v2f vert (appdata v) { v2f o; o.vertex = UnityObjectToClipPos(v.vertex); o.uv = TRANSFORM_TEX(v.uv, _MainTex); UNITY_TRANSFER_FOG(o,o.vertex); return o; } fixed4 frag (v2f i) : SV_Target { // sample the texture fixed4 col = tex2D(_MainTex, i.uv); // apply fog UNITY_APPLY_FOG(i.fogCoord, col); return col; } ENDCG } // Pass to render object as a shadow caster Pass { Name "CastShadow" Tags { "LightMode" = "ShadowCaster" } CGPROGRAM #pragma vertex vert #pragma fragment frag #pragma multi_compile_shadowcaster #include "UnityCG.cginc" struct v2f { V2F_SHADOW_CASTER; }; v2f vert( appdata_base v ) { v2f o; TRANSFER_SHADOW_CASTER(o) return o; } float4 frag( v2f i ) : COLOR { SHADOW_CASTER_FRAGMENT(i) } ENDCG } } }
シェーダーファイルを新規作成
ProjectウィンドウのCreate/Shader/Unlit Shaderからシェーダーファイルを新規作成します。
CastShadow用のPassを追加
新規作成直後のUnlitシェーダーは1Passで実装されています。
そこにCastShadow用のPassを追加し、2Passのシェーダーに変更します。
// Pass to render object as a shadow caster Pass { Name "CastShadow" Tags { "LightMode" = "ShadowCaster" } CGPROGRAM #pragma vertex vert #pragma fragment frag #pragma multi_compile_shadowcaster #include "UnityCG.cginc" struct v2f { V2F_SHADOW_CASTER; }; v2f vert( appdata_base v ) { v2f o; TRANSFER_SHADOW_CASTER(o) return o; } float4 frag( v2f i ) : COLOR { SHADOW_CASTER_FRAGMENT(i) } ENDCG }
それぞれ説明していきます。
LightModeをShadowCasterにすることでオブジェクトをシャドウマップにレンダリングします。
Tags { "LightMode" = "ShadowCaster" }
Unityが用意しているマクロを使うことでライティングや影の計算を一から書かずに、簡単にオブジェクトに影を落とすことができます。
マクロとは値や、式があらかじめ定義されたものでコンパイル時に置き換えられます。
今回はあらかじめ用意されたマクロ(式)を使用します。
- V2F_SHADOW_CASTER
- TRANSFER_SHADOW_CASTER(o)
- SHADOW_CASTER_FRAGMENT(i)
struct v2f { V2F_SHADOW_CASTER; }; v2f vert( appdata_base v ) { v2f o; TRANSFER_SHADOW_CASTER(o) return o; } float4 frag( v2f i ) : COLOR { SHADOW_CASTER_FRAGMENT(i) }
注意点として複数のPassで構成されるシェーダーをマルチパスシェーダーと呼ぶのですが、バッチングが効かなくなるなどパフォーマンスに影響するので1Passで書けるものは1Passで書きましょう。
Unlit Cast Shadowシェーダーを3Dモデルデータに適用
Photogrammetoryで作成したサザエの3DモデルにUnlit Cast Shadowシェーダーを適用します。
Unlit Cast Shadowシェーダーを使うことでUnlitな見た目を保ちつつ、オブジェクトに影が落ちるようになり、より空間にオブジェクトがなじんだ見た目になります。
一昔前のゲームのような見た目であったり、クオリティの低い合成画像のようになってしまうのは適切に影を調整できていないことが多いです。
STYLYへアップロード
自作のシェーダーで作成したMaterialをオブジェクトにつけた状態でアップロードすることで、STYLY Scene内で使用できるようになります。
Photogrammetoryで作成した3DモデルにUnlit Cast Shadowシェーダーを使用したMaterialをつけた状態でSTYLYにアップロードする方法はこちらの記事で詳しく解説しています。
シェーダーの特性を理解し、場面に応じて影を落とすことでそのオブジェクトのプレゼンス(実在感)を高めることができるのでライトの調整は大切です。