Skip to content

粒子材质实现三叉星辉

🕒 Published at:

之前了解了点材质相关属性,并利用其特点做了几个“杂乱无章”的效果,今天来实现一个有规律的曲线效果。

效果如下

看到这种效果首先我们的思路应该怎么办呢,实现一条曲线似乎不是很容易的样子,暂时想不到好方法,无从下手中......

那么实现一条直线是不是就容易的多了,利用BufferGeometry来创建一大堆点,他们的x轴坐标随机分布,y轴和z轴的坐标都是0,这样一条直线上的点是不是就可以完成了

具体关键代码如下

js
// 声明一个变量
const parmasObj = {
count: 100, // 点的数量
size: 10, // 点的大小
radius: 100, // 半径 也就是线的长度
branch: 3 // 分支数
};
// 渲染一大堆点在x轴上
let geometry = null;
let material = null;
const generateGalaxy = () => {
geometry = new THREE.BufferGeometry();
// 沿着x轴创建一堆点
let positions = new Float32Array(parmasObj.count * 3);
for (let i = 0; i < parmasObj.count; i++) {
    const i3 = i * 3;
    positions[i3] = Math.random()*parmasObj.radius;
    positions[i3 + 1] = 0;
    positions[i3 + 2] = 0;
}
geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
// 创建一个空的材质
material = new THREE.PointsMaterial({
    color: 0xffffff,
    size: parmasObj.size,
    sizeAttenuation: true,
    blending: THREE.AdditiveBlending,
    depthWrite: false,
    transparent: true,
    alphaMap: texture, // 透明度贴图
    map: texture // 颜色贴图
});
// 将点添加到场景中
const points = new THREE.Points(geometry, material);
scene.add(points);
};

generateGalaxy();

做到这里一根线已经完成了,那么我们想根据上面parmasObj.branch完成多条线呢,也就是下图这种效果

三叉星辉照亮您的事业与前程

这里我们需要先了解一下几个数学概念

  • Math.cos(x) 函数返回一个数值的余弦值。
    • cos 方法返回一个 -1 到 1 之间的数值,表示角度(单位:弧度)的余弦值。
  • Math.sin(x) 函数返回一个数值的正弦值。
    • sin 方法返回一个 -1 到 1 之间的数值,表示角度(单位:弧度)的正弦值。
  • Math.PI 属性表示一个圆的周长和直径的比值,约等于 3.14159。也就是我们常说的π

了解以后大家分析下这块代码什么意思

js
const angle = (i % parmasObj.branch) * ((Math.PI * 2) / parmasObj.branch);

i % parmasObj.branch 表示的是当前点的索引除以分支数的余数,也就是当前点在第几颗星上,范围一定是0到parmasObj.branch-1之间

2π 就是一个完整的圆角度 2π/parmasObj.branch 就是将一个圆绘制成几份,也就是三叉星辉的角度

angle 就是当前点的角度

再根据勾股定理是不是就能得到

Math.cos(angle) 就是当前点的x轴坐标 Math.sin(angle) 就是当前点的y轴坐标

那么单位坐标 Math.cos(angle) 能知道了 乘上半径 (Math.random() * parmasObj.radius) 是不是就知道所有点的坐标了

具体代码如下

js
for (let i = 0; i < parmasObj.count; i++) {
    // 计算角度
    const angle = (i % parmasObj.branch) * ((Math.PI * 2) / parmasObj.branch);
    const distance = Math.random() * parmasObj.radius;
    const i3 = i * 3;
    positions[i3] = Math.cos(angle) * distance;
    positions[i3 + 1] = 0;
    positions[i3 + 2] = Math.sin(angle) * distance;
}

做到这里已经基本上完成了,下一步我们让三叉星辉弯了呢,如图

原谅我画布不好看,凑合看

观察图片可以看出来,距离圆点越远,角度越大,很明显这个和半径是有关系的,那么我们只需要将上面的代码改一下就可以了

js
for (let i = 0; i < parmasObj.count; i++) {
    // 计算角度
    const angle = (i % parmasObj.branch) * ((Math.PI * 2) / parmasObj.branch);
    const distance = Math.random() * parmasObj.radius;
    const i3 = i * 3;
    positions[i3] = Math.cos(angle+distance*0.02) * distance;
    positions[i3 + 1] = 0;
    positions[i3 + 2] = Math.sin(angle+distance*0.02) * distance;
}

为啥 distance要乘0.02呢,不然太大了,弧度不明显,为啥0.02呢 估摸着写的,和相机、半径等因素有关