three.js中plane透明部分背后的物体变全透明的问题及解决方法

问题描述

最近在使用three.js做一个3D场景的项目,遇到了一个比较奇怪的问题。我使用了一个planeGeometry作为一个平面,然后设置了一个meshBasicMaterial,使用了一个png图片作为纹理贴图,设置了meshBasicMaterial的map属性。由于png图片有透明的部分,我还设置了meshBasicMaterial的transparent属性为true,这样就可以让plane的透明部分不显示。

但是,当我把这个plane放到场景中,发现了一个奇怪的现象:plane透明的部分背后的其他物体变成了全透明的,就像是被plane遮挡住了一样。这显然不是我想要的效果,我想要的是plane透明的部分能够看到背后的物体,而不是让它们消失。

问题原因

根据我从网络上搜索到的信息,这个问题可能是由于深度排序的问题导致的1。深度排序是指three.js在渲染场景中的物体时,会根据物体的距离来决定渲染的顺序,距离相机近的物体会先渲染,距离相机远的物体会后渲染2。这样可以避免一些不必要的渲染,提高性能。

但是,当物体有透明度的时候,深度排序就会出现问题。因为透明度会影响物体的可见性,如果一个物体是半透明的,那么它背后的物体应该是可以看到的,而不是被遮挡住的。但是,如果three.js按照深度排序的规则,先渲染了一个半透明的物体,然后再渲染它背后的物体,那么就会出现一个问题:由于半透明的物体已经写入了深度缓冲区,它背后的物体就会被认为是被遮挡住的,所以就不会被渲染,导致看起来像是全透明的3

这就是我遇到的问题的原因,由于我设置了plane的transparent属性为true,three.js就会按照深度排序的规则,先渲染plane,然后再渲染plane背后的物体,但是由于plane已经写入了深度缓冲区,plane背后的物体就被忽略掉了,导致看起来像是全透明的。

解决方法

针对这个问题,有几种可能的解决方法,我根据我自己的情况尝试了一下,下面我就来介绍一下:

renderOrder

renderOrder是 Three.js 提供的一个强大工具,用于显式控制物体的渲染顺序。通过合理设置 renderOrder,可以在复杂场景中实现预期的渲染效果,特别是在处理透明物体时。然而,需要注意性能和其他属性的综合使用,以达到最佳的渲染效果和性能平衡。

var material = new THREE.MeshBasicMaterial({
    map: texture,
    transparent: true,
    depthWrite: false //这一行
});

这样,plane就不会写入深度缓冲区,也就不会影响背后的物体的渲染,达到了我想要的效果。

  • 设置meshBasicMaterial的alphaTest属性为一个合适的值,比如0.5,这样就可以过滤掉一些完全透明的像素这种方法的原理是,当一个像素的透明度低于alphaTest的值时,就会被认为是完全透明的,不会被渲染,也不会写入深度缓冲区。这样,plane的透明部分就不会影响背后的物体的渲染,但是plane的不透明部分还是会写入深度缓冲区,遮挡背后的物体。这种方法的优点是,可以保留plane的阴影效果,缺点是,需要调整alphaTest的值,找到一个合适的平衡点,否则可能会出现一些锯齿或者断裂的现象。在创建meshBasicMaterial的时候,加上一行代码:
var material = new THREE.MeshBasicMaterial({
    map: texture,
    transparent: true,
    alphaTest: 0.5 //这一行
});
var material = new THREE.MeshBasicMaterial({
    map: texture,
    transparent: true,
    blending: THREE.CustomBlending, //这一行
    blendEquation: THREE.AddEquation, //混合方程
    blendSrc: THREE.SrcAlphaFactor, //源混合因子
    blendDst: THREE.OneMinusSrcAlphaFactor //目标混合因子
});
  • 调整场景中物体的位置,让透明的plane不要遮挡其他物体。这种方法的原理是,通过改变物体的位置,让plane的透明部分和背后的物体不重叠,从而避免深度排序的问题。这种方法的优点是,不需要修改任何代码,只需要调整一下场景的布局,缺点是,可能会影响场景的美观和逻辑,也可能会引入其他的问题,比如物体的遮挡和碰撞。

1: three.js中透明物体的渲染顺序问题2: three.js中的深度排序3: three.js中透明物体的渲染问题4: three.js中透明物体的渲染方法

  • 20
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值