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透明区域显示正常,但切换视角后,透明区域会穿透天空盒,直接显示真实环境:

解决方法
这个问题核心是透明物体的渲染顺序与深度缓冲设置冲突,可以按以下步骤修复:
- 修正天空盒材质设置:天空盒作为场景背景,不需要开启
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
相关产品推荐
相关产品推荐

