ARKitのMetalレンダリングのテンプレートプロジェクトを掃除する手順

Xcodeでプロジェクト新規作成する際、"Augumented Reality App"を選び、その次のページで[Content Technology]の欄で"Metal"を選ぶと、ARSCNViewを用いず、MTKViewにカスタムレンダリングするプロジェクトが生成される。

実行するとこんな感じで、タップした箇所の「カメラの手前20cm」の位置に立方体が設置される。

で、このテンプレートプロジェクト、いろいろ参考になるのだが、プロジェクトのスタート地点としては複雑過ぎるようにいつも思う。たとえば.metalファイルには2系統のシェーダ群が入っているのだが、Metalに慣れていないとそれらがそれぞれ何なのかが、自分がこれからつくろうとしているものについて必要なのかどうかがパッとわからないのでは、と。(まぁ、ちゃんとコメントで説明されているのだけど)

というわけで、今後の自分のためにも、このテンプレートから不要な処理を取り除いて、できるだけプレーンな形にする「手順」を書いておこうと思う。

画面の向きを修正する

Info.plistでPortraitにチェックを入れ、他を外す。

Renderer.swiftで、.landscapeRightが指定されているところを.portraitにする(画面の回転に対応したい場合はここを外から指定できるようにする)

-        uniforms.pointee.viewMatrix = frame.camera.viewMatrix(for: .landscapeRight)
-        uniforms.pointee.projectionMatrix = frame.camera.projectionMatrix(for: .landscapeRight, viewportSize: viewportSize, zNear: 0.001, zFar: 1000)
+        uniforms.pointee.viewMatrix = frame.camera.viewMatrix(for: .portrait)
+        uniforms.pointee.projectionMatrix = frame.camera.projectionMatrix(for: .portrait, viewportSize: viewportSize, zNear: 0.001, zFar: 1000)
-        let displayToCameraTransform = frame.displayTransform(for: .landscapeRight, viewportSize: viewportSize).inverted()
+        let displayToCameraTransform = frame.displayTransform(for: .portrait, viewportSize: viewportSize).inverted()

Metalシェーダから不要なコードを削除

.metalファイルのうち、必要なのはcapturedImageFragmentShader関数まで(ARKitのYCbCrで入ってきたカメラ入力をRGBに変換するもの)。それ以降は立方体をシェーダで描画するためのコードなので削除する。

不要な型の定義を削除

ShaderTypes.hで定義されている型のうちいくつかは削除した立方体を表示するシェーダで用いるものでもう必要ない。SharedUniformsと、InstanceUniformsを削除する。そしてBufferIndicesのkBufferIndexMeshGenerics, kBufferIndexInstanceUniforms, kBufferIndexSharedUniformsと、VertexAttributesのkVertexAttributeNormalを削除する。

レンダラから不要なコードを削除

Renderer.swiftから以下の定数を削除

let kMaxAnchorInstanceCount: Int = 64
let kAlignedInstanceUniformsSize: Int = ((MemoryLayout<InstanceUniforms>.size * kMaxAnchorInstanceCount) & ~0xFF) + 0x100

プロパティを削除

var anchorUniformBuffer: MTLBuffer!
var anchorPipelineState: MTLRenderPipelineState!
var anchorDepthState: MTLDepthStencilState!
var anchorUniformBufferOffset: Int = 0
var anchorUniformBufferAddress: UnsafeMutableRawPointer!
var anchorInstanceCount: Int = 0
var geometryVertexDescriptor: MTLVertexDescriptor!
var cubeMesh: MTKMesh!
var uniformBufferIndex: Int = 0
var sharedUniformBufferOffset: Int = 0
var sharedUniformBufferAddress: UnsafeMutableRawPointer!
var sharedUniformBuffer: MTLBuffer!

以下のメソッドも削除。

func drawAnchorGeometry(renderEncoder:)
func updateAnchors(frame:)
func loadAssets()
func updateBufferStates()
func updateSharedUniforms(frame:)

これでビルドすると削除したプロパティやメソッドにアクセスするコードがエラーになるので、それらをすべて削除。

掃除済みのプロジェクト

以上の手順で不要コードを取り除いたプロジェクト一式。もうちょっとリファクタリングした方が読みやすいが、レンダラの役割がARKitからのカメラ入力をMTKViewに描画するということに絞られ、元のテンプレートコードと比べるとだいぶシンプルになっていると思う。

ここから先は

0字 / 1ファイル

¥ 300

最後まで読んでいただきありがとうございます!もし参考になる部分があれば、スキを押していただけると励みになります。 Twitterもフォローしていただけたら嬉しいです。 https://twitter.com/shu223/