THREE.PointCloudMaterial材质属性介绍与使用
1.THREE.PointCloudMaterial材质属性介绍
我们已经知道创建粒子系统需要两个参数,一个几何体和一个材质。接下来主要介绍一下THREE.PointCloudMaterial的属性。
属性 | 描述 |
---|---|
color | 粒子系统中所有粒子颜色,当vertexColors属性值为true,而且也指定了几何体的colors属性。那么color属性指定的颜色会被忽略,使用几何体colors属性中的颜色。当vertexColors属性值为false,所有粒子会渲染成该属性定义颜色。 该属性的默认值是0xFFFFFF |
map | 通过该属性可以在粒子上应用某种材质。例如看起来像雪花的材质 |
size | 通过该属性指定粒子的大小,默认值是1 |
sizeAnnutation | 该属性是一个布尔值,若为true表示粒子的大小由粒子到相机的距离决定,若为false表示无论粒子到相机的距离是多少,粒子都会有相同的尺寸 |
vertexColors | 该属性是一个布尔值,决定粒子渲染时使用哪里的颜色。当值为true,也指定了几何体的colors属性。就会使用几何体colors属性定义的颜色渲染粒子。当值为false,所有粒子都会渲染成color属性定义的颜色。 该属性的默认值是false,即默认所有粒子会渲染成相同颜色。什么颜色由color属性决定 |
transparent | 该属性决定粒子是否透明,通常和opacity属性配合使用。默认值是false,即粒子默认不透明 |
opacity | 该属性用来指定粒子的透明度,取值范围0~1,当transparent属性值为true时,该属性才能生效。 默认值是1(不透明) |
blending | 该属性指定粒子渲染时的融合模式 |
fog | 该属性指定粒子是否受雾化影响,默认为true |
2.THREE.PointCloudMaterial材质使用
使用THREE.PointCloudMaterial类创建粒子材质和创建其他材质一样。具体看示例代码
// 创建几何体
const geom = new THREE.Geometry()
// 创建粒子材质
const material = new THREE.PointCloudMaterial({
size: this.properties.size.value,
transparent: this.properties.transparent,
opacity: this.properties.opacity.value,
vertexColors: this.properties.vertexColors,
sizeAttenuation: this.properties.sizeAttenuation,
color: this.properties.color
})
const range = 500
for (let i = 0; i < 15000; i++) {
const particle = new THREE.Vector3(
Math.random() * range - range / 2,
Math.random() * range - range / 2,
Math.random() * range - range / 2
)
// 给几何体添加顶点坐标
geom.vertices.push(particle)
const color = new THREE.Color(0xffffff * Math.random())
// 给几何体添加顶点颜色
geom.colors.push(color)
}
// 创建粒子系统对象
this.cloud = new THREE.PointCloud(geom, material)
this.cloud.name = 'particles'
// 将粒子系统对象添加到场景
this.scene.add(this.cloud)
3.demo效果
4.demo代码
<template>
<div>
<div id="container"></div>
<div class="controls-box">
<section>
<el-row>
<el-checkbox v-model="properties.transparent" @change="redraw">transparent</el-checkbox>
</el-row>
<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" @change="redraw"></el-slider>
</el-col>
<el-col :span="3">
<span class="vertice-span">{{item.value}}</span>
</el-col>
</div>
</div>
</el-row>
<el-row>
<el-checkbox v-model="properties.vertexColors" @change="redraw">vertexColors</el-checkbox>
</el-row>
<el-row>
<el-col :span="8" class="label-col"><label> color</label></el-col>
<el-col :span="16">
<div @click="inputClick">
<el-input :value="properties.color"></el-input>
</div>
<div v-show="isShowColors" class="color-select-layer">
<sketch-picker v-model="properties.color" @input="colorChange"></sketch-picker>
</div>
</el-col>
</el-row>
<el-row>
<el-checkbox v-model="properties.sizeAttenuation" @change="redraw">sizeAttenuation</el-checkbox>
</el-row>
<el-row>
<el-checkbox v-model="properties.rotateSystem" @change="redraw">rotateSystem</el-checkbox>
</el-row>
</section>
</div>
</div>
</template>
<script>
import * as THREE from 'three'
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js'
import { Sketch } from 'vue-color'
export default {
components: {
'sketch-picker': Sketch
},
data () {
return {
properties: {
size: {
name: 'size',
value: 4,
min: 0,
max: 20,
step: 0.1
},
opacity: {
name: 'opacity',
value: 0.6,
min: 0,
max: 1,
step: 0.1
},
transparent: true,
vertexColors: true,
sizeAttenuation: true,
rotateSystem: true,
color: '#ccffcc'
},
isShowColors: false,
cloud: null,
camera: null,
scene: null,
renderer: null,
controls: null
}
},
mounted () {
this.init()
},
methods: {
formatTooltip (val) {
return val
},
inputClick () {
this.isShowColors = !this.isShowColors
},
colorChange (val) {
this.properties.color = val.hex
this.redraw()
},
// 初始化
init () {
this.createScene() // 创建场景
this.createParticles() // 创建粒子系统
this.createCamera() // 创建相机
this.createRender() // 创建渲染器
this.createControls() // 创建控件对象
this.render() // 渲染
},
// 创建场景
createScene () {
this.scene = new THREE.Scene()
},
// 创建粒子系统
createParticles () {
// 创建几何体
const geom = new THREE.Geometry()
// 创建粒子材质
const material = new THREE.PointCloudMaterial({
size: this.properties.size.value,
transparent: this.properties.transparent,
opacity: this.properties.opacity.value,
vertexColors: this.properties.vertexColors,
sizeAttenuation: this.properties.sizeAttenuation,
color: this.properties.color
})
const range = 500
for (let i = 0; i < 15000; i++) {
const particle = new THREE.Vector3(
Math.random() * range - range / 2,
Math.random() * range - range / 2,
Math.random() * range - range / 2
)
// 给几何体添加顶点坐标
geom.vertices.push(particle)
const color = new THREE.Color(0xffffff * Math.random())
// 给几何体添加顶点颜色
geom.colors.push(color)
}
// 创建粒子系统对象
this.cloud = new THREE.PointCloud(geom, material)
this.cloud.name = 'particles'
// 将粒子系统对象添加到场景
this.scene.add(this.cloud)
},
// 创建相机
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(35, k, 0.1, 1000)
this.camera.position.set(-80, 60, 40) // 设置相机位置
this.camera.lookAt(new THREE.Vector3(10, 0, 0)) // 设置相机方向
this.scene.add(this.camera)
},
// 创建渲染器
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.shadowMap.type = THREE.PCFSoftShadowMap
this.renderer.setClearColor(0x3f3f3f, 1) // 设置背景颜色
element.appendChild(this.renderer.domElement)
},
// 重新绘制
redraw () {
this.scene.remove(this.cloud)
this.createParticles()
},
render () {
if (this.properties.rotateSystem) {
this.cloud.rotation.y += 0.01
}
this.renderer.render(this.scene, this.camera)
requestAnimationFrame(this.render)
},
// 创建控件对象
createControls () {
this.controls = new OrbitControls(this.camera, this.renderer.domElement)
}
}
}
</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>