three.js学习(11)

201 阅读5分钟

3.详解聚光灯各种属性与应用

1.基础

聚光灯 SpotLight : 光线从一个点沿着一个方向射出,随着光线照射的变远,光线圆锥体的尺寸也逐渐增大。

一样来设置一下聚光灯:

 //聚光灯
 const spotLight = new THREE.SpotLight(0xffffff, 1)
 spotLight.position.set(5, 5, 5)
 spotLight.castShadow = true
 //设置阴影贴图模糊度
 spotLight.shadow.radius = 20
 //设置阴影贴图分辨率
 // spotLight.shadow.mapSize.set(2048, 2048)
 spotLight.shadow.mapSize.set(4096, 4096)
 scene.add(spotLight)

聚光灯一样可以通过设置position和target,来确定光源的位置以及照射目标。

像下面,我们给小球设置一个gui,让它可以左右拖动

 //初始化GUI界面
 const gui = new dat.GUI()
 gui.add(sphere.position, "x").min(-5).max(5).step(0.1)

这样通过去移动小球,我们发现聚光灯还是照着一个地方没有改变,而如果把它的target指向小球,那么它就会一直追随着小球的方向。

 spotLight.target = sphere

2.设置聚光灯的角度。

.angle: 从聚光灯的位置以弧度表示聚光灯的最大范围。应该不超过Math.PI/2。默认值为Math.PI/3。

我们把它设置为30°,并且也给一个gui来调试看看效果。

 spotLight.angle = Math.PI / 6 //30°
 gui.add(spotLight, "angle").min(0).max(Math.PI / 2).step(0.01)

3.聚光灯相机属性

聚光灯同样也是有相机属性的,这里是一个透视相机,没有六个面了 而是只有三个属性,近端远端和角度。一般情况下都不用去改这些东西。

 spotLight.shadow.camera.near = 500
 spotLight.shadow.camera.far = 4000
 spotLight.shadow.camera.fov = 30 //角度

4.最大距离

distance: 从光源触发光的最大距离,其强度根据光源的距离线性衰减。有一个特殊值0,为0的话表示无论距离,光线的强度都一致。一样可以给他设置一个gui调节一下。

 spotLight.distance = 0
 gui.add(spotLight, "distance").min(0).max(10).step(0.1)

5.聚光锥的半影衰减百分比

penumbra: 在0和1之间,默认为0.

 spotLight.penumbra = 0
 gui.add(spotLight, "penumbra").min(0).max(1).step(0.1)

越趋近于1呢,光线的边缘就会越模糊,比较像真实的手电筒的感觉。

6.沿着光照距离的衰减量

decay:物理正确的光照模式下,decay设置为等于2将实现现实世界的光衰减。缺省值为1。

那么上面说到的物理正确的光照模式指的是:在渲染器中的physicallyCorrectLights要设置为true。

 const spotLight = new THREE.SpotLight(0xffffff, 100)
 //这里我们可以把亮度调成100 这样就可以很明显看得出差别
 renderer.physicallyCorrectLights = true
 spotLight.decay = 2

4.点光源属性与应用

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

它就没有规定跟随照明的对象了,不过一样有distance根据距离衰减以及decay根据物理正确模式衰减

 //点光源
 const pointLight = new THREE.PointLight(0xff0000, 7)//给它来个红色,光照强度 7
 pointLight.position.set(2, 2, 2)
 pointLight.castShadow = true
 //设置阴影贴图模糊度
 pointLight.shadow.radius = 20
 //设置阴影贴图分辨率
 // pointLight.shadow.mapSize.set(2048, 2048)
 pointLight.shadow.mapSize.set(4096, 4096)
 // pointLight.distance = 0
 // pointLight.decay = 2
 scene.add(pointLight)

那么既然是点光源呢,我们可以设置一个小球,去绑定这个光,让我们“能够看到”这个点光源。

 const smallBall = new THREE.Mesh(
     new THREE.SphereGeometry(0.1,20,20),
     new THREE.MeshBasicMaterial({color:0xff0000})
 )
 smallBall.position.set(2,2,2)
 scene.add(smallBall)

建立一个小球后,我们把点光源加到小球上。意思是我们不把pointLight加到场景中,加到场景中的是smallBall。

 //把点光源添加到小丘上
 smallBall.add(pointLight)
 scene.add(smallBall)

那么接下来我们让小球进行一个圆周运动,比较有意思嗷。那么在之前的学习中有用到的THREE.Clock( )时钟,可以获取时间。理解一下在空中进行圆周运动的话,y轴高度是不变的,变化的是x轴和z轴。

这里我们先复习一下Math.sin(x)和Math.cos(x)

它们两个返回值都是 [-1,1] ,它们的参数呢,不是跟sin30°一样的角度,而是弧度。

因为我们知道圆的周长是2ΠR,而弧度=弧长/半径,所以如果我们要计算的弧度是一整圈圆的话,那里面的弧长就带入圆的周长2ΠR,半径是R,所以得到一个圆的弧度=2Π。转换成角度就是360°,即可以换算得到:1°的弧度=2Π/360=Π/180。只要改变角度的大小,就可以改变弧度。

可得:总弧度 = 角度( PI / 180 )*

当然讲上面那么细是为了让比较喜欢深追到底的朋友们理解,因为我们这里呢要使用的是时间,不用到角度嘿嘿。我们知道Math.sin(x)和Math.cos(x)范围都是[-1,1],Math.sin(0)是从0开始,Math.cos(0)是从1开始,所以就看我们要从哪个点开始了,我倾向于从(1,0)的点开始。由于我们可以通过THREE.Clock()来拿到从0开始数的时间time,那么就是x:Math.cos(time),z:Math.sin(time)。再分别乘以个半径,看起来明显一点。

 //设置时钟
 const clock = new THREE.Clock()
 ​
 function render() { //设置一个渲染函数
     let time = clock.getElapsedTime() //拿到不断变化的时间
     smallBall.position.x = Math.cos(time) * 3
     smallBall.position.z = Math.sin(time) * 3
     controls.update()
     renderer.render(scene, camera)
         //请求动画帧requestAnimationFrame(),渲染下一帧的时候就会调用一次这个函数
     requestAnimationFrame(render)
 }

这样呢,一个圆周运动就做好了。当然也可以让它纵向波浪运动起来哈哈哈哈哈。

 smallBall.position.y = 2 + Math.sin(time * 3) //为了让它上下运动得快一点,给时间乘了3