在 Three.js 中,精灵(Sprite)材质和点云(Points,原 PointCloud) 都是用于高效渲染大量相似对象的特性,但它们有不同的应用场景和工作方式。
精灵是一种始终面向相机的 2D 平面对象,非常适合用于制作:
粒子效果
标签/标注
公告板效果(始终面向相机)
javascript
// 创建精灵材质
const spriteMaterial = new THREE.SpriteMaterial({
color: 0xff0000,
map: new THREE.TextureLoader().load('texture.png'),
transparent: true
});
// 创建精灵
const sprite = new THREE.Sprite(spriteMaterial);
sprite.scale.set(2, 2, 1); // 设置大小
scene.add(sprite);
javascript
const material = new THREE.SpriteMaterial({
color: 0xffffff, // 颜色
map: texture, // 纹理
transparent: true, // 透明度
opacity: 0.8, // 不透明度
rotation: Math.PI/4 // 旋转(弧度)
});
点云用于高效渲染大量点(粒子),每个点可以使用相同的材质。
javascript
// 创建几何体,添加顶点
const geometry = new THREE.BufferGeometry();
const count = 10000;
const positions = new Float32Array(count * 3);
for (let i = 0; i < count * 3; i++) {
positions[i] = (Math.random() - 0.5) * 100;
}
geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
// 创建点云材质
const material = new THREE.PointsMaterial({
color: 0xffffff,
size: 0.5, // 点的大小
transparent: true
});
// 创建点云
const points = new THREE.Points(geometry, material);
scene.add(points);
javascript
const pointsMaterial = new THREE.PointsMaterial({
color: 0xffffff,
size: 1.0, // 点大小
sizeAttenuation: true, // 透视衰减
map: texture, // 点的纹理
transparent: true,
opacity: 0.8,
alphaTest: 0.5 // 透明度测试
});

javascript
// 使用精灵表(sprite sheet)
const texture = new THREE.TextureLoader().load('spritesheet.png');
texture.repeat.set(1/6, 1/6); // 6x6 精灵表
texture.needsUpdate = true;
const spriteMaterial = new THREE.SpriteMaterial({ map: texture });
javascript
const vertexShader = `
varying vec3 vColor;
uniform float time;
uniform float size;
void main() {
vColor = color;
// 添加脉动动画
float pulse = sin(time * 2.0 + position.x * 0.1) * 0.5 + 0.5;
// 计算最终位置
vec3 pos = position;
pos *= 1.0 + pulse * 0.2; // 脉动效果
vec4 mvPosition = modelViewMatrix * vec4(pos, 1.0);
gl_PointSize = size * (8.0 / -mvPosition.z) * (1.0 + pulse * 0.3);
gl_Position = projectionMatrix * mvPosition;
}
`;
const fragmentShader = `
varying vec3 vColor;
void main() {
// 创建圆形点
vec2 coord = gl_PointCoord - vec2(0.5);
float distance = length(coord);
if (distance > 0.5) {
discard;
}
// 渐变透明度
float alpha = 1.0 - smoothstep(0.3, 0.5, distance);
// 输出颜色
gl_FragColor = vec4(vColor, alpha);
}
`;
// 创建着色器材质
const customMaterial = new THREE.ShaderMaterial({
vertexShader: vertexShader,
fragmentShader: fragmentShader,
transparent: true,
vertexColors: true,
uniforms: {
time: { value: 0.0 },
size: { value: 5.0 }
}
});
精灵优化:
合并多个精灵为一张纹理(精灵图集)
使用 Object3D 的 frustumCulled 属性
点云优化:
使用 BufferGeometry 代替 Geometry
对于静态点云,设置 matrixAutoUpdate = false
使用 InstancedBufferGeometry 处理实例化
javascript
// 创建粒子系统(雨滴效果)
function createRainParticles() {
const geometry = new THREE.BufferGeometry();
const particleCount = 5000;
// 位置
const positions = new Float32Array(particleCount * 3);
const velocities = new Float32Array(particleCount);
for (let i = 0; i < particleCount; i++) {
positions[i * 3] = Math.random() * 200 - 100;
positions[i * 3 + 1] = Math.random() * 100 + 50;
positions[i * 3 + 2] = Math.random() * 200 - 100;
velocities[i] = Math.random() * 0.5 + 0.5;
}
geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
geometry.setAttribute('velocity', new THREE.BufferAttribute(velocities, 1));
const material = new THREE.PointsMaterial({
color: 0xaaaaaa,
size: 0.5,
transparent: true,
opacity: 0.8
});
const rain = new THREE.Points(geometry, material);
// 动画循环中更新位置
function animateRain() {
const positions = rain.geometry.attributes.position.array;
for (let i = 0; i < particleCount; i++) {
positions[i * 3 + 1] -= velocities[i];
if (positions[i * 3 + 1] < -50) {
positions[i * 3 + 1] = 100;
}
}
rain.geometry.attributes.position.needsUpdate = true;
}
return { rain, animateRain };
}
根据具体需求选择:
需要少量、独立控制的 2D 元素 → 使用 精灵
需要大量、批量渲染的粒子 → 使用 点云