Reflection Probeの設定項目としてBox Projectionというチェックボックスがあります。
この記事ではBox Projectionの考え方について書きます。
基本的なキューブマッピングの知識が前提知識となります。
Box Projectionとは?
Box Projectionの概要については下記のReflection Probeの記事で紹介しています。
要するに、Reflection Probeを使ったときに近くにあるオブジェクトの映り込み方がおかしくなるのを補正する機能です。
映り込みがおかしくなる原因
それではそもそもなぜ近くのオブジェクトの映り込みがおかしくなるのでしょうか?
これを考えるために、まずはキューブマップの中心位置における映り込みを考えます。
反射方向にオブジェクトがあるため、このオブジェクトが映り込む必要があります。
このケースでは単純に反射方向のキューブマップをサンプリングすれば、
そこにオブジェクトがレンダリングされているため問題なく映り込みます。
問題となるのは、中心からずれた位置における反射を考えるケースです。
このケースでは、単純に反射方向のキューブマップをサンプリングすると、
オブジェクトがレンダリングされている部分とまったく違う位置がサンプリングされてしまいます。
映り込みの補正
本来映り込むべきオブジェクトをサンプリングしたい場合には、中心からオブジェクトに向かうベクトルを得る必要があります。
キューブマップの中心座標とレンダリング対象の座標は既知なので、
反射方向とボックスの交点が求められれば下記のようにベクトルの足し算で必要なベクトルが求められます。
Box Projectionの実装
それでは上記の補正を行う関数を実装してみます。
float3 boxProjection(float3 normalizedDir, float3 worldPosition, float4 probePosition, float3 boxMin, float3 boxMax) { // それぞれの面との距離を求める float magnitudeX = ((normalizedDir.x > 0 ? boxMax.x : boxMin.x) - worldPosition.x) / normalizedDir.x; float magnitudeY = ((normalizedDir.y > 0 ? boxMax.y : boxMin.y) - worldPosition.y) / normalizedDir.y; float magnitudeZ = ((normalizedDir.z > 0 ? boxMax.z : boxMin.z) - worldPosition.z) / normalizedDir.z; // 一番短い距離がBoxとの交点までの距離 float magnitude = min(min(magnitudeX, magnitudeY), magnitudeZ); // プローブの中心から描画位置へのベクトル + 描画位置から交点へのベクトル = 補正された反射ベクトル return (worldPosition - probePosition) +normalizedDir * magnitude; }
解説はコメントに書いた通りです。
実際にReflection Probeと組み合わせたものは下の記事で解説していますのでこちらを参照してください。