three.js 阴影渲染
学习three.js的时候,发现有些时候场景需要为建筑添加阴影效果,然鹅threejs默认是把阴影效果关闭了的,倒腾了一下,总结开启阴影的四部曲:
- 光源要能照出阴影
// 平行光 DirectionalLight第二个参数为光照强度 范围 0-1 不写默认为1
const directionalLight = new THREE.DirectionalLight(0xffffff, 0.5)
directionalLight.position.set(10, 10, 10) // 平行光相对物体投射的源头位置
directionalLight.castShadow = true // 开启平行光产生阴影的效果 默认是false
directionalLight.target = this.cube // 光线投射的目标
this.scene.add(directionalLight)
- 物体要能产生阴影
// 立方体
const geometry = new THREE.SphereGeometry(1, 32, 32)
// 材质
const material = new THREE.MeshStandardMaterial({
color: '#000000'
})
this.cube = new THREE.Mesh(geometry, material) // 生成网格
this.cube.castShadow = true // 对象是否渲染到阴影贴图中,默认值为false
this.cube.position.y = 3 // 设置物体位置
this.scene.add(this.cube)
- 要有个能接受阴影的面
// 创建一个接受阴影的平面
const planeGeometry = new THREE.PlaneBufferGeometry(20, 20, 32, 32)
const planeMaterial = new THREE.MeshStandardMaterial({
color: '#ffffff'
})
const plane = new THREE.Mesh(planeGeometry, planeMaterial)
plane.rotation.x = -Math.PI / 2
plane.receiveShadow = true // 开启平面接受投射阴影的效果
this.scene.add(plane)
- 渲染器能渲染阴影效果
// 渲染函数
this.renderer = new THREE.WebGLRenderer({
antialias: true // 是否执行抗锯齿
})
// 开启渲染器渲染阴影的效果
this.renderer.shadowMap.enabled = true
this.renderer.shadowMap.type = THREE.PFCSoftShadowMap // 阴影类型
this.renderer.setSize(this.$refs.container.clientWidth, this.$refs.container.clientHeight)
this.$refs.container.appendChild(this.renderer.domElement)
有了上面这四步,基本能渲染出物体的阴影效果。
下面上完整的代码
<template>
<div class="practice">
<div id="container" ref="container"></div>
</div>
</template>
<script>
import * as THREE from 'three'
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js'
export default {
components: {},
data () {
return {
scene: null,
camera: null,
renderer: null,
cube: null,
controls: null
}
},
mounted () {
this.init()
this.animate()
},
methods: {
init () {
// 场景
this.scene = new THREE.Scene()
// 背景
this.scene.background = new THREE.Color(0xaaaaaa)
// 透视摄像机
this.camera = new THREE.PerspectiveCamera(90, this.$refs.container.clientWidth / this.$refs.container.clientHeight, 0.1, 1000)
this.camera.position.set(5, 5, 0)
this.camera.lookAt(0, 0, 0)
// 渲染函数
this.renderer = new THREE.WebGLRenderer({
antialias: true // 是否执行抗锯齿
})
// 开启渲染器渲染阴影的效果
this.renderer.shadowMap.enabled = true
this.renderer.shadowMap.type = THREE.PFCSoftShadowMap // 阴影的类型
this.renderer.setSize(this.$refs.container.clientWidth, this.$refs.container.clientHeight)
this.$refs.container.appendChild(this.renderer.domElement)
// 相机控制器
this.controls = new OrbitControls(this.camera, this.renderer.domElement)
// 立方体
const geometry = new THREE.SphereGeometry(1, 32, 32)
// 材质
const material = new THREE.MeshStandardMaterial({
color: '#000000'
})
this.cube = new THREE.Mesh(geometry, material) // 生成网格
this.cube.castShadow = true // 对象是否渲染到阴影贴图中,默认值为false
this.cube.position.y = 3 // 设置物体位置
this.scene.add(this.cube)
// // 环境光 AmbientLight第二个参数为光照强度 范围 0-1 不写默认为1
const light = new THREE.AmbientLight(0xffffff, 0.5)
this.scene.add(light)
// 平行光 DirectionalLight第二个参数为光照强度 范围 0-1 不写默认为1
const directionalLight = new THREE.DirectionalLight(0xffffff, 0.5)
directionalLight.position.set(10, 10, 10) // 平行光相对物体投射的源头位置
directionalLight.castShadow = true // 开启平行光产生阴影的效果 默认是false
directionalLight.target = this.cube // 光线投射的目标
this.scene.add(directionalLight)
// 创建一个接受阴影的平面
const planeGeometry = new THREE.PlaneBufferGeometry(20, 20, 32, 32)
const planeMaterial = new THREE.MeshStandardMaterial({
color: '#ffffff'
})
const plane = new THREE.Mesh(planeGeometry, planeMaterial)
plane.rotation.x = -Math.PI / 2
plane.receiveShadow = true // 开启平面接受投射阴影的效果
this.scene.add(plane)
},
animate () {
// 实时渲染动画,页面切换离开会停下,性能比较好
requestAnimationFrame(this.animate)
this.controls.update()
this.renderer.render(this.scene, this.camera)
}
}
}
</script>
<style scoped lang='less'>
.practice{
#container{
height: 700px;
}
}
</style>
下面是运行效果