这里首先贴出其第三章绘制正方形代码的简化版本(为了阅读流畅性,去除了一些错误判断):
var VSHADER_SOURCE =
'attribute vec4 a_Position;\n' +
'void main() {\n' +
' gl_Position = a_Position;\n' +
'}\n';
var FSHADER_SOURCE =
'void main() {\n' +
' gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n' +
'}\n';
function main() {
var canvas = document.getElementById('webgl');
var gl = getWebGLContext(canvas);
initShaders(gl, VSHADER_SOURCE, FSHADER_SOURCE);
var n = initVertexBuffers(gl);
gl.clearColor(0, 0, 0, 1);
gl.clear(gl.COLOR_BUFFER_BIT);
gl.drawArrays(gl.TRIANGLE_STRIP, 0, n);
}
function initVertexBuffers(gl) {
var vertices = new Float32Array([-0.5,0.5,-0.5,-0.5,0.5,0.5,0.5,-0.5]);
var n = 4;
var vertexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);
var a_Position = gl.getAttribLocation(gl.program, 'a_Position');
gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(a_Position);
return n;
}
下面对代码中的一些关键点做个解释:
//-------------------------------------------------------------------------------------------------------------------------------
gl.clear(gl.COLOR_BUFFER_BIT);
这行代码的意思是清除缓冲区,参数可以是一下三种
gl.COLOR_BUFFER_BIT 指定颜色缓存
gl.DEPTH_BUFFER_BIT 指定深度缓冲区
gl.STENCIL_BUFFER_BIT 指定模板缓冲区
使用位操作符or(|)可用来清空多个缓冲区。
//-------------------------------------------------------------------------------------------------------------------------------
var a_Position = gl.getAttribLocation(gl.program, 'a_Position');
这行代码的意思是获取字符串'a_Position'参数指定的gl.program着色器对象中的attribute变量存储地址。与此类似的是下面这行代码:
var u_FragColor=gl.getUniformLocation(gl.program,'u_FragColor');
它的意思是获取字符串'au_FragColor参数指定的gl.program着色器对象中的uniform变量存储地址。
需要说明的是在shader中有三种变量类型,分别是attribute、uniform和varying。分别介绍如下:
1.attribute变量是只能在vertex着色器中使用的变量。(它不能在fragment着色器中声明attribute变量,也不能被fragment着色器中使用),一般用attribute变量来表示一些顶点的数据,如:顶点坐标,法线,纹理坐标,顶点颜色等。在application中,一般用函数glBindAttribLocation()来绑定每个attribute变量的位置,然后用函数glVertexAttribPointer()为每个attribute变量赋值。使用参考如下:
uniform mat4 u_matViewProjection;
attribute vec4 a_position;
attribute vec2 a_texCoord0;
varying vec2 v_texCoord;
void main(void)
{
gl_Position = u_matViewProjection * a_position;
v_texCoord = a_texCoord0;
}
2.uniform变量在vertex着色器和fragment着色器两者之间声明方式完全一样,则它可以在vertex着色器和fragment着色器共享使用(相当于一个被vertex着色器和fragment着色器共享的全局变量),uniform变量一般用来表示:变换矩阵,材质,光照参数和颜色等信息。使用参考如下:
uniform mat4 viewProjMatrix;
uniform mat4 viewMatrix;
uniform vec3 lightPosition;
3.varying变量
varying变量是vertex和fragment shader之间做数据传递用的。一般vertex shader修改varying变量的值,然后fragment shader使用该varying变量的值。因此varying变量在vertex和fragment shader二者之间的声明必须是一致的。application不能使用此变量。其在Vertex着色器中使用参考如下:
uniform mat4 u_matViewProjection;
attribute vec4 a_position;
attribute vec2 a_texCoord0;
varying vec2 v_texCoord;
void main(void)
{
gl_Position = u_matViewProjection * a_position;
v_texCoord = a_texCoord0;
}
其在Fragment着色器中使用参考如下:
precision mediump float;
varying vec2 v_texCoord;
uniform sampler2D s_baseMap;
uniform sampler2D s_lightMap;
void main()
{
vec4 baseColor;
vec4 lightColor;
baseColor = texture2D(s_baseMap, v_texCoord);
lightColor = texture2D(s_lightMap, v_texCoord);
gl_FragColor = baseColor * (lightColor + 0.25);
}
//-------------------------------------------------------------------------------------------------------------------------------
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
这行代码的意思是绑定缓冲区,函数原型是gl.bindBuffer(target,buffer)。
其中target可以是下面两种:
gl.ARRAY_BUFFER 表示缓冲区对象包含了顶点的数据。
gl.ELEMENT_ARRAY_BUFFER 表示缓冲区对象中包含顶点的索引值。
buffer指定之前由gl.creareBuffer返回的待绑定的缓冲区对象,如果指定为null,则禁用对target的绑定。
//-------------------------------------------------------------------------------------------------------------------------------
gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);