Three.js Material transparent 两个透明物体的渲染问题

原本想用两个圆柱体实现盛满液体的玻璃容器效果,如实有了如下代码:

 1 var liquid = new THREE.Mesh(
 2   new THREE.CylinderGeometry(40, 40, 150, 32, 32),
 3   new THREE.MeshPhongMaterial({
 4     color: '#318414',
 5     emissive: '#318414',
 6     specular: '#22842c',
 7     shininess: 10,
 8     shading: THREE.FlatShading,
 9     transparent: true,
10     opacity: 0.5,
11   }),
12 );
13 
14 var tube = new THREE.Mesh(
15   new THREE.CylinderGeometry(45, 45, 150, 32, 32, true),
16   new THREE.MeshPhongMaterial({
17     color: '#3d79ff',
18     transparent: true,
19     opacity: 0.4,
20     shininess: 4,
21   }),
22 );
23 
24 SEDU.add( liquid, tube );

 效果如下:

 what? 效果不太对吧,里面绿色液体哪里去了???是不是透明造成的??修改一下试试看:

var tube = new THREE.Mesh(
  new THREE.CylinderGeometry(45, 45, 150, 32, 32, true),
  new THREE.MeshPhongMaterial({
    color: '#3d79ff',
    //transparent: true,
    opacity: 0.4,
    shininess: 4,
  }),
);

果然是transparent属性造成的,但是这样虽然显示出来绿色液体的,但液体缺无法体现透明度了。

为什么一个transparent物体内的 另一个transparent物体无法显示呢?

这是因为Three.js中 WebGLRenderer,会根据对象与摄像机的距离对象进行排序,并按照从最远到最近的顺序渲染透明对象。为了使两个透明对象正确地呈现,后面的对象-也就是绿色液体-必须首先渲染。否则,由于深度缓冲区,它将根本不会渲染。因为我把他们两个物体的坐标设为同一个坐标了,没有了远近的区别,所以绿色液体没有被渲染。那么我们把 绿色液体的坐标稍微改动1个px是不是就能显示出来了呢?

liquid.position.set( 0, 0, -1 );

 OK,绿色液体确实渲染出来了,看来这个问题轻松的就被搞定了。嗯,别高兴的太早。如果物体是静态的,那么可以这么处理,但如果是运动的就要各个方向都要看仔细了。

果然旋转一下问题依然存在,那么怎么能彻底解决这个问题呢?下面提供几种方案。

第一种 renderOrder

将tube的renderOrder设为1,即可正确渲染两个物体。

第二种 depthWrite:false

将两个物体材质的depthWrite属性都设为 false,也可正确渲染两个物体。

猜你喜欢

转载自www.cnblogs.com/huaihuaixiaohao/p/13204356.html
今日推荐