OpenGL ES 3.0 數(shù)據(jù)可視化 0:Hello world

本文檔的任務(wù)是介紹最簡單的OpenGL ES 3.0程序在iOS上的開發(fā)步驟窿冯,功能是打印一些OpenGL ES相關(guān)信息并設(shè)置屏幕顏色扼倘。不使用GLKit的原因是方便理解程度的實(shí)現(xiàn)邏輯并簡化代碼移植至Android平臺(tái)的難度,開發(fā)環(huán)境為Xcode 7赁还、運(yùn)行環(huán)境為iOS 9旨枯。編寫于2016年3月趟佃,修訂于10月且將原系列文檔合并入《OpenGL ES 3.0 數(shù)據(jù)可視化》系列文檔耸袜。代碼托管在GitHub: ES3_0_ClearColor友多。

歡迎加入GPUImage、OpenGL ES堤框、Vulkan域滥、Metal交流群536987698,一起學(xué)習(xí)胰锌。

1、打印OpenGL ES平臺(tái)相關(guān)實(shí)現(xiàn)信息

1藐窄、新建一個(gè)Single View Application工程资昧。
2、創(chuàng)建UIView的子類MyGLView荆忍。
3格带、引入OpenGL ES頭文件撤缴。

#import <OpenGLES/ES3/gl.h>

4、配置OpenGL ES上下文叽唱。OpenGL ES系統(tǒng)與本地窗口(UIKit)橋接由EGL上下文系統(tǒng)實(shí)現(xiàn)屈呕,iOS平臺(tái)的EGL具體實(shí)現(xiàn)稱為EAGL,可認(rèn)為是“Embedded Apple Graphics Library”棺亭。在UIView的初始化方法initWithFrame:中輸入如下代碼

EAGLContext *context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES3];
[EAGLContext setCurrentContext:context]; // 1

注釋// 1設(shè)置當(dāng)前上下文環(huán)境并告知EAGLContext虎眨,即該線程中的后續(xù)OpenGL ES調(diào)用將與該上下文環(huán)境綁定。若不綁定镶摘,則下面的GL調(diào)用都返回?zé)o效值嗽桩。

5、打印廠商信息凄敢。一般是查看當(dāng)前設(shè)備支持的OpenGL ES版本及拓展功能碌冶。OpenGL ES只是標(biāo)準(zhǔn)接口,每個(gè)平臺(tái)的具體實(shí)現(xiàn)細(xì)節(jié)各不相同涝缝,有些平臺(tái)提供了一些紋理的拓展方便開發(fā)或提高性能扑庞,如蘋果提供了PowerVR壓縮紋理。

printf("廠家 = %s\n", glGetString(GL_VENDOR));
printf("渲染器 = %s\n", glGetString(GL_RENDERER));
printf("ES版本 = %s\n", glGetString(GL_VERSION));
printf("拓展功能 =>\n%s\n", glGetString(GL_EXTENSIONS));

模擬器的運(yùn)行結(jié)果:

廠家 = Apple Inc.
渲染器 = Apple Software Renderer
ES版本 = OpenGL ES 3.0 APPLE-12.0.38
拓展功能 =>
GL_OES_standard_derivatives 
GL_EXT_color_buffer_half_float 
GL_EXT_debug_label 
GL_EXT_debug_marker 
GL_EXT_pvrtc_sRGB 
GL_EXT_read_format_bgra 
GL_EXT_separate_shader_objects
GL_EXT_shader_framebuffer_fetch 
GL_EXT_shader_texture_lod 
GL_EXT_shadow_samplers 
GL_EXT_texture_filter_anisotropic 
GL_APPLE_clip_distance 
GL_APPLE_color_buffer_packed_float
GL_APPLE_copy_texture_levels 
GL_APPLE_rgb_422 
GL_APPLE_texture_format_BGRA8888 
GL_IMG_read_format 
GL_IMG_texture_compression_pvrtc 

iPad Air 2的運(yùn)行結(jié)果:

