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