opengles-坐標(biāo)系和矩陣

坐標(biāo)系和矩陣是opengl的基礎(chǔ)也是難點尉剩,本文總結(jié)了opengl的各種坐標(biāo)系和矩陣飞苇,如果有錯誤歡迎指正入挣。

1.什么是opengl和opengl es

OpenGL(全寫Open Graphics Library)是指定義了一個跨編程語言递惋、跨平臺的編程接口規(guī)格的專業(yè)的圖形程序接口访惜。OpenGL是個與硬件無關(guān)的軟件接口,可以在不同的平臺如Windows 95宙址、Windows NT轴脐、Unix、Linux抡砂、MacOS大咱、OS/2之間進(jìn)行移植。因此注益,支持OpenGL的軟件具有很好的移植性碴巾,可以獲得非常廣泛的應(yīng)用。

Opengl2.0開始支持glsl(OpenGL Shading Language)丑搔,opengl1.x是固定渲染管線的已經(jīng)被淘汰無需考慮厦瓢。Opengles是OpenGL裁剪定制而來的,專為手機(jī)啤月,游戲機(jī)等嵌入式設(shè)備而設(shè)計煮仇,在安卓設(shè)備上的opengl就是opengles。

安卓使用GLSurfaceView封裝和簡化opengl的開發(fā)谎仲,它幫助我們建立單獨的opengl線程欺抗,并且支持連續(xù)或者按需渲染,它使用EGL來處理屏幕設(shè)置强重,Egl是OpenGL與底層窗口系統(tǒng)之間的接口绞呈。

  • It provides a dedicated render thread for OpenGL so that the main thread is not stalled.
  • It supports continuous or on-demand rendering.
  • It takes care of the screen setup for you using EGL, the interface between OpenGL and the underlying window system.

2.opengl的各種坐標(biāo)系和矩陣

坐標(biāo)系

  1. 安卓設(shè)備坐標(biāo)系

    屏幕左上點為原點贸人,x軸向右,y軸向下佃声,跟隨屏幕方向變化而變化艺智。

  2. 紋理坐標(biāo)系 uv coordinates

    2d紋理坐標(biāo)系也就是UV坐標(biāo)系,水平方向是U圾亏,垂直方向是V十拣,通過這個平面的,二維的UV坐標(biāo)系志鹃。我們可以定位圖象上的任意一個象素夭问。左下角為原點,U軸向右曹铃,V軸向上缰趋,范圍[0,1]。

  3. 模型坐標(biāo)系 object coordinates

    歸一化的右手坐標(biāo)系陕见,以模型內(nèi)某一點為原點建立的坐標(biāo)系秘血,其它模型內(nèi)的點的位置可以用相對于模型內(nèi)的原點來表示的坐標(biāo)系,該坐標(biāo)系僅在模型內(nèi)有效评甜。

  4. 世界坐標(biāo)系 world coordinates

    右手坐標(biāo)系灰粮,屏幕中心點位原點x軸向右,y軸向上忍坷,z軸向屏幕外粘舟。可以理解為無限大的坐標(biāo)系佩研,用來描述物體或者光源的位置柑肴,跟隨屏幕方向變化而變化。韧骗。

  5. 視點坐標(biāo)系 eye coordinates

    以視點(相機(jī))為原點,以視線的<u>負(fù)方向為Z軸正方向</u>的坐標(biāo)系零聚,注意是相機(jī)看向的其實是-z軸袍暴。

  6. 齊次坐標(biāo)系 clip coordinates

    齊次坐標(biāo)就是用N+1維來代表N維坐標(biāo),在opengl中以第四個值w表示,齊次坐標(biāo)系表示同一個點并不唯一[8,4,2]隶症、[4,2,1]表示的都是二維點[4,2]政模。

    齊次坐標(biāo)系可以使用(x,y,z,w)表示一個點,也可以表示向量蚂会。當(dāng)w==1時表示點(僅限eye坐標(biāo)系及之前的坐標(biāo)系)淋样,當(dāng)w==0時表示向量。

    齊次坐標(biāo)系使得點和向量可以用統(tǒng)一的vec4來表示胁住。

  7. opengl設(shè)備標(biāo)準(zhǔn)化坐標(biāo)系 ndc coordinates

    Normalized device coordinates(ndc坐標(biāo)系)心赶,采用的是左手三維坐標(biāo)系(也就是z軸其實是指向屏幕里的)揭蜒,三個坐標(biāo)軸都是[-1,1]蛛勉,是opengl服務(wù)端唯一理解的內(nèi)部坐標(biāo)系,跟隨屏幕方向變化而變化娱挨。

    opengl是server-client模式,應(yīng)用程序是客戶端捕犬,圖形硬件廠商提供的OpenGL實現(xiàn)是服務(wù)器跷坝。而client也就是應(yīng)用程序內(nèi)部采用的都是右手坐標(biāo)系,只是是在使用Ortho或者Perspective來生成投影矩陣的時候碉碉,近遠(yuǎn)視點分別加了負(fù)號做了轉(zhuǎn)換柴钻。

    glViewport(x,y,width,height)用來函數(shù)指明標(biāo)準(zhǔn)坐標(biāo)系和屏幕坐標(biāo)映射計算關(guān)系,在安卓中一般用在onSurfaceChanged的回調(diào)里垢粮。一般這個計算不需要我們來做贴届,此處只是作為補(bǔ)充說明。

    標(biāo)準(zhǔn)坐標(biāo)轉(zhuǎn)屏幕坐標(biāo)公式

    ?

