【opengl】著色器(Shaders)

著色器(Shader)是運行在GPU上的小程序哆键,為圖形渲染管線的某個特定部分而運行慈省。
著色器只是一種把輸入轉化為輸出的程序憔维。
著色器是一種非常獨立的程序炬守,因為它們之間不能相互通信牧嫉;它們之間唯一的溝通只有通過輸入和輸出剂跟。

GLSL


  • 著色器是使用一種叫GLSL的類C語言寫成的减途。
  • 著色器的開頭總是要聲明版本,
    接著是輸入和輸出變量曹洽、uniform和main函數鳍置。
  • 每個著色器的入口點都是main函數,在這個函數中我們處理所有的輸入變量送淆,并將結果輸出到輸出變量中税产。
  • 一個典型的著色器的結構:
#version version_number
in type in_variable_name;
in type in_variable_name;

out type out_variable_name;

uniform type uniform_name;

int main()
{
  // 處理輸入并進行一些圖形操作
  ...
  // 輸出處理過的結果到輸出變量
  out_variable_name = weird_stuff_we_processed;
}

特別地,在頂點著色器中偷崩,輸入變量又叫頂點屬性(Vertex Attribute),我們能聲明的頂點屬性是有上限的,它一般由硬件來決定稠歉。OpenGL確保至少有16個包含4分量的頂點屬性可用煤杀。

數據類型

GLSL有數據類型可以來指定變量的種類。
GLSL中包含C等其它語言大部分的默認基礎數據類型
int谒出、float隅俘、doubleuintbool
GLSL也有兩種容器類型:
向量(Vector)矩陣(Matrix)

向量

GLSL中的向量是一個可以包含有1笤喳、2为居、3或者4個分量的容器。
分量的類型可以是前面默認基礎類型的任意一個杀狡。

類型 含義
vecn 包含n個float分量的默認向量
bvecn 包含n個bool分量的向量
ivecn 包含n個int分量的向量
uvecn 包含n個unsigned int分量的向量
dvecn 包含n個double分量的向量
  • 大多數時候我們使用vecn
  • 一個向量的分量可以通過vec.x這種方式獲取蒙畴,這里x是指這個向量的第一個分量。你可以分別使用.x呜象、.y膳凝、.z和.w來獲取它們的第1八孝、2、3鸠项、4個分量干跛。
  • GLSL也允許你對顏色使用rgba,或是對紋理坐標使用stpq訪問相同的分量祟绊。

向量的重組(Swizzling):
重組允許這樣的語法:

vec2 someVec;
vec4 differentVec = someVec.xyxx;
vec3 anotherVec = differentVec.zyw;
vec4 otherVec = someVec.xxxx + anotherVec.yxzy;

我們也可以把一個向量作為一個參數傳給不同的向量構造函數楼入,以減少需求參數的數量:

vec2 vect = vec2(0.5, 0.7);
vec4 result = vec4(vect, 0.0, 0.0);
vec4 otherResult = vec4(result.xyz, 1.0);

輸入與輸出


每個著色器都有輸入和輸出,這樣才能進行數據交流和傳遞牧抽。
GLSL定義了inout關鍵字專門來實現這個目的嘉熊。
每個著色器使用這兩個關鍵字設定輸入和輸出,只要一個輸出變量與下一個著色器階段的輸入匹配阐肤,它就會傳遞下去。
但也有例外讲坎,在頂點和片段著色器中:
頂點著色器的輸入特殊在孕惜,它從頂點數據中直接接收輸入。
頂點著色器需要為它的輸入提供一個額外的layout標識晨炕,這樣我們才能把它鏈接到頂點數據衫画。
layout (location = 0)
另一個例外是片段著色器,它需要一個vec4顏色輸出變量瓮栗,因為片段著色器需要生成一個最終輸出的顏色削罩。如果你在片段著色器沒有定義輸出顏色,OpenGL會把你的物體渲染為黑色(或白色)费奸。

Uniform


Uniform是一種從CPU中的應用向GPU中的著色器發(fā)送數據的方式弥激。

  • uniform是全局的(Global):
    全局意味著uniform變量必須在每個著色器程序對象中都是獨一無二的,而且它可以被著色器程序的任意著色器在任意階段訪問愿阐。
  • 無論你把uniform值設置成什么微服,uniform會一直保存它們的數據,直到它們被重置或更新换况。

我們可以在一個著色器中添加uniform關鍵字至類型和變量名前來聲明一個GLSL的uniform职辨。從此處開始我們就可以在著色器中使用新聲明的uniform了。

#version 330 core
out vec4 FragColor;

uniform vec4 ourColor; // 在OpenGL程序代碼中設定這個變量

void main()
{
    FragColor = ourColor;
}

如果你聲明了一個uniform卻在GLSL代碼中沒用過戈二,編譯器會靜默移除這個變量舒裤,導致最后編譯出的版本中并不會包含它,這可能導致幾個非常麻煩的錯誤觉吭,記住這點腾供!

這個uniform現在還是空的;我們還沒有給它添加任何數據,所以下面我們就做這件事伴鳖。

  • 首先需要找到著色器中uniform屬性的索引/位置值
  • 當我們得到uniform的索引/位置值后节值,我們就可以更新它的值了
