这学期选修了计算机图形学这门课,最近刚开始接触WebGL,目前只学到二维的部分,尝试绘制一只平面的小鸡。
效果图
首先上效果图:
下面直接进入代码部分:
drawCircle.html
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title>DrawCircle</title>
<script id="vertex-shader" type="x-shader/x-vertex">
attribute vec4 vPosition;
uniform mat4 u_transMat;
void main(){
gl_Position = u_transMat * vPosition;
}
</script>
<script id="fragment-shader" type="x-shader/x-fragment">
precision mediump float;
uniform vec4 u_FragColor;
void main(){
gl_FragColor = u_FragColor;
}
</script>
<script type="text/javascript" src="../Common/webgl-utils.js"></script>
<script type="text/javascript" src="../Common/initShaders.js"></script>
<script type="text/javascript" src="drawCircle.js"></script>
</head>
<body>
<canvas id="gl-canvas" width="512" height="512">
Oops ... your browser doesn't support the HTML5 canvas element
</canvas>
</body>
</html>
在html文件中,声明了两个着色器。
顶点着色器内,设置了attribute变量vPosition用于记录顶点的属性,uniform变量u_transMat为变换矩阵,用于对绘制出的图案进行旋转平移操作。
片元着色器内,首先设置精度为中低精度,uniform变量u_FragColor用于记录片元颜色。
body中,声明一个canvas画布,所有的绘制都在画布上进行。
需要注意的是,gl_Position的值是用变换矩阵 * 顶点坐标向量得到的,变换矩阵和顶点坐标向量的位置不能交换,因为我们最终需要得到的gl_Position是一个四阶行向量。
drawCircle.js
js代码部分比较长,让我分解为多个部分。
通过对小鸡的分析,不难得知,组成该图形的图形为三角形、圆形、线段。
1. 我们首先来介绍绘制圆的函数getCircleVertex。
// 画圆
// 半径r 面数m 度数c
function getCircleVertex(r, m, c) {
var arr = [];
var addAng = c / m;
var angle = 0;
for (var i = 0; i < m; i++) {
arr.push(Math.sin(Math.PI / 180 * angle) * r, Math.cos(Math.PI / 180 * angle) * r, 0, 1.0);
arr.push(0.0, 0.0, 0.0, 1.0);
angle = angle + addAng;
arr.push(Math.sin(Math.PI / 180 * angle) * r, Math.cos(Math.PI / 180 * angle) * r, 0, 1.0);
}
return arr;
}
由于WebGL没有提供圆这个基本图形,于是我们把圆细分,通过绘制多个三角形来达到圆的效果。该函数它有三个参数:r表示圆的半径,m表示绘制该圆需要的三角形面数(即个数,数字越大,圆的效果越好),c表示需要绘制的度数(c取360时为整圆,取180时为半圆,以此类推),函数返回值为存储了构成圆的每个三角形的三个顶点的数组(有点绕)。
观察for循环内部,我们使用JavaScript内置的Math.sin()和Math.cos()来计算三角形(可看做扇形)圆心角的正余弦,但这两个方法必须接收弧度值,所以要先把角度转换为弧度值。
由于最后我们使用gl.TRIANGLES来绘制三角形,因此每一次for循环就将三角形的三个角的坐标加入到arr数组中。
2. 接着进入js主体代码部分
window.onload = function init () {
var canvas = document.getElementById( "gl-canvas" );
var gl = WebGLUtils.setupWebGL( canvas );
if ( !gl ) {
alert( "WebGL isn't available" ); }
// 设置窗口大小
gl.viewport( 0, 0, canvas.width, canvas.height );
gl.clearColor( 0.0