OpenGL ES 2.0學習(一)入門知識點

啊森弟發表於2018-08-30

前言

一個多月前開始學習Android OpenGL ES,起初是因為需要做濾鏡,然後慢慢發現很有趣。但是自己感覺學起來並沒有想象那麼容易,主要涉及太多的轉換,還有著色器語言等,但它確實強大,可以做一些濾鏡,很炫的3D效果/全景等。目前自己還處於入門階段。

OpenGL ES

  • OpenGL ES 為OpenGL嵌入式系統,是一個適用於嵌入式系統的二維或者三維的圖形庫
  • 是桌面版OpenGL的一個子集

OpenGL ES管道

  • 管道工序大致可以分為Transformation Stage 和Rasterization Stage兩大步
  • 支援的基本圖形為點、線、三角形,其他複雜圖形都是通過這幾種基本幾何圖形組合成的
  • 發出繪圖指令後,會對頂點陣列進行指定的座標變換或光照處理
  • 頂點處理完之後,通過Rasterizer(光柵化,也可以叫做畫素化)來生成畫素資訊,成為“Fragments”
  • 對於Fragment在經過Texture Processing,Color Sum,Fog等處理並將最終結果存放到記憶體中

EGL

  • Display:實際顯示裝置的抽象
  • Surface:用來儲存影象的記憶體區域FrameBuffer的抽象
  • Context:儲存OpenGL ES的一些狀態資訊

著色器

  • 頂點著色器:對每個頂點進行操作,操作結果用於片段著色器

在main函式中必須設定gl_Position全域性變數,將作為Vertex的最終位置,進而把Vertex組合成點、線、三角形

  • 片段著色器:確定每個Fragment的顏色

在main函式必須設定gl_FragColor全域性變數,它將作為Fragment的最終顏色。

光柵化:把點、線、三角形對映到螢幕上的畫素點的過程,也就是生成Fragment的過程。通常一個Fragment對應於螢幕上的一個畫素,但在高解析度可能會有多個畫素點對映到一個Fragment中

座標系

  • Local Space:每個物體建立好模型的時候,它們的座標就是Local Space
  • World Space:進行合理的移動、排布,最終各自的座標就是World Space座標
  • Model Matrix:把Local Space轉變到World Space時所用的矩陣
  • View Space:是從觀察者的角度出發,所看到的空間
  • View Matrix:把World Space轉變到View Space座標所用的變換矩陣,相當於是在移動相機的位置,實際上是反方向移動整個場景
  • Clip space:OpenGL 只會渲染在[-1,1]範圍內的內容,超出這個範圍就會被裁剪。
  • Projection matrix:把View Space轉換到Clip Space座標所用的變換矩陣,指定可見範圍;它有三種建立方式:正投影,透視投影,以及3D投影。
  • Screen Space:螢幕上的空間,glViewport呼叫指定的區域。
  • Viewport transform:OpenGL自動完成的。將ClipSpace轉換到ScreenSpace上
  • 紋理座標系:OpenGL的紋理座標系是二維座標系,原點在左下角,x/y的取值範圍在[0,1];計算機中圖片的y軸是向下的,也就是向下的是正方向

投影變換

投影可以看作是一種將三維座標變換為二維座標的方法

  • 正交投影
    Matrix.orthoM函式來完成正交投影的設定
Matrix.orthoM(
    mProjMatrix,//用於存放生成矩陣元素的float[]型陣列
    0,          //填充起始偏移量
    left,right, //near面的left、right
    bottom,top, //near面的bottom、top
    near,far    //near面和far面與視點的距離
)
  • 透視投影

在3D世界中,物體離相機越遠看起來越小,這個現象叫做透視。

透視是通過投影矩陣變換,改變每一個向量中W分量的值來實現透視的。

透視除法:將齊次座標中的W分量轉換為1

  1. 透視投影使用稜錐作為視錐體,攝像頭位於稜錐的錐頂。該稜錐被前後兩個平面截斷,形成一個稜臺。
  2. 透視投影的目的就是將上述的稜臺轉換為一個立方體轉換後,稜臺的前剪裁平面的右上角點變為立方體的前平面的中心
  3. 透視投影的投影線是不平行的,它們相交於視點。
  4. Matrix.frustumM()方法完成透視投影的設定。
Matrix.frustumM(
    mProjMatrix,
    0,
    left,right,
    bottom,top, 
    near,far    //near面與far面與視點的距離
)

著色器語言

資料型別

標量
- 布林型——bool
- 整型——int
- 浮點型——float(可以不加字尾f來說明型別)

向量
- vec2、vec3、vec4:包含x個浮點數的向量
- ivec2、ivec3、ivec4:包含x個整數的個數
- bvec2、bvec3、bvec4:包含x個布林數的向量
- 訪問向量中的某個分量:<向量名>.<分量名>
- 將一個向量看作是顏色時,可以使用rgba四個分量,如aColor.r、aColor.g等
- 將一個向量看作是位置時,可以使用xyzw四個分量,分別代表xyz軸和向量的模。
- 將一個向量看作是紋理座標時,可以使用stpq等四個分量
- 訪問向量中的各個分量不僅可以使用 . 加上不同的分量名,還可以將向量看作一個陣列