float timeValue = glfwGetTime();
float greenValue = (sin(timeValue) / 2.0f) + 0.5f;
int vertexColorLocation = glGetUniformLocation(shaderProgram, "ourColor");
glUseProgram(shaderProgram);
glUniform4f(vertexColorLocation, 0.0f, greenValue, 0.0f, 1.0f);

我們通過glfwGetTime()獲取運行的秒數.
然后我們使用sin函數讓顏色在0.0到1.0之間改變,將結果儲存到greenValue里
接著榜聂,我們用glGetUniformLocation查詢uniform ourColor的位置值
最后搞疗,我們可以通過glUniform4f函數設置uniform值
注意,查詢uniform地址不要求你之前使用過著色器程序须肆,但是更新一個uniform之前你必須先使用程序(調用glUseProgram)匿乃,因為它是在當前激活的著色器程序中設置uniform的

uniform對于設置一個在渲染迭代中會改變的屬性是一個非常有用的工具,它也是一個在程序和著色器間數據交互的很好工具豌汇。

更多屬性幢炸!


在前面的教程中,我們了解了如何填充VBO拒贱、配置頂點屬性指針以及如何把它們都儲存到一個VAO里宛徊。這次,我們同樣打算把顏色數據加進頂點數據中逻澳。我們將把顏色數據添加為3個float值至vertices數組闸天。我們將把三角形的三個角分別指定為紅色、綠色和藍色:

float vertices[] = {
    // 位置              // 顏色
     0.5f, -0.5f, 0.0f,  1.0f, 0.0f, 0.0f,   // 右下
    -0.5f, -0.5f, 0.0f,  0.0f, 1.0f, 0.0f,   // 左下
     0.0f,  0.5f, 0.0f,  0.0f, 0.0f, 1.0f    // 頂部
};
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末赡盘,一起剝皮案震驚了整個濱河市号枕,隨后出現的幾起案子缰揪,更是在濱河造成了極大的恐慌陨享,老刑警劉巖,帶你破解...
    沈念sama閱讀 207,248評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件钝腺,死亡現場離奇詭異,居然都是意外死亡艳狐,警方通過查閱死者的電腦和手機定硝,發(fā)現死者居然都...
    沈念sama閱讀 88,681評論 2 381
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來毫目,“玉大人蔬啡,你說我怎么就攤上這事《婆埃” “怎么了箱蟆?”我有些...
    開封第一講書人閱讀 153,443評論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長刮便。 經常有香客問我空猜,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,475評論 1 279
  • 正文 為了忘掉前任辈毯,我火速辦了婚禮坝疼,結果婚禮上,老公的妹妹穿的比我還像新娘谆沃。我一直安慰自己钝凶,他們只是感情好,可當我...
    茶點故事閱讀 64,458評論 5 374
  • 文/花漫 我一把揭開白布唁影。 她就那樣靜靜地躺著腿椎,像睡著了一般。 火紅的嫁衣襯著肌膚如雪夭咬。 梳的紋絲不亂的頭發(fā)上啃炸,一...
    開封第一講書人閱讀 49,185評論 1 284
  • 那天,我揣著相機與錄音卓舵,去河邊找鬼南用。 笑死,一個胖子當著我的面吹牛掏湾,可吹牛的內容都是我干的裹虫。 我是一名探鬼主播,決...
    沈念sama閱讀 38,451評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼融击,長吁一口氣:“原來是場噩夢啊……” “哼筑公!你這毒婦竟也來了?” 一聲冷哼從身側響起尊浪,我...
    開封第一講書人閱讀 37,112評論 0 261
  • 序言:老撾萬榮一對情侶失蹤匣屡,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后拇涤,有當地人在樹林里發(fā)現了一具尸體捣作,經...
    沈念sama閱讀 43,609評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,083評論 2 325
  • 正文 我和宋清朗相戀三年鹅士,在試婚紗的時候發(fā)現自己被綠了券躁。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,163評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡掉盅,死狀恐怖也拜,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情趾痘,我是刑警寧澤慢哈,帶...
    沈念sama閱讀 33,803評論 4 323
  • 正文 年R本政府宣布,位于F島的核電站扼脐,受9級特大地震影響岸军,放射性物質發(fā)生泄漏奋刽。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,357評論 3 307
  • 文/蒙蒙 一艰赞、第九天 我趴在偏房一處隱蔽的房頂上張望佣谐。 院中可真熱鬧,春花似錦方妖、人聲如沸狭魂。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,357評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽雌澄。三九已至,卻和暖如春杯瞻,著一層夾襖步出監(jiān)牢的瞬間镐牺,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,590評論 1 261
  • 我被黑心中介騙來泰國打工魁莉, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留睬涧,地道東北人。 一個月前我還...
    沈念sama閱讀 45,636評論 2 355
  • 正文 我出身青樓旗唁,卻偏偏與公主長得像畦浓,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子检疫,可洞房花燭夜當晚...
    茶點故事閱讀 42,925評論 2 344

推薦閱讀更多精彩內容