前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >如何实现一个3d场景中的阴影效果(threejs)?

如何实现一个3d场景中的阴影效果(threejs)?

作者头像
程序你好
发布2021-07-23 14:22:47
2.6K0
发布2021-07-23 14:22:47
举报
文章被收录于专栏:程序你好程序你好

跟OpenGL不同,在threejs中实现一个阴影效果很简单,只需要简单的几个设置。

在Three.js中,物体可以形成阴影投影效果,但是由于渲染阴影需要消耗计算机大量资源,所以Three.js在默认情况下是不会渲染阴影的,所以需要我手工设置开启阴影效果。

1、renderer设置

首先我们需要告诉renderer我们需要显示阴影效果:

代码语言:javascript
复制
        //告诉渲染器需要阴影效果
        renderer.shadowMap.enabled = true;
        renderer.shadowMap.type = THREE.PCFSoftShadowMap;

2、光源设置

其次需要设置正确的光源,光影,有光才有影。现实环境中,人们之所以能看得到物体,是因为有光,物体的材质反射光到人眼中。在ThreeJS中有几种光源,去模拟现实环境。

最常见的四种为:

环境光( AmbientLight ):笼罩在整个空间无处不在的光

点光源( PointLight ):向四面八方发射的单点光源

聚光灯( SpotLight ):发射出锥形状的光, 模拟手电筒,台灯等光源

平行光( DirectinalLight ):平行的一束光,模拟从很远处照射的太阳光

环境光可以说是场景的整体基调,需要注意的是,由于环境光无处不在,也就是说它是没有方向的,当然不能产生阴影。而且,它也不能作为环境中唯一的光源。我们来看一下只有环境光的效果。

显然,只有环境光的场景是不真实的。环境光可以弱化阴影或者给场景添加一些颜色。而环境光又是必不可少的光源,如果没有环境光,整个3d场景就是一片漆黑(除了某些跟光照无关的材质可以显示)。

聚光灯( SpotLight )是产生阴影效果最常见的光源,能做出类似舞台的效果。平行光或者说方向光可以看成是另类的聚光灯,距离太远以至于光线基本平行了,就像太阳对于我们来说一样。它与聚光灯不同的一点是,它在任何地方的强度都是一样的。当然它也是可以产生阴影的。创建平行光的接口与环境光一致。实际使用过程中具体需要用到光源,怎么去布置光源,需要根据具体应用场景来定。

创建好光源之后,需要设置castShadow属性告诉光源开启阴影投射。

代码语言:javascript
复制
 //需要开启阴影投射
        light.castShadow = true;

可以在场景中添加多个不同的光源,同时显示不同方向的阴影效果。

代码语言:javascript
复制
        scene.add(new THREE.AmbientLight(0x444444));

        light = new THREE.SpotLight(0xffffff);
        light.position.set(-60,30,0);

        //需要开启阴影投射
        light.castShadow = true;

        scene.add(light);


        var directionalLight = new THREE.DirectionalLight( 0xffffff, 0.5 );
        directionalLight.position.set( 1, 1, 0 );
        directionalLight.castShadow = true;
        scene.add( directionalLight );


         light = new THREE.PointLight( 0xffffff, 1, 100 );
         light.position.set( 50, 50, 50 );
         light.castShadow = true;
         scene.add( light );

3、材质和模型设置

再次,添加不同材质的模型,设置属性使模型可以产生阴影效果。

代码语言:javascript
复制
        //告诉立方体需要投射阴影
        cube.castShadow = true;

模型的材质也要选择对灯光有反应的材质,否则也不会出现效果。

常用的网格材质有以下几种:

基础网孔材料(MeshBasicMaterial)

一个以简单着色(平面或线框)方式来绘制几何形状的材料。该材料不受光照影响,没有光照也能着色。

默认将呈现为平面多边形。要把网孔绘制为线框,只需设置“线框(wireframe)”属性设置为true。

