在线观看不卡亚洲电影_亚洲妓女99综合网_91青青青亚洲娱乐在线观看_日韩无码高清综合久久

鍍金池/ 教程/ iOS/ Metal
與四軸無人機(jī)的通訊
在沙盒中編寫腳本
結(jié)構(gòu)體和值類型
深入理解 CocoaPods
UICollectionView + UIKit 力學(xué)
NSString 與 Unicode
代碼簽名探析
測試
架構(gòu)
第二期-并發(fā)編程
Metal
自定義控件
iOS 中的行為
行為驅(qū)動開發(fā)
Collection View 動畫
截圖測試
MVVM 介紹
使 Mac 應(yīng)用數(shù)據(jù)腳本化
一個完整的 Core Data 應(yīng)用
插件
字符串
為 iOS 建立 Travis CI
先進(jìn)的自動布局工具箱
動畫
為 iOS 7 重新設(shè)計 App
XPC
從 NSURLConnection 到 NSURLSession
Core Data 網(wǎng)絡(luò)應(yīng)用實例
GPU 加速下的圖像處理
自定義 Core Data 遷移
子類
與調(diào)試器共舞 - LLDB 的華爾茲
圖片格式
并發(fā)編程:API 及挑戰(zhàn)
IP,TCP 和 HTTP
動畫解釋
響應(yīng)式 Android 應(yīng)用
初識 TextKit
客戶端
View-Layer 協(xié)作
回到 Mac
Android
Core Image 介紹
自定義 Formatters
Scene Kit
調(diào)試
項目介紹
Swift 的強(qiáng)大之處
測試并發(fā)程序
Android 通知中心
調(diào)試:案例學(xué)習(xí)
從 UIKit 到 AppKit
iOS 7 : 隱藏技巧和變通之道
安全
底層并發(fā) API
消息傳遞機(jī)制
更輕量的 View Controllers
用 SQLite 和 FMDB 替代 Core Data
字符串解析
終身學(xué)習(xí)的一代人
視頻
Playground 快速原型制作
Omni 內(nèi)部
同步數(shù)據(jù)
設(shè)計優(yōu)雅的移動游戲
繪制像素到屏幕上
相機(jī)與照片
音頻 API 一覽
交互式動畫
常見的后臺實踐
糟糕的測試
避免濫用單例
數(shù)據(jù)模型和模型對象
Core Data
字符串本地化
View Controller 轉(zhuǎn)場
照片框架
響應(yīng)式視圖
Square Register 中的擴(kuò)張
DTrace
基礎(chǔ)集合類
視頻工具箱和硬件加速
字符串渲染
讓東西變得不那么糟
游戲中的多點(diǎn)互聯(lián)
iCloud 和 Core Data
Views
虛擬音域 - 聲音設(shè)計的藝術(shù)
導(dǎo)航應(yīng)用
線程安全類的設(shè)計
置換測試: Mock, Stub 和其他
Build 工具
KVC 和 KVO
Core Image 和視頻
Android Intents
在 iOS 上捕獲視頻
四軸無人機(jī)項目
Mach-O 可執(zhí)行文件
UI 測試
值對象
活動追蹤
依賴注入
Swift
項目管理
整潔的 Table View 代碼
Swift 方法的多面性
為什么今天安全仍然重要
Core Data 概述
Foundation
Swift 的函數(shù)式 API
iOS 7 的多任務(wù)
自定義 Collection View 布局
測試 View Controllers
訪談
收據(jù)驗證
數(shù)據(jù)同步
自定義 ViewController 容器轉(zhuǎn)場
游戲
調(diào)試核對清單
View Controller 容器
學(xué)無止境
XCTest 測試實戰(zhàn)
iOS 7
Layer 中自定義屬性的動畫
第一期-更輕量的 View Controllers
精通 iCloud 文檔存儲
代碼審查的藝術(shù):Dropbox 的故事
GPU 加速下的圖像視覺
Artsy
照片擴(kuò)展
理解 Scroll Views
使用 VIPER 構(gòu)建 iOS 應(yīng)用
Android 中的 SQLite 數(shù)據(jù)庫支持
Fetch 請求
導(dǎo)入大數(shù)據(jù)集
iOS 開發(fā)者的 Android 第一課
iOS 上的相機(jī)捕捉
語言標(biāo)簽
同步案例學(xué)習(xí)
依賴注入和注解,為什么 Java 比你想象的要好
編譯器
基于 OpenCV 的人臉識別
玩轉(zhuǎn)字符串
相機(jī)工作原理
Build 過程

