【Unity】ARシーンでオブジェクトの影を地面に落とす方法

本記事ではUnityを使用してARシーンでオブジェクトの影を地面に落とす方法を紹介します。

影はシェーダーとの関係性が強く、通常の設定ではVR/ARのオブジェクトは光源を受けることで別のオブジェクトに影が描画されます。VRシーンであれば地面となるPlaneなどに影が描画されるのは自然ですが、ARシーンで同じようにPlaneを配置するやり方では、現実空間にPlaneが置かれる形になり、不自然です。

本記事では、通常では「Planeに描画される影」のうち、Planeのみを見えなくすることで、現実空間に影を落とすやり方を説明しています。

地面を表示せずに影のみを表示させることができるので、AR作品などをよりリアルにしたい際などに便利です。

ライトの数値を変更することで影の濃さやクオリティを調整することもできます。

以下がサンプルイメージです。

サンプルイメージ

左:影ナシ|右:影アリ

準備

始めに影を落としたいオブジェクトをシーンに追加します。

今回は球体を使用するので、Hierarchyで右クリックして3D Object→Sphereを選択して球体を追加します。

3D Object→Sphere

3D Object→Sphere

わかりやすいようにPositionを(X=0,Y=1,X=0)にしておきましょう。

Positionを(X=0,Y=1,X=0)

Positionを(X=0,Y=1,X=0)

次に影を落とすための平面を用意します。

球体と同じようにHierarchyで右クリックして3D Object→Planeを選択してPlaneを追加します。

3D Object→Plane

3D Object→Plane

Positionを(X=0,Y=0,X=0)にしておきましょう。

Positionを(X=0,Y=0,X=0)

Positionを(X=0,Y=0,X=0)

シェーダーを作成

元々設定されているシェーダーは、Planeに球体の影が描画されるようにできています。影のみを表示するため、シェーダーとマテリアルを作成します。

Assets上で右クリックをしてCreate→Shader→Standard Surface Shaderを選択して追加します。

Create→Shader→Standard Surface Shader

Create→Shader→Standard Surface Shader

追加できたら、下記のシェーダープログラムをコピーして下さい。

