OpenGLES Android篇零基礎系列(二):OpenGL各座標系及模型矩陣(ModelViewMatrix),投影矩陣(ProjectionMatrix)等的深入理解

上一篇我們粗略的介紹了下GLES20 中 GLSurfaceView以及Render接口的使用。
對於三角形頂點座標的定義並沒有做出註釋,其實在官方的ApiDemo中,它也是赤裸裸的,一個註釋都沒有,且代碼寫得一點都不敢恭維,不知道那位同行現在是不是還在google裏面。下面貼出一小段官方的ApiDemo中的代碼,一起鑑賞鑑賞:

 private static final int FLOAT_SIZE_BYTES = 4;
    private static final int TRIANGLE_VERTICES_DATA_STRIDE_BYTES = 5 * FLOAT_SIZE_BYTES;
    private static final int TRIANGLE_VERTICES_DATA_POS_OFFSET = 0;
    private static final int TRIANGLE_VERTICES_DATA_UV_OFFSET = 3;
 private final float[] mTriangleVerticesData = {
            // X, Y, Z, U, V
            -1.0f, -0.5f, 0, 0.0f, 0.5f,
            1.0f, -0.5f, 0, 1.0f, 0.5f,
            0.0f,  1.0f, 0, 0.0f,  1.0f };

如上,你們能看懂嗎?在定義三角形頂點座標數據時,僅僅只是簡單粗暴的註釋X,Y,Z,U,V,其中X,Y,Z好理解,可這U,V又是什麼呢?X,Y,Z,U,V它們之間又有什麼聯繫呢?

如果僅僅只是想從ApiDemo裏面去研究,去搞懂它們是什麼,怎麼用,那估計不是一天兩天的事,還得從浩瀚的網絡中去查找。

正文:座標系

OpenGL有6種座標系,分別如下:

  • 1,物體或模型座標系(Object or model coordinates);
  • 2,世界座標系(World coordinates)
  • 3,眼座標或相機座標(Eye (or Camera) coordinates)
  • 4,裁剪座標系(Clip coordinates)
  • 5,標準設備座標系(Normalized device coordinates)
  • 6,屏幕座標系(Window (or screen) coordinates)
    除了上面6種外,OpenGL還存在一種假想座標系紋理座標系,這個座標系是不存在的,它其實是一系列變換矩陣的結果,比如它能使頂點從物體或模型座標系變換到世界座標系

從object coordainates到world coordinates再到camera coordinate的變換,在OpenGL中統一稱爲model-view轉換,初始化的時候,object coordinates和world coordinates還有camera coordinates座標重合在原點,變換矩陣都爲Identity,所以在OpenGL中用glLoadIdentity()初始化變換矩陣棧。model-view matix轉換points,vectorsd到camera座標系。

OpenGL 的重要功能之一就是將三維的世界座標經過變換、投影等計算,最終算出它在顯示設備上對應的位置,這個位置就稱爲設備座標。在屏幕、打印機等設備上的座標是二維座標。值得一提的是,OpenGL可以只使用設備的一部分進行繪製,這個部分稱爲視區或視口(viewport)。投影得到的是視區內的座標(投影座標),從投影座標到設備座標的計算過程就是設備變換了。

我們在OpenGL ES中常用到的幾種座標系:世界座標系、物體座標系、設備座標系、眼座標系當然還有假想的紋理座標系

一、屏幕座標系

對於移動設備來說,我們都知道,左上角爲座標原點,向右爲X軸,向下爲Y軸。如下圖(圖畫的醜了點,先忍忍啊^_^):
這裏寫圖片描述

二、世界座標系

這個世界座標系是針對OpenGL來說明的。即三維座標系X,Y,Z.
它有一個漂亮的學名:右手笛卡爾座標系統,這個座標系常用來描述物體及光源的位置。
在移動設備中,屏幕中心爲座標三點,水平向右爲X軸,在原點垂直X軸向上爲Y軸,在原點垂直X,Y軸指向屏幕外爲Z軸(正面對手機屏幕,直戳你眼睛的就是Z軸),同樣如下圖:
這裏寫圖片描述

