attribute 变量

attribute的中文意思是“属性,特征”, attribute 变量只使用在Vertex着色器中,它是一个存储限定符 (storage qualifier),按照以下格式声明:

接着,将其赋值给 gl_Position: gl_Position = a_Position;

此时 a_Position 是个类型为 vec4 的变量,但为空值。要向它传值,首先要知道它在计算机中的哪个位置,通过 gl.getAttribLocation( program, name ) 来获取,它返回 WebGL 程序对象中 name 的下标指向的存储地址。program 通过 initshader() 函数来获得,name 就是 GLSL ES 中的着色器的变量名,在 JavaScript 中写上字符串形式。找到存储地址后,也就是返回值大于等于0后,就可以对 gl_Position 进行动态赋值了,调用 gl.vertexAttrib[1234]f( location, [v0, v1, v2, v3] ) 或 gl.vertexAttrib[1234]fv( location, value )。

attribute 变量的类型只能是 float、vec2、vec3、vec4、mat2、mat3 和 mat4。

<script id="vertexShader" type="x-shader/x-vertex"> attribute vec4 a_Position; void main(){ gl_Position = a_Position; } </script> // 获取地址 var a_Position = gl.getAttribLocation( gl.program, 'a_Position' ); // 检查返回值:指定的 attribute 变量不存在,或者其命名具有 gl_ 或 webgl_ 前缀 if(a_Position < 0) { console.log('Failed to get the location of a_Position'); return; } // 传值 gl.vertexAttrib3f( a_Position, x, y, z ); // 或者 var position = new Float32Array([x, y, z, 1.0]); gl.vertexAttrib4fv( a_Position, position ); GLSL ES 中的 a_Position 是 vec4 类型,用 gl.vertexAttrib3f() 而不用 gl.vertexAttrib4() 是为什么呢? 齐次坐标 (x, y, z, w) 等价于三维坐标 (x/w, y/w, z/w ),而第4个分量 w 默认是1。所以,如果省略第4个参数,gl.vertexAttrib3f() 默认不是第4个分量1.0

加深

1. 传值给尺寸变量 gl_PointSize <script id="vertexShader" type="x-shader/x-vertex"> attribute vec4 a_Position; attribute float a_PointSize; void main(){ gl_Position = a_Position; gl_PointSize = a_PointSize; } </script> var a_PointSize = gl.getAttribLocation( gl.program, 'a_PointSize' ); gl.vertexAttrib1f( a_PointSize, 10.0 ); 2. 用 Buffer 来一次性传入大量数据 // 获取地址 var a_Position = gl.getAttribLocation( gl.program, 'a_Position' ); var a_PointSize = gl.getAttribLocation( gl.program, 'a_PointSize' ); // 检查返回值:指定的 attribute 变量不存在,或者其命名具有 gl_ 或 webgl_ 前缀 if(a_Position < 0 || a_PointSize <0) { console.log('Failed to get the location of a_Position'); return; } var vertics = new Float32Array([0.0, 0.5, -0.5, -0.4, 0.5, -0.4]), sizes = new Float32Array([10.0, 20.0, 30.0]); // 创建缓冲区对象,对其写入数据 initVertexBuffer(gl, a_Position, vertics, 2); initVertexBuffer(gl, a_PointSize, sizes, 1); function initVertexBuffer(gl, location, data, size){ var vertexBuffer = gl.createBuffer(); if(!vertexBuffer){ console.log('Failed to create the buffer object.'); return ; } gl.bindBuffer( gl.ARRAY_BUFFER, vertexBuffer ); gl.bufferData( gl.ARRAY_BUFFER, data, gl.STATIC_DRAW ); gl.vertexAttribPointer( location, size, gl.FLOAT, false, 0, 0); gl.enableVertexAttribArray( location ); } 3. a_Position 的 x、y 坐标写出来 <script id="vertexShader" type="x-shader/x-vertex"> attribute vec4 a_Position; uniform float u_sinB, u_cosB; void main(){ gl_Position.x = a_Position.x * u_cosB - a_Position.y * u_sinB; gl_Position.y = a_Position.x * u_sinB + a_Position.y * u_cosB; gl_Position.z = a_Position.z; gl_Position.w = 1.0; } </script>