版本記錄
版本號(hào) | 時(shí)間 |
---|---|
V1.0 | 2017.09.28 |
前言
OpenGL ES是一個(gè)強(qiáng)大的圖形庫(kù),是跨平臺(tái)的圖形API,屬于OpenGL的一個(gè)簡(jiǎn)化版本。iOS系統(tǒng)可以利用OpenGL ES將圖像數(shù)據(jù)直接送入到GPU進(jìn)行渲染,這樣避免了從CPU進(jìn)行計(jì)算再送到顯卡渲染帶來(lái)的性能的高消耗,能帶來(lái)來(lái)更好的視頻效果和用戶體驗(yàn)。接下來(lái)幾篇就介紹下iOS 系統(tǒng)的 OpenGL ES框架。感興趣的可以看上面幾篇。
1. OpenGL ES 框架詳細(xì)解析(一) —— 基本概覽
2. OpenGL ES 框架詳細(xì)解析(二) —— 關(guān)于OpenGL ES
3. OpenGL ES 框架詳細(xì)解析(三) —— 構(gòu)建用于iOS的OpenGL ES應(yīng)用程序的清單
配置OpenGL ES的上下文
OpenGL ES的每個(gè)實(shí)現(xiàn)都提供了一種創(chuàng)建渲染上下文來(lái)管理OpenGL ES規(guī)范所需的狀態(tài)的方法。 通過(guò)將這種狀態(tài)置于上下文中,多個(gè)應(yīng)用程序可以輕松共享圖形硬件,而不會(huì)干擾對(duì)方的狀態(tài)。
下面詳細(xì)介紹如何在iOS上創(chuàng)建和配置上下文。
EAGL Is the iOS Implementation of an OpenGL ES Rendering Context - EAGL是OpenGL ES渲染上下文的iOS實(shí)現(xiàn)
在您的應(yīng)用程序可以調(diào)用任何OpenGL ES函數(shù)之前,必須初始化一個(gè)EAGLContext
對(duì)象。 EAGLContext類還提供了用于將OpenGL ES內(nèi)容與Core Animation
集成的方法。
The Current Context Is the Target for OpenGL ES Function Calls - 當(dāng)前上下文是OpenGL ES函數(shù)調(diào)用的目標(biāo)
iOS應(yīng)用程序中的每個(gè)線程都具有當(dāng)前上下文; 當(dāng)您調(diào)用OpenGL ES函數(shù)時(shí),這是通過(guò)調(diào)用更改其狀態(tài)的上下文。
要設(shè)置線程的當(dāng)前上下文,請(qǐng)?jiān)谠摼€程上執(zhí)行時(shí)調(diào)用EAGLContext
類方法setCurrentContext:
。
[EAGLContext setCurrentContext: myContext];
調(diào)用EAGLContext
類方法currentContext
來(lái)檢索線程的當(dāng)前上下文。
注意:如果您的應(yīng)用程序主動(dòng)在同一線程上的兩個(gè)或多個(gè)上下文之間切換,請(qǐng)?jiān)趯⑿律舷挛脑O(shè)置為當(dāng)前上下文之前調(diào)用glFlush
函數(shù)。 這樣可以確保先前提交的命令及時(shí)傳遞給圖形硬件。
OpenGL ES對(duì)與當(dāng)前上下文相對(duì)應(yīng)的EAGLContext
對(duì)象有很強(qiáng)的引用。 (如果使用手動(dòng)引用計(jì)數(shù),OpenGL ES保留此對(duì)象。)當(dāng)調(diào)用setCurrentContext:
方法來(lái)更改當(dāng)前上下文時(shí),OpenGL ES不再引用上一個(gè)上下文。 (如果您使用手動(dòng)引用計(jì)數(shù),OpenGL ES會(huì)釋放EAGLContext對(duì)象。)為防止當(dāng)不在當(dāng)前上下文時(shí)EAGLContext對(duì)象被釋放,您的應(yīng)用程序必須保持強(qiáng)制引用(或保留)這些對(duì)象。
Every Context Targets a Specific Version of OpenGL ES - 每個(gè)上下文都針對(duì)特定版本的OpenGL ES
EAGLContext
對(duì)象只支持一個(gè)版本的OpenGL ES。 例如,為OpenGL ES 1.1
編寫(xiě)的代碼與OpenGL ES 2.0
或3.0
上下文不兼容。 使用核心OpenGL ES 2.0功能的代碼與OpenGL ES 3.0上下文兼容,為OpenGL ES 2.0擴(kuò)展設(shè)計(jì)的代碼通常可以在OpenGL ES 3.0上下文中進(jìn)行微小更改。 許多新的OpenGL ES 3.0功能和增加的硬件功能需要OpenGL ES 3.0上下文。
您的應(yīng)用程序決定在創(chuàng)建和初始化EAGLContext對(duì)象時(shí)要支持的OpenGL ES版本。 如果設(shè)備不支持所需版本的OpenGL ES,initWithAPI:
方法返回nil。 您的應(yīng)用程序必須進(jìn)行測(cè)試,以確保在使用上下文之前初始化成功。
為了支持多種版本的OpenGL ES作為應(yīng)用程序中的渲染選項(xiàng),您應(yīng)該首先嘗試初始化要定位的最新版本的渲染上下文。 如果返回的對(duì)象為nil,則會(huì)初始化舊版本的上下文。 下面代碼演示了如何做到這一點(diǎn)。
//Supporting multiple versions of OpenGL ES in the same app
EAGLContext* CreateBestEAGLContext()
{
EAGLContext *context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES3];
if (context == nil) {
context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];
}
return context;
}
上下文的API屬性指出上下文支持的OpenGL ES版本。 您的應(yīng)用程序應(yīng)測(cè)試上下文的API屬性,并使用它來(lái)選擇正確的渲染路徑。 實(shí)現(xiàn)此行為的常見(jiàn)模式是為每個(gè)渲染路徑創(chuàng)建一個(gè)類。 您的應(yīng)用程序在初始化時(shí)測(cè)試上下文并創(chuàng)建一次渲染器。
An EAGL Sharegroup Manages OpenGL ES Objects for the Context - EAGL Sharegroup 管理上下文的OpenGL ES對(duì)象
雖然上下文保持OpenGL ES狀態(tài),但它并不直接管理OpenGL ES對(duì)象。 相反,OpenGL ES對(duì)象由EAGLSharegroup
對(duì)象創(chuàng)建和維護(hù)。 每個(gè)上下文都包含一個(gè)EAGLSharegroup對(duì)象。
當(dāng)兩個(gè)或多個(gè)上下文引用相同的共享組時(shí),共享組的優(yōu)點(diǎn)變得明顯,如下圖所示。 當(dāng)多個(gè)上下文連接到公共共享組時(shí),任何上下文創(chuàng)建的OpenGL ES對(duì)象都可用于所有上下文; 如果綁定到另一個(gè)上下文上與創(chuàng)建它相同的對(duì)象標(biāo)識(shí)符,則引用同一個(gè)OpenGL ES對(duì)象。 移動(dòng)設(shè)備上的資源通常很少; 在多個(gè)上下文中創(chuàng)建相同內(nèi)容的多個(gè)副本是浪費(fèi)的。 共享共享資源可以更好地利用設(shè)備上可用的圖形資源。
一個(gè)共享組是一個(gè)不透明的對(duì)象; 它沒(méi)有您的應(yīng)用可以調(diào)用的方法或?qū)傩浴?使用sharegroup對(duì)象的上下文保持強(qiáng)有力的引用。
在兩種具體情況下,sharegroups最有用:
- 當(dāng)上下文之間共享的大部分資源是不變的。
- 當(dāng)您希望您的應(yīng)用程序能夠在除渲染器的主線程之外的線程上創(chuàng)建新的OpenGL ES對(duì)象。 在這種情況下,第二個(gè)上下文在單獨(dú)的線程上運(yùn)行,專門(mén)用于獲取數(shù)據(jù)和創(chuàng)建資源。 在資源被加載之后,第一個(gè)上下文可以綁定到對(duì)象并立即使用它。
GLKTextureLoader
類使用此模式提供異步紋理加載。
要?jiǎng)?chuàng)建引用同一個(gè)sharegroup
的多個(gè)上下文,首先通過(guò)調(diào)用initWithAPI:
將為上下文自動(dòng)創(chuàng)建一個(gè)共享組。 通過(guò)調(diào)用initWithAPI:sharegroup:
方法,將第二個(gè)和更晚的上下文初始化為使用第一個(gè)上下文的共享組。 下面的代碼顯示了如何工作。 第一個(gè)上下文使用上面代碼中定義的方便函數(shù)創(chuàng)建。 第二個(gè)上下文通過(guò)從第一個(gè)上下文中提取API版本和共享組來(lái)創(chuàng)建。
重要提示:與同一共享組相關(guān)聯(lián)的所有上下文都必須使用與初始上下文相同的OpenGL ES API
版本。
// Creating two contexts with a common sharegroup
EAGLContext* firstContext = CreateBestEAGLContext();
EAGLContext* secondContext = [[EAGLContext alloc] initWithAPI:[firstContext API] sharegroup: [firstContext sharegroup]];
當(dāng)共享組由多個(gè)上下文共享時(shí),應(yīng)用程序有責(zé)任管理OpenGL ES對(duì)象的狀態(tài)更改。 這是規(guī)則:
- 如果對(duì)象未被修改,您的應(yīng)用程序可以同時(shí)訪問(wèn)多個(gè)上下文中的對(duì)象。
- 當(dāng)通過(guò)發(fā)送到上下文的命令修改對(duì)象時(shí),不得在任何其他上下文中讀取或修改該對(duì)象。
- 修改對(duì)象后,所有上下文都必須重新綁定對(duì)象以查看更改。 如果上下文在綁定之前引用它,則該對(duì)象的內(nèi)容是未定義的。
以下是應(yīng)用程序應(yīng)該更新OpenGL ES對(duì)象的步驟:
- 在可能使用對(duì)象的每個(gè)上下文上調(diào)用
glFlush
。 - 在要修改對(duì)象的上下文中,調(diào)用一個(gè)或多個(gè)OpenGL ES函數(shù)來(lái)更改對(duì)象。
- 在接收到狀態(tài)修改命令的上下文中調(diào)用glFlush。
- 在其他上下文中,重新綁定對(duì)象標(biāo)識(shí)符。
注意:共享對(duì)象的另一種方法是使用單個(gè)渲染上下文,但是使用多個(gè)目標(biāo)幀緩沖區(qū)。 在渲染時(shí),您的應(yīng)用程序會(huì)綁定相應(yīng)的幀緩沖區(qū),并根據(jù)需要呈現(xiàn)其幀。 因?yàn)樗蠴penGL ES對(duì)象都是從單個(gè)上下文引用的,所以它們會(huì)看到相同的OpenGL ES數(shù)據(jù)。 此模式使用的資源較少,但僅適用于可以仔細(xì)控制上下文狀態(tài)的單線程應(yīng)用程序。
后記
未完,待續(xù)~~~