// Made with Amplify Shader Editor
// Available at the Unity Asset Store - http://u3d.as/y3X
Shader "TransparentWithShadows"
{
Properties
{
_Texture0("Texture 0", 2D) = "black" {}
[HideInInspector] _texcoord( "", 2D ) = "white" {}
[HideInInspector] __dirty( "", Int ) = 1
}

SubShader
{
Tags{ "RenderType" = "Transparent" "Queue" = "Geometry+0" "IgnoreProjector" = "True" }
Cull Back
ZWrite Off
Blend SrcAlpha OneMinusSrcAlpha
BlendOp Add
CGPROGRAM
#include "UnityPBSLighting.cginc"
#include "UnityShaderVariables.cginc"
#pragma target 3.0
#pragma surface surf StandardCustomLighting keepalpha
struct Input
{
float2 uv_texcoord;
};

struct SurfaceOutputCustomLightingCustom
{
fixed3 Albedo;
fixed3 Normal;
half3 Emission;
half Metallic;
half Smoothness;
half Occlusion;
fixed Alpha;
Input SurfInput;
UnityGIInput GIData;
};

uniform sampler2D _Texture0;
uniform float4 _Texture0_ST;

inline half4 LightingStandardCustomLighting( inout SurfaceOutputCustomLightingCustom s, half3 viewDir, UnityGI gi )
{
UnityGIInput data = s.GIData;
Input i = s.SurfInput;
half4 c = 0;
#if DIRECTIONAL
float ase_lightAtten = data.atten;
if( _LightColor0.a == 0)
ase_lightAtten = 0;
#else
float3 ase_lightAttenRGB = gi.light.color / ( ( _LightColor0.rgb ) + 0.000001 );
float ase_lightAtten = max( max( ase_lightAttenRGB.r, ase_lightAttenRGB.g ), ase_lightAttenRGB.b );
#endif
float2 uv_Texture0 = i.uv_texcoord * _Texture0_ST.xy + _Texture0_ST.zw;
float4 tex2DNode1 = tex2D( _Texture0, uv_Texture0 );
float4 appendResult8 = (float4(tex2DNode1.r , tex2DNode1.g , tex2DNode1.b , 1.0));
c.rgb = ( ( ase_lightAtten * _LightColor0 ) * appendResult8 ).rgb;
c.a = max( tex2DNode1.a , ( 1.0 - ase_lightAtten ) );
return c;
}

inline void LightingStandardCustomLighting_GI( inout SurfaceOutputCustomLightingCustom s, UnityGIInput data, inout UnityGI gi )
{
s.GIData = data;
}

void surf( Input i , inout SurfaceOutputCustomLightingCustom o )
{
o.SurfInput = i;
}

ENDCG
}
Fallback "Diffuse"
CustomEditor "ASEMaterialInspector"
}
/*ASEBEGIN
Version=15001
22;52;1491;745;1412.058;545.3112;1.441795;True;True
Node;AmplifyShaderEditor.TexturePropertyNode;5;-601.3947,-278.6907;Float;True;Property;_Texture0;Texture 0;1;0;Create;True;0;0;False;0;a511279f3fe5df64583b457d53fabf9a;cdb08e5d1f5844840a774f4db2098afc;False;black;Auto;0;1;SAMPLER2D;0
Node;AmplifyShaderEditor.TextureCoordinatesNode;6;-499.0693,34.59831;Float;False;0;-1;2;3;2;SAMPLER2D;;False;0;FLOAT2;1,1;False;1;FLOAT2;0,0;False;5;FLOAT2;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4
Node;AmplifyShaderEditor.RangedFloatNode;18;-100.642,-293.6487;Float;False;Constant;_Float1;Float 1;2;0;Create;True;0;0;False;0;1;0;0;0;0;1;FLOAT;0
Node;AmplifyShaderEditor.LightColorNode;15;-209.5528,29.22202;Float;False;0;3;COLOR;0;FLOAT3;1;FLOAT;2
Node;AmplifyShaderEditor.SamplerNode;1;-238.8079,-181.0969;Float;True;Property;_TextureSample0;Texture Sample 0;1;0;Create;True;0;0;False;0;7be95422710fa4b018659390b6108d74;7be95422710fa4b018659390b6108d74;True;0;False;white;Auto;False;Object;-1;Auto;Texture2D;6;0;SAMPLER2D;;False;1;FLOAT2;0,0;False;2;FLOAT;0;False;3;FLOAT2;0,0;False;4;FLOAT2;0,0;False;5;FLOAT;1;False;5;COLOR;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4
Node;AmplifyShaderEditor.LightAttenuation;12;-649.0541,252.1351;Float;False;0;1;FLOAT;0
Node;AmplifyShaderEditor.OneMinusNode;14;-103.5528,415.222;Float;False;1;0;FLOAT;0;False;1;FLOAT;0
Node;AmplifyShaderEditor.SimpleMultiplyOpNode;21;-9.070984,131.4897;Float;False;2;2;0;FLOAT;0;False;1;COLOR;0,0,0,0;False;1;COLOR;0
Node;AmplifyShaderEditor.DynamicAppendNode;8;101.4472,-170.778;Float;False;FLOAT4;4;0;FLOAT;0;False;1;FLOAT;0;False;2;FLOAT;0;False;3;FLOAT;0;False;1;FLOAT4;0
Node;AmplifyShaderEditor.SimpleMaxOpNode;13;112.4372,243.5498;Float;False;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0
Node;AmplifyShaderEditor.SimpleMultiplyOpNode;16;227.4472,11.22202;Float;False;2;2;0;COLOR;0,0,0,0;False;1;FLOAT4;0,0,0,0;False;1;COLOR;0
Node;AmplifyShaderEditor.StandardSurfaceOutputNode;0;430.0907,-14.65567;Float;False;True;2;Float;ASEMaterialInspector;0;0;CustomLighting;TransparentWithShadows;False;False;False;False;False;False;False;False;False;False;False;False;False;False;True;False;False;False;False;Back;2;False;-1;0;False;-1;False;0;0;False;0;Custom;0.5;True;False;0;True;Transparent;;Geometry;All;True;True;True;True;True;True;True;True;True;True;True;True;True;True;True;True;True;0;False;-1;False;0;False;-1;255;False;-1;255;False;-1;0;False;-1;0;False;-1;0;False;-1;0;False;-1;0;False;-1;0;False;-1;0;False;-1;0;False;-1;False;2;15;10;25;False;0.5;True;2;SrcAlpha;OneMinusSrcAlpha;0;SrcAlpha;OneMinusSrcAlpha;Add;OFF;0;False;0;0,0,0,0;VertexOffset;True;False;Cylindrical;False;Relative;0;;0;-1;-1;-1;0;0;0;False;0;0;0;False;-1;-1;15;0;FLOAT3;0,0,0;False;1;FLOAT3;0,0,0;False;2;FLOAT3;0,0,0;False;3;FLOAT3;0,0,0;False;4;FLOAT;0;False;6;FLOAT3;0,0,0;False;7;FLOAT3;0,0,0;False;8;FLOAT;0;False;9;FLOAT;0;False;10;FLOAT;0;False;13;FLOAT3;0,0,0;False;11;FLOAT3;0,0,0;False;12;FLOAT3;0,0,0;False;14;FLOAT4;0,0,0,0;False;15;FLOAT3;0,0,0;False;0
WireConnection;6;2;5;0
WireConnection;1;0;5;0
WireConnection;1;1;6;0
WireConnection;14;0;12;0
WireConnection;21;0;12;0
WireConnection;21;1;15;0
WireConnection;8;0;1;1
WireConnection;8;1;1;2
WireConnection;8;2;1;3
WireConnection;8;3;18;0
WireConnection;13;0;1;4
WireConnection;13;1;14;0
WireConnection;16;0;21;0
WireConnection;16;1;8;0
WireConnection;0;9;13;0
WireConnection;0;13;16;0
ASEEND*/
//CHKSM=F061730E9029E8D3744314CF555EAA8F030C3348

