在THREE.js中渲染重叠透明网格的最简单方法是什么?

问题描述 投票:0回答:1

我想渲染在THREE.js中部分重叠的透明表面。我不是在寻找多个重叠表面的完美渲染,而是想要看起来比当前结果好一点的东西 - 例如,如果我有两个椭圆体,那么中心在后面的那个就会参考那个深度来渲染即使其表面的某些部分有效地位于另一个表面之前。我还应该提到我正在使用OrbitControls,所以我不能简单地将它们静态排序一次而忘记它们。

我已经看到深度剥皮通常是这种技术,甚至找到了一个人在THREE.js中写了一个例子。不幸的是,它看起来也相当复杂,可能性能很重。我想知道是否有更简单的替代品。我考虑过的东西只是将每个网格分成其基本三角形并将每个网格作为一个单独的几何体推动,但我不知道会造成多大的性能影响,并且会使所有进一步的重新缩放/旋转操作变得更加混乱。我看到THREE的BufferGeometry类有一个'groups'选项,它将在不同的调用中绘制,但仅此一项似乎无法修复它。还有什么你认为我能做的吗?也许使用自定义着色器?或者我应该选择Depth Peeling?

three.js 3d webgl
1个回答
2
投票

enter image description here

Screendoor transparency可用于在帧之间创建稳定的透明度重叠,但附带一些可能不合需要的工件。该技术的要点是丢弃屏幕空间图案中的像素,这取决于对象应该是多么不透明。模式可以从纹理派生或在着色器中生成。未被丢弃的片段仍写入深度,并且不使用alpha混合。

这里有一些入门代码。

使用抖动模式生成DataTexture:

const data = new Float32Array(16);
data[0] = 1.0 / 17.0;
data[1] = 9.0 / 17.0;
data[2] = 3.0 / 17.0;
data[3] = 11.0 / 17.0;

data[4] = 13.0 / 17.0;
data[5] = 5.0 / 17.0;
data[6] = 15.0 / 17.0;
data[7] = 7.0 / 17.0;

data[8] = 4.0 / 17.0;
data[9] = 12.0 / 17.0;
data[10] = 2.0 / 17.0;
data[11] = 10.0 / 17.0;

data[12] = 16.0 / 17.0;
data[13] = 8.0 / 17.0;
data[14] = 14.0 / 17.0;
data[15] = 6.0 / 17.0;

ditherTex = new THREE.DataTexture(data, 4, 4, THREE.LuminanceFormat, THREE.FloatType);
ditherTex.minFilter = THREE.NearestFilter;
ditherTex.magFilter = THREE.NearestFilter;
ditherTex.anisotropy = 1;
ditherTex.wrapS = THREE.RepeatWrapping;
ditherTex.wrapT = THREE.RepeatWrapping;

还有一些着色器代码通过以下方式丢弃片段:

// ...
uniform sampler2D ditherTex;    
void main() {

    // ...

    // get the color of the surface and discard pixels based on the dither pattern       
    vec4 texColor = texture2D(diffuseTex, vUv);
    vec4 color = texColor * vec4(color.rgb, opacity);

    if(texture2D(ditherTex, gl_FragCoord.xy / 4.0).r > color.a) discard;

    // ...

}

您需要将数据纹理设置为着色器中使用的ditherTex制服。如果你想使用风格化或不那么规则的东西,你也可以使用不同的纹理。

最后要记住一些事情:

  • 与抖动纹理比较时,应使用纹理不透明度。
  • 可以通过一些抗锯齿方法来减轻屏幕门伪影以混合周围像素。
  • Material.transparent应该是false
  • 由于碎片未混合,具有相同不透明度的对象将不会显示可见的重叠。

希望这有帮助!如果您有其他问题,请告诉我。

© www.soinside.com 2019 - 2024. All rights reserved.