1

我想用 GLKit 绘制半透明的图元。我已经通过禁用深度测试glDisable(GL_DEPTH_TEST)并通过启用混合

glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

现在对于较大的 alpha 值(例如 0.9),我需要先绘制最远的三角形,这样它们就不会出现在更近的三角形上方glBlendFunc的文档中也说明了这一点:

透明度最好使用混合函数(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA)来实现,基元从最远到最近排序。请注意,此透明度计算不需要帧缓冲区中存在 alpha 位平面

OpenGL 透明度常见问题解答中:

在应用程序中使用深度缓冲时,您需要注意渲染图元的顺序。需要首先渲染完全不透明的图元,然后以从后到前的顺序渲染部分不透明的图元。如果您不按此顺序渲染图元,则通过部分不透明的图元可以看到的图元可能会完全失去深度测试。

但是由于视角可以改变(当我改变渲染效果时modelViewMatrix),从最远到最近的顺序取决于当前的视角。

有没有办法让OpenGL以正确的顺序自动渲染我的图元,如果没有,最好的方法是什么?我认为计算(取决于当前视角)的 z 位置并为每帧排序几千个三角形(或者更准确地说,每次视角变化时,可能是每一帧)成本太高,特别是因为我需要将此订单推送到每帧的 GPU。

请注意,我不关心使用纹理(只是彩色顶点)。

4

2 回答 2

5

没有自动解决方案,因为由于相互重叠的问题,没有强大的实时解决方案。如果你会原谅 ASCII 艺术,请考虑四个四边形排列为:

     +--+             +--+
     |  |             |  |
+---------------------|  |------+
|                     |  |      |
+---------------------|  |------+
     |  |             |  |
     |  |             |  |
     |  |             |  |
+----|  |-----------------------+
|    |  |                       |
+----|  |-----------------------+
     |  |             |  |
     +--+             +--+

没有正确的顺序。您需要将至少一个四边形分成两部分——这就是像构建 BSP 树这样的提前计划要做的事情。这就是存在深度缓冲的原因。在大多数几何体不透明的基础上按像素解决这个问题。

所以最好的方法是:

  • 为您的透明几何构建 BSP 树(以获得完全准确性);
  • 为透明几何构建每个对象的 BSP 树,将对象从后到前排序(以获得相当好的准确性);
  • 要求对象仅具有或多或少的凸透明段,因此如果您构建一个具有单叶的 BSP 树,则最终会得到一个 BSP 树,从前到后排序(为了合理的准确性,取决于您的艺术);
  • 在绘制了所有不透明的几何图形后(用于不同的外观但没有排序问题),使用加法混合并以任何顺序绘制深度注销。
于 2012-11-26T21:15:23.473 回答
4

首先,不,没有办法让 OpenGL 为你做这件事。您必须根据当前相机和模型位置(即模型视图矩阵)手动对透明几何图形进行排序。

为了实现这一点,在实时实现中,您通常不会对单个三角形进行排序,而是对其逻辑子集(网格、子网格)进行排序。问题案例则变为:

  • 单个渲染元素中的非凸几何体。通常通过预先手动拆分几何图形或忽略工件来解决。
  • 不同元素的相交几何。一般不解决。

在性能方面,重要的是,在构建场景时,将元素分为(部分)透明与不透明。这样可以避免大型排序操作,因为您只需要对透明几何进行排序。

先进技术

对于完全不同的方法,请查看深度剥离和类似技术。如果做得好,这些技术可以提供很多东西。但是,我不知道实际实现它们的任何 OpenGL ES标题。这并不意味着它不是一个选择。

然而...

如果您对一般的 3D 编程还不是很熟悉,我强烈建议您坚持手动排序并尝试将伪影减少到最低限度。通过这种方式,您可以做出明智的决定,无论这种实现是否足以满足您的特定情况。

如果不出意外,实现这些东西将自动赋予您超人的能力,即在您以后玩的每个视频游戏中立即发现(并被极大地分散注意力)与透明度相关的渲染问题。有一个了不起的技能。

于 2012-11-26T21:14:18.747 回答