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

该文章介绍了如何在Three.js中遍历飞机模型的物体信息,创建顶点着色器材质并应用随机颜色和纹理。通过设置顶点位置并结合时间参数实现顶点动画,使模型各部分在-10到10的范围内动态移动。同时,文章还展示了顶点和片元着色器的代码片段,用于控制点的大小和颜色变化。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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);
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

山楂树の

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值