当前位置: 首页 > 文档资料 > Three.js 入门指南 >

8.5 阴影

优质
小牛编辑
128浏览
2023-12-01

明暗是相对的,阴影的形成也就是因为比周围获得的光照更少。因此,要形成阴影,光源必不可少。

在Three.js中,能形成阴影的光源只有THREE.DirectionalLightTHREE.SpotLight;而相对地,能表现阴影效果的材质只有THREE.LambertMaterialTHREE.PhongMaterial因而在设置光源和材质的时候,一定要注意这一点。

下面,我们以聚光灯为例,在例8.4.1的基础上增加阴影效果。

例8.5.1

首先,我们需要在初始化时,告诉渲染器渲染阴影:

renderer.shadowMapEnabled = true;

然后,对于光源以及所有要产生阴影的物体调用:

xxx.castShadow = true;

对于接收阴影的物体调用:

xxx.receiveShadow = true;

比如场景中一个平面上有一个正方体,想要让聚光灯照射在正方体上,产生的阴影投射在平面上,那么就需要对聚光灯和正方体调用castShadow = true,对于平面调用receiveShadow = true

以上就是产生阴影效果的必要步骤了,不过通常还需要设置光源的阴影相关属性,才能正确显示出阴影效果。

对于聚光灯,需要设置shadowCameraNearshadowCameraFarshadowCameraFov三个值,类比我们在第二章学到的透视投影照相机,只有介于shadowCameraNearshadowCameraFar之间的物体将产生阴影,shadowCameraFov表示张角。

对于平行光,需要设置shadowCameraNearshadowCameraFarshadowCameraLeftshadowCameraRightshadowCameraTop以及shadowCameraBottom六个值,相当于正交投影照相机的六个面。同样,只有在这六个面围成的长方体内的物体才会产生阴影效果。

为了看到阴影照相机的位置,通常可以在调试时开启light.shadowCameraVisible = true

至此,阴影效果已经能正常显示了:

如果想要修改阴影的深浅,可以通过设置shadowDarkness,该值的范围是01,越小越浅。

另外,这里实现阴影效果的方法是Shadow Mapping,即阴影是作为渲染前计算好的贴图贴上去的,因而会受到贴图像素大小的限制。所以可以通过设置shadowMapWidthshadowMapHeight值控制贴图的大小,来改变阴影的精确度。

而如果想实现软阴影的效果,可以通过renderer.shadowMapSoft = true;方便地实现。

设置阴影完整的代码是:

renderer = new THREE.WebGLRenderer();
renderer.shadowMapEnabled = true;
renderer.shadowMapSoft = true;

var plane = new THREE.Mesh(new THREE.PlaneGeometry(8, 8, 16, 16),
        new THREE.MeshLambertMaterial({color: 0xcccccc}));
plane.rotation.x = -Math.PI / 2;
plane.position.y = -1;
plane.receiveShadow = true;
scene.add(plane);

cube = new THREE.Mesh(new THREE.CubeGeometry(1, 1, 1),
        new THREE.MeshLambertMaterial({color: 0x00ff00}));
cube.position.x = 2;
cube.castShadow = true;
scene.add(cube);

var light = new THREE.SpotLight(0xffff00, 1, 100, Math.PI / 6, 25);
light.position.set(2, 5, 3);
light.target = cube;
light.castShadow = true;

light.shadowCameraNear = 2;
light.shadowCameraFar = 10;
light.shadowCameraFov = 30;
light.shadowCameraVisible = true;

light.shadowMapWidth = 1024;
light.shadowMapHeight = 1024;
light.shadowDarkness = 0.3;

scene.add(light);