廠家 = Apple Inc.
渲染器 = Apple A8X GPU
ES版本 = OpenGL ES 3.0 Apple A8X GPU - 77.14
拓展功能 =>
GL_OES_standard_derivatives
GL_KHR_texture_compression_astc_ldr
GL_EXT_color_buffer_half_float
GL_EXT_debug_label
GL_EXT_debug_marker
GL_EXT_pvrtc_sRGB
GL_EXT_read_format_bgra
GL_EXT_separate_shader_objects
GL_EXT_shader_framebuffer_fetch
GL_EXT_shader_texture_lod
GL_EXT_shadow_samplers
GL_EXT_texture_filter_anisotropic
GL_APPLE_clip_distance
GL_APPLE_color_buffer_packed_float
GL_APPLE_copy_texture_levels
GL_APPLE_rgb_422
GL_APPLE_texture_format_BGRA8888
GL_IMG_read_format
GL_IMG_texture_compression_pvrtc 

可見拒逮,模擬器與真機(jī)的拓展功能幾乎一致罐氨,真機(jī)只多了一項(xiàng)GL_KHR_texture_compression_astc_ldr。下面簡單介紹拓展的命名規(guī)則消恍,后續(xù)文檔再詳細(xì)描述它們的用途:

  • GL_EXT_開頭的拓展在其他平臺(tái)基本也是可用的岂昭,如Android,很可能在下一個(gè)GL版本成為新標(biāo)準(zhǔn)的核心功能狠怨。
  • GL_APPLE這類以廠家開頭(如APPLE)的拓展只能在其設(shè)備上使用约啊。
  • GL_OES特定于當(dāng)前平臺(tái)。
  • GL_IMG為圖像相關(guān)的拓展佣赖,比如支持更多紋理格式恰矩。

逐項(xiàng)獲取拓展名可使用glGetStringi,示例如下憎蛤。

int max = 0;
glGetIntegerv(GL_NUM_EXTENSIONS, &max);
NSMutableSet *extensions = [NSMutableSet set];
for (int i = 0; i < max; i++) {
    [extensions addObject: @( (char *)glGetStringi(GL_EXTENSIONS, i) )];
}
NSLog(@"%@", extensions);

現(xiàn)在外傅,讓我們實(shí)現(xiàn)一個(gè)設(shè)置屏幕顏色的功能。開始真正的繪制操作俩檬,需要配置圖層類萎胰、渲染緩沖區(qū)、幀緩沖區(qū)等棚辽。下面逐步詳細(xì)描述技竟。

2、設(shè)置屏幕顏色

6屈藐、修改MyGLView的+ (Class)layerClass方法榔组,使用CAEAGLLayer作為我們的圖層類熙尉。

+ (Class)layerClass {
    return [CAEAGLLayer class];
}

CAEAGLLayer是蘋果專門為OpenGL ES準(zhǔn)備的一個(gè)圖層類,它用于分配渲染緩沖區(qū)的存儲(chǔ)空間搓扯,相關(guān)文檔如下:

The CAEAGLLayer class supports drawing OpenGL content in iPhone applications. If you plan to use OpenGL for your rendering, use this class as the backing layer for your views by returning it from your view’s layerClass class method. The returned CAEAGLLayer object is a wrapper for a Core Animation surface that is fully compatible with OpenGL ES function calls.

Prior to designating the layer’s associated view as the render target for a graphics context, you can change the rendering attributes you want using the drawableProperties property. This property lets you configure the color format for the rendering surface and whether the surface retains its contents.

Because an OpenGL ES rendering surface is presented to the user using Core Animation, any effects and animations you apply to the layer affect the 3D content you render. However, for best performance, do the following:

  • Set the layer’s opaque attribute to TRUE.
  • Set the layer bounds to match the dimensions of the display.
  • Make sure the layer is not transformed.
  • Avoid drawing other layers on top of the CAEAGLLayer object. If you must draw other, non OpenGL content, you might find the performance cost acceptable if you place transparent 2D content on top of the GL content and also make sure that the OpenGL content is opaque and not transformed.
  • When drawing landscape content on a portrait display, you should rotate the content yourself rather than using the CAEAGLLayer transform to rotate it.

7检痰、配置渲染緩沖區(qū)(Render Buffer)

渲染緩沖區(qū)類似一個(gè)平面,用于保存繪制內(nèi)容锨推,并使用某種數(shù)據(jù)類型加以填充铅歼,比如顏色值。我們?cè)诖藙?chuàng)建的是顏色緩沖區(qū)爱态,用以保存所繪制的顏色信息谭贪,緩沖區(qū)大小由CAEAGLLayer的bounds中size指定,這在處理屏幕旋轉(zhuǎn)時(shí)是個(gè)非常重要的條件锦担。通常俭识,屏幕發(fā)生旋轉(zhuǎn)時(shí),屏幕的寬高值互換洞渔,故需要重新創(chuàng)建幀緩沖區(qū)等內(nèi)容套媚,后續(xù)文檔將詳細(xì)討論此問題。OpenGL ES有Frame buffer磁椒、Render buffer堤瘤、Data buffer等類型的緩沖區(qū),它們的作用各不相同浆熔。不過本辐,它們的創(chuàng)建與綁定等操作流程是類似的,后續(xù)文檔再作詳細(xì)介紹医增。

