iOS 圖形編輯幾種 API(UIKIT、Core Graphics、OpenGL ES及GLKit)

這些api包含的繪制操作都在一個(gè)圖形環(huán)境中進(jìn)行繪制。一個(gè)圖形環(huán)境包含繪制參數(shù)和所有的繪制需要的設(shè)備特定信息,包括屏幕圖形環(huán)境、offscreen 位圖環(huán)境和PDF圖形環(huán)境,用來(lái)在屏幕表面、一個(gè)位圖或一個(gè)pdf文件中進(jìn)行圖形和圖像繪制。在屏幕圖形環(huán)境中進(jìn)行的繪制限定于在一個(gè)UIView類或其子類的實(shí)例中繪制,并直接在屏幕顯示,在offscreen位圖或PDF圖形環(huán)境中進(jìn)行的繪制不直接在屏幕上顯示。

一、UIKIT API

UIKIT是一組Objective-C API,為線條圖形、Quartz圖像和顏色操作提供Objective-C 封裝,并提供2D繪制、圖像處理及用戶接口級(jí)別的動(dòng)畫(huà)。

UIKIT包括UIBezierPath(繪制線、角度、橢圓及其它圖形)、UIImage(顯示圖像)、UIColor(顏色操作)、UIFont和UIScreen(提供字體和屏幕信息)等類以及在位圖圖形環(huán)境、PDF圖形環(huán)境上進(jìn)行繪制和 操作的功能等, 也提供對(duì)標(biāo)準(zhǔn)視圖的支持,也提供對(duì)打印功能的支持。

在UIKIT中UIView類本身在繪制時(shí)自動(dòng)創(chuàng)建一個(gè)圖形環(huán)境(對(duì)應(yīng)Core Graphics層的CGContext類型)作為當(dāng)前的圖形繪制環(huán)境。在繪制時(shí)可以調(diào)用UIGraphicsGetCurrentContext 函數(shù)獲得當(dāng)前的圖形環(huán)境。

二、Core Graphics 與Quartz 2D API

Core Graphics是一套C-based API, 支持向量圖形,線、形狀、圖案、路徑、剃度、位圖圖像和pdf 內(nèi)容的繪制。

Quartz 2D 是Core Graphics中的2D 繪制呈現(xiàn)引擎。Quartz是資源和設(shè)備無(wú)關(guān)的,提供路徑繪制,anti-aliased呈現(xiàn),剃度填充圖案,圖像,透明繪制和透明層、遮蔽和陰影、顏色管理,坐標(biāo)轉(zhuǎn)換,字體、offscreen呈現(xiàn)、pdf文檔創(chuàng)建、顯示和分析等功能。

Quartz 2D能夠與所有的圖形和動(dòng)畫(huà)技術(shù)(如Core Animation, OpenGL ES, 和 UIKit 等)一起使用。

Quartz采用paint模式進(jìn)行繪制。

Quartz 中使用的圖形環(huán)境也由一個(gè)類CGContext表示。

在Quartz 中可以把一個(gè)圖形環(huán)境作為一個(gè)繪制目標(biāo)。當(dāng)使用Quartz 進(jìn)行繪制時(shí),所有設(shè)備特定的特性被包含在你使用的特定類型的圖形環(huán)境中,因此通過(guò)給相同的圖像操作函數(shù)提供不同的圖像環(huán)境你就能夠畫(huà)相同的圖像到不同的設(shè)備上,因此做到了圖像繪制的設(shè)備無(wú)關(guān)性。

Quartz 為應(yīng)用提供如下幾個(gè)圖形環(huán)境:

1)位圖圖形環(huán)境,用來(lái)創(chuàng)建一個(gè)位圖。

使用函數(shù)CGBitmapContextCreate來(lái)創(chuàng)建。

2)PDF圖形環(huán)境,用來(lái)創(chuàng)建一個(gè)pdf文件。

Quartz 2D API提供了兩個(gè)函數(shù)來(lái)創(chuàng)建一個(gè)PDF圖形環(huán)境:

CGPDFContextCreateWithURL,帶有一個(gè)作為pdf 輸出的位置的Core Foundation URL來(lái)創(chuàng)建一個(gè)pdf 圖形環(huán)境。

CGPDFContextCreate, 當(dāng)想PDF 輸出到一個(gè)data consumer時(shí)使用該函數(shù)。

3) 窗口圖形環(huán)境,用來(lái)在一個(gè)窗口上進(jìn)行繪制。

4) 層環(huán)境(CGLayer) ,是一個(gè)與另一個(gè)圖形環(huán)境關(guān)聯(lián)的offscreen繪制目標(biāo),使用層環(huán)境的目的是為了優(yōu)化繪制層到創(chuàng)建它的圖形環(huán)境的性能。層環(huán)境能夠比位圖圖形環(huán)境提供更好的offscreen繪制性能。

Quartz提供的主要類包括:

CGContext:表示一個(gè)圖形環(huán)境;

CGPath:使用向量圖形來(lái)創(chuàng)建路徑,并能夠填充和stroke;

