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

本系列所有文章目錄

下面是本文例子的運(yùn)行截圖为黎,可以前往我的博客查看代碼演示冯事。

上一篇文章中說到了透視和正交兩種投影矩陣,文末提到了三個(gè)基本矩陣MVP。本文就以介紹MVP為開頭信殊,然后再詳細(xì)講解攝像機(jī)的概念挽绩。
MVP表示的是模型變換矩陣(Model),觀察矩陣(View)堰塌,投影矩陣(Projection)赵刑。投影矩陣介紹過了。模型矩陣針對的是單個(gè)3D模型场刑,渲染每一個(gè)3D模型前般此,需要將各自的模型矩陣傳遞給Vertex Shader。觀察矩陣針對的是場景中的所有物體牵现,當(dāng)觀察矩陣改變時(shí)铐懊,所有頂點(diǎn)的位置都會(huì)受到影響,就好像你移動(dòng)現(xiàn)實(shí)世界的攝像機(jī)瞎疼,拍攝到的場景就會(huì)變化一樣科乎。所以觀察矩陣可以理解為WebGL 3D世界中的攝像機(jī)。我們有了攝像機(jī)這個(gè)變換矩陣之后贼急,就可以很方便的在3D世界中游覽茅茂,就像第一人稱視角游戲中一樣。
大概了解MVP之后太抓,我們開始使用代碼實(shí)現(xiàn)它們空闲。首先要修改一下Vertex Shader。

attribute vec4 position;
varying vec4 fragColor;

uniform float elapsedTime;
uniform mat4 projectionMatrix;
uniform mat4 cameraMatrix;
uniform mat4 modelMatrix;
void main() {
    fragColor = position * 0.5 + 0.5;
    gl_Position = projectionMatrix * cameraMatrix * modelMatrix * position;
}

我把之前的uniform transform換成了三個(gè)變換矩陣projectionMatrix,cameraMatrix,modelMatrix,它們分別是投影矩陣走敌,觀察矩陣碴倾,模型矩陣。將它們相乘projectionMatrix * cameraMatrix * modelMatrix,結(jié)果乘以position賦值給gl_Position影斑。注意相乘的順序给赞,這個(gè)順序的結(jié)果是先進(jìn)行模型矩陣變換,再是觀察矩陣矫户,最后是投影矩陣變換片迅。這樣Vertex Shader中的MVP就實(shí)現(xiàn)完了,很簡單是不是皆辽。

回到JS代碼柑蛇,我將之前的屬性transform換成了4個(gè)變換矩陣,分別是兩個(gè)M和VP驱闷。本文的例子將繪制兩個(gè)矩形耻台,所以我為它們分別定義了模型矩陣modelMatrix1modelMatrix2

var perspectiveProjectionMatrix = null;
var cameraMatrix = null;
var modelMatrix1 = null;
var modelMatrix2 = null;

接下來初始化這些屬性空另。

function setupMatrix() {
  perspectiveProjectionMatrix = mat4.create();
  mat4.perspective(perspectiveProjectionMatrix, 90 / 180.0 * Math.PI, canvas.width / canvas.height, 0.1, 1000);

  cameraMatrix = mat4.create();
  mat4.lookAt(cameraMatrix, vec3.fromValues(0,0,2), vec3.fromValues(0,0,0), vec3.fromValues(0,1,0));

  modelMatrix1 = mat4.create();
  modelMatrix2 = mat4.create();
}

投影矩陣使用了透視投影進(jìn)行初始化盆耽。兩個(gè)模型矩陣初始化為單位矩陣。本文的主角觀察矩陣初始化為攝像機(jī)在 0扼菠,0摄杂,2 坐標(biāo),看向 0循榆,0析恢,0點(diǎn),向上朝向0秧饮,1映挂,0。mat4.lookAt提供了快捷創(chuàng)建觀察矩陣的方法盗尸,需要傳遞3個(gè)類型為vec3的參數(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ì)深入講解罕拂。

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

// 保證canvas尺寸改變時(shí),同步投影矩陣的值爆班,你也可以在resize里重新計(jì)算衷掷,那樣會(huì)更好。
mat4.perspective(perspectiveProjectionMatrix, 90 / 180.0 * Math.PI, canvas.width / canvas.height, 0.1, 1000);

var varyingFactor = (Math.sin(elapsedTime / 1000) + 1) / 2.0; // 0 ~ 1
mat4.lookAt(cameraMatrix, vec3.fromValues(0, 0, 2 * (varyingFactor + 1)), vec3.fromValues(0, 0, 0), vec3.fromValues(0, 1, 0));

// 設(shè)置第一個(gè)model matrix
var rotateMatrix = mat4.create();
var translateMatrix = mat4.create();
mat4.rotate(rotateMatrix, rotateMatrix, varyingFactor * Math.PI * 2, vec3.fromValues(0, 1, 0));
mat4.translate(translateMatrix, translateMatrix, vec3.fromValues(-0.7, 0, 0));
mat4.multiply(modelMatrix1, translateMatrix, rotateMatrix);

// 設(shè)置第二個(gè)model matrix
rotateMatrix = mat4.create();
translateMatrix = mat4.create();
mat4.rotate(rotateMatrix, rotateMatrix, varyingFactor * Math.PI * 2, vec3.fromValues(0, 0, 1));
mat4.translate(translateMatrix, translateMatrix, vec3.fromValues(0.7, 0, 0));
mat4.multiply(modelMatrix2, translateMatrix, rotateMatrix);

