如何在透明的大型广告牌渲染中避免距离排序

How to avoid distance ordering in large scale billboard rendering with transparency

场景设置:

我正在渲染一张高度图(广阔的非透明表面),上面有大量的广告牌(通常是草地、鲜花等)。

广告牌因此应用了大部分透明的彩色贴图,只有少数像素着色以产生草或树叶形状等。请注意,这些形状的边缘使用了一点透明度渐变以使它们看起来更平滑,但我也尝试过使用基本的二进制 color/transparent 纹理。

伪渲染代码如下:

map->render();
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
wildGrass->render();
glDisable(GL_BLEND);

wildGrass 渲染指令在单个 OGL 调用中在不同位置渲染多个广告牌。

我遇到的问题与透明度有关,而且广告牌显然相互隐藏,即使在其透明区域也是如此。然而,高度图纯色背景在那些透明部分上正确显示。

这是错误:

根据我对 OGL 混合的理解和一些阅读,似乎解决方案是控制渲染顺序,从最远的对象到最近的对象,以便颜色缓冲区在结束。

我非常希望有另一种方法...这里的顺序通常会根据视角而有所不同,这意味着它必须实时应用于每一帧。再加上这些特定广告牌的性质是——非常大——制作的……性能警报!

有什么建议或者我的混合方法有误吗?

不适合我:

@httpdigest 关于禁用深度缓冲区写入的建议:

它基本上适用于具有相同纹理(可能是特定类型的纹理,例如野草)的广告牌,因为深度不一致在视觉上不明显 - 但是引入另一种纹理,比如具有截然不同的花颜色,会立即突出那些错误。

解法:

@Rabbid76 建议使用具有多重采样和抗锯齿功能的非半透明纹理:我相信这是以合理的低性能成本获得最佳视觉效果的方法。

备选方案:

我找到了一个中间解决方案,它可能是牺牲质量但性能最便宜的解决方案。我仍然使用具有渐变透明边缘的纹理,但我没有丢弃完全透明的像素,而是引入了一定程度的容差,例如丢弃任何 alpha < 0.6 的像素 - 通过实验找到该值以找到正确的平衡。

采用这种方法:

  • 我仍然执行深度测试,所以输出是正确的
  • 纹理质量 degraded/look 不太平滑 - 但合理
  • 半透明像素上的毛刺仍然出现 - 但几乎不明显
  • 见下方截图

所以总结一下:

  • 我的解决方案是一种廉价而简单的近似方法,视觉效果不太流畅
  • 通过将所有广告牌渲染为具有抗锯齿的多采样纹理解析并最终以全屏四边形输出结果,可以获得最佳结果。可能有多种方法可以做到这一点:
    • 要么先渲染地图,然后在渲染广告牌时使用生成的深度缓冲区
    • 或者在多采样纹理上同时渲染地图和广告牌
  • 请注意,上述方法都是为了避免必须对大量广告牌进行基于距离的排序——但这仍然是一个有效的选择,我已经阅读了关于将广告牌位置存储在四叉树中以便快速访问的内容。