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

Three.js中添加PNG图片出现透明区域穿透天空盒异常求助

Three.js透明PNG与天空盒渲染异常解决方案

问题重现代码

透明PNG平面实现

var material = new THREE.MeshLambertMaterial({
    map: loader.load(phoneImg),
    transparent: true,
});
var geometry = new THREE.PlaneGeometry(100, 100);
var phone = new THREE.Mesh(geometry, material);
phone.position.set(0, 180, -220);
scene.add(phone);

天空盒实现

const skyGeo = new THREE.SphereGeometry(1000, 25, 25);
const textureLoader = new THREE.TextureLoader();
const texture = textureLoader.load("/img/moonsky.png");
texture.encoding = THREE.sRGBEncoding;
texture.mapping = THREE.EquirectangularReflectionMapping;
const skyMaterial = new THREE.MeshPhongMaterial({
    map: texture,
    toneMapped: true,
    transparent: true,
});
skyBox = new THREE.Mesh(skyGeo, skyMaterial);
skyBox.material.side = THREE.BackSide;
scene.add(skyBox);

问题现象

部分视角下PNG透明区域显示正常,但切换视角后,透明区域会穿透天空盒,直接显示真实环境:
异常显示效果1
异常显示效果2

解决方法

这个问题核心是透明物体的渲染顺序与深度缓冲设置冲突,可以按以下步骤修复:

  • 修正天空盒材质设置:天空盒作为场景背景,不需要开启transparent: true,开启后会导致它不写入深度缓冲,被透明PNG平面的区域穿透。修改天空盒材质:
const skyMaterial = new THREE.MeshPhongMaterial({
    map: texture,
    toneMapped: true,
    transparent: false,
});
  • 调整渲染顺序(可选):如果仍有问题,强制指定天空盒优先渲染,确保它先写入深度缓冲:
skyBox.renderOrder = -1;
  • 优化PNG材质的透明处理:对于带透明通道的PNG,使用alphaTest替代单纯的transparent,可以避免半透明区域的渲染顺序问题,同时提升性能:
var material = new THREE.MeshLambertMaterial({
    map: loader.load(phoneImg),
    alphaTest: 0.5, // 只渲染alpha值大于0.5的像素
});

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 05:46:18