先ほど追加したシェーダーをダブルクリックするとVisual Studioが起動します。

Visual Studioを開くと既にプログラムが入力されているのですべて削除してください。

Visual Studioを起動します

Visual Studioを起動します

削除したら先ほどコピーしたシェーダープログラムをペーストします。

シェーダープログラムをペースト

シェーダープログラムをペースト

Ctrl+[S]キーを押して保存してからVisual Studioを閉じてください。

追加したシェーダーを選択して右クリックし、Create→Materialを選択します。

Create→Material

Create→Material

すると「TransparentWithShadows」という名前のマテリアルが作成されます。

TransparentWithShadows

TransparentWithShadows

これでマテリアルは完成です。

使い方

作成したマテリアルを先ほど追加したPlaneにドラッグ&ドロップして適応します。

そうするとPlaneが消え、球体と影だけが表示されます。

Planeにドラッグアンドドロップして適応

Planeにドラッグ&ドロップして適応

影の挙動自体は通常通りです。ライトを回転させたりオブジェクトを移動させれば影は変わりますが、地面となるPlaneの大きさがそのまま影が投影される範囲になるのでPlaneの大きさは調整してください。

ライトの回転とPlaneの大きさで影を調整

ライトの回転とPlaneの大きさで影を調整

影の濃さを調整するにはDirectional LightのStrengthの数値を変更します。

数値が1に近いほど影が濃くなりますが、0.4くらいが自然に見えます。

Directional LightのStrengthの数値を変更

Directional LightのStrengthの数値を変更

影の解像度はDirectional LightのResolutionから変更することができます。

影の解像度をDirectional LightのResolutionから変更

影の解像度をDirectional LightのResolutionから変更

Window > Rendering > Lighting Settings からLightingの設定を変更します。

ARで使用する場合はSkybox Materialを「None」にしてEnvironment LightingのSourceを「Color」に変更しておいてください。

Skybox Material→None、Environment LightingのSource→Color

Skybox Material→None、Environment Lighting>Source→Color

STYLYで使用する方法

ここからはSTYLY上で影を使用する方法について解説します。

STYLYにはDirectional LightとPlaneのみをアップロードします。

まずはDirectional LightのRender ModeがImportantになっていることを確認してください。

Directional LIghtのRender ModeをImportantに

Directional LightのRender ModeをImportantに

HierachyにあるDirectional LightとPlaneをそれぞれAssetsにドラッグ&ドロップしてPrefabにします。

irectional LIghtとPlaneをAssetsにドラッグアンドドロップ

Directional LightとPlaneをAssetsにドラッグ&ドロップ

PrefabにしたDirectional LightとPlaneを選択し、右クリックをしてSTYLY→Upload prefab or scene to STYLYをクリックしてSTYLYにアップロードします。

STYLYにアップロード

STYLYにアップロード

STYLY Pluginをまだ導入していない方は下記の記事を参考にしてください。

STYLYアカウントを作成する

アカウント作成方法

STYLYにアップロードする方法

UnityからSTYLYにアップロードする方法

STYLY Studioに移動し、Your Position以外のオブジェクトをすべて削除します(用途に応じてAR Template GridEnable AR Occlusionは削除しなくてもOKです)。

My uploadから先ほどアップロードしたDirectional LightとPlaneをシーンに追加します。

Directional LIghtとPlaneをシーンに追加

Directional LightとPlaneをシーンに追加

次に3D Object→Model→animalsからメインとなるSnow Leopardを追加します。

Snow Leopard

Snow Leopard

このままだと影の具合が確認できないので適当な地面を追加します。

地面を追加

地面を追加

影が途中で切れてしまう場合はPlaneの大きさを調整しましょう。

サイズや向きが調整できたら先ほど追加した地面を削除 or 非表示設定にしてシーンをPublishしたら完成です。

影ナシ

影ナシ


影アリ

影アリ

STYLYに関する質問、バグ報告、改善してほしい要望はSTYLY FORUMまで
https://jp.forum.styly.cc/support/discussions

Certified (QA) by Shota Yoshizawa
Edited by SASAnishiki