Lesson 1 三角与方块的故事
21,268 次浏览
HiWebGL译者声明:因为译者个人方便的原因,我们将原教程中的第三方图形库由glMatrix改为Oak3D实现,这不影响到Demo的最终效果和实现,也不影响到WebGL的讲解和学习。原教程正文中相应的代码和讲解也为做了相应修改!本教程由HiWebGL翻译整理,转载请注明出处!
关于Oak3D:Oak3D是一套简单易用、性能优越的WebGL Javascript Library。您可以在他们的主页找到更多信息。Oak3D主页:
欢迎来到我的第一个WebGL教程!这一课的内容是基于NeHe的OpenGL教程的第2章的,对于学习3D图形游戏开发来说这是一个很受欢迎的教程。在这一课中将会展示如何在网页中绘制一个三角形和一个矩形。也许这看起来一点都不酷,但是却能很好的介绍如何建立WebGL;如果你明白了其中的原理,剩下的部分将会变得相当简单……
下面你看到的这张图片(是图片,不是真正的WebGL渲染哦~)就是我们最重要完成的效果:
如果你已经准备好了支持WebGL的浏览器,那请点击这里在新窗口中打开一个真正的WebGL页面。如果你的浏览器不支持WebGL,请点击这里。
下面开始说说它是如何工作的……
事先声明一下,本系列的教程是针对那些已经具备相应编程知识但没有实际3D图形经验的人的;目标是让学习者创建并运行代码,并且明白代码其中的含义,从而快速地创建自己的3D Web页面。我编写这套教程是因为我在独立学习WebGL,所以教程中可能(非常可能)会有错误,所以还请风险自担。尽管如此,我还是会不断的修正bug和改正其中的错误的,所以如果你发现了教程中的错误,请告诉我。
有两种方法可以获得上面实例的代码:在实例的独立页面中选择“查看源代码”;你也可以在这里下载到打包好的实例代码。得到代码之后,用你喜欢的文本编辑器打开。即使你对OpenGL已经了解了个大概,第一眼望去,你还是会感觉到一种摸不着头脑的沮丧。代码的开始我们先定义了一对着色器,这可是一个通常被认为相对高级的概念。但是别失去信心,实际上它比看起来要简单得多。
和许多程序类似,这个WebGL页面一开始定义了一系列低级别的函数提供给底部那些高级别的代码使用。为了解释这些函数,我会用我的方式从代码底部开始讲起,所以请跟着我从底部开始看起。
在代码底部你会看到如下的HTML代码:
186 187 188 189 190 191 192 193 194 195 196 197 198 > WebGL中文教程,由HiWebGL翻译整理,感谢>Oak3D> >> ></canvas> >> </body>
整个Demo页面中只有这是一段完整的页面body部分的代码,其余的都是Javascript代码(你也许会看到一些其他的东西,那是我用来做站点统计的,所以请忽略不计)。显然我们可以在<body>中插入其他的HTML代码,以使WebGL图形可以嵌入到普通的网页中。在这个独立页面中我们只是简单的插入了一条返回课程正文的链接,而<canvas>标签就是3D图形的部分。Canvas是HTML5中的新概念,它支持使用Javascript来绘制2D图形和通过WebGL来绘制3D图形。我们只需要简单的指定canvas标签中的布局的属性,然后把所有建立WebGL的代码都放到一个叫做webGLStart的Javascript函数中,它在页面加载后被调用使你可以看到绘制的图形。
让我们把鼠标滚轮向上滚滚来看一下这个函数:
167 168 169 170 171 172 173 174 175 176 177 canvas initGL(canvas); initShadersinitBuffers gl.gl. drawScene
它调用了其他函数来初始化WebGL以及之前提到的着色器,并传递给我们将要绘制3D图形的canvas元素模型,然后使用initBuffers来初始化了一些数组对象。这些数组对象用于储存我们将要绘制的三角形和矩形的细节,稍后我们会详细解释这一部分。接下来,函数对WebGL进行了一些基本的设置,具体的含义是当我们清空canvas时应当把颜色设置为黑色,并且要启用深度检测(这样在后面的物体就会被前面的物体遮挡住)。这些设置都是调用gl对象的一些方法完成的,我们稍后来解释它是如何初始化的。最后,函数调用了drawScene函数,你从名字函数名就能看出来,它的用途是使用数组对象来绘制三角形和矩形。
我们稍后会详细讲解initGL和initShaders的,因为对于理解这个页面是如何工作来说它们相当重要。但是首先,我们还是来看看initBuffers和drawScene。
先来一步一步的说说initBuffers:
118 119 var triangleVertexPositionBuffer; var squareVertexPositionBuffer;
我们声明了两个全局变量来存放数组对象(Array Buffer Object)。(实际上在正式的WebGL页面上你不需要为场景中的每个物体分别声明一个全局变量,我们这里这样做是因为在学习之初,解释起来更加容易。)
接下来:
121 122 triangleVertexPositionBuffer
我们创建了一个数组对象来储存三角形的顶点位置。顶点是在3D空间中定义我们要绘制的图形的点。对于三角形来说,我们需要定义3个点(我们一会就要这么做了)。这个数组对象位于显卡中;在初始化代码里,我们把储存有顶点位置信息的数组对象放到显卡中,当我们需要绘制场景的时候,实际上等于告诉WebGL说“按照我之前告诉你的画出这些形状”。这样可以使得我们的代码更加有效率,特别是当我们需要绘制一个动画场景的时候,会想要在1秒钟内画10次物体来模拟运动的效果。当然,目前只是3个顶点的位置信息,即使不放入显卡中也不会消耗太多的资源,但是当你要处理一个大一点的模型例如有好几万个顶点的时候,这种处理方式就会显示出它的优点。接下来:
123 gl.triangleVertexPositionBuffer);
这一行代码告诉WebGL要为下面的操作指定一个数组对象。这个“当前数组对象”(Current Array Buffer)的概念会一直存在下去,函数只能对当前数组对象进行操作而不允许你为函数指定一个数组对象。很奇怪是吧!但我想这背后一定有一个绝妙的可以提高性能的理由吧。
124 125 126 127 128
然后,我们用Javascript的列表的形式定义了我们的顶点位置信息。你可以看出来这是一个以(0,0,0)为中心的等腰三角形。
129 gl.Float32Array