矩陣
- mat2、mat3、mat4:代表n x n的浮點矩陣
- 一個矩陣可以看作由幾個列向量組成,它是按列組織順序的

取樣器
- sampler2D:用於訪問二維紋理
- sampler3D:用於訪問三維紋理
- sampler4D:用於訪問立方貼圖紋理
- 取樣器變數不能在著色器中初始化,一般情況下采用uniform限定符來修飾

結構體
與c類似

struct info{
    vec3 color;
    vec3 position;
    vec2 textureCoor;
}

陣列
- 在宣告的同時,指定陣列的大小:vec3 position[20];
- 在宣告時,不指定陣列的大小:vec3 postion[];訪問陣列時,編譯器會自動建立適當大小的陣列。

空型別
- 使用void,僅用來宣告不返回任何值的函式

型別的基本使用

  • 使用者自定的變數不允許以gl_開頭
  • 屬性變數、一致變數以及易變變數不能在宣告的時候進行初始化
attribute float as;
uniform int k;
varying vec3 position;

型別轉換

  • 沒有提供自動向上轉型機制,而且在型別轉換時很嚴格;
  • 也沒有提供型別強制轉換功能,只能使用建構函式來進行型別轉換:bool b=bool(1); 錯誤的語法:float f=1;
  • 賦值表示式兩邊的型別要一致,呼叫引數時的引數以及實參型別必須一致。

限定符

  • attribute:一般用於每個頂點都各不相同的量,比如頂點位置、顏色

    其修飾的變數用來接收渲染管線傳遞進頂點著色器的當前待處理頂點的各種屬性值。這些屬性值用於描述頂點的各項特徵。

    用限定符attribute修飾的變數其值是由宿主程式批量傳入渲染管線的,管線進行基本的操作後再傳遞給頂點著色器。

    attribute限定符只能用於頂點著色器中,不能在片元著色器中使用。
    對應的方法:

    maPositionHandle = GLES20.glGetAttribLocation(mProgram, "aPosition");
    //將頂點位置資料傳進渲染管線中
    GLES20.glVertexAttribPointer(maPositionHandle, 3,
                GLES20.GL_FLOAT, false, 3 * 4, mVertextBuffer);
  • uniform:
    外部application程式傳遞給著色器的變數。shader只能用,不能修改

    一般用於同一組頂點組成的單個3D物體中所有頂點都相同的量,如當前的光源位置。

    一致變數限定符,指定是同一組頂點組成的單個3D物體中所有頂點的相同的量。

uniform mat4 viewProjMatrix; //投影+檢視矩陣
uniform mat4 viewMatrix;        //檢視矩陣
uniform vec3 lightPosition;     //光源位置

可以用在頂點著色器或片元著色器。也是從宿主程式傳入的(Java程式)

對應的方法:

muMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix"); 
GLES20.glUniformMatrix4fv(muMVPMatrixHandle, 1, false, Triangle.getFinalMatrix(mMMatrix), 0);

GLES20.glUniformNf();//將N個浮點數傳進管線
GLES20.glUniformNi();//將N個整數傳進線
GLES20.glUniformMatrixNfv();//將N x N的矩陣傳入管線
  • varying:用於從頂點著色器傳遞到片元著色器的量,光柵化後產生多少個片元,就會插值計算出多少套易變變數。同時,渲染管線就會呼叫多少次片元著色器。
  • const:用於宣告常量,編譯時常量。

函式宣告

<返回型別> 函式名稱([<引數列表>]){/函式體/}

引數列表中的引數除了可以指定型別外,還可以指定用途。

  • in修飾符:用其修飾的引數為輸入引數,進供函式接收外界傳入的值。若某個引數沒有給出明確的修飾符,則等同於使用in修飾符
  • out修飾符:其修飾的引數為輸入引數,在函式體中對輸出引數賦值可以將值傳遞到呼叫其的外部變數中。注意不可傳進字面常量。
  • inout:用其修飾的引數為輸入輸出引數,具有輸入與輸出兩種功能。

    片元著色器中浮點變數精度的指定

    • lowp float color、varying mediump vec2 Coord、height mat4 m
    • 代表低中高,一般選用mediump即可
    • precision <精度><型別>:整個著色器中浮點相關型別預設的精度。

內建變數

  • 輸入變數:負責將渲染管線中固定功能部分產生的資訊傳遞給著色器。
  • 輸出變數:負責將著色器產生的資訊傳遞給渲染管線中固定功能部分
  • 頂點著色器中的內建變數:主要是輸出變數
    1. gl_Position:從應用程式獲得原始的頂點位置資料
    2. gl_Size:一個點的大小(單位為畫素)
  • 片元著色器的內建變數
    輸入變數:
    • gl_FragCoord:當前片元相對於視窗位置的座標值x、y、z與1/w
    • gl_FrontFacing:是一個bool值,通過讀取該內建變數的值可以判斷正在處理的片元是否屬於在光柵化階段生成此片元對應圖元的正面
      輸出變數:
      1. gl_FragColor:由片元著色器寫入計算完成的片元顏色,此顏色將送入渲染管線的後繼階段進行處理。
      2. gl_Data:是一個vec4的型別陣列,寫入時要給出下標,通過寫入的資訊將供渲染管線中的後繼過程使用。

相關文章