iOS metal API(二) - 使用Metal繪制視圖的內(nèi)容

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

下載demo

縱覽

在這個(gè)示例中,你將學(xué)習(xí)使用Metal 渲染圖形內(nèi)容的基礎(chǔ)知識(shí)。你將使用MetalKit 框架創(chuàng)建一個(gè)視圖并用Metal 來繪制視圖的內(nèi)容。然后,你將編碼為視圖設(shè)置背景顏色的渲染過程中的命令。

注意

MetalKit自動(dòng)執(zhí)行窗口系統(tǒng)任務(wù),加載紋理并處理3D模型數(shù)據(jù)。閱讀MetalKit來了解更多信息。

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

metalKit 提供一個(gè)叫MTKView的類, 它是NSView(在macOS中)或者UIView(在iOS 和 tvOS中)的子類,MTKView處理許多與將用Metal繪制的內(nèi)容顯示在屏幕上相關(guān)的細(xì)節(jié)。
為了在內(nèi)部創(chuàng)建資源,MTKView需要對(duì)Metal設(shè)備對(duì)象的引用,因此,第一步是將視圖的device屬性設(shè)置為現(xiàn)有的MTLDevice

_view.device = MTLCreateSystemDefaultDevice();

MTKView上的其他屬性允許你控制其行為,將視圖內(nèi)容擦除為純背景色,設(shè)置它的clearColor屬性。通過MTLClearColorMake()函數(shù)創(chuàng)建顏色,指定紅色、綠色、藍(lán)色和alpha值。

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

因?yàn)樵谶@個(gè)示例中不會(huì)繪制動(dòng)畫內(nèi)容,所以配置視圖,使其僅在需要更新內(nèi)容時(shí)繪制。

_view.enableSetNeedsDisplay = YES;

代理繪圖任務(wù)

MTKView依賴于您的應(yīng)用程序向Metal發(fā)出命令以生成可視內(nèi)容。MTKView使用代理模式通知應(yīng)用程序何時(shí)應(yīng)該繪制。為了接受代理的回調(diào),將視圖的delegate屬性設(shè)置為符合MTKViewDelegate協(xié)議的對(duì)象。

_view.delegate = _renderer;

代理實(shí)現(xiàn)了兩個(gè)方法:
1.每當(dāng)內(nèi)容大小發(fā)生變化時(shí),視圖將調(diào)用mtkView:drawableSizeWillChange:方法,這種變化在包含視圖的窗口調(diào)整大小時(shí),或者當(dāng)設(shè)備方向發(fā)生變化時(shí)(在iOS上)發(fā)生。這允許應(yīng)用程序根據(jù)視圖的大小調(diào)整渲染時(shí)的分辨率。
2.每當(dāng)?shù)剿⑿乱晥D內(nèi)容的時(shí)間時(shí),視圖會(huì)調(diào)用drawInMTKView:方法。在這個(gè)方法中創(chuàng)建一個(gè)命令緩沖區(qū),編碼命令告訴GPU畫什么和什么時(shí)候現(xiàn)在在屏幕上,然后在將要由GPU執(zhí)行的命令緩沖區(qū)中排隊(duì)。這個(gè)有時(shí)候稱為畫框。你可以把一個(gè)框架看作是產(chǎn)生一個(gè)在屏幕上顯示的單一圖像的所有工作。在一個(gè)交互式App中,比如游戲, 你可能每秒鐘畫很多框架。
在這個(gè)示例中,一個(gè)叫AAPLRenderer的類實(shí)現(xiàn)了代理方法并承擔(dān)繪圖的責(zé)任。視圖控制器創(chuàng)建這個(gè)類的一個(gè)實(shí)例并把它設(shè)置為視圖的代理。

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