GLuint renderbuffer;
glGenRenderbuffers(1, &renderbuffer);
glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer);
[context renderbufferStorage:GL_RENDERBUFFER fromDrawable:(CAEAGLLayer *)self.layer];

在綁定好渲染緩沖區(qū)后慎皱,通知EAGLContext讓CAEAGLLayer實(shí)例中分配存儲(chǔ)空間,用以保存后續(xù)繪制的內(nèi)容叶骨。對(duì)于離屏表面茫多,用戶應(yīng)使用glRenderbufferStorage()進(jìn)行存儲(chǔ)空間的分配操作,這是高級(jí)話題忽刽,后續(xù)文檔再介紹天揖。

8、配置幀緩沖區(qū)(Frame Buffer)

幀緩沖區(qū)由多個(gè)render buffer組成跪帝,在此只綁定一個(gè)渲染緩沖區(qū)今膊,即是把顏色緩沖區(qū)附著到幀緩沖區(qū)中。幀緩沖區(qū)與渲染緩沖區(qū)的關(guān)系如下圖所示伞剑。

幀緩沖區(qū)對(duì)象的內(nèi)容
GLuint framebuffer;
glGenFramebuffers(1, &framebuffer);
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, renderbuffer);

幀緩沖區(qū)的創(chuàng)建斑唬、綁定操作類似渲染緩沖區(qū),第三步略有區(qū)別:將渲染緩沖區(qū)配置成幀緩沖區(qū)的顏色附著(Attachment)。在此可理解成將顏色數(shù)據(jù)放入幀緩沖區(qū)這個(gè)書柜里指定的位置讓別人看赖钞。

9、配置緩沖區(qū)清除顏色

glClearColor(1.0, 0, 1.0, 1.0);設(shè)置顏色緩沖區(qū)渲染聘裁。

10雪营、設(shè)置屏幕顏色(清除渲染緩沖區(qū))

glClear(GL_COLOR_BUFFER_BIT);讓OpenGL ES系統(tǒng)使用前面glClearColor指定的顏色刷一遍指定的緩沖區(qū),這里是顏色緩沖區(qū)衡便。而顏色緩沖區(qū)的內(nèi)容保存在渲染緩沖區(qū)中献起,且最后呈現(xiàn)給用戶的是渲染緩沖區(qū),因此镣陕,這里就是設(shè)置屏幕顏色的具體實(shí)現(xiàn)了谴餐。

11、交換前后端幀緩沖區(qū)

iOS系統(tǒng)維護(hù)著兩個(gè)重要的幀緩沖區(qū)呆抑,當(dāng)前屏幕使用的是前端幀緩沖區(qū)岂嗓。然而,剛才我們的操作都在后端幀緩沖區(qū)執(zhí)行鹊碍,若直接寫在前端幀緩沖區(qū)厌殉,那么沒完成的繪制也會(huì)顯示在屏幕上,而屏幕是逐行掃描刷新的侈咕,顯然這個(gè)行為會(huì)給用戶造成錯(cuò)覺公罕,比如逐行繪制圖片。所以耀销,在后端幀緩沖區(qū)操作完成后楼眷,我們需要通知系統(tǒng),讓其交換前后端幀緩沖區(qū)熊尉,用戶才能看到前面的操作罐柳。所以,這是最后一步操作:[context presentRenderbuffer:GL_RENDERBUFFER];帽揪,現(xiàn)在你應(yīng)該能看到紫色的屏幕硝清。

iPhone 7運(yùn)行截圖

12、清理操作

在結(jié)束OpenGL ES操作后转晰,應(yīng)該在dealloc或適當(dāng)?shù)牡胤阶銮謇聿僮髀茫唇Y(jié)束當(dāng)前上下文的使用,具體表現(xiàn)為:

if ([EAGLContext currentContext] == yourCurrentContext) {
    [EAGLContext setCurrentContext: nil];
}

