最近老学了一门新的课程:WebGL。实验一就是利用WebGL绘制一个顶点颜色不同的三角形和矩形,就像下面这样:
矩形.png
三角形.png
直接上代码吧:
HTML页面:使用canvas元素生成画布。
<canvas id="webgl-1" width="640" height="480">
Your browser doesn't appear to support the HTML5 <code><canvas></code> element.
</canvas>
<br>
<canvas id="webgl-2" width="640" height="480">
Your browser doesn't appear to support the HTML5 <code><canvas></code> element.
</canvas>
这里我是直接用了两个canvas元素以提供两个不同形状的绘制。
然后是javascript代码。
利用WebGL需要使用着色器,这里不多介绍。
1.从HTML页面获取canvas元素的上下文,这里主要要获取到gl对象:
function initWebGL(canvas) {
var gl;
try {
gl = canvas.getContext("webgl");
gl.viewport(0, 0, canvas.width, canvas.height);
} catch (e) {
var msg = "无法从canvas中获取webgl!" + e.toString();
alert(msg);
throw Error(msg);
}
return gl;
}
2.着色器源码:
// =======================================
// 顶点着色器和片元着色器
// =======================================
var vsSource = `
attribute vec3 a_Position;
attribute vec4 a_Color;
varying vec4 v_Color;
void main() {
gl_Position = vec4(a_Position, 1.0);
v_Color = a_Color;
}
`;
var fsSource = `
#ifdef GL_ES
precision mediump float;
#endif
varying vec4 v_Color;
void main() {
gl_FragColor = v_Color;
}
`;
3.需要对着色器进行编译及使用:
function loadShader(gl, type, source) {
// 1.创建着色器对象
var shader;
if(type === "vertex") {
shader = gl.createShader(gl.VERTEX_SHADER);
} else if(type === "fragment") {
shader = gl.createShader(gl.FRAGMENT_SHADER);
}
// 2.向着色器对象中填充着色器程序的源代码
gl.shaderSource(shader, source);
// 3.编译着色器
var compiled = gl.getShaderParameter(shader,
if (!compiled) {
var error = gl.getShaderInfoLog(shader);
console.log('Failed to compile shader: ' + error);
gl.deleteShader(shader);
return -1;
}
// 4.返回着色器对象
return shader;
}
function initShader(gl, vertSource, fragSource) {
// 加载顶点着色器和片元着色器
var vertShader = loadShader(gl, "vertex", vertSource);
var fragShader = loadShader(gl, "fragment", fragSource);
if(!vertShader || !fragShader) {
return null;
}
// 1.创建着色器程序
var shaderProgram = gl.createProgram();
// 2.为程序对象分配着色器
gl.attachShader(shaderProgram, vertShader);
gl.attachShader(shaderProgram, fragShader);
// 3.连接程序对象
gl.linkProgram(shaderProgram);
// 创建失败, alert
if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) {
alert('无法初始化着色器程序: ' + gl.getProgramInfoLog(shaderProgram));
console.log(gl.getProgramInfoLog(shaderProgram));
return null;
}
// 4.使用程序对象
gl.useProgram(shaderProgram);
gl.program = shaderProgram;
return true;
}
4.创建三角形对象:
function createTriangle(gl) {
var verts = new Float32Array([
0.0, 0.5,
-0.5, -0.5,
0.5, -0.5,
]);
var colors = new Float32Array([
1.0, 0.0, 0.0,
0.0, 1.0, 0.0,
0.0, 0.0, 1.0,
]);
var vSIZE = verts.BYTES_PER_ELEMENT;
var vertexBuffer = gl.createBuffer();
var cSIZE = colors.BYTES_PER_ELEMENT;
var colorBuffer = gl.createBuffer();
var triangle = {
vertsArray: verts,
colorsArray: colors,
vertBuffer: vertexBuffer,
colorBuffer: colorBuffer,
vSIZE: vSIZE,
cSIZE: cSIZE,
nVert: 3,
primType: gl.TRIANGLES
};
return triangle;
}
5.类似地,创建矩形对象:
function createSquare(gl) {
var verts = new Float32Array([
0.5, 0.5,
0.5, -0.5,
-0.5, 0.5,
-0.5, -0.5
]);
var colors = new Float32Array([
1.0, 0.0, 0.0,
0.0, 1.0, 0.0,
0.0, 0.0, 1.0,
1.0, 1.0, 0.0
]);
var vSIZE = verts.BYTES_PER_ELEMENT;
var vertexBuffer = gl.createBuffer();
var cSIZE = colors.BYTES_PER_ELEMENT;
var colorBuffer = gl.createBuffer();
var square = {
vertsArray: verts,
colorsArray: colors,
vertBuffer: vertexBuffer,
colorBuffer: colorBuffer,
vSIZE: vSIZE,
cSIZE: cSIZE,
nVert: 4,
primType: gl.TRIANGLE_STRIP
};
return square;
}
6.初始化缓存:
function initBuffer(gl, obj) {
gl.bindBuffer(gl.ARRAY_BUFFER, obj.vertBuffer);
gl.bufferData(gl.ARRAY_BUFFER, obj.vertsArray, gl.STATIC_DRAW);
var a_Position = gl.getAttribLocation(gl.program, 'a_Position');
gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, obj.vSIZE * 2 , 0);
gl.enableVertexAttribArray(a_Position);
gl.bindBuffer(gl.ARRAY_BUFFER, obj.colorBuffer);
gl.bufferData(gl.ARRAY_BUFFER, obj.colorsArray, gl.STATIC_DRAW);
var a_Color = gl.getAttribLocation(gl.program, 'a_Color');
gl.vertexAttribPointer(a_Color, 3, gl.FLOAT, false, obj.cSIZE * 3 , 0);
gl.enableVertexAttribArray(a_Color);
}
7.主程序入口:
window.onload = function main() {
var canvas1 = document.getElementById('webgl-1');
var gl1 = initWebGL(canvas1);
initShader(gl1, vsSource, fsSource);
var obj1 = createSquare(gl1);
initBuffer(gl1, obj1);
drawScene(canvas1, gl1, obj1);
var canvas2 = document.getElementById('webgl-2');
var gl2 = initWebGL(canvas2);
initShader(gl2, vsSource, fsSource);
var obj2 = createTriangle(gl2);
initBuffer(gl2, obj2);
drawScene(canvas2, gl2, obj2);
};
8.完成!