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