three.js自学之旅(4)—— 聚光灯和阴影探究

时间:2021-09-14 04:17:39

由于自己在这个领域也是刚入门,所以我都是一边写一边改的,在探究聚光灯和阴影之前,想对上一章讲到的相机旋转功能进行扩展,通过鼠标滚轮支持物体放大缩小查看,代码如下,想用的可以复制粘贴到demo里。

//监听滚轮,放大缩小物体
document.body.onmousewheel = function(event) {
    var ev = event || window.event;
    if(ev.deltaY > 0){
        if(cameraRound < 30)
            cameraRound = cameraRound + 1;
    }else{
        if(cameraRound > 6)
            cameraRound = cameraRound - 1;
    }
    camera.position.z = cameraRound *(Math.cos(arf));
    camera.position.x = cameraRound *(Math.sin(arf));
};

除了这个功能之外,还对nodejs搭建的本地服务器进行了优化,之前的那个有点脆弱,有兴趣的可以留言,在后面讲到纹理的时候我会把代码放上来,因为后面可能会遇到图片加载404的错误。

进入正题

聚光灯源(SpotLight)

官方文档:一种能投射锥形阴影区域的点光源。

附官方图

three.js自学之旅(4)—— 聚光灯和阴影探究

很明显可以看出,这种光是有方向的,跟“灯泡”是有本质区别的,pointLight会向周围发散,他不会。

SpotLight( color, intensity, distance, angle, penumbra, decay )
color — 颜色的RBG数值。
intensity — 光强的数值。
distance -- 光强为0处到光源的距离,0表示无穷大。
angle -- 光线散射角度,最大为Math.PI/2。
penumbra -- 聚光锥的半影衰减百分比。在0和1之间的值。默认为0。
decay -- 沿着光照距离的衰退量。

点击打开链接

关于spotlight的参数请自己去上面的官网链接玩一下,文字描述不是很好懂(数学文盲不知道怎么描述)。

放个demo,先上代码,大家可以对着代码一边看一边改一边玩

//设置立方体能投射阴影
cube.castShadow = true;

var ground = new THREE.Mesh(geometry2,new THREE.MeshLambertMaterial({color:0xffffff}));
ground.position.set(0,-6,0);
var wall = new THREE.Mesh(geometry3,new THREE.MeshLambertMaterial({color:0xffffff}));
wall.position.set(0,0,-6);
//设置墙既能接收阴影也能投射阴影
wall.receiveShadow = true;
wall.castShadow = true;
scene.add(wall);
//设置地面能接受阴影
ground.receiveShadow = true;
scene.add(ground);

cube.rotation.x=45*Math.PI/180;
cube.rotation.y=45*Math.PI/180;
cube.rotation.z=45*Math.PI/180;
scene.add(cube);


//添加一个聚光灯
var light = new THREE.SpotLight(0xff00ff,1);
//设置聚光灯可以投射阴影
light.castShadow = true;
light.shadow.camera.near = 10;
light.shadow.camera.far = 300;
light.shadow.camera.fov = 20;
light.shadow.mapSize.width = 2048;
light.shadow.mapSize.height = 2048;
light.position.set(0,24,17);
scene.add(light);


three.js自学之旅(4)—— 聚光灯和阴影探究
为了观看效果更佳,我在renderLoop()函数里加了

cube.rotation.x += 0.02;
wall.rotation.z += 0.02;
这样你可以更明显的观察到阴影的渲染是动态的,因此渲染阴影会消耗大量的浏览器性能。

关于阴影的使用,请注意以下四个点:

1.请设置你的渲染器支持阴影渲染的功能(由于阴影很吃性能,所以three.js需要你手动打开这个参数)

renderer.shadowMapEnabled =  true;
在设置渲染器的阴影渲染的时候,three.js还提供了一个参数方便你设置阴影类型,你可以通过设置renderer.shadowMapType来获得更好阴影质量或更好的性能。大家可以试试以下三个参数,第一个和第三个参数有明显的不同,应该可以看得出来。

THREE.BasicShadowMap:普通阴影映射
THREE.PCFShadowMap:柔化边缘的阴影映射
THREE.PCFSoftShadowMap:柔化边缘的软阴影映射

2.请设置你的物体能够接收/投射阴影

cube.castShadow = true;//投射
ground.receiveShadow = true; //接收
在demo中,我放了一wall,他即作为一个投射阴影的对象,他本身也可以接收阴影,可以从上面的截图看到,如果你想设置一个物体既能接收阴影,又可以投射阴影,只需要按照上面的代码将他的castShodow 和 receiveShadow值都设为true即可。

3.请设置你的聚光灯能投射阴影,并将它放在合适的位置

light.castShadow = true;
个人感觉比较有用的一个参数设置

light.shadow.mapSize.width = 4096;
light.shadow.mapSize.height = 4096;
//light.shadow.camera.near = 10;
//light.shadow.camera.far = 100;
//light.shadow.camera.fov = 80;

通过这个可以设置生成阴影的质量,默认值为512,512,如果觉得阴影过于马赛克可以增大这两个值,请不要将这两个值设置的过大,刚设置成1000 WebGL直接挂了。注释掉的几个参数有兴趣可以自己研究。

关于阴影的使用请参照上面三个注意点自己试验,本人目前也在实验阶段,下一期应该会将各种模型探究一遍,大概需要两期左右去探究。写到这儿。。。。(本期质量较差,因为在测试的过程中,发现有些个参数要么弃用,要么没什么用,有什么问题打我电话,110)