學(xué)習(xí)OpenGL ES之?dāng)z像機(jī)

本系列所有文章目錄

獲取示例代碼


上一篇文章中說到了透視和正交兩種投影矩陣,文末提到了三個(gè)基本矩陣MVP恩伺。本文就以介紹MVP為開頭,然后再詳細(xì)講解攝像機(jī)的概念。
MVP表示的是模型矩陣(Model)蒸播,觀察矩陣(View)全景,投影矩陣(Projection)邪意。投影矩陣介紹過了。模型矩陣針對(duì)的是單個(gè)3D模型泰演,渲染每一個(gè)3D模型前,需要將各自的模型矩陣傳遞給Vertex Shader葱轩。觀察矩陣針對(duì)的是場景中的所有物體睦焕,當(dāng)觀察矩陣改變時(shí),所有頂點(diǎn)的位置都會(huì)受到影響靴拱,就好像你移動(dòng)現(xiàn)實(shí)世界的攝像機(jī)垃喊,拍攝到的場景就會(huì)變化一樣。所以觀察矩陣可以理解為OpenGL 3D世界中的攝像機(jī)袜炕。我們有了攝像機(jī)這個(gè)變換矩陣之后缔御,就可以很方便的在3D世界中游覽,就像第一人稱視角游戲中一樣妇蛀。
大概了解MVP之后耕突,我們開始使用代碼實(shí)現(xiàn)它們。首先要修改一下Vertex Shader评架。

attribute vec4 position;
attribute vec4 color;

uniform float elapsedTime;
uniform mat4 projectionMatrix;
uniform mat4 cameraMatrix;
uniform mat4 modelMatrix;

varying vec4 fragColor;

void main(void) {
    fragColor = color;
    mat4 mvp = projectionMatrix * cameraMatrix * modelMatrix;
    gl_Position = mvp * position;
}

我把之前的uniform transform換成了三個(gè)變換矩陣projectionMatrix,cameraMatrix,modelMatrix,它們分別是投影矩陣眷茁,觀察矩陣,模型矩陣纵诞。將它們相乘projectionMatrix * cameraMatrix * modelMatrix上祈,結(jié)果乘以position賦值給gl_Position。注意相乘的順序浙芙,這個(gè)順序的結(jié)果是先進(jìn)行模型矩陣變換登刺,再是觀察矩陣,最后是投影矩陣變換嗡呼。這樣Vertex Shader中的MVP就實(shí)現(xiàn)完了纸俭,很簡單是不是。

回到OC代碼南窗,我將之前的屬性transform換成了4個(gè)變換矩陣揍很,分別是兩個(gè)M和VP郎楼。本文的例子將繪制兩個(gè)矩形,所以我為它們分別定義了模型矩陣modelMatrix1modelMatrix2窒悔。

@property (assign, nonatomic) GLKMatrix4 projectionMatrix; // 投影矩陣
@property (assign, nonatomic) GLKMatrix4 cameraMatrix; // 觀察矩陣
@property (assign, nonatomic) GLKMatrix4 modelMatrix1; // 第一個(gè)矩形的模型變換
@property (assign, nonatomic) GLKMatrix4 modelMatrix2; // 第二個(gè)矩形的模型變換

接下來初始化這些屬性呜袁。

    // 使用透視投影矩陣
    float aspect = self.view.frame.size.width / self.view.frame.size.height;
    self.projectionMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(90), aspect, 0.1, 100.0);
    
    // 設(shè)置攝像機(jī)在 0,0简珠,2 坐標(biāo)阶界,看向 0,0聋庵,0點(diǎn)膘融。Y軸正向?yàn)閿z像機(jī)頂部指向的方向
    self.cameraMatrix = GLKMatrix4MakeLookAt(0, 0, 2, 0, 0, 0, 0, 1, 0);
    
    // 先初始化矩形1的模型矩陣為單位矩陣
    self.modelMatrix1 = GLKMatrix4Identity;
    // 先初始化矩形2的模型矩陣為單位矩陣
    self.modelMatrix2 = GLKMatrix4Identity;

