着色器詳解


在頂點着色器中,每個輸入變量叫做頂點屬性

着色器語言之變量類型
1>uniform:

其實就是統一(全局)變量,統一變量通常保存在所謂的“常量存儲”中,uniform變量是外部(cpu)application程序傳遞給(頂點和片元)(GPU)着色器的變量,該變量不會隨着頂點或片元的變化而變化,除非應用程序對它進行了更新。在GLSL語言中,其類似於C語言中的常量const,它不能被shader程序修改,也就是個只讀變量,只能讀,不能更改。

uniform 的空間被頂點和片元着色器共享,因此若在一個頂點着色器中聲明了uniform,相當於在片元着色器中也聲明過了。

uniform變量一般用來表示:變換矩陣,材質,光照參數和顏色等信息。

uniform變量在所有可用的着色階段之間都是共享的。

例如:

我們設置一個給圖元着色的顏色值,此時可以聲明一個uniform變量,將顏色值信息傳遞到着色器中。而着色器中會進行如下聲明:

uniform vec4 color;

在片元着色器中設置:

1 #version 330 core
2 out vec4 FragColor;
3 
4 uniform vec4 ourColor; // 在OpenGL程序代碼中設定這個變量
5 
6 void main()
7 {
8     FragColor = ourColor;
9 }

我們在片段着色器中聲明了一個uniform vec4ourColor,並把片段着色器的輸出顏色設置為uniform值的內容。因為uniform是全局變量,我們可以在任何着色器中定義它們,而無需通過頂點着色器作為中介。頂點着色器中不需要這個uniform,所以我們不用在頂點着色器中定義顏色。

這個uniform現在還是空的;我們還沒有給它添加任何數據,所以下面我們就做這件事。我們首先需要找到着色器中uniform屬性的索引/位置值。當我們得到uniform的索引/位置值后,我們就可以更新它的值了。這次我們不去給像素傳遞單獨一個顏色,而是讓它隨着時間改變顏色:

1 float timeValue = glfwGetTime();
2 float greenValue = (sin(timeValue) / 2.0f) + 0.5f;
3 int vertexColorLocation = glGetUniformLocation(shaderProgram, "ourColor");
4 glUseProgram(shaderProgram);
5 glUniform4f(vertexColorLocation, 0.0f, greenValue, 0.0f, 1.0f);

首先我們通過glfwGetTime()獲取運行的秒數。然后我們使用sin函數讓顏色在0.0到1.0之間改變,最后將結果儲存到greenValue里。

接着,我們用glGetUniformLocation查詢uniform ourColor的位置值。我們為查詢函數提供着色器程序和uniform的名字(這是我們希望獲得的位置值的來源)。如果glGetUniformLocation返回-1就代表沒有找到這個位置值。

最后,我們可以通過glUniform4f函數設置uniform值。注意,查詢uniform地址不要求你之前使用過着色器程序,但是更新一個uniform之前你必須先使用程序(調用glUseProgram),因為它是在當前激活的着色器程序中設置uniform的。

如果我們打算讓顏色慢慢變化,我們就要在游戲循環的每一次迭代中(所以他會逐幀改變)更新這個uniform,否則三角形就不會改變顏色。所以我們把這5行代碼放在渲染循環中。

glUniform的功能:為當前程序對象指定Uniform變量的值
void glUniform4f(GLint location,  GLfloat v0,  GLfloat v1,  GLfloat v2,  GLfloat v3); 

location指明要更改的uniform變量的位置,

v0,v1,v2,v3指明在指定的uniform變量中要使用的新值

1、為什么是greenValue?

只因為放在了RGB中第二個位置,如果放在第一個位置,則為紅色。

2、為什么是變成了黑色?

因為用了sin讓值在0-1中漸變,當為0的時候,就變成了黑色。同理,如果設置了另外的RGB中的值,視情況而定。

2>attribute變量

attribute變量是只能在vertex shader中使用的變量。(它不能在fragment shader中聲明attribute變量,也不能被fragment shader中使用)

一般用attribute變量來表示一些頂點的數據,如:頂點坐標,法線,紋理坐標,頂點顏色等。

例如:

1 uniform mat4 u_matViewProjection;
2 attribute vec4 a_position;
3 attribute vec2 a_texCoord0;
4 varying vec2 v_texCoord; 5 void main(void) 6 { 7 gl_Position = u_matViewProjection * a_position; 8 v_texCoord = a_texCoord0; 9 }

3>varying變量

varying變量是vertex和fragment shader之間做數據傳遞用的。一般vertex shader修改varying變量的值,然后fragment shader使用該varying變量的值。因此varying變量在vertex和fragment shader二者之間的聲明必須是一致的。

例如:

 1 // Vertex shader
 2 uniform mat4 u_matViewProjection;
 3 attribute vec4 a_position; 4 attribute vec2 a_texCoord0; 5 varying vec2 v_texCoord; // Varying in vertex shader 6 void main(void) 7 { 8 gl_Position = u_matViewProjection * a_position; 9 v_texCoord = a_texCoord0;//被修改 10 } 11 12 13 // Fragment shader 14 precision mediump float; 15 varying vec2 v_texCoord; // Varying in fragment shader 16 uniform sampler2D s_baseMap; 17 uniform sampler2D s_lightMap; 18 void main() 19 { 20 vec4 baseColor; 21 vec4 lightColor; 22 baseColor = texture2D(s_baseMap, v_texCoord); 23 lightColor = texture2D(s_lightMap, v_texCoord);//被使用 24 gl_FragColor = baseColor * (lightColor + 0.25); 25 }

4>in/out

in --輸入

out--輸出

在頂點着色器中的out變量在片元着色器中就是對應的in變量,因為片元着色器的輸入就是頂點着色器的輸出

in out定義的變量的值會在openGL每次執行着色器的時候更新(如果處理的是頂點,那么這里會為每個頂點傳遞新的值;如果處理的是片元,那么會為每個片元傳遞新的值)

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM