光照和阴影
本指南将帮助你开始在 TresJS 中使用简单的光照和阴影。
我们将构建一个包含三个网格和一个平面的简单场景,但只有两个网格会有阴影。
设置场景(可选)
我们导入所有需要的模块,为了方便,我们可以使用 cientos 中的轨道控制器,点击此处了解如何使用。
让我们在场景中放置四个对象,一个将是接收阴影的平面,其中两个将投射阴影,最后一个根本不会投射任何阴影。
我将使用 MeshToonMaterial。仅仅是因为我们可以轻松地看到“柔和的阴影”。
<script setup lang="ts">
import { TresCanvas } from '@tresjs/core'
import { OrbitControls } from '@tresjs/cientos'
</script>
<template>
<TresCanvas
clear-color="#111"
window-size
>
<OrbitControls />
<TresPerspectiveCamera :position="[5, 7.5, 7.5]" />
<TresMesh
:position="[-2, 2, 0]"
:rotation="[0, Math.PI, 0]"
>
<TresConeGeometry :args="[1, 1.5, 3]" />
<TresMeshToonMaterial color="#82DBC5" />
</TresMesh>
<TresMesh
:position="[0, 0, 0]"
>
<TresBoxGeometry :args="[1.5, 1.5, 1.5]" />
<TresMeshToonMaterial color="#4F4F4F" />
</TresMesh>
<TresMesh
:position="[2, -2, 0]"
>
<TresSphereGeometry />
<TresMeshToonMaterial color="#FBB03B" />
</TresMesh>
<TresMesh
:position="[0, -3, 0]"
:rotation="[-Math.PI / 2, 0, 0]"
>
<TresPlaneGeometry :args="[10, 10, 10, 10]" />
<TresMeshStandardMaterial color="#f7f7f7" />
</TresMesh>
</TresCanvas>
</template>
光照(说明)
如你所知,ThreeJs 中的每个实例在 TresJs 中都是可用的,所有类型的灯光也是如此,我们只需要添加 Tres
前缀即可使用它们。
但并非所有灯光都能投射阴影,这个设定直接来自 ThreeJs 并且合乎情理,例如,ambientLight 的目的是照亮场景的每一面,因此让它投射阴影毫无意义,相反,模仿太阳的 DirectionalLight 可以且应该投射阴影。
阴影(说明)
阴影也有很多类型,例如,“柔和阴影”会在物体从一侧接收到更多光线时自动生成,但总的来说,需要投射到另一个表面的“ThreeJS 默认阴影”需要由一个网格投射,另一个网格需要接收它。正如我们在示例中看到的,Plane
正在接收阴影,但不会投射阴影。请注意,并非所有材质都能投射或接收阴影。
在内部,ThreeJS 会自动生成一个带有 ShadowMaterial 的新网格,该网格会在每一帧中更新,这就是为什么如果你应用动画,阴影也会被动画化,但也正是为什么你必须谨慎使用阴影,因为它们可能会降低你的性能。
WARNING
过度使用阴影可能会降低你的性能。但是,有一些方法可以提高你的性能,有关更多信息,请查看 此视频。
启用阴影
我们可以将此分为三个步骤:
在渲染器上激活阴影
//...
<template>
<TresCanvas
clear-color="#111"
shadows
window-size
/>
//...
</template>
设置光线以投射阴影
我们可以简单地放置布尔值 cast-shadow
,Vue 将其理解为具有 true
值的 prop
AmbientLight 在这里不会生成任何类型的阴影
//...
<template>
<TresAmbientLight :intensity="1" />
<TresDirectionalLight
cast-shadow
:position="[0, 2, 0]"
:intensity="1"
/>
//...
</template>
设置对象以投射或接收阴影
与上一步类似,我们使用 cast-shadow
prop 设置我们要投射阴影的网格(我们的球体),并使用 receive-shadow
prop 设置要接收阴影的对象(我们的平面)。
//...
<template>
<TresMesh
cast-shadow
:position="[2, -2, 0]"
>
<TresSphereGeometry />
<TresMeshToonMaterial color="#FBB03B" />
</TresMesh>
<TresMesh
receive-shadow
:position="[0, -3, 0]"
:rotation="[-Math.PI / 2, 0, 0]"
>
<TresPlaneGeometry :args="[10, 10, 10, 10]" />
<TresMeshStandardMaterial color="#f7f7f7" />
</TresMesh>
//...
</template>
现在,我们已经完成了向场景添加阴影所需的所有必要步骤,如果我们应用我们在 基本动画 中学到的知识,并为我们的立方体添加运动,你将看到阴影也会随之动画化 🤩
<script setup>
import { shallowRef } from 'vue'
import { TresCanvas, useRenderLoop } from '@tresjs/core'
const boxRef = shallowRef()
const { onLoop } = useRenderLoop()
onLoop(() => {
if (boxRef.value) {
boxRef.value.rotation.y += 0.01
}
})
</script>
<template>
//...
<TresMesh
ref="boxRef"
cast-shadow
:position="[0, 0, 0]"
>
<TresBoxGeometry :args="[1.5, 1.5, 1.5]" />
<TresMeshToonMaterial color="#4F4F4F" />
</TresMesh>
//...
</template>
请注意,我特意没有对 Cone
应用 cast-shadow
,因此它不会投射任何阴影