OpenGLES學(xué)習(xí)之路-三維變換

學(xué)習(xí)之路系列

OpenGLES學(xué)習(xí)之路

今天我們實(shí)現(xiàn)一個(gè)三維空間中物體的變換操作

本篇主要內(nèi)容

三維坐標(biāo)變換

效果圖

實(shí)現(xiàn)過程

首先我們跟之前一樣給出以下頂點(diǎn)數(shù)據(jù)

//4個(gè)頂點(diǎn)(分別表示xyz軸)
static const float Vertices[] = {
    
    -0.5, -0.5, 0,  //左下
     0.5, -0.5, 0,  //右下
    -0.5,  0.5, 0,  //左上
     0.5,  0.5, 0,  //右上
};

//4個(gè)點(diǎn)的顏色(分別表示RGBA值)
static const float Colors[] = {
    
    1, 0, 0, 1,
    0, 1, 0, 1,
    0, 0, 1, 1,
    0, 0, 0, 1,
};

然后進(jìn)行渲染, 中間的渲染緩沖區(qū)拓巧、幀緩沖區(qū)、編譯著色器我們暫時(shí)先省略骗污,有不明白的小伙伴可以參考這篇文章

- (void)render:(CADisplayLink *)displayLink {
    
    //用指定的顏色清除,清除顏色被設(shè)置為(0.5f, 0.5f, 0.5f, 1.0f), 所以為黑色
    glClearColor(0.5f, 0.5f, 0.5f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT);
    
    //設(shè)定窗口的范圍(如果不是很明白, 可以自己動(dòng)手修改下試試)
    //他這個(gè)是左下角為(0,0) 右上角為(width,height)
    glViewport(0, 0, _width, _height);
    
    //指定了渲染時(shí)索引值為 index 的頂點(diǎn)屬性數(shù)組的數(shù)據(jù)格式和位置智听。
    /*
     *  indx:指定要修改的頂點(diǎn)屬性的索引值
     *  size:指定每個(gè)頂點(diǎn)屬性的組件數(shù)量。(必須坐標(biāo)xyz軸就是3, 顏色rgba就是4)
     *  type:指定數(shù)組中每個(gè)組件的數(shù)據(jù)類型。(一般為GL_FLOAT)
     *  normalized:一般為GL_FALSE
     *  stride:指定連續(xù)頂點(diǎn)屬性之間的偏移量。如果為0羡儿,那么頂點(diǎn)屬性會(huì)被理解為:它們是緊密排列在一起的。初始值為0是钥。
     *  ptr:指向數(shù)據(jù)的指針
     */
    glVertexAttribPointer(_positionSlot, 3, GL_FLOAT, GL_FALSE, 0, Vertices);
    glVertexAttribPointer(_colorSlot,    4, GL_FLOAT, GL_FALSE, 0, Colors);
    
    glDrawArrays(GL_TRIANGLE_STRIP, 0, sizeof(Vertices) / (sizeof(int) * 3));
    
    //把緩沖區(qū)的數(shù)據(jù)呈現(xiàn)到UIView上
    [_context presentRenderbuffer:GL_RENDERBUFFER];
}
渲染結(jié)果

我們接下來需要把他弄成正方形的失受,由于還沒有學(xué)習(xí)投影,我們先改動(dòng)渲染的窗口來達(dá)成這一目的
render:方法中的

glViewport(0, 0, _width, _height);

改成

glViewport(0, 0, _width, _width);
看下效果

這樣子就實(shí)現(xiàn)了正方形了

三維變換

給大家介紹一個(gè)網(wǎng)址LearnOpenGL, 上面對(duì)三維變換的講解很詳細(xì), 下面就來實(shí)現(xiàn)下這三種操作(縮放咏瑟、位移、旋轉(zhuǎn))


系統(tǒng)已經(jīng)提供了矩陣操作的框架痪署, 網(wǎng)上也有一些大神提供的矩陣操作的第三方庫码泞,我們可以直接拿到使用,不會(huì)矩陣的小伙伴也可以玩轉(zhuǎn)三維操作O(∩_∩)O狼犯。這里我們直接使用系統(tǒng)的

我們先修改下頂點(diǎn)著色器

attribute vec4 Position;

attribute vec4 InColor;
varying   vec4 OutColor;

uniform mat4 Model;     //new

void main(void){
    OutColor = InColor;
//    gl_Position = Position;
    gl_Position = Model * Position;
}