將物體放到場景中也就是將物體平移到特定位置、旋轉一定角度,這些操作就是座標變換。OpenGL中提供了glTranslate*/glRotate*/glScale*三條座標變換命令,利用OpenGL的矩陣運算命令,則可以實現任意複雜的座標變換。
在這裏還要提一個重要的概念:座標變換矩陣棧(ModelView)

座標變換矩陣棧

用來存儲一系列的變換矩陣,棧頂就是當前座標的變換矩陣,進入OpenGL管道的每個座標(齊次座標)都會先乘上這個矩陣,結果纔是對應點在場景中的世界座標。OpenGL中的座標變換都是通過矩陣運算完成的。
如圖:
這裏寫圖片描述
ModelViewMatrix:模型矩陣
ProjectionMatrix:投影矩陣

三、紋理座標系

通過上一節,我們知道,紋理是圖片,視頻等的一種渲染方式,圖片只有通過紋理才能加載到GLES中。
因此紋理座標系是指圖片,視頻等在手機屏幕上的座標系,即U,V也有叫ST。該座標系是一種假想座標系,並不真正存在的,只是變換矩陣的結果。下面就統一叫UV座標系。
當應用初始化時,UV座標系與三維座標系(世界座標系)重合。
我們要注意的是,在OpenGL繪製過程中,它是可以選擇繪製模式的,比如:點,線,面,且都是座標集合裏面進行順序繪製的。i.e.:

private final float[] mTriangleVerticesData = {
            // X, Y, Z,
            -1.0f, -0.5f, 0, //1
            1.0f, -0.5f, 0, //2
            0.0f,  1.0f, 0, //3
             };

當我們以紋理的形式加載一個圖片到OpenGL中時,如何讓它顯示在世界座標系中呢?這時就用到了紋理貼圖的方式(即根據在世界座標系中繪製頂點的先後順序,把UV座標系中的座標與其一一對應),畫圖更加直接(從網上copy的圖,在此感謝):

倒立的圖片

四、物體座標系

物體座標系是以物體的某一個點爲原點來建立的三維座標系(世界座標系)。僅針對該物體。物體放到場景中時,各部分經歷的座標變換矩陣相同,相對位置不變,所以可視爲一個整體

五、眼座標系或相機座標系

以視點爲原點,以視線的方向爲Z+軸正方向的座標系中的方向。OpenGL管道會將世界座標先變換到眼座標,然後進行裁剪,只有在視線範圍(視見體)之內的場景纔會進入下一階段的計算。

六、裁剪座標系

由眼座標可知,OpenGL管道首先會將目標從世界座標變換到眼座標,然後對視線範圍外的部分進行裁剪。
裁剪過程中用到投影變換矩陣棧(ProjectionMatrix),棧頂矩陣就是當前投影變換矩陣,負責將場景各座標變換到眼座標,由所得到的結果是裁剪後的場景部分,稱爲裁剪座標

我們上面說到了ModelViewMatrix 與ProjectionMatrix兩個矩陣棧,那矩陣棧是怎麼切換的呢?
用函數:glMatrixMode(GL_MODELVIEWING或GL_PROJECTION);本命令執行後參數所指矩陣棧就成爲當前矩陣棧,以後的矩陣棧操縱命令將作用於它。
緊接着glMatrixMode()就是初始化矩陣,我們在上面也講到,所有矩陣都爲Identity,所以用方法glLoadIdentity()初始化矩陣。

上一節

參考資料

OpenGL座標系介紹
OpenGL中各種座標系的理解
Android OpenGL20 世界座標系,屏幕座標系,紋理座標系
Android OpenGL 座標系
詳解OpenGL的座標系、投影和幾何變換-矩陣壓棧思想/矩陣列式存儲
OpenGL 矩陣變換(講的太好了~!)

發佈了73 篇原創文章 · 獲贊 26 · 訪問量 16萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章