平面の鏡面反射

平面の鏡面反射

ReflectionProbeを使用する方法

 Create→3DObject→Planeより、鏡面用の平面を作成します。新しくMaterialを作成します。このMaterialのShaderをStandardへ、MetallicとSmoothnessを1へ変更します。そして、このMaterialを平面へアタッチします。

新しく空のゲームオブジェクトを作成し、AddComponentからReflectionProbeをアタッチします。

TypeをRealtimeへ変更し、Refresh ModeをEvery frameへTime SlicingをNo time slicingへ変更します。また、CubeMap capture settingのResolutionを512へ変更します。

以下のScriptを作成ます。先ほどのReflectionProbeをアタッチしたゲームオブジェクトに、このScriptをアタッチします。

実行結果

 実行するとこのように平面が鏡面反射するようになります。

ReflectionProbeを使用しない方法

 ここを参考に作成しました。Reflection用のカメラを用意し、そのカメラに映った映像を平面に描画することで、鏡面を作成します。鏡面にしたい平面に以下のShaderを設定したMaterialとScriptをアタッチすると動作します。
ReflectionMatrixに関しては以下のページに詳しく記述されています。
Introduction to 3D Game Programming with DirectX 12 (Computer Science) (2016)

Script

 鏡面にしたい平面にこのScirptをアタッチします。このScriptでは平面のレイヤーをMirrorへ変更する必要があります。

Shader

 このShaderを選択したMaterialを平面へアタッチします。ついでにフレネル反射を追加してみました。Flesnelを1にすると完全な鏡面となります。

実行結果

 実行すると、このように平面が鏡面になります。ReflectionProbeを使用した場合より、動作が軽いことがわかります。

Scriptの改良

 鏡面ができた、と思いきや一つ問題があります。それは、以下の画像のように、平面に円柱を差し込んだ状態で実行すると

このように、平面より下の部分もカメラに映るため、鏡面に映ってはいけないものが映ってしまいます。

解決方法

 CalculateObliqueMatrixにクリップ平面とみなすVector4を渡し、得られたMatrixをカメラのProjectionMatrixに代入します。すると、カメラと指定した平面の間を描画対象から外すことができるようです。クリップ平面とみなすVector4は、以下の平面の方程式内にある\((a,b,c,d)\)です。

$$
\begin{align}
&ax+by+cz+d=0\\
&d=-\vec{n}\cdot\vec{p}
\end{align}
$$
\(\vec{n}\)は平面の法線、また、\((a,b,c)\)は平面の法線を表しているので\(\vec{n}=(a,b,c)\)です。そして、\(\vec{p}=(x_{o}, y_{o}, z_{o})\)であり、\((x_{o}, y_{o}, z_{o})\)は平面上の任意の座標です。

Script

 上記をもとに、Scriptを変更しました。

実行結果

 鏡面より下の部分は描画されなくなりました。

参考ページ

Combined Reflections: Stereo Reflections in VR
Introduction to 3D Game Programming with DirectX 12 (Computer Science) (2016)
UnityでVR対応のどこでもドア実現を目指す その2 Oblique Near-Plane Clipping編

このコンテンツはユニティちゃんライセンス条項の元に提供されています