varying 变量

varying 的中文意思是“不同的;变化的”,它负责从顶点着色器向片元着色器传递数据。

在 GLSL ES 的 Vertex Shader 中,attribute 变量和 varying 变量都要声明,然后在 main() 函数中把 attribute 变量赋值给 varying 变量。在 Fragment Shader 中声明一个相同命名的 varying 变量,然后在 main() 函数中把 varying 变量赋值给 gl_FragColor 变量。只有 varying 变量在顶点着色器和片元着色器中是相同命名的,值就会自动传递。 下面代码用 Buffer 的 gl.vertexAttribPointer 来一次性写入数据,实现图中的点的颜色并不是 uniform 的。

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

<script id="vertexShader" type="x-shader/x-vertex"> attribute vec4 a_Position; attribute float a_PointSize; attribute vec4 a_Color; varying vec4 v_Color; void main(){ gl_Position = a_Position; gl_PointSize = a_PointSize; v_Color = a_Color; } </script> <script id="fragmentShader" type="x-shader/x-fragment"> precision mediump float; varying vec4 v_Color; void main(){ gl_FragColor = v_Color; } </script> function init(){ var canvas = document.getElementById('canvas'), gl = canvas.getContext('webgl'); if(!gl){ console.log('Failed to get WebGL.'); return; } if(!initShaders(gl, "vertexShader", "fragmentShader")){ console.log('Failed to init Shaders.'); return; } // 获取 attribute 变量的存储地址 var a_Position = gl.getAttribLocation(gl.program, 'a_Position'), a_PointSize = gl.getAttribLocation(gl.program, 'a_PointSize'), a_Color = gl.getAttribLocation(gl.program, 'a_Color'); if(a_Position < 0 || a_PointSize < 0 || a_Color < 0){ console.log('Failed to get the location'); console.log(a_Position, a_PointSize, a_Color); return; } var verticsSize = new Float32Array([ 0.0, 0.5, 10.0, 1.0, 0.0, 0.0, 1.0, -0.5, -0.4, 20.0, 0.0, 1.0, 0.0, 1.0, 0.5, -0.4, 30.0, 0.0, 0.0, 1.0, 1.0]); var element_size = verticsSize.BYTES_PER_ELEMENT; // 创建缓冲区对象,对其写入数据 initVertexBuffer(gl, verticsSize, a_Position, a_PointSize, a_Color, element_size); // 设置背景色, 清空颜色缓冲区 gl.clearColor(0.0, 0.0, 0.0, 1.0); gl.clear(gl.COLOR_BUFFER_BIT); // 画点 gl.drawArrays(gl.POINTS, 0, 3); } function initVertexBuffer(gl, data, a_Position, a_PointSize, a_Color, 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( a_Position, 2, gl.FLOAT, false, size * 7, 0); gl.enableVertexAttribArray( a_Position ); // 尺寸数据 gl.vertexAttribPointer( a_PointSize, 1, gl.FLOAT, false, size * 7, size * 2); gl.enableVertexAttribArray( a_PointSize ); // 颜色数据 gl.vertexAttribPointer( a_Color, 4, gl.FLOAT, false, size * 7, size * 3); gl.enableVertexAttribArray( a_Color ); }

gl.drawArrays() 的第一个参数改为 gl.TRIANGLES,就能画出一个彩色三角形了。点在不同颜色间进行变换,是顶点着色器中的 v_Color 在传入片元着色器之前就已经经过了内插过程。它与片元着色器中的 v_Color 不是同一个东西,只是名字相同,自动传值。