Metal

Metal 框架支持 GPU 加速高級 3D 圖像渲染,以及數(shù)據(jù)并行計算工作。Metal 提供了先進(jìn)合理的 API,它不僅為圖形的組織、處理和呈現(xiàn),也為計算命令以及為這些命令相關(guān)的數(shù)據(jù)和資源的管理,提供了細(xì)粒度和底層的控制。Metal 的主要目的是最小化 GPU 工作時 CPU 所要的消耗。

Metal Programming Guide

Metal 是針對 iPhone 和 iPad 中 GPU 編程的高度優(yōu)化的框架。其名字來源是因為 Metal 是 iOS 平臺中最底層的圖形框架 (意指 "最接近硬件")。

該框架被設(shè)計用來實現(xiàn)兩個目標(biāo): 3D 圖形渲染和并行計算。這兩者有很多共同點(diǎn)。它們都在數(shù)量龐大的數(shù)據(jù)上并行運(yùn)行特殊的代碼,并可以在 GPU. 上執(zhí)行。

什么人應(yīng)該使用 Metal?

在談?wù)?API 和語言本身之前,我們應(yīng)該討論一下什么樣的開發(fā)者能從 Metal 中受益。正如上面提過的,Metal 提供兩個功能: 圖形渲染和并行計算。

對于尋找游戲引擎的開發(fā)者來說,Metal 不是最佳選擇。蘋果官方的的 Scene Kit (3D) 和 Sprite Kit (2D) 是更好的選擇。這些 API 提供了包括物理模擬在內(nèi)的更高級別的游戲引擎。另外還有功能更全面的 3D 引擎,例如 Epic 的 Unreal EngineUnity,二者都是跨平臺的。使用這些引擎,你無需直接使用 Metal 的 API,就可以從 Metal 中獲益。

編寫基于底層圖形 API 的渲染引擎時,除了 Metal 以外的其他選擇還有 OpenGL 和 OpenGL ES。OpenGL 不僅支持包括 OSX,Windows,Linux 和 Android 在內(nèi)的幾乎所有平臺,還有大量的教程,書籍和最佳實踐指南等資料。目前,Metal 的資源非常有限,并且僅限于搭載了 64 位處理器的 iPhone 和 iPad。但另外一方面,因為 OpenGL 的限制,其性能與 Metal 相比并不占優(yōu)勢,畢竟后者是專門用來解決這些問題的。

如果想要一個 iOS 上高性能的并行計算庫,答案非常簡單。Metal 是唯一的選擇。OpenCL 在 iOS 上是私有框架,而 Core Image (使用了 OpenCL) 對這樣的任務(wù)來說既不夠強(qiáng)大又不夠靈活。

使用 Metal 的好處

Metal 的最大好處就是與 OpenGL ES 相比顯著降低了消耗。在 OpenGL 中無論創(chuàng)建緩沖區(qū)還是紋理,OpenGL 都會復(fù)制一份以防止 GPU 在使用它們的時候被意外訪問。出于安全的原因復(fù)制類似紋理和緩沖區(qū)這樣的大的資源是非常耗時的操作。而 Metal 并不復(fù)制資源。開發(fā)者需要負(fù)責(zé)在 CPU 和 GPU 之間同步訪問。幸運(yùn)的是,蘋果提供了另一個很棒的 API 使資源同步訪問更加容易,那就是 Grand Central Dispatch。雖然使用 Metal 時仍然有些這方面的問題需要注意,但是一個在渲染時加載和卸載資源的先進(jìn)的引擎,在避免額外的復(fù)制后能夠獲得更多的好處。