var varyingFactor = (Math.sin(elapsedTime / 1000) + 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賦值旧困。

// 設(shè)置投影和觀察矩陣
var projectionMatrixUniformLoc = gl.getUniformLocation(program, 'projectionMatrix');
gl.uniformMatrix4fv(projectionMatrixUniformLoc, false, perspectiveProjectionMatrix);
var cameraMatrixUniformLoc = gl.getUniformLocation(program, 'cameraMatrix');
gl.uniformMatrix4fv(cameraMatrixUniformLoc, false, cameraMatrix);

// 使用不同的model matrix繪制兩次物體
var modelMatrixUniformLoc = gl.getUniformLocation(program, 'modelMatrix');
gl.uniformMatrix4fv(modelMatrixUniformLoc, false, modelMatrix1);
gl.drawArrays(gl.TRIANGLES, 0, 6);

modelMatrixUniformLoc = gl.getUniformLocation(program, 'modelMatrix');
gl.uniformMatrix4fv(modelMatrixUniformLoc, false, modelMatrix2);
gl.drawArrays(gl.TRIANGLES, 0, 6);

先給uniform projectionMatrixuniform cameraMatrix賦值醇份。每個(gè)矩形繪制之前,再將各自的modelMatrix賦值給uniform modelMatrix吼具,就像開頭說的那樣僚纷,每個(gè)3D模型有自己的模型變換。

本篇主要介紹了攝像機(jī)(觀察矩陣)拗盒,三大基本矩陣MVP的概念怖竭。下一篇小試牛刀,開始渲染真正的3D物體-正方體陡蝇。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末痊臭,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子登夫,更是在濱河造成了極大的恐慌广匙,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,039評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件恼策,死亡現(xiàn)場離奇詭異鸦致,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,426評論 3 395
  • 文/潘曉璐 我一進(jìn)店門分唾,熙熙樓的掌柜王于貴愁眉苦臉地迎上來抗碰,“玉大人,你說我怎么就攤上這事绽乔「暮” “怎么了?”我有些...
    開封第一講書人閱讀 165,417評論 0 356
  • 文/不壞的土叔 我叫張陵迄汛,是天一觀的道長捍壤。 經(jīng)常有香客問我,道長鞍爱,這世上最難降的妖魔是什么鹃觉? 我笑而不...
    開封第一講書人閱讀 58,868評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮睹逃,結(jié)果婚禮上盗扇,老公的妹妹穿的比我還像新娘。我一直安慰自己沉填,他們只是感情好疗隶,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,892評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著翼闹,像睡著了一般斑鼻。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上猎荠,一...
    開封第一講書人閱讀 51,692評論 1 305
  • 那天坚弱,我揣著相機(jī)與錄音,去河邊找鬼关摇。 笑死荒叶,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的输虱。 我是一名探鬼主播些楣,決...
    沈念sama閱讀 40,416評論 3 419
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼宪睹!你這毒婦竟也來了愁茁?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,326評論 0 276
  • 序言:老撾萬榮一對情侶失蹤横堡,失蹤者是張志新(化名)和其女友劉穎埋市,沒想到半個(gè)月后冠桃,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體命贴,經(jīng)...
    沈念sama閱讀 45,782評論 1 316
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,957評論 3 337
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了胸蛛。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片污茵。...
    茶點(diǎn)故事閱讀 40,102評論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖葬项,靈堂內(nèi)的尸體忽然破棺而出泞当,到底是詐尸還是另有隱情,我是刑警寧澤民珍,帶...
    沈念sama閱讀 35,790評論 5 346
  • 正文 年R本政府宣布襟士,位于F島的核電站,受9級特大地震影響嚷量,放射性物質(zhì)發(fā)生泄漏陋桂。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,442評論 3 331
  • 文/蒙蒙 一蝶溶、第九天 我趴在偏房一處隱蔽的房頂上張望嗜历。 院中可真熱鬧,春花似錦抖所、人聲如沸梨州。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,996評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽暴匠。三九已至,卻和暖如春傻粘,著一層夾襖步出監(jiān)牢的瞬間巷查,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,113評論 1 272
  • 我被黑心中介騙來泰國打工抹腿, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留岛请,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,332評論 3 373
  • 正文 我出身青樓警绩,卻偏偏與公主長得像崇败,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子肩祥,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,044評論 2 355

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

  • 本系列所有文章目錄[http://www.reibang.com/p/df4c8f9bc08d] 獲取示例代碼[...
    handyTOOL閱讀 2,938評論 2 5
  • OpenGL本身沒有攝像機(jī)的概念后室,但我們可以通過把場景中的所有物體往相反方向移動(dòng)的方式來模擬出攝像機(jī),這樣感覺就像...
    IceMJ閱讀 2,494評論 0 7
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,167評論 25 707
  • 一 她喜歡他,同學(xué)都看的出來将饺,他卻不知道贡避?自打分班起的第一天他兩的故事就開始了痛黎。 她并不是“外貌協(xié)會(huì)的人”,所以她...
    Z同學(xué)你好閱讀 615評論 4 9
  • 六一慢步跑過來刮吧, 童叟興奮樂開懷湖饱。 你看這伙老小孩, 童心永駐激情在杀捻。
    旖旎i閱讀 297評論 5 2