創(chuàng)建MetalKit視圖和渲染過程以繪制視圖的內(nèi)容
概觀
在本示例中防嗡,您將學(xué)習(xí)使用Metal渲染圖形內(nèi)容的基礎(chǔ)知識宪巨。您將使用MetalKit框架創(chuàng)建一個使用Metal繪制視圖內(nèi)容的視圖。然后,您將編碼用于將修改視圖背景顏色的渲染過程的命名舒裤。
注意
MetalKit自動化窗口任務(wù)系統(tǒng)忍些,加載紋理和處理3D模型數(shù)據(jù)。有關(guān)更多信息,請參閱MetalKit岖沛。
準備MetalKit視圖繪制
MetalKit提供一個名為MTKView的類暑始,他是NSView(macOS中)或者UIView(iOS和tvOS中)的子類。MetalKit處理許多與將您使用Metal繪制內(nèi)容放到屏幕上相關(guān)的細節(jié)婴削。
一個MTKView需要一個Metaldevice
對象的引用廊镜,以便在其內(nèi)部創(chuàng)建資源,所以你的第一步是以現(xiàn)有的MTLDevice設(shè)置視圖的device屬性唉俗。
mtkView?.device = MTLCreateSystemDefaultDevice()
MTKView
允許您控制其他屬性的行為嗤朴。要將視圖的內(nèi)容改為純色背景,請設(shè)置其clearColor屬性虫溜。您可以使用MTLClearColorMake(_: _: _: _:)函數(shù)創(chuàng)建color
雹姊,指定rgba
。
mtkView?.clearColor = MTLClearColorMake(0.0, 0.5, 1.0, 1.0)
因為您不需要在此示例中繪制動畫內(nèi)容衡楞,所以請配置視圖吱雏,使其僅在需要更新內(nèi)容時繪制,例如視圖改變形狀時:
mtkView?.enableSetNeedsDisplay = true
代理繪圖責(zé)任
MTKView
依賴于您的應(yīng)用程序向Metal發(fā)出命令以生成可視內(nèi)容瘾境。MTKView
使用代理模式通知您的應(yīng)用程序何時可以繪制歧杏。要接收代理回調(diào),請將視圖的delegate
設(shè)置為符合MTKViewDelegate協(xié)議的對象迷守。
mtkView?.delegate = renderer
代理實現(xiàn)的兩種方法:
- 只要內(nèi)容的大小發(fā)生變化犬绒,視圖就會調(diào)用mtkView(_:drawableSizeWillChange:)方法。當包含視圖的窗口調(diào)整大小或設(shè)備方向更改時(在iOS上)兑凿,會發(fā)生這種情況凯力。這允許您的應(yīng)用根據(jù)根據(jù)其呈現(xiàn)的分辨率調(diào)整視圖大小。
- 只要有時間更新視圖內(nèi)容急膀,試圖就會調(diào)用draw(in:)方法沮协。在此方法中,您將創(chuàng)建一個命令緩沖區(qū)卓嫂,編碼命令慷暂,告訴GPU繪制什么及何時在屏幕上顯示它,并將該命令緩沖區(qū)排入隊列以供GPU執(zhí)行晨雳。這有時被稱為繪制框架行瑞。您可以將框架視為生成在屏幕上顯示的單個圖像的所有工作。在交互式應(yīng)用程序中餐禁,如游戲血久,您可以每秒繪制許多幀。
在此示例中帮非,調(diào)用類APPLRenderer
實現(xiàn)代理方法并承擔(dān)繪制責(zé)任氧吐。視圖控制器視圖控制器創(chuàng)建此類的實例并將其設(shè)置為視圖的代理讹蘑。
創(chuàng)建渲染通道描述符(Render Pass Descriptor)
繪制時,GPU會將結(jié)果存儲到紋理中筑舅,紋理是包含圖像數(shù)據(jù)并可供GPU訪問的內(nèi)存塊座慰。在此示例中,將MTKView
創(chuàng)建繪制到視圖中所需的所有紋理翠拣。他創(chuàng)建多個紋理版仔,以便在渲染到另一個紋理的過程中可以顯示一個紋理的內(nèi)容。
要繪制误墓,您需要創(chuàng)建一個渲染過程蛮粮,它是一系列渲染命令,可以繪制成一組紋理谜慌。在渲染過程中使用時然想,紋理也稱為渲染目標。要創(chuàng)建渲染過程欣范,需要一個渲染過程描述符又沾,一個MTLRenderPassDescriptor實例。在此示例中熙卡,不要配置自己的渲染過程描述符,而是要求MetalKit視圖為您創(chuàng)建一個励饵。
guard let renderPassDescriptor = view.currentRenderPassDescriptor else { return }
渲染過程描述符渲染目標集驳癌,以及如何在渲染過程的開始和結(jié)束時處理它們。渲染過程還定義了渲染的其他一些方面役听,這些方面不屬于此示例的一部分颓鲜。視圖返回一個渲染過程描述符,其中包含指向視圖紋理之一的單一顏色附件典予,否則根據(jù)視圖的屬性配置渲染過程甜滨。默認情況下,這意味著渲染過程開始瘤袖,渲染目標將被刪除為與視圖clearColor
屬性匹配的純色衣摩,并且在渲染過程結(jié)束時,所有更改都將存儲會紋理捂敌。
因為視圖渲染過程描述符可能nil
艾扮,所以您應(yīng)該測試以確保在創(chuàng)建渲染過程之前渲染過程描述符(Render Pass Descriptor)
對象是non-nil
。
創(chuàng)建渲染通道
您可以使用MTLRenderCommand對象將其編碼帶命令緩沖區(qū)中來創(chuàng)建渲染過程占婉。調(diào)用命令緩沖區(qū)的makeRenderCommandEncoder(descriptor:)方法并傳入渲染過程描述符泡嘴。
let commandEncoder = commandBuffer?.makeRenderCommandEncoder(descriptor: renderPassDescriptor)
在此示例中,您不對繪圖命令進行任何編碼逆济,因此渲染過程唯一要做的就是擦除紋理酌予。調(diào)用編碼器的endEncoding
方法以指示傳遞完成磺箕。
commandEncoder?.endEncoding()
向屏幕呈現(xiàn)可繪制對象(Drawable)
繪制到紋理不會自動在屏幕呈現(xiàn)新內(nèi)容。實際上抛虫,屏幕上只能顯示一些紋理松靡。在Metal中,可以在屏幕上顯示的紋理由可繪制對象管理莱褒,要顯示內(nèi)容击困,您將呈現(xiàn)可繪制對象(drawable)
。
MTKView會自動創(chuàng)建可繪制對象(drawable)
來管理紋理广凸,讀取currentDrawable屬性以獲取擁有作為渲染目標的紋理的可繪制對象阅茶。這個視圖返回一個CAMetalDrawable對象,這個對象用來連接到Core Animation谅海。
guard let drawable = view.currentDrawable else { return }
在命令緩沖區(qū)上調(diào)用present(_:)方法脸哀,傳入drawable
。
commandBuffer?.present(drawable)
此方法告訴Metal扭吁,當命令緩沖區(qū)被安排執(zhí)行時撞蜂,Metal應(yīng)與Core Animation協(xié)調(diào)以在渲染完成后顯示紋理。當Core Animation呈現(xiàn)紋理時侥袜,它將成為視圖的新內(nèi)容蝌诡。在此示例中,這意味著已擦除的紋理將成為視圖的新背景枫吧。此更改與Core Animation為屏幕用戶界面元素進行的其他可視更新一起發(fā)生浦旱。
提交命令緩沖區(qū)
現(xiàn)在您已經(jīng)為該幀發(fā)出了所有命令,請?zhí)峤幻罹彌_區(qū)九杂。
commandBuffer?.present(drawable)