Metal 的另外一個好處是其預(yù)估 GPU 狀態(tài)來避免多余的驗證和編譯。通常在 OpenGL 中,你需要依次設(shè)置 GPU 的狀態(tài),在每個繪制指令 (draw call) 之前需要驗證新的狀態(tài)。最壞的情況是 OpenGL 需要再次重新編譯著色器 (shader) 以反映新的狀態(tài)。當(dāng)然,這種評估是必要的,但 Metal 選擇了另一種方法。在渲染引擎初始化過程中,一組狀態(tài)被烘焙 (bake) 至預(yù)估渲染的 路徑 (pass) 中。多個不同資源可以共同使用該渲染路徑對象,但其它的狀態(tài)是恒定的。Metal 中一個渲染路徑無需更進(jìn)一步的驗證,使 API 的消耗降到最低,從而大大增加每幀的繪制指令的數(shù)量。

Metal API

雖然這個平臺上許多 API 都暴露為具體的類,但 Metal 提供的大多是協(xié)議。因為 Metal 對象的具體類型取決于 Metal 運(yùn)行在哪個設(shè)備上。這更鼓勵了面向接口而不是面向?qū)崿F(xiàn)編程。然而,這同時也意味著,如果不使用 Objective-C 運(yùn)行時的廣泛而危險的操作,就不能子類化 Metal 的類或者為其增加擴(kuò)展,

Metal 為了速度而在安全性上做了必要的妥協(xié)。對于錯誤,蘋果的其它框架顯得更加安全和健壯,而 Metal 則完全相反。在某些時候,你會收到指向內(nèi)部緩沖區(qū)的裸指針,你必須小心的同步訪問它。OpenGL 中發(fā)生錯誤時,結(jié)果通常是黑屏;然而在 Metal 中,結(jié)果可能是完全隨機(jī)的效果,例如閃屏和偶爾的崩潰。之所以有這些陷阱,是因為 Metal 框架是對 GPU 的非常輕量級抽象。

一個有趣的方面是蘋果并沒有為 Metal 實現(xiàn)可以在 iOS 模擬器上使用的軟件渲染。使用 Metal 框架的時候應(yīng)用必須運(yùn)行在真實設(shè)備上。

基礎(chǔ) Metal 程序

在這部分中,我們會介紹寫出第一個 Metal 程序所必要的部分。這個簡單的程序繪制了一個正方形的旋轉(zhuǎn)。你可以在 GitHub 中下載這篇文章的示例代碼。

雖然不能涵蓋每一個細(xì)節(jié),但我們盡量涉及至少所有的移動部分。你可以閱讀源代碼和參閱線上資源來深入理解。

使用 UIKit 創(chuàng)建設(shè)備和界面

在 Metal 中,設(shè)備是 GPU 的抽象。它被用來創(chuàng)建很多其它類型的對象,例如緩沖區(qū),紋理和函數(shù)庫。使用 MTLCreateSystemDefaultDevice 函數(shù)來獲取默認(rèn)設(shè)備:

id<MTLDevice> device = MTLCreateSystemDefaultDevice();

注意 device 并不是一個詳細(xì)具體的類,正如前面提到的,它是遵循 MTLDevice 協(xié)議的類。

下面的代碼展示了如何創(chuàng)建一個 Metal layer 并將它作為 sublayer 添加到一個 UIView 的 layer:

CAMetalLayer *metalLayer = [CAMetalLayer layer];
metalLayer.device = device;
metalLayer.pixelFormat = MTLPixelFormatBGRA8Unorm;
metalLayer.frame = view.bounds;
[view.layer addSublayer:self.metalLayer];

CAMetalLayerCALayer 的子類,它可以展示 Metal 幀緩沖區(qū)的內(nèi)容。我們必須告訴 layer 該使用哪個 Metal 設(shè)備 (我們剛創(chuàng)建的那個),并通知它所預(yù)期的像素格式。我們選擇 8-bit-per-channel BGRA 格式,即每個像素由藍(lán),綠,紅和透明組成,值從 0-255。

