Metal 繪制視圖內(nèi)容

創(chuàng)建一個(gè)MetalKit視圖和一個(gè)渲染過(guò)程以繪制視圖的內(nèi)容。

在這個(gè)示例中我們可以學(xué)習(xí)到:

  • 使用Metal渲染圖形內(nèi)容的基礎(chǔ)。
  • 使用MetalKit框架創(chuàng)建一個(gè)使用Metal繪制視圖內(nèi)容的視圖。
  • 將編碼用于渲染過(guò)程的命令,該過(guò)程會(huì)將視圖擦除為背景色。

準(zhǔn)備要繪制的MetalKit視圖

MetalKit提供了一個(gè)名為的類(lèi)MTKView,它是NSView(在macOS中)或UIView(在iOS和tvOS中)的子類(lèi)。MTKView處理與將您使用Metal繪制的內(nèi)容顯示到屏幕上有關(guān)的許多細(xì)節(jié)。

MTKView為了在內(nèi)部創(chuàng)建資源,需要引用Metal設(shè)備對(duì)象(GPU),因此第一步是將視圖的 device屬性設(shè)置為MTLDevice。

_view.device = MTLCreateSystemDefaultDevice();

我們可以為視圖的內(nèi)容清除,并設(shè)置成為一個(gè)純色的背景,你可以使用MTLClearColorMake(_:_:_:_:)并指定紅色,綠色,藍(lán)色和Alpha值。

_view.clearColor = MTLClearColorMake(0.0, 0.5, 1.0, 1.0);

在這里我們不需要繪制動(dòng)態(tài)的內(nèi)容,所以將view的enableSetNeedsDisplay屬性設(shè)置為YES,以便于僅在需要更新內(nèi)容時(shí)(例如,視圖改變形狀時(shí))才繪制視圖:

_view.enableSetNeedsDisplay = YES;

設(shè)置繪制的代理

MTKView依靠您的應(yīng)用向Metal發(fā)出命令以生成視覺(jué)內(nèi)容。MTKView使用代理模式來(lái)通知您的應(yīng)用何時(shí)應(yīng)繪制。要接收代理的回調(diào),請(qǐng)將視圖的delegate屬性設(shè)置為符合MTKViewDelegate協(xié)議的對(duì)象。

_view.delegate = _renderer;

該代理需要實(shí)現(xiàn)兩個(gè)方法:

  • mtkView:drawableSizeWillChange:在iOS上一般發(fā)生于當(dāng)視圖的尺寸發(fā)生改變,或者設(shè)備的方向發(fā)生改變時(shí)MTKView都會(huì)調(diào)用該方法。
  • drawInMTKView:當(dāng)MTKView需要繪制內(nèi)容是,MTKView會(huì)調(diào)用該方法,在這個(gè)方法中。你將創(chuàng)建命令緩沖區(qū),然后對(duì)命令進(jìn)行編碼,告訴圖形處理器(GPU)繪制什么以及什么時(shí)候在屏幕上顯示。并讓該命令緩沖區(qū)由GPU執(zhí)行,你可以將屏幕上所有的顯示工作認(rèn)為是一個(gè)幀,在一個(gè)交互式應(yīng)用程序中,比如一個(gè)游戲,你可能每秒鐘渲染很多幀。

創(chuàng)建渲染過(guò)程描述符

繪制時(shí),GPU將結(jié)果存儲(chǔ)到紋理中,紋理是包含圖像數(shù)據(jù)的內(nèi)存塊,GPU可以訪(fǎng)問(wèn)它們。在此示例中,MTKView負(fù)責(zé)創(chuàng)建所有需要繪制到視圖中的紋理。它會(huì)創(chuàng)建多個(gè)紋理,這樣當(dāng)你渲染另一個(gè)紋理時(shí),它可以顯示一個(gè)紋理的內(nèi)容。

