iOS 視覺特效四 OpenGL繪制圖形案例

前言

在學(xué)習(xí)編程的時(shí)候我們總是通過編寫demo來加深印象产禾,本篇目的是介紹OpenGL中三角形的繪制,是一個(gè)入門級(jí)的圖形繪制,重點(diǎn)是理解圖形是如何繪制的编整。

環(huán)境配置

開發(fā)環(huán)境的配置是編寫代碼的前期準(zhǔn)備工作找御,詳細(xì)操作步驟可參考:Xcode搭建OpenGL環(huán)境

工具類

主要講述三個(gè)工具類

  • 著色器管理類

#include <GLShaderManager.h> 移入了GLTool 著色器管理器(shader Mananger)類元镀。沒有著色器绍填,我們就不能在OpenGL(核心框架)進(jìn)行著色。著色器管理器不僅允許我們創(chuàng)建并管理著色器栖疑,還提供一組“存儲(chǔ)著色器”讨永,他們能夠進(jìn)行一些初步?基本的渲染操作。

  1. 創(chuàng)建并管理著色器蔽挠;
  2. 提供一組存儲(chǔ)著色器住闯;
  3. 進(jìn)行基本的渲染操作;
  • GLTools函數(shù)

#include<GLTools.h> GLTool.h頭文件包含了大部分GLTool中類似C語言的獨(dú)立函數(shù)

  • GLUT靜態(tài)庫

在Mac 系統(tǒng)下澳淑,#include <GLUT/GLUT.h>
在Windows 和 Linux上比原,我們使用freeglut的靜態(tài)庫版本并且需要添加一個(gè)宏

方法函數(shù)

  • void changeSize(int w,int h)

changeSiz是用于改變窗口大小的自定義函數(shù),glViewport中有4個(gè)參數(shù)杠巡,分別是x, y, w, h量窘。其中x,y表示窗口中視圖的左下角坐標(biāo)氢拥,通常都是為0蚌铜。w,h表示窗口的寬和高嫩海,通常用像素位表示冬殃。代碼如下:

/*
 在窗口大小改變時(shí),接收新的寬度&高度叁怪。
 */
void changeSize(int w,int h) {
    /*
      x,y 參數(shù)代表窗口中視圖的左下角坐標(biāo)审葬,而寬度、高度是像素為表示奕谭,通常x,y 都是為0
     */
    glViewport(0, 0, w, h);
}

其觸發(fā)條件是:

  1. 新建窗口;
  2. 窗口尺寸發(fā)生調(diào)整;

為什么窗口大小發(fā)生調(diào)整會(huì)觸發(fā)這個(gè)函數(shù)方法呢涣觉?原因就是在main函數(shù)方法中我們會(huì)使用glutMainLoop,其原理相當(dāng)于iOS的runloop血柳,當(dāng)窗口大小改變時(shí)官册,實(shí)時(shí)調(diào)用此方法。需要在main中通過glutReshapeFunc(函數(shù)名) 注冊(cè)為重塑函數(shù)难捌,隨著窗口大小改變而改變膝宁,使用代碼如下:

 //注冊(cè)重塑函數(shù)
 glutReshapeFunc(changeSize);
  • void RenderScene(void)函數(shù)

RenderScene函數(shù)是將傳入的頂點(diǎn)數(shù)據(jù)、顏色等通過批次容器類提交到著色器中進(jìn)行繪制渲染根吁。需要在main函數(shù)中通過glutDisplayFunc(RenderScene(函數(shù)名)) 注冊(cè)為顯示函數(shù)昆汹。此方法是自定義渲染場(chǎng)景函數(shù),當(dāng)屏幕屏幕發(fā)生變化或者開發(fā)者駐主動(dòng)渲染會(huì)調(diào)用此函數(shù)婴栽,具體使用步驟:

  1. 清除一個(gè)或者一組特定的緩存區(qū)满粗;
  2. 設(shè)置一組浮點(diǎn)數(shù),傳遞到存儲(chǔ)著色器愚争;
  3. 繪制圖形

