前言
作為一個開發(fā)者,有一個學(xué)習(xí)的氛圍跟一個交流圈子特別重要這是一個我的iOS交流群:776598941衙耕,不管你是小白還是大牛歡迎入駐 瀑凝,分享BAT,阿里面試題、面試經(jīng)驗臭杰,討論技術(shù), 大家一起交流學(xué)習(xí)成長谚中!
最近在研究OpenGL 被各種陌生的名詞虐成狗,所以記錄下來一些學(xué)習(xí)知識點供學(xué)習(xí)和參考.
GLSL(OpenGL Shading Language) 是OpenGL的著色器語言,純粹的和GPU打交道的計算機語言.可以理解為C的變種專門針對OpenGL編程,不支持指針等等一些C的特性等. (名詞解釋:著色器(Shader))
GPU是多線程并行處理器渴杆,GLSL直接面向單指令流多數(shù)據(jù)流(SIMD)模型的多線程計算。
GLSL編寫的著色器函數(shù)是對每個數(shù)據(jù)同時執(zhí)行的宪塔。
每個頂點都會由頂點著色器中的算法處理磁奖,每個像素也都會由?片段著色器(也有叫片元著色器)中的算法處理。
初學(xué)者在編寫自己的著色器時某筐,需要考慮到SIMD的并發(fā)特性比搭,并用并行計算的思路來思考問題 這就是GLSL.
我們最常見的用法是在?頂點著色器里生成所需要的值,然后傳給?片斷著色器用.
日以逼真的材質(zhì) – 金屬南誊,巖石身诺,木頭,油漆等
日益逼真的光照效果 – 區(qū)域光和軟陰影
非現(xiàn)實材質(zhì) – 美術(shù)效果抄囚,鋼筆畫霉赡,水墨畫和對插畫技術(shù)的模擬
針對紋理內(nèi)存的新用途
更少的紋理訪問
圖形處理 – 選擇,邊緣鈍化遮蔽和復(fù)雜混合
動畫效果 – 關(guān)鍵幀插值幔托,粒子系統(tǒng)
用戶可編程的反走樣方法
GLSL支持函數(shù)重載(就是父類定義方法,子類復(fù)寫該方法叫重載)
GLSL不存在數(shù)據(jù)類型的自動提升(就是不支持類型自動向上轉(zhuǎn)換 eg:float 轉(zhuǎn) double)穴亏,類型必須嚴(yán)格保持一致.
GLSL不支持指針,字符串重挑,字符嗓化,它基本上是一種處理數(shù)字?jǐn)?shù)據(jù)的語言
GLSL不支持聯(lián)合(union)、枚舉類型(enum)谬哀、結(jié)構(gòu)體(stuct)位字段(>> or << 左右移)及按位運算符(| or &這種按位與)(就是干掉麻煩的C操作 讓這個更單純的處理圖形數(shù)據(jù)使用)
GLSL有三種基本數(shù)據(jù)類型:
float
int
double
由float刺覆、int、double組成的array[]或者結(jié)構(gòu)體
42// 十進(jìn)制?
042// 八進(jìn)制?
0x2A// 十六進(jìn)制
注意:GLSL不支持指針,GLSL把向量和矩陣作為基本數(shù)據(jù)類型
向量(vector):有起始位置有方向的線段,也稱作?矢量(不要被這些名詞嚇到,我記得這個向量是我高二的時候數(shù)學(xué)學(xué)的東西).
矢量可以和標(biāo)量甚至矩陣做加減乘除(必須遵守一定規(guī)則才可以 否則報錯)
vec2,? vec3,? vec4? //包含2/3/4個浮點數(shù)的矢量(浮點型)
ivec2, ivec3, ivec4 //包含2/3/4個整數(shù)的矢量(整形數(shù) 前邊帶i 代表integer)
bvec2, bvec3, bvec4 //包含2/3/4個布爾值的矢量(bool不用解釋)
上邊這些是一種GLSL的數(shù)據(jù)類型, 可以簡單理解為?vec+數(shù)字?就代表 是一個數(shù)組里面放幾個元素(應(yīng)該都是 vec2~vec4之間,沒見過 vec5以上和vec2以下,好像這就代表幾維坐標(biāo)系),默認(rèn)元素是float浮點類型,前邊帶i代表integer整形,b代表bool.
vec3 v; //聲明三維浮點型向量v
v[1] = 3.0;? //給向量v的第二個元素賦值(數(shù)組從0開始,下標(biāo)為1就是第二個元素)
//下面兩種等價
vec3 v = vec3(0.6); //數(shù)組是連續(xù)的存儲空間 相當(dāng)于其它元素默認(rèn)被這個0.6值填充
vec3 v = vec3(0.6,0.6,0.6);
注意: 除了用索引方式外,還能用選擇運算符的方式來使用向量.擇運算符是對于向量的各個元素(最多為4個)約定俗成的名稱隅津,用一個小寫拉丁字母來表示诬垂。根據(jù)向量表示對象的意義不同,可以使用以下選擇運算符:
表示頂點可以用 (x伦仍、y结窘、z、w) (坐標(biāo)系)
表示顏色可以用 (r充蓝、g隧枫、b、a) (顏色值帶透明)
表示紋理坐標(biāo)用 (s谓苟、t官脓、p、q)
三種任選一種都一樣,作用都是等效的. 也就是說涝焙,如果v是一個向量卑笨,那么:
v[0]
v.x
v.r
v.s
都指的是向量v的第一個元素。
例如:
//用構(gòu)造函數(shù)的方式聲明并初始化四維浮點型
vec4v1 =vec4(1.0,2.0,3.0,4.0);
vec4v2;
v2.xy=v1.yz;//將v1的第二個和第三個元素復(fù)制到v2的第一個和第二個元素
v2.z=2.0;//給v2的第三個元素賦值?
v2.xy=v1.yx;//將v1的頭兩個元素互換仑撞,再復(fù)制到v2的頭兩個元素中
矩陣(matrix)以下類型都以mat開頭
mat2?代表2x2的矩陣
mat3?代表3x3的矩陣
mat4?代表4x4的矩陣
注意:矩陣是按列順序組織的赤兴,先列后行
如下代碼:
mat4m;//聲明四維浮點型方陣m?
m[2][3]=2.0;//給方陣的第三列、第四行元素賦值
// 下面兩種等價隧哮,初始化矩陣對角
mat2m =mat2(1.0)
mat2m =mat2(1.0,0.0,0.0,1.0);
紋理查找需要制定哪個紋理或者紋理單元將制定查找.
sampler1D// 訪問一個一維紋理
sampler2D// 訪問一個二維紋理? ? ? ? ?
sampler3D// 訪問一個三維紋理
samplerCube// 訪問一個立方貼圖紋理
sampler1DShadow// 訪問一個帶對比的一維深度紋理
sampler2DShadow// 訪問一個帶對比的二維深度紋理
uniformsampler2Dgrass;
vcc2 coord =vec2(100,100);
vec4color =texture2D(grass, coord);
如果一個著色器在程序里結(jié)合多個文理, 可以使用取樣器數(shù)組.
constinttex_nums =4;
uniformsampler2Dtextures[tex_nums];
for(inti =0; i < tex_nums; ++i) {
sampler2Dtex = textures[i];
// todo ...
}
這是唯一的用戶能用的自定義類型
struct light?
{?
vec3position;
vec3color;
};?
light ceiling_light;
數(shù)組索引是從0開始的桶良,而且沒有指針概念
// 創(chuàng)建一個10個元素的數(shù)組?
vec4points[10];
// 創(chuàng)建一個不指定大小的數(shù)組
vec4points[];
points[2] =vec4(1.0);// points現(xiàn)在大小為3
points[7] =vec4(2.0);// points現(xiàn)在大小為8
只能用于聲明函數(shù)返回值
必須明確地進(jìn)行類型轉(zhuǎn)換,不會自動類型提升
floatf =2.3;
boolb =bool(f);// b is true
GLSL中有4個限定符(variable qualifiers)可供使用沮翔,它們限定了被標(biāo)記的變量不能被更改的”范圍”.
const
attribute
uniform
varying
const: 和C++里差不多陨帆,定義不可變常量
表示限定的變量在編譯時不可被修改.
attribute:是應(yīng)用程序傳給頂點著色器用的
不允許聲明時初始化
attribute限定符標(biāo)記的是一種全局變量,該變量在頂點著色器中是只讀(read-only)的,該變量被用作從OpenGL應(yīng)用程序向頂點著色器中傳遞參數(shù)采蚀,因此該限定符僅能用于頂點著色器.
attribute變量是只能在vertex shader中使用的變量
它不能在fragment shader中聲明attribute變量瑰步,
也不能被fragment shader中使用)
在application中,一般用函數(shù)glBindAttribLocation()來綁定每個attribute變量的位置,然后用函數(shù)
glVertexAttribPointer()為每個attribute變量賦值。
以下是例子:
uniform mat4 u_matViewProjection;
attribute vec4 a_position;
attribute vec2 a_texCoord0;
varying vec2 v_texCoord;
void main(void)
{
? gl_Position = u_matViewProjection * a_position;
? v_texCoord = a_texCoord0;
}
uniform:一般是應(yīng)用程序用于設(shè)定頂點著色器和片斷著色器相關(guān)初始化值.不允許聲明時初始化.uniform限定符標(biāo)記的是一種全局變量,該變量對于一個圖元(primitive)來說是不可更改的 它可以從OpenGL應(yīng)用程序中接收傳遞來的參數(shù)
uniform變量 外部程序傳遞給shader的變量.
函數(shù)glUniform**()函數(shù)賦值的.
shader 中是只讀變量,不能被 shader 修改.
uniform變量一般用來表示:變換矩陣,材質(zhì)齿税,光照參數(shù)和顏色等信息。
uniform mat4 viewProjMatrix; //投影+視圖矩陣
uniform mat4 viewMatrix;? ? ? ? //視圖矩陣
uniform vec3 lightPosition;? ? //光源位置
varying:用于傳遞頂點著色器的值給片斷著色器.它提供了從頂點著色器向片段著色器傳遞數(shù)據(jù)的方法,varying限定符可以在頂點著色器中定義變量芜壁,然后再傳遞給光柵化器纫溃,光柵化器對數(shù)據(jù)插值后疗锐,再將每個片段的值交給片段著色器.
varying變量是vertex和fragment shader之間做數(shù)據(jù)傳遞用的口芍。
一般vertex shader修改varying變量的值关划,
然后fragment shader使用該varying變量的值。
因此varying變量在vertex和fragment shader二者之間的聲
明必須是一致的呵扛。
application不能使用此變量烫堤。
以下是例子:
// Vertex shaderuniform
mat4 u_matViewProjection;
attribute vec4 a_position;
attribute vec2 a_texCoord0;
varying vec2 v_texCoord; // Varying in vertex shader
void main(void)
{?
? gl_Position = u_matViewProjection * a_position;
? v_texCoord = a_texCoord0;
}
// Fragment shaderprecision
mediump float;
varying vec2 v_texCoord; // Varying in fragment shader
uniform sampler2D s_baseMap;
uniform sampler2D s_lightMap;
void main()
{
? vec4 baseColor;
? vec4 lightColor;
? baseColor = texture2D(s_baseMap, v_texCoord);
? lightColor = texture2D(s_lightMap, v_texCoord);
? gl_FragColor = baseColor * (lightColor + 0.25);
}
注意:以上這幾種限定符很重要
不能在if-else中聲明變量
用于判斷的條件必須是bool類型(if,while,for…)
(?:)操作符后兩個參數(shù)必須類型相同
不支持switch語句
vec4toonify(infloatintensify)
{
vec4color;
color =vec4(0.8,0.8,0.8,0.8)
returncolor;
}
discard關(guān)鍵字可以避免片段更新幀緩沖區(qū)剩燥,當(dāng)流控制遇到這個關(guān)鍵字時变擒,正在處理的片段就會被標(biāo)記為丟.
如果不理解什么叫標(biāo)記為丟 可以參考一下UIView的繪制過程
函數(shù)名可以通過參數(shù)類型重載,但是和返回值類型無關(guān)
所有參數(shù)必須完全匹配材部,參數(shù)不會自動
函數(shù)不能被遞歸調(diào)用
函數(shù)返回值不能是數(shù)組
函數(shù)參數(shù)標(biāo)識符
in: 進(jìn)復(fù)制到函數(shù)中毫缆,但不返回的參數(shù)(默認(rèn))
out: 不將參數(shù)復(fù)制到函數(shù)中,但返回參數(shù)
inout: 復(fù)制到函數(shù)中并返回
通過在選擇器(.)后列出各分量名乐导,就可以選擇這些分量
vec4v4;
v4.rgba;// 得到vec4
v4.rgb;// 得到vec3
v4.b;// 得到float
v4.xy;// 得到vec2
v4.xgba;// 錯誤苦丁!分量名不是同一類
v4.wxyz;// 打亂原有分量順序
v4.xxyy;// 重復(fù)分量
最后推薦一個GLSL編輯調(diào)試工具OpenGL Shader Builder(Graphics Tools.dmg)
文章來源于網(wǎng)絡(luò),如有侵權(quán)物臂,請聯(lián)系小編刪除旺拉!
全文完