矩陣

opengl的矩陣是4*4的矩陣足丢,可以用16個元素的數(shù)組表示粱腻,opengl采用column-major order(列主序矩陣),也就是一列一列從數(shù)組讀取數(shù)據(jù)斩跌。由于列主序的存在绍些,導(dǎo)致4×4矩陣作用于vector4(例如shader中的位置、顏色等耀鸦,實際為4×1矩陣)柬批,所以vector4只能左乘變換矩陣(線性代數(shù)矩陣乘法規(guī)定,它只有在第一個矩陣的列數(shù)(column)和第二個矩陣的行數(shù)(row)相同時才有意義)袖订。

列主序矩陣
  1. modelMatrix模型矩陣:

    模型矩陣可以包括對模型的縮放氮帐、旋轉(zhuǎn)、平移操作洛姑。先縮放再旋轉(zhuǎn)再平移上沐,由于矩陣乘法不滿足交換律,順序不能變化楞艾。例如先向左轉(zhuǎn)再走兩步参咙,和先走兩步再像左轉(zhuǎn)是完全不一樣的結(jié)果。

    <u>如果要改變順序一定要清楚其帶來的影響</u>

    scaleMatrix在矩陣中的表示:
    縮放變換矩陣
    rotationMatrix矩陣中比較復(fù)雜硫眯,暫時不列出
    translateMatrix矩陣變換
    平移變換矩陣表示

    綜上蕴侧,最終的modelMatrix = TranslationMatrix * RotationMatrix * ScaleMatrix,從右向左乘,先變換的最先乘两入。

    通過左乘模型矩陣可以將局部物體坐標(biāo)系坐標(biāo)轉(zhuǎn)化為世界坐標(biāo)系的坐標(biāo)净宵。

    vec4 worldCoordinateVector = modelMatrix * modelCoordinateVector;

  2. viewMatrix視圖矩陣

    setLookAtM(float[] rm, int rmOffset, float eyeX, float eyeY, float eyeZ, float centerX, float centerY, float centerZ, float upX, float upY, float upZ)

    用來生成視圖矩陣,主要規(guī)定視點位置、焦點位置择葡、相機(jī)y軸up朝向紧武。

    世界坐標(biāo)系的坐標(biāo)值左乘視圖矩陣可以將世界坐標(biāo)系轉(zhuǎn)化為視點相機(jī)坐標(biāo)系。

    vec4 cameraCoordinateVector = viewMatrix * worldCoordinateVector;

    理論上viewMatrix和modelMatrix是可以相互替代的刁岸,如變相機(jī)位置向左移動5厘米和改變物體位置像右移動5厘米都可以實現(xiàn)相同的結(jié)果脏里,但存在多個物體的話顯然移動物體合適。

  3. projectMatrix投影矩陣

    投影矩陣并不是用來計算射線碰撞的,也不是所謂的將3d物體投射到2d平面上虹曙。投影矩陣真正作用來是把相機(jī)坐映射為標(biāo)準(zhǔn)的[-1,1]的齊次坐標(biāo)迫横,也就是帶w值的標(biāo)準(zhǔn)設(shè)備坐標(biāo)系,并且可以clip視錐之內(nèi)的點酝碳,投影內(nèi)的點記為vertex(clip)矾踱。

    opengl負(fù)責(zé)將齊次坐標(biāo)系轉(zhuǎn)化為標(biāo)準(zhǔn)坐標(biāo),也就是PerspectiveDivide(透視除)由opengl內(nèi)部調(diào)用疏哗,無需我們關(guān)心呛讲。透視除其實就是將x/y/z值分別除以w來得到屏幕標(biāo)準(zhǔn)坐標(biāo)。

    vertex(ndc) = PerspectiveDivide(vertext(clip));

    一旦拿到ndc坐標(biāo)返奉,opengl會使用公式將它映射到viewport屏幕坐標(biāo)贝搁,屏幕上就顯示了當(dāng)前點。

    關(guān)于w

    w主要是用在透視投影中的芽偏,在視點坐標(biāo)系下其值一般初始化為1,而經(jīng)過透視矩陣變換之后雷逆,其中會變?yōu)?z(注意負(fù)號,因為需要轉(zhuǎn)為左手坐標(biāo)系),經(jīng)過正交投影變換后其值仍是原值污尉,即1膀哲。

    所謂透視矩陣,就是通過各個分量divide by w來實現(xiàn)近大遠(yuǎn)小的透視效果的被碗。w雖然對正交矩陣沒有什么用某宪,但是統(tǒng)一了正交和透視矩陣的處理,避免了直接divide z锐朴。

    正交投影

    orthoM(float[] m, int mOffset, float left, float right, float bottom, float top, float near, float far)

    用來生成正交投影,near和far分別表示近視點和遠(yuǎn)視點的距離需要為正兴喂,正交矩陣視錐是一長方體,物體沒有近大遠(yuǎn)小特性焚志,同一個物體無論遠(yuǎn)近都是一樣大小的衣迷,這看起來并不自然,但是卻可以保證物體無論遠(yuǎn)近都保持一致的外觀娩嚼,某些游戲畫面就需要這個特點蘑险。

    正交矩陣應(yīng)該考慮品屏幕比例,不然會導(dǎo)致橫豎屏切換后畫面變形滴肿。

    //橫屏,例如800*600岳悟,橫屏width是800,豎屏width為600
    float aspectRatio = (float) width / (float) height;
    orthoM(projectionMatrix, 0, -aspectRatio, aspectRatio, -1, 1, -1, 1);
    //豎屏
    orthoM(projectionMatrix, 0, -aspectRatio, aspectRatio, -1, 1, -1, 1);
    

    安卓沒有任何配置的情況下,默認(rèn)相機(jī)處于世界坐標(biāo)系(0,0)點贵少,默認(rèn)使用的是[-1,1]的立方體正交投影呵俏,投影矩陣內(nèi)的所有點在屏幕上都可見,故可以看到(0,0,0)點的物體滔灶,即使默認(rèn)相機(jī)在(0,0,0)點也可以看到普碎。

    透視投影

    perspectiveM(float[] m, float yFovInDegrees, float aspect, float n, float f)

    用來定義透視矩陣

    透視矩陣也應(yīng)該考慮品屏幕比例,不然會導(dǎo)致橫豎屏切換后畫面變形,同樣near和far需要為正數(shù)。

    //橫屏,例如800*600录平,橫屏width是800麻车,豎屏width為600
    perspectiveM(projectionMatrix, 45, (float) width / (float) height, 1f, 10f);
    

    ?

    投影矩陣小結(jié):

    1.無論是正交還是透視投影,投影矩陣作用于EyeVertex點后斗这,會將該點轉(zhuǎn)化為齊次式表示的標(biāo)準(zhǔn)化設(shè)備坐標(biāo)动猬。使用正交投影的的w并沒有用,只是為了保持和透視投影處理的一致性表箭,w值經(jīng)過左乘之后沒有任何變化赁咙。

    2.透視投影的w經(jīng)過矩陣左乘之后會變成-z。

    3.正交投影和透視投影作用后的x,y,z值不相同(表達(dá)式不同)免钻,具體表達(dá)式可以參考下方鏈接彼水。

    矩陣左乘導(dǎo)致坐標(biāo)系的轉(zhuǎn)換過程

    ?

    ?

    關(guān)于投影矩陣的數(shù)學(xué)計算,請參考如下網(wǎng)站极舔,講的非常清晰凤覆,耐心看完一定會理解的。

    http://www.songho.ca/opengl/gl_projectionmatrix.html#perspective

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末姆怪,一起剝皮案震驚了整個濱河市叛赚,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌稽揭,老刑警劉巖俺附,帶你破解...
    沈念sama閱讀 216,919評論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異溪掀,居然都是意外死亡事镣,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,567評論 3 392
  • 文/潘曉璐 我一進(jìn)店門揪胃,熙熙樓的掌柜王于貴愁眉苦臉地迎上來璃哟,“玉大人,你說我怎么就攤上這事喊递∷嫔粒” “怎么了?”我有些...
    開封第一講書人閱讀 163,316評論 0 353
  • 文/不壞的土叔 我叫張陵骚勘,是天一觀的道長铐伴。 經(jīng)常有香客問我撮奏,道長,這世上最難降的妖魔是什么当宴? 我笑而不...
    開封第一講書人閱讀 58,294評論 1 292
  • 正文 為了忘掉前任畜吊,我火速辦了婚禮,結(jié)果婚禮上户矢,老公的妹妹穿的比我還像新娘玲献。我一直安慰自己,他們只是感情好梯浪,可當(dāng)我...
    茶點故事閱讀 67,318評論 6 390
  • 文/花漫 我一把揭開白布捌年。 她就那樣靜靜地躺著,像睡著了一般挂洛。 火紅的嫁衣襯著肌膚如雪延窜。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,245評論 1 299
  • 那天抹锄,我揣著相機(jī)與錄音逆瑞,去河邊找鬼。 笑死伙单,一個胖子當(dāng)著我的面吹牛获高,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播吻育,決...
    沈念sama閱讀 40,120評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼念秧,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了布疼?” 一聲冷哼從身側(cè)響起摊趾,我...
    開封第一講書人閱讀 38,964評論 0 275
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎游两,沒想到半個月后砾层,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,376評論 1 313
  • 正文 獨居荒郊野嶺守林人離奇死亡贱案,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,592評論 2 333
  • 正文 我和宋清朗相戀三年肛炮,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片宝踪。...
    茶點故事閱讀 39,764評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡侨糟,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出瘩燥,到底是詐尸還是另有隱情秕重,我是刑警寧澤,帶...
    沈念sama閱讀 35,460評論 5 344
  • 正文 年R本政府宣布厉膀,位于F島的核電站溶耘,受9級特大地震影響套鹅,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜汰具,卻給世界環(huán)境...
    茶點故事閱讀 41,070評論 3 327
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望菱魔。 院中可真熱鬧留荔,春花似錦、人聲如沸澜倦。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,697評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽藻治。三九已至碘勉,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間桩卵,已是汗流浹背验靡。 一陣腳步聲響...
    開封第一講書人閱讀 32,846評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留雏节,地道東北人胜嗓。 一個月前我還...
    沈念sama閱讀 47,819評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像钩乍,于是被迫代替她去往敵國和親辞州。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,665評論 2 354

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