Threejs中的透明对象 [英] Transparent objects in Threejs

查看:195
本文介绍了Threejs中的透明对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试用 Three.js 编写一个小程序,它显示两个球体,一个在另一个球体中.sphere2 的半径应该在 0.5 和 1.5 之间振荡,而 sphere1 的半径始终为 1.0.每个球体都是透明的(不透明度:0.5),因此可以看到较大球体中包含的较小球体.当然小"和大"的作用随着sphere2半径的变化而变化.

I am trying to write a small program in Three.js that displays two spheres, one inside the other. The radius of sphere2 is supposed to oscillate between 0.5 and 1.5 while the radius of sphere1 is always 1.0. Each sphere is transparent (opacity: 0.5) so that it would be possible to see the smaller sphere contained in the larger one. Of course the roles of "smaller" and "larger" change as the radius of sphere2 varies.

现在的问题是 Three.js 使我在我的程序中定义的第一个球体透明,而不是第二个球体.如果我定义第一个 sphere1 那么它会变得透明,但 sphere2 是完全不透明的.如果我定义第一个 sphere2 那么这是透明的.将它们添加到场景中的顺序无关紧要.

The problem now is that Three.js makes transparent the first sphere I define in my program but not the second one. If I define first sphere1 then it becomes transparent but then sphere2 is completely opaque. If I define first sphere2 then this is the transparent one. The order of adding them to the scene plays no role.

我在下面包含一个显示正在发生的事情的最小程序(没有动画).在当前状态下,只有 sphere1 可见,并且不透明.如果我在 sphere2 之前定义 sphere1,那么 sphere1 将变为透明,但 sphere2 不再透明.将 sphere2 的半径更改为 1.2 将隐藏 sphere1.

I include below a minimal program that shows what is going on (without the animation). In its current state only sphere1 is visible and it is not transparent. If I define sphere1 before sphere2 then sphere1 becomes transparent but sphere2 is no longer transparent. Changing sphere2's radius to 1.2 will then hide sphere1.

有没有办法让两个球体都透明?

Is there any way to make both spheres transparent?

var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(75, window.innerWidth/window.innerHeight, 0.1, 1000);

camera.position.set(0, 0, 3);
camera.lookAt(new THREE.Vector3(0, 0, 0));
scene.add(camera);

var ambient = new THREE.AmbientLight( 0x555555 );
scene.add(ambient);

var light = new THREE.DirectionalLight( 0xffffff );
light.position = camera.position;
scene.add(light);

var renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);

// Definition 2
var geometry2 = new THREE.SphereGeometry(0.8,32,24);
var material2 = new THREE.MeshLambertMaterial({color: 0x0000ff, transparent: true, opacity: 0.5});
var sphere2 = new THREE.Mesh(geometry2, material2);

// Definition 1
var geometry1 = new THREE.SphereGeometry(1.0,32,24);
var material1 = new THREE.MeshLambertMaterial({color: 0x00ff00, transparent: true, opacity: 0.5});
var sphere1 = new THREE.Mesh(geometry1, material1);

scene.add(sphere1);
scene.add(sphere2);

renderer.render(scene, camera);

推荐答案

您的两个球体都是透明的,并且仍然如此.发生的事情是根本没有渲染较小的球体.

Both your spheres are transparent, and are remaining so. What is happening is that the smaller sphere is not being rendered at all.

WebGL 中的透明度很棘手.您可以谷歌这个问题以了解更多信息.

Transparency in WebGL is tricky. You can google the issue to find out more about it.

但是您偶然发现了一个与three.js 特别如何处理透明度相关的问题.

But you have stumbled upon an issue related to how three.js in particular handles transparency.

three.js 中的 WebGLRenderer 根据对象与相机的距离对对象进行排序,并按照从最远到最近的顺序渲染透明对象.(这是很重要的一点:它根据位置对象进行排序,并按排序顺序呈现对象.)

The WebGLRenderer in three.js sorts objects based upon their distance from the camera, and renders transparent objects in order from farthest to closest. (This is an important point: It sorts objects based on their position, and renders objects in the sorted order.)

因此,要正确渲染两个透明对象,必须首先渲染后面的对象(在您的示例中是较小的球体).否则,由于深度缓冲区,它根本不会被渲染.

So for two transparent objects to render correctly, the object that is in back -- the smaller sphere in your case -- must be rendered first. Otherwise, it will not be rendered at all, due to the depth buffer.

但在您的情况下,您有两个位于同一位置的球体,因此与相机的距离相等.这就是问题——先渲染哪个;这是一个折腾.

But in your case, you have two spheres that are in the same location, and hence are equidistant from the camera. That is the problem -- which one to render first; it is a toss-up.

因此,与较大的球体相比,您需要将较小的球体放置在离相机更远的位置,以便正确渲染场景.

So you need to place the smaller sphere further away from the camera than the larger sphere in order for the scene to render correctly.

一种解决方案是将较小的球体向后移动一点.

One solution is to move the smaller sphere back a little.

另一种解决方案是设置renderer.sortObjects = false.然后对象将按照它们添加到场景中的顺序进行渲染.在这种情况下,请务必先将较小的球体添加到场景中.

Another solution is to set renderer.sortObjects = false. Then the objects will render in the order they are added to the scene. In that case, be sure to add the smaller sphere to the scene first.

第三种解决方案是设置material1.depthWrite = falsematerial2.depthWrite = false.

A third solution is to set material1.depthWrite = false and material2.depthWrite = false.

具有material.transparent = false(不透明对象)的可渲染对象在具有material.transparent = true(透明对象)的对象之前渲染.

Renderable objects having material.transparent = false (opaque objects) are rendered before objects having material.transparent = true (transparent objects).

所以第四个解决方案是使较小的球体不透明,以便首先渲染它.

So a fourth solution is to make the smaller sphere opaque so it is rendered first.

r.71 的新功能:

现在有一个 Object3D.renderOrder 属性.在每个对象类(不透明或透明)中,对象按照 object.renderOrder 指定的顺序呈现.renderOrder 的默认值为 0.注意 renderOrder 不会被子对象继承;您必须为每个可渲染对象设置它.

There is now an Object3D.renderOrder property. Within each class of object (opaque or transparent), objects are rendered in the order specified by object.renderOrder. The default value of renderOrder is 0. Note that renderOrder is not inherited by child objects; you must set it for each renderable object.

具有相同 renderOrder(关系)的对象按深度排序,如上所述.

Objects with the same renderOrder (ties), are sorted by depth, as described above.

所以第五个解决方案是为更大的球体设置 renderOrder = 1.这可能是您的最佳解决方案.

So a fifth solution is to set renderOrder = 1 for the larger sphere. This is likely the best solution in your case.

three.js r.71

three.js r.71

这篇关于Threejs中的透明对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