03. 光源与阴影

2022-10-19 11:42:48发布
39

本章将介绍4种常见的光源以及光源与物体的阴影关系

threejs中常见的光源有以下4种 :

PointLight(点光源)

AmbientLight(环境光)

SpotLight(聚光灯)

DirectionalLight(平行光)


PointLight

从一个点向各个方向发射的光源。一个常见的例子是模拟一个灯泡发出的光。该光源可以投射阴影

构造函数

PointLight( color : Integer, intensity : Float, distance : Number, decay : Float )
 
color - (可选参数)) 十六进制光照颜色。 缺省值 0xffffff (白色)。
intensity - (可选参数) 光照强度。 缺省值 1。 
distance - 这个距离表示从光源到光照强度为0的位置。 当设置为0时,光永远不会消失(距离无穷大)。缺省值 0.
decay - 沿着光照距离的衰退量。缺省值 1。 在 physically correct 模式中,decay = 2。

创建代码

let pointLight = new THREE.PointLight(0xffffff,1,5,2);
pointLight.position.set(2.5, 1, 0); 
scene.add(pointLight); 

例子

点光源


AmbientLight

环境光会均匀的照亮场景中的所有物体的每个面,环境光不能用来投射阴影,因为它没有方向。如下图 :

该图我们没办法,找到具体的光源在哪里,但是整个场景我们还是可以看的见的。每个物体,每个人的光照面积都是均匀的。

构造函数

AmbientLight( color : Integer, intensity : Float )
 
color - (参数可选)颜色的rgb数值。缺省值为 0xffffff。
intensity - (参数可选)光照的强度。缺省值为 1。

创建代码

let ambient = new THREE.AmbientLight(0x444444,1);
scene.add(ambient);

例子

环境光

环境光+点光源


SpotLight

聚光灯是从一个方向上的一个点发出,沿着一个圆锥体,它离光越远,它的尺寸就越大。该光源可以投射阴影

构造函数

SpotLight( color : Integer, intensity : Float, distance : Float, angle : Radians, penumbra : Float, decay : Float )
 
color - (可选参数) 十六进制光照颜色。 缺省值 0xffffff (白色)。
intensity - (可选参数) 光照强度。 缺省值 1。
distance - 从光源发出光的最大距离,其强度根据光源的距离线性衰减。 
angle - 光线散射角度,最大为Math.PI/2。
penumbra - 聚光锥的半影衰减百分比。在0和1之间的值。默认为0。
decay - 沿着光照距离的衰减量。

创建代码

let spotLight = new THREE.SpotLight(0xffffff);
spotLight.position.set(0, 15, 0);
spotLight.angle = Math.PI / 10;
spotLight.penumbra = 1;
scene.add(spotLight);

例子

聚光灯


DirectionalLight

平行光是沿着特定方向发射的光。这种光的表现像是无限远,从它发出的光线都是平行的。常常用平行光来模拟太阳光 的效果; 太阳足够远,因此我们可以认为太阳的位置是无限远,所以我们认为从太阳发出的光线也都是平行的。平行光可以投射阴影

构造函数

DirectionalLight( color : Integer, intensity : Float )
 
color - (可选参数) 16进制表示光的颜色。 缺省值为 0xffffff (白色)。
intensity - (可选参数) 光照的强度。缺省值为1。

创建代码

let directionalLight = new THREE.DirectionalLight(0xffffff, 1);
directionalLight.position.set(0, 5000, 10000);
scene.add(directionalLight);

注意这里的位置属性,因为平行光是可以看作很远的光源,所以物体受到平行光照射的面积都是均匀的。所以这里的位置y轴5000,z轴10000,在同等的比例下,怎么修改位置,物体受到的光照面级都不会改变。比如y轴改成0.5,z轴改成1

例子

平行光


阴影

由于计算阴影是一件很消耗性能的一件工作,threejs默认关闭了物体的阴影特性。若要开启,分以下四个步骤 :

1. 渲染器的shadowMap.enabled属性设置为true

2. 网格模型的castShadow属性设置为true

3. 光源的castShadow属性设置为true

4. 接受阴影的物体的receiveShadow属性设置为true

例子

点光源阴影

聚光灯阴影

平行光阴影

其中,平行光的阴影比较特殊。点开上面平行光的阴影链接可以看到,立方体生成的阴影不全。这是因为平行光照射的范围是整个场景,如果被照射到的物体都生成阴影,这实在太损耗性能。所以在threejs中,若要给平行光照射到的物体产生阴影,需要设置一个“阴影矩形”,在这个矩形下的物体才会产生阴影。

具体设置

let directionalLight = new THREE.DirectionalLight(0xffffff, 1);
directionalLight.position.set(10, 5, 0);
scene.add(directionalLight);
 
directionalLight.castShadow = true;
 
/* 
  设置计算阴影的区域,最好刚好紧密包围在对象周围
  计算阴影的区域过大:模糊  过小:看不到或显示不完整
*/
directionalLight.shadow.camera.near = 0.5;
directionalLight.shadow.camera.far = 100;
directionalLight.shadow.camera.left = -25;
directionalLight.shadow.camera.right = 25;
directionalLight.shadow.camera.top = 25;
directionalLight.shadow.camera.bottom = -25;

例子

解决平行光阴影不全问题

上面的例子中还存在阴影模糊的问题,我们可以调用光源的shadow.mapSize.set方法,该方法需要2个参数 :

shadowWidth :阴影的宽度用多少像素绘制

shadowHeight :阴影的高度用多少像素绘制

例子

解决阴影模糊问题


最后是个人制作的一个小案列

移动的光源