この記事は前回の解説的内容です。
入門としては1.5回目に位置します。
目的
Metalの使用用途がGameというイメージが強すぎるので、通常のアプリや表現としても使えることを探っていきます。
注意
MetalはiOS8以上の固有機能です。Metalを動かすにはA7チップ以上のデバイスが必要です。Macで開発する場合は
シュミレーターではなく、実機で確認するようにしてください。
前回のコードと確認しながら進めると分かりやすいと思います。
MetalとOpenGLの違い
MetalはOpenGLESより高速で動きます。しかしOpenGLESはクロスプラットフォームというメリットがあります。そのためOpenGLESのアプリはAndroid、Windowsなどに移植しやすいです。ちなみにSpriteKitやSceneKitはOpenGLESを利用しています。
MetalのメリットはOpenGLESより優れたパフォーマンスと、個人的にはコードの記述がスマートな所だと思います。パファーマンスが出ない場合はMetalの使用を検討しても良いと思います。
まとめるとMetalのメリットとしては
- OpenGLESよりすぐれたパフォーマンス(CPUとGPUのメモリを共通使用するためとかとか)
- コードの記述がスマート(私の個人的な感想です)
グラフィックスライブラリの2つのフェーズ
前回の投稿をみても、グラフィックスライブラリを使う場合、大きく2つのフェーズに分かれます。
- 初期化フェーズ
- 描画フェーズ
初期化フェーズ
まず初期化フェーズではグラフィックスライブラリの初期化、描画の準備を行います。
順番にみると
- 1.GPUへのアクセス方法を用意
- 2.CPUとGPUの連携準備
- 3.頂点やバッファの準備
- 4.レンダリングパイプラインを準備
で設定します。
1.GPUへのアクセス方法を用意
ここで最初にすることは、deviceを取得することです。これでプログラムを実行しているdeviceとやり取りができます。またデバイスの情報も取得できます。
let device: MTLDevice! = MTLCreateSystemDefaultDevice()
2.CPUとGPUの連携準備
グラフィックスの情報は非同期にCPUからGPUに送信されます。これはCPUでまず処理が実行され、次にGPUに転送されます。画面上の特定の1pxで考えると、CPUとGPUが同一のピクセルに対して同時に処理をすることはないです。
この処理を順番に行うためにキューを準備します。CPUはGPUに渡す情報をキューに追加していき、GPUはキューから順番に情報を抜き出し処理します。
let commandQueue: MTLCommandQueue! = device.newCommandQueue()
3.頂点、バッファの準備
GPUへ渡したい頂点情報を準備します。スクリーン上に表示するオブジェクトを定義します。
// 頂点
let vertexArray: [Float] = [
-1.0, 1.0, 0, 1,
-1.0, -1.0, 0, 1,
1.0, -1.0, 0, 1,
-1.0, 1.0, 0, 1,
1.0, -1.0, 0, 1,
1.0, 1.0, 0, 1
]
ヴァッファは頂点、色、テクスチャなどあり、頂点の数だけバッファを作成します。
let vertexBuffer: MTLBuffer! = device.newBufferWithBytes( vertexArray,
length: vertexArray.count * sizeofValue(vertexArray[0]),
options: MTLResourceOptions.OptionCPUCacheModeDefault
)
4.レンダリングパイプラインを準備
このステップは2に分かれます。最初のフェーズでは、Shaderプログラムを用意し読み込みます。
SwiftでShaderプログラムを使う場合は、Shader Libraryに読み込む必要があります。
// Shader Library設定
let defaultLibrary = device.newDefaultLibrary()
let newVertexFunction = defaultLibrary!.newFunctionWithName("vertexShader")
let newFragmentFunction = defaultLibrary?.newFunctionWithName("fragmentShader")
次のステップではディスクリプタを作成します。
ディスクリプタに
パイプラインを初期化し画像をラスタライズしながら、フォーマットが使用するピクセルを教えてくれます。
let pipelineStateDescriptor = MTLRenderPipelineDescriptor()
pipelineStateDescriptor.vertexFunction = newVertexFunction
pipelineStateDescriptor.fragmentFunction = newFragmentFunction pipelineStateDescriptor.colorAttachments[0].pixelFormat = .BGRA8Unorm // 色成分の順序を設定
ディスクリプタの役目あたりは、まだ曖昧ですみません。
今回は初期化フェーズまでとします。次回は描画フェーズの解説を投稿します。