You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为GLTF/OBJ模型节点的材质透明度添加淡入淡出动画?

GLTF模型材质透明度动画实现方案

问题描述

我试过多种方法都没用,手里有个GLTF模型,已经拿到带网格的节点,节点也有材质,但不知道怎么给材质的透明度值加动画?

另外还有个相关问题:给场景里带材质的OBJ模型加动画没问题,但网格和材质一多,这种方法就乱得不行,有没有解决思路?

尝试过的方案

方案1

if (node.isMesh) {
  node.material.transparent = node.material.opacity < 1.0;
  node.material.needsUpdate = true;

  // 报错:node.setAttribute is not a function
  node.setAttribute('animation', {
    property: "material.opacity",
    from: 0,
    to: 1,
    dur: 2000,
    easing: "easeInQuad",
    loop: false,
  });
}

方案2

if (node.isMesh) {
  node.material.transparent = node.material.opacity < 1.0;
  node.material.needsUpdate = true;

  // 报错:node.appendChild is not a function
  const animation = document.createElement("a-animation");
  animation.setAttribute("attribute", "material.opacity");
  animation.setAttribute("from", "0");
  animation.setAttribute("to", "1");
  animation.setAttribute("dur", "2000");
  animation.setAttribute("easing", "easeInQuad");
  animation.setAttribute("loop", "false");

  node.appendChild(animation);
}

解决思路

核心问题说明

你之前的错误是把Three.js的Mesh对象当成了DOM元素来操作——setAttribute和appendChild是浏览器DOM节点的方法,Three.js的3D对象并没有这些API,得用Three.js自身的动画系统或者第三方补间库来实现。

方法一:使用Three.js原生Animation系统

利用Three.js的AnimationMixer、AnimationClip和KeyframeTrack来创建材质透明度动画,适合单网格或少量网格的场景:

// 假设node是Three.js的Mesh实例,已引入Three.js核心库
const mixer = new THREE.AnimationMixer(node);

// 创建透明度关键帧轨道:时间点(秒)对应透明度值
const opacityTrack = new THREE.NumberKeyframeTrack(
  '.material.opacity', // 属性路径
  [0, 2],              // 时间轴:0秒到2秒
  [0, 1]               // 对应透明度:从0到1
);

// 创建动画片段
const clip = new THREE.AnimationClip('opacityAnim', -1, [opacityTrack]);
// 创建动画动作并配置
const action = mixer.clipAction(clip);
action.setEasing(THREE.EaseInQuad); // 设置缓动函数
action.play();

// 必须在渲染循环中更新动画混合器
const clock = new THREE.Clock();
function renderLoop() {
  requestAnimationFrame(renderLoop);
  const deltaTime = clock.getDelta();
  mixer.update(deltaTime);
  renderer.render(scene, camera);
}
renderLoop();

方法二:用Tween.js批量处理多材质动画

如果场景中有大量网格和材质,推荐用Tween.js做批量动画管理,代码更简洁易维护:

// 先引入Tween.js库
import * as TWEEN from '@tweenjs/tween.js';

// 收集所有需要添加透明度动画的材质
const targetMaterials = [];
scene.traverse((child) => {
  if (child.isMesh && child.material) {
    child.material.transparent = true; // 开启透明
    child.material.needsUpdate = true; // 标记材质需要更新
    targetMaterials.push(child.material);
  }
});

// 创建批量补间动画
new TWEEN.Tween({ currentOpacity: 0 })
  .to({ currentOpacity: 1 }, 2000) // 2秒内从0过渡到1
  .easing(TWEEN.Easing.Quadratic.In) // 缓动函数
  .onUpdate((obj) => {
    // 批量更新所有目标材质的透明度
    targetMaterials.forEach(material => {
      material.opacity = obj.currentOpacity;
    });
  })
  .start();

// 在渲染循环中更新Tween
function renderLoop() {
  requestAnimationFrame(renderLoop);
  TWEEN.update();
  renderer.render(scene, camera);
}
renderLoop();

关键注意事项

  • 必须将材质的transparent属性设为true,否则opacity属性不会生效。
  • 如果使用PBR材质(如MeshStandardMaterial),建议根据需求调整depthWrite和depthTest属性,避免透明物体渲染顺序异常。
  • 如果多个网格共享同一个材质,修改材质透明度会影响所有使用该材质的网格,若需要单独动画,需先克隆材质:child.material = child.material.clone();

内容的提问来源于stack exchange,提问作者Millefolium Ink

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.24 00:05:17