學習資料來源:java
OpenGL ES 3.0編程指南android
OpenGL ES 2 for Android —a Quick-Start Guidec++
https://developer.android.com/guide/topics/graphics/opengl編程
上一節中學習了opengl es的大致執行過程,這一節學習一下着色器這塊內容。數組
若是要使用着色器進行渲染的時候,須要建立兩個基本對象:着色器和程序對象。着色器對象和程序對象能夠理解爲c中的編譯器和連接程序:ide
在c中將一段代碼編譯成目標代碼,在建立目標文件後,c連接程序會將對象文件連接爲最後的程序函數
着色器對象是包含的歌着色器的對象。源代碼提供給着色器對象,而後着色器對象被編譯成一個目標形式。學習
得到連接後的桌而起對象通常6個步驟:ui
注意:居於Android系統code
//GL_VERTEX_SHADER or GL_FRAGMENT_SHADER 建立對應的着色器,返回着色器句柄 int shader1= GLES30.glCreateShader(type); //刪除對應的着色器對象句柄 GLES30.glDeleteShader(shader1); //爲着色器對象提供源代碼,參數依次:shader句柄,shader代碼 GLES30.glShaderSource(shader,shaderSourceCode); //編譯着色器對象 GLES30.glCompileShader(shader);
上述描述瞭如何去建立和編譯一個着色器對象。
建立程序對象代碼以下:
//建立程序對象 mProgram = GLES30.glCreateProgram(); //與着色器進行連接,每一個程序對象須要連接一個頂點着色器和一個片斷着色器 GLES30.glAttachShader(mProgram, vertexShader); GLES30.glAttachShader(mProgram, fragmentShader); //連接程序對象 GLES30.glLinkProgram(mProgram);
上面寫好後能夠看到對應着上方的六個步驟。全部步驟完成後須要在執行以下代碼:
GLES30.glUseProgram(mProgram);
該代碼代表激活程序對象,而後就能夠渲染了。
###opengl es 着色語言
在計算機圖形中,兩個基本數據類型組成變換基礎:向量和矩陣。這兩種數據在opengl es的着色語言中也是核心(ps:學很差線性代數就流淚...)。opengl es着色語言數據類型以下:
變量分類 | 類型 | 描述 |
---|---|---|
標量 | float,int,uint,bool | 與c對應變量解釋一致 |
浮點向量 | float,vec2,vec3,vec4 | 有1,2,3,4個份量的基於浮點的向量類型 |
整數向量 | int,,ivec2,ivec3,ivec4 | 有1,2,3,4個份量的基於整數的向量類型 |
無符號向量 | uint,,uvec2,uvec3,uvec4 | 有1,2,3,4個份量的基於無符號整數的向量類型 |
布爾變量 | bool,bvec2,bvec3,bvec4 | 有1,2,3,4個份量的基於布爾值的向量類型 |
矩陣 | mat2(mat2x2底下類推),mat2x3,mat3x2,mat3,mat3x4,mat4x2,mat4x3,mat4 | 2x2,2x3,3x2,3x3,3x4,4x2,4x3,4x4的基於浮點的矩陣 |
聲明例子,與c語法相近:
float a; vec4 v; mat4 m; ivec2 iv;
標量
float mm=1.0; float mm=1;//不正確,語法很是嚴格 bool ll=true; int kk=0; int ka=0.0;//error float sd=float(ll) //轉換成float
向量
vec4 myVec4=vec4(1.0);//myVec4={1.0,1.0,1.0,1.0} vec3 myVec3=vec3(1.0,1.0,1.0); vec3 temp=vec3(myVec3);//賦值操做 vec2 myVec2=vec2(myVec3);//myVec2={1.0,1.0}即取x,y點 vec4 myVec4=vec4(myVec2,temp);//myVec4={myVec2.x,myVec2.y,temp.x,temp.y}
向量和矩陣份量
向量的單獨份量能夠用兩種方式訪問,**"."運算符號和數組下標的形式。**根據組成向量 的份量數量,每一個份量可使用{x,y,z,w}或{r,g,b,a}或者{s,t,p,q}來訪問。使用"."運算符號售後,能夠再操做中從新排列響亮的份量,如:
vec3 my3=vec3(1.0,0.0,3.0); vec3 temp; temp=my3.xyz;//(1.0,0.0,3.0) temp=my3.yzx;//(0.0,3.0,1.0)
矩陣有向量組成,如mat2能夠當作兩個vec2等,例子:
mat4 m=mat4(1.0); vec4 v4=m[0]; float k=mat4[0][1];
常量
const float zrto=0.0;
結構體
struct ff{ vec4 volor; float end; } fo; //初始化能夠跟c相同,也能夠以下 fo=ff(vec4(0.0,0.0,0.0,0.0),4.0);
數組
float fl[4]; vec4 vec[2];
函數
函數聲明跟c語言的相同,惟一不一樣在於函數參數的傳遞方法,opengl es有特殊的限定符,定義函數是否能夠修改可變參數:
限定符 | 描述 |
---|---|
in | 指定參數按值傳送,函數不能修改 |
inout | 規定變量按引用傳入函數,若是該值被修改,他將在函數退出後變化 |
out | 表示該變量不被傳入函數,但在函數返回時候被修改 |
關於opengl es着色語言中的函數還要注意一點,**函數不能遞歸。**這一限制的緣由是某些實現經過吧函數代碼真正內嵌到GPU生成的最終程序實施函數調用。着色語言有意構造這種內嵌式實現,以支持沒有堆棧的GPU。
頂點着色器的輸入和輸出
定點輸入變量用於指定頂點着色器中每一個頂點的輸入,用in關鍵字指定。他們一般存儲位置,發現,紋理座標和顏色這樣的數據。(能夠理解爲從咱們程序中寫的代碼中去讀取對應變量的值)
in vec4 a_Position; in vec3 a_color; out vec3 v_color; void main()[ v_color=a_color; ]
這個着色器的兩個頂點輸入變量a_position和a_color的數據由應用程序加載。相對應的有in就有out,out表明着來自頂點着色器的輸出變量。基本上來講,從頂點着色器out的值由片斷着色器接收,這些out出去的變量在片斷着色器中會經過in的形式進行接收。
控制流語句(if else)跟c同樣,不展開。