【问题标题】:Multisampling in pipeline管道中的多重采样
【发布时间】:2014-03-25 02:17:27
【问题描述】:

在多重采样中,在光栅化过程中,每个像素中有多个采样点,并确定构成图元的采样点。

像素中每个样本的哪些属性相同?我在某处读到颜色和纹理值相同,但像素中样本的深度和模板值不同。但是由于对每个样本点执行片段着色器,所以它们应该是不同的。

另外,在片段着色器之后,何时在管道中解析多个样本?它们是线性平均的吗?

【问题讨论】:

    标签: opengl graphics multisampling


    【解决方案1】:

    首先,您必须了解多重采样的工作原理以及创建它的原因。

    我将从抗锯齿的角度来解决这个问题,因为在 GL3 中引入多采样纹理之前,这是多采样的主要用例。

    当某物被多重采样时,这意味着每个采样点包含多个样本。如果一个基元具有相对统一的特征(例如,到处都有相同的深度),这些样本可能彼此相同,并且智能 GL/硬件实现能够识别这种情况并通过智能地读取/写入共享样本(类似于颜色)来减少内存带宽/深度缓冲区压缩)。但是,4x MSAA 帧缓冲区所需的存储成本与 4x SSAA 相同,因为 GL 必须适应最坏的情况,即 4 个样本中的每一个都是唯一的。

    像素中每个样本的哪些属性相同?

    每个片段可以覆盖多个采样点的属性,例如颜色、纹理坐标等。与其频繁调用片段着色器 4x 来实现 4x 抗锯齿,我们设计了一个技巧,其中每个属性都将在片段处进行采样中心(这是默认值),然后将单个输出写入每个覆盖的样本位置。在片段的中心不是实际覆盖区域的一部分的情况下,默认行为有些缺乏 - 为此,引入了质心采样......顶点属性将被插值在片段内图元覆盖区域的中心而不是片段本身的中心。

    稍后,当需要将颜色写入帧缓冲区时,需要对所有这些样本进行平均以产生单个像素;我们称之为多样本解析。这在某些情况下效果很好,但它不能解决片段着色本身期间出现的别名问题。

    纹理发生在片段着色器的执行过程中,这意味着纹理的采样频率保持不变,因此 MSAA 通常对纹理混叠没有帮助。因此,虽然超采样抗锯齿改善了两个几何边缘的锯齿纹理/着色器锯齿(例如镜面反射亮点),多重采样通常只会减少“锯齿”。

    我在某处读到颜色和纹理值相同,但像素中样本的深度和模板值不同。

    简而言之,在片段着色器中计算的任何内容对于所有覆盖的样本都是相同的。 片段着色(例如深度)之前可以确定的任何内容都可能会有所不同。

    针对每个子样本评估片段测试,例如深度/模板。但是多重采样深度缓冲区有一些限制。在 D3D 10.1 之前,硬件不需要支持多重采样深度纹理,因此您无法在片段着色器中对多重采样深度缓冲区进行采样。

    但是由于对每个采样点执行片段着色器,所以它们应该是不同的。

    有一个称为样本着色的功能,它可以通过提高着色片段与光栅化期间生成的样本之间的比率来强制 MSAA 的实现更像 SSAA。但默认情况下,您描述的行为不是多重采样。

    在片段着色器之后,何时在管道中解析多个样本?它们是线性平均的吗?

    多采样分辨率发生在片段着色之后,您必须将多采样缓冲区的内容写入单采样缓冲区。这包括像glBlitFramebuffer (...) 这样的东西。如果您使用多重采样纹理,您也可以自己片段着色器中手动实现多重采样分辨率。

    最后,关于用于多样本解析的过程,它是特定于实现的,样本布局也是如此。如果您曾经打开显示驱动程序的控制面板并查看无数可用的抗锯齿选项,您会看到示例布局和 MSAA 解析算法的多个选项。


    我强烈建议您查看this article。虽然它与 D3D10+ 而不是 OpenGL 相关,但通用规则适用于两种 API(D3D9 的规则略有不同)并且图表的质量非常出色。

    特别要特别注意三角形的 MSAA 光栅化规则部分,其中指出:

    对于三角形,会针对每个样本位置(而不是像素中心)执行覆盖测试。如果覆盖了多个样本位置,则像素着色器将运行一次,并在像素中心插入属性。为通过深度/模板测试的像素中每个覆盖的样本位置存储(复制)结果。

    【讨论】: