当前位置: 首页 > news >正文

Three.js 这样写就有阴影效果啦


theme: smartblue

我报名参加金石计划1期挑战——瓜分10万奖池,这是我的第1篇文章,点击查看活动详情


本文简介

点赞 + 关注 + 收藏 = 学会了

渲染阴影效果需要消耗一定的资源,所以 Three.js 默认是关闭阴影效果的。

想要在 Three.js 中实现阴影效果,只需记住接下来要讲的几个点即可。

本文要实现的效果

01.png

本文适合 Three.js 入门级的工友阅读~

如果你还不了解 Three.js ,可以先看看 《Three.js 起飞》 。

本文使用 Three 的版本是 137

基础概念

在学习 Three.js 时,很多知识点其实记住几个重要的步骤就能实现相应的效果。

比如在 《Three.js 起飞》 中提到的,只要有 场景、摄像机、渲染器、物体 就能在页面中展示一些东西出来了。

要实现阴影效果同样需要几个重要的概念。

我们首先研究一下日常生活中是如何产生阴影效果的。

  1. 需要有光。
  2. 需要一个物体,比如苹果、狗等。
  3. 需要一个接受投影的元素,比如地面、桌面等。

Three.js 中要产生阴影效果其实和现实世界的原理差不多。

但考虑到性能原因,Three.js 默认关闭了阴影效果,需要手动开启阴影效果:

  1. 渲染器开启阴影效果。
  2. 有一个能产生阴影的光源,并开启阴影效果。
  3. 有一个接受阴影投射的元素(比如地面),并设置 接受阴影的属性true
  4. 有一个能产生阴影效果的物体,并开启阴影效果。

动手实现

动手之前先观察一下最终效果

01.png

上图有一个立方体、地面、光源。

还有基础元素:场景、摄像机、渲染器。

我把用到的元素整理成一个表格:

| 元素 | 描述 | 相关代码 | | ------ | ------------------------------------------------------------ | ------------------------------------------------------------ | | 场景 | 容器,光源、立方体、地面等元素都要添加到场景中。 | let scene = new Scene() | | 摄像机 | 场景中的相机,代替人眼去观察的工具。 | let camera = new PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000) | | 渲染器 | 渲染工具,本文主要讲的是开启阴影渲染功能。 | 需要开启阴影渲染功能 renderer.shadowMap.enabled = true | | 地面 | 地面,接收阴影的元素。 | 用 PlaneGeometry 生成一个平面,并设置该平面的 receiveShadow 属性为 true 就能接受别的物体投射过来的阴影。 | | 立方体 | 本例的物体元素。 | 用 BoxGeometry 创建一个立方体,并设置该立方体的 castShadow 属性为 true ,就能产生投影效果。 | | 光源 | 要使用 可产生阴影效果 的光源,比如本例的 SpotLight 聚光灯。
AmbientLight 环境光PointLight 点光源 是不能产生阴影效果的。 | 使用 SpotLight 创建光源,并设置该光源的 castShadowtrue 开启阴影效果。 |

第1步:搭建基础场景

Three 中搭建基础场景需要3要素:场景 Scene、摄像机 PerspectiveCamera、渲染器 WebGLRenderer

02.png

```html

```

我把场景的背景色设置成灰色 renderer.setClearColor(new Color(0xEEEEEE))

此时页面上是一片空白,还没元素可以展示。

第2步:创建光源

因为本例 没有使用 基础材质(MeshBasicMaterial) ,渲染出来的物体没有光源是不会显示的,所以我先把光源添加到场景中,之后添加地面和立方体时就比较方便观察了。

要实现阴影效果,我选择了 SpotLight 聚光灯。

```js // 省略部分代码

// 光源 let spotLight = new SpotLight(0xFFFFFF) spotLight.position.set(-40, 50, 30)

scene.add(spotLight) // 将聚光灯添加到场景中 ```

虽然创建了光源,但此时场景中并没有其他物体,所以场景还是一片空白。

第3步:创建地面

在本例中地面是用来接受物体投影的载体。

创建地面我使用了 PlaneGeometry 平面,该方法只需传入宽和高即可。

然后使用 MeshLambertMaterial 材质,设置地面颜色为白色。

```js // 省略部分代码

// 地面 let planeGeometry = new PlaneGeometry(60, 20) // 骨架 let planeMaterial = new MeshLambertMaterial({ color: 0xffffff }) // 可产生阴影的材质 let plane = new Mesh(planeGeometry, planeMaterial) // 网格

scene.add(plane) // 将地面添加到场景中 ```

03.png

此时看到的地面呈现上图的样子(一点都不想地面)。

由于灯光的关系,地面看上去并不是纯白色,离灯光越近的地方就越白,越远就越灰。

我希望地面可以水平放置,所以我将地面沿x轴旋转 -90°

js // 省略部分代码 plane.rotation.x = -90 * Math.PI / 180 // 地面 x轴 旋转-90度

