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

Three.js开启Bloom泛光时PNG贴图Sprite显示异常如何解决

Three.js UnrealBloomPass 下PNG贴图Sprite正常显示方案

核心原因

现有分层Bloom实现的暗化逻辑仅判断了对象的isMesh属性,Three.js中Sprite对象的类型标识为isSprite,未被纳入暗化处理范围,导致Bloom渲染阶段Sprite贴图被泛光效果覆盖,出现显示异常。

落地方案

方案1:补全暗化逻辑的类型覆盖(改造成本最低)

  • 修改场景遍历的判断条件,从仅匹配isMesh调整为同时匹配obj.isMesh || obj.isSprite,覆盖Sprite类型对象
  • 提前初始化纯黑色的SpriteMaterial作为Sprite的暗化替换材质,注意将材质的transparent属性设为true,适配PNG贴图的透明通道
  • 遍历替换材质时先缓存对象的原始材质,待UnrealBloomPass渲染流程完成后,再遍历所有对象恢复原始材质即可
  • 核心逻辑代码参考:
// 提前初始化暗化材质
const darkMeshMat = new THREE.MeshBasicMaterial({ color: 0x000000 });
const darkSpriteMat = new THREE.SpriteMaterial({ color: 0x000000, transparent: true });

// Bloom渲染前的暗化遍历
scene.traverse(obj => {
  if (obj.isMesh || obj.isSprite) {
    // 非泛光层对象替换为暗化材质
    if (!obj.layers.test(bloomTargetLayer)) {
      obj.userData.originMat = obj.material;
      obj.material = obj.isMesh ? darkMeshMat : darkSpriteMat;
    }
  }
});

// 执行完BloomPass渲染后,恢复原材质
scene.traverse(obj => {
  if (obj.userData.originMat) {
    obj.material = obj.userData.originMat;
    delete obj.userData.originMat;
  }
});

方案2:平面网格模拟Sprite(复用现有逻辑无需额外适配)

如果不想修改现有暗化逻辑,可以直接用平面网格替代原生Sprite,实现完全一致的效果:

  • 用PlaneGeometry搭配加载了PNG贴图的MeshBasicMaterial替代原Sprite对象
  • 在每帧渲染调用前,执行planeMesh.lookAt(camera.position),即可实现平面始终朝向相机,和原生Sprite的表现完全一致,满足标签类使用需求
  • 该方案下平面属于Mesh类型,原有针对Mesh的暗化逻辑可以直接生效,无需额外调整

避坑说明

  • 不要尝试仅通过图层隔离跳过Sprite的暗化处理:UnrealBloomPass默认会读取全场景的渲染结果,未做暗化处理的非泛光层Sprite会被泛光计算覆盖原有颜色,无法正常显示
  • 暗化用的SpriteMaterial不要绑定原贴图,保持纯黑即可,避免残留贴图内容干扰Bloom的亮度计算结果

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.01 23:42:44