版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、尝试WebGL的第一步就是让浏览器支持它。现在,这意味着你必须使用特殊的预览发布版本,因为它甚至还不是测试版。幸运的是,这非常容易!WebGL 不能运行在我所知道的任何版本的Internet Explorer上,但对于其他三大主流浏览器,情况如下: Firefox:WebGL工作在Windows、Mac OS X和Linux中每日构建(Nightly Build,也叫Daily Build),是将一个软件项目的所有最新代码取出,从头开始编译,链接,运行测试软件包对代码进行单元测试并对主要功能进行测试,发现错误并报告错误的完整过程。译者注)的Firefox开发版上。点击此处了解如何安装支持Web
2、GL的Firefox。如果你使用PC机,建议用Firefox。Safari:Safari的WebKit核心支持WebGL,但只针对Mac电脑的雪豹操作系统(即OS X 10.6)(它曾工作在版本10.5又名豹操作系统上,但遗憾的是现在不再被支持了)。如果你在使用雪豹操作系统,我建议你选择Safari;如果你仍旧使用豹操作系统,我建议你使用Chromium 或Minefield。点击此处了解如何安装支持WebGL的Safari。Chrome:在Chrome上尝试WebGL的最佳方式是使用每日构建的多个Chromium浏览器版本之一,Chromium开源项目是Chrome的基础。点击此处了解如何获
3、取可在Chromium上运行的WebGL。Firefox“不稳定的”Firefox开发版叫做Minefield。它每天更新,实际上现在相当稳定:在设置上有一个小调整,最近我还没有看见它崩溃(我使用它做一切事情)。同时也可以安装一个普通版本的Firefox。因此,如果你不想用它或者只是想切换回普通版本一段时间,你不必去卸载。获取Minefield: 登陆到每日构建网页上去获取与你电脑匹配的版本。 安装它(当你安装时,你需要退出所有正在运行 的Firefox实例)。 启动Minefield。 打开“about:config”页面 查找“webgl” 将“webgl.enabled_for_all_
4、sites”的值改为true。 在2010年2月9日,我也建议你 将“”设置为false这将禁用最近添加的一个功能,我发现特别是当你浏览器有一个正在显示PDF文件的不可见标签栏时,它往往导致浏览器死锁。(感谢Vladimir Vukievi为此提供了资料。)接下来,点击此处尝试一些WebGL网页。如果他们不工作,可能是你的图形驱动程序不支持OpenGL 2.1。如果是这种情况,你应该尝试更新驱动程序,如果这不起作用,你可以用软件渲染运行WebGL,这种方法明显会比全硬件加速图形卡要慢。但是这比什么都没有好。如下是Vladimir使用MESA软件渲染库的方法。对于那些没有最新的OpenGL驱动或
5、者不能获取驱动的windows用户来说,你可以下载实现OpenGL的Mesa软件的windows版本来进行软件渲染。它不会很快,但是足以让你明白WebGL是怎么回事和运行一些演示。为了使用Mesa,请下载webgl-mesa-751.zip,然后将它解压缩在你的电脑上。它有一个OSMESA32.DLL文件,你需要告知Firefox它的位置:打开about:config页面,设置webgl.osmesalib的值为OSMESA32.DLL路径。如果你将其展开在“C:temp”,则其值应设为“C:temposmesa32.dll”。然后将webgl.software_rendering的值设为tr
6、ue即可。Safari记住,Safari只支持运行在Mac电脑雪豹操作系统(OS X 10.6)上的WebGL;如果你工作在豹操作系统 (版本10.5)、PC或者linux上,那么你将不得不使用Firefox或者Chromium。(如果你工作在较早版本的OS/X上,我就不知道你该用什么浏览器了 :-( )如果你工作在雪豹上,为了使其运行,你需要: 确保你的Safari版本至少为4.0; 下载并安装每日构建的WebKit; 启动终端,运行命令: 运行刚安装的WebKit。(感谢Chris Marrin为此提供了资料。)接下来,点击此处尝试一些WebGL的网页。Chromium目前,Chrome开
7、发人员建议你在Chrome中获取WebGL的方法是使用每日构建的Chromium浏览器,这个开源浏览器是Chrome浏览器的基础。对于不同的操作系统来说,这个过程有一些不同。这里提供了针对Windows 、Macintosh 和Linux的方法。(警告:我自己只尝试了针对windows的方法,但是我得知其他方法也是可用的。如果有问题,请在下面留言 :-)对于Windows 进入下载页面,获得chrome-win32.zip 解压缩文件到合适的地方。 打开一个命令窗口,进入你解压缩chrome-win32.zip的目 录。 确保您没有运行浏览器 运行以下命令:chrome.exe -enable
8、-webgl对于Macintosh 进入下载页面,获得chrome-mac.zip 解压缩文件到合适的地方。 打开一个终端窗口,进入你解压缩chrome-mac.zip的目 录。 确保你没有运行浏览器 运行以下命令:./Chromium.app/Contents/MacOS/Chromium -enable-webgl对于Linux 如果你使用32位Linux,到32位的下载网页获得chrome-linux.zip。如果你想要一个64位版本,你可以到64位的下载页面,在页面的底部找到最新的build目录,进入并从那里获得chrome-linux.zip。 解压缩文件到合适的地方,进入你解压缩c
9、hrome- linux.zip的目录。 确保你没有运行浏览器。 运行以下命令:./chromium -enable-webgl(感谢Mohamed Mansour为此提供了资料。)接下来,点击此处尝试一些WebGL的网页。一些例子一旦你安装好浏览器,你应该能够看到WebGL的内容。这里是一个完整性检查:WebGL第二课的结果。你应该看到一个染有红、绿、蓝三色的三角形和一个浅蓝色的正方形。如果你没有看到正方形和三角形,请在下面留言,我会尽力提供帮助。如果能看到,那一切就绪!这里有一些有趣的网页: 来自Murphy的一个旋转的三维棋盘球体。我的一个演示:弹跳曼德尔布罗立方体。来至谷歌:一个闪亮的
10、茶壶(点击并拖动旋转它),“San Angeles”和一些比较炫的粒子效果。来至Ilmari Heikkinen,一个立方螺旋纺纱和基于立方体的画图程序。来至Pl4n3,一个友好的外来生物.一个看起来相当不友好的外来生物的游戏的开始部分。Copperlicht是一个建立在WebGL上面的高级图书馆,这是他们雷神之锤级别的接口。一个使用WebGL的真实世界:ChemDoodle3D在网页上显示分子结构。来至Jacob Seidelin,两个惊人的图形演示一个音乐太阳能系统和WebGL的世界。一些来至演示场景喜欢创建令人吃惊小程序的人的WebGL接口:Dag grens port of rolas
11、 Puls demo、Metatunnel、一个Escher-Droste效果的演示、以及Four dollar Plastic Laminator(最后一个需要几秒钟才可以开始-这是值得等待的!)。最后,我看到的第一个WebGL演示(那是2009年9月的事了),但不幸的是现在只支持Firefox:Vladimir Vukievis的孢子生物(使用鼠标旋转)。这是我的第一篇关于WebGL入门的文章,如果你想进一步了解如何创建自己的WebGL网页,你可以查阅我的WebGL第一节课。学习WebGL 第1课 一个三角形和一个正方形欢迎来到WebGL教程的第一课!这一课以NeHeOpenGL教程的第二
12、课内容为基础,NeHe OpenGL是一套针对游戏开发人员讲解3D图形技术的流行教程。本课将向你显示如何在一个网页上绘制一个三角形和一个正方形。也许它本身并不令人激动,但它却是一个不错的WebGL基础介绍;如果你理解它是如何工作的,那么剩下的学习将变得很简单.在支持WebGL的浏览器上运行本课代码显示如下:如果你已经有了一个支持webGL的浏览器,点击此处你将看到WebGL的实时版;如果你还没有,从这里你可以获取一个。更多关于它是如何工作的细节,请看下面.一点提示:这些课程是面向那些具有一定编程知识但没有实际3D图形开发经验的开发人员的;其目的是让你对代码层上发生了什么事有很好的理解,以便你能
13、尽可能快地创建出自己的3D网页。我一边自学WebGL一边写这个教程,因此有可能(甚至很有可能)有些概念是错误的;然而,一旦我知道有错误,我就会去修改和纠正它们。所以,如果你发现什么错误的话,请留言让我知道。获取这个例子的代码有两种方法:一种就是当你观看实时版的时候点击“查看源码”的链接,另一种是你从GitHub的代码库获取(包括以后课程的代码)。对于任一种方式,一旦你获得源码,你就可以用你喜欢的文本编辑器打开并查看它。即使你已经比较熟悉OpenGL,但是当你初次见到它时,你也会望而生畏。首先,我们定义一对渲染器,一般认为渲染器相对高级一些。但是不要害怕,它实际上比它看起来要简单一些。像大多数程
14、序一样,这个WebGL网页从定义一些下层函数开始,它们被位于网页底部的上层代码调用。为了解释这个问题,我将按照我的方式从网页底部开始介绍它们。因此,如果你正在浏览代码,请跳到网页的底部。你将看到下面的html代码:rningwebgl /blog/?p=28a href= :/learningwebgl /blog/?p=28这是一个网页完整的body部分,其他的代码是在JavaScript中(如果你是通过“查看源码”方式得到这个代码的话,会看到一些额外用于网站分析的代码,你可以忽略它们)。显然,我们可以将任何数量的普通HTML标签放入body标签内,并在一个普通网页里创建我们的WebGL图像
15、,但是对于这个简单的演示来说,我们只是得到WebGL以及返回到这个博客帖子的链接。同时,canvas标签是3D图形放置的地方。canvas是html5.0的新特性它允许JavaScript脚本在网页中绘制二维和三维(通过WebGL)元素。我们不会指定多于canvas标签本身简单布局属性的其他属性,相反,我们将所有WebGL的安装代码放置在一个叫做webGLStart的JavaScript函数中,一旦网页被装载,这个函数就会被调用。 现在让我们向上翻到这个函数,来看一看它:function webGLStart() var canvas = document.getElementById(les
16、son01-canvas);initGL(canvas);initShaders();initBuffers();gl.clearColor(0.0, 0.0, 0.0, 1.0);gl.clearDepth(1.0);gl.enable(gl.DEPTH_TEST);gl.depthFunc(gl.LEQUAL);setInterval(drawScene, 15);它调用函数来初始化我们前面提到的WebGL和渲染器,传入前面我们想要绘制三维物体的canvas元素,接着它使用initBuffers函数初始化缓冲区;缓冲区用来保留我们要绘制的三角形和正方形的细节稍后我们将更多地谈论此问题。接下
17、来,它对GL引擎做了一些基本设置,就是说当我们清除画布的时候我们应该使其变黑,以及清除操作应当百分之百的清除掉我们正在绘制的物体。同时,我们应该做深度测试(以使位于其它物体后面的被绘制物体隐藏在它们前面的物体之后)。最后,我们使用setInterval函数每隔15毫秒就调用一次drawScene函数。根据函数名就可以知道,drawScene函数是通过使用缓冲区来绘制物体的。稍后我们将回到initGL和initShaders函数上,因为它们对于理解网页如何工作是很重要的。现在让我们先来看看initBuffers和drawScene函数。var triangleVertexPositionBuff
18、er;var squareVertexPositionBuffer;我们声明了两个全局变量来保存缓冲区。(在一个真实的WebGL网页中,你不用对场景中的每一个对象声明一个单独的全局变量,但在这里我们使用它们是为了在第一课中让事情变得简单些:-)接下来:function initBuffers() triangleVertexPositionBuffer =gl.createBuffer();我们为三角形顶点的位置创建一个缓冲区。顶点是三维空间中定义我们正在绘制的图形的形状的点。对于三角形,我们有三个这样的点(稍后我们将设置)。这个缓冲区实际上是图形卡上的内存;在初始化代码中将顶点位置放置在图形
19、卡上,当重绘时,本质上只是告诉WebGL去“绘制先前我告诉你要绘制的物体”。这样,我们就可以使代码运行起来十分有效率。当然,在此例中我们只有三个顶点,将它们绘制到图形卡上不会花费太多的代价但是当你处理具有成千上万个顶点的大型模型时,用这种方法处理将体现出其真正的优势。gl.bindBuffer(gl.ARRAY_BUFFER, triangleVertexPositionBuffer);这行代码告诉WebGL以下任何在缓冲区上的操作都应该使用我们指定的缓冲区。这里有一个“当前数组缓冲区”的概念,以及工作在其上的函数,而不是让你自行定义数组缓冲区。听上去有点奇怪,但我确信这样做是为了获得良好的性
20、能。var vertices = 0.0, 1.0, 0.0, -1.0, -1.0, 0.0, 1.0, -1.0, 0.0;接下来,我们用一个JavaScript数组定义顶点位置。可以看到它们位于一个中心为(0,0,0)的等腰三角形的顶点上。gl.bufferData(gl.ARRAY_BUFFER,new WebGLFloatArray(vertices),gl.STATIC_DRAW);现在,我们创建一个基于这个JavaScript数组的WebGLFloatArray对象,指示WebGL使用它来填充当前的缓冲区,即triangleVertexPositionBuffer。在后面的课程中
21、我们将更多地谈论WebGLFloatArrays,不过现在你只需知道,它是一种将JavaScript数组转换成某种数据的方法,这种数据我们用来传递给WebGL,以填充其缓冲区。triangleVertexPositionBuffer.itemSize = 3;triangleVertexPositionBuffer.numItems = 3;最后,我们对缓冲区设置两个新的属性。WebGL没有内置这两个属性,但是稍后它们将变得非常有用。一件关于JavaScript的好事情(某些人会说是坏事情)是一个对象不必显式地支持某个你想给它设置的属性。因此,尽管这个缓冲区对象以前没有itemSize和num
22、Items属性,但是现在它具有了这样的属性。我们使用它们来表示这个具有9个元素的缓冲区,该缓冲区实际上表示了三个独立的顶点位置(numItems),其中每一个由三个数(itemSize)组成。我们已经完全设置好了三角形的缓冲区,现在轮到正方形了:squareVertexPositionBuffer = gl.createBuffer();gl.bindBuffer(gl.ARRAY_BUFFER, squareVertexPositionBuffer);vertices = 1.0, 1.0, 0.0,-1.0, 1.0, 0.0,1.0, -1.0, 0.0,-1.0, -1.0, 0.0;
23、gl.bufferData(gl.ARRAY_BUFFER, new WebGLFloatArray(vertices), gl.STATIC_DRAW);squareVertexPositionBuffer.itemSize = 3;squareVertexPositionBuffer.numItems = 4;所有这些都很明显正方形有4个顶点而不是3个,因此数组要大一些而且numItems的值不同。好了,我们所要做的是将两个对象的顶点位置放置到图形卡上。现在让我们看看drawScene函数,这个函数是我们使用缓冲区真正绘制我们所看到图形的地方。让我们一步步来看看它:function dra
24、wScene() gl.clear(gl.COLOR_BUFFER_BIT |gl.DEPTH_BUFFER_BIT);第一步:清除画布,以便在画布上绘制图形。接下来: perspective(45, 1.0, 0.1, 100.0);此处我们为想要观看的场景设置透视参数。默认情况下,WebGL将绘制与远端物体同尺寸的近端物体(一种称为正投影的三维类型)。为了使较远的物体看起来较小,需要告诉它一些正在使用的透视参数。对于这个场景,我们的(垂直)视野是45,画布的宽高比是1:1,我们不想看到那些距离观察点近于0.1个单位的物体,也不想看到那些距离观察点远于100个单位的物体。这个perspect
25、ive函数十分有用,但它并不内置于WebGL,因此,它在代码中被定义为应用函数。稍后我将更详细地描述它是如何工作的,但是在不知其细节的情况下也应该清楚如何使用它。现在我们已经设置好perspective函数,我们可以继续绘制一些物体: loadIdentity();第一步是“移动”到三维场景的中心。在OpenGL中,当我们绘制一个场景时,你要告诉它用“当前的”旋转方法在“当前的”位置上绘制每一个物体因此,例如你说“向前移动20个单位,旋转32度,接着绘制机器人”,这非常有用,因为你能将“绘制机器人”的代码封装在一个函数中,然后,只需在调用函数前改变“平移/旋转”参数,就能轻松绘制机器人。当前的
26、位置和旋转信息放在一个矩阵中;正如你可能在学校了解的一样,矩阵可以表示平移(从一个位置到另一个位置的移动),旋转和其他几何变换。现在我不想讲得太多,你可以用一个44(不是33)的矩阵来表示三维空间的任何变换;你从单位矩阵开始这种矩阵表示一种什么都不做的变换,用第一个变换矩阵与之相乘,接着乘以第二个变换矩阵,以此类推。合并后的矩阵在一个变换中表示了所有的变换。我们使用的这个矩阵表示了模型视图矩阵的当前平移/旋转状态,现在你可能已经编制好了loadIdentity函数,该函数将模型视图矩阵转换为单位矩阵,我们可以将其相乘并旋转以得到它。换句话说,它使我们从一个原始的点出发,开始绘制三维世界。细心的
27、读者可能会发现,一开始我讨论矩阵的时候说的是“在OpenGL中”而不是“在WebGL中”。这是因为像perspective函数一样,WebGL没有内置这样的函数;我们不得不自己实现它,或者拷贝一个已经实现好的应用函数。再说一下,我稍后将详细地解释这些应用函数是如何工作的,不过你在不了解其细节的情况下也能使用它们。让我们看一看绘制在画布左边的三角形的代码。 mvTranslate(-1.5, 0.0, -7.0);loadIdentity函数使其移动到三维空间的中心。我们通过向左移动1.5个单位(即沿着X轴的负方向)和向场景中移动7个单位(即远离观察者的方向,也就是沿着Z轴的负方向)开始绘制三角
28、形。(正如你可能猜到的一样,mvTranslate函数通过模型视图矩阵乘以一个带有下列参数的变换矩阵做了一次底层变换。)下一步真正开始绘制图形了!gl.bindBuffer(gl.ARRAY_BUFFER, triangleVertexPositionBuffer);gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, triangleVertexPositionBuffer.itemSize, gl.FLOAT, false, 0, 0);因此,你要记住为了使用其中的一个缓冲区,我们将调用gl.bindBuffer函数来指
29、定一个当前的缓冲区,接着调用在缓冲区执行的代码。我们选择 triangleVertexPositionBuffer来告诉WebGL哪些值应该被用于顶点位置。稍后我将更多地解释其如何工作;现在,你能看到我们正在使用itemSize属性,该属性是我们设置在缓冲区上用来告诉WebGL缓冲区的每项有3个数大小。接下来我们使用setMatrixUniforms();告诉WebGL考虑当前的模型视图矩阵(以及投影矩阵,稍后有详细的解释)。这是必须的,因为WebGL没有内置这个矩阵的参数,但是这些都发生在JavaScript私有域中。setMatrixUniforms把矩阵参数传到图形卡。一旦完成这个函数,
30、WebGL将要处理一组被看做是顶点位置和关于我们矩阵的数值。下一步是告诉WebGL怎么处理这些数值:gl.drawArrays(gl.TRIANGLES,0,triangleVertexPositionBuffer.numItems); 从顶点数组的第0项开始一直到第numItems个元素,将顶点数组绘制成三角形。一旦这个过程结束,WebGL就绘制好了三角形。下一步,我们来绘制正方形:mvTranslate(3.0, 0.0, 0.0)我们一开始将模型视图矩阵向右移动3个单位。记住,我们当前已经向左移动了1.5个单位并远离了屏幕7个单位,因此这次我们只需向右移动1.5个单位,向屏幕移动7个单位
31、。接下来:gl.bindBuffer(gl.ARRAY_BUFFER, squareVertexPositionBuffer);gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute,squareVertexPositionBuffer.itemSize, gl.FLOAT, false, 0, 0); 我们告诉WebGL使用正方形顶点位置的缓冲区setMatrixUniforms();我们再次推到模型视图矩阵和投影矩阵,以至于我们能考虑到最近使用的mvTranslate函数,这意味着我们最终可以绘制这些点。gl.drawArr
32、ays(gl.TRIANGLE_STRIP,0,squareVertexPositionBuffer.numItems);你可能会问:什么是三角形带?嗯,它是一个三角形的条带:)说详细点,三角形带中的头三个顶点定义了第一个三角形,接着这三个顶点中的后两个与下一个顶点一起定义了下一个三角形,以此类推。此例是一种快速的定义正方形的方法。在更复杂的情况下,根据与其近似的由许多三角形组成的图形来定义一个复杂表面可能会是一种真正有用的方法。总之,一旦完成这个过程,drawScene函数就结束了。 到此,你完全可以开始一些实验。从GitHub或者直接从实时版本中拷贝代码到本地文件中;如果你选择后者,你需要
33、用到index.html,sylvester.js和glUtils.js这三个文件。在本地运行代码并确保其可以正常工作,接着尝试改变一些上面提到的顶点位置;特别地,场景立刻会变得十分平坦;尝试改变正方形的Z值为2或-3,你将看到它随着向后或向前移动而变得更大或更小。或者尝试只改变一个或两个顶点,你将发现它会出现视角上的扭曲。 现在我们来看看刚才我们忽略的一些函数。正如我前面所说,如果你愿意忽视这些细节而仅仅是拷贝和粘帖这些在initBuffers函数之前出现的函数,你很有可能侥幸创建出有趣的WebGL页面(哪怕还只是黑白的彩色在下一课介绍)。但是这些细节并非很难理解,同时通过理解它们是如何工作
34、的有助于你将来写出更好的WebGL代码。继续和我一起看看这些细节吗?谢谢:-)首先让我们回避一些最为乏味的函数;第一个被webGLStart调用的函数是initGL。它靠近网页顶部,拷贝在下面以供参考:var gl;function initGL(canvas) try gl = canvas.getContext(experimental-webgl);gl.viewport(0, 0, canvas.width, canvas.height); catch(e) if (!gl) alert(Could not initialise WebGL, sorry :-();这个函数非常简单。你
35、可能已经注意到,initBuffers和drawScene函数经常涉及一个叫做gl的对象,很明显该对象牵涉某种WebGL核心。这个函数获取了这一核心称为WebGL context,它是通过使用标准的context名称请求canvas赋予的(你可能猜测,在某个时候context的名字将从“experimental-webgl”变成“webgl”,那时我将更新我的课程和博客)。一旦得到上下文,我们将使用viewport函数告诉WebGL画布的大小;在后面的课程中我们会回过来讲讲这为什么会很重要;现在,你只需知道该函数调用时需要画布的大小。一旦函数执行完,GL的context就设置好了。调用init
36、GL之后,webGLStart调用initShaders。这个函数用来初始化渲染器。我们稍后再回来看这个函数,因为我们首先要来看看处理模型视图矩阵的应用函数。下面是其代码:var mvMatrix;function loadIdentity() mvMatrix = Matrix.I(4);function multMatrix(m) mvMatrix = mvMatrix.x(m);function mvTranslate(v) var m = Matrix.Translation($V(v0, v1, v2).ensure4x4();multMatrix(m);我们定义mvMatrix变量
37、来保存模型视图矩阵,接着定义使用该变量的loadIdentity和mvTranslate函数以及multMatrix应用函数。如果你知道JavaScript,你就会明白我们在此使用的矩阵代数函数并不是一般的JavaScript的API;事实上它们由先前提到的两个文件所支持,这两个文件位于HTML网页的顶部:第一个文件,Sylvester,是一个处理矩阵和矢量代数的开源JavaScript库,第二个文件是由Vladimir Vukievi开发的Sylvester库的一系列扩展。总之,在这些简单函数和有用的库文件的帮助下,我们可以维护模型视图矩阵。这里需要说明另一个矩阵,就是我前面提到的投影矩阵。
38、你也许记得,WebGL不内置perspective函数。但是模型视图矩阵封装了像移动和旋转物体这样的过程,这正是矩阵擅长的事情。你现在肯定已经猜到,投影矩阵正是这么一个矩阵。下面是其代码:var pMatrix; function perspective(fovy, aspect, znear, zfar) pMatrix = makePerspective(fovy, aspect, znear, zfar);makePerspective函数是另一个定义在glUtils.js文件中的函数;它返回一个我们需要应用在指定的全景透视图中的特定矩阵。现在,我们除了setMatrixUniforms
39、函数外已经浏览了所有函数,正如我先前所说,这个函数将模型视图矩阵和投影矩阵从JavaScript中转移到WebGL中,并与渲染器相关。由于它们相互关联,所以我们将从一些背景知识开始。你也许会问:什么是渲染器?在三维图形的历史上,渲染器曾经“名副其实”过:在绘制一个场景之前,它指示系统如何渲染或着色。然而,随着时间的推移,它的功能日益增强,以至于如今要这样定义它才更为合适:渲染器是这样一些代码,在一个场景开始绘制之前,它能对场景的任何部分做任何处理。这的确十分有用,由于它运行在图形卡上,所以它能很快运行且能很便利地做各种变换,哪怕是在这个简单的例子中。我们引入渲染器是为了一个简单的WebGL例子
40、(在OpenGL教程中这至少算是“中级”),该例子能运行在图形卡上且使用渲染器获得WebGL系统。它把模型视图矩阵和投影矩阵应用到场景中,而不需要使用相对较慢的JavaScript来移动场景中的每一个点和每一个三角形顶点。这相当有用并且值得额外的开销。下面是如何设置它们。正如你所记得的,webGLStart函数调用initShaders函数,那么让我们一步一步地来看一看:var shaderProgram;function initShaders() var fragmentShader = getShader(gl, shader-fs);var vertexShader = getShad
41、er(gl, shader-vs);shaderProgram = gl.createProgram();gl.attachShader(shaderProgram, vertexShader);gl.attachShader(shaderProgram, fragmentShader);gl.linkProgram(shaderProgram);if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS) alert(Could not initialise shaders);gl.useProgram(shaderProgram);正
42、如你所见,它使用getShader函数来获得两个渲染器:一个片段渲染器和一个顶点渲染器,接着将两者绑定在一个WebGL“程序”上。一个程序是一段放置在系统WebGL上的代码;你可以把它视作一种运行在图形卡上的特定方式。正如你所期望的,你可以将它和一些渲染器联系在一起,每个渲染器都可以视为程序中的一个代码片段;确切地说,每个程序可以拥有一个片段渲染器和一个顶点渲染器。让我们简单地看一下:shaderProgram.vertexPositionAttribute =gl.getAttribLocation(shaderProgram, aVertexPosition);gl.enableVerte
43、xAttribArray(shaderProgram.vertexPositionAttribute); 一旦设置好程序并绑定了渲染器,函数将得到一个“属性”的引用,该属性存储在vertexPositionAttribute对象中。我们再次利用JavaScript把任一字段设置在任一对象上;默认情况下对象没有vertexPositionAttribute字段,但是对于我们来说将两个值保留在一起是很方便的,因此我们仅设置程序中新字段的属性。那么,vertexPositionAttribute是做什么的呢?也许你还记得,我们在drawScene函数中使用过它;如果你回过去看一看从适当的缓冲区设置三
44、角形顶点位置的那段代码,你将看到我们所做的就是将缓冲区与该属性关联在一起。稍后你将明白这是什么意思。现在,只需注意到我们也使用gl.enableVertexAttribArray函数来指示WebGL使用一个数组来为该属性提供数值。shaderProgram.pMatrixUniform =gl.getUniformLocation(shaderProgram, uPMatrix);shaderProgram.mvMatrixUniform =gl.getUniformLocation(shaderProgram, uMVMatrix);initShaders函数所做的最后一件事就是从程序中获取
45、两个多的值,这两个变量称作uniform变量,我们很快会再遇见它们,但现在你只需注意到,正如属性一样,我们为了方便而将其存储在对象中。现在,我们来看看getShader函数:function getShader(gl, id) var shaderScript = document.getElementById(id);if (!shaderScript) return null;var str = ;var k = shaderScript.firstChild;while (k) if (k.nodeType = 3)str += k.textContent;k = k.nextSibli
46、ng;var shader;if (shaderScript.type = x-shader/x-fragment) shader = gl.createShader(gl.FRAGMENT_SHADER);else if (shaderScript.type = x-shader/x-vertex) shader = gl.createShader(gl.VERTEX_SHADER);else return null;gl.shaderSource(shader, str);gl pileShader(shader);if (!gl.getShaderParameter(shader, gl
47、 PILE_STATUS) alert(gl.getShaderInfoLog(shader);return null;return shader;这是另一个比看起来要简单的函数。我们要做的是在HTML网页中寻找一个元素,其具有与传入参数匹配的ID,取出其内容并基于其类型创建一个片段渲染器或者一个顶点渲染器(以后我们将更多地解释它们的区别),接着将其传入到WebGL中编译成可以在图形卡上运行的形式。接下来,代码进行出错处理,最后完成整个处理。当然,我们只能在JavaScript中将渲染器定义为字符串而不能从HTML中提取通过这样做,我们使其更易读,因为它们被定义为网页中的脚本,就像它们本身就是
48、JavaScript一样。看完这个以后,我们应该来看看渲染器的代码:关 于这些你要记住的第一件事就是:这些代码不是用JavaScript所写,即使这两种脚本语言的祖先十分相似。事实上,它们使用一种特殊的与C语言有很大 关系的渲染器语言(当然,JavaScript也是如此)所写。第一个渲染器即片段渲染器什么也不做;它简单地规定了被绘制的物体将被绘制成白色 (怎么给物体着色是下一节课程的话题)。第二个渲染器有点意思,它是一个顶点渲染器还记得吧,它是一段图形卡上的代码,能用一个顶点完成它想做的任何事。与之相关联的是,它有两个uniform变量:uMVMatrix和uPMatrix。uniform变量
49、十分有用,因为它们能在渲染器之外获得实际上是在包含它们的程序之外,你可能还记得, 当时我们从initShaders函数获得了它们,它们也可以从将其设置为模型视图矩阵和投影矩阵的代码(我敢肯定你已经实现了它)中获得。你可能认为渲 染器程序是一个对象(在面向对象的场景中),而统一变量是对象中的字段。现在,渲染器在每个顶点上调用,顶点作为aVertexPosition参数传入 到渲染器的代码中,由于在drawScene函数中使用vertexPositionAttribute,此时,我们将其属性与缓冲区关联在一起。渲染器 主程序中的这部分代码只是将顶点与模型视图矩阵和投影矩阵相乘,然后作为顶点最终位置
50、的结果传出。webGLStart函数调用initShaders函 数,在网页的脚本中使用getShader函数装载了片段渲染器和顶点渲染器,以便它们能被编译后传入到WebGL,最终使用WebGL渲染出三维场景。剩下还没有说明的代码是setMatrixUniforms函数,一旦你理解了上面所讲的,就很容易理解它。function setMatrixUniforms() gl.uniformMatrix4fv(shaderProgram.pMatrixUniform, false,new WebGLFloatArray(pMatrix.flatten();gl.uniformMatrix4fv(s
51、haderProgram.mvMatrixUniform, false,new WebGLFloatArray(mvMatrix.flatten();通过引用uniform来表示initShaders中的投影矩阵和模型视图矩阵,我们将值从JavaScript类型矩阵传递给了WebGL。第一课的内容真的很多,但是希望你(也包括我)能够理解所有这些基本知识,我们将以此为基础创建更加有趣的模型:五彩缤纷的、可移动的、真正的三维WebGL模型。为了了解更多关于WebGL的知识,请阅读第2课。学习WebGL 第2课 添加颜色欢迎来到第二节WebGL教程!这一次我们将要讨论如何给场景着色。这一节课的内容是
52、基于NeHe的OpenGL教程第三课。下面是本课内容在支持WebGL的浏览器中运行的样子:点击此处,你将看到这个WebGL现场版。如果你还没有一个支持WebGL的浏览器,你可以从这里知道如何获取它。一 点提示:本教程是面向那些具有一定编程知识而缺乏实际3D图形开发经验的开发人员;其目的是为了让你更好地明白代码,以便于你能尽可能快地开发出你自己的 三维网页。如果你已经看过第一节课的内容(你应该在开始本课之前去看一看第一节的内容),那么我现在就只是解释新旧代码间的区别。本课的代码和第一节课的十分相似。从网页的顶部到底部开始运行,我们使用具有x-shader/x-vertex和x-shader/x-
53、fragment类型的script标签定义了顶点渲染器和片段渲染器;在initGL函数中初始化了一个WebGL的上下文;使用getShader和initShaders函数装载渲染器到一个WebGL对象中;定义了模型视图矩阵以及操该矩阵的应用函数loadIdentity、multMatrix和mvTranslate;定义了投影矩阵pMatrix和一个操作该矩阵的应用函数perspective;定义setMatrixUniforms函数用于将模型视图矩阵和投影矩阵,以便渲染器能看见它们使用initBuffers加载包含场景对象信息的缓冲区;在适当命名的drawScene函数中绘制场景;定义WebG
54、LStart函数在网页起始位置设置WebGL的环境;最后,我们提供了所需的最少的html代码来显示它。与第一课代码相比,唯一改变的地方在于渲染器,initBuffers函数和drawScene函数。为了解释它是如何工作的,你需要一些关于WebGL贴图管线的知识。下面是一个流程图:这个流程图用十分简洁的方式显示了在drawScene函数中传入JavaScript函数的数据是如何转变为在场景画布中显示在WebGL上的像素点的。它仅显示了本课中需要说明的几个步骤;我们将在以后的课程中去讲解较为细节的地方。在最高级别上,该过程工作如下:你每次调用像drawArrays这样的函数,WebGL都要处理先前以属性(如第一课中用于顶点的缓冲区)和统一变量(其用于投影矩阵和模型视图矩阵)的形式提交给它的数据,并将其传入到顶点渲染器。对每个顶点调用一次顶点渲染器,每次都为该顶点设置合适的属性。同时,将统一变量传入到顶点渲染器。但是,统一变量正如它们的名字,在调用的过程并不发生改变。顶点渲染器用第一课中提到的这个数据来工作,它使用投影和模型视图矩阵以便顶点能根据当前的模型视图状态来将其置入场景中和在
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025年基层金融质押协议
- 2025年连带责任保证合同(借款)
- 中小企业2024年期限劳动合同3篇
- 正规2025年度艺人经纪合同3篇
- 2025年度度假酒店委托运营管理服务合同
- 2025年度门窗行业产品召回与质量追溯合同电子版
- 2025年度船舶转让合同与手续办理及船舶维修保养服务协议
- 二零二五年度水稻繁殖产业可持续发展战略合同
- 二零二五年度音乐版权音乐版权交易中介服务合同
- 二零二五年度解除劳动合同保密协议书及知识产权保护
- 工会换届公示文件模板
- 江苏省南京市协同体七校2024-2025学年高三上学期期中联合考试英语试题答案
- 青岛版二年级下册三位数加减三位数竖式计算题200道及答案
- GB/T 12723-2024单位产品能源消耗限额编制通则
- GB/T 16288-2024塑料制品的标志
- 麻风病防治知识课件
- 干部职级晋升积分制管理办法
- TSG ZF003-2011《爆破片装置安全技术监察规程》
- 2024年代理记账工作总结6篇
- 电气工程预算实例:清单与计价样本
- VOC废气治理工程中电化学氧化技术的研究与应用
评论
0/150
提交评论