Three.js / WebGL - 透明平面隐藏在它们后面的其他平面

Posted

技术标签:

【中文标题】Three.js / WebGL - 透明平面隐藏在它们后面的其他平面【英文标题】:Three.js / WebGL - transparent planes hiding other planes behind them 【发布时间】:2012-06-25 07:01:07 【问题描述】:

当您在 Three.js / WebGL 中有两个平面并且其中一个或两个都是透明的时,有时后面的平面会被上面的透明平面隐藏。这是为什么呢?

【问题讨论】:

related 【参考方案1】:

这对我有用,不要使用文字布尔值 true 尝试使用 1。

object3d.material.transparent = 1; 

【讨论】:

【参考方案2】:

设置Mesh renderOrder解决我的问题,下面是我的代码,你可以修改 node.renderOrder值:

loader.load(model_url, (gltf)=>
            let scene = gltf.scene

            scene.traverse((node)=>

                if(node.isMesh)
                    node.material.transparent = true

                    if(node.name === 'car_windows')
                        node.material.opacity = 0.4
                        node.material.side = 0
                        node.renderOrder = 110
                    

                    if(node.name === 'car_body')
                        node.material.opacity = 0.4
                        node.renderOrder = 100
                    

                    if(node.name === 'car_seats')
                        node.material.opacity = .5
                        node.renderOrder = 90
                    

                    mesh_arr.push(node)
                    mesh_objs[node.name] = node
                
            )
)

【讨论】:

虽然,答案不包括任何示例,也不是真正的描述性,这是唯一对我有用的选项,谢谢! @Footniko 抱歉没有示例代码,我已经添加了它,希望对您有所帮助。 :)【参考方案3】:

depthWrite 属性设置为false 解决了我的问题。

new THREE.MeshBasicMaterial( 
    opacity: 0.25, 
    transparent: true, 
    side: THREE.DoubleSide, 
    depthWrite: false
);

【讨论】:

谢谢。不再有“透明黑盒问题”!【参考方案4】:

假设您正在使用一些透明的 *.png 图像。那么这会有所帮助:

new THREE.MeshBasicMaterial(  side:THREE.BackSide,map:texture, depthWrite: false, depthTest: false );

【讨论】:

由于某种原因,side: THREE.BackSide 部分阻止了我的图像一起渲染。但除此之外,其余的都很好! 您可能想要使用 THREE.DoubleSide 以便从两侧都可见。 它适用于我的情况,但有什么影响?哪些案例现在将开始不起作用?【参考方案5】:

fwiw,如果你有很多平行平面(看不到你的样本,谷歌无法解析你的域),很容易让它们沿着垂直轴排序。对于平面列表 [A B C D],抽签顺序将是 [A B C D] 或 [D C B A],仅此而已!因此,排序不需要对性能造成影响。随身携带它们就可以了。

【讨论】:

问题是我有一些平面应该被渲染穿过其他平面。就像它们是 3D 平剑一样。我可以问一下,您是如何在提出这个问题这么久之后才找到这个问题的,以及 4 个支持者是如何来到这里的? 您的问题与人们的行为有关,我无法回答 :) 但是,如果您有相互交叉的多边形,那么除了像 K-Buffers 或原始 A- 这样的每个片段之外,没有简单的正确解决方案缓冲区算法,除非您专门监管三角形交叉点并即时对其进行镶嵌。【参考方案6】:

尝试在材料中添加alphaTest: 0.5

【讨论】:

试过了,没用:/我猜这是一个 webgl 问题,所以我必须重新设计我的游戏如何显示飞机。不过它看起来有点被黑了。 我有一个平面,其基于画布的纹理映射到它以显示文本。在某些角度/位置,我遇到了纹理材质的透明度问题,这解决了它,所以谢谢! 注意:alphaTest 是一个阈值,它将使纹理中的半透明区域完全不透明(当像素不透明度 > 阈值时)或完全透明(当像素不透明度 【参考方案7】:

这不是错误,它只是 OpenGL(以及 WebGL)的工作原理。透明表面不能很好地与 z 缓冲区配合使用,因此必须手动排序并从后到前渲染。三个 JS 正在尝试为您执行此操作(这就是为什么当您设置 X 值 > 0 时问题消失的原因)但无法像您显示的那样可靠地处理相交几何体的情况。

我已在 different SO question 中更深入地解释了该问题,因此您可能需要参考。

【讨论】:

感谢您的回答,但您是在告诉我最好重新设计我的游戏,或者是破解 Three.JS 的解决方案? @Toji 您提到的问题并未处理完全相同的问题。在另一个问题中,只有对象/纹理的一部分是透明的,在这个问题中,整个平面都是透明的,这很容易通过完全停用透明平面的 depthWrite 来解决。

以上是关于Three.js / WebGL - 透明平面隐藏在它们后面的其他平面的主要内容,如果未能解决你的问题,请参考以下文章

WebGL 多画布three.js 示例

Three.js中同一网格面上的多个透明纹理

学习threejs / webGL - 颜色和透明度

WebGL 渲染透明对象。渲染顺序

Three.js 精密地形碰撞

浅谈图形学WebGL 以及 Three.js