Three.js 這樣寫就有陰影效果啦

本文簡介

點贊 + 關注 + 收藏 = 學會了


渲染陰影效果需要消耗一定的資源,所以 Three.js 默認是關閉陰影效果的。

想要在 Three.js 中實現(xiàn)陰影效果,只需記住接下來要講的幾個點即可。


本文要實現(xiàn)的效果

file


本文適合 Three.js 入門級的工友閱讀~

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

本文使用 Three 的版本是 137



基礎概念

在學習 Three.js 時,很多知識點其實記住幾個重要的步驟就能實現(xiàn)相應的效果。

比如在 《Three.js 起飛》 中提到的,只要有 場景、攝像機、渲染器、物體 就能在頁面中展示一些東西出來了。


要實現(xiàn)陰影效果同樣需要幾個重要的概念。

我們首先研究一下日常生活中是如何產生陰影效果的。

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


Three.js 中要產生陰影效果其實和現(xiàn)實世界的原理差不多。

但考慮到性能原因,Three.js 默認關閉了陰影效果,需要手動開啟陰影效果:

  1. 渲染器開啟陰影效果。
  2. 有一個能產生陰影的光源,并開啟陰影效果。
  3. 有一個接受陰影投射的元素(比如地面),并設置 接受陰影的屬性true。
  4. 有一個能產生陰影效果的物體,并開啟陰影效果。


動手實現(xiàn)

動手之前先觀察一下最終效果

file

上圖有一個立方體、地面、光源。

還有基礎元素:場景、攝像機、渲染器。

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

元素 描述 相關代碼
場景 容器,光源、立方體、地面等元素都要添加到場景中。 let scene = new Scene()
攝像機 場景中的相機,代替人眼去觀察的工具。 let camera = new PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000)
渲染器 渲染工具,本文主要講的是開啟陰影渲染功能。 需要開啟陰影渲染功能
renderer.shadowMap.enabled = true
地面 地面,接收陰影的元素。 PlaneGeometry 生成一個平面,并設置該平面的 receiveShadow 屬性為 true 就能接受別的物體投射過來的陰影。
立方體 本例的物體元素。 BoxGeometry 創(chuàng)建一個立方體,并設置該立方體的 castShadow 屬性為 true ,就能產生投影效果。
光源 要使用 可產生陰影效果 的光源,比如本例的 SpotLight 聚光燈。
AmbientLight 環(huán)境光 、PointLight 點光源 是不能產生陰影效果的。
使用 SpotLight 創(chuàng)建光源,并設置該光源的 castShadowtrue 開啟陰影效果。


第1步:搭建基礎場景

Three 中搭建基礎場景需要3要素:場景 Scene、攝像機 PerspectiveCamera、渲染器 WebGLRenderer 。

file
<script type="module">
  import {
    Scene, // 場景
    PerspectiveCamera, // 攝像機
    WebGLRenderer, // 渲染器
    Color, // 顏色(不是本例重點)
    PlaneGeometry, // 平面幾何(創(chuàng)建地面時會用到)
    BoxGeometry, // 立方幾何體(創(chuàng)建立方體時會用到)
    MeshLambertMaterial, // 非光澤表面的材質(可接受光照產生陰影效果)
    Mesh, // 網(wǎng)格,合成物體元素時會用到
    SpotLight // 聚光燈
  } from '../js/Three/src/Three.js'

  // 場景
  let scene = new Scene()

  // 攝像機
  let camera = new PerspectiveCamera(
    45,
    window.innerWidth / window.innerHeight,
    0.1,
    1000
  )

  // 設置攝像機位置
  camera.position.set(-30, 60, 60)
  // 鎖定攝像機鏡頭方向
  camera.lookAt(scene.position)

  // 渲染器
  let renderer = new WebGLRenderer()
  renderer.setClearColor(new Color(0xEEEEEE)) // 設置渲染器顏色
  renderer.setSize(window.innerWidth, window.innerHeight) // 渲染器尺寸

  // 將渲染器添加到頁面
  document.body.appendChild(renderer.domElement)

  // 渲染
  renderer.render(scene, camera)

</script>

我把場景的背景色設置成灰色 renderer.setClearColor(new Color(0xEEEEEE)) 。

此時頁面上是一片空白,還沒元素可以展示。


第2步:創(chuàng)建光源

因為本例 沒有使用 基礎材質(MeshBasicMaterial) ,渲染出來的物體沒有光源是不會顯示的,所以我先把光源添加到場景中,之后添加地面和立方體時就比較方便觀察了。

要實現(xiàn)陰影效果,我選擇了 SpotLight 聚光燈。

// 省略部分代碼

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

scene.add(spotLight) // 將聚光燈添加到場景中

雖然創(chuàng)建了光源,但此時場景中并沒有其他物體,所以場景還是一片空白。


第3步:創(chuàng)建地面

在本例中地面是用來接受物體投影的載體。

創(chuàng)建地面我使用了 PlaneGeometry 平面,該方法只需傳入寬和高即可。

然后使用 MeshLambertMaterial 材質,設置地面顏色為白色。

// 省略部分代碼

// 地面
let planeGeometry = new PlaneGeometry(60, 20) // 骨架
let planeMaterial = new MeshLambertMaterial({ color: 0xffffff }) // 可產生陰影的材質
let plane = new Mesh(planeGeometry, planeMaterial) // 網(wǎng)格

scene.add(plane) // 將地面添加到場景中
file

此時看到的地面呈現(xiàn)上圖的樣子(一點都不想地面)。

由于燈光的關系,地面看上去并不是純白色,離燈光越近的地方就越白,越遠就越灰。


我希望地面可以水平放置,所以我將地面沿x軸旋轉 -90°

// 省略部分代碼
plane.rotation.x = -90 * Math.PI / 180 // 地面 x軸 旋轉-90度
file


第4步:創(chuàng)建立方體

我使用 BoxGeometry 創(chuàng)建立方體,設置一個紅色的紋理。

// 省略部分代碼

// 立方體
let cubeGeometry = new BoxGeometry(6, 6, 6)
let cubeMaterial = new MeshLambertMaterial({ color: 0xff0000 }) // 可產生陰影的材質
let cube = new Mesh(cubeGeometry, cubeMaterial)

scene.add(cube)
file


修改一下立方體的位置

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


第5步:開啟陰影效果

用回上面提到的四句口訣就能開啟陰影效果

  1. 渲染器開啟陰影效果。
  2. 有一個能產生陰影的光源,并開啟陰影效果。
  3. 有一個接受陰影投射的元素(比如地面),并設置 接受陰影的屬性true
  4. 有一個能產生陰影效果的物體,并開啟陰影效果。


// 省略部分代碼

// 渲染器開啟陰影效果
renderer.shadowMap.enabled = true

// 光源開啟陰影效果
spotLight.castShadow = true

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

// 立方體開啟陰影效果
cube.castShadow = true
file

完成!


如果想設置陰影的精細度,還可以通過聚光燈的三個屬性進行控制:

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


本文主要講解陰影的基礎使用方法,先入個門,后面的案例文章會和結合其他效果完成更好玩的東西~



代碼倉庫

?Three 基礎陰影用法



推薦閱讀

??《『Three.js』起飛!》

??《『Three.js』輔助坐標軸》

??《『Three.js』場景 Scene》

??《『Three.js』幾個簡單的入門動畫(新手篇)》


點贊 + 關注 + 收藏 = 學會了
代碼倉庫

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容