在三维程序中,绘制第一个三角形就像写一个“Hello World”一样代表的写三维程序的开始,在以往C&C++里用OpenGL绘制一个三角化很容易,但在WebGL里从哪里入手呢?当然,还是先创建VertexBuffer, 然后BindBuffer后Draw一个三角面就可以,但在WebGL里,采用了OpenGL ES2.0的接口,那又如何呢?那必须先写好Shader才可以,怎么WebGL像DirectX 10&11一样啰嗦了?但我觉得这是一个进步,用灵活的可编程Shader代替N多的GL API不是好事么?我比较喜欢简单的程序,相信每个优秀的程序员都喜欢。
1. 创建Shader的function
WebGL有Vertex shader和Fragment shader两种,我们创建一个专门创建和编译Shader的方法:
function buildShader (gl, type, string) {
var shader;
if (type === "fragment") {
shader = gl.createShader(gl.FRAGMENT_SHADER);
}
else if (type === "vertex") {
shader = gl.createShader(gl.VERTEX_SHADER);
}
gl.shaderSource(shader, string);
gl.compileShader(shader);
if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
console.error(gl.getShaderInfoLog(shader));
console.error(string);
return null;
}
return shader;
}
有了建好的Shader,我们就可以创建和连接一个Program:
function buildProgram (gl, vertexShader, fragmentShader) {
var program = gl.createProgram();
var glVertexShader = buildShader(gl, "vertex", vertexShader);
var glFragmentShader = buildShader(gl, "fragment", fragmentShader);
gl.attachShader(program, glVertexShader);
gl.attachShader(program, glFragmentShader);
gl.linkProgram(program);
if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
console.log(fragmentShader);
console.log(vertexShader);
}
return program;
}
3. 创建一个简单的Program对像
我们先只写一个最简单的Shader,不用任何顶点变化,基本上是不能再简单了:
var vertexShader =
'attribute vec4 vPosition; \n\
void main() \n\
{ \n\
gl_Position = vPosition; \n\
} \n';
var fragmentShader =
'precision mediump float; \n\
void main() \n\
{ \n\
gl_FragColor = vec4 ( 1.0, 1.0, 0.0, 1.0 );\n\
}\n';
然后用之前定义的buildProgram来创建Program对像:
program = buildProgram(gl, vertexShader, fragmentShader);
4. 创建VertexBuffer
在JavaScript无法直接使用二进制数据比较麻烦,但我们可以用Float32Array来创建定点缓存然后交给WebGL,我们首先创建一个Float3dArray:
var vertices = new Float32Array(
[0.0, 0.5, 0.0,
-0.5, -0.5, 0.0,
0.5, -0.5, 0.0]);
然后创建WebGL VBO对像,并把顶点数据交给VBO:
vb = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vb);
gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);
记得从Program里获得"vPosition"属性的location:
vb.vertexAttribLoc = gl.getAttribLocation(program, "vPosition");
5. 绘制三角形:
剩下的就是绘制三角形了,在之前定义的updateFrame中添加绘制代码,首先是绑定Program:
gl.useProgram(program);
然后绑定VertexBuffer:
gl.bindBuffer(gl.ARRAY_BUFFER, vb);
gl.vertexAttribPointer(vb.vertexAttribLoc, 3, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(vb.vertexAttribLoc);
最后绘制一个三角形:
gl.drawArrays(gl.TRIANGLES, 0, 3);
在Shader里gl_FragColor被设置成了固定的颜色,你可以随意改,然后只需要刷新下网页就可以,这就是脚本语言最大的魅力,如果不要求大数据和高性能的话。