【ARKit】SCNNodeのrenderingOrderとSCNMaterialのcolorBufferWriteMaskとwritesToDepthBufferについて
ARKitでオクルージョンを実現するのに、
geometry.firstMaterial!.colorBufferWriteMask = []
occlusionNode = SCNNode(geometry: geometry)
occlusionNode.renderingOrder = -1
とするテクニックがある。Appleのフェイストラッキングのサンプルで使われている。(仮想のメガネが、鼻の影にちゃんと隠れる)
このrenderingOrderについては結構日本語でも説明がある。
最後のappleengineさんの記事のサンプルがGitHubにもあって、これで各ノードのrenderingOrderを変えたりしてみると理解が捗る。
で、renderingOrderはその名の通り「レンダリング順」を指定するプロパティで、「数値が低いほうが先に描画される」という説明がされていることが多いんだけど、renderingOrderでオクルージョンを実現できることを理解するにはSCNMaterialのcolorBufferWriteMaskとwritesToDepthBufferについても理解したほうがより腹落ちするかなと思ったので本記事で補足してみる。
たとえば、
occlusionNode = SCNNode(geometry: geometry)
occlusionNode.renderingOrder = 100
これでocclusionNodeのレンダリング順はめっちゃ後ろだから、occlusionNodeより後ろの物体が隠れないかというと、隠れる。occlusionNodeが白く描画されて普通に見えるようになるので、いやそりゃ隠れるのは当然でしょと思われるかもしれないが、とにかくこれが物体が後方にある物体を覆い隠すかどうかはレンダリング順だけで説明がつかないということがいえる。
また、renderingOrderを用いたオクルージョンは、「見えない」ノードのレンダリング順を前にすることで、カメラに対して後方にある物体を覆い隠すというテクニックなんだけど、「見えない」といっても、hiddenなノードや、opacityが0なノード、マテリアルのtransparencyが0の場合等はレンダリング順が前であっても後方のノードを覆い隠さない。
transparencyを0.00001とかの極小に設定すると後方オブジェクトを見えないオブジェクトで覆い隠せるようになるんだけど、これってどういうことなんだろうか?
で、ポイントになるのが最初のコードのこれ:
geometry.firstMaterial!.colorBufferWriteMask = []
これをやると、マテリアルのtransparencyを0.00001に設定したりする必要がない。これは何をしているのか?
このcolorBufferWriteMaskはググっても日本語記事は見当たらない。そしてなんと公式ドキュメントにも何も書いてない。
ヘッダにはちょっと説明が書いてある:
Determines whether the receiver writes to the color buffer when rendered. Defaults to SCNColorMaskAll.
最後まで読んでいただきありがとうございます!もし参考になる部分があれば、スキを押していただけると励みになります。 Twitterもフォローしていただけたら嬉しいです。 https://twitter.com/shu223/