庫和函數(shù)

你的 Metal 程序的很多功能會被用頂點(diǎn)和片段函數(shù)的方式書寫,也就是我們所說的著色器。Metal 著色器用 Metal 著色器語言編寫,我們將在下面詳細(xì)討論。Metal 的優(yōu)點(diǎn)之一就是著色器函數(shù)在你的應(yīng)用構(gòu)建到中間語言時進(jìn)行編譯,這可以節(jié)省很多應(yīng)用啟動時所需的時間。

一個 Metal 庫是一組函數(shù)的集合。你的所有寫在工程內(nèi)的著色器函數(shù)都將被編譯到默認(rèn)庫中,這個庫可以通過設(shè)備獲得:

id<MTLLibrary> library = [device newDefaultLibrary]

接下來構(gòu)建渲染管道狀態(tài)的時候?qū)⑹褂眠@個庫。

命令隊列

命令通過與 Metal 設(shè)備相關(guān)聯(lián)的命令隊列提交給 Metal 設(shè)備。命令隊列以線程安全的方式接收命令并順序執(zhí)行。創(chuàng)建一個命令隊列:

id<MTLCommandQueue> commandQueue = [device newCommandQueue];

構(gòu)建管道

當(dāng)我們在 Metal 編程中提到管道,指的是頂點(diǎn)數(shù)據(jù)在渲染時經(jīng)歷的變化。頂點(diǎn)著色器和片段著色器是管道中兩個可編程的節(jié)點(diǎn),但還有其它一定會發(fā)生的事件 (剪切,柵格化和視圖變化) 不在我們的直接控制之下。管道特性中的后者的類組成了固定功能管道。

在 Metal 中創(chuàng)建一個管道,我們需要指定對于每個頂點(diǎn)和每個像素分別想要執(zhí)行哪個頂點(diǎn)和片段函數(shù) (譯者注: 片段著色器又被稱為像素著色器)。我們還需要將幀緩沖區(qū)的像素格式告訴管道。在本例中,該格式必須與 Metal layer 的格式匹配,因為我們想在屏幕上繪制。

從庫中通過名字來獲取函數(shù):

id<MTLFunction> vertexProgram = [library newFunctionWithName:@"vertex_function"];
id<MTLFunction> fragmentProgram = [library newFunctionWithName:@"fragment_function"];

接下來創(chuàng)建一個設(shè)置了函數(shù)和像素格式的管道描述器:

MTLRenderPipelineDescriptor *pipelineStateDescriptor = [[MTLRenderPipelineDescriptor alloc] init];
[pipelineStateDescriptor setVertexFunction:vertexProgram];
[pipelineStateDescriptor setFragmentFunction:fragmentProgram];
pipelineStateDescriptor.colorAttachments[0].pixelFormat = MTLPixelFormatBGRA8Unorm;        

最后,我們從描述器中創(chuàng)建管道狀態(tài)。這會根據(jù)程序運(yùn)行的硬件環(huán)境,從中間代碼中編譯著色器函數(shù)為優(yōu)化后的代碼。

id<MTLRenderPipelineState> pipelineState = [device newRenderPipelineStateWithDescriptor:pipelineStateDescriptor error:nil];

讀取數(shù)據(jù)到緩沖區(qū)

現(xiàn)在已經(jīng)有了一個構(gòu)建好的管道,我們需要用數(shù)據(jù)填充它。在示例工程中,我們繪制了一個簡單的幾何圖形: 一個旋轉(zhuǎn)的正方形。正方形由兩個共享一條邊的直角三角形組成:

static float quadVertexData[] =
{
     0.5, -0.5, 0.0, 1.0,     1.0, 0.0, 0.0, 1.0,
    -0.5, -0.5, 0.0, 1.0,     0.0, 1.0, 0.0, 1.0,
    -0.5,  0.5, 0.0, 1.0,     0.0, 0.0, 1.0, 1.0,

     0.5,  0.5, 0.0, 1.0,     1.0, 1.0, 0.0, 1.0,
     0.5, -0.5, 0.0, 1.0,     1.0, 0.0, 0.0, 1.0,
    -0.5,  0.5, 0.0, 1.0,     0.0, 0.0, 1.0, 1.0,
};  

