본문 바로가기

프로그래밍

(287)
[Metal] 이미지렌더링~ 카메라 입력과 가우시안 블러~ 이전 kernel shader 를 사용하는 샘플에 입력 텍스처를 이미지가 아닌 카메라 픽셀버퍼로 변경해보자~ 대부분 소스는 동일한데, 카메라 입력을 처리하기 위한 부분들만 차이가 있다. 샘플이므로 비율처리 없이 카메라 입력을 그대로 받아 256x256 사이즈로 줄이고, 가우시안블러, 최종 렌더링시에 마스킹 이미지를 추가해 실제 이미지와 블러된 이미지를 혼합해 픽셀을 결정하게 된다. ViewController 렌더러에 있던 metal view delegate 를 뷰컨트롤러로 이동하고, 렌더링 루틴을 2단계로 분리했다. 첫번째 카메라 이미지가 입력되었을때 첫번째 리사이징 렌더링을 수행하고, 해당 작업 이후에 블러와 화면 렌더링을 진행한다. 첫번째 렌더링은 별도의 렌더타겟인 텍스처에 렌더링하므로, 카메라에서 ..
CVPixelBuffer, CMSampleBuffer,Data, Metal Texture, vImage CMSampleBuffer -> CVPixelBuffer let pixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer) // nano timestamp가 필요한 경우 let scale:Float64 = 1_000_000_000 let time = Int64( CMTimeGetSeconds(CMSampleBufferGetPresentationTimeStamp(sampleBuffer)) * scale) CVPixelBuffer -> CMSampleBuffer var sampleBuffer: CMSampleBuffer? = nil let scale = CMTimeScale(1_000_000_000) let time = CMTime(value: CMTimeValue..
[Metal] 이미지 렌더링~ 가우시안 블러~ Kernel 쉐이더 이전 가우시안 블러 샘플을 Kernel(compute) 쉐이더를 사용해 구현해 본다. 원본이미지를 리사이징해 작은 텍스처를 만들고, 블러링 작업은 이전 샘플과 동일하게 kernel 쉐이더로 5회 적용했다. 속도는 fragment 쉐이더와 큰 차이는 없다. 렌더타겟은 사이즈를 줄여 렌더링하는 용도로만 사용한다. 가로, 세로 작업을 위한 MTLTexture, MTLComputePipelineState 와 MTLFunction을 선언했다. class Renderer:NSObject { var device:MTLDevice! var commandQueue: MTLCommandQueue! var sharedDataPtr: UnsafeMutablePointer? var imageVertexBuffer: MTLBuf..
[Metal] 이미지 렌더링~ 가우시안 블러 이번에는 이미지 필터링에 많이 사용되는 가우시안 블러를 적용해 보자. 블러링은 비용이 많이 드는 프로세스이기에 사용 조건에 따라 방식을 달리 적용해야 한다. 이미지 품질이 중요한 경우 원본 사이즈에 좀더 넓은 사이즈(탭)로 블러를 적용하고, 영상처리 같은 곳에선 속도를 위해 원본이미지를 축소해 블러를 적용한다. 이 샘플은 약 1/4 크기로 이미지를 축소하고, 7탭, 2 pass 작업을 총 5회 적용하였다. 공통타입 헤더 가우시안의 가중치 값은 초기에 미리 계산해 공통으로 사용할 데이터에 저장한다. #include typedef struct { float tapCount; float gaussian[7]; } SharedData; 2 pass 블러 이므로 가로용, 세로용 텍스처와 파이프라인을 구성 clas..
[Metal] 이미지 렌더링~ 여러 텍스처 합치기 원본텍스처와 사이즈를 줄인 텍스처, 마스킹용 텍스처를 합치는 간단한 샘플. (어째 원본외에 캡처한 이미지들 색상이 좀 이상..) 이전 예제에서 원본텍스처와 렌더타겟 텍스처가 존재하니 마스킹용 텍스처만 하나 추가로 로드한다. func initMetal() { . . . . initRederTarget() initSwapRender() self.imageTexture = loadTexture(name:"sample", ext:"png") self.maskingTexture = loadTexture(name: "masking", ext: "png") } 화면 렌더링용 쉐이더에 3개의 텍스처를 전달한다 func render(view:MTKView) { print("render") . . . . swapEncod..
[Metal] 이미지 렌더링~ 텍스처에 렌더링 이번엔 텍스처에 렌더링하고, 해당 텍스처를 화면에 렌더링하는 예제이다. 예제에서는 일반 사이즈보다 훨씬 작은 64x64 크기의 렌더타겟 텍스처를 생성해 렌더링을 진행했다. 여전히 기존 코드들은 동일. 버텍스 let kImagePlaneVertexData:[Float] = [ -1.0, -1.0, 0.0, 1.0, 1.0, -1.0, 1.0, 1.0, -1.0, 1.0, 0.0, 0.0, 1.0, 1.0, 1.0, 0.0, ] 기본 프로퍼티들 선언 텍스처로 렌더링하기 위해 MTLRenderPipelineState와 MTLRenderPassDescriptor 가 추가되고, 렌더타겟인 MTLTexture, 프래그먼트 쉐이더 MTLFunction 이 추가되었다. var device:MTLDevice! var c..
[Metal] 이미지 렌더링~ 텍스처 표시 뷰 컨트롤러 스토리보드에 MTKView 추가하고, mtk view 의 기본적인 설정을 한다. delegate는 아래 정의할 renderer로 연결 class ViewController: UIViewController { @IBOutlet weak var mtkView: MTKView! var renderer: Renderer = .init() override func viewDidLoad() { super.viewDidLoad() self.mtkView.enableSetNeedsDisplay = true self.mtkView.device = self.renderer.device self.mtkView.delegate = self.renderer } } 정점 이미지만을 표시하기 위해 4각형 정의 let ..
[Metal] 이미지 렌더링~ 사각형 그리기 뷰 컨트롤러 스토리보드에 MTKView 추가하고, mtk view 의 기본적인 설정을 한다. delegate는 아래 정의할 renderer로 연결 class ViewController: UIViewController { @IBOutlet weak var mtkView: MTKView! var renderer: Renderer = .init() override func viewDidLoad() { super.viewDidLoad() self.mtkView.enableSetNeedsDisplay = true self.mtkView.device = self.renderer.device self.mtkView.delegate = self.renderer } } 정점 이미지만을 표시하기 위해 4각형 정의 let ..