投影矩陣使用了透視投影進(jìn)行初始化。兩個(gè)模型矩陣初始化為單位矩陣珍策。本文的主角觀察矩陣初始化為攝像機(jī)在 0托启,0,2 坐標(biāo)攘宙,看向 0屯耸,0,0點(diǎn)蹭劈,向上朝向0疗绣,1,0铺韧。GLKMatrix4MakeLookAt提供了快捷創(chuàng)建觀察矩陣的方法多矮,需要傳遞9個(gè)參數(shù),攝像機(jī)的位置eyeX哈打,eyeY塔逃,eyeZ,攝像機(jī)看向的點(diǎn)centerX料仗,centerY湾盗,centerZ,攝像機(jī)向上的朝向upX, upY, upZ立轧。改變這幾個(gè)參數(shù)就能控制攝像機(jī)在3D世界中通過不同角度拍攝物體格粪。
我把上一篇的剖面示意圖做了一下修改。

圖中的lookAt就是center氛改。

我們可以這么理解觀察矩陣帐萎。在觀察矩陣的作用下,透視矩陣的原點(diǎn)變成了攝像機(jī)的位置eye胜卤。up決定了攝像機(jī)圍繞eye和lookAt形成的軸(本例中就是Z軸)的旋轉(zhuǎn)角度疆导,讀者可以修改本例的中的up值看看效果。lookAt決定了攝像機(jī)能看到的區(qū)域瑰艘,可以看做是控制攝像機(jī)在Y軸和X軸上的旋轉(zhuǎn)角度是鬼。

在第一人稱的游戲中肤舞,只要控制lookAt的位置就可以實(shí)現(xiàn)360度查看周邊景物的效果紫新,后面介紹到渲染3D場景的時(shí)候會(huì)深入講解均蜜。

初始化完后在update中為這些矩陣賦新的值。

- (void)update {
    [super update];
    float varyingFactor = (sin(self.elapsedTime) + 1) / 2.0; // 0 ~ 1
    self.cameraMatrix = GLKMatrix4MakeLookAt(0, 0, 2 * (varyingFactor + 1), 0, 0, 0, 0, 1, 0);
    
    GLKMatrix4 translateMatrix1 = GLKMatrix4MakeTranslation(-0.7, 0, 0);
    GLKMatrix4 rotateMatrix1 = GLKMatrix4MakeRotation(varyingFactor * M_PI * 2, 0, 1, 0);
    self.modelMatrix1 = GLKMatrix4Multiply(translateMatrix1, rotateMatrix1);
    
    GLKMatrix4 translateMatrix2 = GLKMatrix4MakeTranslation(0.7, 0, 0);
    GLKMatrix4 rotateMatrix2 = GLKMatrix4MakeRotation(varyingFactor * M_PI, 0, 0, 1);
    self.modelMatrix2 = GLKMatrix4Multiply(translateMatrix2, rotateMatrix2);
}

float varyingFactor = (sin(self.elapsedTime) + 1) / 2.0;的值從0到1芒率。
攝像機(jī)的Z軸坐標(biāo)為2 * (varyingFactor + 1)囤耳,從2到4。
第一個(gè)矩形向左偏移0.7偶芍,繞Y軸旋轉(zhuǎn)varyingFactor * M_PI * 2充择,從0到360度。
第二個(gè)矩形向右偏移0.7匪蟀,繞Z軸旋轉(zhuǎn)varyingFactor * M_PI * 2椎麦,從0到360度。

最后給uniform賦值材彪。

- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect {
    [super glkView:view drawInRect:rect];
  
    GLuint projectionMatrixUniformLocation = glGetUniformLocation(self.shaderProgram, "projectionMatrix");
    glUniformMatrix4fv(projectionMatrixUniformLocation, 1, 0, self.projectionMatrix.m);
    GLuint cameraMatrixUniformLocation = glGetUniformLocation(self.shaderProgram, "cameraMatrix");
    glUniformMatrix4fv(cameraMatrixUniformLocation, 1, 0, self.cameraMatrix.m);
    
    GLuint modelMatrixUniformLocation = glGetUniformLocation(self.shaderProgram, "modelMatrix");
    // 繪制第一個(gè)矩形
    glUniformMatrix4fv(modelMatrixUniformLocation, 1, 0, self.modelMatrix1.m);
    [self drawRectangle];
    
    // 繪制第二個(gè)矩形
    glUniformMatrix4fv(modelMatrixUniformLocation, 1, 0, self.modelMatrix2.m);
    [self drawRectangle];
}