并在編譯著色器(compileShaders:)的地方獲取著色器中的ModelView變量

_modelView = glGetUniformLocation(_program, "ModelView");

下面的的代碼直接在

  • 縮放
GLKMatrix4 modelView = GLKMatrix4MakeScale(_transformScale[0],
                                           _transformScale[1],
                                           _transformScale[2]);
    
    //給著色器變量賦值
    /*
        location:   變量的位置
        count   :   要更改變量的個(gè)數(shù)
        transpose:  是否需要轉(zhuǎn)置
        value   :   給出對(duì)應(yīng)count個(gè)元素的指針
    */
    glUniformMatrix4fv(_modelView, 1, GL_FALSE, modelView.m);

GLKMatrix4MakeScale是系統(tǒng)初始化縮放矩陣的函數(shù)
看下效果:

  • 位移
GLKMatrix4 modelView = GLKMatrix4MakeTranslation(_transformTranslation[0],
                                                 _transformTranslation[1],
                                                 _transformTranslation[2]);
    
    //給著色器變量賦值
    /*
        location:   變量的位置
        count   :   要更改變量的個(gè)數(shù)
        transpose:  是否需要轉(zhuǎn)置
        value   :   給出對(duì)應(yīng)count個(gè)元素的指針
    */
    glUniformMatrix4fv(_modelView, 1, GL_FALSE, modelView.m);

GLKMatrix4MakeTranslation是系統(tǒng)初始化平移矩陣的函數(shù)
看下效果:

  • 旋轉(zhuǎn)
    GLKMatrix4 modelView = GLKMatrix4MakeRotation(_transformRotation[0],1,0,0);
    modelView = GLKMatrix4Rotate(modelView, _transformRotation[1], 0, 1, 0);
    modelView = GLKMatrix4Rotate(modelView, _transformRotation[2], 0, 0, 1);
    
    //給著色器變量賦值
    /*
        location:   變量的位置
        count   :   要更改變量的個(gè)數(shù)
        transpose:  是否需要轉(zhuǎn)置
        value   :   給出對(duì)應(yīng)count個(gè)元素的指針
    */
    glUniformMatrix4fv(_modelView, 1, GL_FALSE, modelView.m);

旋轉(zhuǎn)操作需要將3個(gè)軸(x余寥、y、z)分開單獨(dú)操作
上面的旋轉(zhuǎn)函數(shù)需要用弧度悯森。

角度 = 弧度 * (180.0f / PI)
弧度 = 角度 * (PI / 180.0f)

看下效果:

  • 矩陣組合

學(xué)過矩陣的童鞋都知道宋舷,矩陣相乘不遵守交換律
縮放、位移瓢姻、旋轉(zhuǎn)三種矩陣按照不同的順序相乘會(huì)產(chǎn)生不一樣的效果
舉個(gè)例子: 先縮放位移那么當(dāng)你縮放完以后祝蝠,你的位移向量一樣會(huì)被縮放,比如你要向右移動(dòng)兩個(gè)單位幻碱,這時(shí)候縮小兩倍绎狭,那么的平移的向量一樣會(huì)縮小兩倍,就變成了一個(gè)單位

順序的話一般都沒有硬性規(guī)定, 看需求, 本文順序位移->旋轉(zhuǎn)->縮放

下面我們把三種效果組合試一下

GLKMatrix4 modelView = GLKMatrix4MakeTranslation(_transformTranslation[0],
                                                     _transformTranslation[1],
                                                     _transformTranslation[2]);
    
    modelView = GLKMatrix4Rotate(modelView, _transformRotation[0], 1, 0, 0);
    modelView = GLKMatrix4Rotate(modelView, _transformRotation[1], 0, 1, 0);
    modelView = GLKMatrix4Rotate(modelView, _transformRotation[2], 0, 0, 1);
    
    modelView = GLKMatrix4Scale(modelView,
                                _transformScale[0],
                                _transformScale[1],
                                _transformScale[2]);
    
    //給著色器變量賦值
    /*
        location:   變量的位置
        count   :   要更改變量的個(gè)數(shù)
        transpose:  是否需要轉(zhuǎn)置
        value   :   給出對(duì)應(yīng)count個(gè)元素的指針
    */
    glUniformMatrix4fv(_modelView, 1, GL_FALSE, modelView.m);

看下效果:

本來想著這篇文章到這樣就結(jié)束了褥傍,但是回頭一看發(fā)現(xiàn)內(nèi)容有點(diǎn)少儡嘶,就順便在實(shí)現(xiàn)多一個(gè)效果吧