每一行的前四個數(shù)字代表了每一個頂點(diǎn)的 x,y,z 和 w 元素。后四個數(shù)字代表每個頂點(diǎn)的紅色,綠色,藍(lán)色和透明值元素。

你可能會奇怪為什么需要四個數(shù)字來描述 3D 空間中的一個位置。第四個頂點(diǎn)位置元素,w,是一個數(shù)學(xué)上的便利,使我們能以一種統(tǒng)一的方式描述 3D 轉(zhuǎn)換 (旋轉(zhuǎn),平移,縮放)。這個細(xì)節(jié)在本文的示例代碼并沒有體現(xiàn)。

為了使用 Metal 繪制頂點(diǎn)數(shù)據(jù),我們需要將它放入緩沖區(qū)。緩沖區(qū)是被 CPU 和 GPU 共享的簡單的無結(jié)構(gòu)的內(nèi)存塊:

vertexBuffer = [device newBufferWithBytes:quadVertexData
                                       length:sizeof(quadVertexData)
                                      options:MTLResourceOptionCPUCacheModeDefault];

我們將使用另一個緩沖區(qū)來存儲用來旋轉(zhuǎn)正方形的旋轉(zhuǎn)矩陣。與預(yù)先提供數(shù)據(jù)不同,這里只是通過創(chuàng)建規(guī)定長度的緩沖區(qū)來創(chuàng)建一個空間。

uniformBuffer = [device newBufferWithLength:sizeof(Uniforms) 
                                        options:MTLResourceOptionCPUCacheModeDefault];

動畫

為了在屏幕上旋轉(zhuǎn)正方形,我們需要把轉(zhuǎn)換頂點(diǎn)作為頂點(diǎn)著色器的一部分。這需要更新每一幀的統(tǒng)一緩沖區(qū)。我們運(yùn)用三角學(xué)知識,從當(dāng)前旋轉(zhuǎn)角度生成一個旋轉(zhuǎn)矩陣,將它復(fù)制到統(tǒng)一緩沖區(qū)。

Uniforms 結(jié)構(gòu)體只有一個成員,該成員是一個保存了旋轉(zhuǎn)矩陣的 4x4 的矩陣。矩陣類型 matrix_float4x4 來自于蘋果的 SIMD 庫,該庫是一個類型的集合,它們可以從 數(shù)據(jù)并行操作 中獲益:

typedef struct
{
    matrix_float4x4 rotation_matrix;
} Uniforms;

為了將旋轉(zhuǎn)矩陣復(fù)制到統(tǒng)一緩沖區(qū)中,我們?nèi)〉盟膬?nèi)容的指針并將矩陣 memcpy 進(jìn)去:

Uniforms uniforms;
uniforms.rotation_matrix = rotation_matrix_2d(rotationAngle);
void *bufferPointer = [uniformBuffer contents];
memcpy(bufferPointer, &uniforms, sizeof(Uniforms));

準(zhǔn)備繪制

為了在 Metal layer 上繪制,首先我們需要從 layer 中獲得一個 'drawable' 對象。這個可繪制對象管理著一組適合渲染的紋理:

id<CAMetalDrawable> drawable = [metalLayer nextDrawable];

接下來我們創(chuàng)建一個渲染路徑描述器,它描述了在渲染之前和完成之后 Metal 應(yīng)該執(zhí)行的不同動作。下面我們展示了一個渲染路徑,它將首先把幀緩沖區(qū)清除為純白色,然后執(zhí)行繪制指令,最后將結(jié)果存儲到幀緩沖區(qū)來展示:

MTLRenderPassDescriptor *renderPassDescriptor = [MTLRenderPassDescriptor renderPassDescriptor];
renderPassDescriptor.colorAttachments[0].texture = drawable.texture;
renderPassDescriptor.colorAttachments[0].loadAction = MTLLoadActionClear;
renderPassDescriptor.colorAttachments[0].clearColor = MTLClearColorMake(1, 1, 1, 1);
renderPassDescriptor.colorAttachments[0].storeAction = MTLStoreActionStore;

發(fā)布繪制指令

要放入設(shè)備的命令隊列的命令必須被編碼到命令緩沖區(qū)里。命令緩沖區(qū)是一個或多個命令的集合,可以以一種 GPU 了解的緊湊的方式執(zhí)行和編碼。

id<MTLCommandBuffer> commandBuffer = [self.commandQueue commandBuffer];

為了真正編碼渲染命令,我們還需要另一個知道如何將我們的繪制指令轉(zhuǎn)換為 GPU 懂得的語言的對象。這個對象叫做命令編碼器。我們將上面創(chuàng)建的渲染路徑描述器作為參數(shù)傳入,就可以向命令緩沖區(qū)請求一個編碼器:

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

在繪制指令之前,我們使用預(yù)編譯的管道狀態(tài)設(shè)置渲染命令編碼器并建立緩沖區(qū),該緩沖區(qū)將作為頂點(diǎn)著色器的參數(shù):

[renderEncoder setRenderPipelineState:pipelineState];
[renderEncoder setVertexBuffer:vertexBuffer offset:0 atIndex:0];
[renderEncoder setVertexBuffer:uniformBuffer offset:0 atIndex:1];

為了真正的繪制幾何圖形,我們告訴 Metal 要繪制的形狀 (三角形) 和緩沖區(qū)中頂點(diǎn)的數(shù)量 (本例中 6 個):

[renderEncoder drawPrimitives:MTLPrimitiveTypeTriangle vertexStart:0 vertexCount:6];

最后,執(zhí)行 endEncoding 通知編碼器發(fā)布繪制指令完成。

[renderEncoder endEncoding];

展示幀緩沖區(qū)

現(xiàn)在我們的繪制指令已經(jīng)被編碼并準(zhǔn)備就緒,我們需要通知命令緩沖區(qū)應(yīng)該將結(jié)果在屏幕上顯示出來。調(diào)用 presentDrawable,使用當(dāng)前從 Metal layer 中獲得的 drawable 對象作為參數(shù):

[commandBuffer presentDrawable:drawable];

執(zhí)行 commit 告訴緩沖區(qū)已經(jīng)準(zhǔn)備好安排并執(zhí)行:

[commandBuffer commit];

就這么多!

Metal 著色語言

雖然 Metal 和 Swift 是在 WWDC keynote 上被一同發(fā)表的,但著色語言是基于 C++11 的,有一些有限制的特性和增加的關(guān)鍵字。

Metal 著色語言實踐

為了在著色器里使用頂點(diǎn)數(shù)據(jù),我們定義了一個對應(yīng) Objective-C 中頂點(diǎn)數(shù)據(jù)的結(jié)構(gòu)體:

typedef struct
{
    float4 position;
    float4 color;
} VertexIn;

我們還需要一個類似的結(jié)構(gòu)體來描述從頂點(diǎn)著色器傳入片段著色器的頂點(diǎn)類型。然而,在本例中,我們必須區(qū)分 (通過使用 [[position]] 屬性) 哪一個結(jié)構(gòu)體成員應(yīng)該被看做是頂點(diǎn)位置:

typedef struct {
 float4 position [[position]];
 float4 color;
} VertexOut;

頂點(diǎn)函數(shù)在頂點(diǎn)數(shù)據(jù)中每個頂點(diǎn)被執(zhí)行一次。它接收頂點(diǎn)列表的一個指針,和一個包含旋轉(zhuǎn)矩陣的統(tǒng)一數(shù)據(jù)的引用。第三個參數(shù)是一個索引,用來告訴函數(shù)當(dāng)前操作的是哪個頂點(diǎn)。

