上节我们画了一个点,不过点的位置和大小都是写死的,这节我们看看怎么传递数据到 shader 中。
// vertex shader
var VERTEX_SHADER_SOURCE =
'attribute vec4 a_Position;\n' +
'uniform float u_PointSize;\n' +
'void main() {\n' +
' gl_Position = a_Position;\n' +
' gl_PointSize = u_PointSize;\n' +
'}\n';
// fragment shader
var FRAGMENT_SHADER_SOURCE =
'void main() {\n' +
' gl_FragColor = vec4(1.0,0.0,0.0,1.0);\n' +
'}\n';
有 2 种方式可传值到 shader 中,通过 attribute(属性) variable 或者 uniform variable。 attribute 用来传递可变数据,uniform 用来传递常量。我们定义了 a_Position 来接收顶点信息,由于我们希望每个顶点的大小都一样,所以定义了 u_PointSize 为 uniform 变量。
var a_Position = gl.getAttribLocation(gl.program, 'a_Position');
gl.vertexAttrib3f(a_Position, 0.0, 0.0, 0.0);
var u_PointSize = gl.getUniformLocation(gl.program, 'u_PointSize');
gl.uniform1f(u_PointSize, 5.0);
- gl.getAttribLocation(program, name)
用来获得 attribute 变量的地址(可理解为内存地址或指针)
第一个参数是 program 对象, 第二个参数是 变量名
- gl.getUniformLocation(program, name)
用来获得 uniform 变量的地址
同上第一个参数是 program 对象, 第二个参数是 变量名
- gl.vertexAttrib3f(location, v0, v1, v2)
给 attribute 变量赋值,f 表示 float
第一个参数是变量地址,后面是值
gl.vertexAttrib*f 是一系列方法
gl.vertexAttrib1f(location, v0)
gl.vertexAttrib2f(location, v0, v1)
gl.vertexAttrib3f(location, v0, v1, v2)
gl.vertexAttrib4f(location, v0, v1, v2, v3)
分别对应 float, vec2, vec3, vec4 类型
我们的 a_Position 是 vec4 类型的,但我们只传了 3 个值,因为第4个值 w 默认为 1.0, 前 3 个值默认为 0
- gl.uniform1f(location, v0)
给 uniform 变量赋值
同理 gl.uniform*f 也是一系列方法
gl.uniform1f(location, v0)
gl.uniform2f(location, v0, v1)
gl.uniform3f(location, v0, v1, v2)
gl.uniform4f(location, v0, v1, v2, v3)
attribute 变量只能定义在 vertex shader 中,uniform 变量既可以定义在 vertex shader 中也可以定义在 fragment shader 中。
练习:
现在点的颜色是在 shader 中写死的, 尝试从 JS 中传一个值进去。