04.png

第4步:创建立方体

我使用 BoxGeometry 创建立方体,设置一个红色的纹理。

```js // 省略部分代码

// 立方体 let cubeGeometry = new BoxGeometry(6, 6, 6) let cubeMaterial = new MeshLambertMaterial({ color: 0xff0000 }) // 可产生阴影的材质 let cube = new Mesh(cubeGeometry, cubeMaterial)

scene.add(cube) ```

05.png

修改一下立方体的位置

js cube.position.set(-6, 6, 3)

06.png

第5步:开启阴影效果

用回上面提到的四句口诀就能开启阴影效果

  1. 渲染器开启阴影效果。
  2. 有一个能产生阴影的光源,并开启阴影效果。
  3. 有一个接受阴影投射的元素(比如地面),并设置 接受阴影的属性true
  4. 有一个能产生阴影效果的物体,并开启阴影效果。

```js // 省略部分代码

// 渲染器开启阴影效果 renderer.shadowMap.enabled = true

// 光源开启阴影效果 spotLight.castShadow = true

// 地面接受阴影 plane.receiveShadow = true

// 立方体开启阴影效果 cube.castShadow = true ```

07.png

完成!

如果想设置阴影的精细度,还可以通过聚光灯的三个属性进行控制:

  • spotLight.shadow.mapSize
  • spotLight.shadow.camera.far
  • spotLight.shadow.camera.nera

本文主要讲解阴影的基础使用方法,先入个门,后面的案例文章会和结合其他效果完成更好玩的东西~

代码仓库

⭐Three 基础阴影用法

推荐阅读

👍《『Three.js』起飞!》

👍《『Three.js』辅助坐标轴》

👍《『Three.js』场景 Scene》

👍《『Three.js』几个简单的入门动画(新手篇)》

点赞 + 关注 + 收藏 = 学会了

相关文章:

  • Cravatar头像
  • Python-爬虫 (BS4数据解析)
  • java基于ssm+vue+elementui的多用户博客管理系统
  • java毕业设计网站swing mysql实现的仓库商品管理系统[包运行成功]
  • java毕业设计论文题目基于SSM实现的小区物业管理系统[包运行成功]
  • “蔚来杯“2022牛客暑期多校训练营10 EF题解
  • 人工智能科学计算库—Numpy教程
  • i.MX6ULL应用移植 | 基于ubuntu base 16.04搭建python3.9+pip3环境
  • vim文本编辑器
  • 网课搜题接口
  • 网课查题API接口(免费)
  • 超分辨率重建DRRN
  • MacOS 环境编译 JVM 源码
  • Linux内核互斥技术1
  • 【RHCE-第五天作业】
  • ES6指北【2】—— 箭头函数
  • 【技术性】Search知识
  • 【剑指offer】让抽象问题具体化
  • Android开源项目规范总结
  • Android系统模拟器绘制实现概述
  • gops —— Go 程序诊断分析工具
  • hadoop集群管理系统搭建规划说明
  • JAVA多线程机制解析-volatilesynchronized
  • JS创建对象模式及其对象原型链探究(一):Object模式
  • Laravel 菜鸟晋级之路
  • Linux下的乱码问题
  • MySQL QA
  • React中的“虫洞”——Context
  • SQLServer之创建显式事务
  • 阿里云爬虫风险管理产品商业化,为云端流量保驾护航
  • 给第三方使用接口的 URL 签名实现
  • 技术攻略】php设计模式(一):简介及创建型模式
  • 开年巨制!千人千面回放技术让你“看到”Flutter用户侧问题
  • 码农张的Bug人生 - 初来乍到
  • 如何学习JavaEE,项目又该如何做?
  • 使用 Xcode 的 Target 区分开发和生产环境
  • 微信小程序:实现悬浮返回和分享按钮
  • 要让cordova项目适配iphoneX + ios11.4,总共要几步?三步
  • 在GitHub多个账号上使用不同的SSH的配置方法
  • CMake 入门1/5:基于阿里云 ECS搭建体验环境
  • shell使用lftp连接ftp和sftp,并可以指定私钥
  • 如何在招聘中考核.NET架构师
  • ​2020 年大前端技术趋势解读
  • #QT(智能家居界面-界面切换)
  • ( 10 )MySQL中的外键
  • (C)一些题4
  • (Ruby)Ubuntu12.04安装Rails环境
  • (多级缓存)缓存同步
  • (附源码)spring boot校园拼车微信小程序 毕业设计 091617
  • (附源码)基于SSM多源异构数据关联技术构建智能校园-计算机毕设 64366
  • (六)库存超卖案例实战——使用mysql分布式锁解决“超卖”问题
  • (十一)图像的罗伯特梯度锐化
  • (四)linux文件内容查看
  • (转) SpringBoot:使用spring-boot-devtools进行热部署以及不生效的问题解决
  • (转)C语言家族扩展收藏 (转)C语言家族扩展