本节我们将介绍Three.js提供的三种用于非常特殊用途的光源。我们首先介绍THREE.HemisphereLight,它对于创建逼真的户外场景照明效果至关重要。接下来我们将讨论THREE.RectAreaLight,它从一个较大的区域而不是一个点发射光线。接下来,我们将讨论如何使用LightProbe根据立方体贴图应用光照,最后,我们将展示如何为场景添加镜头光晕效果。
我们要探讨的第一种特殊光源是THREE.HemisphereLight。
通过使用THREE.HemisphereLight,我们可以创建看起来更自然的户外照明效果。如果不使用这个光源,我们可以通过创建THREE.DirectionalLight来模拟户外场景,该光源模拟太阳,然后可能会再添加另一个THREE.AmbientLight来为场景提供一些一般性的颜色。但是这样做看起来不会很自然。在室外,并非所有的光线都直接来自上方:大部分光线是经过大气层散射,以及从地面和其他对象反射而来。Three.js中的THREE.HemisphereLight就是为这种场景而设计的。这是一种获得更自然户外光照效果的简单方法。你可以查看图3.16中示例hemisphere-light.html,观察THREE.HemisphereLight在场景中的效果。
图3.16 THREE.HemisphereLight的光照效果
如果你仔细看图3.16,在底部,地面的颜色更为突出;而在场景的顶部,则可以看到通过color属性设置的天空颜色更为突出。你可以在这个示例中设置这些颜色及其强度来实验。创建THREE.HemisphereLight和创建其他类型的光源一样简单:
你只需指定从天空接收到的颜色、从地面接收到的颜色以及这些光的强度。在创建THREE.HemisphereLight对象后,你可以通过表3.4所示的属性修改效果。
表3.4 THREE.HemisphereLight对象的属性
由于HemisphereLight的行为类似于THREE.AmbientLight对象,只是为场景中的所有对象添加颜色,因此它无法投射阴影。到目前为止,我们看到的光源都比较传统。接下来的这种光源允许你模拟来自矩形光源的光——例如,窗户或计算机屏幕的光。
使用THREE.RectAreaLight,我们可以定义一个矩形发光区域。在讲述细节之前,先看看我们的最终效果(打开示例rectarea-light.html)。图3.17包括了几个THREE.RectAreaLight对象。
图3.17 多个THREE.RectAreaLight对象在场景中的效果
在图3.17中,我们定义了三个THREE.RectAreaLight对象,每个对象都有自己的颜色。你可以看到这些光源如何影响整个区域。当你移动它们或改变它们的位置时,你可以看到这些动作如何影响场景中的对象。
我们还没有深入探讨不同材质对光线的影响。这点我们将在第4章介绍。THREE.RectAreaLight仅适用于THREE.MeshStandardMaterial或THREE.MeshPhy-sicalMaterial材质。这些材质的更多信息将在第4章中介绍。
要使用THREE.RectAreaLight,我们需要进行几项额外的小步骤。首先,我们需要加载和初始化RectAreaLightUniformsLib,这是为了使用这个光源所需的额外底层WebGL脚本:
在完成必要的初始化步骤后,我们可以像创建其他光源一样创建THREE.RectArea-Light对象:
THREE.RectAreaLight对象的构造函数有四个属性。第一个是光源的颜色,第二个是强度,最后两个定义了光源的区域大小。注意,如果你想要像示例中可视化光源的照明范围和效果,你必须创建一个与你的THREE.RectAreaLight位置、旋转和大小都相同的矩形。
THREE.RectAreaLight可以用来创建一些独特的效果,但可能需要一些实验才能获得理想的效果。再次提醒,示例中提供了一个右侧菜单,以便用户调整各种设置,以观察不同参数变化对THREE.RectAreaLight效果的影响。
Three.js的最近版本中新增了一种名为THREE.LightProbe的光源。这种光源类似于THREE.AmbientLight,但利用了WebGLRenderer的立方体贴图来计算光照效果。THREE.LightProbe将是本章讨论的最后一个光源。
在第2章中,我们稍微讨论了立方体贴图。通过使用立方体贴图,我们可以将模型置于一个环境中。在第2章中,我们使用立方体贴图创建了一个与相机视角同步旋转的背景,如图3.18所示。
在第4章中,我们将学习如何使用立方体贴图中的信息来在材质上展示反射效果。然而,通常情况下,这些环境贴图不会为场景提供任何光照。然而,使用THREE.LightProbe,我们可以从立方体贴图中提取光照级别信息,并将其用于照亮我们的模型。因此,你得到的效果有点像THREE.AmbientLight,但它会根据场景中的位置和立方体贴图中的信息来影响对象。
图3.18 第2章的立方体贴图示例
最简单的解释方法是查看示例。在浏览器中打开light-probe.html,你将看到如图3.19所示的场景。
图3.19 使用LightProbe和立方体贴图创建逼真环境光照效果的场景示例
以上示例中,模型位于一个类似洞穴的环境内。如果你旋转相机,那么模型在不同位置会受到不同光照的效果。在前面的截图中,我们从洞穴深处观察模型的背面,因此模型在该侧显得较暗。如果我们完全旋转相机,转到洞穴的入口,那么我们会发现模型受到更多光照,从而显得更亮,如图3.20所示。
图3.20 相机旋转到洞穴入口时,LightProbe让模型接收更多光线
这是一个非常棒的技巧,可以使你的对象看起来更加逼真,并减少平面的感觉,并且使用THREE.LightProbe,你的模型将不均匀地接收光线,看起来更加生动真实。
设置THREE.LightProbe需要一些额外工作,但只需要在创建场景时进行一次。只要环境不变,就不需要重新计算THREE.LightProbe对象的值:
在上述代码中,我们主要进行了两件事。首先,我们使用THREE.CubeTex-tureLoader加载立方体贴图。正如我们将在第4章中看到的那样,立方体贴图由六个图像组成,每个图像代表立方体的一个面,这六个图像共同构成了我们的环境。在立方体贴图加载完成后,我们将其设置为场景的背景(但需要注意这并不是THREE.LightProbe工作的必要条件)。
现在,我们已经有了立方体贴图,我们可以从中生成一个THREE.LightProbe。通过将cubeTexture传递给LightProbeGenerator就可以生成THREE.LightProbe对象了。从立方体贴图生成的结果是一个THREE.LightProbe对象,我们可以像添加任何其他光源一样将其添加到场景中。就像THREE.AmbientLight一样,你可以通过设置intensity属性来控制该光源对网格照明的贡献量。
提示
Three.js还提供了另一种类型的LightProbe:THREE.HemisphereLightProbe。THREE.HemisphereLightProbe的工作原理与正常的THREE.HemisphereLight基本相同,但它在内部使用了LightProbe技术。
本章介绍的最后一个对象不是光源,而是在电影中经常出现的相机技巧:THREE.LensFlare。
你可能已经熟悉镜头光晕的基本概念。例如,当直接拍摄太阳或其他明亮光源时,镜头会产生光晕效果。在大多数情况下,你希望避免这种情况,但对于游戏和3D生成的图像,它提供了一种使场景看起来更逼真的效果。Three.js也支持镜头光晕,并且非常容易将其添加到场景中。在本节中,我们将向场景中添加一个镜头光晕,并创建出如图3.21所示的输出,你可以打开lens-flare.html自己实验。
我们可以通过实例化LensFlare对象并添加LensFlareElement对象来创建一个镜头光晕:
图3.21 当你看向光源时,会出现镜头光晕效果
LensFlare元素只是LensflareElement对象的容器,LensflareElement对象负责生成可见的光斑效果。在创建和配置好镜头光晕效果后,只需要将其添加到光源上即可。如果你查看代码,那么你将看到我们为每个LensflareElement传入了多个属性。这些属性决定了LensflareElement的外观以及其在屏幕上的渲染位置。LensflareElement构造函数的参数如表3.5所示。
表3.5 THREE.LensflareElement对象的属性
首先让我们更仔细地看一下第一个LensflareElement:
第一个参数texture是一个用于定义光晕的形状和基本颜色的图像。我们使用THREE.TextureLoader来加载它,通过添加texture路径即可,如图3.22所示。
图3.22 示例中使用的光晕
第二个参数是光晕的大小。由于这是我们在光源处看到的光晕,因此我们会使其相当大:在这种情况下是512像素。接下来,我们需要设置这个光晕的distance属性。在这里设置的是光源与相机中心之间的相对距离。如果我们将距离设置为0,则纹理将显示在光源位置;如果我们将其设置为1,则纹理将显示在相机位置。本例我们直接将其放在光源处。
现在,如果你回头看看其他LensflareElement对象的位置,你会发现我们将它们定位在从0到1的间隔上,从而得出你打开lens-flare.html示例时看到的效果:
至此我们已经介绍了Three.js提供的各种光源。