Skip to content

171. 实战:佛光普照

Published:

这节开始我们来做一个有意思的 3D 场景:

一尊大佛坐在中央,地下一圈圈转动的金色花纹,空中飘舞着金色的经文,然后背景音乐是念经的声音,旁边有个木鱼可以敲,然后敲的时候会有功德 +1 的粒子效果

image.png

这个佛光很明显就是粒子效果,很适合作为粒子的实战。

我们来写一下:

npx create-vite online-buddha

image.png

创建项目,进入项目,安装依赖:

pnpm install
pnpm install --save three
pnpm install --save-dev @types/three

改下 src/main.js

import './style.css';
import * as THREE from 'three';
import {
    OrbitControls
} from 'three/addons/controls/OrbitControls.js';
import mesh from './mesh.js';

const scene = new THREE.Scene();

scene.add(mesh);

const light = new THREE.DirectionalLight(0xffffff);
light.position.set(500, 300, 600);
scene.add(light);

const light2 = new THREE.AmbientLight();
scene.add(light2);

const axesHelper = new THREE.AxesHelper(1000);
scene.add(axesHelper);

const width = window.innerWidth;
const height = window.innerHeight;

const camera = new THREE.PerspectiveCamera(60, width / height, 1, 10000);
camera.position.set(0, 500, 500);
camera.lookAt(0, 0, 0);

const renderer = new THREE.WebGLRenderer({
  antialias: true
});
renderer.setSize(width, height)

function render() {
    renderer.render(scene, camera);
    requestAnimationFrame(render);
}

render();

document.body.append(renderer.domElement);

const controls = new OrbitControls(camera, renderer.domElement);

创建 Scene、Light、Camera、Renderer

改下 style.css

body {
    margin: 0;
}

然后创建 mesh.js

import * as THREE from 'three';

const geometry = new THREE.BoxGeometry(100, 100, 100);
const material = new THREE.MeshPhongMaterial({
    color: 'orange'
})
const mesh = new THREE.Mesh(geometry, material);

export default mesh;

先画个立方体

跑一下:

npm run dev

image.png

2025-08-10 09.03.47.gif

然后我们去找个佛祖的模型:

https://sketchfab.com/3d-models/buddha-ae0f992ba88842649d4655ba650c15d2

image.png

image.png

下载这个 4M 的精简模型就行。

放到 public 目录:

image.png

加载下:

import * as THREE from 'three';
import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';

const loader = new GLTFLoader();

const buddha = new THREE.Group();

export const loadPromise = loader.loadAsync("./buddha.glb");

loadPromise.then(gltf => {
    buddha.add(gltf.scene);
    console.log(gltf);

    gltf.scene.scale.setScalar(50);

    const box = new THREE.BoxHelper(gltf.scene);
    buddha.add(box);
})

export default buddha;

放大 50 倍,加一个包围盒

看下效果:

2025-08-10 09.24.32.gif

让它绕 y 轴旋转 180 度,给它一个 name:

image.png

buddha.rotateY(Math.PI);
buddha.name = 'buddha';

然后相机焦点调到佛祖中央的位置:

image.png

loadPromise.then(() => {
  const box3 = new THREE.Box3();
  box3.expandByObject(mesh);

  const center = box3.getCenter(new THREE.Vector3());
  
  camera.lookAt(center.x, center.y, center.z);
  controls.target.set(center.x, center.y, center.z);
})

用包围盒拿到佛祖的中央位置,注意这里要等模型加载完。

把相机焦点和 OrbitControls 的焦点移到佛祖中央位置。

试一下:

2025-08-10 09.34.01.gif

现在整个 3D 场景的中心点就是佛祖中央了。

我们给佛祖调成金色:

image.png

gltf.scene.traverse(obj => {
    if(obj.isMesh) {
        console.log(obj.name, obj);
    }
})

先打印下所有 mesh:

image.png

不用区分那么细了,整体改颜色就行。

image.png

obj.material.color.set('gold')

image.png

光线强一点:

image.png

const light = new THREE.DirectionalLight(0xffffff, 25);
light.position.set(0, 200, 500);
camera.position.set(0, 200, 600);

改下灯光、相机位置。

2025-08-10 09.55.12.gif

这样我们的佛祖就准备好了。

案例代码上传了小册仓库

总结

这节开始更在线佛祖项目。

我们从 sketchfab 找了一个模型,用包围盒计算出模型中央位置,把相机焦点放到中央,然后调了一下材质颜色,灯光强度。

现在佛祖就在 3D 场景中央了,并且颜色也是对的。

下节加上佛光效果。

评论