You need to enable JavaScript to run this app. ThreeJS加载透明PNG纹理出现黑背景,如何处理并实现纹理可移动?
优惠活动
大模型
产品
解决方案
定价
更多

ThreeJS加载透明PNG纹理出现黑背景,如何处理并实现纹理可移动?

问题解决方案

修复PNG纹理黑色背景问题

材质默认未开启透明通道,PNG的透明区域会被渲染为黑色,实例化MeshPhongMaterial时添加transparent: true配置即可启用alpha通道渲染,若透明边缘出现杂色,可额外添加alphaTest: 0.5过滤低透明度像素。

修复纹理横穿线条问题

该问题通常由非2的幂尺寸纹理的mipmap采样异常导致,加载纹理后添加以下配置即可解决:

const texture = new THREE.TextureLoader().load("assets/smile2.png");
// 关闭非必要的mipmap生成
texture.generateMipmaps = false;
// 配置线性过滤避免采样异常
texture.minFilter = THREE.LinearFilter;
texture.magFilter = THREE.LinearFilter;
// 若纹理出现上下颠倒可额外添加以下配置
// texture.flipY = false;

实现纹理背景匹配T恤底色

原有逻辑存在错误:先给模型设置发射色,又直接替换了子网格材质,导致选中的颜色失效。你可以直接将用户选择的颜色作为材质基础色,叠加透明笑脸纹理,纹理的透明区域会自动透出材质的基础色,也就是T恤底色,修改后的代码如下:

const colorSelection = {
  "pink": "#ff2d55",
  "purple": "#5856d6",
  "blue": "#007aff",
  "orange": "#ff9500",
}

const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 );
const renderer = new THREE.WebGLRenderer({ antialias: true });
const loader = new THREE.OBJLoader();
const myCanvas = document.getElementById("container");
const controls = new THREE.OrbitControls(camera, renderer.domElement);
const axisHelper = new THREE.AxisHelper(5);
const hlight = new THREE.AmbientLight (0x404040);
const directionalLight = new THREE.DirectionalLight(0xffffff,0.4);
// 提前加载纹理并配置参数
const texture = new THREE.TextureLoader().load("assets/smile2.png");
texture.generateMipmaps = false;
texture.minFilter = THREE.LinearFilter;
texture.magFilter = THREE.LinearFilter;

myCanvas.appendChild( renderer.domElement );

renderer.setSize( 800, 800 );
renderer.setClearColor ("darkgrey", 1);

camera.position.set(200,300,200);
controls.addEventListener("change", animate);

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

// 场景与灯光配置
scene.add(axisHelper);
scene.add(hlight);
scene.add(directionalLight);
directionalLight.position.set(0,1155,325);
directionalLight.castShadow = true;

// 提前缓存加载的T恤模型,避免重复请求
let tshirtModel = null;
// 预加载模型
loader.load("assets/standard-t-shirt/source/tshirt.obj", function(obj) {
  obj.scale.set(0.4,0.4,0.4)
  obj.position.set(0,-500,0)
  tshirtModel = obj;
})

function changeTextureColor(color) {
  if(!tshirtModel) return;
  // 生成对应颜色的纹理材质
  const tshirtMat = new THREE.MeshPhongMaterial({ 
    color: colorSelection[color],
    map: texture,
    transparent: true,
    alphaTest: 0.5
  });
  // 遍历更新所有子网格材质
  tshirtModel.traverse((child) => {
    if (child instanceof  THREE.Mesh) {
      child.material = tshirtMat;
    }
  })
  // 避免重复添加模型
  if(!scene.getObjectById(tshirtModel.id)) {
    scene.add(tshirtModel)
  }
}

document.querySelectorAll("button").forEach(colorBtn => colorBtn.addEventListener("click", function () {
  const userColor = this.id;
  changeTextureColor(userColor);
}))

额外优化说明

原有逻辑每次点击按钮都会重新加载OBJ模型,会导致场景内模型重复叠加、资源浪费,上述代码已经做了预加载处理,仅请求一次模型,点击时仅更新材质属性,性能更高。

内容的提问来源于stack exchange,提问作者DavidL.theRabbitKing

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.21 09:36:09