attribute
和uniform
关键字的目的主要是为了javascript语言可以通过相关的WebGL API把一些数据传递给着色器,如果一个着色器中一个变量,着色器代码中变量不通过attribute
或uniform
声明标识,该变量是不能从javascript代码中获得相应的数据。
关键字 | 数据传递 | 声明变量 |
---|---|---|
attribute | javascript ------> 顶点着色器 | 声明顶点数据变量 |
uniform | javascript ------>顶点、片元着色器 | 声明非顶点数据变量 |
varying | 顶点着色器 ------> 片元着色器 | 声明需要插值计算的顶点变量. |
attribute变量
attribute变量:又称属性变量,该变量只能用于定点着色器,不能用于片元着色器,一般用于描述定点着色器的顶点位置、顶点颜色、顶点纹理坐标等;
attribute
关键字通常用来声明与顶点数据相关的变量,比如顶点位置坐标数据、顶点颜色数据、顶点法向量数据...
因为javascript没必要给片元着色器传递顶点数据,所以规定attribute
关键字只能在顶点着色器中声明变量使用。只要注意attribute
关键字声明顶点变量代码位于主函数main
之外就可以。
// attribute声明顶点位置变量
attribute vec4 position;
// 与顶点相关的浮点数
attribute float scale;
void main() {
// 每个顶点的x坐标乘以该顶点对应的一个系数scale
gl_Position = vec4(position.x*scale,position.y,position.z,1.0);
}
uniform
类型变量
uniform
关键字出现的目的就是为了javascript可以通过相关的WebGL API给着色器变量传递数据,比如传递一个光源的位置数据、一个光源的方向数据、一个光源的颜色数据、一个用于顶点变换的模型矩阵、一个用于顶点变换的视图矩阵...
uniform
其实就是统一(全局) 变量,统一变量通常保存在所谓的"常量存储”中,uniform变量是外部(cpu)application程序传递给(顶点和片元) (GPU)着色器的变量,该变量不会随着顶点或片元的变化而变化,除非应用程序对它进行了更新。在GLSL语言中,其类似于C语言中的常量const,它不能被shader程序修改,也就是个只读变量,只能读,不能更改。
uniform的空间被顶点和片元着色器共享,因此若在一个顶点着色器中声明了uniform,相当于在片元着色器中也声明过了。
uniform变量一般用来表示:变换矩阵,材质,光照参数和颜色等信息。
uniform变量在所有可用的着色阶段之间都是共享的。
javascript可以给顶点着色器的变量传递数据,也可以给片元着色器的变量传递数据,也就是说uniform
关键字既可以在顶点着色器中使用,也可以在片元着色器中使用。只要注意uniform
关键字声明变量需要在主函数main
之前声明。
注意:和顶点相关的变量不能用uniform声明。
varying
类型变量
attribute vec4 a_color;
在顶点着色器中声明了一个顶点颜色变量,如果想在片元着色器中获得顶点颜色插值计算以后的数据,需要同时在顶点着色器和片元着色器中执行varying vec4 v_color;
,也就是在顶点、片元两个着色器代码中都需要通过关键字varying
声明一个新变量v_color
,最后再顶点着色器中执行v_color = a_color;
即可
顶点着色器
attribute vec4 a_color;// attribute声明顶点颜色变量
varying vec4 v_color;//varying声明顶点颜色插值后变量
void main() {
//顶点颜色插值计算
v_color = a_color;
}
片元着色器
// 接收顶点着色器中v_color数据
varying vec4 v_color;
void main() {
// 插值后颜色数据赋值给对应的片元
gl_FragColor = v_color;
}
varying
类型变量主要是为了完成顶点着色器和片元着色器之间的数据传递和插值计算。比如在一个WebGL程序中通过三个顶点绘制一个彩色三角形,三个顶点的位置坐标定义了一个三角形区域,这个三角形区域经过片元着色器处理后会得到由一个个片元或者说像素组成的三角形区域,在片元化的过程中,顶点的颜色数据也会进行插值计算,插值计算之前每个顶点对应一个颜色,插值计算之后,每个片元对应一个颜色值,通过varying
关键字就可以在片元着色器中获得插值后的颜色数据,然后赋值给片元。
<!-- 顶点着色器源码 -->
<script id="vertexShader" type="x-shader/x-vertex">
//attribute声明vec4类型变量apos
attribute vec4 apos;
// attribute声明顶点颜色变量
attribute vec4 a_color;
//varying声明顶点颜色插值后变量
varying vec4 v_color;
void main() {
// 顶点坐标apos赋值给内置变量gl_Position
gl_Position = apos;
//顶点颜色插值计算
v_color = a_color;
}
</script>
<!-- 片元着色器源码 -->
<script id="fragmentShader" type="x-shader/x-fragment">
// 所有float类型数据的精度是lowp
precision lowp float;
// 接收顶点着色器中v_color数据
varying vec4 v_color;
void main() {
// 插值后颜色数据赋值给对应的片元
gl_FragColor = v_color;
}
</script>
varying变量的原理
在线段上进行混合插值
在三角形上进行混合插值