OpenGL 圖形庫(kù)使用(一) —— 概念基礎(chǔ)

版本記錄

版本號(hào) 時(shí)間
V1.0 2017.07.22

前言

OpenGL 圖形庫(kù)項(xiàng)目中一直也沒(méi)用過(guò),最近也想學(xué)著使用這個(gè)圖形庫(kù),感覺(jué)還是很有意思,也就自然想著好好的總結(jié)一下。首先要給大家介紹個(gè)學(xué)習(xí)網(wǎng)站。
1. 歡迎來(lái)到OpenGL的世界
2.系列教程
3.教程代碼
4.落影簡(jiǎn)書(shū)

OpenGL ES基礎(chǔ)

OpenGL

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

OpenGL ES規(guī)范本身不定義繪制表面和繪制窗口,因此ios為了使用它必須提供和創(chuàng)建一個(gè)OpenGL ES的呈現(xiàn)環(huán)境,創(chuàng)建和配置存儲(chǔ)繪制命令結(jié)果的framebuffer 及創(chuàng)建和配置一個(gè)或多個(gè)呈現(xiàn)目標(biāo)。在 iOS中使用EAGL提供的EAGLContext類(lèi) 來(lái)實(shí)現(xiàn)和提供一個(gè)呈現(xiàn)環(huán)境,用來(lái)保持OpenGLES使用到的硬件狀態(tài)。 EAGL是一個(gè)Objective-C API,提供使OpenGL ESCore AnimationUIKIT集成的接口。

在調(diào)用任何OpenGL ES 功能之前必須首先初始化一個(gè)EAGLContext 對(duì)象。每一個(gè)iOS應(yīng)用的每一個(gè)線程都有一個(gè)當(dāng)前context,在調(diào)用OpenGLES函數(shù)時(shí),使用或改變此context中的狀態(tài)。EAGLContext的類(lèi)方法setCurrentContext:用來(lái)設(shè)置當(dāng)前線程的當(dāng)前context。EAGLContext 的類(lèi)方法currentContext返回當(dāng)前線程的當(dāng)前context。在切換相同線程的兩個(gè)上下文之前,必須調(diào)用glFlush函數(shù)來(lái)確保先前已提交的命令被提交到圖形硬件中。

可以采用不同的方式使用OpenGL ES以便呈現(xiàn)OpenGL ES內(nèi)容到不同的目標(biāo):GLKitCAEAGLLayer。為了創(chuàng)建全屏幕的視圖或使OpenGL ES
內(nèi)容與UIKit視圖集成,可以使用GLKit。在使用GLKit時(shí),GLKit提供的類(lèi)GLKView類(lèi)本身實(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 類(lèi),為使用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)域:

  • GLKViewGLKViewController類(lèi)提供一個(gè)標(biāo)準(zhǔn)的OpenGL ES視圖和相關(guān)聯(lián)的呈現(xiàn)循環(huán)。GLKView可以作為OpenGL ES內(nèi)容的呈現(xiàn)目標(biāo),GLKViewController提供內(nèi)容呈現(xiàn)的控制和動(dòng)畫(huà)。視圖管理和維護(hù)一個(gè)framebuffer,應(yīng)用只需在framebuffer進(jìn)行繪畫(huà)即可。
  • GLKTextureLoader 為應(yīng)用提供從iOS支持的各種圖像格式的源自動(dòng)加載紋理圖像到OpenGL ES 圖像環(huán)境的方式,并能夠進(jìn)行適當(dāng)?shù)霓D(zhuǎn)換,并支持同步和異步加載方式。
  • 數(shù)學(xué)運(yùn)算庫(kù),提供向量、矩陣、四元數(shù)的實(shí)現(xiàn)和矩陣堆棧操作等OpenGL ES 1.1功能。
  • Effect效果類(lèi)提供標(biāo)準(zhǔn)的公共著色效果的實(shí)現(xiàn)。能夠配置效果和相關(guān)的頂點(diǎn)數(shù)據(jù),然后創(chuàng)建和加載適當(dāng)?shù)闹鳌?code>GLKit 包括三個(gè)可配置著色效果類(lèi):GLKBaseEffect實(shí)現(xiàn)OpenGL ES 1.1規(guī)范中的關(guān)鍵的燈光和材料模式,GLKSkyboxEffect提供一個(gè)skybox效果的實(shí)現(xiàn),GLKReflectionMapEffectGLKBaseEffect基礎(chǔ)上包括反射映射支持。

GLKView和OpenGL ES繪制過(guò)程

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

  • 創(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屬性。在iOSGLKit的使用需要?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ì)象的屬性。

  • 繪制OpenGL內(nèi)容(發(fā)布繪制命令)
    使用GLKit視圖繪制OpenGL內(nèi)容需要三個(gè)子步驟:

    • 準(zhǔn)備OpenGL ES基礎(chǔ);
    • 發(fā)布繪制命令;
    • 呈現(xiàn)顯示內(nèi)容到Core Animation。

