03. 光源与阴影
本章将介绍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 :阴影的高度用多少像素绘制
例子
最后是个人制作的一个小案列