先給uniform projectionMatrixuniform cameraMatrix賦值观挎。每個(gè)矩形繪制之前,再將各自的modelMatrix賦值給uniform modelMatrix段化,就像開頭說的那樣嘁捷,每個(gè)3D模型有自己的模型變換。

最終效果如下显熏。

本篇主要介紹了攝像機(jī)(觀察矩陣)雄嚣,三大基本矩陣MVP的概念。下一篇小試牛刀喘蟆,開始渲染真正的3D物體-正方體缓升。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市蕴轨,隨后出現(xiàn)的幾起案子港谊,更是在濱河造成了極大的恐慌,老刑警劉巖尺棋,帶你破解...
    沈念sama閱讀 216,496評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件封锉,死亡現(xiàn)場離奇詭異,居然都是意外死亡膘螟,警方通過查閱死者的電腦和手機(jī)成福,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,407評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來荆残,“玉大人奴艾,你說我怎么就攤上這事∧谒梗” “怎么了蕴潦?”我有些...
    開封第一講書人閱讀 162,632評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵像啼,是天一觀的道長。 經(jīng)常有香客問我潭苞,道長忽冻,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,180評(píng)論 1 292
  • 正文 為了忘掉前任此疹,我火速辦了婚禮僧诚,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘蝗碎。我一直安慰自己湖笨,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,198評(píng)論 6 388
  • 文/花漫 我一把揭開白布蹦骑。 她就那樣靜靜地躺著慈省,像睡著了一般。 火紅的嫁衣襯著肌膚如雪眠菇。 梳的紋絲不亂的頭發(fā)上边败,一...
    開封第一講書人閱讀 51,165評(píng)論 1 299
  • 那天,我揣著相機(jī)與錄音琼锋,去河邊找鬼放闺。 笑死,一個(gè)胖子當(dāng)著我的面吹牛缕坎,可吹牛的內(nèi)容都是我干的怖侦。 我是一名探鬼主播,決...
    沈念sama閱讀 40,052評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼谜叹,長吁一口氣:“原來是場噩夢啊……” “哼匾寝!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起荷腊,我...
    開封第一講書人閱讀 38,910評(píng)論 0 274
  • 序言:老撾萬榮一對(duì)情侶失蹤艳悔,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后女仰,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體猜年,經(jīng)...
    沈念sama閱讀 45,324評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,542評(píng)論 2 332
  • 正文 我和宋清朗相戀三年疾忍,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了乔外。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,711評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡一罩,死狀恐怖杨幼,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤差购,帶...
    沈念sama閱讀 35,424評(píng)論 5 343
  • 正文 年R本政府宣布四瘫,位于F島的核電站,受9級(jí)特大地震影響欲逃,放射性物質(zhì)發(fā)生泄漏找蜜。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,017評(píng)論 3 326
  • 文/蒙蒙 一暖夭、第九天 我趴在偏房一處隱蔽的房頂上張望锹杈。 院中可真熱鬧撵孤,春花似錦迈着、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,668評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至闭专,卻和暖如春奴潘,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背影钉。 一陣腳步聲響...
    開封第一講書人閱讀 32,823評(píng)論 1 269
  • 我被黑心中介騙來泰國打工画髓, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人平委。 一個(gè)月前我還...
    沈念sama閱讀 47,722評(píng)論 2 368
  • 正文 我出身青樓奈虾,卻偏偏與公主長得像,于是被迫代替她去往敵國和親廉赔。 傳聞我的和親對(duì)象是個(gè)殘疾皇子肉微,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,611評(píng)論 2 353

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