2012-03-23 59 views
0

如何让我自己的z缓冲区正确混合alpha通道?我正在使用glsl。 我只有一个想法。这是使用2“缓冲区”,其中一个存储深度组件和另一种颜色(与alpha通道)。我不需要访问我的程序中的缓冲区。我不能使用统一数组,因为glsl对统一变量的数量有限制。我不能使用FBO,因为有时写入和读取Frame Buffer的行为没有定义(并且不在任何卡上工作)。我自己的z缓冲区

我该如何解决这个问题?

或者如何从glsl读取实际的实时z-buffer? (我的意思是每个片段着色器调用z-buffer必须更新)

+3

“正确混合alpha通道”是什么意思?你想解决什么问题?你是否想要做一些与订单无关的事情? – 2012-03-23 20:27:11

+1

除了Nicol Bolas所说的内容:对于与订单无关的透明度,一些额外的深度缓冲区是不够的。什么可以分层分解场景,这就是所谓的深度剥离。但是,这不是微不足道的。 – datenwolf 2012-03-23 20:36:20

+0

@NicolBolas,是的。如果我可以从glsl读取Z-Buffer,那么我有一个简单的方法来做到这一点! – 2012-03-24 07:27:17

回答

2

如果它是与顺序无关的透明胶片,那么基本问题是深度缓冲区存储每个像素的深度,但如果您正在编写部分透明几何的视图,那么不止一个片段对每个像素都有贡献。

如果您要稳健地解决问题,则需要每个像素有序的深度列表,然后回到最近的不透明片段。然后你会按照相反的顺序走这个列表。在实践中,OpenGL不会像可变大小的数组那样做事情,所以人们通过按照先后顺序绘制它们的几何图形来达到非常好的效果。

GL_SAMPLE_ALPHA_TO_COVERAGE的一个替代方案是切换到屏幕门透明度,无论是以非常高的分辨率还是采用多重采样,都无法区分真正的透明度。理想情况下,你会这样做,但这会使OpenGL重复性规则失效。尽管如此,因为你在GLSL,你可以自己做。您的采样器只需输入alpha,并将其用作输出最终像素的概率。因此,从某个地方抓住一个范围在0.0到1.0之间的随机值,如果它大于alpha,则丢弃该像素。始终以1.0的alpha值输出,并使用正常的深度缓冲区。 Answers like this对你可以做些什么来获得GLSL中的随机数字有了更多的了解,显然你想尽可能多地进行多重采样。

Eric Enderton写了a decent paper(其中有slide version)关于随机顺序无关的透明度,并附带一个值得检查的DirectX实现。

2

如何让我自己的z缓冲区正确混合alpha通道?

这是不可能的。对于完美的与顺序无关的透明度,您必须摆脱z缓冲区并将其替换为隐藏表面移除的另一种机制。

使用z缓冲区有两种可能的方法来解决这个问题。

  1. 多层z缓冲区(硬件加速不切实际) - 基本上它会存储几层“深度”值,并将用它来混合透明表面。会占用很多内存,并且会有最大数量的透明覆盖表面,一旦超过极限,就会出现伪像。
  2. 深度去皮(谷歌它)。订购独立的透明度,但每个像素的“覆盖”透明多边形的最大数量是有限制的。实际上可以在硬件上实现。

两种方法都会有一个限制(每个像素的重叠透明多边形的最大数量),一旦超过极限,场景将不再正确渲染。这意味着整个事情都变得毫无用处。你可以做的(获得完美的解决方案)是完全移除zbuffer,并制作一个图形渲染管道,它将收集所有要渲染的多边形,剪切它们,拆分它们(当两个多边形相交时),排序然后按照正确的顺序在屏幕上绘制它们,以确保您获得正确的结果。但是,这很难,而用硬件加速来完成则更困难。我认为(我并不完全肯定它发生了)6年前的某些ATI GPU相关文档提到,它们的某些卡可以通过启用某种扩展来禁用Z-Buffer来渲染正确的场景。但是,他们没有提到α混合的事情。自那以后,我还没有听说过这个功能。也许它没有变得流行,并分享了TruForm的命运(被遗忘)。此外,这样的渲染管道将无法在z缓冲区上实现某些功能