半透明玻璃叠在一起,看不见背面
给玻璃幕墙设了 opacity: 0.4,结果每一层玻璃都像实心板,后面的楼完全被挡住。

现象
单块玻璃看起来正常,两块前后叠放时,后一块完全不可见, 或者前后关系随相机角度跳变。透过玻璃看不到内部的家具和结构。
原因
transparent: true 只影响混合,不改变深度写入。
three.js 的透明物体默认仍然 depthWrite: true,
先画的玻璃把深度写进了缓冲,后画的玻璃在深度测试中被剔除。
同时,透明物体按对象中心排序,不按面排序。 一个由很多面组成的玻璃盒,其各个面无法正确前后排序, 就会出现“某几面消失、某几面又叠出新颜色”的情况。
排查过程
- 把
depthWrite设为false,观察背面是否出现,以确认是深度写入问题。 - 把
transparent暂时设为false、opacity设 1,确认几何与朝向正常。 - 用
material.side试THREE.DoubleSide,判断是否因背面剔除导致缺面。
解决方案
常规玻璃材质:关闭深度写入、双面渲染,并让透明层统一排在最后:
var glassMat = new THREE.MeshPhysicalMaterial({
color: 0x9fc6e8,
transparent: true,
opacity: 0.35,
roughness: 0.1,
metalness: 0,
depthWrite: false, // 关键
side: THREE.DoubleSide,
transmission: 0.6
});
glassMat.renderOrder = 10; // 数值大的后画
多层玻璃需要正确的层次时,把每一层拆成独立网格,按距离相机由远到近绘制。
简单可控的做法是逐层设置 renderOrder:
glassLayers.forEach(function (mesh, i) {
mesh.material.depthWrite = false;
mesh.renderOrder = 100 - i; // 远景先画
});
如果材质只有“透明/不透明”两种状态,不需要渐变,用 alphaTest
走不透明管线,性能更好也不会排序出错:
var foliageMat = new THREE.MeshStandardMaterial({
map: leafTexture,
alphaTest: 0.5, // 低于 0.5 的像素直接丢弃
transparent: false,
side: THREE.DoubleSide
});
可运行示例
复现器保留了本页的故障输入:给玻璃幕墙设了 opacity: 0.4 ,结果每一层玻璃都像实心板,后面的楼完全被挡住。点「修复后」可以看到同样的输入在正确配置下的结果。
修复后:常规玻璃材质:关闭深度写入、双面渲染,并让透明层统一排在最后:
验证
绕建筑旋转一周,透过玻璃应始终能看到内部的柱子,不会出现某角度突然变实心。
两块玻璃前后叠放时,叠合区颜色应比单层更深,符合叠加规律。
用 renderer.info.render.calls 确认没有因为拆层导致调用数失控。
性能提醒:透明物体越多,overdraw 越严重。 大片玻璃幕墙建议只在近景开启透明,远景改用半透明贴图烘焙进材质, 避免整个城市都在混合计算。
经纬志(2026)。《半透明玻璃叠在一起,看不见背面》。https://www.jingweizhi.com/cookbook/three-material-transparent.html(访问日期 2026-11-03)。