實(shí)現(xiàn)代碼如下:

/// 渲染場(chǎng)景
void RenderScene(void) {
    //1.清除一個(gè)或者一組特定的緩存區(qū)
    /*
     緩沖區(qū)是一塊存在圖像信息的儲(chǔ)存空間映皆,紅色挤聘、綠色、藍(lán)色和alpha分量通常一起分量通常一起作為顏色緩存區(qū)或像素緩存區(qū)引用捅彻。
     OpenGL 中不止一種緩沖區(qū)(顏色緩存區(qū)组去、深度緩存區(qū)和模板緩存區(qū))
      清除緩存區(qū)對(duì)數(shù)值進(jìn)行預(yù)置
     參數(shù):指定將要清除的緩存的
     GL_COLOR_BUFFER_BIT :指示當(dāng)前激活的用來進(jìn)行顏色寫入緩沖區(qū)
     GL_DEPTH_BUFFER_BIT :指示深度緩存區(qū)
     GL_STENCIL_BUFFER_BIT:指示模板緩沖區(qū)
     */
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
    //2.設(shè)置一組浮點(diǎn)數(shù)來表示白色
    GLfloat vRed[] = {1.0f,1.0f,1.0f,1.0f};
    //傳遞到存儲(chǔ)著色器,即GLT_SHADER_IDENTITY著色器步淹,這個(gè)著色器只是使用指定顏色以默認(rèn)笛卡爾坐標(biāo)第在屏幕上渲染幾何圖形
    //單元著色器
    shaderManager.UseStockShader(GLT_SHADER_IDENTITY,vRed);
    //提交著色器 (繪制)
    triangleBatch.Draw();
    //在開始的設(shè)置openGL 窗口的時(shí)候从隆,我們指定要一個(gè)雙緩沖區(qū)的渲染環(huán)境。這就意味著將在后臺(tái)緩沖區(qū)進(jìn)行渲染缭裆,渲染結(jié)束后交換給前臺(tái)键闺。這種方式可以防止觀察者看到可能伴隨著動(dòng)畫幀與動(dòng)畫幀之間的閃爍的渲染過程。緩沖區(qū)交換平臺(tái)將以平臺(tái)特定的方式進(jìn)行澈驼。
    //將后臺(tái)緩沖區(qū)進(jìn)行渲染辛燥,然后結(jié)束后交換給前臺(tái)
    glutSwapBuffers();
}
  • void setupRC()函數(shù)

setupRC()函數(shù)主要用于
1.設(shè)置圖形繪制所需的顏色、頂點(diǎn)數(shù)據(jù)等并且初始化一個(gè)渲染管理器:shaderManager缝其,將這些數(shù)據(jù)傳遞到著色管理器中挎塌。
2.系統(tǒng)監(jiān)聽到數(shù)據(jù)已經(jīng)配置完成,去自動(dòng)調(diào)用OpenGL的渲染回調(diào)函數(shù)
觸發(fā)條件:

  1. 手動(dòng)main函數(shù)出發(fā)

具體實(shí)現(xiàn)代碼如下:

///正方形四個(gè)頂點(diǎn)坐標(biāo)
GLfloat vVerts[] = {
    -blockSize,-blockSize,0.0f,
    blockSize,-blockSize,0.0f,
    blockSize,blockSize,0.0f,
    -blockSize,blockSize,0.0f
};

