Flutter+Metal實(shí)現(xiàn)圖像處理詳細(xì)流程
背景
在之前自制的圖像處理App中,使用了OpenGL處理圖片,這次使用Metal替代OpenGL,來(lái)達(dá)到更好的性能,順便熟悉一下Metal的渲染流程
基本思路
Flutter使用CVPixelBuffer和iOS交互,我們可以直接使用CVPixelBuffer創(chuàng)建MTLTexture,然后將MTLTexture設(shè)置為渲染目標(biāo)。這樣Metal框架可以直接將渲染結(jié)果寫(xiě)入CVPixelBuffer,達(dá)到更加高效的目的。
Metal環(huán)境設(shè)置
主要初始化Device
,PipelineState
,CommandQueue
三個(gè)對(duì)象。我們需要依賴Device
分配各種Metal資源,PipelineState
管理著渲染流水線的各個(gè)環(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)建一個(gè)CVPixelBuffer
對(duì)象
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
獲得一個(gè)CommandBuffer
,用于保存需要執(zhí)行的繪制命令
_activeCmdBuffer = [_commandQueue commandBuffer];
創(chuàng)建MTLRenderPassDescriptor
設(shè)置本次繪制的相關(guān)配置,比如繪制到哪里,這里指定通過(guò)CVPixelBuffer
創(chuàng)建出來(lái)的MTLTexture
,是否清除當(dāng)前內(nèi)容,清除的顏色
MTLRenderPassDescriptor *renderPassDesc = [MTLRenderPassDescriptor new]; renderPassDesc.colorAttachments[0].texture = target; renderPassDesc.colorAttachments[0].loadAction = MTLLoadActionClear; renderPassDesc.colorAttachments[0].clearColor = MTLClearColorMake(0, 0, 0, 1);
通過(guò)CommandBuffer
和MTLRenderPassDescriptor
創(chuàng)建一個(gè)MTLRenderCommandEncoder
_activeEncoder = [_activeCmdBuffer renderCommandEncoderWithDescriptor:renderPassDesc];
指定MTLRenderCommandEncoder
所在的PipelineState
[_activeEncoder setRenderPipelineState:_pipelineState];
使用MTLRenderCommandEncoder
綁定Buffer
和Texture
,在Metal里,Uniform和Vertex Buffer 都是通過(guò)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];
顯式的結(jié)束MTLRenderCommandEncoder
[_activeEncoder endEncoding];
提交CommandBuffer
[_activeCmdBuffer commit];
等待繪制結(jié)束,如果你想要異步等待,需要在[_activeCmdBuffer commit]
之前設(shè)置completedHandler
// 同步等待 [_activeCmdBuffer waitUntilCompleted]; // 異步等待 [_activeCmdBuffer addCompletedHandler:^(id<MTLCommandBuffer> _Nonnull buf) { }];
到此繪制的內(nèi)容就已經(jīng)在CVPixelBuffer
中了,再將CVPixelBuffer
提交給Flutter顯示即可。
到此這篇關(guān)于Flutter+Metal實(shí)現(xiàn)圖像處理的文章就介紹到這了,更多相關(guān)Flutter圖像處理內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Android編程實(shí)現(xiàn)自定義title功能示例
這篇文章主要介紹了Android編程實(shí)現(xiàn)自定義title功能,結(jié)合具體實(shí)例形式分析了Android自定義title的具體實(shí)現(xiàn)步驟與相關(guān)操作技巧,需要的朋友可以參考下2017-03-03Android ListView分頁(yè)簡(jiǎn)單實(shí)現(xiàn)
這篇文章主要介紹了Android ListView分頁(yè)簡(jiǎn)單實(shí)現(xiàn)的相關(guān)資料,需要的朋友可以參考下2017-06-06Android實(shí)現(xiàn)簡(jiǎn)易的柱狀圖和曲線圖表實(shí)例代碼
柱狀圖是統(tǒng)計(jì)圖表中經(jīng)常用到的一種圖表,比如降雨量之類的統(tǒng)計(jì)展示。這篇文章主要給大家介紹了關(guān)于利用Android如何實(shí)現(xiàn)簡(jiǎn)易的柱狀圖和曲線圖表的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友可以參考下。2017-12-12php 異步調(diào)用方法實(shí)現(xiàn)示例
客戶端與服務(wù)器端是通過(guò)HTTP協(xié)議進(jìn)行連接通訊,客戶端發(fā)起請(qǐng)求,服務(wù)器端接收到請(qǐng)求后執(zhí)行處理,并返回處理結(jié)果2014-01-01android判斷一個(gè)Activity是否處于棧頂?shù)膶?shí)例
下面小編就為大家分享一篇android判斷一個(gè)Activity是否處于棧頂?shù)膶?shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-03-03安卓(android)怎么實(shí)現(xiàn)下拉刷新
這里我們將采取的方案是使用組合View的方式,先自定義一個(gè)布局繼承自LinearLayout,然后在這個(gè)布局中加入下拉頭和ListView這兩個(gè)子元素,并讓這兩個(gè)子元素縱向排列。對(duì)安卓(android)怎么實(shí)現(xiàn)下拉刷新的相關(guān)知識(shí)感興趣的朋友一起學(xué)習(xí)吧2016-04-04Android多點(diǎn)觸控實(shí)現(xiàn)圖片自由縮放
這篇文章主要為大家詳細(xì)介紹了Android多點(diǎn)觸控實(shí)現(xiàn)圖片自由縮放,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-12-12Android 6.0權(quán)限請(qǐng)求相關(guān)及權(quán)限分組方法
今天小編就為大家分享一篇Android 6.0權(quán)限請(qǐng)求相關(guān)及權(quán)限分組方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-08-08將替代ListView的RecyclerView 的使用詳解(一)
這篇文章主要介紹了將替代ListView的RecyclerView 的使用詳解(一)的相關(guān)資料,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2016-07-07