這些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