深度网孔材料(MeshDepthMaterial)

一种通过深度绘制几何体的材料。深度基于相机的远近平面。白色是最近的,黑色是最远的。

兰伯特网孔材料(MeshLambertMaterial)

一种非发光材料(兰伯特)的表面,计算每个顶点。

法向量网孔材料(MeshNormalMaterial)

一种把法向量映射到RGB颜色的材料。

基础网孔材料(MeshStandardMaterial)

我们添加不同材质的立方体模型到场景中,并设置好属性产生阴影。

代码语言:javascript
复制
        var cubeGeometry = new THREE.CubeGeometry(10,10,8);
        var cubeMaterial = new THREE.MeshPhongMaterial({color:0x444fff});

        var cube = new THREE.Mesh(cubeGeometry, cubeMaterial);
        cube.position.x = 25;
        cube.position.y = 5;
        cube.position.z = -5;

        //告诉立方体需要投射阴影
        cube.castShadow = true;

        scene.add(cube);



        //立方体
        cubeGeometry = new THREE.CubeGeometry(10,10,8);
        cubeMaterial = new THREE.MeshBasicMaterial({color:0x444fff});

        cube = new THREE.Mesh(cubeGeometry, cubeMaterial);
        cube.position.x = 15;
        cube.position.y = 5;
        cube.position.z = -25;

        //告诉立方体需要投射阴影
        cube.castShadow = true;

        scene.add(cube);


        //立方体
        cubeGeometry = new THREE.CubeGeometry(10,10,8);
        cubeMaterial = new THREE.MeshDepthMaterial({color:0x444fff});

        cube = new THREE.Mesh(cubeGeometry, cubeMaterial);
        cube.position.x = 15;
        cube.position.y = 5;
        cube.position.z = 25;

        //告诉立方体需要投射阴影
        cube.castShadow = true;

        scene.add(cube);


         //立方体
        cubeGeometry = new THREE.CubeGeometry(10,10,8);
        cubeMaterial = new THREE.MeshLambertMaterial({color:0x444fff});

        cube = new THREE.Mesh(cubeGeometry, cubeMaterial);
        cube.position.x = -15;
        cube.position.y = 5;
        cube.position.z = 25;

        //告诉立方体需要投射阴影
        cube.castShadow = true;

        scene.add(cube);


         //立方体
        cubeGeometry = new THREE.CubeGeometry(10,10,8);
        cubeMaterial = new THREE.MeshStandardMaterial({color:0x444fff});

        cube = new THREE.Mesh(cubeGeometry, cubeMaterial);
        cube.position.x = -15;
        cube.position.y = 5;
        cube.position.z = -25;

        //告诉立方体需要投射阴影
        cube.castShadow = true;

        scene.add(cube);


         //立方体
        cubeGeometry = new THREE.CubeGeometry(10,10,8);
        cubeMaterial = new THREE.MeshNormalMaterial({color:0x444fff});

        cube = new THREE.Mesh(cubeGeometry, cubeMaterial);
        cube.position.x = -15;
        cube.position.y = 5;
        cube.position.z = -10;

        //告诉立方体需要投射阴影
        cube.castShadow = true;

        scene.add(cube);

4、创建底部平面接收阴影设置

最后,添加一个接收阴影的平面,通过receiveShadow属性设置平面接收阴影。

代码语言:javascript
复制
        //平面
        var planeGeometry = new THREE.PlaneGeometry(100,100);
        var planeMaterial = new THREE.MeshStandardMaterial({color:0xcccccc});

        var plane = new THREE.Mesh(planeGeometry, planeMaterial);
        plane.rotation.x = - 0.5 * Math.PI;
        plane.position.y = -0;

        //设置平面需要接收阴影
        plane.receiveShadow = true;

        scene.add(plane);
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-07-07,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 程序你好 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1、renderer设置
  • 2、光源设置
  • 3、材质和模型设置
  • 4、创建底部平面接收阴影设置
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档