繁体   English   中英

实现混合功能对于固定功能混合来说过于复杂

[英]Implementing blending functions too complicated for fixed-function blending

我正在尝试在 gpu 上实现高级混合。但是每当我尝试搜索资源时,我都会被顺序独立渲染、片段着色器互锁等术语弄得不知所措。 而且我不知道哪些与我的问题相关。

简单地给出 3 个对象,( b0b1b2 ),它们都位于同一个像素上并具有特定的 z 顺序。 (您可以假设对象已正确排序)。

那么设置像素的最终颜色应该是

f( b2, f( b1, f( b0, background_color ) ) )

其中f是来自 vec4 的任意 function(在编译时决定) vec4, vec4 -> vec4使用固定的 function 混合无法实现。

我的直觉是使用看起来像的代码

void main() {
  vec4 previous_color = //...
  gl_FragColor = f( object_color, previous_color );
}

然而,根据我有限的研究和理解,您不能简单地读取片段着色器中已经渲染的数据。 (因此我认为VK_EXT_fragment_shader_interlock的原因)。

但是,如果我不能依赖这样的扩展,我还能在 GPU 上实现它吗?

还可以解释为什么“幼稚”的实施会导致问题。

基于链表的顺序独立透明性让你免费获得这个,因为该算法根本不使用固定函数混合。 解析混合时,片段着色器(或计算着色器,但 FS 很好)会获得影响特定片段的 colors 列表。 FS 必须使用这些 colors(及其距离)来计算混合结果。 所以所有的信息都在那里。

当然,OIT 并不便宜。 如果对场景进行排序很困难,那么它可能是值得的(尤其是在计算顺序涉及大量 CPU 交互的情况下),但这不是免费的。

OIT 仅依赖于拥有任意大小和原子增量的 SSBO 的能力。 这些代表 Vulkan 的基本功能。

除了 OIT,您最终要做的是让 FS 执行图像的有序、原子读/修改/写,其中“修改”操作非常重要(即:不是增量或其他)。

未扩展的 Vulkan 可以通过输入附件和管道屏障来做到这一点。

您必须有一个使用附件作为颜色附件和输入附件的子通道。 然后,您渲染一个非重叠的 object(这非常重要)。 FS 中的previous_color现在来自subpassLoad操作。 这个 function 没有纹理坐标,因为它总是从与当前片段位置对应的纹素中读取。 也就是说,它读取该片段下方的帧缓冲区中已有的颜色。 output 转到颜色附件,它是与输入附件相同的图像。

但是,您只能对每个像素执行一次此操作。 也就是说,每个像素只能有一次读取/修改/写入。 要获得第二个,您必须在一个 object 的绘图和下一个 object 的绘图之间发出管道屏障。这意味着每组重叠的对象都必须在子通道中分解成它们自己的块。 管道屏障本身很特殊,因为它必须使用子通道自依赖性(也在渲染通道定义中指定)。

为了高效渲染,您需要将绘图调用分解为绘图块,其中每个块内没有重叠像素。

片段着色器互锁是另一种机制,但它不适用于片段着色器的输出。 只有当你想通过图像加载/存储或 SSBO 对 memory 执行原子 RMW 时,它才有用。 因此,您必须渲染主场景,结束渲染通道,启动一个不使用该图像作为附件的新渲染通道,然后对其进行联锁图像加载/存储。 然后为您可能需要的任何其他后处理结束该渲染过程。

问题未解决?试试以下方法:

实现混合功能对于固定功能混合来说过于复杂

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2023 STACKOOM.COM