先看下下面這段頂點(diǎn)數(shù)據(jù)

//4個(gè)頂點(diǎn)(分別表示xyz軸)
static const float Vertices[] = {
    
    -0.5, -0.5, 0,  //左下
     0.5, -0.5, 0,  //右下
    -0.5,  0.5, 0,  //左上
     0.5,  0.5, 0,  //右上
};

這里有個(gè)Z軸還沒用到的,上面是其中一個(gè)面
我們還需要把后面的4個(gè)坐標(biāo)點(diǎn)加上恍风,才能湊夠一個(gè)立方體(8個(gè)點(diǎn))

//4個(gè)頂點(diǎn)(分別表示xyz軸)
static const float Vertices[] = {
    
    //前面4個(gè)坐標(biāo)
    -0.5, -0.5,  0.5,
     0.5, -0.5,  0.5,
    -0.5,  0.5,  0.5,
     0.5,  0.5,  0.5,
    
    //后面4個(gè)坐標(biāo)
    -0.5, -0.5, -0.5,
     0.5, -0.5, -0.5,
    -0.5,  0.5, -0.5,
     0.5,  0.5, -0.5,
};

//4個(gè)點(diǎn)的顏色(分別表示RGBA值)
static const float Colors[] = {
    
    1, 0, 0, 1,
    0, 1, 0, 1,
    0, 0, 1, 1,
    0, 0, 0, 1,
    
    1, 0, 0, 1,
    0, 1, 0, 1,
    0, 0, 1, 1,
    0, 0, 0, 1,
};

由于我們只給了8個(gè)點(diǎn)的坐標(biāo), 所以我們用原來的這個(gè)方法有點(diǎn)不合適

glDrawArrays(GL_TRIANGLE_STRIP, 0, sizeof(Vertices) / (sizeof(float) * 3));

我們來介紹另一個(gè)方法glDrawElements, 這個(gè)方法跟glDrawArrays一樣都是渲染

這兩種方法的介紹蹦狂,可以看下這篇文章

創(chuàng)建索引數(shù)組

static const GLubyte Indices[] = {
    
    0,  1,  2,
    2,  3,  1,
    
    4,  5,  6,
    6,  7,  5,
    
    2,  3,  6,
    6,  7,  3,
    
    0,  1,  4,
    4,  5,  1,
    
    0,  4,  2,
    2,  6,  4,
    
    1,  5,  3,
    3,  7,  5
};

渲染

/*
*  mode   :    渲染的方式
*  count  :    索引數(shù)組元素的數(shù)量
*  type   :    索引值的類型
*  indices:    索引數(shù)組的指針
*/
glDrawElements(GL_TRIANGLES, sizeof(Indices)/sizeof(Indices[0]), GL_UNSIGNED_BYTE, Indices);

很明顯的看到誓篱,層次有點(diǎn)不對(duì)

我們需要新增一個(gè)深度緩沖區(qū)
深度緩沖區(qū)簡(jiǎn)單來說就是讓物體的渲染有層次感, 詳解看這篇文章

下面這段代碼需要在渲染緩沖區(qū)前調(diào)用

/**
 *  設(shè)置深度緩沖區(qū)
 */
- (void)setupDepthBuffer {
    
    glGenRenderbuffers(1, &_depthRenderBuffer);
    glBindRenderbuffer(GL_RENDERBUFFER, _depthRenderBuffer);
    glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, _width, _height);
}

在幀緩沖區(qū)中新增一段代碼

/**
 *  設(shè)置幀緩沖區(qū)
 */
- (void)setupFrameBuffer {
    
    glGenFramebuffers(1, &_frameBuffer);
    glBindFramebuffer(GL_FRAMEBUFFER, _frameBuffer);
    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, _renderBuffer);

    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, _depthRenderBuffer);    //new
}

render:中的glClearColor修改下

    glClearColor(0.8f, 0.8f, 0.8f, 1.0f);
//    glClear(GL_COLOR_BUFFER_BIT); 
    glEnable(GL_DEPTH_TEST);        //new
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);  //new
效果:
結(jié)語

自從把這個(gè)三維的立方體實(shí)現(xiàn)以后,突然感覺OpenGLES很好玩凯楔,雖然在這過程中不斷的踩坑調(diào)試窜骄,但是實(shí)現(xiàn)以后又有了滿滿的信心.(??????)??加油
后面的例子會(huì)越來越好玩的,一起一步一步的學(xué)下去吧
Demo

