深度材质-MeshDepthMaterial介绍和使用
1.MeshDepthMaterial材质介绍
深度材质有个特性,其外观不是由光照或某个材质属性决定的,而是由物体到相机的距离决定的,通过这一个特性,我们可以创建出逐渐消失的效果,通常我们会利用相机的属性near和far来控制物体的消失速度,如果near和far之间的差值非常大时,物体远离相机时消失的速度会很慢,相反当near和far之间的差值非常小,那么物体消失的速度就会很快
2.MeshDepthMaterial材质的属性
MeshDepthMaterial材质的属性非常少,只有两个控制线框的属性
属性 | 描述 |
---|---|
wireframe | 是否显示线框 |
wireframeLinewidth | 线框的宽度 |
注:在更新完相机的属性far和near后要调用camera.updateProjectionMatrix()
3.demo说明
如上图,该示例支持以下功能
- 调整相机near属性
- 调整相机far属性
- 可以通过addCube和removeCube按钮新增和删除方块
- 调整speed来控制方块旋转速度
- 调整near和far属性后通过鼠标滚动,观察方块消失的速度
4.demo代码
<template>
<div>
<div id="container"></div>
<div class="controls-box">
<section>
<el-row>
<div v-for="(item,key) in properties" :key="key">
<div v-if="item&&item.name!=undefined">
<el-col :span="8">
<span class="vertice-span">{{item.name}}</span>
</el-col>
<el-col :span="13">
<el-slider v-model="item.value" :min="item.min" :max="item.max" :step="item.step" :format-tooltip="formatTooltip"></el-slider>
</el-col>
<el-col :span="3">
<span class="vertice-span">{{item.value}}</span>
</el-col>
</div>
</div>
</el-row>
<el-row>
<el-button type="primary" class="controls-button" size="mini" @click="addCube">addCube</el-button>
<el-button type="primary" class="controls-button" size="mini" @click="removeCube">removeCube</el-button>
</el-row>
</section>
</div>
</div>
</template>
<script>
import * as THREE from 'three'
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js'
export default {
components: {},
data () {
return {
properties: {
near: {
name: 'near',
value: 66,
min: 0,
max: 500,
step: 1
},
far: {
name: 'far',
value: 230,
min: 50,
max: 1000,
step: 1
},
speed: {
name: 'speed',
value: 0.02,
min: 0,
max: 0.5,
step: 0.01
}
},
defaultCubeNum: 0,
camera: null,
scene: null,
renderer: null,
controls: null
}
},
mounted () {
this.init()
},
methods: {
formatTooltip (val) {
return val
},
// 初始化
init () {
this.createScene() // 创建场景
this.createLight() // 创建光源
this.createCamera() // 创建相机
this.createRender() // 创建渲染器
this.createControls() // 创建控件对象
this.render() // 渲染
this.initCube() // 初始化方块
},
// 创建场景
createScene () {
this.scene = new THREE.Scene()
this.scene.overrideMaterial = new THREE.MeshDepthMaterial()
},
// 创建光源
createLight () {
// 环境光
const ambientLight = new THREE.AmbientLight(0xffffff, 0.1) // 创建环境光
this.scene.add(ambientLight) // 将环境光添加到场景
},
// 创建相机
createCamera () {
const element = document.getElementById('container')
const width = element.clientWidth // 窗口宽度
const height = element.clientHeight // 窗口高度
const k = width / height // 窗口宽高比
// PerspectiveCamera( fov, aspect, near, far )
this.camera = new THREE.PerspectiveCamera(45, k, 20, 300)
this.camera.position.set(80, 60, 80) // 设置相机位置
this.camera.lookAt(new THREE.Vector3(0, 0, 0)) // 设置相机方向
this.scene.add(this.camera)
},
initCube () {
while (this.defaultCubeNum < 300) {
this.addCube()
this.defaultCubeNum++
}
},
removeCube () {
const allChildren = this.scene.children
const lastObject = allChildren[allChildren.length - 1]
if (lastObject instanceof THREE.Mesh) {
this.scene.remove(lastObject)
}
},
addCube () {
const cubeSize = Math.ceil(3 + Math.random() * 3)
const cubeGeometry = new THREE.BoxGeometry(cubeSize, cubeSize, cubeSize)
const cubeMaterial = new THREE.MeshLambertMaterial({
color: 0xffffff
})
this.cube = new THREE.Mesh(cubeGeometry, cubeMaterial)
this.cube.castShadow = true
this.cube.updateMatrix()
// 设置方块位置
this.cube.position.x = -50 + Math.round(Math.random() * 150)
this.cube.position.y = Math.round(Math.random() * 10)
this.cube.position.z = -150 + Math.round(Math.random() * 250)
// 将方块添加到场景
this.scene.add(this.cube)
},
// 创建渲染器
createRender () {
const element = document.getElementById('container')
this.renderer = new THREE.WebGLRenderer()
this.renderer.setSize(element.clientWidth, element.clientHeight) // 设置渲染区域尺寸
this.renderer.shadowMap.enabled = true // 显示阴影
this.renderer.setClearColor(0x000000, 1) // 设置背景颜色
element.appendChild(this.renderer.domElement)
},
// 更新属性
updateFun () {
this.camera.near = this.properties.near.value
this.camera.far = this.properties.far.value
this.camera.updateProjectionMatrix()
const THIS = this
THIS.scene.traverse(function (e) {
if (e instanceof THREE.Mesh) {
e.rotation.x += THIS.properties.speed.value
e.rotation.y += THIS.properties.speed.value
e.rotation.z += THIS.properties.speed.value
}
})
},
render () {
this.updateFun()
this.renderer.render(this.scene, this.camera)
requestAnimationFrame(this.render)
},
// 创建控件对象
createControls () {
this.controls = new OrbitControls(this.camera, this.renderer.domElement)
this.controls.target = new THREE.Vector3(0, 0, 0)
}
}
}
</script>
<style>
#container {
position: absolute;
width: 100%;
height: 100%;
}
.controls-box {
position: absolute;
right: 5px;
top: 5px;
width: 300px;
padding: 10px;
background-color: #fff;
border: 1px solid #c3c3c3;
}
.label-col {
padding: 8px 5px;
}
.color-select-layer {
position: relative;
left: -20px;
padding: 15px 0;
}
.vertice-span {
line-height: 38px;
padding: 0 2px 0 10px;
}
</style>