序言
最近筆者剛學習到OpenGLES,在這里也對所學的知識做一個總結(jié),有不對的地方,希望大佬們拍板!
OpenGLES
在這里既然是學習OpengGLES,相信很多人會有疑問,什么是OpenGLES ? 筆者在這里先賣一個關子。細心的應該發(fā)現(xiàn)了,OpengGLES 和OpenGL簡直太像了,難道他們有什么關系嘛?是的,OpenGL是一種應用程序編程接口,它是一種可以對圖形硬件設備特性進行訪問的軟件庫。而且它也是跨平臺的?,F(xiàn)在的主要應用領域:視頻 圖形圖片處理,2D/3D游戲引擎開發(fā),科學可視化,醫(yī)學軟件的開發(fā),CAD(計算機輔助技術),虛擬實境(AR VR),AI人工智能。那OpenGLES是什么呢?OpenGL ES是OpenGL的子集,針對手機、PDA和游戲主機嵌入式設備而設計。筆者理解的就比較簡單了——OpenGL包太大了,當運用到移動平臺太消耗運行,有些又不實用,就把里面比較有用的提取出來,就誕生了OpenGLES
著色語言(Shader)
著色器(Shader)是運行在GPU上的小程序,從基本意義上來說,著色器只是一種把輸入轉(zhuǎn)化為輸出的程序。現(xiàn)在我們會用一種更加廣泛的形式詳細解釋著色器,特別是OpenGL著色器語言(GLSL)。
GLSL
著色器是使用一種叫GLSL的類C語言寫成的。GLSL是為圖形計算量身定制的,它包含一些針對向量和矩陣操作的有用特性。
數(shù)據(jù)類型
既然是一門自己的編程語言,肯定有一些自己的規(guī)范。GLSL中包含C等其他語言,大部門的基礎數(shù)據(jù)類型為:int、float、double、Uint、bool。在GLSL也有二種容器類型,在實際運用中會使用很多,分別是向量(Vector)和矩陣(Matrix)
向量
這個筆者第一次接觸在高中,沒想到在這里也會運用到,哈哈。GLSL中的向量可以包含1、2、3、4個分量的容器,分量分量的類型可以是基本類型的一個
類型????????????含義
vecn?????????包含 n 個float分量的默認向量
bvecn????????包含 n 個bool分量的向量
ivecn????????包含 n 個int分量的向量
uvecn????????包含 n 個unsigned int分量的向量
dvecn????????包含 n 個double分量的向量
在一個向量的分量中,你可以通過 vec.x 這種方式獲取,這里 x 是指這個向量的第一個分量。比如在4向量中(位置、顏色),可以通過 .x、.y、.z、.w(齊次坐標)、.r、.g...等來獲取響應的分量的值。當然你也可以通過4個任意字母任意組合,創(chuàng)建一個自己想要的向量
vec4 vect = vec4(0.5f, 0.7f,1.0f,2.0f);頂點著色器
頂點著色器(vertex?shader)提供頂點操作的通用可編程方法.執(zhí)行頂點變換、紋理坐標變換、光照、材質(zhì)等相關操作。這里就很靈活了,開發(fā)者可以根據(jù)自己的需求進行開發(fā)
uniform mat4 uMVPMatrix;???????? //總變換矩陣
attribute vec3 aPosition;????????//位置
attribute vec2 aTexCoor;?????????//紋理
varying vec2 vTextureCoord;??????//傳入片元著色器紋理值
void main()
{ ??? ?gl_Position = uMVPMatrix * vec4(aPosition,1);
????????vTextureCoord = aTexCoor;
}

在頂點著色器中我們能夠看到三個變量uniform、attribute、varying:
uniform:該變量是外部應用程序傳遞給頂點著色器和片元著色器的變量.
該變量一般用來表示:變換矩陣,材質(zhì),光照參數(shù)和顏色等信息。
attribute:該變量只能在頂點著色器中使用,不能在片元著色器中使用。一般用來表示矩陣、光照參數(shù)、紋理采樣器等。
varying:變量是從頂點著色器傳遞到片元著色器的數(shù)據(jù)變量。在此需要注意的是,在頂點著色器中和片元著色器中必須相同。(說白了就是在頂點著色器中得到變換的值,傳給片元著色器)
片元著色器
片元著色器(fragment shader)實現(xiàn)了一個通用的可編程操作片段的方法。此片元著色器的主要功能為根據(jù)接收的記錄片元紋理坐標的易變變量中的紋理坐標,調(diào)用texture2D內(nèi)建函數(shù)從采樣器中進行紋理采樣,得到此片元的顏色值。最后,將采樣到的顏色值傳給gl_FragColor內(nèi)建變量,完成片元的著色。
precision mediump float;
varying vec2 vTextureCoord; ????????????????????//從頂點接收的紋理值
uniform sampler2D sTexture; //采樣器
void main(){
????????gl_FragColor= texture2D(sTexture, //采樣器:對紋理進行采樣的
???????????????????????????????vTextureCoord); //紋理坐標
}
在這段代碼中,最后將通過采樣器將值傳給gl_FragColor內(nèi)建變量中。片元著色器可執(zhí)行紋理的訪問、顏色的匯總、霧等操作。

