WebGL入门教程3 - Canvas、Context、API和绘制一个矩形
iefreer 发表于 2016-05-26 00:10:54
标签: webgl, canvas, 教程
在教程2中,我们已经讲述了计算机图形处理硬件结构和流水线。
在本文中,我们将开始讲述WebGL的具体应用程序编程接口(API)。
WebGL应用程序编程步骤分为以下几步:
所有的WebGL渲染都是在一个上下文(context)中完成的,context是一个JavaScript DOM对象,提供了完整的WebGL API。这和canvas 2D绘图上下文类似。下面的代码演示了如何从canvas DOM元素中获取WebGL context:
function initWebGL(canvas) { var gl; try { gl = canvas.getContext("webgl"); } catch (e) { var msg = "Error creating WebGL Context!: " + e.toString(); alert(msg); throw Error(msg); } return gl; }上面代码中的try/catch用来处理不支持webgl的浏览器,提示一个用户友好的错误信息。
接下来,我们需要设定我们的绘图区域,在WebGL中,这被称为Viewport,可以通过context的viewport()方法来获得:
function initViewport(gl, canvas) { gl.viewport(0, 0, canvas.width, canvas.height); }上面的gl对象是由initWebGL方法所获取的渲染上下文。
缓存,数组缓存和类型化数组(Typed Arrays)WebGL的绘制对象是通过原型(primitives)来定义的,比如三角形数组,点和线段,在教程2中我们对此有过详细描述。Primitives使用数组数据,称之为缓存(buffers),定义了顶点的位置信息。下面的例子演示如何创建一个单元正方形 (1 × 1)的顶点数据,通过一个JavaScript对象返回结果,包含顶点缓存数据,三个浮点数来保存x, y和z坐标,要绘制的顶点数目,用来绘制矩形的原型类型,在这里是去除重叠线段的三角形(GL_TRIANGLE_STRIP, 在教程2也有过描述)。
// 创建一个矩形的顶点数据用户绘制 function createSquare(gl) { var vertexBuffer; vertexBuffer = gl.createBuffer();//创建缓存 gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);//设置为gl当前数组缓存 var verts = [ .5, .5, 0.0, -.5, .5, 0.0, .5, -.5, 0.0, -.5, -.5, 0.0 ]; gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(verts), gl.STATIC_DRAW); var square = {buffer:vertexBuffer, vertSize:3, nVerts:4, primtype:gl.TRIANGLE_STRIP}; return square; }上面使用了一个Float32Array类型,这是一个类型化数组,是为了WebGL而引入的新JS数据类型,和普通数组的访问方法类似,但是要快得多并且占用更少的内存。(关于类型化数组的最新规格,请阅读)。我们知道JavaScript是弱类型语言,你使用一个变量时,不需要定义其数据类型,但C语言则相反是一个强类型语言,如果未定义类型,编译时就会报错,类似的,GLSL中的变量都有限定符(qualifier)、类型(type)和精度(precision),从JavaScript传递给GL的变量也必须具备指定的类型。对于数组,我们基本上就是使用Float32Array,暂时不用考虑浮点精度。
限定符(Qualifiers)类型(Types)矢量(Vector):
如果你不熟悉几何向量或元组,你可以想他们作为一个固定大小的数组,每个数组元素代表某个维度上的度量。通常,我们用矢量来表示空间坐标(x,y,z)或颜色(r,g,b,a)。vec4(1,1,1,1)构造一个4维的向量。uniform vec3 u_myuniform; 声明一个三维恒量。片段的颜色始终是一个vec4(red,green,blue,alpha),元素取值范围在0 - 1之间。
矩阵变换(Matrices)我们在教程2中讲述顶点着色器的时候,提到了多个矩阵变换,模型变换、视图变换和投影变换。
首先我们需要一个矩阵来定义正方形在3D坐标系统中相对于camera的位置,这个就是模型加视图变换(ModelView matrix),在下面的例子中,我们把正方形放到远离相机3.333单元的地方(z=-3.333)。还有一个矩阵定义投影变换,用来把3D相机空间的对象映射到2D的Viewport上。本例中,我们定义45°的观察角度:
function initMatrices() { // The transform matrix for the square - translate back in Z // for the camera modelViewMatrix = new Float32Array( [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 3.333, 1]); // The projection matrix (for a 45 degree field of view) projectionMatrix = new Float32Array( [2.41421, 0, 0, 0, 0, 2.41421, 0, 0, 0, 0, 1.002002, 1, 0, 0, 0.2002002, 0]); }第2个矩阵难于阅读和编写,实际上不需要来自己算矩阵的值,我们可以利用已有的JS矩阵计算开发库()来简化编程。
坐标系统(Coordinate System)