在 Three.js 的三维世界构建中,纹理动画能为场景增添动态活力,让静态模型栩栩如生。本教程将深入探讨纹理动画在 Three.js 中的使用,涵盖关键概念、代码实现及优化技巧,助你提升场景表现力。
纹理动画基础原理
纹理动画的核心在于按特定顺序和时间间隔切换纹理。在 Three.js 里,通常借助 TextureLoader 加载纹理图片,利用材质(如 MeshBasicMaterial 或 MeshStandardMaterial)将纹理应用到几何体上。通过改变材质的map属性来切换纹理,配合requestAnimationFrame实现流畅动画效果。
准备工作
开始前,需确保已引入 Three.js 库。可通过 CDN 链接在 HTML 文件中引入:
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r134/three.min.js"></script>
同时,准备一系列用于动画的纹理图片,假设这些图片命名规则为texture_0.jpg、texture_1.jpg...texture_n.jpg,且保存在textures/目录下。
加载纹理序列
首先,编写函数加载纹理序列:
function loadTextureSequence(numTextures) {
const textureLoader = new THREE.TextureLoader();
const textures = [];
for (let i = 0; i < numTextures; i++) {
const texture = textureLoader.load(`textures/texture_${i}.jpg`);
textures.push(texture);
}
return textures;
}
此函数通过循环加载指定数量的纹理图片,返回包含所有纹理的数组。
创建动画材质
接着,创建用于动画的材质,动态更新map属性:
function createAnimatedMaterial(textures) {
const material = new THREE.MeshStandardMaterial({
map: textures[0]
});
let currentTextureIndex = 0;
const textureUpdateInterval = 100; // 每100毫秒切换一次纹理,可根据需求调整
let textureUpdateTimer = 0;
return {
material,
update: (deltaTime) => {
textureUpdateTimer += deltaTime;
if (textureUpdateTimer >= textureUpdateInterval) {
textureUpdateTimer = 0;
currentTextureIndex = (currentTextureIndex + 1) % textures.length;
material.map = textures[currentTextureIndex];
material.needsUpdate = true;
}
}
};
}
上述代码定义了一个createAnimatedMaterial函数,接受纹理数组作为参数。在返回的对象中,包含动画材质material和用于更新纹理的update函数。update函数根据时间间隔切换纹理,并标记材质需要更新。
整合到场景中
将动画材质应用到几何体并添加到场景:
// 创建场景、相机和渲染器
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// 加载纹理序列
const numTextures = 10; // 假设共有10张纹理图片
const textures = loadTextureSequence(numTextures);
// 创建动画材质
const animatedMaterialObject = createAnimatedMaterial(textures);
const animatedMaterial = animatedMaterialObject.material;
// 创建几何体并应用动画材质
const geometry = new THREE.BoxGeometry(1, 1, 1);
const mesh = new THREE.Mesh(geometry, animatedMaterial);
scene.add(mesh);
// 设置相机位置
camera.position.z = 5;
// 动画循环
function animate() {
requestAnimationFrame(animate);
const deltaTime = clock.getDelta();
animatedMaterialObject.update(deltaTime);
renderer.render(scene, camera);
}
const clock = new THREE.Clock();
animate();
上述代码创建了一个简单场景,加载纹理序列,创建动画材质并应用到立方体上。通过requestAnimationFrame和clock.getDelta()实现动画更新和渲染。
优化与扩展
- 纹理压缩:使用压缩格式(如 JPEG、WebP)减少纹理文件大小,提升加载速度。
- 预加载:在场景加载初期预加载所有纹理,避免动画卡顿。可使用Promise.all方法并行加载纹理。
- 动态帧率调整:根据设备性能动态调整纹理切换间隔,保证动画流畅性。例如,在性能较低设备上适当增大切换间隔。
纹理动画为 Three.js 场景注入生机。通过理解原理、掌握代码实现及优化技巧,你能创建更具吸引力的三维场景,为用户带来沉浸式体验。