1.可以嘗試著把縮放啼辣、位移啊研、旋轉(zhuǎn)三種方式的順序換一下,看會(huì)有怎么樣子的效果
2.感興趣的小伙伴可以把紋理加上
3.下篇文章我們來實(shí)現(xiàn)一個(gè)更好玩的坐標(biāo)系統(tǒng)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末鸥拧,一起剝皮案震驚了整個(gè)濱河市党远,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌富弦,老刑警劉巖沟娱,帶你破解...
    沈念sama閱讀 211,561評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異腕柜,居然都是意外死亡济似,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,218評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門盏缤,熙熙樓的掌柜王于貴愁眉苦臉地迎上來砰蠢,“玉大人,你說我怎么就攤上這事唉铜√ú眨” “怎么了?”我有些...
    開封第一講書人閱讀 157,162評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵潭流,是天一觀的道長(zhǎng)竞惋。 經(jīng)常有香客問我,道長(zhǎng)灰嫉,這世上最難降的妖魔是什么拆宛? 我笑而不...
    開封第一講書人閱讀 56,470評(píng)論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮讼撒,結(jié)果婚禮上浑厚,老公的妹妹穿的比我還像新娘。我一直安慰自己根盒,他們只是感情好瞻颂,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,550評(píng)論 6 385
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著郑象,像睡著了一般贡这。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上厂榛,一...
    開封第一講書人閱讀 49,806評(píng)論 1 290
  • 那天盖矫,我揣著相機(jī)與錄音丽惭,去河邊找鬼。 笑死辈双,一個(gè)胖子當(dāng)著我的面吹牛责掏,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播湃望,決...
    沈念sama閱讀 38,951評(píng)論 3 407
  • 文/蒼蘭香墨 我猛地睜開眼换衬,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了证芭?” 一聲冷哼從身側(cè)響起瞳浦,我...
    開封第一講書人閱讀 37,712評(píng)論 0 266
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎废士,沒想到半個(gè)月后叫潦,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,166評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡官硝,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,510評(píng)論 2 327
  • 正文 我和宋清朗相戀三年矗蕊,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片氢架。...
    茶點(diǎn)故事閱讀 38,643評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡傻咖,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出岖研,到底是詐尸還是另有隱情没龙,我是刑警寧澤,帶...
    沈念sama閱讀 34,306評(píng)論 4 330
  • 正文 年R本政府宣布缎玫,位于F島的核電站,受9級(jí)特大地震影響解滓,放射性物質(zhì)發(fā)生泄漏赃磨。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,930評(píng)論 3 313
  • 文/蒙蒙 一洼裤、第九天 我趴在偏房一處隱蔽的房頂上張望邻辉。 院中可真熱鬧,春花似錦腮鞍、人聲如沸值骇。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,745評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽吱瘩。三九已至,卻和暖如春迹缀,著一層夾襖步出監(jiān)牢的瞬間使碾,已是汗流浹背蜜徽。 一陣腳步聲響...
    開封第一講書人閱讀 31,983評(píng)論 1 266
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留票摇,地道東北人拘鞋。 一個(gè)月前我還...
    沈念sama閱讀 46,351評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像矢门,于是被迫代替她去往敵國(guó)和親盆色。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,509評(píng)論 2 348

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

  • 變換(Transformations) 我們可以嘗試著在每一幀改變物體的頂點(diǎn)并且重設(shè)緩沖區(qū)從而使他們移動(dòng)祟剔,但這太繁...
    IceMJ閱讀 4,106評(píng)論 0 1
  • 版本記錄 前言 OpenGL 圖形庫項(xiàng)目中一直也沒用過隔躲,最近也想學(xué)著使用這個(gè)圖形庫,感覺還是很有意思峡扩,也就自然想著...
    刀客傳奇閱讀 5,129評(píng)論 0 3
  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 171,769評(píng)論 25 707
  • WebGL從2012年開始接觸蹭越,后面因?yàn)殚_始專注前端其他方面的事情,慢慢地就把它給遺忘教届。最近前端開始又流行起繪畫制...
    我不是傳哥閱讀 4,083評(píng)論 1 22
  • 作詞:板藍(lán)根 作曲:板藍(lán)根 F G 眼睛里有光响鹃, Em Am 是因?yàn)樾睦镒≈屏迹?F...
    耽九閱讀 809評(píng)論 0 1