おもちゃラボ

Unityで遊びを作ってます

【Unity】Ambient Occlusionを綺麗に見せる3つの方法

ライトをベイクするとき、あわせてAmbient Occlusionの設定もすることが多いと思います。このAmbient Occlusionがなかなかの曲者で、適当に設定すると綺麗に見えないのです。ここではライトをベイクする際にオススメなAmbient Occlusionの設定を3つ紹介します。

f:id:nn_hokuson:20170306193548j:plain

Precomputed Realtime GIはオンのままで

Precomputed Realtime GIはメニューバーから「Window」→「Lighting」で表示される項目の一つです。これをオフにすると、ろくなことにならないので、基本的にはオンのままにしておきましょう。

f:id:nn_hokuson:20170306190812p:plain:w400

かといって、シーンを下手に構成すると事前計算に膨大な時間がかかるそうなので、一度この資料に目を通しておくと良いと思います。

unity3d.com

AOの強度はIndirectを中心に設定

次にAmbient Occlusionの設定です。Max Distanceは特別なことがなければ1.0のままで良いです。これで1mの範囲でAmbient Occlusionが計算されるようになります。

f:id:nn_hokuson:20170306191131p:plain:w400

続いてIndirectとDirectの項目です。基本的にはAmbient Occlusionの強度はIndirectで設定します。Directは「もう少し暗いところを暗くしたい」というときに少しずつ強度を上げて見ます。あまりに上げすぎると不自然な絵になります。

下記のキャプチャはDirectは0のままでIndirectを0、3、6と変化させたときの結果です。Indirectを上げるにしたがって赤いキューブと黄色キューブの隙間がだんだん暗くなっていくのがわかると思います。

f:id:nn_hokuson:20170306192057p:plain

次にIndirectは1に固定したまま、Directを1、5、10と変化させたときの結果です。3つのキューブの隙間がどんどん暗くなっていきます。キューブの隙間から闇が広がっていく感じですね・・・・Direct=10は不自然すぎます。

f:id:nn_hokuson:20170306192655p:plain

ということで、基本はIndirectでAmbient Occlusionの強度を決めて、Directは味付け程度と考えておきましょう。

少しだけオブジェクトと床の間に隙間をつくる

これは裏技的な感じですが・・・・オブジェクトと床の間に少しだけ隙間を作ることで、その隙間がAmbient Occlusionによって暗くなります。これにより、接地面が強調され綺麗に見えます(場合によりますが・・・)。

f:id:nn_hokuson:20170306192848p:plain:w450

左の箱は少しだけ床面から浮かせています。右奥の箱は床にめり込んでいます。

まとめ

この記事ではライトをベイクする際にAmbient Occlusionを綺麗に見せるための設定方法を3種類紹介しました。一方で、ライトをベイクしなくてもリアルタイムでもAmbient Occlusionをかけることもできます。

わざわざ苦労してライトをベイクしたり、ややこしいAmbient Occlusionの設定をしたくない!と言っても怒られない人(モバイル関係ではない人)は、Unityに用意されているカメラエフェクトを使ってみてください。ただし、結構計算コストは高くなるので注意です。

【Unityシェーダ】テクスチャの両面を描画する方法

Planeオブジェクトにテクスチャを貼り付けると、両面が描画されるのではなく裏面は透明になってしまいます。

f:id:nn_hokuson:20170303202052g:plain

片面だけが描画されてしまうのは、カリングと呼ばれる「見えないところは描画しない設定」が原因です。カリングをオフにして両面を表示するためには、シェーダを書く必要があります(インスペクタから設定したいところですが・・・)

ここでは、プロジェクトビューで「Create」→「Shader」→「Unlit Shader」を選択してください。作成したデフォルトのUnlitシェーダに、カリングをオフにして両面表示する設定を書き加えます。

Shader "Unlit/culloff"
{
	Properties
	{
		_MainTex ("Texture", 2D) = "white" {}
	}
	SubShader
	{
		Tags { "RenderType"="Transparent" "Queue"="Transparent" }
		LOD 100
		Cull off
		Blend SrcAlpha OneMinusSrcAlpha 

		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
		}
	}
}

ここでは、デフォルトで生成されるUnlitLシェーダに3行追加しています。「LOD100」と書かれた行の下に「Cull off」の一行を追加しています。カリングを切るだけであれば追加するのはこの一行でOKです。これによりテクスチャの両面表示ができるようになります。

ここではテクスチャの透明部分にも対応できるようにするため、合わせてTransparentの設定をしています。

Tags { "RenderType"="Transparent" "Queue"="Transparent" }
Blend SrcAlpha OneMinusSrcAlpha 