在上面的頂點著色器中,相信很多小伙伴會發(fā)現(xiàn)一遍變量gl_Position 和gl_FragColor,沒有聲明就在使用,肯定很困惑。筆者剛開始學也一樣,下面給大家分析
內(nèi)建變量
就是在OpenGL ES中內(nèi)部定義的量(筆者是這樣理解的),內(nèi)建變量分為二種:頂點著色器中的變量和片元著色器中的變量。著色器通過內(nèi)建變量同這些固定功能進行通信,內(nèi)建變量具有全局作用域。
頂點著色器
頂點著色器中有gl_Position,gl_PointSize等
gl_Position :只能用在頂點著色器中,在正常的頂點著色器中,都應該給該變量傳一個值,可以在運行時傳入一個新值,也可以讀取他的值,這個值可以用在頂點處理開始之后的圖元裝配,剪裁,剔除和其他操作圖元的固定功能上。如果頂點著色器已經(jīng)執(zhí)行,但是并沒有寫入gl_Position,那么gl_Position的值是未定義的。
gl_PointSize :只能用在頂點語言中,頂點著色器用它來寫入將要光柵化的點的尺寸,單位是像素。
片元著色器
片元著色器中有gl_FragColor、gl_FragData、gl_FragCoord、gl_FrontFacing、gl_PointCoord等
在介紹片元著色器之前先介紹一個關鍵字discard,這個關鍵字當執(zhí)行時,會discard命令會導致丟棄片元(這個筆者也沒用過,只是知道)
gl_FragColor:片元著色器中的可寫變量,為了指明隨后固定功能管線要用到的片元顏色值
gl_FragData:片元著色器中的可寫變量,變量值是一個數(shù)組。gl_FragData[n]寫入數(shù)據(jù)時為了指明后續(xù)固定功能管線要使用的片元數(shù)據(jù)n。
如果著色器靜態(tài)地給gl_FragColor賦值,那么它就不會給gl_FragData的任何元素賦值。如果著色器靜態(tài)地給gl_FragData的任何元素賦值,那么它就不會給gl_FragColor賦值。也就是說,著色器不會同時給gl_FragColor和gl_FragData變量都賦值。
gl_FragCoord:片元著色器中的只讀變量,它保存了片元相對窗口的坐標位置:x, y, z, 1/w。這個值是頂點處理產(chǎn)生片元后固定功能內(nèi)插圖元的結(jié)果。
gl_FrontFacing:片元著色器的內(nèi)建只讀變量,如果片元屬于一個當前圖元,那么這個值就為true。這個變量的一個用法就是來模擬兩面光,通過選擇由頂點著色器計算的兩個顏色中的一個。
?gl_PointCoord:片元著色器的內(nèi)建只讀變量,它的值是當前片元所在點圖元的二維坐標。點的范圍是0.0到1.0。如果當前的圖元不是一個點,那么從gl_PointCoord讀出的值是未定義的。
講到這里,相信小伙伴對著色器有初始的認識了。在最后,筆者給講解一下著色器整個的渲染過程,為方便小伙伴更好的理解
可編程管線的編程階段(著色器運行流程)
1.頂點數(shù)據(jù):這里就是基本的頂點數(shù)據(jù)
2.頂點著色器:接收頂點數(shù)據(jù),單獨處理每個頂點
3.細分著色器:描述物體的形狀,在管線中生成新的幾何體,處理(平順)模型,生成最終狀態(tài)。在細分著色器中分為二步:細分控制著色器和細分計算著色器
4.幾何著色器:對所有的圖像進行修改,改變幾何圖元的類型,或者放棄掉所有的圖元
5.圖元設置:是圖形軟件包中用來描述各種圖形元素的函數(shù),對圖形函數(shù)的操作
6.裁剪:裁剪掉視口之外的繪制
7.光柵化:將輸入圖元的數(shù)學描述,轉(zhuǎn)換為與屏幕位置對應的像素片元(實際位置坐標轉(zhuǎn)化為圖像的過程)
8.片元著色器:片元顏色以及深度值,然后傳遞到片元測試和混合模板
9.效果