/// 設(shè)置
void setupRC()
{
    //設(shè)置清屏顏色(背景顏色)
    glClearColor(0.98f, 0.40f, 0.7f, 1);    
    //沒有著色器内边,在OpenGL 核心框架中是無法進(jìn)行任何渲染的榴都。初始化一個(gè)渲染管理器。
    //在前面的課程漠其,我們會(huì)采用固管線渲染嘴高,后面會(huì)學(xué)著用OpenGL著色語言來寫著色器
    shaderManager.InitializeStockShaders();
    //指定頂點(diǎn)
    //在OpenGL中,三角形是一種基本的3D圖元繪圖原素辉懒。
//    GLfloat vVerts[] = {
//        -0.5f,0.0f,0.0f,
//        0.5f,0.0f,0.0f,
//        0.0f,0.5f,0.0f
//    };
    //連接方式 九種連接方式  GL_TRIANGLE_FAN
    //GL_POINTS 每個(gè)頂點(diǎn)在屏幕上都是單獨(dú)點(diǎn)
    //GL_LINES 每?對(duì)頂點(diǎn)定義?個(gè)線段;
    //GL_LINE_STRIP ?個(gè)從第?個(gè)頂點(diǎn)依次經(jīng)過每?個(gè)后續(xù)頂點(diǎn)?繪制的線條
    //GL_LINE_LOOP 和GL_LINE_STRIP相同,但是最后?個(gè)頂點(diǎn)和第?個(gè)頂點(diǎn)連接起來了
    //GL_TRIANGLES 每3個(gè)頂點(diǎn)定義?個(gè)新的三?形
    //GL_TRIANGLE_STRIP 共??個(gè)條帶(strip)上的頂點(diǎn)的?組三?形
    //GL_TRIANGLE_FAN 以?個(gè)圓點(diǎn)為中?呈扇形排列,共?相鄰頂點(diǎn)的?組三?形
    triangleBatch.Begin(GL_TRIANGLE_FAN, 4);
    triangleBatch.CopyVertexData3f(vVerts);
    triangleBatch.End();
}
  • int main(int argc,char *argv[])函數(shù)

main函數(shù)是程序的入口阳惹,主要是做繪制前的準(zhǔn)備工作谍失,例如:初始化GLUT庫眶俩、初始化雙緩沖窗口,設(shè)置窗口大小和窗口標(biāo)題快鱼,設(shè)置數(shù)據(jù)颠印,啟動(dòng)glutMainLoop()類似iOS runloop的運(yùn)行循環(huán)。
實(shí)現(xiàn)的運(yùn)行流程圖如下所示:

main函數(shù)結(jié)構(gòu)流程圖解

main函數(shù)代碼如下所示:

int main(int argc,char *argv[]) {
    //初始化GLUT庫,這個(gè)函數(shù)只是傳說命令參數(shù)并且初始化glut庫
    glutInit(&argc, argv);
    /*
     初始化雙緩沖窗口抹竹,其中標(biāo)志GLUT_DOUBLE线罕、GLUT_RGBA、GLUT_DEPTH窃判、GLUT_STENCIL分別指
     雙緩沖窗口钞楼、RGBA顏色模式、深度測(cè)試袄琳、模板緩沖區(qū)
     --GLUT_DOUBLE`:雙緩存窗口询件,是指繪圖命令實(shí)際上是離屏緩存區(qū)執(zhí)行的燃乍,然后迅速轉(zhuǎn)換成窗口視圖,這種方式宛琅,經(jīng)常用來生成動(dòng)畫效果刻蟹;
     --GLUT_DEPTH`:標(biāo)志將一個(gè)深度緩存區(qū)分配為顯示的一部分,因此我們能夠執(zhí)行深度測(cè)試嘿辟;
     --GLUT_STENCIL`:確保我們也會(huì)有一個(gè)可用的模板緩存區(qū)舆瘪。
     深度、模板測(cè)試后面會(huì)細(xì)致講到
     */
glutInitDisplayMode(GLUT_DOUBLE|GLUT_RGBA|GLUT_DEPTH|GLUT_STENCIL);
    //GLUT窗口大小红伦、窗口標(biāo)題
    glutInitWindowSize(500, 500);
    glutCreateWindow("Square 標(biāo)題");
    /*
     GLUT 內(nèi)部運(yùn)行一個(gè)本地消息循環(huán)英古,攔截適當(dāng)?shù)南ⅰH缓笳{(diào)用我們不同時(shí)間注冊(cè)的回調(diào)函數(shù)色建。我們一共注冊(cè)2個(gè)回調(diào)函數(shù):
     1)為窗口改變大小而設(shè)置的一個(gè)回調(diào)函數(shù)
     2)包含OpenGL 渲染的回調(diào)函數(shù)
     */
    //注冊(cè)重塑函數(shù)
    glutReshapeFunc(changeSize);
    //注冊(cè)顯示函數(shù)
    glutDisplayFunc(RenderScene);
    //注冊(cè)特殊函數(shù) (鍵盤調(diào)用)
    glutSpecialFunc(SpecialKeys);
    /*
     初始化一個(gè)GLEW庫,確保OpenGL API對(duì)程序完全可用哺呜。
     在試圖做任何渲染之前,要檢查確定驅(qū)動(dòng)程序的初始化過程中沒有任何問題
     */
    GLenum status = glewInit();
    if (GLEW_OK != status) {
        printf("GLEW Error:%s\n",glewGetErrorString(status));
        return 1;
    }
    //設(shè)置我們的渲染環(huán)境
    setupRC();
    glutMainLoop();
    return  0;
}

