2017-10-19 91 views
0

我遇到的问题是当我有一个网格,其中只有网格的一些面应该是半透明的,而对象的其余部分应该是不透明的。任何人都知道我应该如何解决这个问题?如何渲染部分半透明的网格?

下面是对这个问题的更多描述:清晰度:在我们的浏览器中,如果它们具有相同的材质属性,我们会合并多个网格物体。

然后,如果用户点击合并对象,我们会发现被点击的表面和该面部对象的原始ID。然后,我们只用我们自己的自定义着色器突出显示该对象的面部。

一个对象选择
one object selected

现在的问题是,如果我们使材料透明的(因此所选择的部分是半透明的),则整个合并的网格是透明的,该模型的不透明部分被呈现透明。

你可以看到一些视觉问题,在这样的画面:

视觉问题的部分透明的对象
visual issues for partially transparent object

我对我们如何能够解决这个问题,但他们都将增加存储多思路消耗和复杂度:

  1. 丢弃应该是透明的碎片,然后用选定的面和透明材质创建一个新的网格。

  2. 创建一个透明的整个合并网格的副本,然后只渲染透明对象中的选定对象面并丢弃原始非透明网格中的片段。

任何人都有更好的主意吗?

使用三个r84。

+0

你对所有的盒子都有'.transparent = true'吗? – prisoner849

+0

所有的盒子都是这个例子中的一个网格,所以通过设置材质为透明的,所以我可以显示一些透明的面孔,这样所有的盒子都是透明的。 – Krigsdal

+1

使用深度剥离你可以实现你想要的,但我认为three.js本身并不实现它。我认为你的最佳策略是将你的“分组网格”分成几个网格,并独立处理每个“盒子”。透明度在3D渲染中从来不是一个微不足道的问题。 – 2017-10-19 09:39:29

回答

0

我不明白为什么你不想使用分离的盒子网格,因为它更容易管理每个网格的透明度。

但是,如果你想使用单一的几何,我想出了一种使用两种材料,.materialIndex和动态几何的方法。该方法依赖于this SO answer

var materials = [ 
    new THREE.MeshLambertMaterial({ color: "white" }), 
    new THREE.MeshLambertMaterial({ color: "white", transparent: true, opacity: 0.5}) 
]; 

. . . 

var cloneGeom = new THREE.Geometry(); 

var oldBoxIndex = 0; 

function setBoxTransparent(boxIndex) { 
    cloneGeom = mesh.geometry.clone(); 
    setBoxMaterial(oldBoxIndex, 0); 
    setBoxMaterial(boxIndex, 1); 
    mesh.geometry.dispose(); 
    mesh.geometry = cloneGeom; 
    oldBoxIndex = boxIndex; 
} 

function setBoxMaterial(boxIndex, materialIndex) { 
    for (let i = 0; i < 12; i++) { 
    cloneGeom.faces[12 * boxIndex + i].materialIndex = materialIndex; 
    } 
} 

jsfiddle例子r87。

+0

因为分离的盒子网格意味着,而不是有1个网格= 1绘制电话,你将有50k盒子= 50 000绘制电话,这将意味着非常低的FPS,或者我误解你的意思?此外,我使用BufferGeometry和customShaders,所以我将不得不适应它来使用它。即使使用materialIndex,它也会增加渲染调用的次数,因为如果我正确理解渲染函数,每个组都会被调用一次,但它只会对所选对象进行双重渲染调用。感谢您抽出宝贵的时间和精力仔细查看使用团体是否可以工作! – Krigsdal

+0

不客气)但是你应该提到在你的问题中有超过5万个盒子(或场景的复杂性)和自定义着色器)而是,你只展示一个只有256个盒子的图片,这并不是什么大不了的) – prisoner849

+1

是的,你说得对::)我用这些框来容易地展示这个概念,但它的真正应用是大型的CAD模型。 – Krigsdal