Apple Engine

Apple, iPhone, iOS, その周辺のことについて

ARKit でジオメトリの影を描画する

今までに自分が作成してきたサンプルはジオメトリの影をテクスチャで表現してきたが、ライトを置きジオメトリの影を描画したい時があるかもしれない。

ARKit の場合、現実空間と仮想のジオメトリを合成するため、平面認識後アンカーノードとしてジオメトリを置いた時に影を投影するのが難しい。

そんな時に対処する方法を書いていこうと思う。

内容的には WWDC 2017 SceneKit: What's New SceneKit の中で紹介されている話をそのまま書いているので、観たことがある人はこの記事を読む必要はないかも。

developer.apple.com

 

まずはライトを設定する

ジオメトリの影を落とすことができるライトはシャドウマップが使用できる Directional と Spot のみ。
どちらかを設置し、キャストシャドウをオンにする。

f:id:x67x6fx74x6f:20190412181140p:plain
キャストシャドウをオンにする

 

ARKit のカメラは初期状態で pointOfView に専用のカメラが設定されるが、
ライトはシーン内のものが使用できるため、コードで書かなくてもシーンファイルで設定したものでも適応される。

 

影を投影する場所をつくる

平面認識で取得する ARPlaneAnchor で設定する SCNPlane や ARSCNPlaneGeometry、 平面認識しないのであれば何らかのジオメトリにマテリアルを設定する。

マテリアルを設定すると投影する物に色がついてしまうので影だけを表示するように設定し直していく。

 

影だけを表示する方法

マテリアル描画に影を描画する

マテリアルの色を抜いてしまうと影も消えてしまうので、Directional や Spot ライトの Shadow の Mode を Fowerd から Differred に変更する。

f:id:x67x6fx74x6f:20190412181528p:plain
Mode が Fowerd

f:id:x67x6fx74x6f:20190412181548p:plain
Mode が Differred

 

Fowerd はマテリアルの処理の前にシャドウマップを考慮して描画計算していると思われ、 Differred はマテリアルの色の情報を設定してからシャドウマップを適応している。

SCNLight の Mode についてはこちらを参照

appleengine.hatenablog.com

 

以下の画像のは Differred でライティングしたもので、下からテクスチャのエミッションで光が照らされているが、
モンスター自体にはスポットライトから生成されたシャドウマップの影が下側についている。 本来なら下の影の色はエミッションで光で明るくなる。

f:id:x67x6fx74x6f:20190412181650p:plain

 

マテリアルの色の情報設定後に影を描画するため、マテリアルで色情報がなくても影がのることになる。

 

マテリアルの色を抜く

影を描画するマテリアルの色情報を抜く場合 Write To Color のチェックを全て外す。

f:id:x67x6fx74x6f:20190412181756p:plain
Write To Color のチェックを全て外す

 

色情報が無視され透過され Differed で設定された影だけ残ることになる。

ジオメトリにキャストシャドウを設定されているので、それをオフにしないとシェーディングされた影が残るので注意。

f:id:x67x6fx74x6f:20190412181847p:plain
ノードのキャストシャドウをオフにする

 

欠点

色情報を無視して影を落とすため影ののり方が異なる。
影の色がそのままのるため、濃くなるのでライトの Shadow カラーを透過させる。

f:id:x67x6fx74x6f:20190412182038p:plain
影の色を調整したもの

 

また、ライトやシェーディングの処理やシャドウマップなど色々処理されるため、厳密な影の描画が必要なければ SCNLight の Gabo や板ポリで影を作成した方が処理的に優しい。

 

サンプルファイル

github.com

 

まとめ

サンプルファイルでは説明用にシーンファイルの SCNPlane に影を描画しているが、ARSCNPlaneGeometry で面を生成しても同じ設定をすれば影だけ描画されると思われる。

例えば、時刻に合わせて現実世界の太陽日差しで影を落としたい時などに使用できるだろう。