Use vue to learn three.js particles and particle system-introduction and use of THREE.PointCloudMaterial material properties

1. Introduction to THREE.PointCloudMaterial material properties

We already know that creating a particle system requires two parameters, a geometry and a material. Next, I mainly introduce the properties of THREE.PointCloudMaterial.

Attributes description
color The color of all particles in the particle system, 当vertexColors属性值为true,而且也指定了几何体的colors属性。那么color属性指定的颜色会被忽略,使用几何体colors属性中的颜色。当vertexColors属性值为false,所有粒子会渲染成该属性定义颜色。the default value of this attribute is 0xFFFFFF
map With this attribute, a certain material can be applied to the particles. For example, a material that looks like a snowflake
size Specify the size of the particle through this attribute, the default value is 1
sizeAnnutation This attribute is a Boolean value. If true, the size of the particle is determined by the distance between the particle and the camera. If false, it means that the particle will have the same size regardless of the distance between the particle and the camera.
vertexColors This attribute is a boolean value, which determines the color of the particles when rendering. 当值为true,也指定了几何体的colors属性。就会使用几何体colors属性定义的颜色渲染粒子。当值为false,所有粒子都会渲染成color属性定义的颜色。The default value of this property is false, which means that all particles will be rendered in the same color by default. What color is determined by the color attribute
transparent This attribute determines whether the particle is transparent, and is usually used in conjunction with the opacity attribute. The default value is false, that is, the particles are opaque by default
opacity This attribute is used to specify the transparency of the particles, the value range is 0~1, the 当transparent属性值为true时,该属性才能生效。default value is 1 (opaque)
blending This attribute specifies the blending mode when the particles are rendered
fog This attribute specifies whether the particles are affected by fog, the default is true

2. THREE.PointCloudMaterial material usage

Using the THREE.PointCloudMaterial class to create particle materials is the same as creating other materials. See the sample code specifically

// 创建几何体
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 effect

Insert picture description here

4.demo code

<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>

Guess you like

Origin blog.csdn.net/qw8704149/article/details/111055119