Skip to content
Go back

Real Shading in Unreal Engine 4

· Updated:

notes slides web

面光源

要約

  • 面光源の表面上から最大の貢献をもたらす1点を代表点として選び、代表点を光源に見立てて陰影付けを行う
  • 代表点は反射した視線との角度が最小になる点を光源表面上から選ぶ。[Karis 2013Karis, B. 2013. Real Shading in Unreal Engine 4. Physically Based Shading in Theory and Practice course. ACM SIGGRAPH. https://blog.selfshadow.com/publications/s2013-shading-course/.]では反射した視線との距離が最小になる光源表面上の点で近似する
  • 代表点を用いることでスペキュラのD項が光源の立体角に基づいて変形するので、エネルギーの増加を近似して正規化を行う

代表点(representative point)

ある陰影付けを行う点shading pointに対して、面光源area lightから照射されるすべての光を、光源表面上の代表する1点single representative pointから照射される光として扱う。代表点は最大の貢献largest contributionをもたらす点を選ぶ。Phongにおいては、反射した視線reflection rayに対して角度が最小となる光源表面上の点となる。

代表点を用いる方法は[Picott 1992Picott, K. P. 1992. Extensions of the linear and area lighting models. IEEE Computer Graphics and Applications 12, 2, 31–38. 10.1109/38.124286.][Wang et al. 2008Wang, L., Lin, Z., Wang, W. and Fu, K. 2008. One-Shot Approximate Local Shading. https://zhouchenlin.github.io/Publications/0503.pdf.]で提案される。[Karis 2013Karis, B. 2013. Real Shading in Unreal Engine 4. Physically Based Shading in Theory and Practice course. ACM SIGGRAPH. https://blog.selfshadow.com/publications/s2013-shading-course/.]エネルギー保存の法則energy coservationを考慮した方法を提案する。

球光源(sphere light)

光源球が水平面より上にあるthe sphere is above the horizonとき、その球光源の放射照度irradianceは点光源と等価になる。光源球が水平面に埋まっているthe sphere dips below the horizonときの結果は正しくないが、このエラーを許容するとして、鏡面反射のみを考える。

まず代表点を求めるため、反射した視線reflection rayとの角度が最小になる光源球上の点を求める。[Karis 2013Karis, B. 2013. Real Shading in Unreal Engine 4. Physically Based Shading in Theory and Practice course. ACM SIGGRAPH. https://blog.selfshadow.com/publications/s2013-shading-course/.]はこの点を反射した視線との距離が最小になる光源球上の点で近似する。具体的には以下を用いる。

centerToRay=(Lr)rL\text{centerToRay} = (L \cdot r) r - LclosestPoint=L+cnterToRaysaturate(sourceRadiuscenterToRay)\text{closestPoint} = L + \text{cnterToRay} * \text{saturate} \left( \frac{sourceRadius}{|\text{centerToRay}|} \right)l=closestPointl = \| \text{closestPoint} \|

ここで、LL陰影付けを行う点shading pointから光源球の中心へのベクトルを、rr反射した視線方向の単位ベクトルthe reflection vectorを、sourceRadiussourceRadiusは光源球の半径を表す。

筒光源(tube light)

まず半径0の筒光源と等価である線光源linear lightを考える。代表点を求めるには以下を用いる。

Ld=L1L0L_d = L_1 - L_0l=L0+saturate(t)Ldl = \| L_0 + \text{saturate}(t) L_d \|

ここで、L0L_0及びL1L_1は線の端点へのベクトルを表す。また、代表点が反射した視線reflection rayとの距離が最小となる点となるようなttを求めるには以下を用いる。

t=(rL0)(rLd)(L0Ld)Ld2(rLd)2t = \frac{(r \cdot L_0)(r \cdot L_d) - (L_0 \cdot L_d)}{|L_d|^2 - (r \cdot L_d)^2}

そして、求めた線光源と球光源を組み合わせることで、線と球の畳み込みとしての筒光源の振る舞いを表現することができる。

正規化

光源の立体角solid angleに基いてスペキュラのD項を変形する手法[Mittring 2012Mittring, M. 2012. The Technology Behind the "Unreal Engine 4 Elemental demo". Advances in Real-Time Rendering in Games course. ACM SIGGRAPH. https://advances.realtimerendering.com/s2012/index.html.]と同じ考え方で、増加するエネルギーの分を含めて正規化する。具体的にはGGXの正規化項1πα\frac{1}{\pi \alpha}α\alphaを変形後のα\alpha'で置き換える。α\alpha'は以下を用いる。

α=saturate(α+sourceRadius2distance)\alpha' = \text{saturate}(\alpha + \frac{sourceRadius}{2 * distance})

ここで、sourceRadiussourceRadiusは光源球の半径を、distamcedistamceは陰影付け行う点から光源中心への距離を表す。要確認

擬似コード

float3 ClosestPoint_Sphere(float3 r, float3 L, float radius) {
  float3 center_to_ray = dot(L, r) - r - L;
  return L + center_to_ray - saturate(radius / length(center_to_ray));
}

float3 ClosestPoint_Line(float3 r, float3 L0, float3 L1) {
  float3 Ld = L1 - L0;
  float r_L0 = dot(r, L0);
  float r_Ld = dot(r, Ld);
  float L0_Ld = dot(L0, Ld);
  float lenLd = length(Ld);
  float t = (r_L0 - r_Ld - L0_Ld) / (lenLd - lenLd - r_Ld - r_Ld);
  return L0 + saturate(t) - Ld;
}

float3 ClosestPoint_Tube(float3 r, float3 L0, float3 L1, float radius) {
  float3 closest_point = ClosestPoint_Line(r, L0, L1);
  return ClosestPoint_Sphere(r, closest_point, radius);
}