當(dāng)你繪圖,GPU會(huì)把結(jié)果存儲(chǔ)到紋理中,紋理是包含圖像數(shù)據(jù)的內(nèi)存塊,可被GPU訪問。在本示例中,MTKView將創(chuàng)建需要繪制到視圖中的所有紋理。它創(chuàng)建多個(gè)紋理,以便在渲染到另一個(gè)紋理時(shí)顯示一個(gè)紋理的內(nèi)容。
要進(jìn)行繪制,請(qǐng)創(chuàng)建一個(gè)渲染過程,該過程是一系列渲染命令,這些命令繪制成一組紋理。在渲染過程中使用時(shí),紋理也被稱為渲染目標(biāo)。若要?jiǎng)?chuàng)建渲染過程,需要一個(gè)渲染過程描述符,即MTLRenderPassDescriptor的實(shí)例。在這個(gè)示例中,與其配置自己的渲染過程描述符,不如讓MetalKit 給你創(chuàng)建一個(gè)。

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

一個(gè)渲染過程描述符描述一組渲染目標(biāo),以及在渲染過程開始和結(jié)束時(shí)應(yīng)如何處理這些目標(biāo)。渲染過程還定義了渲染的某些其他方面,這些方面不是此例的一部分。該視圖返回一個(gè)渲染過程描述符,該描述符具有指向該視圖的某個(gè)紋理的單色附件,并根據(jù)該視圖的屬性配置渲染過程。默認(rèn)情況下,這意味著渲染過程開始時(shí),渲染目標(biāo)將被擦除為純色來匹配視圖的clearColor屬性,并且在渲染過程結(jié)束時(shí)所有更改都存儲(chǔ)回紋理。
一個(gè)一個(gè)視圖的渲染過程描述符可能為nil, 在創(chuàng)建渲染過程之前, 應(yīng)該確保渲染過程描述符對(duì)象不為nil。

創(chuàng)建一個(gè)渲染過程

通過使用 MTLRenderCommandEncoder對(duì)象將其編碼到命令緩沖區(qū)來創(chuàng)建渲染過程。調(diào)用命令緩沖區(qū)的render>CommandEncoderWithDescriptor:方法并在渲染過程描述符中傳遞。

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

在本示例中,您不編碼任何繪圖命令,因此渲染過程只會(huì)刪除紋理。調(diào)用編碼器的endEncoding方法以指示該過程已完成。

[commandEncoder endEncoding];

在屏幕上呈現(xiàn)一幅圖畫

繪制到紋理不會(huì)自動(dòng)在屏幕上顯示新內(nèi)容。實(shí)際上, 只有一些紋理可以顯示在屏幕上。Metal中,可以在屏幕上顯示的紋理由drawable對(duì)象管理,要顯示內(nèi)容,請(qǐng)顯示可繪制對(duì)象。
MTKView自動(dòng)創(chuàng)建可繪制對(duì)象來管理它的紋理,讀取currentDrawable
屬性以獲取擁有作為渲染過程目標(biāo)的紋理的drawable。視圖返回一個(gè)CAMetalDrawable
對(duì)象,一個(gè)連接到核心動(dòng)畫的對(duì)象。

id<MTLDrawable> drawable = view.currentDrawable;

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

[commandBuffer presentDrawable:drawable];

此方法告訴Metal,當(dāng)計(jì)劃執(zhí)行命令緩沖區(qū)時(shí),Metal應(yīng)與核心動(dòng)畫協(xié)調(diào)以在渲染完成后顯示紋理。當(dāng)核心動(dòng)畫呈現(xiàn)紋理時(shí),它將成為視圖的新內(nèi)容。在本示例中,這意味著刪除的紋理將成為視圖的新背景。這種變化與核心動(dòng)畫為屏幕用戶界面元素所做的任何其他視覺更新一起發(fā)生。

提交命令緩沖區(qū)

現(xiàn)在已經(jīng)發(fā)出了幀的所有命令,提交命令緩沖區(qū)。

[commandBuffer commit];
?著作權(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)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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