注意頂點(diǎn)函數(shù)的參數(shù)后面緊跟著標(biāo)明它們用途的屬性。在緩沖區(qū)參數(shù)中,參數(shù)中的索引對應(yīng)著我們在渲染命令編碼器中設(shè)置緩沖區(qū)時指定的索引。Metal 就是這樣來區(qū)分哪個參數(shù)對應(yīng)哪個緩沖區(qū)。

在頂點(diǎn)函數(shù)中,我們用頂點(diǎn)的位置乘以旋轉(zhuǎn)矩陣。我們構(gòu)建矩陣的方式?jīng)Q定了效果是圍繞中心旋轉(zhuǎn)正方形。接著我們將這個轉(zhuǎn)換過的位置傳入輸出頂點(diǎn)。頂點(diǎn)顏色則從輸入?yún)?shù)中直接復(fù)制。

vertex VertexOut vertex_function(device VertexIn *vertices [[buffer(0)]],
                                     constant Uniforms &uniforms [[buffer(1)]],
                                     uint vid [[vertex_id]])
{
    VertexOut out;
    out.position = uniforms.rotation_matrix * vertices[vid].position;
    out.color = vertices[vid].color;
    return out;
}

片段函數(shù)每個像素就會被執(zhí)行一次。Metal 在 rasterization 過程中會通過在每個頂點(diǎn)中指定的位置和顏色參數(shù)中添加來生成參數(shù)。在這個簡單的片段函數(shù)中,我們只是簡單的返回了 Metal 添加的顏色。這會成為屏幕像素的顏色:

fragment float4 fragment_function(VertexOut in [[stage_in]])
{
    return in.color;
}

為什么不干脆擴(kuò)展 OPENGL?

蘋果是 OpenGL 架構(gòu)審查委員會的成員,并且歷史上也在 iOS 上提供過它們自己的 GL 擴(kuò)展。但從內(nèi)部改變 OpenGL 看起來是個困難的任務(wù),因為它有著不同的設(shè)計目標(biāo)。實際上,它必須有廣泛的硬件兼容性以運(yùn)行在很多不同的設(shè)備上。雖然 OpenGL 還在持續(xù)發(fā)展,但速度緩慢。

而 Metal 則本來就是只為了蘋果的平臺而創(chuàng)建的。即使基于協(xié)議的 API 最初看起來不太常見,但和其它框架配合的很好。Metal 是用 Objective-C 編寫的,基于 Foundation,使用 GCD 在 CPU 和 GPU 之間保持同步。它是更先進(jìn)的 GPU 管道的抽象,而 OpenGL 想達(dá)到這些的話只能完全重寫。

Mac 上的 Metal?

OS X 上支持 Metal 也是遲早的事。API 本身并不局限于 iPhone 和 iPad 使用的 ARM 架構(gòu)的處理器。Metal 的大多數(shù)優(yōu)點(diǎn)都可以移植到先進(jìn)的 GPU 上。另外,iPhone 和 iPad 的 CPU 和 GPU 是共享內(nèi)存的,無需復(fù)制就可以交換數(shù)據(jù)。這一代的 Mac 電腦并未提供共享內(nèi)存,但這只是時間問題。或許,API 會被調(diào)整為支持使用了專門內(nèi)存的架構(gòu),或者 Metal 只會運(yùn)行在下一代的 Mac 電腦上。

總結(jié)

本文中我們嘗試給出公正并有所幫助的關(guān)于 Metal 框架的介紹。

當(dāng)然,大多數(shù)的游戲開發(fā)者并不會直接使用 Metal。然而,頂層的游戲引擎已經(jīng)從中獲益,并且開發(fā)者無需直接使用 API 就可以從最新的技術(shù)中得到好處。另外,對于那些想要發(fā)揮硬件全部性能的開發(fā)者來說,Metal 或許可以讓他們在游戲中創(chuàng)建出與眾不同而華麗的效果,或者進(jìn)行更快的并行計算,從而得到競爭優(yōu)勢。

資源

上一篇:Build 工具下一篇:初識 TextKit