在顶点着色器中,每个输入变量叫做顶点属性。
着色器语言之变量类型
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每次执行着色器的时候更新(如果处理的是顶点,那么这里会为每个顶点传递新的值;如果处理的是片元,那么会为每个片元传递新的值)