Three.js 3JS中的透明对象
我正在尝试用Three.js编写一个小程序,它显示两个球体,一个在另一个球体内。假设球体2的半径在0.5和1.5之间振荡,而球体1的半径始终为1.0。每个球体都是透明的(不透明度:0.5),因此可以看到较大球体中包含的较小球体。当然,“小”和“大”的作用随着球体2半径的变化而变化 现在的问题是Three.js使我在程序中定义的第一个球体透明,而不是第二个球体。如果我定义了第一个sphere1,那么它将变得透明,但sphere2是完全不透明的。如果我首先定义sphere2,那么这是透明的。将它们添加到场景的顺序不起任何作用 我在下面包括一个显示正在发生的事情(没有动画)的最小程序。在其当前状态下,只有sphere1可见且不透明。如果我在sphere2之前定义sphere1,则sphere1变为透明,但sphere2不再透明。将sphere2的半径更改为1.2将隐藏sphere1 有没有办法使两个球体都透明Three.js 3JS中的透明对象,three.js,Three.js,我正在尝试用Three.js编写一个小程序,它显示两个球体,一个在另一个球体内。假设球体2的半径在0.5和1.5之间振荡,而球体1的半径始终为1.0。每个球体都是透明的(不透明度:0.5),因此可以看到较大球体中包含的较小球体。当然,“小”和“大”的作用随着球体2半径的变化而变化 现在的问题是Three.js使我在程序中定义的第一个球体透明,而不是第二个球体。如果我定义了第一个sphere1,那么它将变得透明,但sphere2是完全不透明的。如果我首先定义sphere2,那么这是透明的。将它们添
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);
一些评论
首先。如果您要问一个期望人们检查代码的问题,请将其放在JSFIDLE中。如果你这样做,你会让更多的人偷看。话虽如此,这里是您在JSFIDLE中代码的一个稍加修改的版本,请将其用作未来问题的指南
我在代码中所做的更改是将sortObjects设置为false,然后更改球体添加到场景中的顺序。这是因为在接下来的2个链接中提供了信息
您的两个球体都是透明的,并且保持透明。发生的情况是,较小的球体根本没有被渲染 WebGL中的透明度很棘手。你可以通过谷歌搜索这个问题来了解更多信息 但是您偶然发现了一个问题,这个问题与three.js如何处理透明度有关 three.js中的
WebGLRenderer
根据对象与摄影机的距离对对象进行排序,并按从最远到最近的顺序渲染透明对象。(这一点很重要:它根据对象的位置对对象进行排序,并按排序顺序渲染对象。)
因此,要正确渲染两个透明对象,必须首先渲染位于后面的对象(本例中较小的球体)。否则,由于深度缓冲区的原因,它将根本不会被渲染
但是在你的例子中,你有两个球体在同一个位置,因此与相机的距离相等。这就是问题所在——首先呈现哪一个;这件事很难决定
因此,为了正确渲染场景,需要将较小的球体放置在距离摄影机较远的位置
一种解决方案是将较小的球体向后移动一点
另一种解决方案是设置renderer.sortObjects=false
。然后,对象将按照它们添加到场景中的顺序进行渲染。在这种情况下,请确保先将较小的球体添加到场景中
第三种解决方案是设置material1.depthWrite=false
和material2.depthWrite=false
编辑:
具有material.transparent=false
(不透明对象)的可渲染对象在具有material.transparent=true
(透明对象)的对象之前进行渲染
所以第四种解决方案是使较小的球体不透明,以便首先渲染它
r.71的新功能:
现在有一个Object3D.renderOrder
属性。在每一类对象(不透明或透明)中,对象都按照object.renderOrder
指定的顺序进行渲染。renderroder
的默认值为0
。请注意,renderOrder
不是由子对象继承的;必须为每个可渲染对象设置它
具有相同的renderOrder
(ties)的对象按深度排序,如上所述
因此,第五种解决方案是为较大的球体设置renderOrder=1
。这可能是您的最佳解决方案
three.js r.71值得一提的是,我无法使用上述方法解决相同的问题,但我发现:
scene = new THREE.Scene();
group = new THREE.Group();
scene.add( group );
在my init()中,然后将正面网格添加到场景中,但将背面网格分组解决了问题。i、 e:
var materialfront = new THREE.MeshPhongMaterial({
opacity:1, map:texture });
materialfront.transparent = true ;
materialfront.side = THREE.FrontSide ;
frontthing = new THREE.Mesh( geometry, materialfront );
frontthing.renderOrder = 2;
scene.add(frontthing);
然后
我的材质贴图是一个透明的.png纹理
我无法解释为什么其他建议的方法对我不起作用,但我希望上述方法可能会对处于类似位置的人有所帮助。感谢您抽出时间检查我的代码并回复。将
rendered.sortObjects
设置为false
会使最终结果取决于我将对象添加到场景中的顺序,如WestLangley稍后的回答中所述。问题是,我想为场景设置动画,对于某些帧,最好先绘制一个球体,然后在其他帧之前绘制另一个球体。depthWrite到底做什么?缺点是什么(性能、新错误等等?)?我认为深度写入信号表明对象应该写入自己的深度,这意味着它们根据与摄影机的距离计算出场景中的深度。如果禁用它,可以覆盖新的深度r.71中的renderOrder
功能为我工作。注意:必须在子对象上设置它。在父对象上设置它不适用于子对象。添加depthWrite:false
是解决方案,谢谢!所以我现在使用:var material_plane=new THREE.MeshBasicMaterial({color:drawcol,side:THREE.DoubleSide,opacity:0.5,transparent:true,depthWrite:false})代码>德普斯威特为我修复了它
var materialfront = new THREE.MeshPhongMaterial({
opacity:1, map:texture });
materialfront.transparent = true ;
materialfront.side = THREE.FrontSide ;
frontthing = new THREE.Mesh( geometry, materialfront );
frontthing.renderOrder = 2;
scene.add(frontthing);
var texture2 = texture.clone();
texture2.needsUpdate = true;
var materialBack = new THREE.MeshPhongMaterial({
opacity:0.1, map: texture2})
materialBack.transparent = true ;
materialBack.side = THREE.BackSide;
backthing = new THREE.Mesh( geometryback, materialBack );
backthing.renderOrder = 1;
group.add(backthing);