使用金屬繪制視圖內(nèi)容
創(chuàng)建一個(gè)MetalKit視圖和一個(gè)渲染過(guò)程以繪制視圖的內(nèi)容。
概述
在此示例中,您將學(xué)習(xí)使用Metal渲染圖形內(nèi)容的基礎(chǔ)。您將使用MetalKit框架創(chuàng)建一個(gè)使用Metal繪制視圖內(nèi)容的視圖,然后,您將編碼用于渲染過(guò)程的命令,該過(guò)程會(huì)將視圖擦除為背景色。
筆記
MetalKit自動(dòng)執(zhí)行窗口系統(tǒng)任務(wù),加載紋理并處理3D模型數(shù)據(jù)。有關(guān)更多信息,請(qǐng)常見(jiàn)MetalKit.
準(zhǔn)備要繪制的MetalKit 視圖
MetalKIt 提供了一個(gè)名為MTKView類(lèi)。它是NSView(在macOS中)或UIView(在iOS 和 tvOS中)的子類(lèi)。MTKView處理與將您使用Metal繪制的內(nèi)容顯示到屏幕上有關(guān)的許多細(xì)節(jié)。
MTKView 需要引用Metal設(shè)備對(duì)象在內(nèi)部創(chuàng)建資源,因此第一步是將視圖的device屬性設(shè)置為MTLDevice.
其它屬性MTKView 允許您控制其行為。要將視圖的內(nèi)容擦出為純背景色,請(qǐng)?jiān)O(shè)置clearColor屬性,您可以使用MTLClearColorMake(:::)函數(shù)創(chuàng)建顏色,并指定紅色,綠色,藍(lán)色和alpha值.
_view.clearColor = MTLClearColorMake(0.0,0.5,1.0,1.0);
因?yàn)樵诖耸纠心鷮⒉粫?huì)繪制動(dòng)畫(huà)內(nèi)容,所以請(qǐng)配置視圖,以便僅在需要更新內(nèi)容時(shí)(例如,視圖改變形狀時(shí))才繪制視圖:
_view.enableSetNeedsDisplay = YES;
委托圖紙責(zé)任
MTKView 依靠您的應(yīng)用向Metal發(fā)出命令以生成視覺(jué)內(nèi)容,MTKView 使用委托模式來(lái)通知您的應(yīng)用何時(shí)應(yīng)繪制,要接受委托回調(diào),請(qǐng)將視圖的delegate屬性設(shè)置為符合協(xié)議的對(duì)象,
_view.delegate = _renderer;
該委托實(shí)現(xiàn)兩種方法:
- 每當(dāng)內(nèi)容大小更改時(shí),視圖都會(huì)調(diào)用mtkView(_:drawableSizeWillChange:)該方法,當(dāng)調(diào)整包含視圖窗口的大小或更改設(shè)備方向(在ios上)時(shí),會(huì)發(fā)生這種情況,這使您的應(yīng)用可以根據(jù)視圖的大小調(diào)整其呈現(xiàn)的分辨率。
- draw(in:) 每當(dāng)需要更新視圖內(nèi)容時(shí),視圖就會(huì)調(diào)用該方法,在這種方法中,您將創(chuàng)建命令緩沖區(qū),對(duì)告訴GPU繪制內(nèi)容以及何時(shí)在屏幕上顯示的命令進(jìn)行編碼,并排隊(duì)該命令緩沖區(qū)以供GPU執(zhí)行,有時(shí)這稱(chēng)為繪制框架,您可以將框架視為產(chǎn)生單個(gè)圖像并顯示在屏幕上的所有工作,在像游戲這樣的交互式應(yīng)用程序中,您可能每秒繪制很多幀。
在此示例中,名為AAPLRender類(lèi)實(shí)現(xiàn)委托犯法并承擔(dān)繪制的責(zé)任,視圖控制器創(chuàng)建此類(lèi)的實(shí)例,并將其設(shè)置為視圖的委托。
創(chuàng)建渲染過(guò)程描述符
繪制時(shí),GPU將結(jié)果存儲(chǔ)在紋理中,紋理是包含圖像數(shù)據(jù)的內(nèi)存快。,GPU可以訪問(wèn)它們。在此示例中,將MTKView創(chuàng)建您需要繪制到視圖中的所有紋理。它創(chuàng)建多個(gè)紋理,以便在渲染到另一個(gè)紋理時(shí)可以顯示一個(gè)紋理的內(nèi)容。
要進(jìn)行繪制,請(qǐng)創(chuàng)建一個(gè)RenderPass,這是一系列繪制命令可以繪制成一組紋理,在渲染過(guò)程中使用時(shí),紋理也稱(chēng)為渲染目標(biāo)。要?jiǎng)?chuàng)建渲染過(guò)程,您需要一個(gè)渲染過(guò)程描述符,即MTLRenderPassDescriptor的實(shí)例,在此示例中,無(wú)需配置自己的渲染過(guò)程描述符,而是請(qǐng)MetalKit視圖為您創(chuàng)建一個(gè)。
MTLRenderPassDescriptor *renderPassDescriptor = view.currentRenderPassDescriptor;
if (renderPassDescriptor == nil ){
return;
}
渲染過(guò)程描述符描述了渲染目標(biāo)的集合,以及在渲染過(guò)程的開(kāi)始和結(jié)束時(shí)應(yīng)如何處理它們。渲染過(guò)程還定義了一些其它方面的渲染,這些方面不屬于本示例。視圖返回帶有單個(gè)顏色附件的渲染過(guò)程描述符,該描述符指向紋理之一,否則將基于視圖的屬性配置渲染過(guò)程。默認(rèn)情況下,這意味著在渲染過(guò)程開(kāi)始時(shí),渲染目標(biāo)被擦除為與視圖屬性匹配的顏色,并且在渲染過(guò)程結(jié)束時(shí),所有更改都被存儲(chǔ)回紋理。
由于視圖的渲染過(guò)程描述符可能時(shí)nil,因此nil在創(chuàng)建渲染過(guò)程之前,應(yīng)進(jìn)行測(cè)試以確保渲染過(guò)程描述符對(duì)象為非對(duì)象。
創(chuàng)建渲染通行證
您可以通過(guò)使用MTLRenderCommandEncoder對(duì)象將渲染過(guò)程編碼到命令緩沖區(qū)中來(lái)創(chuàng)建渲染過(guò)程。調(diào)用命令緩沖區(qū)的方法makeRenderCommandEncoder(descriptor:)并傳入渲染過(guò)程描述符。
id <MTLRenderCommandEncoder> commandEncoder = [commandBuffer renderCommandEncoderWithDescriptor:descriptor];
在此示例中,您不對(duì)任何繪圖命令進(jìn)行編碼,因此渲染過(guò)程唯一要做的就是擦除紋理。調(diào)用編碼器的方法endEncoding以指示通過(guò)已完成。
[commandEncoder endEncoding];
在屏幕上顯示一個(gè)可繪制對(duì)象
繪制到紋理不會(huì)自動(dòng)在屏幕上顯示新內(nèi)容。實(shí)際上,只有一些紋理可以顯示在屏幕上。在Metal中,可以在屏幕上顯示的紋理由可繪制對(duì)象管理,要顯示內(nèi)容,請(qǐng)顯示可繪制對(duì)象。
MTKView 自動(dòng)創(chuàng)建可繪制對(duì)象以管理其紋理。讀取currentDrawable屬性以獲得具有紋理的可繪制對(duì)象,該紋理是渲染通道的目標(biāo)。該視圖返回一個(gè)CAMetalDrawable對(duì)象,該對(duì)象連接到Core Animation。
id <MTLDrawable> drawable = view.currentDrawable;
調(diào)用present(_:)命令緩沖區(qū)中的方法,并傳入drawable;
[commandBuffer presentDrawable:drawable];
此方法告訴Metal,計(jì)劃執(zhí)行命令緩沖區(qū)時(shí),Metal應(yīng)該與Core Animation 協(xié)調(diào)以在渲染完成后顯示紋理。當(dāng)Core Animation 呈現(xiàn)紋理時(shí),它將成為視圖的新內(nèi)容。在此示例中,這意味著刪除的紋理成為該視圖的新背景。該更改與Core Animation 對(duì)屏幕用戶界面元素所做的任何其它視覺(jué)更新同時(shí)進(jìn)行。
提交命令緩沖區(qū)
現(xiàn)在,您可以為框架發(fā)出了所有命令,請(qǐng)?zhí)峤幻罹彌_區(qū)
[commandBuffer commit];