Flutter+Metal實現(xiàn)圖像處理詳細流程
背景
在之前自制的圖像處理App中,使用了OpenGL處理圖片,這次使用Metal替代OpenGL,來達到更好的性能,順便熟悉一下Metal的渲染流程

基本思路
Flutter使用CVPixelBuffer和iOS交互,我們可以直接使用CVPixelBuffer創(chuàng)建MTLTexture,然后將MTLTexture設置為渲染目標。這樣Metal框架可以直接將渲染結果寫入CVPixelBuffer,達到更加高效的目的。
Metal環(huán)境設置
主要初始化Device,PipelineState,CommandQueue三個對象。我們需要依賴Device分配各種Metal資源,PipelineState管理著渲染流水線的各個環(huán)節(jié)的配置,比如vertex shader,fragment shader,輸出像素格式等。CommandQueue用于管理執(zhí)行的繪制命令。
_device = MTLCreateSystemDefaultDevice(); id<MTLLibrary> lib = [_device newDefaultLibrary]; id<MTLFunction> vertexFunc = [lib newFunctionWithName:vertexFuncName]; id<MTLFunction> fragFunc = [lib newFunctionWithName:fragFuncName]; MTLRenderPipelineDescriptor *renderPipelineDesc = [MTLRenderPipelineDescriptor new]; renderPipelineDesc.vertexFunction = vertexFunc; renderPipelineDesc.fragmentFunction = fragFunc; renderPipelineDesc.colorAttachments[0].pixelFormat = MTLPixelFormatBGRA8Unorm; _pipelineState = [_device newRenderPipelineStateWithDescriptor:renderPipelineDesc error:nil]; _commandQueue = [_device newCommandQueue];
從CVPixelBuffer創(chuàng)建MTLTexture紋理
首先創(chuàng)建一個CVPixelBuffer對象
NSDictionary *pixelAttributes = @{( id )kCVPixelBufferIOSurfacePropertiesKey : @{}};
CVPixelBufferCreate(
kCFAllocatorDefault,
imageWidth,
imageHeight,
kCVPixelFormatType_32BGRA,
(__bridge CFDictionaryRef)pixelAttributes,
&_renderTargetPixelBuffer);利用CVMetalTextureCacheCreateTextureFromImage從CVPixelBuffer創(chuàng)建MTLTexture
CVReturn ret = CVMetalTextureCacheCreate(kCFAllocatorDefault, nil, _mtContext.device, nil, &_textureCache); CVMetalTextureRef renderTargetMetalTextureRef; ret = CVMetalTextureCacheCreateTextureFromImage(kCFAllocatorDefault, _textureCache, _renderTargetPixelBuffer, nil, MTLPixelFormatBGRA8Unorm, imageWidth, imageHeight, 0, &renderTargetMetalTextureRef); id<MTLTexture> mtlTexture = CVMetalTextureGetTexture(renderTargetMetalTextureRef);
渲染到紋理
從CommandQueue獲得一個CommandBuffer,用于保存需要執(zhí)行的繪制命令
_activeCmdBuffer = [_commandQueue commandBuffer];
創(chuàng)建MTLRenderPassDescriptor設置本次繪制的相關配置,比如繪制到哪里,這里指定通過CVPixelBuffer創(chuàng)建出來的MTLTexture,是否清除當前內容,清除的顏色
MTLRenderPassDescriptor *renderPassDesc = [MTLRenderPassDescriptor new]; renderPassDesc.colorAttachments[0].texture = target; renderPassDesc.colorAttachments[0].loadAction = MTLLoadActionClear; renderPassDesc.colorAttachments[0].clearColor = MTLClearColorMake(0, 0, 0, 1);
通過CommandBuffer和MTLRenderPassDescriptor創(chuàng)建一個MTLRenderCommandEncoder
_activeEncoder = [_activeCmdBuffer renderCommandEncoderWithDescriptor:renderPassDesc];
指定MTLRenderCommandEncoder所在的PipelineState
[_activeEncoder setRenderPipelineState:_pipelineState];
使用MTLRenderCommandEncoder綁定Buffer和Texture,在Metal里,Uniform和Vertex Buffer 都是通過MTLBuffer綁定到Shader中
[_activeEncoder setVertexBuffer:vertexBuffer offset:0 atIndex:0]; [_activeEncoder setFragmentBuffer:uniformBuffer offset:0 atIndex:0]; [_activeEncoder setFragmentBuffer:texture offset:0 atIndex:0];
繪制圖形
[_activeEncoder drawPrimitives:MTLPrimitiveTypeTriangle vertexStart:0 vertexCount:vertexCount instanceCount:1];
顯式的結束MTLRenderCommandEncoder
[_activeEncoder endEncoding];
提交CommandBuffer
[_activeCmdBuffer commit];
等待繪制結束,如果你想要異步等待,需要在[_activeCmdBuffer commit]之前設置completedHandler
// 同步等待
[_activeCmdBuffer waitUntilCompleted];
// 異步等待
[_activeCmdBuffer addCompletedHandler:^(id<MTLCommandBuffer> _Nonnull buf) {
}];到此繪制的內容就已經在CVPixelBuffer中了,再將CVPixelBuffer提交給Flutter顯示即可。
到此這篇關于Flutter+Metal實現(xiàn)圖像處理的文章就介紹到這了,更多相關Flutter圖像處理內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
Android頂部工具欄和底部工具欄的簡單實現(xiàn)代碼
Android頂部工具欄和底部工具欄的簡單實現(xiàn)代碼,需要的朋友可以參考一下2013-05-05
AFURLSessionManager 上傳下載使用代碼說明
本文通過代碼給大家介紹了AFURLSessionManager 上傳下載使用說明,代碼簡單易懂,非常不錯,具有參考借鑒價值,需要的朋友參考下吧2017-09-09
Android 實現(xiàn)微信長按菜單 -FloatMenu
在日常開發(fā)中,長按某個view出現(xiàn)個菜單是很常見的需求,下面小編給大家?guī)砹薃ndroid 實現(xiàn)微信長按菜單 -FloatMenu的實現(xiàn)思路及具體實現(xiàn)代碼,感興趣的朋友跟隨腳本之家小編一起看看吧2018-07-07
Material Design系列之自定義Behavior支持所有View
這篇文章主要為大家詳細介紹了Material Design系列之自定義Behavior支持所有View,具有一定的參考價值,感興趣的小伙伴們可以參考一下2016-09-09

