【问题标题】:Disable writing in depth buffer from glsl禁用从 glsl 写入深度缓冲区
【发布时间】:2012-01-12 09:48:52
【问题描述】:

所有几何图形都存储在一个 VBO 中(透明 + 不透明)。我无法对几何进行排序。如何在不丢失数据颜色的情况下禁用从 glsl 写入深度缓冲区?

【问题讨论】:

  • 我应该在下一条规则中在 vbo 中短接多边形:检测不透明的多边形并在 VBO 的开头移动他,然后绘制。对吗?

标签: opengl glsl alphablending depth-buffer


【解决方案1】:

如果我理解正确,您想禁用深度写入,因为您同时绘制不透明和透明对象。除了它在 GLSL 中不能以这种方式工作之外,它不会产生你想要的东西,如果它产生了。

如果您只是禁用深度写入ad hoc,则在透明对象之后的不透明对象将覆盖它,而不管 z 顺序如何。

你真正想做的是:

  1. 启用深度写入和深度测试
  2. 绘制所有不透明的几何图形。如果可以的话,按照大致排序(大致就足够了!)的顺序,最接近的对象优先。
  3. 禁用深度写入,保持启用深度测试
  4. 启用混合
  5. 绘制透明对象,按相反方向排序,即最远的优先。这会遮挡具有不透明几何体的透明对象,并使混合正常工作。

如果由于某种原因,您无法对 不透明 几何图形进行排序(尽管确实没有理由不能这样做?),没关系 - 它会稍微慢一些因为它不会剔除片段,但会产生相同的图像。

如果由于某种原因,您无法对 透明 几何图形进行排序,则在多个透明对象重叠的情况下,您将不得不期待不正确的结果。这可能会或可能不会引起注意(特别是如果顺序是“随机的”,即逐帧更改,这将非常明显 - 否则您实际上可能会侥幸逃脱,尽管它不正确。

请注意,正如 datenwolf 已经指出的那样,多个对象位于一个 VBO 中的事实并不意味着您不能绘制它们的子集,或者以您想要的任何顺序绘制多个子集。毕竟,一个 VBO 只包含一些顶点,这取决于你按什么顺序绘制它们中的哪些组。

【讨论】:

  • 我不明白为什么给客户端代码带来这样的负担。在片段自动处理之后,它会容易上千倍,并且会在不涉及 CPU 计算的情况下大大提高性能。我越来越相信 OpenGL 在编写这个越来越愚蠢的标准时不会使用他们的大脑。
  • @lukasz1985:之所以如此繁重,是因为您只有一个深度值。具有透明对象的场景每个片段有多个对象重叠的深度,但您只能保留一个(最接近眼睛的不透明)。对于透明对象,它们在任何给定片段上绘制的 Z 顺序没有明确定义(OpenGL 无法先验地知道),但它对结果非常重要。因此,您必须在应用程序级别对它们进行排序。使用原子操作和“胖”缓冲区,可以实现您设想的“轻松千倍”,但这有巨大的需求......
  • ... 在内存和带宽上,它只在最近的硬件上运行,而且这也不是一件容易的事(参见here 以获取此类示例)。 OpenGL 还必须考虑不是顶级的硬件,并且当您没有两位数千兆字节的可用视频内存时,它仍然必须工作。因此,不幸的是,它不可能完全进化。
  • @lukasz1985:嗯,不......“高级”意味着诸如对纹理和缓冲区对象的原子操作,在帧缓冲区中实现每个片段的链表并在着色器中对它们进行排序。那种简单的东西。如果您想要可预测的、可重现的、正确的结果(这是 OpenGL 通常试图断言的),这确实不是 f**n 容易的。如果您不关心结果是否正确(并且当场景中的对象移动时仍然正确),那么将一些对象与 alpha 一起敲击只是微不足道的。或者,当然,如果只有一个透明对象。
  • 在 OpenGL 的“早期”(即 1990 年代)中的图形硬件远不能提供任何这样的东西,无论是在内存方面、在带宽方面、在 ALU 中还是在一般功能或可编程性(2009 年左右的硬件都不是)。问题是,你在比较苹果和橘子。当然,您可以简单地进行 alpha 混合对象(无需排序等),但这不是一回事,它充其量只是一个非常糟糕的 hack,结果是一种“随机运气”。
【解决方案2】:

你不能。

我无法对几何图形进行排序。

为什么?你认为是因为这一切都在一个 VBO 中吗?然后我得到了好消息:完全可以从缓冲区对象的子集中进行绘制。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-04-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-27
    • 1970-01-01
    相关资源
    最近更新 更多