版本記錄
版本號(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 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è)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 ES
與Core Animation
和UIKIT
集成的接口。
在調(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):GLKit
和CAEAGLLayer
。為了創(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)域:
-
GLKView
和GLKViewController
類(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),GLKReflectionMapEffect
在GLKBaseEffect
基礎(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
屬性。在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ì)象的屬性。-
繪制
OpenGL
內(nèi)容(發(fā)布繪制命令)
使用GLKit
視圖繪制OpenGL
內(nèi)容需要三個(gè)子步驟:- 準(zhǔn)備
OpenGL ES
基礎(chǔ); - 發(fā)布繪制命令;
- 呈現(xiàn)顯示內(nèi)容到
Core Animation
。
- 準(zhǔn)備
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è)方法update
和display
),用來(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)系是不同的,具體如下所示。
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
,GLKViewController
的view
為GLKView
類(lèi),GLKView
的delegate
定義了繪制回調(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
,與UIKit
中CGContextRef
相似,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ù)~~~