Metal

이전까지는 ARKit의 ARFrame 데이터를 Metal로 전달해서 Point Cloud를 추출하는 과정과 원리에 대해서 알아봤다.

이번엔 실제로 Point Cloud를 연산하는 Metal 자체에 대해서 자세히 알아보자.

Pipeline

파이프라인이란, 일련의 작업을 단계별로 나눈 것이다.

Metal, OpenGL 등에서는 그래픽스 렌더링을 위한 "Render Pipeline"이라는 구조를 사용한다. CPU와 GPU 사이에 연결되며, 마찬가지로 작업을 단계별로 나눠놓았다.

때문에 밑에서 보겠지만, Pipeline에 필요한 작업을 하나하나 설정해주는 과정이 있다.

Metal에서는 2가지 Pipeline을 만들어서 사용한다.

MTLRenderPipelineState

이름에 쓰여 있는 그대로. Render. 뭔가를 3D나 2D로 렌더링, 화면에 보여져야 할 때 사용한다.

이 Pipeline에는 Render 할 정점을 연산하는 vertex shader, 연산된 vertex의 색을 결정하는 fragment shader를 등록하고, 정점의 깊이에 따라 예외 여부를 따지는 DepthStencil, 색상의 타입을 정할 Pixel format, 최종적으로 Render 할 Target 등을 정해준다.

func makeParticlePipelineState() -> MTLRenderPipelineState? {
  guard let vertexFunction = library.makeFunction(name: "particleVertex"),
  let fragmentFunction = library.makeFunction(name: "particleFragment") else {
    return nil
  }
        
		let descriptor = MTLRenderPipelineDescriptor()
		descriptor.vertexFunction = vertexFunction
		descriptor.fragmentFunction = fragmentFunction
		descriptor.depthAttachmentPixelFormat = renderDestination.depthStencilPixelFormat
		descriptor.colorAttachments[0].pixelFormat = renderDestination.colorPixelFormat
		descriptor.colorAttachments[0].isBlendingEnabled = true
		descriptor.colorAttachments[0].sourceRGBBlendFactor = .sourceAlpha
		descriptor.colorAttachments[0].destinationRGBBlendFactor = .oneMinusSourceAlpha
		descriptor.colorAttachments[0].destinationAlphaBlendFactor = .oneMinusSourceAlpha
        
    return try? device.makeRenderPipelineState(descriptor: descriptor)
}