Three.js制作物体粒子爆炸特效,Shader实现

PBomb

首先,遍历构成飞机模型的物体信息,得到由每个物体顶点信息组成的points对象组成的group组

   
  console.log(this.fighterGroup, '飞机模型如下图');
  this.createPoints(this.fighterGroup); // 飞机模型


  createPoints(object3d) {
    if (!this.fighterPointsGroup) { 
      this.fighterPointsGroup = this.transformPoints(object3d);
      this.scene.add(this.fighterPointsGroup); // 由每个物体顶点信息组成的points对象的group
    }
  }

  transformPoints(object3d) {
    const texture = new THREE.TextureLoader().load("./assets/particles/1.png"); // 创建纹理图像
    const group = new THREE.Group();
    function createPoints(object3d, newObject3d) {
      if (object3d.children.length > 0) {
        object3d.children.forEach((child) => {
          if (child.isMesh) {
            const color = new THREE.Color( // 随机生成颜色
              Math.random(),
              Math.random(),
              Math.random()
            );
            const material = new THREE.ShaderMaterial({
              uniforms: {
                uColor: { value: color },
                uTexture: { value: texture },
                uTime: {
                  value: 0,
                },
              },
              vertexShader: vertexShader, // 顶点着色器
              fragmentShader: fragmentShader, // 片元着色器
              blending: THREE.AdditiveBlending,
              transparent: true,
              depthTest: false,
            });
            const points = new THREE.Points(child.geometry, material);
            points.position.copy(child.position);
            points.rotation.copy(child.rotation);
            points.scale.copy(child.scale);
            newObject3d.add(points);
            createPoints(child, points);
          }
        });
      }
    }

    createPoints(object3d, group);
    return group;
  }

操作用于传递到每个物体的着色器材质ShaderMaterial中的顶点着色器配置信息,遍历物体顶点组,得到每个每个物体的顶点信息对象points,设置所有物体所有顶点的xyz移动范围为-10到10,将坐标信息设置到每个物体缓冲区对象中,由顶点着色器接收

    this.fighterPointsGroup.traverse((child) => {
      if (child.isPoints) {
        let randomPositionArray = new Float32Array(
          child.geometry.attributes.position.count * 3
        );
        for (let i = 0; i < child.geometry.attributes.position.count; i++) { // 每个物体顶点数量
          randomPositionArray[i * 3 + 0] = (Math.random() * 2 - 1) * 10; // -10~10
          randomPositionArray[i * 3 + 1] = (Math.random() * 2 - 1) * 10;
          randomPositionArray[i * 3 + 2] = (Math.random() * 2 - 1) * 10;
        }

        child.geometry.setAttribute(
          "aPosition",
          new THREE.BufferAttribute(randomPositionArray, 3)
        );
        
        // 设置执行时间
        gsap.to(child.material.uniforms.uTime, {
          value: 10,
          duration: 10,
        });
      }
    });

顶点着色

attribute vec3 aPosition; // 最终位置(三维向量xyz)
uniform float uTime; // 动画帧时间
void main(){
    vec4 currentPosition = modelMatrix * vec4(position, 1.0);
    vec3 direction = aPosition - currentPosition.xyz; // 当前点最终位置减去起始位置

    vec3 targetPosition = currentPosition.xyz + direction * 0.1 * uTime;
    vec4 vPosition = viewMatrix * vec4(targetPosition, 1.0);
    gl_Position = projectionMatrix*vPosition;
    
    gl_PointSize = -100.0/vPosition.z; // 设置顶点近大远小效果
}

片元着色

uniform sampler2D uTexture;
uniform vec3 uColor;
void main(){
    vec4 uTextureColor = texture2D(uTexture, gl_PointCoord);
    gl_FragColor = vec4(uColor, uTextureColor.x);
}

扫描二维码关注公众号,回复: 15855113 查看本文章

猜你喜欢

转载自blog.csdn.net/dabaooooq/article/details/130656424