![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=1739538083-0ZItfMc5mGSk3MQgjTI4nqdZYIzu1Naj-0-ec8903281319769d832bacf0bd7c0750)
图2-6 地月系模拟动画
同时,一并介绍一些前面没有提及的概念及其使用方法,包括:
(1)第一人称漫游;
(2)图片纹理;
(3)子类与层级关系;
(4)线段处理;
(5)粒子系统。
对于这些内容的解释和说明,我们在脚本文件中穿插进行。
![](https://epubservercos.yuewen.com/9C24F9/17180253304506706/epubprivate/OEBPS/Images/img00026002.jpg?sign=1739538083-bTx034GAC7kAFp5oKd7cpaFikUdr2vDx-0-b6af4f8a5311ab2f46926f313f14e190)
(1)第一人称漫游。它允许用户通过键盘或鼠标对场景进行巡游控制,详见本书3.5.1节。
![](https://epubservercos.yuewen.com/9C24F9/17180253304506706/epubprivate/OEBPS/Images/img00026003.jpg?sign=1739538083-50tAEUmXmJ1HGjOCVTlA0kPp8Oi09T2V-0-848897f0affa5e5644a45b392ce96f69)
![](https://epubservercos.yuewen.com/9C24F9/17180253304506706/epubprivate/OEBPS/Images/img00027001.jpg?sign=1739538083-L2an8two2ra5cJucUatqtABijZhJxZfS-0-b6303b1db74e7d5da50cdff88c75e9c5)
(2)图片纹理。在真实的3D场景中,模型是有纹理的,而不仅仅是只有颜色值,Three.js通过ImageUtils.loadTexture方法使用图片纹理对3D模型进行贴图,使得模型更接近真实。MeshLambertMaterial(朗勃面)是一种很常用的材质,它将使用漫反射的方式引用前面的纹理图片,最终效果还与光线有关;另外一种常用的材质是MeshPhongMaterial,它可以产生镜面效果。
![](https://epubservercos.yuewen.com/9C24F9/17180253304506706/epubprivate/OEBPS/Images/img00027002.jpg?sign=1739538083-RscJNArKPl4WCoRQ27aqlwyPGANSzZSD-0-094ef390bc0430ac4ffcc7223343c702)
(3)子类与层级关系。在本例中,月亮属于地球的子类,将跟随地球一起绕太阳公转,通过创建子类,不管地球如何运动,月亮将自动跟随地球,程序不需要再单独处理这部分内容。层级关系是计算机动画的重要概念之一。比如骨骼动画,对于人体动画,小腿骨骼将跟随大腿骨骼一起运动。
![](https://epubservercos.yuewen.com/9C24F9/17180253304506706/epubprivate/OEBPS/Images/img00027003.jpg?sign=1739538083-d76D9Lb1BcRVK7i9uOtxl4HW4G05K2Nd-0-3b783cf5ea5e4aaa4fe5d1da652afb8e)
![](https://epubservercos.yuewen.com/9C24F9/17180253304506706/epubprivate/OEBPS/Images/img00028001.jpg?sign=1739538083-shx6VYUJ8iZ7MVdt9hEjjhkBlGI76wMG-0-a5c088f50d969da1814c8f58c7bd512e)
![](https://epubservercos.yuewen.com/9C24F9/17180253304506706/epubprivate/OEBPS/Images/img00029001.jpg?sign=1739538083-ALH5W9m6xITor90zsdfPFN1przS9xP2g-0-4dd9641ddb18d6b69d605b984b3e5b41)
(4)线段处理。在真实的太阳系中并没有轨道线,但在程序中加入轨道线将使场景更加美观。我们使用圆形轨道来模拟真实轨道(真实轨道是椭圆的),THREE.LineBasicMaterial材质可将geometry中的顶点逐个相连,只要分段足够多,最终的效果将趋于平滑的圆形,本例中,轨道线被分成了120段。
![](https://epubservercos.yuewen.com/9C24F9/17180253304506706/epubprivate/OEBPS/Images/img00029002.jpg?sign=1739538083-EvlMa7evydFcYKDjrQy7R65bGTLRHnE9-0-4f36d1ee75b989d4c49d49db3442476c)
![](https://epubservercos.yuewen.com/9C24F9/17180253304506706/epubprivate/OEBPS/Images/img00030001.jpg?sign=1739538083-f1Dgzwfb3qorTeRbM9VoZh7zg2Uj1x7j-0-5a3a7e8429d80c7013088c2b83167aa5)
(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=1739538083-uALU3a82dBAKM9GukKyWrT9sgbLTNXFC-0-8d9ae62c45ae38136f2d93f5042fefba)
图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=1739538083-SY3DTV9EsXKKl5wclNRol2ackS93hgS6-0-2c7342956cbfe9ca6f45862a1a198269)
图2-8 雪花飘飘网页效果
![](https://epubservercos.yuewen.com/9C24F9/17180253304506706/epubprivate/OEBPS/Images/img00031002.jpg?sign=1739538083-OpVKo1zVsNjp9UYe3N0E74VX6Fc4kvki-0-6999ba86515a909d665a681cdb9914e0)
这段代码随机地生成了10000个点,为每一个点贴上了雪花的图片纹理,并在update事件中不断更新每个顶点的y坐标,最终形成了“雪花飘飘”的动画效果。
本例共使用了10000个顶点来构成雪花效果,顶点越多,越消耗资源,对于烟雾效果来说,经常会有几十万甚至更多的顶点数。为提高效率,Three.js提供了BufferGeometry这种几何体它可以大大提高渲染效率。利用BufferGeometry构建粒子系统的一般方法如下:
![](https://epubservercos.yuewen.com/9C24F9/17180253304506706/epubprivate/OEBPS/Images/img00031003.jpg?sign=1739538083-QuFWXy2n2bhJ61lRQI3eJ0jS7QBhuule-0-9822e439f7bd6e3398723d2a2e2ae04b)
![](https://epubservercos.yuewen.com/9C24F9/17180253304506706/epubprivate/OEBPS/Images/img00032001.jpg?sign=1739538083-dKuSt5sB35UwKqMj2dLC3dPcJB2QD9eK-0-39755659e7b1094b5f3963f9f165bc04)