【Unity】Refrection Probeの使い方

Reflection Probeの使い方をまとめました。

Reflection Probe?

Reflection Probeは環境の反射を実現するための仕組みです。
Reflection Probeの位置からレンダリングしたキューブマップを作成し、それをシェーダに渡してサンプリングすることで反射を実現します。

今回はまず検証用として、下記のシーンを用意します。

  • Sphereを生成して(-2, 0, 0)に配置
  • Sphereを生成してStaticにして(2, 0, 0)に配置
  • StandardShaderのMetallicとSmoothnessを1にしたマテリアルをアサインしたSphereを(0, 0, 0)に配置
  • GameObject > Light > Reflection Probeからリフレクションプローブを生成し、(0, 0, 0)に配置

f:id:halya_11:20180702134948p:plain:w400

ベイク方法1: Staticなオブジェクトのみ対象とする

Staticなオブジェクトのみ映り込みの対象とするには、Reflection ProbeのTypeをBakedにします。

f:id:halya_11:20180702135012p:plain:w400

レンダリング結果は次のようになります。

f:id:halya_11:20180702135019p:plain:w400

StaticにしたSphereだけが映り込んでいることがわかります。
ちなみに正確にはStaticのチェックボックスの横にあるプルダウンメニューのうち、Reflection Probe Staticにチェックが入っていることが映り込みの条件です。

f:id:halya_11:20180702135028p:plain:w400

ベイク方法2: 動的なオブジェクトも含める

オブジェクトをStaticにするとランタイムで動かすことができません。
Staticでないオブジェクトを映り込ませたい場合には次のようにします。

  1. Reflection ProbeのTypeをCustomにする
  2. Dynamic Objectsにチェック入れる
  3. Bakeボタンを押す

これでStaticでないオブジェクトも映り込みました。

f:id:halya_11:20180702135336p:plain:w400

ただしこの方法はベイクを非ランタイムで行うので、ランタイムでオブジェクトを動かしてもキューブマップは更新されません。

ベイク方法3: ランタイムでReflection Probeを生成する

方法2ではランタイムでオブジェクトを動かしてもキューブマップが更新されませんでした。
キューブマップをランタイムで生成するにはTypeをRealtimeにします。

f:id:halya_11:20180702135724p:plain:w400

するとRefresh Modeが選択できるようになるので、これでキューブマップを更新するタイミングを制御します。

まずRefresh ModeをEvery frameにすると毎フレームベイクされます。
より正確な反射を実現できますが、毎フレーム行うにはかなり重い処理なので現実的ではない設定です。

実際にはRefresh ModeをAwakeにしてAwake時にベイクしたり、Via scriptingにしてベイクするタイミングをスクリプトで制御したりする必要があります。
Via scriptingにした場合は下記のようにすればベイクできます。

using UnityEngine;

public class ReflectionProbeSample : MonoBehaviour {

    private ReflectionProbe _probe;

    private void Awake () {
        _probe = GetComponent<ReflectionProbe>();
    }
    
    public void RenderProbe () {
        if (_probe != null) {
            _probe.RenderProbe();
        }
    }
}

ベイク方法4: 独自に作ったキューブマップをReflection Probeとして使う

何らかの別の方法でベイクしたキューブマップをReflection Probeとして使用することもできます。

  • TypeをCustomにする
  • Cubemapフィールドにキューブマップをセットする
  • (Bakeボタンは押さない)

これだけです。

効果範囲を設定する

Reflection Probeを選択するとSceneビューに黄色い直方体が表示されます。

f:id:halya_11:20180702141429p:plain:w400

これはReflection Probeの効果範囲です。
Reflection Probeにより生成されたキューブマップはこの範囲内にあるオブジェクトにのみ渡され、範囲外のオブジェクトには渡されません。

この直方体の位置とサイズはBox SizeとBox Offsetで設定できます。
InspectorからEdit Bounding Volumeボタンを押せばSceneビューで視覚的に設定することもできます。

f:id:halya_11:20180702144535p:plain:w400

Box Projection

ここまでの設定では、近くにあるオブジェクトを床などに反射させる場合にうまく映り込みません。
たとえば下のようにPlaneと3つの縦長のCubeを配置し、Planeを床と見立てて映り込みをさせてみます。

f:id:halya_11:20180708220918p:plain

カメラの位置を変えると、映り込みはしているものの映り込み方が明らかにおかしいことが確認できます。

f:id:halya_11:20180708221026p:plain

このおかしさはBox Projectionの設定で解消できます。
まずEdit > Project Settings > GraphicsからReflection Probes Box Projectionを有効にします。

f:id:halya_11:20180708221456p:plain

次に前節で設定したReflection Probeの効果範囲をPlaneの大きさにピッタリ合わせます。

f:id:halya_11:20180708221744p:plain

実はこの直方体はReflection Probeの効果範囲という意味合いのほか、Box Projectionの範囲設定という意味も持っています。

最後にRefletion ProbeのBox Projectionにチェックを入れます。

f:id:halya_11:20180708221928p:plain

これで、効果範囲の際に近い物体ほど完全に正確な反射をするようになります。

f:id:halya_11:20180708222130p:plain

四角い部屋の床の反射などに効果的に使えそうです。

ブレンド

Reflection Probeを二つ作って効果範囲を重ねると、重なった部分は二つのキューブマップがシェーダに渡されて反射結果がブレンドされます。

f:id:halya_11:20180702144816p:plain:w400

ブレンドを有効にするためには前節のBox ProjectionのようにGraphics SettingsからReflection Probes BlendingをONする必要があります。

また、RendererのReflection ProbesをBlend Probesにする必要があります。

f:id:halya_11:20180708222556p:plain

参考

docs.unity3d.com

Unity - Scripting API: ReflectionProbe.RenderProbe

関連

light11.hatenadiary.com

light11.hatenadiary.com