因为WebGL并没有内建任何关于这个矩阵的操作,所以我们必须使用这个语句用来告知WebGL我们当前的模型视图矩阵(以及投影矩阵,这个概念稍后我们再说)。尽管你已经可以通过修改mvMatrix变量来进行任何移动和旋转,但是这些还都只存在于Javascript的私有空间中。而setMatrixUniforms这个函数将会超越网页文件的范畴,将这些操作推送到显卡中去。
随着这一步的完成,WebGL已经知道了一个用来表示顶点位置信息的数字数组以及我们的矩阵。下一步将会告诉WebGL用它们来做什么。
157 gl.triangleVertexPositionBuffer.
换一种通俗的说法就是“用之前我给你的顶点数组来绘制一个三角形,顶点从item 0开始一直到numItems的值”。
到此为止,三角形绘制完毕。记下来我们看看如何绘制矩形。
159 mvMatrix
开始我们先把我们的模型视图矩阵向右移动3个单位。记住,我们之前的位置是中心偏左1.5个单位、中心偏内7个单位,现在我们的位置应该是中心偏右1.5个单位、中心偏内7个单位。下面:
160 161 gl.squareVertexPositionBuffer); gl.squareVertexPositionBuffer.
我们告诉WebGL去使用矩形的数组对象来获得顶点位置信息。
162 setMatrixUniforms
我们把模型视图矩阵和投影矩阵再次推送到显卡端,于是我们终于可以:
163 gl.squareVertexPositionBuffer.
开始绘制矩形。什么?你问我说怎么会出现一个三角形带的绘制方法?好吧,这的确是一个三角形带。但是它更实用,首先用前三个顶点绘制一个三角形然后用这个绘制完成的三角形的后面两个顶点加上第四个顶点来绘制第二个三角形。这样就用投机取巧的方法绘制出了一个矩形。在更复杂的实例中,这的确是一个很实用的方法来绘制复杂表面,当然如果可以的话。
不管如何,到此我们结束了drawScene函数。
164 }
如果你能坚持看到这里,一定跃跃欲试准备开始一番试验。拷贝代码到你本地或者点击这里下载打包好的代码。在本地运行一下看看是否正常,然后试着改变一下顶点位置;现在的场景还特别平坦,所以再试着改变一下矩形Z轴的位置,改成2或者-3,看看它是否变大或者变小,也就是变近或者变远。或者改变其中一个或两个值,看一下矩形在透视中的变形。是不是很神奇呢?慢慢来,别着急,我会等着你的!
……
好吧,你终于回来了。那让我们来看看之前我们忽略掉的函数吧。如同我之前说过的,如果你很乐于忽略这些细节和工作原理并且仅仅是复制粘贴这些函数的代码,例如initBuffers,你也许可以绘制出有趣的WebGL页面(还不仅是黑白,下节课我们就要讲到颜色了)。但是这些细节和工作原理其实并不难理解,而理解了它们会帮助你创作出更好地WebGL页面的。
你决定继续看下去?好吧,非常感谢!让我们来看看这些无聊的函数中的第一个,这个被webGLStart函数调用的叫做initGL的函数。它位于代码的最顶端,如下:
33 34 35 36 37 38 39 40 41 42 43 44 gl gl.gl.egl
这段代码很简单。你也许已经注意到了,在initBuffers和drawScene函数中频繁的提及一个叫做gl的对象,每次提及的时候通常都与一些WebGL核心的东西有关。在上面的函数中,明确了这个核心的东西的概念,那就是WebGL上下文(WebGL Context),并且从canvas那里获得了一个拥有标准名称的上下文。(也许你会问,上下文的标准名称会不会变呢?比如从“experimental-webgl”变成“webgl”。是的,也会说不准哪天就变了。但到时候我会更新这篇教程的,所以请关注我们的网站吧!)一旦我们获得了上下文,我们就可以使用之前提到的Javascript的动态定义对象属性的优点(或者有人认为是缺点),在上下文中为任何对象创建新的属性,比如canvas的宽度、长度和其他相关数据。到这里,我们的WebGL上下文已经建立起来了。
在调用initGL之后,webGLStart又调用了initShaders函数。这个函数,毫无疑问的,是用来初始化着色器的。我们等会再聊这个函数,先让我们看看之前说过的模型视图矩阵和投影矩阵吧。
108 109 var mvMatrix; var pMatrix;
我们定义了一个名叫mvMatrix的变量来储存模型视图矩阵,另一个叫pMatrix的变量来储存投影矩阵。这里有必要多说说投影矩阵。也许你还记得,在drawScene函数的开始部分,我们把这个变量用Oak3D中的okMat4Proj函数建立了我们的透视。这是因为WebGL并不直接支持透视,就像它同样也不直接支持模型视图矩阵一样。然而就如同把移动物体、旋转物体等几何变换封装到模型视图矩阵中一样,表现出让远处的物体看起来小一些的这种透视效果也是矩阵的拿手好戏。现在不用猜也知道,投影矩阵就是用来做这件事情的。okMat4Proj函数根据宽高比和视野信息,将我们需要的透视效果的值填充到矩阵中。
现在我们已经了解了除setMatrixUniforms 函数以外的所有部分,如同我之前说过的,这个函数可以将模型视图矩阵和投影矩阵从平易近人的Javascript推送到高深莫测的WebGL中。WebGL和着色器其实是内在关联的,让我们先来了解一下一些背景知识。
你也许会问,到底什么是着色器? 好吧,从3D图形学历史的角度来讲,它的确曾经扮演过和它名字一样的角色——二进制码告诉系统如何在绘制一个场景之前进行渐变或上色。但随着时间的推移,着色器开始渐渐扩展自己的应用范围,现在应当把它定义为二进制码在绘制一个场景之前做任何想要做的事情。这的确非常实用,一是因为这些操作是在显卡中进行的,所以运行速度非常快;二是因为这些操作调用起来非常方便,即使在这种简单的实例中。
我们之所以在一个WebGL的初级实例中引入着色器的概念(要知道在OpenGL中,到中级开发才会出现着色器啊!),是因为我们要使用着色器来进入WebGL系统,将我们的场景的模型视图矩阵和投影矩阵的运算交给显卡来进行,而不是在相对较慢的Javascript中移动每一个点和每一个顶点。它是如此难以置信的实用,提高了我们的效率,所以我们值得花时间去学习和了解它。
下面,我们看看是如何设置着色器的。你也许会记得,webGLStart调用了initShaders函数,让我们一步一步来看:
83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 var shaderProgram; fragmentShader vertexShader shaderProgram gl.gl.gl. gl. gl.