我自己的z缓冲区

时间:2012-03-23 20:17:12

标签: opengl glsl framebuffer fbo zbuffer

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

我如何解决这个问题?!

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

2 个答案:

答案 0 :(得分:3)

  

如何制作自己的z缓冲区以正确混合alpha通道?

那是不可能的。为了获得完美的与顺序无关的透明度,您必须摆脱z缓冲区并将其替换为隐藏表面移除的其他机制。

使用z-buffer有两种方法可以解决这个问题。

  1. 多层z缓冲区(硬件加速不切实际) - 基本上它会存储几层“深度”值,并将用于混合透明表面。会占用大量内存,并且会有最大数量的透明叠加表面,一旦超出限制,就会出现伪影。
  2. 深度剥离(google it)。订单独立透明度,但每个像素的“覆盖”透明多边形的最大数量是有限制的。实际上可以在硬件上实现。
  3. 两种方法都有一个限制(每个像素重叠的透明多边形的最大数量),一旦超过限制,场景将不再正确渲染。这意味着整个事情相当无用。

    你真正能做到的(获得完美的解决方案)是完全删除zbuffer,并制作一个图形渲染管道,收集所有要渲染的多边形,剪切它们,分割它们(当两个多边形相交时),对它们进行排序然后按正确的顺序在屏幕上绘制它们,以确保您获得正确的结果。但是,这很难,而且硬件加速这样做更难。我认为(我并不完全确定它发生过)5 6年前,一些ATI GPU相关文档提到他们的一些卡可以通过启用某种扩展来禁用Z-Buffer来呈现正确的场景。然而,他们没有说阿尔法混合的事情。从那以后我没有听说过这个功能。也许它并没有变得流行并且分享了TruForm的命运(被遗忘)。此类渲染管道也无法在z-buffer

    上进行某些操作

答案 1 :(得分:2)

如果它是与顺序无关的透明度,那么基本问题是深度缓冲存储在每个像素的深度上,但如果你正在构成部分透明几何的视图,那么多个片段对每个像素都有贡献。 / p>

如果你要强有力地解决问题,你需要一个有序的每个像素深度列表,回到最近的不透明片段。然后,您将以相反的顺序遍历列表。实际上,OpenGL不会像可变大小的数组那样做,所以人们通过按照从前到后的顺序绘制几何图形来实现这一点。

GL_SAMPLE_ALPHA_TO_COVERAGE体现的另一种选择是切换到屏幕门透明度,这与真正的高透明度或多重采样无法区分。理想情况下,你会随机地做到这一点,但这将使OpenGL重复性规则无效。不过因为你在GLSL,你可以自己做。您的采样器只是获取输入alpha并将其用作输出最终像素的概率。因此,从某处获取0.0到1.0范围内的随机值,如果它大于alpha,则丢弃像素。始终输出alpha为1.0,只使用普通深度缓冲区。 Answers like this更多地说明了如何在GLSL中获取随机数,显然你想要将多重采样变为尽可能高。

Eric Enderton撰写了a decent paper(有slide version)关于随机顺序无关的透明度,与DirectX实现一起值得一试。