繪制效果

圖形繪制后的展示效果如圖所示:


繪制效果
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末箕戳,一起剝皮案震驚了整個(gè)濱河市某残,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌陵吸,老刑警劉巖玻墅,帶你破解...
    沈念sama閱讀 219,490評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異壮虫,居然都是意外死亡澳厢,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,581評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門囚似,熙熙樓的掌柜王于貴愁眉苦臉地迎上來剩拢,“玉大人,你說我怎么就攤上這事饶唤⌒旆ィ” “怎么了?”我有些...
    開封第一講書人閱讀 165,830評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵募狂,是天一觀的道長(zhǎng)办素。 經(jīng)常有香客問我,道長(zhǎng)祸穷,這世上最難降的妖魔是什么性穿? 我笑而不...
    開封第一講書人閱讀 58,957評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮雷滚,結(jié)果婚禮上需曾,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好呆万,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,974評(píng)論 6 393
  • 文/花漫 我一把揭開白布刻蚯。 她就那樣靜靜地躺著,像睡著了一般桑嘶。 火紅的嫁衣襯著肌膚如雪炊汹。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,754評(píng)論 1 307
  • 那天逃顶,我揣著相機(jī)與錄音讨便,去河邊找鬼。 笑死以政,一個(gè)胖子當(dāng)著我的面吹牛霸褒,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播盈蛮,決...
    沈念sama閱讀 40,464評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼废菱,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了抖誉?” 一聲冷哼從身側(cè)響起殊轴,我...
    開封第一講書人閱讀 39,357評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎袒炉,沒想到半個(gè)月后旁理,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,847評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡我磁,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,995評(píng)論 3 338
  • 正文 我和宋清朗相戀三年孽文,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片夺艰。...
    茶點(diǎn)故事閱讀 40,137評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡芋哭,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出郁副,到底是詐尸還是另有隱情减牺,我是刑警寧澤,帶...
    沈念sama閱讀 35,819評(píng)論 5 346
  • 正文 年R本政府宣布霞势,位于F島的核電站烹植,受9級(jí)特大地震影響斑鸦,放射性物質(zhì)發(fā)生泄漏愕贡。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,482評(píng)論 3 331
  • 文/蒙蒙 一巷屿、第九天 我趴在偏房一處隱蔽的房頂上張望固以。 院中可真熱鬧,春花似錦、人聲如沸憨琳。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,023評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽篙螟。三九已至菌湃,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間遍略,已是汗流浹背惧所。 一陣腳步聲響...
    開封第一講書人閱讀 33,149評(píng)論 1 272
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留绪杏,地道東北人下愈。 一個(gè)月前我還...
    沈念sama閱讀 48,409評(píng)論 3 373
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像蕾久,于是被迫代替她去往敵國(guó)和親势似。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,086評(píng)論 2 355

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