このシェーダを両面を描画したいオブジェクトにアタッチして実行してみてください。設定する前は片面しか描画されていませんでしたが、カリングをOFFにしたことで両面ともテクスチャが描画されるようになりました。

f:id:nn_hokuson:20170303202119g:plain

【Unityシェーダ入門】暗闇から光が溢れ出るライトブルームの演出をする

室内から外を眺めたときや、トンネルから出るとき、イルミネーションなど、暗い場所から明るい場所を眺めるときに、光が溢れ出るような映像がよく使われます。

f:id:nn_hokuson:20170226004333p:plain

この光のあふれるエフェクトをライトブルーム(Light Bloom)と呼びます。Unityでは標準機能を使って簡単にライトブルームを実現することができます。今回は「かまくら」から溢れ出る光を作ってみましょう。

Unityで真っ暗闇の世界をつくる

まずはライトブルームを作る前に、Unityの世界を真っ暗にしなければエフェクトの効果が分かりません。Unityで真っ暗闇を作るには次の2ステップです。

  1. Directional Lightを消す
  2. Skyboxからの光を遮断する

Directional Lightはライトオブジェクト自体を消しても良いですが、薄っすらと光を当てたい場合はインスペクタからIntensityを小さな値に設定します。

f:id:nn_hokuson:20170226005047p:plain:w250

Skyboxからの光を遮断するには、Lighting WindowからAmbient ColorとReflection Intensityの項目を設定します。Unityのメニューバーから「Window」→「Lighting」でウインドウを開き、次のように設定します。

f:id:nn_hokuson:20170226005454g:plain

ポイントライトを配置する

ライトブルームに使うポイントライト(Point Light)をかまくらの中に配置します。ポイントライトはヒエラルキービューから「Create」→「Light」→「Point Light」で使用できます。光の強度などはインスペクタから設定して下さい。

f:id:nn_hokuson:20170226005934p:plain

ライトブルームを実現する場合は明るさのダイナミックレンジを広げる必要があります。通常、Unityの画面の明度は0.0〜1.0の範囲ですが、HDR(High Dynamic Range)を利用することで1.0以上の値も扱えるようになります。

HDRを利用するには、Main CameraのインスペクタからHDRの項目にチェックを入れるだけです。

f:id:nn_hokuson:20170226010522p:plain:w300

ただ、上の画像のように「HDR and MultisampleAntiAliasing (in Forward Rendering Path) is not supported.」というエラーがでるので、アンチエイリアスの機能を切って下さい。アンチエイリアスを使わないようにするには、メニューから「Edit」→「Project Settings」→「Quality」を選択し、Anti AliasingをDisableに設定します。

f:id:nn_hokuson:20170226011027g:plain

ライトブルームのエフェクトをかける

ライトブルームのエフェクトにはStandard Assetsに用意されているEffectsパッケージを使用します。「Assets」→「Import Package」→「Effects」を選択してインポートして下さい。

インポートできたら「Standard Assets/Effects/ImageEffects/Scripts」フォルダにある以下の4つのエフェクトをMain Cameraにアタッチします。

  1. Antialiasing
  2. Bloom
  3. ScreenSpaceAmbientOcclusion
  4. Tonemapping

それぞれの効果は、次の画像を参考にして下さい。まずは元画像がこちらです。光は溢れ出してないし、エッジがギザギザしています。まだ、単純にオブジェクトを配置しただけ、という感じで余り綺麗な映像ではありませんね。
f:id:nn_hokuson:20170226011720p:plain

Antialiasingのエフェクトをかけることで、画面のエッジのギザギザを滑らかにしました。かまくらの入り口部分とUnityちゃんの髪の毛がきれいになりました。
f:id:nn_hokuson:20170226011758p:plain

Bloomエフェクトを追加しました。これで、かまくらの中から光の溢れ出す映像になりましたね。ただ、明暗のメリハリがなく立体感に欠けています。
f:id:nn_hokuson:20170226011819p:plain

ScreenSpaceAmbientOcclusionを追加することで、暗くなるべきところを更に暗くしています。SSAOと略されることが多いこのエフェクトは、地面とオブジェクトが接する部分や、オブジェクトが重なる部分など、光が回り込まない部分を更に暗くするエフェクトです。
f:id:nn_hokuson:20170226011848p:plain

最後にTonemappingをすることで、全体的な色のバランスを整えています。Unityで用意されているトーンマッピングには様々な種類が用意されているので、好みによって使い分けて下さい。
f:id:nn_hokuson:20170226011915p:plain

エフェクトをかけるのは、お化粧をしていくみたいで楽しいですね〜。UnityのEffectsパッケージには他にも色々と楽しいエフェクトが用意されているので、試してみると楽しいですよ^^/