在頂點着色器中,每個輸入變量叫做頂點屬性。
着色器語言之變量類型
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 vec4
的ourColor,並把片段着色器的輸出顏色設置為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每次執行着色器的時候更新(如果處理的是頂點,那么這里會為每個頂點傳遞新的值;如果處理的是片元,那么會為每個片元傳遞新的值)