Go...

当前位置: 首页>>世界杯1998

MSAA的原理

遮挡告诉我们被一个图形覆盖的像素是否被其它的像素覆盖了,这种情况大家应该很熟悉就是z buffer的深度测试。

覆盖和遮挡两个一起决定了一个图形的可见性。

就光栅化而言,MSAA跟SSAA的方式差不多,覆盖和遮挡信息都是在一个更大分辨率上进行的。对于覆盖信息来说,硬件会对每个子像素根据采样规则生成n的子采样点。接下来的这张图展示了一个使用了旋转网格(rotated grid)采样方式的子采样点位置。

三角形会与像素的每个子采样点进行覆盖测试,会生成一个二进制覆盖掩码,它代表了这个三角形覆盖当前像素的比例。对于遮挡测试来说,三角形的深度在每一个覆盖的子采样点的位置进行插值,并且跟z buffer中的深度信息进行比较。由于深度测试是在每个子采样点的级别而不是像素级别进行的,深度buffer必须相应的增大以来存储额外的深度值。在实现中,这意味着深度缓冲区是非MSAA情况下的n倍。

MSAA跟SSAA不同的地方在于,SSAA对于所有子采样点着色,而MSAA只对当前像素覆盖掩码不为0的进行着色,顶点属性在像素的中心进行插值用于在片断程序中着色。这是MSAA相对于SSAA来说最大的好处。

虽然我们只对每个像素进行着色,但是并不意味着我们只需要存储一个颜色值,而是需要为每一个子采样点都存储颜色值,所以我们需要额外的空间来存储每个子采样点的颜色值。所以,颜色缓冲区的大小也为非MSAA下的n倍。当一个片断程序输出值时,只有地了覆盖测试和遮挡测试的子采样点才会被写入值。因此如果一个三角形覆盖了4倍采样方式的一半,那么一半的子采样点会接收到新的值。或者如果所有的子采样点都被覆盖,那么所有的都会接收到值。接下来的这张图展示了这个概念:

通过使用覆盖掩码来决定子采样点是否需要更新值,最终结果可能是n个三角形部分覆盖子采样点的n个值。接下来的图像展示了4倍MSAA光栅化的过程。

MSAA Resolve(MSAA 解析)

像超采样一样,过采样的信号必须重新采样到指定的分辨率,这样我们才可以显示它。

这个过程叫解析(resolving)。在它最早的版本里,解析过程是在显卡的固定硬件里完成的。一般使用的采样方法就是一像素宽的box过滤器。这种过滤器对于完全覆盖的像素会产生跟没有使用MSAA一样的效果。好不好取决于怎么看它(好是因为你不会因为模糊而减少细节,坏是因为一个box过滤器会引入后走样(postaliasing))。对于三角形边上的像素,你会得到一个标志性的渐变颜色值,数量等于子采样点的个数。接下来的图展示了这一现象:

当然不同的硬件厂商可能会使用不同的算法。比如nVidia的"Quincunx" AA等。随着显卡的不断升级,我们现在可以通过自定义的shader来做MSAA的解析了。

小结

通过上面的解释,我们可以看到,整个MSAA并不是在光栅化阶段就可以完全的,它在这个阶段只是生成覆盖信息。然后计算像素颜色,根据覆盖信息和深度信息决定是否来写入子采样点。整个完成后再通过某个过滤器进行降采样得到最终的图像。大体流程如下所示:

PC与Mobile对比

上面我们讲解了MSAA的基本原理,那么具体到不同显卡厂商以及不同平台上的实现有什么不同吗?下面就让我们做些简单的对比。其实,既然算法已经确定了,那么差异基本上就是在一些细节上的处理,以及GPU架构不同带来的差异。

版本

MSAA是否支持

自定义Shader解析

是否需要更大的颜色 深度 缓冲区

Direct3D 9

需要

Direct3D 11

需要

Direct3D 12

需要

OpenGL ES 2.0

(Multisample rasterization cannot be enabled or disabled after a GL context is created. It is enabled if the value of SAMPLE_BUFFERS is one, and disabled otherwise)

Multisample Texture:

使用GL_EXT_multisampled_render_to_texture扩展

苹果:

APPLE_framebuffer_multisample

安卓:

使用EGL

看GPU架构 :

TBR(Mali Qualcomm Adreno(300系列之前)) TBDR(PowerVR) 不需要

IMR(nVidia Tera Qualcomm Adreno 300系列以及之后可以在IMR、TBR之间切换)需要。

如果使用GL_EXT_multisampled_render_to_texture也需要(跟硬件实现有关(enabling MSAA the right way in OpenGL ES))。

OpenGL ES 3.0

(The technique is to sample all primitives multiple times at each pixel. The color sample values are resolved to a single, displayable color. For window system-provided framebuffers, this occurs each time a pixel is updated, so the antialiasing appears to be automatic at the application level. For application-created framebuffers, this must be requested by calling the BlitFramebuffer command (see section 4.3.3).)

When rendering textures, emphasis is placed on multisample anti-aliasing (MSAA), which earlier hardware generations could only run against the framebuffer. OpenGL ES 3.0 can presently support MSAA-type rendering for a texture.

如果是系统提供的framebuffer,那么同OpenGL ES 2.0的版本。如果是用户创建的framebuffer,那么是需要额外的显存的(跟硬件实现有关???)。

OpenGL ES 3.1

是(sampler2DMS)

如果是系统提供的framebuffer,那么同OpenGL ES 2.0的版本。如果是用户创建的framebuffer,那么是需要额外的显存的(跟硬件实现有关???)。

IMR vs TBR vs TBDR

IMR (立即渲染模式)

目前PC平台上基本上都是立即渲染模式,CPU提交渲染数据和渲染命令,GPU开始执行。它跟当前已经画了什么以及将来要画什么的关系很小(Early Z除外)。流程如下图所示:

TBR(分块渲染)

TBR把屏幕分成一系列的小块,每个单独来处理,所以可以做到并行。由于在任何时候显卡只需要场景中的一部分数据就可完成工作,这些数据(如颜色 深度等)足够小到可以放在显卡芯片上(on-chip),有效得减少了存取系统内存的次数。它带来的好处就是更少的电量消耗以及更少的带宽消耗,从而会获得更高的性能。

分块

TBDR (分块延迟渲染)

TBDR跟TBR有些相似,也是分块,并使用在芯片上的缓存来存储数据(颜色以及深度等),它还使用了延迟技术,叫隐藏面剔除(Hidden Surface Removal),它把纹理以及着色操作延迟到每个像素已经在块中已经确定可见性之后,只有那些最终被看到的像素才消耗处理资源。这意味着隐藏像素的不必要处理被去掉了,这确保了每帧使用最低可能的带宽使用和处理周期数,这样就可以获取更高的性能以及更少的电量消耗。

一个简单的对比传统GPU与TBDR

移动平台上的MSAA

有了上面对移动GPU架构的简单了解,下面我们看下在移动平台上是怎么处理MSAA的,如下图所示:

可以看到如果相对于IMR模式的显卡来说,TBR或者TBDR的实现MSAA会省很多,因为好多工作直接在on-chip上就完成了。这里还是有两个消耗: