![WebGL开发与应用](https://wfqqreader-1252317822.image.myqcloud.com/cover/712/31729712/b_31729712.jpg)
2.4 综合实例
Sim.js框架简化了开发工作,面向对象和模块化的特点使得网页代码更加易于管理和维护,但同时也要求程序员要有清晰的设计思路,尤其是在3D对象类的定义上。本节我们介绍两个实例,以便让读者能够更好地理解并掌握Sim.js框架的编程方法。
2.4.1 地月系模拟动画
本节介绍了一个地月系模拟动画,最终的效果如图2-6所示,月亮自转的同时围绕地球公转,地球自转的同时围绕太阳公转,月亮作为地球的子类跟随地球运动,在运动过程中,还可以观察到光线变化、月偏食、月全食等现象。
![](https://epubservercos.yuewen.com/9C24F9/17180253304506706/epubprivate/OEBPS/Images/img00026001.jpg?sign=1739538854-O5YYO4140Y2nTgtg1LOjQxrw8IAJxe4a-0-642099f1e95e4bd52ad8db04e92061c5)
图2-6 地月系模拟动画
同时,一并介绍一些前面没有提及的概念及其使用方法,包括:
(1)第一人称漫游;
(2)图片纹理;
(3)子类与层级关系;
(4)线段处理;
(5)粒子系统。
对于这些内容的解释和说明,我们在脚本文件中穿插进行。
![](https://epubservercos.yuewen.com/9C24F9/17180253304506706/epubprivate/OEBPS/Images/img00026002.jpg?sign=1739538854-wEWOcjkSejofJbqkVDmuEE3KHVepnpkd-0-b221b9d834980b4e31960115f2c6bf19)
(1)第一人称漫游。它允许用户通过键盘或鼠标对场景进行巡游控制,详见本书3.5.1节。
![](https://epubservercos.yuewen.com/9C24F9/17180253304506706/epubprivate/OEBPS/Images/img00026003.jpg?sign=1739538854-oBfHWtw5chlDhC2py1Ou5Isul7fenpD0-0-16aef56271a11023fefb45b3831b1741)
![](https://epubservercos.yuewen.com/9C24F9/17180253304506706/epubprivate/OEBPS/Images/img00027001.jpg?sign=1739538854-smjDsSTsZgIfm2pQtrJYDnelU1c6b66W-0-13d6ab1b661d0b67c2c6214253121d55)
(2)图片纹理。在真实的3D场景中,模型是有纹理的,而不仅仅是只有颜色值,Three.js通过ImageUtils.loadTexture方法使用图片纹理对3D模型进行贴图,使得模型更接近真实。MeshLambertMaterial(朗勃面)是一种很常用的材质,它将使用漫反射的方式引用前面的纹理图片,最终效果还与光线有关;另外一种常用的材质是MeshPhongMaterial,它可以产生镜面效果。
![](https://epubservercos.yuewen.com/9C24F9/17180253304506706/epubprivate/OEBPS/Images/img00027002.jpg?sign=1739538854-pps1qzWQSEef4ONcrgahJhOGhzJbhg04-0-71d08a37028786190eb28739582f1036)
(3)子类与层级关系。在本例中,月亮属于地球的子类,将跟随地球一起绕太阳公转,通过创建子类,不管地球如何运动,月亮将自动跟随地球,程序不需要再单独处理这部分内容。层级关系是计算机动画的重要概念之一。比如骨骼动画,对于人体动画,小腿骨骼将跟随大腿骨骼一起运动。
![](https://epubservercos.yuewen.com/9C24F9/17180253304506706/epubprivate/OEBPS/Images/img00027003.jpg?sign=1739538854-qqSDtU4zBFoiPRTxN3M3N5fQBE9cG7pI-0-458e85b2afaae869d0bbf219ed0423a7)
![](https://epubservercos.yuewen.com/9C24F9/17180253304506706/epubprivate/OEBPS/Images/img00028001.jpg?sign=1739538854-LE3eBxTC2vNyKfpzkp7Bv55GFxIaJzJq-0-d74c5bb8c41dcb8915900382e626496a)
![](https://epubservercos.yuewen.com/9C24F9/17180253304506706/epubprivate/OEBPS/Images/img00029001.jpg?sign=1739538854-re2vKzGmBKaNqJFf4z3hfImQNOwkMPOG-0-ba32f7ee4360346c6aef2f461ad402a6)
(4)线段处理。在真实的太阳系中并没有轨道线,但在程序中加入轨道线将使场景更加美观。我们使用圆形轨道来模拟真实轨道(真实轨道是椭圆的),THREE.LineBasicMaterial材质可将geometry中的顶点逐个相连,只要分段足够多,最终的效果将趋于平滑的圆形,本例中,轨道线被分成了120段。
![](https://epubservercos.yuewen.com/9C24F9/17180253304506706/epubprivate/OEBPS/Images/img00029002.jpg?sign=1739538854-uvAacAOLzxftBfiL9FN7HRaFVRLZA6CV-0-ca68df923444766b2ad3f840b870a126)
![](https://epubservercos.yuewen.com/9C24F9/17180253304506706/epubprivate/OEBPS/Images/img00030001.jpg?sign=1739538854-c7qNZMZHL4HkA5QqDm1oOqN16dedUxyr-0-e1f58d35c34e190c2f8f45970391a0df)
(5)粒子系统。为使整个地月系看起来更加生动,我们为其添加了背景星空,随机地添加了1000颗星星,它们的大小和亮度不等,类似的情形包括烟雾效果、火焰效果、波纹效果等,在Three.js中,这类效果可以使用粒子系统来实现,即THREE.ParticleSystem。
请注意ParticleSystemMaterial材质的sizeAttenuation属性,它用于通知Three.js在摄像机移动时是否重新缩放每个粒子。此处设置为false的意义在于:这些星星粒子距离我们非常遥远,摄像机的移动对其而言产生不了视觉上的明显差异。
图2-7将场景扩展到了整个太阳系,包含水星、金星、地球、火星、木星、土星六大近地行星,所有星球均按真实大小比例和距太阳的距离构造,通过第一人称视角漫游,用户可以自由选择在任意位置、任意角度来观察太阳系。
![](https://epubservercos.yuewen.com/9C24F9/17180253304506706/epubprivate/OEBPS/Images/img00030002.jpg?sign=1739538854-bTyjQnup2Yqz12kvfK7PFfXKlHqDt75a-0-0c4d0de024fd87dc75ba1e1665083b31)
图2-7 太阳系模拟动画
在这个模拟动画的制作过程中,还会用到一些更高级的编程知识,比如自定义几何体、着色器编程等。其中关于着色器编程方面的内容涉及一门新的语言GLSL(OpenGL Shading Language),本书不打算深入讨论,因为其涉及过多的GPU渲染管线方面的知识,这部分内容并非本书的主要写作目的。
2.4.2 雪花飘飘
2.4.1节中,背景星空部分我们使用了粒子系统(THREE.ParticleSystem)。粒子系统是一种特殊的几何体,它只有点(vertices),没有面(faces),实践中我们经常用它实现烟雾、火焰、尾气等效果。粒子系统的应用面很广,本节以“雪花飘飘”为例进行介绍,网页的最终效果如图2-8所示,主要的代码如下:
![](https://epubservercos.yuewen.com/9C24F9/17180253304506706/epubprivate/OEBPS/Images/img00031001.jpg?sign=1739538854-sRlKuhLWzKvdIRS4SVAADpMCJlm60G8M-0-68236ec2b7e9a7792d09bb09fdbf0aa1)
图2-8 雪花飘飘网页效果
![](https://epubservercos.yuewen.com/9C24F9/17180253304506706/epubprivate/OEBPS/Images/img00031002.jpg?sign=1739538854-jPzvdBKdW1WAgDyJI9gbYBimiGfBtPzJ-0-b66bfd675058fd23cceac8c3a2d635eb)
这段代码随机地生成了10000个点,为每一个点贴上了雪花的图片纹理,并在update事件中不断更新每个顶点的y坐标,最终形成了“雪花飘飘”的动画效果。
本例共使用了10000个顶点来构成雪花效果,顶点越多,越消耗资源,对于烟雾效果来说,经常会有几十万甚至更多的顶点数。为提高效率,Three.js提供了BufferGeometry这种几何体它可以大大提高渲染效率。利用BufferGeometry构建粒子系统的一般方法如下:
![](https://epubservercos.yuewen.com/9C24F9/17180253304506706/epubprivate/OEBPS/Images/img00031003.jpg?sign=1739538854-cfQWw2urbRwYVP6iNm1Fgb0ZCRxjV69H-0-52a97eacdb3464b9f19fd9ebd6ab313e)
![](https://epubservercos.yuewen.com/9C24F9/17180253304506706/epubprivate/OEBPS/Images/img00032001.jpg?sign=1739538854-Il0ddynmaubc14kTb2grhiaMpbybEsfz-0-78415664ad5d087fa85bef70ae2ce4e8)