CGImage:用來(lái)表示位圖;

CGLayer:用來(lái)表示一個(gè)能夠用于重復(fù)繪制和offscreen繪制的繪制層;

CGPattern:用來(lái)表示Pattern,用于重復(fù)繪制;

CGShading和 CGGradient:用于繪制剃度;

CGColor 和 CGColorSpace;用來(lái)進(jìn)行顏色和顏色空間管理;

CGFont, 用于繪制文本;

CGPDFContentStream、CGPDFScanner、CGPDFPage、CGPDFObject,CGPDFStream, CGPDFString等用來(lái)進(jìn)行pdf文件的創(chuàng)建、解析和顯示。

三、OpenGL ES和GLKit

OpenGL ES是一套多功能開(kāi)放標(biāo)準(zhǔn)的用于嵌入系統(tǒng)的C-based的圖形庫(kù),用于2D和3D數(shù)據(jù)的可視化。OpenGL被設(shè)計(jì)用來(lái)轉(zhuǎn)換一組圖形調(diào)用功能到底層圖形硬件(GPU),由GPU執(zhí)行圖形命令,用來(lái)實(shí)現(xiàn)復(fù)雜的圖形操作和運(yùn)算,從而能夠高性能、高幀率利用GPU提供的2D和3D繪制能力。

OpenGL ES規(guī)范本身不定義繪制表面和繪制窗口,因此ios為了使用它必須提供和創(chuàng)建一個(gè)OpenGLES 的呈現(xiàn)環(huán)境,創(chuàng)建和配置存儲(chǔ)繪制命令結(jié)果的framebuffer 及創(chuàng)建和配置一個(gè)或多個(gè)呈現(xiàn)目標(biāo)。

在 iOS中使用EAGL提供的EAGLContext類 來(lái)實(shí)現(xiàn)和提供一個(gè)呈現(xiàn)環(huán)境,用來(lái)保持OpenGLES使用到的硬件狀態(tài)。 EAGL是一個(gè)Objective-C API,提供使OpenGL ES與Core Animation和UIKIT集成的接口。

在調(diào)用任何OpenGLES 功能之前必須首先初始化一個(gè)EAGLContext 對(duì)象。

每一個(gè)iOS應(yīng)用的每一個(gè)線程都有一個(gè)當(dāng)前context,在調(diào)用OpenGLES函數(shù)時(shí),使用或改變此context中的狀態(tài)。

EAGLContext 的類方法setCurrentContext:用來(lái)設(shè)置當(dāng)前線程的當(dāng)前context。EAGLContext 的類方法currentContext 返回當(dāng)前線程的當(dāng)前context。在切換相同線程的兩個(gè)上下文之前,必須調(diào)用glFlush函數(shù)來(lái)確保先前已提交的命令被提交到圖形硬件中。

可以采用不同的方式使用OpenGL ES以便呈現(xiàn)OpenGL ES內(nèi)容到不同的目標(biāo):GLKit和CAEAGLLayer。

為了創(chuàng)建全屏幕的視圖或使OpenGL ES內(nèi)容與UIKit視圖集成,可以使用GLKit。在使用GLKit時(shí),GLKit提供的類GLKView類本身實(shí)現(xiàn)呈現(xiàn)目標(biāo)及創(chuàng)建和維護(hù)一個(gè)framebuffer。

為了使OpenGL ES內(nèi)容作為一個(gè)Core Animation層的部分內(nèi)容時(shí),可以使用CAEAGLLayer 作為呈現(xiàn)目標(biāo),并需要另外創(chuàng)建framebuffer以及自己實(shí)現(xiàn)和控制整個(gè)繪制流程。

GLKit是一組Objective-C 類,為使用OpenGL ES 提供一個(gè)面向?qū)ο蠼涌冢脕?lái)簡(jiǎn)化OpenGL ES應(yīng)用的開(kāi)發(fā)。GLKit支持四個(gè)3D應(yīng)用開(kāi)發(fā)的關(guān)鍵領(lǐng)域:

1) GLKView 和GLKViewController類提供一個(gè)標(biāo)準(zhǔn)的OpenGLES視圖和相關(guān)聯(lián)的呈現(xiàn)循環(huán)。GLKView可以作為OpenGLES內(nèi)容的呈現(xiàn)目標(biāo),GLKViewController提供內(nèi)容呈現(xiàn)的控制和動(dòng)畫(huà)。視圖管理和維護(hù)一個(gè)framebuffer,應(yīng)用只需在framebuffer進(jìn)行繪畫(huà)即可。

2)GLKTextureLoader 為應(yīng)用提供從iOS支持的各種圖像格式的源自動(dòng)加載紋理圖像到OpenGLES 圖像環(huán)境的方式,并能夠進(jìn)行適當(dāng)?shù)霓D(zhuǎn)換,并支持同步和異步加載方式。

3)數(shù)學(xué)運(yùn)算庫(kù),提供向量、矩陣、四元數(shù)的實(shí)現(xiàn)和矩陣堆棧操作等OpenGL ES 1.1功能。

