
在上一篇已經(jīng)講過著色器了,但只是簡單的介紹了著色器語言的數(shù)據(jù)類型,這里就繼續(xù)介紹著色器語言,讓你更全面的了解GLSL語言。
在前面我們已經(jīng)知道OpenGL的渲染過程,其中的頂點著色器和片段著色器都是可編程的。頂點著色器是負(fù)責(zé)應(yīng)用程序傳入的頂點數(shù)據(jù)處理,而片段著色器主要是做最后顯示的像素處理,這也說明為什么片段著色器無法直接接受頂點數(shù)據(jù)的原因。
關(guān)于著色器的基本編寫與應(yīng)用在前面的文章中已經(jīng)說過。Xcode中可以在新建文件 -> Other -> Empty保存文件名后綴為.glsl即可。
然后就是著色器源碼的運行時編譯,這個在前面也有封裝。
GLSL語法:
先可以看下上一篇的vetexShader源碼
attribute vec4 Position;
void main(void) {
gl_Position = Position;
}
比較簡單,在接受到頂點數(shù)據(jù)之后不做任何處理直接賦值給gl_Position。
而片段著色器:
uniform vec4 color;
void main(void) {
gl_FragColor = color;
}
我們定義了一個uniform屬性,相當(dāng)于全局屬性,可以從應(yīng)用程序中直接傳值。
GLSL變量聲明:
我們先看一下做過改進(jìn)的著色器
attribute vec4 position;
attribute vec4 color;
uniform float variable;
varying vec4 fColor;
void main(void) {
fColor = color;
float xPos = position.x * sin(variable);
float yPos = position.y * sin(variable);
gl_Position = vec4(xPos, yPos, position.z, 1.0);
}
先看屬性聲明:
1.頂點位置屬性:attribute是變量類型,vec4是數(shù)據(jù)類型,position是變量名
3.uniform:相當(dāng)于定義的全局變量
4.varying:傳遞給片段著色器的變量,因為片段著色器無法直接接受頂點數(shù)據(jù)。
主函數(shù)體:
1.將傳入的顏色數(shù)據(jù)color不作任何修改賦值給fColor
2.將位置變量的x值sin(change),其中change是應(yīng)用程序傳入
3.同樣將位置變量的y值sin(change)
4.賦值給gl_Position
下面再看片段著色器:
varying lowp vec4 fColor;
void main(void) {
gl_FragColor = fColor;
}
比較簡單,定義一個varying類型的4分享向量fColor以接受頂點著色器傳入的顏色數(shù)據(jù)fColor未做處理直接賦值給gl_FragColor
看一下處理的最終效果:
對于頂點著色器中的處理不難理解,把頂點坐標(biāo)的x和y乘以一個常量的正弦值,因為sin()值域在-1和1之間,所以三角形的頂點坐標(biāo)會在正負(fù)之間轉(zhuǎn)換,如果為0的話,那么就是在正中心,所以才有出現(xiàn)三角形顛倒轉(zhuǎn)換和大小的收縮。
既然可以改變頂點坐標(biāo),那么我們也可以試試改變圖形顏色,這里直接操作片段著色器即可:
precision highp float;
varying lowp vec4 fColor;
uniform float variable;
void main(void) {
// sin()的值域在[-1,1],而顏色分量值在0和1之間,所以將!sin()+1) / 2
float scale = (sin(variable) + 1.0) / 2.0;
gl_FragColor = fColor * scale;
}
第一行是指明變量的精度,在fragment shader的變量只能是uniform和varying,這里的varying是從Vertex Shader傳過來的值。與Vertex Shader不同的是,這里的變量都要聲明精度,比如 highp float processedElapsedTime = elapsedTime;中的highp代表高精度。精度包括lowp highp mediump,低精度,高精度,中等精度。如果你不想為每一個變量都指定精度可以在第一行寫上precision highp float; ,當(dāng)然這只是為float指定默認(rèn)精度highp。要為其他類型指定精度的話繼續(xù)加就好了。
在應(yīng)用程序中,我們需要新增代碼為change屬性復(fù)制:
GLuint variableLoca = glGetUniformLocation(program, "variable");
glUniform1f(variableLoca, (GLfloat)self.changeValue);
先獲取uniform highp float variable的位置,因為variable是float類型,所以使用glUniform1f進(jìn)行賦值。
最后效果如下:

需要源碼可以移步GitHub
參考《OpnGL ES編程指南》