Skip to content

174. 实战:佛光普照(四)

Published:

上节画了光环的部分:

2025-08-10 12.29.01.gif

这节加上底座。

其实底座和之前的云雷纹差不多:

2025-08-09 23.35.36.gif

但花纹会更复杂。

首先,现在没有地面的感觉:

2025-08-10 12.43.58.gif

其实是有地面的,我们加一个碰撞检测:

image.png

particles.addBehavior(
    new ApplyForce(
        new THREE.Vector3(0, -1, 0),
        new ConstantValue(100)
    )
)

particles.addBehavior(new ApplyCollision({
    resolve(pos, normal) {
        if(pos.y < -size.y * 2 / 3) {
            normal.set(0, 1, 0);
            return true;
        } else {
            return false;
        }
    }
}, 0.5));

加一下重力和碰撞检测。

这里地面是模型底部,我们上移了三分之二的模型高度,所以地面是 -size * 2 /3

particles.addBehavior(
    new ApplyForce(
        new THREE.Vector3(0, -1, 0),
        new ConstantValue(100)
    )
)

particles.addBehavior(new ApplyCollision({
    resolve(pos, normal) {
        if(pos.y < -size.y * 2 / 3) {
            normal.set(0, 1, 0);
            return true;
        } else {
            return false;
        }
    }
}, 0.5));

2025-08-10 12.43.58.gif

还是球状发射器比较好,换回去:

image.png

emissionOverTime: new ConstantValue(1000),
shape: new SphereEmitter({
    radius: 150,
    thickness: 0,
    arc: Math.PI * 2
}),

2025-08-10 12.49.48.gif

背面看不到圆:

image.png

改一下:

image.png

2025-08-10 12.52.02.gif

现在能感觉到地面反弹了,但重力还是有点大。

调小点:

image.png

重力调小,反弹系数调小。

2025-08-10 12.55.11.gif

然后把地面画出来。

新建 ground.js

import * as THREE from 'three';
import { Line2, LineGeometry, LineMaterial } from 'three/examples/jsm/Addons.js';

const group = new THREE.Group();

for(let i = 0; i < 5; i++) {
    const R = 80 + i * 50 ;
    const arc1 = new THREE.EllipseCurve(0, 0, R, R, 0, Math.PI * 2);
    const pointsArr1 = arc1.getPoints(50);
    const geometry1 = new LineGeometry();
    geometry1.setFromPoints(pointsArr1);
    const material1 = new LineMaterial({
        color: new THREE.Color('gold'),
        linewidth: 5 - i 
    });
    const line1 = new Line2(geometry1, material1);
    group.add(line1);
}

group.rotateX(-Math.PI / 2);
export default group;

先画 5 个圆环,从粗到细。

2025-08-10 13.59.38.gif

在每一圈圆环内加上 卍

image.png

for(let i = 0; i < 5; i++) {
    const figureGroup = new THREE.Group();

    const R = 50 + i * 50 ;
    for(let angle = Math.PI / 10; angle <= Math.PI * 2; angle += Math.PI  / 6) {
        const figureText = new SpriteText('卍', 12);
        figureText.color = 'gold';
        figureText.strokeWidth = 1;
        figureText.strokeColor = 'gold';
        figureText.position.set(R * Math.cos(angle), R * Math.sin(angle), 0);
        figureGroup.add(figureText);
    }
    group.add(figureGroup);
}

2025-08-10 14.07.52.gif

让它转起来:

image.png

let obj = {rotation: 0};
gsap.to(obj, {
    rotation: Math.PI * 2,
    repeat: -1,
    duration: 10,
    ease: 'none',
    onUpdate() {
        group.children.forEach((item, index) => {
            const flag = index % 2 === 0 ? 1 : -1;
            item.rotation.z = obj.rotation * flag;
        })
    }
});

2025-08-10 14.08.54.gif

外面再加上一圈云雷纹理的那种花纹:

image.png

for(let i = 1; i <= 5; i++) {
    const figureGroup = new THREE.Group();
    for(let angle = 0; angle < Math.PI  * 2; angle += Math.PI  / 10) {
        const R = 250 + i * 70;
        const x = R * Math.cos(angle);
        const y = R * Math.sin(angle);

        const pointsArr = [
            new THREE.Vector3(0, 0, 0),
            new THREE.Vector3(15, 0, 0),
            new THREE.Vector3(15, 15, 0),
            new THREE.Vector3(-15, 15, 0),
            new THREE.Vector3(-15, -15, 0),
            new THREE.Vector3(30, -15, 0),
            new THREE.Vector3(30, 30, 0),
            new THREE.Vector3(-30, 30, 0),
            new THREE.Vector3(-30, -30, 0),
            new THREE.Vector3(30, -30, 0)
        ];

        const geometry = new THREE.BufferGeometry();
        geometry.setFromPoints(pointsArr);
        const material = new THREE.LineBasicMaterial({
            color: new THREE.Color('gold')
        });
        const line = new THREE.Line(geometry, material);
        
        line.position.set(x, y, 0);    
        line.rotation.z = angle;
        
        figureGroup.add(line);
    }
    group.add(figureGroup);
}

五圈,每一圈的半径不同,具体画法就是 11 个点连起来。

2025-08-10 14.18.14.gif

外层应该更密一些:

image.png

我们画 3 圈,每一圈画的角度更密一些:

angle += Math.PI  / (10 + i)

2025-08-10 14.22.15.gif

粒子颜色统一都是金色,不用随机了:

image.png

startColor: new RandomColor(
    new THREE.Vector4(1, 0.7, 0, 1),
    new THREE.Vector4(1, 0.7, 0, 1)
),

2025-08-10 14.29.44.gif

案例代码上传了小册仓库

总结

这节我们画了底座的部分。

同样是用 Line、Curve 来画曲线,然后用 gasp 来做动画。

下节我们加上空中飘舞的经文。

评论