在繪制時(shí),你需要?jiǎng)?chuàng)建一個(gè)render pass,創(chuàng)建render pass時(shí),你需要一個(gè)渲染描述符(MTLRenderPassDescriptor)在這里示例中,我們無(wú)需使用自己定義渲染描述符,直接使用MetalKit view 中提供的渲染描述符。

MTLRenderPassDescriptor *renderPassDescriptor = view.currentRenderPassDescriptor;
if (renderPassDescriptor == nil)
{
    return;
}

創(chuàng)建命令隊(duì)列

你使用MTLCommandQueue 去創(chuàng)建對(duì)象,并且加入MTLCommandBuffer 對(duì)象中.確保它們能夠按照正確順序發(fā)送到GPU.對(duì)于每一幀,一個(gè)新的MTLCommandBuffer 對(duì)象創(chuàng)建并且填滿(mǎn)了由GPU執(zhí)行的命令.

_commandQueue = [_device newCommandQueue];

創(chuàng)建命令緩沖區(qū)

使用MTLCommandQueue 創(chuàng)建對(duì)象并且加入到MTCommandBuffer對(duì)象中去.為當(dāng)前渲染的每個(gè)渲染傳遞創(chuàng)建一個(gè)新的命令緩沖區(qū)。

id<MTLCommandBuffer> commandBuffer = [_commandQueue commandBuffer];

創(chuàng)建渲染流程

使用MTLCommandBuffer對(duì)象,調(diào)用命令緩沖區(qū)的renderCommandEncoderWithDescriptor:方法來(lái)創(chuàng)建一個(gè)命令編碼器(MTLRenderCommandEncoder)。

id<MTLRenderCommandEncoder> commandEncoder = [commandBuffer renderCommandEncoderWithDescriptor:renderPassDescriptor];

在此示例中,您不對(duì)任何繪制命令進(jìn)行編碼,因此渲染過(guò)程唯一要做的就是清除紋理。調(diào)用命令編碼器的endEncoding方法表示渲染流程已完成。

[commandEncoder endEncoding];

在屏幕上顯示繪制

紋理繪制后不會(huì)自動(dòng)在屏幕上顯示新的內(nèi)容,事實(shí)上,只有一些紋理可以在屏幕上顯示。在Metal中可以在屏幕上顯示的紋理由drawable對(duì)象管理,要顯示內(nèi)容,你需要獲取一個(gè)drawable對(duì)象。

MTKView自動(dòng)創(chuàng)建drawable對(duì)象以管理其紋理。通過(guò)讀取currentDrawable可以獲取到當(dāng)前的drawable對(duì)象。

id<MTLDrawable> drawable = view.currentDrawable;

調(diào)用命令緩沖區(qū)中的方法,并傳入drawable。presentDrawable:

[commandBuffer presentDrawable:drawable];

該方法告訴M??etal在執(zhí)行命令緩沖區(qū)時(shí),Metal應(yīng)該與Core Animation協(xié)調(diào)??以在渲染完成后顯示紋理。當(dāng)Core Animation呈現(xiàn)紋理時(shí),它將成為視圖的新內(nèi)容。在此示例中,這意味著擦除的紋理成為該視圖的新背景。該更改與Core Animation對(duì)屏幕用戶(hù)界面元素所做的任何其他視覺(jué)更新同時(shí)進(jìn)行。

提交命令緩沖區(qū)

現(xiàn)在,您已經(jīng)為框架發(fā)出了所有命令,請(qǐng)?zhí)峤幻罹彌_區(qū)。

[commandBuffer commit];

至此我們就使用Metal完成了一次顯示。

命令對(duì)象之間的關(guān)系

  1. 命令緩存區(qū)(command buffer) 是從命令隊(duì)列列(command queue) 創(chuàng)建的。
  2. 命令編碼器器(command encoders) 將命令編碼到命令緩存區(qū)中。
  3. 提交命令緩存區(qū)并將其發(fā)送到GPU。
  4. GPU執(zhí)行命令并將結(jié)果呈現(xiàn)為可繪制。


    -w942
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀(guān)點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容