4)Effect效果類提供標(biāo)準(zhǔn)的公共著色效果的實(shí)現(xiàn)。能夠配置效果和相關(guān)的頂點(diǎn)數(shù)據(jù),然后創(chuàng)建和加載適當(dāng)?shù)闹鳌LKit 包括三個(gè)可配置著色效果類:GLKBaseEffect實(shí)現(xiàn)OpenGL ES 1.1規(guī)范中的關(guān)鍵的燈光和材料模式, GLKSkyboxEffect提供一個(gè)skybox效果的實(shí)現(xiàn), GLKReflectionMapEffect 在GLKBaseEffect基礎(chǔ)上包括反射映射支持。

使用GLKView和OpenGLES進(jìn)行繪制過(guò)程:

1)創(chuàng)建一個(gè)GLKView 對(duì)象

GLKView 對(duì)象可以編程或使用Interface Builder來(lái)創(chuàng)建和配置。

在采用編程方式時(shí),首先創(chuàng)建一個(gè)context然后調(diào)用initWithFrame:context:方法。

使用Interface Builder方式時(shí),在從storyboard加載一個(gè)GLKView后,創(chuàng)建一個(gè)context和設(shè)置它作為視圖的context屬性.

在iOS中GLKit的使用需要?jiǎng)?chuàng)建OpenGL ES 2.0以上的圖形環(huán)境context。

GLKit視圖自動(dòng)創(chuàng)建和配置它所有的OpenGLES framebuffer對(duì)象和renderbuffers,可以通過(guò)修改視圖的drawable屬性來(lái)控制這些對(duì)象的屬性。

2)繪制OpenGL內(nèi)容(發(fā)布繪制命令)

使用GLKit視圖繪制OpenGL內(nèi)容需要三個(gè)子步驟:準(zhǔn)備OpenGLES基礎(chǔ);發(fā)布繪制命令;呈現(xiàn)顯示內(nèi)容到Core Animation。 GLKit類本身已經(jīng)實(shí)現(xiàn)了第一個(gè)和第三個(gè)步驟,用戶只需實(shí)現(xiàn)第二個(gè)步驟,在視圖的方法drawRect或視圖的代理對(duì)象的glkView:drawInRect:中調(diào)用適當(dāng)?shù)腛penGLES繪制命令進(jìn)行內(nèi)容繪制。

GLKViewController類維護(hù)一個(gè)animation 呈現(xiàn)循環(huán)(包含兩個(gè)方法update和display),用來(lái)實(shí)現(xiàn)連續(xù)的動(dòng)畫(huà)復(fù)雜的場(chǎng)景。

animation 呈現(xiàn)循環(huán)的交替速率由GLKViewController的屬性framesPerSecond 指示,并使用preferredFramesPerSecond 屬性來(lái)修改它。

四、其它圖形編程相關(guān)API

1)Core Animation

Core Animation是一套Objective-C API,實(shí)現(xiàn)了一個(gè)高性能的復(fù)合引擎,并提供一個(gè)簡(jiǎn)單易用的編程接口,給用戶UI添加平滑運(yùn)動(dòng)和動(dòng)態(tài)反饋能力。

Core Animation 是 UIKit實(shí)現(xiàn)動(dòng)畫(huà)和變換的基礎(chǔ),也負(fù)責(zé)視圖的復(fù)合功能。使用Core Animation可以實(shí)現(xiàn)定制動(dòng)畫(huà)和細(xì)粒度的動(dòng)畫(huà)控制,創(chuàng)建復(fù)雜的、支持動(dòng)畫(huà)和變換的layered 2D視圖。

Core Animation不屬于繪制系統(tǒng),但它是以硬件復(fù)合和操作顯示內(nèi)容的基礎(chǔ)設(shè)施。這個(gè)基礎(chǔ)設(shè)施的核心是layer對(duì)象,用來(lái)管理和操作顯示內(nèi)容。在ios 中每一個(gè)視圖都對(duì)應(yīng)Core Animation的一個(gè)層對(duì)象,與視圖一樣,層之間也組織為層關(guān)系樹(shù)。一個(gè)層捕獲視圖內(nèi)容為一個(gè)被圖像硬件容易操作的位圖。在多數(shù)應(yīng)用中層作為管理視圖的方式使用,但也可以創(chuàng)建獨(dú)立的層到一個(gè)層關(guān)系樹(shù)中來(lái)顯示視圖不夠支持的顯示內(nèi)容。

OpenGL ES的內(nèi)容也可以與Core Animation內(nèi)容進(jìn)行集成。

為了使用Core Animation實(shí)現(xiàn)動(dòng)畫(huà),可以修改層的屬性值來(lái)觸發(fā)一個(gè)action對(duì)象的執(zhí)行,不同的action對(duì)象實(shí)現(xiàn)不同的動(dòng)畫(huà)。

Core Animation 提供了一下一組應(yīng)用可以采用的類來(lái)提供對(duì)不同動(dòng)畫(huà)類型的支持:

CAAnimation是一個(gè)抽象公共基類,CAAnimation采用CAMediaTiming 和CAAction協(xié)議為動(dòng)畫(huà)提供時(shí)間(如周期、速度、重復(fù)次數(shù)等)和action行為(啟動(dòng)、停止等)。

CAPropertyAnimation是 CAAnimation的抽象子類,為動(dòng)畫(huà)提供一個(gè)由一個(gè)key路徑規(guī)定的層屬性的支持;

CABasicAnimation 是CAPropertyAnimation的具體子類,為一個(gè)層屬性提供簡(jiǎn)單插入能力。

CAKeyframeAnimation也是CAPropertyAnimation的具體子類,提供key幀動(dòng)畫(huà)支持。

CATransition是CAAnimation的具體子類,提供影響整個(gè)層內(nèi)容的事物效果。

CAAnimationGroup也是CAAnimation的子類,允許動(dòng)畫(huà)對(duì)象組合到一起并同時(shí)運(yùn)行。

2)Image I/O

Image I/O 提供讀寫(xiě)多數(shù)格式圖像文件的數(shù)據(jù)的接口。主要包括圖像源CGImageSourceRef和圖像目標(biāo)CGImageDestinationRef兩個(gè)類。

3)Sprite Kit

Sprite Kit建立于OpenGL ES之上,Sprite Kit使用圖形硬件來(lái)有效的呈現(xiàn)動(dòng)畫(huà)幀,因此可以高幀率地動(dòng)畫(huà)和呈現(xiàn)任意的2D紋理圖像或游戲sprite,呈現(xiàn)的內(nèi)容包括sprites、文本、CGPath形狀、視頻等。

在Sprite Kit中動(dòng)畫(huà)和呈現(xiàn)由一個(gè)SKView視圖對(duì)象執(zhí)行。游戲的內(nèi)容組織為以SKScene對(duì)象表現(xiàn)的一個(gè)個(gè)場(chǎng)景。一個(gè)場(chǎng)景包含要呈現(xiàn)的sprites和其它內(nèi)容,一個(gè)場(chǎng)景也實(shí)現(xiàn)每個(gè)幀關(guān)聯(lián)的邏輯和內(nèi)容處理。

在同一時(shí)刻,一個(gè)SKView視圖只呈現(xiàn)一個(gè)場(chǎng)景,在場(chǎng)景呈現(xiàn)時(shí),場(chǎng)景關(guān)聯(lián)的動(dòng)畫(huà)和幀關(guān)聯(lián)的邏輯被自動(dòng)執(zhí)行。在切換場(chǎng)景時(shí)使用SKTransition 類來(lái)執(zhí)行兩個(gè)場(chǎng)景間的動(dòng)畫(huà)。

4)SceneKit

SceneKit是一個(gè)使用3D圖形技術(shù)實(shí)現(xiàn)的Objective-C 框架,包含一個(gè)高性能的呈現(xiàn)引擎和一個(gè)高級(jí)的描述性API。可以利用該框架創(chuàng)建簡(jiǎn)單的游戲和界面豐富的用戶UI,使用SceneKit僅需要使用描述性API描述你的場(chǎng)景的內(nèi)容(如幾何形狀、材料、燈光和攝像等)和你想在那些內(nèi)容上要執(zhí)行的行動(dòng)或動(dòng)畫(huà)即可。

SceneKit的內(nèi)容組織為由節(jié)點(diǎn)組成的樹(shù)形結(jié)構(gòu),稱為scene graph。一個(gè)場(chǎng)景包含一個(gè)根節(jié)點(diǎn),定義場(chǎng)景的坐標(biāo)空間,其它節(jié)點(diǎn)定義場(chǎng)景的可視內(nèi)容。SceneKit在GPU上呈現(xiàn)每一幀之前在一個(gè)視圖上顯示場(chǎng)景、處理scene graph和執(zhí)行動(dòng)畫(huà)處理。

SceneKit包含的主要類:

SCNView & SCNSceneRenderer:SCNView是顯示或呈現(xiàn)SceneKit內(nèi)容的視圖。SCNSceneRenderer是一個(gè)協(xié)議,定義用于視圖的一些重要方法。

SCNScene: 表現(xiàn)一個(gè)場(chǎng)景,是所有SceneKit內(nèi)容的一個(gè)容器。場(chǎng)景可以從使用3D著作工具創(chuàng)建的一個(gè)文件中加載,也可以編程創(chuàng)建,場(chǎng)景需要在一個(gè)視圖上顯示。

SCNNode:一個(gè)場(chǎng)景的基本構(gòu)造塊,表示scene graph樹(shù)的一個(gè)節(jié)點(diǎn)。scene graph樹(shù)定義了場(chǎng)景上節(jié)點(diǎn)之間的邏輯結(jié)構(gòu),通過(guò)為一個(gè)節(jié)點(diǎn)附屬geometries、lights、cameras來(lái)提供場(chǎng)景的可視內(nèi)容。

SCNGeometry、SCNLight、SCNCamera:分別是geometries、lights、cameras對(duì)應(yīng)的類。SCNGeometry為場(chǎng)景提供形狀、文本或定制頂點(diǎn)數(shù)據(jù),SCNLight為場(chǎng)景提供陰影效果,SCNCamera為場(chǎng)景提供可視點(diǎn)。

SCNMaterial:為SCNGeometry對(duì)象定義表面外觀屬性,規(guī)定對(duì)象表面如何著色或紋理以及如何反應(yīng)燈光。

SceneKit內(nèi)容的動(dòng)畫(huà):

SceneKit動(dòng)畫(huà)基于Core Animation 框架,可以隱式或顯式創(chuàng)建。

隱式創(chuàng)建是實(shí)際是通過(guò)動(dòng)畫(huà)節(jié)點(diǎn)的一些動(dòng)畫(huà)屬性來(lái)實(shí)現(xiàn):SceneKit自動(dòng)在run loop一次運(yùn)行期間對(duì)一個(gè)場(chǎng)景包含節(jié)點(diǎn)屬性的所有改變組合成一個(gè)原子操作,稱為一個(gè)事務(wù),由SCNTransaction 類表示;當(dāng)設(shè)置SCNTransaction類的動(dòng)畫(huà)周期不為0時(shí),所有對(duì)節(jié)點(diǎn)動(dòng)畫(huà)屬性的改變自動(dòng)執(zhí)行動(dòng)畫(huà)。

如下代碼片段所示:

func fallAndFade(sender:  a href="" AnyObject /a ) {
    SCNTransaction.setAnimationDuration(1.0)
    textNode.position = SCNVector3(x: 0.0, y: -10.0, z: 0.0)
    textNode.opacity = 0.0
}

顯式創(chuàng)建動(dòng)畫(huà)時(shí),可以選擇CAAnimation一種類型的子類來(lái)創(chuàng)建特定類型的動(dòng)畫(huà)。使用key-value為動(dòng)畫(huà)規(guī)定屬性及設(shè)置動(dòng)畫(huà)參數(shù),然后把創(chuàng)建的動(dòng)畫(huà)附屬到場(chǎng)景的一個(gè)或多個(gè)元素。可以使用不同的Core Animation動(dòng)畫(huà)類組合或序列化幾個(gè)動(dòng)畫(huà)或創(chuàng)建動(dòng)畫(huà)在幾個(gè) keyframe值之間插入屬性值。

如下代碼片段為顯式創(chuàng)建動(dòng)畫(huà)的例子:

let animation = CABasicAnimation(keyPath: ``"geometry.extrusionDepth"``)`

`animation.fromValue = 0.0`

`animation.toValue = 100.0`

`animation.duration = 1.0`

`animation.autoreverses = ``true`

`animation.repeatCount = Float.infinity`

`textNode.addAnimation(animation, forKey: “extrude")

SceneKit也支持使用SCNSceneSource 類從一個(gè)場(chǎng)景文件中加載CAAnimation動(dòng)畫(huà)對(duì)象,然后附屬它到SCNNode對(duì)象。

5)Metal

Metal框架是一個(gè)OpenGL ES類似的底層API,為GPU加速的先進(jìn)的3D圖形呈現(xiàn)或數(shù)據(jù)并行計(jì)算任務(wù)提供支持。Metal負(fù)責(zé)和3D繪圖硬件交互,為圖形和計(jì)算命令的組織、處理、提交和相關(guān)資源和數(shù)據(jù)的管理提供一個(gè)細(xì)粒度的、底層的支持流式計(jì)算的現(xiàn)代API。Metal的目標(biāo)是在執(zhí)行GPU任務(wù)時(shí)盡量減少CPU的負(fù)載,消除在GPU執(zhí)行圖形和數(shù)據(jù)并行計(jì)算操作時(shí)的性能瓶頸,能夠有效的使用多線程并行創(chuàng)建和提交命令到GPU。

Metal也提供了一個(gè)映射編程語(yǔ)言用來(lái)編寫(xiě)能夠被Metal應(yīng)用使用的圖形映射或計(jì)算函數(shù)。Metal映射語(yǔ)言編寫(xiě)的代碼能夠在編譯時(shí)與應(yīng)用代碼一起被編譯,然后在運(yùn)行時(shí)被加載到GPU上執(zhí)行;也支持運(yùn)行時(shí)對(duì)Metal 映射語(yǔ)言代碼進(jìn)行編輯。

在Metal架構(gòu)中包括如下幾個(gè)重要的類或協(xié)議:

1、MTLDevice協(xié)議和對(duì)象

一個(gè)MTLDevice代表一個(gè)執(zhí)行命令的GPU設(shè)備,MTLDevice協(xié)議為其定義了相關(guān)接口,包括查詢?cè)O(shè)備能力屬性和創(chuàng)建其它設(shè)備特定的對(duì)象等接口,例如創(chuàng)建命令隊(duì)列、從內(nèi)存中分配緩沖區(qū)以及創(chuàng)建紋理等。

應(yīng)用通過(guò)調(diào)用MTLCreateSystemDefaultDevice 函數(shù)來(lái)獲取一個(gè)系統(tǒng)能夠使用的MTLDevice對(duì)象。

2、命令和命令編碼器

在Metal框架中,3D圖形呈現(xiàn)命令、計(jì)算命令和blitting命令在提交到特定設(shè)備GPU上執(zhí)行前必須進(jìn)行相應(yīng)的格式編碼,以便能夠被GPU識(shí)別和執(zhí)行。

Metal框架為每種命令提供了一種編碼器協(xié)議:

MTLRenderCommandEncoder 協(xié)議:提供接口用來(lái)編碼一個(gè)單次循環(huán)呈現(xiàn)期間要執(zhí)行的3D圖形呈現(xiàn)命令。MTLRenderCommandEncoder 對(duì)象用來(lái)代表一次圖形呈現(xiàn)流程的呈現(xiàn)狀態(tài)和繪制命令。

MTLComputeCommandEncoder協(xié)議:提供接口用來(lái)編碼數(shù)據(jù)并行計(jì)算任務(wù)。

MTLBlitCommandEncoder協(xié)議:提供接口用來(lái)編碼在緩沖和紋理之間的簡(jiǎn)單拷貝操作。

在同一時(shí)刻,僅能有一個(gè)命令編碼器激活來(lái)添加命令到一個(gè)命令緩沖空間上,即每一個(gè)命令編碼器必須在另一個(gè)使用相同命令緩沖空間的命令編碼器創(chuàng)建前結(jié)束。

Metal為了支持多個(gè)不同任務(wù)的并行執(zhí)行,提供了一個(gè)MTLParallelRenderCommandEncoder協(xié)議來(lái)支持多個(gè)MTLBlitCommandEncoder在不同線程同時(shí)運(yùn)行提交不同的命令緩沖到同一個(gè)命令緩沖空間。每一個(gè)線程有一個(gè)它自己的命令緩沖對(duì)象,在同一時(shí)刻,該緩沖對(duì)象只能被該線程的一個(gè)命令編碼器存取。

MTLParallelRenderCommandEncoder對(duì)象允許一次呈現(xiàn)循環(huán)的命令編碼分解到多個(gè)命令編碼器進(jìn)行編碼,使用多線程進(jìn)行并行處理來(lái)提高處理效率。

一個(gè)命令編碼器對(duì)象調(diào)用endEncoding方法來(lái)結(jié)束。

命令編碼器對(duì)象的創(chuàng)建:

命令編碼器對(duì)象由MTLCommandBuffer對(duì)象負(fù)責(zé)創(chuàng)建。MTLCommandBuffer協(xié)議定義了如下方法用來(lái)創(chuàng)建相應(yīng)類型的命令編碼器對(duì)象:

renderCommandEncoderWithDescriptor:為執(zhí)行圖形呈現(xiàn)任務(wù)創(chuàng)建一個(gè)MTLRenderCommandEncoder 對(duì)象。方法的參數(shù)MTLRenderPassDescriptor表現(xiàn)一個(gè)編碼呈現(xiàn)命令的目標(biāo)(是一個(gè)附屬點(diǎn)的集合,最多可以包括四個(gè)顏色點(diǎn)數(shù)據(jù)附屬點(diǎn)、一個(gè)深度點(diǎn)數(shù)據(jù)附屬點(diǎn)、一個(gè)圖案點(diǎn)數(shù)據(jù)附屬點(diǎn)),在MTLRenderPassDescriptor對(duì)象的附屬點(diǎn)屬性中指定要呈現(xiàn)的圖形目標(biāo)。

computeCommandEncoder方法為數(shù)據(jù)并行計(jì)算任務(wù)創(chuàng)建一個(gè)MTLComputeCommandEncoder 對(duì)象。

blitCommandEncoder 方法為內(nèi)存Blit操作和紋理填充操及mipmaps的產(chǎn)生等操作創(chuàng)建一個(gè)MTLBlitCommandEncoder 對(duì)象。

parallelRenderCommandEncoderWithDescriptor: 方法創(chuàng)建一個(gè)MTLParallelRenderCommandEncoder對(duì)象。呈現(xiàn)目標(biāo)由 參數(shù)MTLRenderPassDescriptor規(guī)定。

3、命令緩沖MTLCommandBuffer對(duì)象及協(xié)議

在經(jīng)過(guò)命令編碼器編碼后的命令被命令編碼器添加到一個(gè)稱為命令緩沖的MTLCommandBuffer對(duì)象上,然后該CommandBuffer對(duì)象被提交到GPU來(lái)執(zhí)行其中包含的命令。

MTLCommandBuffer協(xié)議為CommandBuffer對(duì)象定義接口以及提供命令編碼器的創(chuàng)建、提交CommandBuffer到一個(gè)命令隊(duì)列以及檢查狀態(tài)等操作方法。

一個(gè)CommandBuffer對(duì)象包含打算在特定設(shè)備(GPU)上執(zhí)行的被編碼的命令。一旦所有的編碼完成,CommandBuffer本身必須提交到一個(gè)命令隊(duì)列,并標(biāo)記命令緩沖為準(zhǔn)備好狀態(tài),以便能夠被GPU 執(zhí)行。

在標(biāo)準(zhǔn)標(biāo)準(zhǔn)應(yīng)用中,通常一個(gè)呈現(xiàn)幀的呈現(xiàn)命令使用一個(gè)線程被編碼進(jìn)一個(gè)命令緩沖中。

MTLCommandBuffer對(duì)象的創(chuàng)建和相應(yīng)方法:

一個(gè)MTLCommandBuffer對(duì)象由MTLCommandQueue的commandBuffer方法或commandBufferWithUnretainedReferences方法創(chuàng)建。

一個(gè)MTLCommandBuffer對(duì)象僅能提交到創(chuàng)建它的MTLCommandQueue 對(duì)象中。

一個(gè)MTLCommandBuffer對(duì)象還實(shí)現(xiàn)協(xié)議定義的如下方法:

enqueue方法用來(lái)在命令隊(duì)列中為該命令緩沖保留一個(gè)位置。

commit 方法使MTLCommandBuffer對(duì)象被提交執(zhí)行。

addScheduledHandler:方法用來(lái)為一個(gè)命令緩沖對(duì)象登記一個(gè)在該命令緩沖被調(diào)度時(shí)被調(diào)用的代碼執(zhí)行塊。可以為一個(gè)命令緩沖對(duì)象登記多個(gè)調(diào)度執(zhí)行塊。

waitUntilScheduled 方法等待命令緩沖被調(diào)度及在為該命令緩沖登記的所有調(diào)度執(zhí)行塊已經(jīng)執(zhí)行完。

addCompletedHandler:方法為一個(gè)命令緩沖對(duì)象登記一個(gè)在設(shè)備已經(jīng)執(zhí)行完該命令緩沖后被調(diào)用的代碼執(zhí)行塊。也可以為一個(gè)命令緩沖對(duì)象登記多個(gè)完成執(zhí)行代碼塊。

waitUntilCompleted 方法等待命令緩沖中命令被設(shè)備執(zhí)行完和為該命令緩沖登記的所有完成執(zhí)行塊都執(zhí)行結(jié)束。

presentDrawable:方法用來(lái)在命令緩沖對(duì)象被調(diào)度時(shí)呈現(xiàn)一個(gè)可顯示資源(CAMetalDrawable 對(duì)象)的內(nèi)容。

4、MTLCommandQueue協(xié)議和命令隊(duì)列對(duì)象

MTLCommandQueue協(xié)議為包含命令緩沖的一個(gè)隊(duì)列。命令隊(duì)列用來(lái)組織其中包含的命令緩沖對(duì)象的執(zhí)行次序和控制命令隊(duì)列中的命令緩沖對(duì)象包含的命令什么時(shí)候被執(zhí)行。

MTLCommandQueue協(xié)議為命令隊(duì)列定義了接口,主要的接口包括命令緩沖對(duì)象的創(chuàng)建。

MTLCommandQueue對(duì)象的創(chuàng)建:

使用MTLDevice對(duì)象的newCommandQueue方法或newCommandQueueWithMaxCommandBufferCount:方法來(lái)創(chuàng)建一個(gè)命令隊(duì)列對(duì)象。

下圖為以上這些對(duì)象之間的關(guān)系圖:

[圖片上傳失敗...(image-e2266b-1525855450923)]

如圖中所示:必須為一個(gè)呈現(xiàn)命令編碼器設(shè)置呈現(xiàn)相關(guān)的狀態(tài)、設(shè)置和創(chuàng)建相關(guān)的呈現(xiàn)用到的緩沖區(qū)、紋理等Metal資源對(duì)象。

為呈現(xiàn)命令編碼器指定的狀態(tài)包括一個(gè)呈現(xiàn)管道流水線狀態(tài)(Render Pipeline State),一個(gè)深度和圖案狀態(tài)(Depth Stencil State),一個(gè)采樣狀態(tài)(Sampler State)。

一個(gè)Blit命令編碼器與一個(gè)緩沖區(qū)和一個(gè)紋理關(guān)聯(lián),用來(lái)在兩者之間進(jìn)行Blit操作。

命令編碼器指定圖形或計(jì)算功能時(shí)可以分配三種類型的MTLResource Metal資源對(duì)象使用:

MTLBuffer 表現(xiàn)一個(gè)能夠包含任意類型數(shù)據(jù)的無(wú)格式內(nèi)存。MTLBuffer通常用于多邊形頂點(diǎn)vertex、著色器shader及計(jì)算狀態(tài)數(shù)據(jù)。

MTLTexture表現(xiàn)一個(gè)有著特定紋理類型和點(diǎn)格式的具有相應(yīng)格式的圖像數(shù)據(jù)。紋理對(duì)象可以作為多邊形頂點(diǎn)vertex、片段fragment或計(jì)算功能的一個(gè)源,也可以在呈現(xiàn)描述符中作為圖形呈現(xiàn)的輸出目標(biāo)。

MTLSamplerState對(duì)象當(dāng)一個(gè)圖形或計(jì)算功能在一個(gè)MTLTexture上執(zhí)行紋理采樣操作時(shí)使用,用來(lái)定義地址、過(guò)濾和其它屬性。

圖形呈現(xiàn)編碼器MTLRenderCommandEncoder 可以使用setVertex及setFragment 方法組作為其參數(shù)來(lái)為相應(yīng)的映射函數(shù)分配一個(gè)或多個(gè)資源。

5、CAMetalLayer 對(duì)象和CAMetalDrawable 協(xié)議

Core Animation定義了一個(gè)CAMetalLayer類和一個(gè)CAMetalDrawable 協(xié)議用來(lái)提供一個(gè)Metal內(nèi)容呈現(xiàn)的層后備視圖。CAMetalLayer對(duì)象包含有關(guān)要呈現(xiàn)內(nèi)容的位置、尺寸、可視屬性(背景顏色、邊界和陰影)及Metal呈現(xiàn)內(nèi)容使用到的資源等。CAMetalDrawable 協(xié)議是MTLDrawable 的擴(kuò)展,指定了可顯示資源對(duì)象要符合的MTLTexture協(xié)議,使可顯示資源對(duì)象可用作呈現(xiàn)命令的目標(biāo)。

為了實(shí)現(xiàn)Metal內(nèi)容在一個(gè)CAMetalLayer對(duì)象的呈現(xiàn),應(yīng)為每次呈現(xiàn)流程創(chuàng)建一個(gè)CAMetalDrawable對(duì)象,從中得到它包含的MTLTexture 對(duì)象,然后在呈現(xiàn)流水線描述MTLRenderPipelineDescriptor 的顏色附屬點(diǎn)屬性中使用,指定其為圖形呈現(xiàn)命令的目標(biāo)。

一個(gè)CAMetalLayer對(duì)象調(diào)用CAMetalLayer 對(duì)象的nextDrawable 方法來(lái)創(chuàng)建。

在創(chuàng)建一個(gè)可顯示資源作為圖形命令的目標(biāo)后,就可以調(diào)用如下步驟完成圖形的繪制。

1)、首先創(chuàng)建一個(gè)MTLCommandQueue 對(duì)象,然后使用它創(chuàng)建一個(gè)MTLCommandBuffer對(duì)象;

2)、創(chuàng)建一個(gè)MTLRenderPassDescriptor對(duì)象,為其規(guī)定用作圖形緩沖中的編碼呈現(xiàn)命令目標(biāo)的附屬點(diǎn)集合;然后使用這個(gè)MTLRenderPassDescriptor 對(duì)象創(chuàng)建一個(gè)MTLRenderCommandEncoder對(duì)象;

3) 創(chuàng)建相應(yīng)的Metal資源對(duì)象,來(lái)存儲(chǔ)繪制用到資源數(shù)據(jù),如頂點(diǎn)坐標(biāo)和頂點(diǎn)顏色數(shù)據(jù);并調(diào)用MTLRenderCommandEncoder的setVertex:offset:atIndex: 和setFragment :offset:atIndex:方法來(lái)為呈現(xiàn)編碼器指定用到的資源;

4) 創(chuàng)建一個(gè)MTLRenderPipelineDescriptor 對(duì)象并為其指定vertexFunction和fragmentFunction 屬性,這些屬性使用Metal映射語(yǔ)言代碼中讀取的相應(yīng)映射函數(shù)MTLFunction對(duì)象來(lái)設(shè)置。

5)使用MTLDevice的newRenderPipelineStateWithDescriptor:error:方法或類似方法并根據(jù)MTLRenderPipelineDescriptor創(chuàng)建一個(gè)MTLRenderPipelineState對(duì)象;然后調(diào)用MTLRenderCommandEncoder 的setRenderPipelineState: 方法來(lái)為呈現(xiàn)編碼器對(duì)象MTLRenderCommandEncoder設(shè)置管道流水線;

6)調(diào)用MTLRenderCommandEncoder 的drawPrimitives:vertexStart:vertexCount: 方法來(lái)執(zhí)行圖形的呈現(xiàn),然后調(diào)用MTLRenderCommandEncoder的endEncoding 方法來(lái)結(jié)束本次呈現(xiàn)流程的編碼,最后調(diào)用MTLCommandBuffer 的commit方法來(lái)在GPU上執(zhí)行整個(gè)繪制命令。
來(lái)源:http://www.cocoachina.com/ios/20141104/10124.html

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,797評(píng)論 6 531
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,179評(píng)論 3 414
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人,你說(shuō)我怎么就攤上這事。” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 175,628評(píng)論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我,道長(zhǎng),這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 62,642評(píng)論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 71,444評(píng)論 6 405
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 54,948評(píng)論 1 321
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,040評(píng)論 3 440
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 42,185評(píng)論 0 287
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,717評(píng)論 1 333
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 40,602評(píng)論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 42,794評(píng)論 1 369
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,316評(píng)論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,045評(píng)論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 34,418評(píng)論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 35,671評(píng)論 1 281
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 51,414評(píng)論 3 390
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 47,750評(píng)論 2 370

推薦閱讀更多精彩內(nèi)容