在OpenGL 3.0之前漓拾,OpenGL 使用的是固定渲染管線乌企,使用存儲著色器完成渲染虑润,存儲著色器就是寫好了著色程序,直接修改參數(shù)加酵,調(diào)用API就可以滿足渲染拳喻,而3.1版本以后哭当,我們可以通過 GLSL(OpenGL Shading Langruage)自定義著色程序(主要是頂點著色器和片元著色器程序)來完成渲染。
在OpenGL ES中冗澈,我們就是通過使用GLSL來自己編寫著色器的钦勘,所以接下來介紹下GLSL基礎知識。
簡介
GLSL作為一種著色器編寫語言是純粹和GPU打交道的計算機語言渗柿。
圖中Client通過三種方式向server發(fā)送數(shù)據(jù)
- Attributes个盆,屬性以向量傳遞數(shù)據(jù),屬性只有向頂點著色器傳遞才有意義朵栖。
- Uniforms,Uniforms可以在頂點著色器和片元著色器使用柴梆,Uniforms只能使用不可以修改陨溅。
- Texture Data,可以在頂點著色器和片元著色器使用绍在。
最常見用法是在頂點著色器里生成所需要的值门扇,然后傳給片元著色器用。
需要注意的是:
- GLSL支持函數(shù)重載偿渡。
- GLSL不能自動提升數(shù)據(jù)類型臼寄,所以類型必須嚴格保持一致。
float f = 2.3;
bool b = bool(f); // b is true
- GLSL沒有指針溜宽,字符串吉拳,字符,它基本上是一種處理數(shù)字數(shù)據(jù)的語言适揉。
- GLSL不支持聯(lián)合留攒、枚舉類型、結(jié)構(gòu)體位字段及按位運算符嫉嘀。
數(shù)據(jù)類型
- 標量
GLSL有三種標量基本數(shù)據(jù)類型:float炼邀,int和bool。
- 向量數(shù)據(jù)類型
vec3 v; //聲明三維浮點型向量v
v[1]=3.0; //給向量v的第二個元素賦值
// 下面兩種等價
vec3 v = vec3(0.6);
vec3 v = vec3(0.6, 0.6, 0.6);
另外剪侮,可以用選擇運算符的方式來使用向量拭宁。選擇運算符是對于向量的各個元素(最多為4個)約定俗成的名稱,用一個小寫拉丁字母來表示:
- 頂點 (x瓣俯、y杰标、z、w)
- 顏色 (r降铸、g在旱、b、a)
- 紋理 (s推掸、t桶蝎、r驻仅、q)
vec4 v1=vec4(1.0, 2.0, 3.0, 4.0); //四維浮點型向量
vec4 v2;
v2.xy=v1.yz; //將v1的第二個和第三個元素復制到v2的第一個和第二個元素
v2.z=2.0; //給v2的第三個元素賦值
v2.xy=v1.yx; //將v1的頭兩個元素互換登渣,再復制到v2的頭兩個元素中
- 矩陣數(shù)據(jù)類型
mat4 m; //聲明四維浮點型方陣m
m[2][3]=2.0; //給方陣的第三列噪服、第四行元素賦值
// 下面兩種等價,初始化矩陣對角
mat2 m = mat2(1.0)
mat2 m = mat2(1.0, 0.0, 0.0, 1.0);
- 取樣器(Sampler)
sampler1D 訪問一個一維紋理
sampler2D 訪問一個二維紋理
sampler3D 訪問一個三維紋理
samplerCube 訪問一個立方貼圖紋理
sampler1DShadow 訪問一個帶對比的一維深度紋理
sampler2DShadow 訪問一個帶對比的二維深度紋理
uniform sampler2D grass;
vcc2 coord = vec2(100, 100);
vec4 color = texture2D(grass, coord);
如果一個著色器要在程序里結(jié)合多個紋理胜茧,可以使用取樣器數(shù)組:
const int tex_nums = 4;
uniform sampler2D textures[tex_nums];
for(int i = 0; i < tex_nums; ++i) {
sampler2D tex = textures[i];
// todo ...
}
- 結(jié)構(gòu)體
struct light
{
vec3 position;
vec3 color;
};
light ceiling_light;
- 數(shù)組
數(shù)組索引是從0開始的粘优,而且沒有指針概念
// 創(chuàng)建一個10個元素的數(shù)組
vec4 points[10];
// 創(chuàng)建一個不指定大小的數(shù)組
vec4 points[];
points[2] = vec4(1.0); // points現(xiàn)在大小為3
points[7] = vec4(2.0); // points現(xiàn)在大小為8
void
限定符
常用的限定符有:
const,和C++里差不多呻顽,定義不可變常量雹顺,表示限定的變量在編譯時不可被修 改。
attribute廊遍,該限定符標記的是一種全局變量,該變量在頂點著色器中是只讀(read-only)的嬉愧,該變量被用作從OpenGL應用程序向頂點著色器中傳遞參數(shù),因此該限定符僅能用于頂點著色器喉前,例如頂點坐標没酣、顏色,法線卵迂,紋理坐標裕便。
attribute vec4 position;
attribute vec2 textureCoord0;//紋理坐標
- uniform,一般是外部應用程序傳給頂點著色器和片斷著色器见咒,也是一種全局變量,該變量對于一個圖元(primitive)來說是不可更改的偿衰,它可以從OpenGL應用程序中接收傳遞來的參數(shù),例如:
uniform mat4 viewProjectMatix;
uniform mat4 viewMatix;
uniform vec3 lightPosition;
- varying论颅,用于傳遞頂點著色器的值給片元著色器哎垦,它提供了從頂點著色器向片元著色器傳遞數(shù)據(jù)的方法,varying限定符可以在頂點著色器中定義變量恃疯,然后再傳遞給光柵化器漏设,光柵化器對數(shù)據(jù)插值后,再將每個片段的值交給片元著色器今妄,注意在頂點著色器定義的變量名要跟片元著色器中接收的變量名一樣郑口。
varying vec2 textureCoord0;
混合操作
通過在選擇器(.)后列出各分量名,就可以選擇這些分量
vec4 v4;
v4.rgba; // 得到vec4
v4.rgb; // 得到vec3
v4.b; // 得到float
v4.xy; // 得到vec2
v4.xgba; // 錯誤盾鳞!分量名不是同一類
v4.wxyz; // 打亂原有分量順序
v4.xxyy; // 重復分量