當(dāng)然查邢,在本文這么簡單的使用場合中不解除也能正常運(yùn)行蔗崎,因?yàn)閕OS幫我們做了這個(gè)處理。然而扰藕,之后隨著我們的應(yīng)用越來越復(fù)雜時(shí)缓苛,需要自行處理進(jìn)入前后臺(tái)情況下的EGL上下文的保存情況。

3、總結(jié)

從上述內(nèi)容可知未桥,在iOS上通過繼承UIView進(jìn)行OpenGL ES 3.0開發(fā)的最簡單步驟為:

  1. 若繼承UIView子類笔刹,則需覆蓋+layerClass
  2. 配置EAGLContext。若使用GLKViewController冬耿,應(yīng)配置GLKView的context屬性為新生成的Context舌菜。
  3. 配置渲染緩沖區(qū)Render Buffer
  4. 創(chuàng)建幀緩沖區(qū)Frame Buffer并配置渲染、深度等緩沖區(qū)
  5. 設(shè)置視口glViewport
  6. 清空緩沖區(qū)glClear(指定緩沖區(qū))
  7. 繪制操作
  8. 通知EAGLContext將渲染緩沖區(qū)內(nèi)容發(fā)送至屏幕

其中亦镶,步驟5日月、7在本文檔沒使用,因?yàn)槟J(rèn)情況缤骨,我們使用了全屏顯示且沒繪制幾何圖元爱咬,比如點(diǎn)、直線和三角形绊起。

下一篇文檔:OpenGL ES 3.0 數(shù)據(jù)可視化 1:繪制圓點(diǎn)精拟。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市虱歪,隨后出現(xiàn)的幾起案子串前,更是在濱河造成了極大的恐慌,老刑警劉巖实蔽,帶你破解...
    沈念sama閱讀 218,941評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件荡碾,死亡現(xiàn)場離奇詭異,居然都是意外死亡局装,警方通過查閱死者的電腦和手機(jī)坛吁,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,397評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來铐尚,“玉大人拨脉,你說我怎么就攤上這事⌒觯” “怎么了玫膀?”我有些...
    開封第一講書人閱讀 165,345評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長爹脾。 經(jīng)常有香客問我帖旨,道長,這世上最難降的妖魔是什么灵妨? 我笑而不...
    開封第一講書人閱讀 58,851評(píng)論 1 295
  • 正文 為了忘掉前任解阅,我火速辦了婚禮,結(jié)果婚禮上泌霍,老公的妹妹穿的比我還像新娘货抄。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,868評(píng)論 6 392
  • 文/花漫 我一把揭開白布蟹地。 她就那樣靜靜地躺著积暖,像睡著了一般。 火紅的嫁衣襯著肌膚如雪怪与。 梳的紋絲不亂的頭發(fā)上呀酸,一...
    開封第一講書人閱讀 51,688評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音琼梆,去河邊找鬼。 笑死窿吩,一個(gè)胖子當(dāng)著我的面吹牛茎杂,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播纫雁,決...
    沈念sama閱讀 40,414評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼煌往,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼!你這毒婦竟也來了轧邪?” 一聲冷哼從身側(cè)響起刽脖,我...
    開封第一講書人閱讀 39,319評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎忌愚,沒想到半個(gè)月后曲管,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,775評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡硕糊,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,945評(píng)論 3 336
  • 正文 我和宋清朗相戀三年院水,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片简十。...
    茶點(diǎn)故事閱讀 40,096評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡檬某,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出螟蝙,到底是詐尸還是另有隱情恢恼,我是刑警寧澤,帶...
    沈念sama閱讀 35,789評(píng)論 5 346
  • 正文 年R本政府宣布胰默,位于F島的核電站场斑,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏牵署。R本人自食惡果不足惜和簸,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,437評(píng)論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望碟刺。 院中可真熱鬧锁保,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,993評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至浩村,卻和暖如春做葵,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背心墅。 一陣腳步聲響...
    開封第一講書人閱讀 33,107評(píng)論 1 271
  • 我被黑心中介騙來泰國打工酿矢, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人怎燥。 一個(gè)月前我還...
    沈念sama閱讀 48,308評(píng)論 3 372
  • 正文 我出身青樓瘫筐,卻偏偏與公主長得像,于是被迫代替她去往敵國和親铐姚。 傳聞我的和親對(duì)象是個(gè)殘疾皇子策肝,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,037評(píng)論 2 355

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