GLKit類(lèi)本身已經(jīng)實(shí)現(xiàn)了第一個(gè)和第三個(gè)步驟,用戶只需實(shí)現(xiàn)第二個(gè)步驟,在視圖的方法drawRect或視圖的代理對(duì)象的glkView:drawInRect:中調(diào)用適當(dāng)?shù)?code>OpenGL ES繪制命令進(jìn)行內(nèi)容繪制。GLKViewController類(lèi)維護(hù)一個(gè)animation呈現(xiàn)循環(huán)(包含兩個(gè)方法updatedisplay),用來(lái)實(shí)現(xiàn)連續(xù)的動(dòng)畫(huà)復(fù)雜的場(chǎng)景。animation 呈現(xiàn)循環(huán)的交替速率由GLKViewController的屬性framesPerSecond指示,并使用preferredFramesPerSecond 屬性來(lái)修改它。


OpenGL ES版本

iOS系統(tǒng)默認(rèn)支持OpenGl ES1.0、ES2.0以及ES3.0 3個(gè)版本,三者之間并不是簡(jiǎn)單的版本升級(jí),設(shè)計(jì)理念甚至完全不同,在開(kāi)發(fā)OpenGL項(xiàng)目前,需要根據(jù)業(yè)務(wù)需求選擇合適的版本。在學(xué)習(xí)OpenGL代碼的時(shí)候也需要知道它對(duì)應(yīng)著哪個(gè)版本,在ES1中執(zhí)行ES2代碼是看不到任何效果的,你可以在初始化EAGLContext時(shí)指定ES版本號(hào)。

指定版本方法如下所示。

EAGLContext *context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES1];


OpenGL ES坐標(biāo)系

OpenGL ES坐標(biāo)系和UI的坐標(biāo)系是不同的,具體如下所示。

OpenGL ES 坐標(biāo)系

UI是以左上角為原點(diǎn)的,而OpenGL ES 坐標(biāo)系是以屏幕中心為原點(diǎn)的。除了方向,還有一點(diǎn)需要注意,默認(rèn)情況各個(gè)方向坐標(biāo)值范圍為(-1,1),而不是UIKit中的(0,320)。當(dāng)繪制點(diǎn)(320,0)時(shí),它并不會(huì)出現(xiàn)在屏幕右上角。在ES1中,可以通過(guò)以下代碼將坐標(biāo)系轉(zhuǎn)化為熟悉的(320,480)。下面我們看代碼。

- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect 
{
    glViewport(0, 0, rect.size.width * 2, rect.size.height * 2);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glOrthof(0, 320, 0, 480, -1024, 1024);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
}


幾個(gè)重要的類(lèi)

下面介紹幾個(gè)重要的類(lèi)。

1. GLKViewController & GLKView

為了方便大家更快的開(kāi)發(fā),系統(tǒng)為OpenGL提供了簡(jiǎn)單的封裝,繼承GLKViewController定義自己的ViewController,GLKViewControllerviewGLKView類(lèi),GLKViewdelegate定義了繪制回調(diào)函數(shù)。

- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect

GLKViewController定義數(shù)據(jù)刷新函數(shù),當(dāng)子類(lèi)實(shí)現(xiàn)-(void)update方法,glkViewControllerUpdate方法將不再被調(diào)用。

- (void)glkViewControllerUpdate:(GLKViewController *)controller

需要補(bǔ)充一點(diǎn),默認(rèn)情況下,GLKViewController渲染RunLoop并非NSRunLoopCommonModes,而是NSDefaultRunLoopMode,因此在UIKit中使用GLKViewController,當(dāng)滑動(dòng)界面時(shí),OpenGL是不會(huì)渲染的。

2. EAGLContext

在介紹選擇版本時(shí)已經(jīng)提到EAGLContext,與UIKitCGContextRef相似,EAGLContext相當(dāng)于OpenGL繪制句柄或者上下文,在繪制試圖之前,需要指定使用創(chuàng)建的上下文繪制。

[EAGLContext setCurrentContext:view.context];

當(dāng)一個(gè)APP可能存在多個(gè)EAGLContext時(shí),需要處理并存沖突等問(wèn)題,比如大家所熟知的GPUImage,都會(huì)使用到EAGLContext。因此,在使用中要記得及時(shí)釋放。有興趣的朋友可以看看這篇文章。
這里還需要記住的是:當(dāng)App退到后臺(tái)時(shí), 切記暫停OpenGL繪制,否則可能導(dǎo)致crash

后記

這篇主要是基本的介紹和幾個(gè)基礎(chǔ)概念,后面還會(huì)繼續(xù)給大家擴(kuò)展,畢竟基礎(chǔ)的部分是固定的。未完,待續(xù)~~~

湖泊
最后編輯于
?著作權(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ù)。

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