Photogrammetoryで使えるUnlitだけど影を落とすシェーダー

この記事ではPhotogrammetoryで作成した3Dモデルを使用して、シーンにあるオブジェクトに影を落とす方法を紹介します。

Unlitだけど影を落とすシェーダーを使ったサザエ

Unlitだけど影を落とすシェーダーを使ったサザエ

Photogrammetoryとは?

Photogrammetoryの技術を使うことで、ポリゴンモデリングやスカルプトモデリングすることなくメッシュデータとテクスチャデータを用意することができます。

 

 

ちゃんとした照明設備のあるスタジオを用意しない限りカメラで撮影した画像は太陽の光や照明の影響を受けた状態になるので、Materialを設定するときはUnlitのものを使うことが多いかと思います

 

UnityのStandardシェーダーを使用すると陰影が付いたテクスチャの上にライトの影響で陰影が付くので不自然な見た目になります。

Standardシェーダーを使用したサザエ

Standardシェーダーを使用したサザエ

Unlitシェーダーとは?

Unlitシェーダーとは「ライトの影響を受けないシェーダー」です。

ライトによる陰影が付かず、他のオブジェクトに影を落とすこともありません。

Unlit/Textureシェーダーを使用したサザエ

Unlit/Textureシェーダーを使用したサザエ

 

設定されたColorやTextureがそのまま描画されるので、ゲームではライトの影響を受ける必要のないUIやフラットな絵作りをする際に使われます。

UIが不自然に白く飛んでいたりする場合はUnlit/Textureシェーダーを使いましょう。

また、ライトに関する計算を一切行わないので一番軽いシェーダーです。

オブジェクトに影を落とす

Unlitシェーダーに対して、UnityのStandardシェーダーはライトの影響を受けるシェーダーです。

 

ライトの影響を受けるシェーダーを使っている場合、3DモデルについているMesh Rendererの「Cast Shadows」をオンオフすることで他のオブジェクトに影を落とすかどうかを切り替えることができます。

それぞれオンオフ切り替えることができます

それぞれオンオフ切り替えることができます

 

また、影を受ける方のオブジェクト側でも影を受けるかどうかを「Receive Shadows」で切り替えることができます。

Cast ShadowsとReceive Shadowsを切り替える

Cast ShadowsとReceive Shadowsを切り替える

 

今回目指すゴールは「Photogrammetoryで作った3Dモデルに陰影はつけたくないが、他のオブジェクトに影を落としたい」なのでUnlitなシェーダーにCast Shadow機能が付いたUnlit CastShadow Shaderシェーダーを実装します。

Unlit Cast Shadowシェーダーを適用した状態

Unlit Cast Shadowシェーダーを適用した状態

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からシェーダーファイルを新規作成します。

シェーダーファイルに「UnlitCastShadow」とつけます

シェーダーファイル名に「UnlitCastShadow」とつけます

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で書きましょう。

ドローコールバッチング – Unity – Manual

Unlit Cast Shadowシェーダーを3Dモデルデータに適用

Photogrammetoryで作成したサザエの3DモデルにUnlit Cast Shadowシェーダーを適用します。

Unlit Cast Shadowシェーダーを使うことでUnlitな見た目を保ちつつ、オブジェクトに影が落ちるようになり、より空間にオブジェクトがなじんだ見た目になります。

 

Unlit Cast Shadowシェーダーを使用したサザエ

Unlit Cast Shadowシェーダーを使用したサザエ

 

一昔前のゲームのような見た目であったり、クオリティの低い合成画像のようになってしまうのは適切に影を調整できていないことが多いです。

Unlit Cast Shadowシェーダーを使用しない合成画像のようなサザエ

Unlit Cast Shadowシェーダーを使用しない合成画像のようなサザエ

STYLYへアップロード

自作のシェーダーで作成したMaterialをオブジェクトにつけた状態でアップロードすることで、STYLY Scene内で使用できるようになります。

Photogrammetoryで作成した3DモデルにUnlit Cast Shadowシェーダーを使用したMaterialをつけた状態でSTYLYにアップロードする方法はこちらの記事で詳しく解説しています。

 

 

シェーダーの特性を理解し、場面に応じて影を落とすことでそのオブジェクトのプレゼンス(実在感)を高めることができるのでライトの調整は大切です。